# Smoke Test Plan — Quote Optimization (Ticket 1154)

**Branch:** `feature/quoteOptimization-ticket_1154`
**Compared against:** `staging` (merge-base `1d5d074`)
**Scope:** 60 files changed (~3,690 insertions / ~2,652 deletions), 20 new files. Evolution ERP repo.
**Audience:** Tester (user point of view) → feedback to developers.

---

## 1. What this ticket actually does (read first)

This is mostly a **performance refactor, not a feature change.** Previously, every pop-up dialog ("modal") and the History panel on the Quote Edit and Job Edit screens was built into the page every time it loaded — even if the user never opened it. This branch changes them to **load on demand**, the moment the user clicks the button that opens them (fetched in the background via AJAX).

**What this means for testing:**
- Most "features" are unchanged — they have just **moved into separate files and now load when clicked**. Nothing should be missing.
- The #1 risk everywhere: a pop-up that **opens empty, opens blank/slow, fails to open, or opens but its Save / calculation buttons don't work** because its supporting script didn't load.
- A master switch (`moveModalsToAjax`) is currently **ON for everyone** (`index.php`). If a widespread problem appears, this is the single switch developers can flip off to revert behaviour.

Mixed in with the refactor are a few **real bug fixes** (fence costing route labels, BOM cost/markup maths, stock-on-hand figures, dropdown population). Those are called out as ⚠️ **VERIFY THE FIX** below and deserve extra attention.

**General rule for every pop-up listed below:** confirm it (a) opens, (b) shows the correct content/data, (c) Save works and the data persists after reload, and (d) any money figure inside the pop-up **matches the figure shown on the screen behind it**.

---

## 2. Screens affected & what to smoke test

### A. QUOTE EDIT SCREEN (`Quote Edit`) — heaviest change

The Quote Edit screen was reorganised into a **top tab bar with three tabs: General / Files & Uploads / History.** The previous single long-scrolling layout is now split across these tabs. Most pop-ups now load on demand.

**Core layout tests**
1. Open an existing quote → page loads on the **General** tab with three tabs visible.
2. Click each tab (General, Files & Uploads, History) → content shows; the web address updates with `&tab=...`. Reload while on a non-General tab → it should reopen on that same tab.
3. **General tab:** change a line item's quantity/price → the line total and quote total recalculate. Add a line item → it appears and totals update.
4. Click the section/tab filter buttons above the item list → items filter by section. (May take a second to become active — it now initialises after the tab loads.)
5. Drag-and-drop a file onto a line item → upload works (give it a couple of seconds on a slow connection).
6. **Files & Uploads tab:** the quote attachments area appears here now.
7. **History tab:** the history log loads; the **PRICE ANALYSIS** link now lives here.
8. Save the quote, reload → all data persists.

**Quote pop-ups to open one by one (each must open with content + working buttons):**
| Pop-up | How to open | What to check |
|---|---|---|
| **Notes** | Notes icon | Both sub-tabs (Quotation / Internal) show existing text; load a template; tick a Special Clause; Save; reload → persists. The Inclusions / Optional Extras totals match the line items. |
| **Pricing Analysis** | PRICE ANALYSIS link (History tab) | **Save the quote first** (banner warns figures reflect saved data only). Category % rows display and look sane (~100% total); expand a section accordion; a $0 quote shows 0% (no error). |
| **Revisions** | Revisions button | All revisions list; original shows bold "Original"; clicking a row opens that revision. |
| **Load Starter Template** | "⋮" icon next to quote reference | Templates populate; for a client *with* contract pricing the "Apply Customer Contract Pricing" box appears, for one *without* it's hidden; load a template → items appear. Confirm it doesn't wipe an existing quote unexpectedly. |
| **Copy Quote (Quotation Cloning Tool)** | Copy Quote button | Clone a quote → new quote created against the correct client/site with the right line items (no duplicates). |
| **UOM Conversion Tools** | UOM button | Opens with content and converts. |
| **Add Task / Edit Task** | Task add/edit | Opens, saves a task. |
| **Add Inventory Item — Advanced (BOM builder)** | Advanced add option | See section D — exercise the BOM builder carefully. |

⚠️ **VERIFY THE FIX — Quote Type settings:** Open **Quote Type → Add** and **Quote Type → Edit**. Confirm the **Quote Template** and **Invoice Template** dropdowns both populate (and on Edit the saved template stays selected). A variable-collision bug previously could leave these empty.

---

### B. JOB EDIT SCREEN — pop-ups moved to on-demand loading

The Job Edit screen's tabs are unchanged in layout, but most of their pop-ups were extracted into separate files and now load on demand. **Test that every pop-up still opens with the right content and saves.** The table shows where each lives now (so the tester knows nothing was deleted):

