--- phase: 111-payment-transition-event plan: 01 subsystem: automation tags: [allegro, shoppro, payment-status, automation, import] requires: - phase: 98-order-imported-first-only provides: gate $wasCreated dla order.imported (commit 7eefd1a) - phase: 62-import-reimport-safety provides: logika preservacji status_code przy re-imporcie provides: - detekcja payment_transition oparta o porownanie payment_status (0/1 -> 2) - emit payment.status_changed w Allegro/shopPRO re-imporcie - bin/backfill_payment_transition_111.php (idempotent CLI) affects: [Allegro re-import flow, ShopPRO re-import flow, Automation rule chain] tech-stack: added: [] patterns: - "Rozdzielenie paymentTransition (event) i statusOverwriteAllowed (status_code preservation) jako osobnych decyzji w upsertOrderAggregate" key-files: created: - bin/backfill_payment_transition_111.php modified: - src/Modules/Orders/OrderImportRepository.php - src/Modules/Settings/AllegroOrderImportService.php - src/Modules/Settings/ShopproOrdersSyncService.php - .paul/codebase/architecture.md - .paul/codebase/tech_changelog.md key-decisions: - "paymentTransition oparte o porownanie payment_status (0/1 -> 2), nie status_code" - "Logika preservacji status_code (Phase 62) wydzielona jako $statusOverwriteAllowed — niezalezna decyzja" - "Reuse istniejacej reguly automatyzacji #7 (bez warunku integration_id) zamiast tworzenia osobnej reguly per integracja" - "Backfill idempotentny przez kryterium status_code='nieoplacone' AND payment_status=2 — po updateOrderStatus zamowienie nie spelnia warunku" patterns-established: - "Re-import emituje payment.status_changed gdy repo zwraca payment_transition i !$wasCreated — wzor dla potencjalnych przyszlych integracji" duration: ~30min started: 2026-05-05T13:00:00Z completed: 2026-05-05T13:30:00Z --- # Phase 111 Plan 01: Payment Transition Event Summary **Re-import zamowienia (Allegro + shopPRO) wykrywa tranzycje payment_status 0/1 -> 2 i emituje `payment.status_changed`, dzieki czemu chain reguly automatyzacji #7 zmienia status na `w_realizacji` dla zamowien zaimportowanych przed potwierdzeniem platnosci.** ## Performance | Metric | Value | |--------|-------| | Duration | ~30 min | | Started | 2026-05-05T13:00:00Z | | Completed | 2026-05-05T13:30:00Z | | Tasks | 4 completed | | Files modified | 5 (1 nowy + 4 zmienione) | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Repo wykrywa tranzycje 0/1 → 2 | Pass (code) | Logika rozszerzona w `OrderImportRepository::upsertOrderAggregate`: `paymentTransition = in_array($oldPaymentStatus, [0, 1], true) && $newPaymentStatus === 2`. `statusOverwriteAllowed` zachowuje semantyke Phase 62. Lint OK. Pelny runtime test wymaga zamowienia testowego pre-payment — operator zweryfikuje po deploy. | | AC-2: Allegro + shopPRO emituje payment.status_changed | Pass (code) | Oba serwisy emituja event tylko gdy `!$wasCreated && $wasPaymentTransition`. Lint OK. Runtime weryfikacja jak w AC-1 — wymaga zamowienia testowego. | | AC-3: Backfill naprawia historyczne dane | Pass (preview) | Skrypt `bin/backfill_payment_transition_111.php` zgodny ze wzorcem Phase 98 (flagi `--dry-run`/`--use-remote`, idempotentny). SQL preview na produkcji znalazl **0 kandydatow** — zamowienie #864 jest juz `wyslane`, brak innych analogicznych. Skrypt zostaje jako safety net. | | AC-4: Brak regresji w istniejacym flow | Pass | `order.imported` gate `$wasCreated` nietknięty; nowy emit pod osobnym warunkiem `!$wasCreated && $wasPaymentTransition` — pierwszy import ma `$wasPaymentTransition=false` z definicji (created=true → blok detekcji nieuruchomiony). | ## Accomplishments - **OrderImportRepository** rozdzielil dwie semantyki: `paymentTransition` (eventowa, oparta o porownanie payment_status) i `statusOverwriteAllowed` (preservacja status_code z Phase 62) — dotychczas mieszane w jednej fladze - **AllegroOrderImportService + ShopproOrdersSyncService** spojnie emituja `payment.status_changed` na re-import, bez ruszania gate'u `order.imported` (commit 7eefd1a Phase 98) - **Backfill CLI** wzorem Phase 98 — gotowy do uruchomienia po deploy, obecnie no-op (luki historyczne brak) - **Reuse reguly #7** zamiast tworzenia osobnej reguly per integracja — chain automatyzacji obejmuje teraz Allegro automatycznie ## Task Commits | Task | Commit | Type | Description | |------|--------|------|-------------| | Task 1: OrderImportRepository payment_transition | (uncommitted) | feat | Rozszerzenie detekcji 0/1→2 + getCurrentStatusAndPaymentStatus | | Task 2: Allegro+shopPRO emit payment.status_changed | (uncommitted) | feat | Konsumpcja payment_transition flag, emit do AutomationService | | Task 3: Backfill CLI | (uncommitted) | feat | bin/backfill_payment_transition_111.php | | Task 4: Docs update | (uncommitted) | docs | architecture.md + tech_changelog.md | **Note:** Wszystkie zmiany wykonane w trybie inline jako jeden working tree state. Atomowe commity zostana wykonane przez transition-phase. ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `src/Modules/Orders/OrderImportRepository.php` | Modified | `upsertOrderAggregate`: rozdzielenie paymentTransition (0/1→2) i statusOverwriteAllowed; nowa metoda `getCurrentStatusAndPaymentStatus` | | `src/Modules/Settings/AllegroOrderImportService.php` | Modified | Emit `payment.status_changed` na payment_transition w re-imporcie | | `src/Modules/Settings/ShopproOrdersSyncService.php` | Modified | Emit `payment.status_changed` analogicznie do Allegro | | `bin/backfill_payment_transition_111.php` | Created | Jednorazowy CLI dla zamowien `payment_status=2 && status_code='nieoplacone'` | | `.paul/codebase/architecture.md` | Modified | Sekcja Order Lifecycle: pkt 2 Re-import (Phase 111) | | `.paul/codebase/tech_changelog.md` | Modified | Wpis `2026-05-05 - Phase 111` | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | `paymentTransition` oparte o porownanie payment_status (nie status_code) | Restrykcyjna definicja "0/1 → 2" wybrana przez uzytkownika — lapie wszystkie tranzycje platnosci niezaleznie od stanu status_code | Bedzie emitowac event tez dla zamowien w nietypowych stanach status (np. po recznym ustawieniu) | | Rozdzielenie `statusOverwriteAllowed` od `paymentTransition` | Phase 62 logika preservacji status_code musiala zostac zachowana — laczenie obu w jednej fladze rozszerzaloby zakres nadpisywania status_code | Zachowane zachowanie shopPRO (replacePayments przy paymentTransition) i Phase 62 (preservacja przy ogolnym re-imporcie) | | Reuse reguly #7 (bez warunku integration_id) | Regula juz istnieje, dziala dla shopPRO; brak integration_id oznacza universal coverage; chain idempotentny przez OrdersRepository::updateOrderStatus | Nie tworzymy duplikatu reguly per integracja, mniej rzeczy do utrzymania | | Backfill idempotentny przez `status_code='nieoplacone' AND payment_status=2` | Po updateOrderStatus → status_code='w_realizacji', warunek SELECT przestaje pasowac | Bezpieczne wielokrotne uruchomienie | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | Auto-fixed | 0 | — | | Scope additions | 0 | — | | Deferred | 0 | — | **Total impact:** Plan wykonany dokladnie wg specyfikacji. Brak odchylen. ### Auto-fixed Issues None — plan executed exactly as written. ### Deferred Items None — wszystkie 4 zadania ukonczone w zakresie planu. ## Issues Encountered | Issue | Resolution | |-------|------------| | Lokalny runtime backfillu niemozliwy (brak `vendor/`) | Zweryfikowano przez `php -l` (lint) + bezposredni SQL preview na DB — 0 kandydatow potwierdzonych. Operator uruchomi skrypt na serwerze po deploy (no-op spodziewany). | | Pelny test E2E `payment.status_changed` chain wymaga zamowienia testowego Allegro pre-payment | Udokumentowane w SUMMARY jako "operator weryfikuje po deploy". Code path zweryfikowany staticznie (lint + przeglad logiki + idempotencja przez kryterium). | ## Next Phase Readiness **Ready:** - Hotfix gotowy do deploy (3 zmienione pliki PHP + 1 nowy CLI + 2 docs) - Backfill jako safety net (no-op na obecnym stanie DB) - Architektura udokumentowana w `.paul/codebase/architecture.md` **Concerns:** - Pelny test E2E wymaga zamowienia testowego Allegro w stanie pre-payment + wymuszenia re-importu po confirm-paid. Operator powinien zweryfikowac na pierwszym realnym przypadku po deploy. - Idempotencja przy podwojnym pokryciu shopPRO (osobny `ShopproPaymentStatusSyncService` tez emituje `payment.status_changed`) — w praktyce regula 7 jest idempotentna (`update_order_status` na juz-w_realizacji nie tworzy nowej historii). **Blockers:** - None --- *Phase: 111-payment-transition-event, Plan: 01* *Completed: 2026-05-05*