# TODO — R&U (Read & Understood) on Scan Station

> **Feature:** After scanning a Job Wallet QR code on the Scan Station kiosk,
> the monitor displays a list of documents the operator must read and acknowledge
> (R&U — Read & Understood) before proceeding with the operation.

> **Cross-module feature** — spans `scanstation` + `doccontrol` + `trainmatrix`

---

## 0. Context from General Roadmap

- `scanstation` PHASE 3 *(pending)*: "WI display from doccontrol" — this TODO is that phase
- `trainmatrix` PHASE 2: "Link with doccontrol (R&U = proof of training)" — R&U records feed training matrix
- `doccontrol` PHASE 1 scaffold ready — document registry, versioning, approval flow

### How R&U fits in the dependency chain

```
doccontrol  ──── documents (WI, quality alerts, safety, ECR)
    │
    │  R&U acknowledgement
    ▼
scanstation ──── scan job wallet ──► show R&U screen ──► operator confirms ──► record saved
    │
    ▼
trainmatrix ──── R&U = proof of training (IATF 7.2 — Competence)
```

---

## 1. UX Flow — Step by Step

```
1. Operator scans job wallet QR code on Scan Station
       QR = "MO:{rowid}|JOB:{job_number}|ENTITY:{entity}"

2. scan_station.php looks up:
       → MO → fk_product, fk_ws (workstation)
       → find all documents linked to this product + workstation

3. Query: which of those docs does the current operator have a VALID R&U for?

4. Screen shows R&U panel:
   ┌─────────────────────────────────────────────────────────────────┐
   │  JOB FG1090  ·  14AD645CP  ·  FM4                              │
   │─────────────────────────────────────────────────────────────────│
   │  Documents to Read & Understand                                 │
   │                                                                 │
   │  ✅  WI-001  Forming Procedure Rev.3        [already signed]    │
   │  ⚠️  WI-047  Updated Tool Setup FM4 Rev.1   [NEW — must read]   │
   │  ⚠️  QA-012  Safety Alert — Metal Flash     [NEW — must read]   │
   │                                                                 │
   │  [ Open WI-047 ]   [ Open QA-012 ]                             │
   │                                                                 │
   │  [ ✔ I have Read and Understood all documents ]                 │
   │  (button active only when all new docs have been opened)        │
   └─────────────────────────────────────────────────────────────────│
   │  [ Skip — return to scan ]   ← allowed only if 0 new docs      │
   └─────────────────────────────────────────────────────────────────┘

5. Operator opens each document (PDF inline or new tab)

6. Operator clicks "I have Read and Understood"
       → writes to llx_doccontrol_ru (one row per document per operator)
       → sets training_proof = 1 in llx_tm_operator_skill (if linked)

7. Scan station proceeds to operation confirm screen
```

---

## 2. Document Linking — Which docs to show

Documents in `doccontrol` are linked to jobs via one or more of:

| Link type | Trigger | Example |
|-----------|---------|---------|
| **Product-level** | `fk_product` on MO | WI for part FG1090 |
| **Workstation-level** | `fk_ws` on MO | Setup procedure for FM4 |
| **Operation-level** | `llx_mrp_production.rowid` | Specific op on BOM routing |
| **Global / all jobs** | `scope = 'global'` | Safety alert, quality notice |
| **Customer-level** | `fk_soc` via MO | Customer-specific WI (e.g. AS9100 req) |

The scan station query uses a **union** across all relevant link types.

---

## 3. Database Schema

### 3.1 `llx_doccontrol_document` (in `doccontrol` module — already planned)

```sql
CREATE TABLE IF NOT EXISTS llx_doccontrol_document (
    rowid           INT AUTO_INCREMENT PRIMARY KEY,
    ref             VARCHAR(30) NOT NULL,          -- e.g. WI-047
    label           TEXT NOT NULL,                 -- document title
    doc_type        VARCHAR(30) DEFAULT 'WI',      -- WI | QA | SAFETY | ECR | OTHER
    status          TINYINT DEFAULT 1,             -- 1=Active, 0=Obsolete
    version         VARCHAR(10) DEFAULT '1',       -- current approved version
    file_path       VARCHAR(255),                  -- path to PDF in ECM / file store
    date_approved   DATE,
    fk_user_approved INT,
    ru_required     TINYINT DEFAULT 1,             -- 1 = R&U mandatory before op
    ru_valid_days   INT DEFAULT 365,               -- re-acknowledge every N days (0=once only)
    entity          INT NOT NULL DEFAULT 1
) ENGINE=InnoDB;
```

### 3.2 `llx_doccontrol_doc_link` — link table (document → scope)

