WFDASH-WEBAPP/docs/superpowers/specs/2026-07-08-invoicing-quickbooks-writeback-design.md
SJCoetz 18334721cb feat(invoicing): add QuickBooks invoicing flow and print functionality
Add complete end-to-end QuickBooks invoicing workflow for the invoicing page:
- Add `jspdf` dependency for client-side PDF generation
- Implement updated item status handling with fallback for new invoice statuses
- Add server-side proxy API for secure QuickBooks customer lookup
- Build utilities to combine QuickBooks invoices and picking slips into a single PDF
- Add invoicing view models for row grouping, payload construction, and status checks
- Add full test coverage for all new components, APIs, and utilities
- Include feature design documentation and sample n8n workflow config
2026-07-09 09:44:55 +02:00

7 KiB

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 = <returned invoice pdf reference>
  • 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:

{
  "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.