Skip to main content

Invoice Delivery

Phases 3-4

Phase 3 (PlanFact + R2) is implemented. Phase 4 (Didox + email) is planned.

After approval, invoices are delivered to clients and synced with external systems.

Delivery Flow

Cloudflare R2 Storage (Phase 3) ✅

PDFs are uploaded to Cloudflare R2 on invoice approval (best-effort, before transaction).

SettingValue
Bucketproxima-invoices
Domaininvoices.prxm.uz
Key formatinvoices/{year}/{application_key}/Act_{display_number}.pdf
SDKAWS SDK v2 (S3-compatible)
Packageinternal/services/r2/

After upload, the r2_storage_key and r2_public_url fields on the invoice are populated. If upload fails, approval proceeds normally and the PDF remains available from the database.

Frontend shows "Open PDF" link in the Integrations card when r2_public_url is set, or "Not uploaded" otherwise.

PlanFact Sync (Phase 3) ✅

Approved invoices are synced to PlanFact (accounting system) as shipments via an async goroutine (30s timeout):

PlanFact configuration:

  • Company ID: 146673 (default)
  • API Key: Stored in INVOICE_PLANFACT_API_KEY env var
  • Product IDs: b78ac753-... (hourly), d9c144af-... (support) — seeded in migration 000007

Manual retry: POST /api/v1/invoices/:id/sync-planfact for approved/sent invoices. Frontend shows "Retry" button in the Integrations card when sync has not completed.

Didox.uz (Phase 4)

Local (UZS) invoices are sent via the Didox.uz e-invoicing platform, required for B2B invoicing in Uzbekistan.

FieldValue
Seller TIN309630523 (ProximaOps)
Document typeService act (Акт выполненных работ)

After submission, the didox_document_id and didox_status fields are populated.

Email Delivery (Phase 4)

International invoices are delivered as PDF email attachments:

  • To: Client contact email from ClickHouse (cdm.jira_contacts)
  • Subject: Invoice <display_number> — <period>
  • Attachment: PDF from R2 storage
  • Template: Professional email with payment instructions

Status Updates

ActionStatus Transition
Send via Didoxapprovedsent
Send via emailapprovedsent
Client accepts (Didox callback)sentaccepted
Client rejects (Didox callback)sentrejected
Manual acceptancesentaccepted
Payment receivedacceptedpaid