```sql
CREATE TABLE IF NOT EXISTS llx_doccontrol_doc_link (
    rowid           INT AUTO_INCREMENT PRIMARY KEY,
    fk_document     INT NOT NULL,                  -- llx_doccontrol_document.rowid
    link_type       ENUM('product','workstation','operation','customer','global') NOT NULL,
    fk_object       INT DEFAULT NULL,              -- rowid in the linked table (NULL if global)
    entity          INT NOT NULL DEFAULT 1,
    KEY idx_doc (fk_document),
    KEY idx_obj (link_type, fk_object)
) ENGINE=InnoDB;
```

### 3.3 `llx_doccontrol_ru` — R&U acknowledgement log

```sql
CREATE TABLE IF NOT EXISTS llx_doccontrol_ru (
    rowid           INT AUTO_INCREMENT PRIMARY KEY,
    fk_document     INT NOT NULL,                  -- which document
    fk_version_at   VARCHAR(10),                   -- version at time of sign-off
    fk_user         INT NOT NULL,                  -- operator who acknowledged
    fk_mo           INT DEFAULT NULL,              -- MO context (from scan station)
    fk_ws           INT DEFAULT NULL,              -- workstation context
    scan_context    TINYINT DEFAULT 0,             -- 1 = signed via scan station
    date_ru         DATETIME NOT NULL,
    ip_addr         VARCHAR(45),                   -- for audit
    entity          INT NOT NULL DEFAULT 1,
    KEY idx_user_doc (fk_user, fk_document)
) ENGINE=InnoDB;
```

### 3.4 R&U validity check (SQL)

```sql
-- Find documents for a given MO that the current operator has NOT yet acknowledged
-- (or whose acknowledgement has expired)

SELECT d.rowid, d.ref, d.label, d.doc_type, d.version, d.file_path,
       MAX(r.date_ru) AS last_ru
FROM llx_doccontrol_document d
JOIN llx_doccontrol_doc_link l ON l.fk_document = d.rowid
LEFT JOIN llx_doccontrol_ru r
    ON r.fk_document = d.rowid
    AND r.fk_user    = :fk_user
    AND r.fk_version_at = d.version
    AND (d.ru_valid_days = 0 OR r.date_ru >= DATE_SUB(NOW(), INTERVAL d.ru_valid_days DAY))
WHERE d.status = 1
  AND d.ru_required = 1
  AND d.entity = :entity
  AND (
      (l.link_type = 'global')
   OR (l.link_type = 'product'     AND l.fk_object = :fk_product)
   OR (l.link_type = 'workstation' AND l.fk_object = :fk_ws)
   OR (l.link_type = 'customer'    AND l.fk_object = :fk_soc)
  )
GROUP BY d.rowid, d.ref, d.label, d.doc_type, d.version, d.file_path
ORDER BY (r.date_ru IS NULL) DESC, d.doc_type, d.ref
```

`r.date_ru IS NULL` = not acknowledged → sorts to top (shown first, highlighted).

---

## 4. Scan Station Integration

### 4.1 Changes to `scan_station.php`

After successful `lookup` AJAX call (QR decoded, MO found):
1. Issue a second AJAX call: `ajax/ru_check.php` with `{fk_mo, fk_user}`
2. If response returns `ru_required: true` with a list of docs → render the R&U modal/panel
3. R&U panel **blocks** the Confirm button until all new docs are opened + acknowledged
4. On acknowledge button → `ajax/ru_save.php` → writes `llx_doccontrol_ru`
5. After save → R&U panel closes → normal confirm screen resumes

### 4.2 New AJAX endpoints

#### `ajax/ru_check.php`

```
GET  ?fk_mo=X&fk_user=Y&entity=Z
→ returns JSON:
{
  "ru_required": true,
  "docs": [
    { "rowid": 47, "ref": "WI-047", "label": "Updated Tool Setup FM4 Rev.1",
      "doc_type": "WI", "version": "1", "file_url": "/document.php?id=...",
      "already_signed": false },
    { "rowid": 1,  "ref": "WI-001", "label": "Forming Procedure",
      "doc_type": "WI", "version": "3", "file_url": "/document.php?id=...",
      "already_signed": true }
  ]
}
```

#### `ajax/ru_save.php`

```
POST { fk_mo, fk_ws, doc_ids: [47, 12] }
→ inserts one llx_doccontrol_ru row per doc_id
→ returns { "saved": 2, "success": true }
```

### 4.3 Kiosk UI — R&U panel

