# Implementation Plan — Operator Tiles + History Cleanup (DO Expected Labels) > Status: **implemented** (UI-only; manual device checks pending). > Scope: **UI labels/columns only** — no API/DB/predict semantics change. > Ports (locked): **5721 = office** · **5000 = operator** (DO manual uploads, legacy manual, live counts). > Operator does **not** need history; history/analytics stay **office-only** (`/history`, `/analytics` already gated in `counter_dashboard.py`). --- ## 1. Why Current operator tiles in `do_manual` show **Net / Target** next to **Karung Masuk / Box Masuk**. When unloading is 0 (normal load-out), net == gross → redundant and confusing. History has a **Net** column that duplicates sacks/boxes when net ≈ count, and **Expected** has no unit hint (sack vs box). **Goal:** operator compares **counted** vs **DO paper qty** in four clear tiles. History drops Net; Expected is labeled as DO sacks/boxes. --- ## 2. Locked decisions | # | Topic | Decision | |---|---|---| | 1 | Port split | 5721 office (mode/model switches, history, analytics, plate require) · 5000 operator (start/stop, DO photo upload, live counts). Unchanged. | | 2 | Operator history | Operator does not consume history/count analytics; no history link/panel on `operator.html`. History page stays office-only. | | 3 | Operator tiles | Four tiles only (see §3). **No “Net …” tiles** on operator UI. | | 4 | DO expected naming | UI name = **DO Sacks** / **DO Boxes** (paper expected). Server fields stay `expected_sack` / `expected_box`. | | 5 | History columns | Cleaner set (§4). **Remove Net column.** Expected labeled as DO sacks/boxes. | | 6 | Backend NET | **Keep** `net_sack` / `net_box` in API, `current_batch.json`, DB, discard rule (`both nets 0`), exports if still needed for audit. **UI stop showing net on operator.** | --- ## 3. Operator tiles (`templates/operator.html`) Replace current info grid rows with: | Tile label | Value | Source (`GET /api/current-batch`) | |---|---|---| | **Sacks** | counted sacks | `count` (same as today’s “Karung Masuk”) | | **Boxes** | counted boxes | `box_count` (same as “Box Masuk”) | | **DO Sacks** | expected sacks | `expected_sack` (0 if no batch/no DO) | | **DO Boxes** | expected boxes | `expected_box` | Render rules: - **All four tiles always visible** on the operator card (not only in `do_manual`). - Non-`do_manual`: DO Sacks / DO Boxes show `0` or `--` (no staged expectation); still show label so layout is stable. - `do_manual` + active batch: DO tiles = values from batch state (start sum of staged DOs). - Remove rows/IDs: `opNetSackItem`, `opNetBoxItem`, and JS that writes `net_sack` / `net_box` into those tiles. - Keep: Batch Berjalan, Waktu Mulai, Plat / No. DO (batch active), mode badge, DO panel. DO card form labels (same vocabulary): - `Ekspektasi karung` → **`DO Sacks`** (or `DO Sacks (karung)` if Indonesian preferred — pick one at implement; default English matches tiles). - `Ekspektasi box` → **`DO Boxes`**. Group preview chips unchanged (already “N karung · M box”). Optional polish (same file, if trivial): under Sacks show `of DO Sacks` only in `do_manual` — **not** a second Net row. --- ## 4. History (`templates/history.html`) — office only Current header: `Batch # | Plate | No. DO | Sacks | Boxes | Expected | Net | Start | End | Duration` **New header (no Net, clearer Expected):** | Column | Content | |---|---| | Batch # | `batch_number` | | Plate | `plate` or `—` | | No. DO | `do_numbers` joined or `—` | | Sacks | `count` (gross loaded; stored as `count`) | | Boxes | `box_loading` | | DO Sacks / Boxes | `expected_sack / expected_box` e.g. `100 / 12` | | Start | time | | End | time | | Duration | minutes | - Remove cell that prints `net_sack / net_box`. - API: keep returning nets if already present; **UI ignores them** (or stop emitting in `day-detail` later — not required). - colspan updates (loading, empty, error rows). - Export day XLSX: drop Net columns if present; rename Expected headers to `DO Sacks`, `DO Boxes` (match UI). No changes to operator gate: `GET /history` still office-only. --- ## 5. Non-goals - No change to `net_counts` / discard-both-nets / `finalize_batch`. - No change to ports, office-only POSTs, OCR engine toggle. - No history page for operator. - No API rename of `expected_*` (JSON keys stable). --- ## 6. Files | File | Change | |---|---| | `templates/operator.html` | Four tiles Sacks/Boxes/DO Sacks/DO Boxes; remove Net tiles + JS | | `templates/history.html` | Drop Net column; Expected → `DO Sacks / DO Boxes` | | `counter_dashboard.py` | Optional: export headers only (if export shows Net/Expected) | | `docs/do-expected-tiles-plan.md` | This plan | | Old plan | Delete `docs/do-batch-implementation-plan.md` (superseded by shipped feature + this UI plan) | --- ## 7. Test / verify ```bash python -m pytest tests/ -q python -m compileall predict.py counter_dashboard.py src tests ``` Manual (office vs operator): 1. `:5000/operator` — tiles labeled Sacks, Boxes, DO Sacks, DO Boxes; no “Net …” labels. 2. `:5000/operator` in `do_manual` — start with DO → DO Sacks/Boxes = sum of DO fields; Sacks/Boxes track camera. 3. `:5721/history` — columns as §4; no Net; Expected shows `n / m`. 4. Operator browser → `/history` → still operator page (office gate). 5. Mode/model POST from `:5000` still 403 (unchanged). --- ## 8. Acceptance 1. Operator live card shows exactly: Sacks, Boxes, DO Sacks, DO Boxes (+ batch meta). 2. No operator-visible string “Net Karung”, “Net Box”, “Net / Target”. 3. History table has no Net column; Expected header communicates DO sacks/boxes. 4. History remains office-only. 5. Discard rule and DB `net_*` columns unchanged. 6. pytest + compileall green.