| Tab | Pop-up / feature | Smoke test |
|---|---|---|
| **General** | Site Address | Edit Address 1/2, Suburb, State, Postcode → Save → persists. ⚠️ Address feeds delivery/dispatch — confirm a change flows through to dispatch docs. |
| General | Snapshot Help (?) | Help text appears (WIP / Pending cards explained). |
| General | Defects list | Defect list shows with correct statuses/assignees; rows open the defect. |
| General | Add Task / Edit Task / Predefined Tasks | Each opens and saves. |
| General | **Close Job** | See ⚠️ financial note below. |
| **Manufacturing** | **External Manufacture Order** | On a job with active external shop orders: rows show correct Item / SO ID / Process / Required / Ready; "Order All" fills enabled qty fields; pick a BOM item; "Generate Requisitions" creates reqs and returns to the MF tab. |
| **Servicing** | New Maintenance Schedule | Set reference, days, weekly/monthly interval, start/end dates, activity type, customer PO. End-before-start should be blocked. Save. |
| Servicing | Edit Maintenance Schedule | Fields prefill; change status; "Save" and "Finalize Schedule" both work. If auto-dispatch is on, the dispatch section appears. |
| **Job Inventory** | Assign Inventory / New Production Order / Return Dispatched Goods / Add Inventory Item | Each opens and completes. Item filter search still works. |
| Job Inventory | Advanced Add Inventory (BOM builder) | See section D. Confirm a non-privileged user still gets basic Add but not the advanced editor. |
| **Invoicing** | Cost Type help | Nominal / Default / Quoted definitions display. |
| Invoicing | Invoicing modal | See ⚠️ financial note. |
| **Quotes** | **Import a Quotation** | Searchable list shows this client's unattached quotes; type to filter; select → options load; "Import Quotation" → items land on the job with correct qty/price; an already-imported quote doesn't double-import; you can't import another client's quote. |
| **Warehouse / QA** | Report Defect | Form opens, fill, Save → defect created. Existing QA view modals still display. |
| **Field Service** | Produce Site Instructions | Opens, submit → instructions produced. |
| **RCTI** | New RCTI Claim | Opens, create a claim, saves (check amounts). |
| Shared (any tab) | Notes / Add Note | Notes list shows; "+" adds a note linked to the correct client; if you're a job-control admin you can toggle delete/undo (non-admins should NOT see/delete inactive notes). |
| Shared | Manage Retention (Edit Retention) | See ⚠️ financial note. |
| Shared | Project Hold / Job Settings | Toggle status to On Hold → reason + note fields reveal → Save → persists. With Strict Mode on and no planned activity, the form is blocked and the Calendar link works. |
| Shared | Custom Fields | Fields populate and save. |
| Shared | Dispatch / Picking / Call-up / Production Order / Return Goods / Requisition | Each opens from the job and completes. **Picking especially** — its dedicated script file was removed, so confirm the picking-slip form behaves fully (see dev flags). |

⚠️ **FINANCIAL PARITY — highest-priority Job Edit check.** Close Job, Invoicing, Invoice Job, and Manage Retention all now recompute their money figures independently when the pop-up loads. For each, **open the pop-up and confirm the money figure inside matches the figure on the tab behind it** (estimated revenue, invoiced amount, remaining-to-invoice, uninvoiced amount, retention amounts). A mismatch is a real over/under-invoicing risk and must go straight back to developers.

- **Close Job:** on a job with open dispatches/requisitions/MF orders → expect a warning and no close form. On a clean job → close form appears; tick "Retention owing" → date/amount rows appear and add/remove work; "Ignore Uninvoiced Value" appears when there's an uninvoiced amount; submit closes the job.
- **Edit Retention:** open an existing retention → fields populate; Save persists date + amount; Void / Mark Paid / Mark Not Paid transition correctly.

---

### C. FENCE COSTING PLUGIN — ⚠️ VERIFY THE FIX (calculations + labels)

Real bug fix to the manufacturing-route label shown on fence quote items, plus removal of stray text that was leaking into quote output.

1. Build a fence-costing quote; set / override a manufacturing route on a line.
2. Confirm each line shows the **correct** "Manufacturing Route: <name>" label — including when the advanced BOM route dropdown isn't shown or has a different selection, and across multiple fence lines with different route overrides (override / powder-coated / hot-dip).
3. Confirm **no stray text** appears in the quote output (a leaked value was removed).
4. Confirm fence totals/costs still compute correctly.
5. **Edge case for developers to watch:** an item assigned to an **inactive/archived** manufacturing route may error or show a blank label — test one if possible.

---

### D. ADVANCED BOM BUILDER / ADD-INVENTORY — ⚠️ VERIFY THE FIX (cost & markup maths)

Used from both Quote Edit and Job Inventory "Advanced Add Inventory". Real bug fixes to cost/markup parsing live here.

