Skip to main content

Invoices — Test Cases

Manual acceptance test cases for the invoice flows. See Invoices concept and the invoice guides for context.


TC-INV-001 — Feature flag toggles invoice surface area

Verifies: Invoices concept

Preconditions:

  • Logged in as Admin.
  • Tenant setting feature_flag_invoices_enabled is initially on.

Steps:

  1. Confirm the Invoices menu item is visible in the top navigation bar.
  2. Navigate to Settings and turn feature_flag_invoices_enabled off.
  3. Reload.

Expected:

  • The Invoices menu disappears from the top navigation bar.
  • Direct navigation to /admin/invoices returns a 404.
  • The Invoice card on a completed work order does not show a Create Invoice button.
  • Reset the setting to on at the end of the test.

TC-INV-002 — Create an invoice from a single completed work order

Verifies: Create an Invoice

Preconditions:

  • Logged in as Office (with invoices.create).
  • Invoices feature flag is on.
  • A completed work order exists with line items totaling $500 (use TC-WO-007).

Steps:

  1. Navigate to Work Orders and open the completed work order.
  2. In the Invoice card on the right, select Create Invoice.
  3. Leave Include unit price on. Confirm the Tax Rate (%) is the tenant default.
  4. Confirm the Grand Total matches the items subtotal plus the device-model unit cost plus tax.
  5. Select Create Invoice.

Expected:

  • Invoice is created with status sent and an invoice_id using the configured prefix (default TFT).
  • The Invoice card on the work order updates to show the invoice number, breakdown, and a Cancel Invoice button.
  • The work order's status is unchanged by invoicing — to mark it billed, a supervisor uses the separate Mark as Billed action.
  • Editing the original work order's line items afterward does not change the invoice totals (unit_subtotal and item_subtotal are snapshotted at create time).

TC-INV-003 — Tax-exempt customer: zero tax produces matching subtotals

Verifies: Create an Invoice, Invoices concept

Preconditions:

  • Logged in as Office (with invoices.create).
  • A completed work order exists for a tax-exempt customer with line items totaling $500.

Steps:

  1. Open the completed work order.
  2. In the Invoice card, select Create Invoice.
  3. Toggle Include unit price off.
  4. Set Tax Rate (%) to 0.
  5. Confirm the breakdown shows Unit Subtotal $0.00, Items Subtotal $500.00, both VAT lines $0.00, Grand Total $500.00.
  6. Select Create Invoice.

Expected:

  • Invoice is created with status sent, unit_subtotal 0, item_subtotal 500, tax_rate 0.
  • The Invoice card now shows the invoice number and a Cancel Invoice button.
  • A second attempt to create an invoice on this work order fails with "An invoice already exists for this work order." (active-invoice protection).

TC-INV-004 — Cancel an unpaid invoice unblocks re-invoicing

Verifies: Cancel an Invoice, Invoices concept

Preconditions:

  • A sent (unpaid) invoice exists from TC-INV-002.
  • Logged in as Office (with invoices.edit).
  • The connected billing system (CaribeEats) is reachable.

Steps:

  1. Open the work order that has the invoice.
  2. In the Invoice card, select the red Cancel Invoice button.
  3. Confirm when prompted.

Expected:

  • Invoice status moves to cancelled, and cancelled_at is recorded.
  • The cancellation is mirrored to the connected billing system (verify a corresponding cancellation log entry).
  • The work order's status is unchanged (still completed or billed — invoicing does not flip it back).
  • The cancelled invoice remains visible in the Invoices list with a Cancelled badge for audit purposes.
  • A new invoice can now be created on the same work order — the Create Invoice button reappears in the Invoice card.

TC-INV-005 — Paid invoice cannot be cancelled

Verifies: Invoices concept

Preconditions:

  • A paid invoice exists.
  • Logged in as Office (with invoices.edit).

Steps:

  1. Open the work order that has the paid invoice.
  2. In the Invoice card, look for the Cancel Invoice button.
  3. If the button still appears (guard is server-side), force a POST to /admin/invoices/<id>/cancel.

Expected:

  • The forced POST is rejected with a danger flash "A paid invoice cannot be cancelled."
  • The invoice status remains paid.
  • No call is made to the billing system.