# WP8 — Routing operations, CoA parameters, and the order material grid get column control

**Repo:** FE (`/home/moonui2/public_html/moon-erp`) · **Branch:** `hazemdev2` · **Depends on WP7** · **BE change:** none

## Goal

Three Production grids that **cannot** become `TransactionLineItemsComponent`, but should still get
drag-to-reorder and drag-to-resize. Use `src/app/shared/util/tx-column-layout.ts` over their existing
hand-written cells — exactly the WP5 approach. Read WP5's report (`../tasks/WP5-report.md`) first and
follow the structure it established.

| Screen | docKey | Why it stays bespoke |
|---|---|---|
| `src/app/features/production/routing/` — operations | `production.routing` | 12 columns, **no product at all**, and two checkbox columns (inspection / critical). The shared component has no boolean cell type. |
| `src/app/features/production/coa/` — parameters | `production.coa` | A derived pass/fail **status** cell; the shared component's computed cell returns a number, not a state. |
| `src/app/features/production/orders/` — **the Issue Materials dialog grid** | `production.order_issue` | Widest grid in the module; lines are **built by the server and cannot be added to**; several columns are read-only. It is an execution grid, not an entry grid. |

### Field keys — registered and VERIFIED by WP4 against the real row models. Use verbatim.

`production.routing`: `operation_no` · `name` 🔒 · `work_center_id` 🔒 · `tool_id` ·
`setup_time_minutes` · `run_time_per_unit` · `cavity_count` · `cycle_time_seconds` ·
`queue_time_minutes` · `move_time_minutes` · `inspection_required` · `critical_operation`

`production.coa`: `name` 🔒 · `unit` · `spec_min` · `spec_max` · `result` 🔒 · `result_status`

`production.order_issue`: `product_id` 🔒 · `unit_id` · `planned_quantity` · `consumed_quantity` ·
`remaining` · `quantity` 🔒 · `warehouse_id` · `owner_partner_id`

🔒 = `locked: true`. Note WP4 deliberately locked `quantity` (Issue Qty) too — hiding it would leave
a dialog that cannot issue anything.

⚠️ **`line_value`, `result_status`, and `operation_no` are display-only columns whose keys WP4
chose** (they have no control name of their own). Use those exact strings or the column becomes
permanently unhideable.

⚠️ **Target correction:** WP4 found the grid carrying these columns is the **Issue Materials
dialog**, not the read-only Materials tab named in the original analysis. Wire the dialog's grid.

## ⛔ The material grid's EDITABILITY MUST NOT CHANGE — this is the hard constraint

Column control only. Whatever is editable in the Issue Materials dialog today stays exactly that;
**nothing read-only becomes editable**, no add-line/remove-line button appears, and **no unit picker
is added**. (The dialog does let the keeper set issue quantity, warehouse and consignor — that is
existing, intended behaviour. Leave it precisely as it is.) The read-only Materials tab is not
touched by this WP at all.

Why, concretely — this is a live landmine, not a style preference:
- The manual material save path does **not** run the ownership resolver, does **not** apply waste,
  and does **not** apply the batch ratio; that logic lives only in the BOM path. Today the screen
  sends no materials, so the trap is dormant. Making the grid editable wakes it: `supply_source`
  falls to `own`, customer quantities stay zero, and a toll order's materials post to the factory's
  WIP instead of the customer's account.
- The issue line's `unit_id` is **advisory** — the server overwrites it with the planned material's
  unit. Adding a unit picker breaks that match and routes every issue down the conversion branch,
  which in turn changes toll-fee invoicing.
- Costs are **computed, not posted**. An editable cost cell writes a number the server contradicts.

If you believe a cell must become editable to make column control work, **stop and report** — it
must not.

## Also do not touch

- `owner_partner_id = 0` is a sentinel (`null` = auto split, `0` = force "own", `>0` = a customer).
  Nothing in this WP may cause a blank control to emit `0`.
- The routing checkboxes keep their exact bindings; only their column position/width becomes dynamic.

## Implementation notes

- Structural columns (row `#`, trailing actions) render **outside** the ordered loop so they stay
  pinned — the reorder index math depends on it.
- Header `<th>` loop and every row's `<td>` loop must consume the **same** `layout.orderedColumns()`
  list, or they drift out of alignment on reorder.
- Supply a `defaultWidths` map per grid: under `table-layout: fixed` an unsized column collapses.
  Routing has 12 columns — give it realistic defaults or the row will be unusable.
- Verify each registry field key against the real template/control name; where they disagree, fix the
  registry and report it.

## Acceptance criteria

1. All three grids reorder and resize, RTL-correct, persisted company-wide, surviving reload.
2. Hiding a non-locked column from the Documents settings screen works on all three; locked columns
   cannot be hidden.
3. Header and body cells stay aligned after any reorder + any hide, on all three.
4. **The order material grid is still entirely read-only** — no cell became editable, no line can be
   added or removed. State explicitly in your report that you verified this.
5. Routing's two checkbox columns still toggle and save correctly after reordering.
6. CoA's derived pass/fail cell still derives correctly after reordering.
7. Saving each screen produces a payload identical to before this WP. Say how you verified it.
8. `npx ng build --base-href /app/` green; `npx tsc --noEmit` no new errors.

## Environment / rules

- ⛔ **NEVER** `git checkout` / `restore` / `stash` on `src/assets/i18n/ar.json` or `en.json`.
  Additive edits only; a new key goes in BOTH files.
- **Do NOT deploy to `/app`** — the orchestrator deploys.
- `chown moonui2:moonui2` every edited file. Commit on `hazemdev2`, conventional. **No push, no merge.**
- moonui2 ONLY — never `/home/moonui`. Never print a git remote URL.

## Out of scope

Making the material grid editable (explicitly forbidden above) · toll contracts, shop-floor,
calendars, confirmations (all judged non-convertible) · modifying `TxColumnLayout` itself.
