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:
- Fetches
client_invoice_configfor the application - Validates the numbering seed exists (rejects generation if
last_invoice_numberis NULL) - Begins a transaction
- Atomically increments
last_invoice_numberusingSELECT ... FOR UPDATE - Copies display toggle defaults and legal text from the config
- Inserts the invoice and line items
- 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"]
}'
| Operation | Effect |
|---|---|
add | Creates new line items with source = 'manual' |
update | Modifies existing line items, records changes in edit history |
remove | Soft-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.