Commit Graph

4 Commits

Author SHA1 Message Date
979aae426b perf(db): batch the good-parts N+1 + cache the press/reason reference reads
- _good_parts_map: collapse the per-press 3-query loop (3xN) into 3 grouped
  queries across all presses; semantics preserved (Joborder JSON/substring
  matching, per-press scoping, whole-map degrade-to-{} on error).
- _press_list + /reasons: served from the kernel cached_select() TTL cache.

Part of the gateway connection-pool-saturation fix
(see fastAPI/agent_docs/db-pool-relief.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 12:06:49 +02:00
ac63988e6d feat(rejects): attribute Ausschuss to the cart's cycle interval (median cycle)
The station's /reject now uses the booked-against cart's stored cycle interval
(temper_tracking ttCycleFirstId/LastId/Count, migration 009): body.ttId — until
now only logged — resolves the interval's MEDIAN cycle for rejCycleID/rejToolNo/
rejCycletimeAct/rejArticleID instead of the press's latest cycle (MAX(id)), and
writes rejTtId (audit link). Self-contained probes/resolver (no fastpress import);
falls back to MAX(id) pre-009 / when no ttId or interval. Returns CY.<ttId>:<a>-<b>.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 08:57:43 +02:00
83d86dfe90 feat: wire live data + fail-safe reject booking
Backend (api/routes.py) — replace sample data with live reads/writes:
- GET /overview reads production.temper_tracking (done carts, plant-scoped,
  windowed, newest-first, one row per ttId); each order's 5-station belt is
  derived from planned timestamps vs NOW(), faithful to fastpress
  _temper_aggregates_all. sample:false.
- GET /reasons reads settings.reject_reasons (active=1).
- POST /reject WRITES production.rejects keyed by the ORDER (rejOrdernumber +
  rejPress, press taken from the body) — an un-scoped port of PressV
  send_reject; no rejTtId column needed (ttId is context-only). Failures
  return HTTP 200 + {success:false}, NOT 4xx/5xx.
Belt: the single pre-oven buffer (Wagenzeit) shows under Unterwegs; Wagen=0.

Frontend — never report an unconfirmed booking as success:
- store.submitReject returns the gateway's own {success} and reports failure on
  a transport error instead of faking success.
- store.refresh keeps the last REAL data on a transient poll error (only a cold
  start falls back to demo carts) so a live terminal never shows fabricated carts.
- the failure toast is now red (was always green).

Verified live against cdbserv15 (12 carts, 25 reasons, INSERT round-trip).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 13:46:56 +02:00
c340aef2c3 feat: scaffold Ausschuss-Station reject-booking page-module (temper_rejects)
Vue 3 + Vite 8 + TS + PrimeVue 4 (Nora/Industrial) + Pinia + vue-i18n SPA, served
by the SPRO gateway as a static page-module under /module/temper_rejects. A central,
login-free reject-booking terminal for all presses' tempered carts.

- Implements the LOCKED design (memory: ausschuss-station): per-ttId list (newest
  first), left press checkbox filter (default all, greyed when no carts, hit-count
  badge), style-C 5-station temper belt per entry (badges + animated conveyor),
  12h/1T/7T/14T/30T window, touch density. Booking dialog = PrimeVue Dialog +
  InputNumber + reason Select. Colours match PressV + Ausschuss #C4162A.
- Python page-module wrapper: register(app) mounts committed dist/ + a no-auth API
  (GET /overview, GET /reasons, POST /reject). _db.py exposes run_select_query +
  transaction() for the future INSERT.
- Backend returns SAMPLE data and POST /reject echoes success WITHOUT writing;
  frontend falls back to bundled sample so `npm run dev` is fully demoable offline.
  TODOs point at the real temper_tracking reads + the rejects INSERT (needs a DBA
  rejTtId column) + the login-free-write security open question.
- Rich README bakes in the design, contract, wiring, open questions + Grafana embed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:44:22 +02:00