---
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*
