Files
orderPRO/.paul/phases/111-payment-transition-event/111-01-SUMMARY.md
Jacek Pyziak 5cf531d718 feat(111): payment transition event for Allegro+shopPRO re-import
Re-import zamowienia wykrywa tranzycje payment_status 0/1->2 i emituje
payment.status_changed, dzieki czemu chain reguly automatyzacji #7 zmienia
status na w_realizacji.

- OrderImportRepository: rozdzielenie paymentTransition (event 0/1->2) i
  statusOverwriteAllowed (preservacja status_code z Phase 62)
- AllegroOrderImportService + ShopproOrdersSyncService: emit
  payment.status_changed na re-imporcie (gate !wasCreated && wasPaymentTransition)
- bin/backfill_payment_transition_111.php: jednorazowy CLI dla zamowien
  payment_status=2 && status_code='nieoplacone' (Allegro + shopPRO)
- Naprawa luki znalezionej w analizie zamowienia #864

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:35:14 +02:00

152 lines
8.7 KiB
Markdown

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