Skip to main content

Generate & Edit

After reviewing the prefill preview, users generate a draft invoice (saving to PostgreSQL) and can then edit any field before finalizing.

Generate Flow

Generate Request

curl -X POST http://localhost:8081/api/v1/invoices/generate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"application_key": "APP-001",
"period_start": "2026-02-01",
"period_end": "2026-02-28",
"deal_type": "SUP",
"currency": "UZS",
"base_amount": "15000000.00",
"total_amount": "15825000.00",
"total_hours": "45.50",
"overtime_hours": "5.50",
"overtime_amount": "825000.00",
"is_overtime": true,
"line_items": [...]
}'

The frontend sends the full prefill result (possibly modified by the user) as the generate request. The backend:

  1. Fetches client_invoice_config for the application
  2. Validates the numbering seed exists (rejects generation if last_invoice_number is NULL)
  3. Begins a transaction
  4. Atomically increments last_invoice_number using SELECT ... FOR UPDATE
  5. Copies display toggle defaults and legal text from the config
  6. Inserts the invoice and line items
  7. Commits the transaction

This ensures sequential, collision-free invoice numbering even under concurrent requests.

Bulk Generate

For generating invoices for all active clients at once:

curl -X POST http://localhost:8081/api/v1/invoices/generate-bulk \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"period_start": "2026-02-01",
"period_end": "2026-02-28"
}'

This runs the prefill pipeline for every active application and generates draft invoices for each.

Edit Flow

Draft invoices are fully editable. All edits are tracked in invoice_edit_history.

Edit Invoice Fields

curl -X PATCH http://localhost:8081/api/v1/invoices/{id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"base_amount": "16000000.00",
"total_amount": "16825000.00",
"invoice_date": "2026-03-01"
}'

Editable fields: base_amount, total_amount, overtime_hours, overtime_amount, is_overtime, invoice_date, show_task_list, show_tracked_time, show_task_pricing, show_overtime, legal_text.

Edit Line Items

Line items support three operations in a single request:

curl -X PATCH http://localhost:8081/api/v1/invoices/{id}/line-items \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"add": [
{
"line_type": "task",
"description": "Additional consulting",
"time_seconds": 3600,
"billable_seconds": 3600,
"unit_price": "150000.00",
"quantity": "1.00",
"line_total": "150000.00",
"source": "manual"
}
],
"update": [
{
"id": "uuid-of-existing-line",
"description": "Updated description",
"line_total": "500000.00"
}
],
"remove": ["uuid-of-line-to-remove"]
}'
OperationEffect
addCreates new line items with source = 'manual'
updateModifies existing line items, records changes in edit history
removeSoft-deletes line items, records removal in edit history

Edit History

Every edit is recorded with before/after values:

curl http://localhost:8081/api/v1/invoices/{id}/edit-history \
-H "Authorization: Bearer $TOKEN"
{
"data": [
{
"edit_type": "line_modified",
"field_name": "line_total",
"old_value": "300000.00",
"new_value": "500000.00",
"edited_by": "[email protected]",
"edited_at": "2026-02-15T10:30:00Z"
},
{
"edit_type": "line_added",
"field_name": null,
"old_value": null,
"new_value": "Additional consulting",
"edited_by": "[email protected]",
"edited_at": "2026-02-15T10:31:00Z"
}
]
}

Edit types: line_modified, line_added, line_removed, total_override, deal_amount_override.

Regenerate

Regenerating re-fetches fresh data from ClickHouse and resets the invoice to draft:

curl -X PUT http://localhost:8081/api/v1/invoices/{id}/regenerate \
-H "Authorization: Bearer $TOKEN"

This is used when:

  • An invoice was declined and needs rework
  • A client rejected an invoice
  • Worklog data has been updated in ClickHouse

The regenerate flow re-runs the full prefill pipeline and replaces the current line items. Previous edit history is preserved for audit purposes.