Invoice sync — HTTP response (POST …/sync)
The controller wraps the service result in a fixed JSON envelope. Source: src/controllers/invoice.controller.js → syncInvoice.
Response shape (success)
HTTP status: 200 OK
Body:
{
"success": true,
"status": 200,
"data": [ /* see below */ ],
"message": "Invoice numbers synchronized successfully"
}
| Field | Type | Meaning |
|---|---|---|
success |
boolean | Always true for this successful branch |
status |
number | Same as HTTP status (http-status OK code) |
data |
array | One object per input invoice, after number assignment (see next section) |
message |
string | Fixed success copy |
What is in data (each element)
data is the array returned from invoiceService.syncInvoice. It is not the raw return value of the BullMQ addJob calls. Each element is your original invoice object plus these added or overwritten fields:
| Field | Type | When set | Meaning |
|---|---|---|---|
order_no |
number | Always set for each processed entry | Order number used for this UUID (from Redis cache or newly generated) |
customer_invoice_id |
number | Always set | Invoice number (invoiceNumber in internal/cache structures) |
cached |
boolean | Always set | true if order_no / customer_invoice_id were read from Redis for this UUID; false if freshly generated and cached |
All other properties you sent (items, totals, customer info, etc.) are still on each object as spread from your input, except order_no is explicitly set to the resolved value (your client order_no may be overwritten).
What happens to the invoice after the response
The HTTP response does not mean the invoice is already saved to the database. Flow:
Before the response: invoice/order numbers are resolved and cached in Redis (when new), and each order in memory is updated with
order_no,customer_invoice_id,cached.Before the response: each order is queued on
order-processing(BullMQ). The API waits only for jobs to be added, not for workers to complete.After the response (async worker):
- Invoice row: insert, update, or skip depending on existing DB state and business rules (
handleInvoice— e.g. skip when the order is already in a state that should not be overwritten). - Line items:
handleInvoiceItemsaligns DB line items with the payload based on the invoiceaction. - Payments: if the invoice was not skipped and
payment_methodis non-empty,insertPaymentsruns. - Timestamps and payment method may be normalized during the worker (
refactorInvoice, date conversion, JSON stringification of complexpayment_method).
- Invoice row: insert, update, or skip depending on existing DB state and business rules (
So: data tells you the authoritative numbers for each UUID (idempotent per UUID via Redis). DB state catches up when the worker job succeeds; on worker failure, BullMQ retries (see queue attempts / backoff in order-processing-queue.js).
Errors (not the success envelope)
- Validation: invalid body vs Joi → typical
400with validation details from your global error handler (not the success wrapper above). - Missing UUID in service:
400with message like “UUID is required for invoice synchronization” (service-level check). - Worker failures: logged and retried by the queue; the client may already have received
200withdata— clients that need strong consistency should poll another API (e.g. get invoice by UUID) or listen to downstream events, not assume DB write completed at response time.
Related code
| Piece | Path |
|---|---|
| Response envelope | src/controllers/invoice.controller.js |
data construction |
src/services/invoice.service.js → syncInvoice |
| Post-response processing | src/queue/order-processing-queue.js → processOrder |
| DB + payments | src/workers/invoiceSyncWorker.js |