Skip to main content

Business Logic Overview

Proxima Invoice handles three types of client deals, each with distinct billing logic. Understanding deal types, client classification, and currency handling is essential to working with the system.

Deal Types

Every client application (contract) has a deal_type that determines how hours are billed.

Deal TypeNameBilling Model
SUPSupportFixed monthly amount + overtime beyond limit
HRHourlyAll hours billed at hourly rate
FPFixed PriceFlat amount regardless of hours worked

SUP (Support)

The most common deal type. The client pays a fixed monthly base_amount that covers hours up to monthly_limit. Hours beyond the limit are billed as overtime at the contract's hourly_rate.

if total_hours <= monthly_limit:
total = base_amount
else:
overtime_hours = total_hours - monthly_limit
overtime_amount = overtime_hours * hourly_rate * rate_multiplier
total = base_amount + overtime_amount

HR (Hourly)

All hours are billable. Each hour is multiplied by the hourly_rate and the applicable rate multiplier (for critical incidents, off-hours work, etc.).

total = sum(hours_per_tier * hourly_rate * tier_multiplier)

FP (Fixed Price)

A flat amount is charged regardless of how many hours were logged. Rate multipliers do not apply.

total = base_amount  // always

Client Types

Clients are classified as local (Uzbekistan) or international based on their financial details.

CriterionLocalInternational
CurrencyUZSUSD, EUR, or other
SWIFT/BICEmpty or ≤2 charsPresent (>2 chars)
Invoice templateRussian ("Акт выполненных работ")English ("Invoice")
DeliveryDidox.uzEmail with PDF
Base amount sourcedeal_amountinvoice_amount (if set), else deal_amount

Detection logic:

isInternational = (swift_bic?.length > 2) || (currency !== 'UZS')

See International Invoices for full details.

Currency

The system supports three currencies:

  • UZS — Uzbekistani som (local clients)
  • USD — US dollar (international clients)
  • EUR — Euro (international clients)

Currency is set at the application level in ClickHouse and carried through to the invoice. All financial math uses shopspring/decimal (never float64) to avoid rounding errors.

Key Business Rules

  1. Minimum billable time: Every worklog is rounded up to a minimum of 30 minutes (1800 seconds)
  2. Invoice numbering: Per-client atomic counter stored in client_invoice_config.last_invoice_number. Incremented via SELECT ... FOR UPDATE within the generation transaction to prevent concurrent collisions. The numbering seed must be set before the first invoice can be generated for a client.
  3. Jira/Tempo data is pre-fill only: Users can edit every field before finalizing
  4. PDF generated only on finalize: Not during pre-fill or draft editing
  5. Rate multipliers: Phase 1 ships with all multipliers = 1.0 (except P1-P3 off-hours = 1.5)
  6. ProximaOps company: TIN 309630523, registered in Uzbekistan
  7. Display toggles: 4 per-invoice boolean flags control PDF/HTML rendering — task list visibility, time column, pricing column, overtime row. Defaults are inherited from client_invoice_config and can be overridden per-invoice while in draft.
  8. Legal text: Per-invoice legal text replaces hardcoded template paragraphs. Defaults from client_invoice_config.default_legal_text, editable per-invoice with "Reset to default".
  9. SUP task linking: Line items show linked_issue_key (SUP-* tasks) from ClickHouse jira.jira_issues linked via Jira "duplicates" relation.
  10. Company name enrichment: Invoice list and detail views show company names from ClickHouse cdm.jira_customers, with graceful degradation if ClickHouse is unavailable.