```html
<!-- Appears between QR decode result and the Confirm button -->
<div id="ru-panel" class="ru-panel" style="display:none">
  <h2>Read & Understood</h2>
  <p>Please read all required documents before confirming this operation.</p>
  <ul id="ru-doc-list">
    <!-- JS renders each doc as a list item -->
    <!-- ⚠️ NEW docs: orange badge + [Open] button -->
    <!-- ✅ already signed: green tick, no action needed -->
  </ul>
  <button id="ru-confirm-btn" disabled onclick="ruConfirm()">
    ✔ I have Read and Understood all documents
  </button>
</div>
```

JS logic:
- `[Open]` button → `window.open(file_url)` → marks doc as "opened" in JS state
- `ruConfirm()` active only when all new docs have been opened
- On click → POST to `ru_save.php` → on success: hide panel, show confirm screen

---

## 5. Document Viewer

Documents stored as PDF files (uploaded via `doccontrol` admin → ECM).
Opened via Dolibarr's built-in `document.php?modulepart=doccontrol&file=...`
(same as any other ECM document, no extra viewer needed).

On tablet/kiosk: PDF opens in a new tab (or inline iframe if screen is large enough).

---

## 6. Admin — Link Documents to Products / Workstations

A UI in `doccontrol/admin/ru_links.php` (or inside each document's card):

```
Document: WI-047  "Updated Tool Setup FM4 Rev.1"
──────────────────────────────────────────────────
Applies to:
  [+ Add product]      [+ Add workstation]   [+ Add customer]   [☁ All jobs (global)]

Current links:
  ● Workstation  FM4  ×
  ● Product      FG1090  ×
  ● Product      FG1091  ×
```

Saved to `llx_doccontrol_doc_link`.

---

## 7. trainmatrix integration

When `llx_doccontrol_ru` is written with `scan_context = 1`:
- Check if a `llx_tm_operator_skill` row exists for `(fk_user, skill_ref = d.ref)`
- If yes → update `last_ru_date`, potentially advance skill level
- If no → create with `level = 1` (In training — exposure recorded)

This gives the training matrix **automatic evidence** of operator qualification — no manual entry.

---

## 8. Implementation Phases

### PHASE 1 — Core R&U on scan station 🔲

- [ ] `sql/llx_doccontrol_document.sql` — document registry table
- [ ] `sql/llx_doccontrol_doc_link.sql` — link table (product / WS / customer / global)
- [ ] `sql/llx_doccontrol_ru.sql` — acknowledgement log
- [ ] `ajax/ru_check.php` — query docs for MO + user
- [ ] `ajax/ru_save.php` — write R&U acknowledgement
- [ ] `scan_station.php` — add R&U panel between QR decode and Confirm
- [ ] JS: open-doc tracking, confirm button enable logic
- [ ] `doccontrol/admin/ru_links.php` — link documents to products / workstations

### PHASE 2 — Full doccontrol UI 🔲 *(doccontrol module PHASE 1)*

- [ ] Document card (create / edit / version bump)
- [ ] Upload PDF to ECM
- [ ] Approval workflow (draft → approved → obsolete)
- [ ] R&U history per document (who signed, when, in which MO context)
- [ ] R&U history per operator (all docs signed in a date range)

### PHASE 3 — trainmatrix link 🔲 *(trainmatrix PHASE 2)*

- [ ] Auto-update `llx_tm_operator_skill` on R&U save
- [ ] Training matrix shows "last R&U date" column per document per operator
- [ ] Alert when re-acknowledgement is due (`ru_valid_days` expiry)
- [ ] Report: operators with overdue R&U (for any active document)

---

## 9. Key Questions to Resolve Before Implementation

| # | Question | Impact |
|---|----------|--------|
| Q1 | Where are PDFs stored — ECM or flat file? | `file_path` format in schema |
| Q2 | Is `doccontrol` module scaffold available to reuse, or build from scratch here? | Can pull tables / classes from there |
| Q3 | Should R&U be **blocking** (can't confirm op without it) or **advisory** (shown but skippable)? | UX + button logic |
| Q4 | Who links documents to products — QA manager via admin, or automatic? | Admin UI complexity |
| Q5 | `ru_valid_days` — what standard values? 365 days? Once-only per version? | Default in schema |

---

## 10. Module placement

| Component | Module | File |
|-----------|--------|------|
| DB tables (documents, links, R&U) | `doccontrol` | `sql/` |
| `ru_check.php`, `ru_save.php` | `scanstation` | `ajax/` |
| R&U panel HTML + JS | `scanstation` | `scan_station.php` or `tpl/ru_panel.tpl.php` |
| Admin: link docs to products | `doccontrol` | `admin/ru_links.php` |
| R&U history viewer | `doccontrol` | `ru_history.php` |
| trainmatrix auto-update | `trainmatrix` | hook on `llx_doccontrol_ru` INSERT |
