---
name: evolution-invoice-job-quote-import
description: "Invoice Job modal quote-import fixes — target invoice, invoice type, quote-number tagging, and the section-summary zero-GST bug"
metadata: 
  node_type: memory
  type: project
  originSessionId: 223a3fcc-5606-40f1-bcfd-fcae3c4ac754
  modified: 2026-07-30T00:48:15.111Z
---

The **Invoice Job** modal (jobedit Job Costing tab → `newLineInvoice` handler in `jobeditsave.php`, importing via `invoice::importQuote()` in `library/invoice.php`) had four defects, all fixed 2026-07-30 and verified live on dev:

1. **Select Target Invoice was ignored for quote imports** — the dropdown rendered but the handler always called `newInvoice()`. `importQuote()` already appends correctly when `$this->invoiceid` is pre-set (it only builds a header when it's null), so the fix was handler-only.
2. **Select Invoice Type was ignored for quote imports** — the quote's own `qtype` always won. Override now applied inside the header-creation block only, so appending never re-types an existing invoice.
3. **`combineLines()` merged identical lines across different quotes** (proved live: `Delivery to site.` on quotes 22429+22431 collapsed to one qty-3 line). Fixed by the new `$tagQuoteRef` arg on `importQuote()` — appends `" (Quote <id>)"` to each imported description, which also makes the lines non-mergeable. Applied when the invoice will carry >1 quote (existing target **or** multiple quotes ticked), not for a lone quote to a new invoice.
4. **Section-summary imports were raised with ZERO GST** and `accountid=0` (pre-existing, not a regression — dev invoice 59701 from 2025-09-25 shows it too). The sections branch inserted no `taxId`/`taxAmount`/`accountid`. Fixed by grouping each section's `quoteitems` by tax rate, one insert per rate, with the rate name suffixed to the description **only** when the section is multi-rate.

Gotchas found while doing this:
- The custref stamp (`update invoices,jobs set invoices.custref=jobs.contract`) must be guarded to `$targetInvoice == 0` or appending rewrites the target's header.
- The handler had latent PHP 8 fatals: `foreach` over a missing `jInvTimesheetIDs`, `count()` on missing `jInvQuoteId`/`jInvItemId`. Both now defaulted.
- **The multi-rate split path is code-verified only.** No non-zero mixed-rate quote section exists anywhere in the dev tenant (the one mixed-rate section, 20461 on quote 23175, is all zeros), so only the single-rate path was exercised live (invoice 59908, quote 23198: tax 120.69 on 1206.90).

Docs: `docs/projects/invoicing-jobs.php` (new page, all five methods, six screenshots). Prod release notes 148 (first three fixes) + 149 (GST fix), both `status=0`. See [[feature_release_docs_policy]], [[evolution_importquote_tax_drift]], [[evolution_invoice_total_reconciliation]].
