# Info Board — Daily Performance Table

## Overview

The Daily Performance table shows production KPIs per workstation (WS) per day
for a configurable date range (default: last 30 days → most recent 5–7 days displayed).

Eligible workstations: `FM*` (Forming), `CNC*`, `LASER*` (Trimming).
Other WS refs are excluded.

---

## Columns

### P — Planned quantity

**What it shows:** How many pieces were planned to be produced on that day.

**Source:** `planning_schedule.planned_hours × product_extrafields.qty_per_hour_*`

- FM workstations use `qty_per_hour_form` extrafield on the product
- CNC / LASER workstations use `qty_per_hour_trim` extrafield
- If the product has no extrafield set → P = 0 → shown as `—`

**Table:** `llx_planning_schedule` JOIN `llx_mrp_mo` JOIN `llx_product_extrafields`

---

### A — Actual quantity

**What it shows:** How many pieces were actually produced (confirmed by operators via ScanStation).

**Source:** Sum of `mrp_mo_optracking.qty_delta` for that WS + day.

**Table:** `llx_mrp_mo_optracking` (no `entity` column — filtered via JOIN on `llx_mrp_mo`)

---

### % — Performance percentage

**What it shows:** `A / P × 100` — how close actual was to plan.

**Formula:** `round($actual / $planned * 100)`

**Color coding:**
- 🟢 Green: ≥ 90%
- 🟡 Amber: 60–89%
- 🔴 Red: < 60%
- `—` if P = 0 (nothing planned)

---

### D — Downtime

**What it shows:** Total downtime minutes recorded for that WS on that day.

**Source:** Sum of `planning_downtime.duration_minutes`.

**Display:** Raw minutes, e.g. `45m`. Shown as `—` if no downtime recorded.

**Table:** `llx_planning_downtime`

---

### S — Scrap quantity

**What it shows:** Number of scrapped pieces **confirmed and booked** to `llx_scrap`.

**Source:** Sum of `scrap.qty` grouped by `fk_ws` + `DATE(scrap_date)`.

**Table:** `llx_scrap`

> ⚠️ **Known bug** — see `BUG_daily_performance_scrap.md`
>
> Scrap logged via ScanStation lands in `scanstation_log` (pending) first.
> It only reaches `llx_scrap` after confirmation in `scrap_confirmation.php`.
> Until confirmed, S = `—` even if pieces were scrapped that day.

---

### Q — Quality percentage

**What it shows:** What fraction of actual output was good (not scrapped).

**Formula:** `(A − S) / A × 100`

**Color coding:**
- 🟢 Green: ≥ 90%
- 🟡 Amber: 60–89%
- 🔴 Red: < 60%
- `—` if A = 0

> ⚠️ Subject to same lag as S — will show 100% until scrap is confirmed.

---

## Sat / Sun visibility rules

Weekend columns are shown only when **all three conditions** are met:

| # | Condition | Source |
|---|-----------|--------|
| A | At least one eligible WS has `use_sat=1` / `use_sun=1` | `llx_planning_ws_config` |
| C | Effective capacity > 0 on that specific day (override takes precedence over default `hrs_sat`/`hrs_sun`) | `llx_planning_capacity_override` → `llx_planning_ws_config` |
| B | At least one actual activity exists: A > 0, D > 0, or S > 0 (direct DB query) | `llx_mrp_mo_optracking`, `llx_planning_downtime`, `llx_scrap` |

If a Sunday is planned but then capacity is overridden to `0h` → condition C fails → column hidden automatically.

---

## Date range

- Default filter: last 30 days (from URL params `date_from` / `date_to`)
- `perfDays` is capped at **7 most recent** eligible days (Mon–Fri + optional Sat/Sun)
- Days are always shown in ascending order (oldest left, newest right)
