--- phase: 09-apilo-email-fix plan: 01 subsystem: integrations tags: [apilo, cron, email, retry] requires: - phase: 08-apilo-orders-fix provides: cron job system, Apilo email notification provides: - Infinite retry dla order-related Apilo jobów (30 min interval) - Email notyfikacji z danymi zamówienia (numer, klient, kwota) - Cleanup starych jobów po udanym wysłaniu affects: [] tech-stack: added: [] patterns: - "isOrderRelatedApiloJob() — centralna identyfikacja order jobów Apilo" - "Infinite retry pattern — stały backoff zamiast exponential dla krytycznych jobów" key-files: modified: - autoload/Domain/CronJob/CronJobType.php - autoload/Domain/CronJob/CronJobRepository.php - cron.php key-decisions: - "Order joby Apilo nigdy nie failują trwale — infinite retry co 30 min" - "Email rozróżnia PONAWIANY vs TRWAŁY BŁĄD" - "Po udanym wysłaniu zamówienia czyszczone są stuck joby sync_payment/sync_status" duration: ~15min completed: 2026-03-19 --- # Phase 9 Plan 01: Apilo email fix + infinite retry — Summary **Email notyfikacji Apilo wzbogacony o dane zamówienia (numer, klient, kwota) + order joby ponawiane w nieskończoność co 30 min zamiast permanent failure po 10 próbach.** ## Performance | Metric | Value | |--------|-------| | Duration | ~15 min | | Completed | 2026-03-19 | | Tasks | 2 completed | | Files modified | 4 (+ 1 test file) | | Tests | 820 passed, 2277 assertions | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Email zawiera dane zamówienia | Pass | Numer, klient, data, kwota z pp_shop_orders | | AC-2: Brak order_id nie powoduje błędu | Pass | Graceful handling — pokazuje tylko dane joba | | AC-3: Order joby retry co 30 min w nieskończoność | Pass | isOrderRelatedApiloJob() + stały backoff 1800s | | AC-4: Inne joby zachowują limit prób | Pass | Testy potwierdzają — price_history nadal failuje po max_attempts | | AC-5: Cleanup po udanym wysłaniu | Pass | delete stuck sync_payment/sync_status jobów | ## Accomplishments - Order-related Apilo joby (send_order, sync_payment, sync_status) nigdy nie wpadają w permanent failure — zawsze wracają do pending co 30 min - Email notyfikacji zawiera czytelne dane zamówienia zamiast surowego JSON payload - Temat emaila zawiera numery zamówień dla szybkiej identyfikacji - Email rozróżnia "PONAWIANY CO 30 MIN" vs "TRWAŁY BŁĄD" w zależności od typu joba - Po udanym wysłaniu zamówienia do Apilo czyszczone są stare stuck joby sync_payment/sync_status ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `autoload/Domain/CronJob/CronJobType.php` | Modified | +APILO_ORDER_BACKOFF_SECONDS (1800s), +isOrderRelatedApiloJob() | | `autoload/Domain/CronJob/CronJobRepository.php` | Modified | markFailed() — infinite retry dla order jobów | | `cron.php` | Modified | Email z danymi zamówienia + cleanup po sukcesie | | `tests/Unit/Domain/CronJob/CronJobRepositoryTest.php` | Modified | +2 testy infinite retry, fix mocków z job_type | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Stały backoff 1800s zamiast exponential | Zamówienia muszą trafić do Apilo — przewidywalny interwał ważniejszy niż agresywny retry | Order joby ponawiane regularnie co 30 min | | Email ostrzegawczy zamiast "trwały błąd" | Order joby nigdy nie failują trwale, ale admin musi wiedzieć o problemie | Zmieniony temat i treść emaila | | Cleanup starych jobów po sukcesie | Zapobieganie zaśmiecaniu kolejki stuck jobami sync_payment/sync_status | Delete zamiast cancel — prostsze | ## Deviations from Plan None — plan executed as written. ## Issues Encountered | Issue | Resolution | |-------|------------| | Testy CronJob failowały — mock get() nie zwracał job_type | Dodano job_type do willReturn() w 3 istniejących testach | | test.ps1 nie istnieje | Użyto bezpośrednio `php phpunit.phar` | ## Next Phase Readiness **Ready:** - System retry Apilo jest kompletny i odporny na awarie - Email notyfikacji daje adminowi pełen kontekst do szybkiej reakcji **Concerns:** - None **Blockers:** - None --- *Phase: 09-apilo-email-fix, Plan: 01* *Completed: 2026-03-19*