README docs INVOICE_RESPONSE.md

Invoice sync — HTTP response (POST …/sync)

The controller wraps the service result in a fixed JSON envelope. Source: src/controllers/invoice.controller.jssyncInvoice.


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:

  1. 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.

  2. 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.

  3. 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: handleInvoiceItems aligns DB line items with the payload based on the invoice action.
    • Payments: if the invoice was not skipped and payment_method is non-empty, insertPayments runs.
    • Timestamps and payment method may be normalized during the worker (refactorInvoice, date conversion, JSON stringification of complex payment_method).

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 400 with validation details from your global error handler (not the success wrapper above).
  • Missing UUID in service: 400 with 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 200 with data — 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.jssyncInvoice
Post-response processing src/queue/order-processing-queue.jsprocessOrder
DB + payments src/workers/invoiceSyncWorker.js