A sleep(1) szimuláció helyén valódi import: árlista fejrekord -> új gyártók ->
új termékek -> termékfrissítés -> árak -> lezárás.
- szándékosan nincs egyetlen átfogó tranzakció: fázisonként/chunkonként
tranzakciózunk, az atomicitást az adja, hogy az árlista E6-ig draft marad,
tehát félbeszakadáskor sem kerül ki félkész ár a felhasználók felé
- minden fázis idempotencia-jelölője az az artefaktum, amit maga hoz létre
(price_list_id / producer_id / product_id / applied_snapshot / pivot sor),
így a megszakadt futás folytatható, nem kezd elölről
- E4 a termék TÉNYLEGES, írás előtti állapotát menti az applied_snapshot-ba,
ugyanabban a tranzakcióban - ebből áll majd vissza a Visszavonás
- új EXECUTION_FIELD_MAP: a PRODUCT_FIELD_MAP csak a diff-számításhoz kellett,
az import a legacy importPriceList()-tel azonos, bővebb mezőkört ír
- hiányzó opcionális oszlop (pl. Akció) nem írja felül a termék meglévő értékét
- updateStepStatus: az Execution lépés 'failed' státusza execution_failed
fájlstátuszra képződik le, a többi lépésé marad fail
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- PricelistFile::canBeApproved() / hasExecutionStarted(): a jóváhagyás feltételei
egy helyen, hogy a felületi gomb és a service ugyanazt ellenőrizze
- approve(): a státusz MÉG A DISPATCH ELŐTT billen át, különben a queue-latency
alatt a gomb látszana és egy második kattintás párhuzamos importot indítana
- reject(): új 'rejected' lépésstátusz - nem 'failed', mert azt az
updateStepStatus fail fájlstátuszra fordítaná, az elutasítás viszont closed
- a döntés (ki, mikor, milyen indokkal) a file_meta.approval-ba kerül, mert a
BaseAuditable a nevével ellentétben nem naplóz
- Edit gomb szűkítése hasExecutionStarted()-tel három helyen, köztük az
EditPricelistFile::afterSave()-ben, ami a teljes láncot újraindítja
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>