Appearance
Universal Invoice Builder — manual E2E script
Use when adding Playwright later; run manually until automated.
Setup
- Backend migrated + running
- Admin logged in with
billing.create,billing.read - One inventory invoice exists (regression)
Automated smoke (local)
With Admin (localhost:3000), Backend, DB, and qa-tests/.env + Backend/.env:
powershell
npm run invoice-builder:smoke --prefix d:\Client\Beentara\qa-testsChecks: API custom_layout tab count, /new-invoice Custom toggle + builder, /invoice Custom layouts chip.
Optional deep checks (needs at least one saved custom invoice):
powershell
$env:INVOICE_BUILDER_DEEP=1; npm run invoice-builder:smoke --prefix d:\Client\Beentara\qa-testsValidates singleinvoice JSON + PDF for the latest custom row.
Manual E2E
Flow A — Custom invoice happy path
- Create
/new-invoice→ Custom invoice → expand Table columns & calculations if needed - Add 2 columns (Text + Currency), 2 rows, set currency column for subtotal
- Add shipping; verify grand total on form
- Publish (draft OK for portal skip)
- Detail
/invoice-detail/:id— preview table + Custom badge - Download PDF — compare to Resend email attachment (should match)
- Customer ledger — Custom badge + chip filter
- Main list
/invoice— folder hint + Custom layouts chip
Flow B — Portal / pay (if enabled)
- Open pay link or portal invoice
- Confirm dynamic columns match layout labels
Flow C — Regression inventory
- Open old inventory invoice → PDF download → email table unchanged
Automation hints (Playwright)
- Store
invoiceIdfrom create API or URL after publish - Assert
GET /newinvoice/singleinvoice/:id/pdfreturnsapplication/pdf - Assert portal JSON includes
invoice_mode: "custom"andcustom_table.headers.length >= 2