--- phase: 60-order-status-aged-event plan: 01 subsystem: automation tags: [automation, cron, order-status, time-based, aged] requires: - phase: 59-order-status-automation-event provides: order_status condition type, evaluateOrderStatusCondition provides: - order.status_aged cron-based automation event - days_in_status condition type - OrderStatusAgedService (cron scanner) - OrderStatusAgedHandler (cron handler) affects: [automation workflows, cron infrastructure] tech-stack: added: [] patterns: [cron-based automation event scanning order_status_history] key-files: created: - src/Modules/Automation/OrderStatusAgedService.php - src/Modules/Cron/OrderStatusAgedHandler.php - database/migrations/20260331_000074_seed_order_status_aged_cron.sql modified: - src/Modules/Automation/AutomationController.php - src/Modules/Automation/AutomationService.php - src/Modules/Cron/CronHandlerFactory.php - resources/views/automation/form.php - resources/views/automation/index.php - public/assets/js/modules/automation-form.js key-decisions: - "Skanowanie przez JOIN order_status_history z HAVING MAX(changed_at) — precyzyjne wykrywanie czasu w statusie" - "Limit 100 zamowien na regule na cykl — bezpieczenstwo przed przeciazeniem" - "Naturalna deduplikacja — po zmianie statusu zamowienie nie spelnia warunku w nastepnym cyklu" - "Cron co 1 godzine (3600s) — kompromis miedzy reaktywnoscia a obciazeniem" patterns-established: - "Cron-based automation event: OrderStatusAgedService skanuje DB i emituje event przez AutomationService.trigger()" - "days_in_status condition: pole numeryczne, ewaluacja >= (nie ==)" duration: 15min started: 2026-03-31T00:10:00Z completed: 2026-03-31T00:25:00Z --- # Phase 60 Plan 01: Order Status Aged Event Summary **Zdarzenie automatyzacji `order.status_aged` wyzwalane cronem — skanuje zamowienia w danym statusie od X dni i uruchamia reguly** ## Performance | Metric | Value | |--------|-------| | Duration | ~15min | | Tasks | 3 completed | | Files created | 3 | | Files modified | 6 | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Event order.status_aged dostepny w formularzu | Pass | Opcja "Minelo X dni od zmiany statusu" w dropdown | | AC-2: Warunek days_in_status z polem numerycznym | Pass | Input number min=1, placeholder "Liczba dni" | | AC-3: Warunek order_status dziala z tym zdarzeniem | Pass | Reuse warunku z Phase 59, oba warunki zapisuja sie poprawnie | | AC-4: Cron handler skanuje i wyzwala event | Pass | OrderStatusAgedService skanuje order_status_history, trigger z kontekstem | | AC-5: Deduplikacja naturalna | Pass | Po zmianie statusu zamowienie nie spelnia warunku w nastepnym cyklu | ## Accomplishments - Cron-based event `order.status_aged` — pierwsze zdarzenie czasowe w silniku automatyzacji - OrderStatusAgedService skanuje zamowienia po `order_status_history.changed_at` z precyzyjnym query HAVING - Warunek `days_in_status` z polem numerycznym i ewaluacja >= (zamowienie w statusie od 7 dni spelnia warunek "5 dni") - Handler zarejestrowany w CronHandlerFactory, migracja seeduje cron schedule co 1 godzine ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `database/migrations/20260331_000074_seed_order_status_aged_cron.sql` | Created | Seed cron schedule: job_type=order_status_aged, interval=3600s | | `src/Modules/Automation/OrderStatusAgedService.php` | Created | Serwis skanowania: findActiveByEvent, extractStatusCodes/Days, findAgedOrders, trigger | | `src/Modules/Cron/OrderStatusAgedHandler.php` | Created | Cron handler delegujacy do OrderStatusAgedService.scan() | | `src/Modules/Automation/AutomationController.php` | Modified | ALLOWED_EVENTS + order.status_aged, ALLOWED_CONDITION_TYPES + days_in_status, parseConditionValue + days_in_status | | `src/Modules/Automation/AutomationService.php` | Modified | evaluateDaysInStatusCondition() — porownanie context.days_in_status >= value.days | | `src/Modules/Cron/CronHandlerFactory.php` | Modified | Import OrderStatusAgedService, rejestracja handlera order_status_aged | | `resources/views/automation/form.php` | Modified | Etykieta zdarzenia, opcja warunku days_in_status, pole numeryczne | | `resources/views/automation/index.php` | Modified | Etykieta order.status_aged | | `public/assets/js/modules/automation-form.js` | Modified | buildDaysInStatusInput(), opcja w addCondition/onChange | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Query HAVING MAX(changed_at) vs kolumna na orders | Precyzyjne — bazuje na faktycznej dacie zmiany z historii, nie wymaga nowej kolumny | Brak zmian schematu tabeli orders | | Limit 100 zamowien na regule | Bezpieczenstwo — zapobiega przeciazeniu przy wielu zamowieniach w starym statusie | Moze wymagac podwyzszenia przy duzej skali | | Cron co 1 godzine | Kompromis — wystarczajaco czeste dla regul dniowych, nie przeciaza bazy | Konfigurowalny z panelu cron schedules | | Ewaluacja >= (nie ==) | Zamowienie "8 dni w statusie" spelnia regule "7 dni" — intuicyjne | Brak false negatives | ## Deviations from Plan None — plan executed exactly as written. ## Issues Encountered None ## Next Phase Readiness **Ready:** - Pelny zestaw eventow: receipt.created, shipment.created, shipment.status_changed, payment.status_changed, order.status_changed, order.status_aged - Pelny zestaw warunkow: integration, shipment_status, payment_status, order_status, days_in_status - Pierwszy cron-based event — wzorzec do reuzytku dla przyszlych eventow czasowych **Concerns:** - None **Blockers:** - None --- *Phase: 60-order-status-aged-event, Plan: 01* *Completed: 2026-03-31*