# Downtime Feature — Design Notes

**Data:** 2026-04-03  
**Aktualizacja:** 2026-04-04  
**Status:** ✅ Implementacja zakończona.

---

## Kontekst

Downtime = przestój maszyny/stanowiska wpływający na efektywną pojemność produkcyjną i harmonogram MO.

### Rodzaje downtime

| Typ | Przykłady | Charakter |
|---|---|---|
| **Planowany** | TPM, First Off, Changeover, Break, Cleaning | Znany z góry, wliczony w harmonogram |
| **Nieplanowany** | Awaria, brak materiału, problem jakościowy | Nieprzewidziany, wymaga raportowania na bieżąco |

> Kategorie **TPM / First Off / Changeover / Break / Cleaning** traktowane są jako **planowany downtime** — planner może je uwzględnić z wyprzedzeniem przy układaniu harmonogramu.

---

## Aktualna architektura (zdecydowana)

### Kto dodaje downtime

**Operator** — z poziomu modułu **ScanStation** (dedykowany formularz: kategoria + czas trwania + notatka).

Planner **nie dodaje i nie edytuje** downtime z poziomu Planning.

### Schemat działania

```
Operator (ScanStation)
  └─ zgłasza downtime → llx_planning_downtime

Planner (Planning)
  └─ widzi w siatce informację o downtimie (read-only)
  └─ calc_engine odejmuje downtime od pojemności dnia
```

---

## Moduł Planning — rola (read-only)

- Wiersz "Downtime" w siatce **domyślnie ukryty** (hidden)
- W navbarze / pasku nad siatką — **checkbox "Show Downtime"** — zaznaczenie odkrywa wiersz
- Wiersz jest wyłącznie do odczytu (kliknięcie w komórkę nie otwiera formularza)
- Każda komórka pokazuje sumę minut downtime dla danego WS/dnia, tooltip z kategorią i notatką
- Link do pełnej listy: `downtime_list.php` pozostaje
- `calc_engine` nadal automatycznie odejmuje minuty downtime od pojemności dnia (niezależnie od widoczności wiersza)

---

## Tabela DB

```sql
llx_planning_downtime (
    rowid            INT UNSIGNED AUTO_INCREMENT,
    fk_ws            INT UNSIGNED NOT NULL,
    downtime_date    DATE NOT NULL,
    duration_minutes SMALLINT UNSIGNED NOT NULL DEFAULT 0,
    category         VARCHAR(100) NOT NULL DEFAULT '',
    note             VARCHAR(255) NULL,
    fk_user_creat    INT UNSIGNED NULL,
    entity           INT NOT NULL DEFAULT 1,
    tms              TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
```

Tabela należy do modułu Planning (przestrzeń nazw `llx_planning_*`), ale **zapis** odbywa się wyłącznie przez ScanStation.

---

## Podział odpowiedzialności

| Akcja | Moduł | Kto |
|---|---|---|
| Dodawanie / edycja / usuwanie downtime | ScanStation | Operator |
| Podgląd downtime w siatce | Planning | Planner |
| Odejmowanie downtime od pojemności | Planning (calc_engine) | Automatycznie |
| Lista wszystkich downtime | Planning (downtime_list.php) | Planner |

---

## Status implementacji

- [x] Tabela `llx_planning_downtime` — schemat gotowy (`sql/llx_planning_downtime.sql`)
- [x] Formularz dodawania w ScanStation (panel ⏱️ DOWNTIME, edit/delete w pasku)
- [x] Pasek "Shift downtime" w ScanStation z listą wpisów zmiany (`getShiftDate()` — świadomy godziny startu zmiany)
- [x] `SS_SHIFT_START` exportowany z `scan_station.php`, odświeżany po zmianie maszyny (`get_ws_mos`)
- [x] Planning — wiersz Downtime (read-only, domyślnie ukryty, odkrywany checkboxem **DT** w navbarze)
- [x] Planning — badge `Xm` w komórce MO z pływającym tooltip (kategoria + czas per wpis)
- [x] Planning — `calc_engine` (`ajax/calc.php`) odejmuje downtime od pojemności dnia
- [x] Planning — `downtime_list.php` (lista z filtrami WS + zakres dat, subtotale per dzień)

## Commity

| Hash | Opis |
|---|---|
| `94bf128` | Scrap reason dropdown z tabeli `llx_scrap_reason` |
| `28cb21c` | `SS_SHIFT_START` + `getShiftDate()` — świadoma data zmiany |
| `b6aad6e` | Fix: brakujący `}` w `get_ws_mos` (PHP parse error) |
| `e646708` | Planning: calc_engine + wiersz DT + lista downtime |
| `1ddd7a8` | Badge `Xm` na komórce MO (tylko gdy `$ph > 0`) |
| `a295801` | Tooltip na całej komórce (`data-dt-tip` na `<td>`) |