1. Open the advanced BOM builder on a quote/job item; walk every wizard step.
2. Confirm BOM line **subtotals and costs compute correctly** (a cost-parsing bug was fixed).
3. Enter a **decimal markup** (e.g. 12.5%) → sell price recalculates correctly (decimals were previously dropped).
4. Add a labour line **without** selecting a labour category → shows 0, not "NaN".
5. Filter dropdowns on step 1 work.
6. Modify an existing item through the builder and save → changes persist.

---

### E. APP-WIDE REGRESSION CHECK (because shared global code changed)

Shared files (`global.js`, `app/ajax.php`) that every screen uses were changed. Do a light pass beyond quotes/jobs:

1. Load several unrelated screens (dashboard, contacts list, jobs list, purchase orders, opportunities) → nothing broken; buttons and pop-ups elsewhere still work.
2. On **purchase order** and **opportunity** screens, confirm features that rely on the record id (history, attachments, deep links) still find the right record.
3. Click any lazily-loaded modal trigger **twice** → first click opens it, second click reopens it without breaking.
4. Open the **History** panel on a quote and on a contract-pricing screen → entries load.

---

## 3. High-risk areas to flag to developers

These are where a bug is most likely and most costly. Worth a developer's explicit confirmation alongside testing.

1. **Modal allowlist in `app/ajax.php` (highest blast radius).** Only modals on a hardcoded allow-list will load now; any production modal *missing* from the list will silently **404 / do nothing**. Devs should confirm the list covers every modal actually used on quote and job screens. Similarly the `getPage` allow-list is narrow (`history`, `attachmentdiv` only) — any other screen that fetched a page this way will break.

2. **Financial figures recomputed twice** (`jobeditmovemodalcommon.inc` / `quoteditmovemodalcommon.inc`). Invoice totals, remaining-to-invoice, uninvoiced amount, retention, and **job-close eligibility** are re-derived when a pop-up loads, separately from the main screen. If the two computations drift, users see different money / are wrongly allowed or blocked from closing a job. **Cross-check every money figure between pop-up and screen.**

3. **Scripts must load inside on-demand pop-ups.** Close Job, Retention, External MF, and Picking depend on JavaScript functions (`validateRententionOwing`, `submitEditRetention`, `mf_force_bom_external`, etc.). When a pop-up is fetched on its own, confirm its scripts come with it. **Picking is the clearest regression risk** — its dedicated script file (`pickingadd.js`) was removed.

4. **JS load-order dependency.** `itemModify.js` now relies on variables declared in `invaddadvanced.js` and must load after it. Both scripts' page-load init was changed to run on injection (not `DOMContentLoaded`). Confirm the BOM builder works only via the new on-demand path and the order always holds.

5. **External MF requisition quantities** (`jobexternalmf.inc`). The ready/remaining calculation was refactored from loops into lookup arrays. Compare ready/remaining numbers against staging for multi-depth routes and items with prior requisitions — a wrong "ready" could over- or under-order materials.

6. **Stock-on-hand / allocated figures** (`jobedit.inc`). A variable-collision fix (`$inv` → `$invt`) touches the on-hand/allocated calculation. Confirm those columns still match staging.

7. **The master switch is hardcoded ON** (`index.php`, `$moveModalsToAjax = true`). The entire ticket is live on every screen. It's a literal `true`, not a configurable setting — devs should confirm there's an easy off-switch if a regression ships, and that the old inline (switch-OFF) code path still works as a true no-op.

8. **Minified JS twin (process check).** `global.js` and the module JS were edited — confirm whatever bundling/minification Evolution uses picked up the changes so the fixes actually ship.

9. **Inline SQL pattern (low exploit risk, flagged for consistency).** Several new includes build queries with interpolated values instead of bound parameters (`quotenotes.inc`, the two `*movemodalcommon.inc` files). Values are int-cast or DB-sourced, so injection risk is low, but it's inconsistent with the project's prepared-statement convention.

---

## 4. Quick reference — every changed page

**Quote:** Quote Edit (quotedit), Quote Type Add/Edit, plus new pop-up files (notes, pricing summary, revisions, starter template, copy, import quotation, quote information panel).
**Job:** Job Edit container + all tabs (General, Manufacturing, Service, Inventory, Invoice, Quotes, Warehouse, Field Service, RCTI) and their extracted pop-ups (address, scheduling add/edit, close job, retention, settings, external MF, defects, notes, cost-type help, snapshot help).
**Shared / global:** `app/ajax.php` (AJAX router), `assets/js/global.js`, advanced inventory + item-modify JS, custom fields, history panel, index.php, invoice/dispatch/picking/return/call-up/MF/note add modals, activity summary.
**Plugins:** fence costing (route label fix), cost updater & CSV exporter (whitespace only — no test needed).
