# Invoicing QuickBooks Write-Back Design Date: 2026-07-08 Area: `src/app/(app)/invoicing/page.tsx`, `n8n_workfows/1 - WFDASH QUICKBOOKS INVOICE1 - WFDASH QUICKBOOKS INVOICE-2.json`, `order_items` Status: Drafted for review ## Goal Complete the QuickBooks invoicing round-trip from the Invoicing page. After an operator selects the QuickBooks billing company and customer, the app should create the invoice in QuickBooks, write the result back to PocketBase on the linked `order_items`, and then let the screen show the invoice number, invoiced status, invoice PDF, and print actions after refresh. ## User Need Operators create one QuickBooks invoice per selected order group. Once QuickBooks returns success, the app must clearly show which items are on that invoice, mark those items as invoiced, and make the invoice available for viewing and printing. The user confirmed that the write-back target should be `order_items` only. ## Approved Direction - Keep the existing QuickBooks creation flow in n8n. - Treat the selected QuickBooks billing company as `billing_company` and the matched QuickBooks customer as `invoice_company`. - Include the person who clicked send in the webhook payload. - After QuickBooks success, n8n updates only the linked `order_items` in PocketBase. - The Invoicing page continues to use PocketBase as the source of truth and simply reloads after success. ## Scope In scope: - sending sender identity and linked item ids from the frontend, - updating `order_items` after QuickBooks success, - writing invoice metadata into `order_item_details.invoice`, - marking all linked items as `invoiced`, - storing the returned invoice PDF reference in `qb_invoice_pdf`, - surfacing the saved state on the existing Invoicing page after reload. Out of scope: - updating `orders`, `purchase_order`, or any other collection, - redesigning the Invoicing page layout, - changing the existing print composition logic, - optimistic UI state that bypasses PocketBase, - partial-success handling that leaves some items updated and some not updated. ## Data Contract ### Frontend To n8n The frontend send action should include the existing invoice payload plus: - `billing_company`: selected QuickBooks context, for example `CNL` or `ISHERWOOD` - `invoice_company`: matched QuickBooks customer name, for example `Adal Engineering` - `customer_id`: selected QuickBooks customer id - `customer_name`: selected QuickBooks customer display name - `order_item_ids`: PocketBase ids for every linked item in the invoice group - `sent_by_id`: PocketBase user id for the logged-in operator - `sent_by_name`: display name for the logged-in operator ### n8n To PocketBase After successful QuickBooks invoice creation and PDF retrieval, n8n updates every linked `order_item` with: - `item_status = "invoiced"` - `qb_invoice_pdf = ` - `order_item_details.invoice = { number, date, setAt, setBy, setByName, billingCompany, invoiceCompany, qbInvoiceId, qbInvoiceLink }` The same invoice metadata is written to every linked item that belongs to the invoice. ## PocketBase Shape The existing page already reads `order_item_details.invoice.number`, `order_item_details.invoice.date`, `item_status`, and `qb_invoice_pdf`. To avoid adding a parallel format, the workflow should extend the existing invoice object instead of creating a new top-level structure. Recommended saved shape: ```json { "invoice": { "number": "INV28819", "date": "2026-07-08", "setAt": "2026-07-08T12:34:56.000Z", "setBy": "USER_ID", "setByName": "Operator Name", "billingCompany": "CNL", "invoiceCompany": "Adal Engineering", "qbInvoiceId": "129869", "qbInvoiceLink": "https://app.qbo.intuit.com/app/invoice?txnId=129869" } } ``` ## Flow 1. Operator opens the invoice modal for a PO group. 2. Operator selects the QuickBooks billing company. 3. The app fetches and shows matching QuickBooks customers for that billing company. 4. Operator selects the QuickBooks customer and clicks send. 5. The frontend posts the payload, including `order_item_ids`, `sent_by_id`, and `sent_by_name`, to the n8n webhook. 6. n8n creates the QuickBooks invoice, downloads or resolves the invoice PDF, and prepares the success payload. 7. Before returning success, n8n updates all linked `order_items` in PocketBase. 8. The frontend receives success, shows the success toast, and reloads the page. 9. The Invoicing page reads the updated PocketBase rows and now shows invoice number, invoiced status, invoice view link, and print action. ## Error Handling - If QuickBooks create fails, n8n must not update PocketBase. - If QuickBooks succeeds but PocketBase write-back fails, n8n should return an error and the UI should not show a clean success state. - If any linked `order_item` update fails, treat the whole operation as failed rather than silently accepting a partial write-back. - The frontend should continue to show the existing error toast behavior when the webhook response is not successful. ## Implementation Shape - Modify `src/app/(app)/invoicing/page.tsx` to include `order_item_ids`, `sent_by_id`, and `sent_by_name` in both the single-order and bulk invoice payloads. - Reuse the existing `pb.authStore.model` data for the sender identity. - Modify the n8n workflow JSON to add a PocketBase update branch on the success path after invoice creation and PDF retrieval. - The workflow update step should iterate over all linked `order_item_ids` and patch each item using the shared invoice metadata. - Keep the existing frontend refresh behavior after success. ## Validation Plan After implementation, validate that: 1. The webhook payload includes the selected billing company, invoice company, sender identity, and linked item ids. 2. A successful QuickBooks invoice writes back to every linked `order_item`. 3. Each updated item shows `item_status = invoiced`. 4. Each updated item stores `qb_invoice_pdf`. 5. Each updated item stores `order_item_details.invoice.number` and `order_item_details.invoice.date`. 6. The Invoicing page refresh shows the invoice number beside the rows. 7. `View invoice` becomes available. 8. `Print` becomes available for the invoiced group. ## Risks And Guardrails Primary risk: QuickBooks success is reported to the operator before PocketBase reflects the result, leaving the page looking stale or incomplete. Guardrails: - PocketBase write-back happens before the final success response, - all linked items receive the same invoice metadata, - partial write-back is treated as an error, - the page keeps PocketBase as the single source of truth after reload. ## Acceptance Criteria This enhancement is complete when: - the user can create a QuickBooks invoice from the Invoicing page, - n8n writes the QuickBooks result back to the linked `order_items` only, - linked items are marked `invoiced`, - linked items store the invoice number, date, sender, billing company, invoice company, QuickBooks id, QuickBooks link, and PDF reference, - the Invoicing page refresh shows the saved invoice data without extra manual steps, - the operator can view and print the invoice from the existing page actions.