Files
orderPRO/.paul/phases/112-reimport-data-protection/112-01-SUMMARY.md
Jacek Pyziak 782a291210 feat(112): re-import data protection — delta-only re-import + project_generated preservation
Phase 112 / Plan 112-01 complete (v3.6):
- OrderImportRepository::upsertOrderAggregate split into create vs re-import paths
- replaceAddresses/Items/Notes/Shipments/StatusHistory invoked only on first import
- new updateOrderDelta() narrows UPDATE to status_code (cond.), payment_status,
  total_paid, is_canceled_by_buyer, source_updated_at, payload_json, fetched_at
- source-side cancellation override (is_canceled_by_buyer=1 OR pull status_code='anulowane')
- identical-payload no-op guard via normalizePayloadJson()
- fixes case #882: order_items.id stable, project_generated (Phase 97) preserved
- Phase 111 payment.status_changed emit retained without regression

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

9.4 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, duration, started, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established duration started completed
112-reimport-data-protection 01 orders
order-import
re-import
data-protection
payload-guard
allegro
shoppro
pdo
phase provides
111-payment-transition-event payment_transition flag + payment.status_changed emit
phase provides
97-project-generation order_items.project_generated, project_generated_at columns
Delta-only re-import for existing orders (skip replaceAddresses/Items/Notes)
updateOrderDelta() — narrow UPDATE to status_code, payment_status, total_paid, is_canceled_by_buyer, source_updated_at, payload_json, fetched_at
Source-side cancellation propagation (is_canceled_by_buyer=1 OR mapped pull status_code='anulowane' → forces orders.status_code='anulowane')
Identical-payload no-op guard via normalizePayloadJson()
Future re-import scenarios (Allegro + shopPRO cron)
Project generation flow (stable order_items.id)
Any phase relying on local order_items state (project flags, future custom fields)
added patterns
Delta-only update: re-import touches only fields that legitimately change at source
Identical-payload guard: normalize JSON via decode→encode then compare strings; skip UPDATE on equality
created modified
src/Modules/Orders/OrderImportRepository.php
.paul/codebase/architecture.md
.paul/codebase/tech_changelog.md
Skip replaceAddresses/Items/Notes on re-import (created=false) — addresses/items/notes are immutable from source perspective
Cancellation override applies AFTER status preservation block, so is_canceled_by_buyer=1 always wins
Identical-payload guard short-circuits before updateOrderDelta when no transitions detected — fetched_at and updated_at remain unchanged
replacePayments at paymentTransition unchanged — risk of overwriting manual payments (Phase 56) deferred
getCurrentOrderState() — extended SELECT returning status_code + payment_status + payload_json in one query (replaces getCurrentStatusAndPaymentStatus)
normalizePayloadJson() — reusable helper for comparing two JSON representations (array or stored string) under identical encoding flags
~25min 2026-05-07T00:00:00Z 2026-05-07T00:25:00Z

Phase 112 Plan 01: Re-import Data Protection Summary

Re-import istniejacego zamowienia jest teraz delta-only: skip dla pozycji/adresow/notatek, zawezony updateOrderDelta(), propagacja anulowania ze zrodla i identical-payload guard. Bug case #882 (znikajaca flaga "Projekt") przyczynowo naprawiony.

Performance

Metric Value
Duration ~25 min
Started 2026-05-07T00:00:00Z
Completed 2026-05-07T00:25:00Z
Tasks 3 / 3 completed
Files modified 3

Acceptance Criteria Results

Criterion Status Notes
AC-1: Re-import nie kasuje pozycji Pass (code-level) replaceItems przeniesione pod if ($created); manualny test na zywej DB pending (XAMPP offline w sesji)
AC-2: Re-import nie kasuje adresow ani notatek Pass (code-level) replaceAddresses i replaceNotes analogicznie; manualny test pending
AC-3: updateOrder zawezony do delta-only Pass (code-level) Stara updateOrder() usunieta, updateOrderDelta() aktualizuje tylko 7 kolumn + updated_at
AC-4: Pierwszy import bez regresji Pass (code-level) Galaz if ($created) zachowuje pelny przebieg insertOrder + 6 replace*; manualny test importu nowego zamowienia pending
AC-5: Re-import emituje payment.status_changed Pass (code-level) Logika paymentTransition (linie 50-51) + replacePayments przy paymentTransition/statusOverwriteAllowed zachowane; AllegroOrderImportService/ShopproOrdersSyncService nieruszane
AC-6: Re-import propaguje anulowanie Pass (code-level) Override `is_canceled_by_buyer
AC-7: Identyczny payload jest no-op Pass (code-level) Guard via normalizePayloadJson zwraca przed updateOrderDelta gdy nie ma tranzycji; manualny test pending

Uwaga: Wszystkie AC zweryfikowane na poziomie kodu (struktura, kontrola przeplywu, syntax check php -l OK). Manualne testy na zywej bazie odlozone — XAMPP/MySQL nieosiagalne w sesji. Operator powinien przeprowadzic AC-1, AC-3, AC-6, AC-7 po wdrozeniu.

Accomplishments

  • Bug case #882 przyczynowo naprawiony — order_items.id i flagi project_generated/project_generated_at (Phase 97) sa stabilne miedzy re-importami.
  • Phase 111 (payment.status_changed event) dziala bez regresji — emit logiki nieruszany.
  • Re-import nie nadpisuje juz pol zamowienia, ktore moga byc zmienione w orderPRO (zamowienie jest w docelowym narzedziu, nie w zrodle).
  • Zerowe write'y do DB przy cyklicznym imporcie identycznych zamowien (identical-payload guard).
  • Dokumentacja .paul/codebase/architecture.md i .paul/codebase/tech_changelog.md zaktualizowane.

Task Commits

Task Commit Type Description
Task 1: Rozdzielic create vs update w upsertOrderAggregate (uncommitted) feat replace* tylko przy created=true
Task 2: updateOrderDelta + cancellation + payload guard (uncommitted) feat Zawezony UPDATE, override anulowania, identical-payload no-op
Task 3: Architecture + tech_changelog (uncommitted) docs Sekcja Re-import w architecture.md, wpis 2026-05-07

Plan metadata: bedzie commit'owany w ramach transition-phase (feat(112): re-import data protection).

Files Created/Modified

File Change Purpose
src/Modules/Orders/OrderImportRepository.php Modified Delta-only re-import, updateOrderDelta(), getCurrentOrderState(), normalizePayloadJson(), cancellation override
.paul/codebase/architecture.md Modified Sekcja Re-import (Phase 111 + 112) opisuje delta-only flow
.paul/codebase/tech_changelog.md Modified Wpis 2026-05-07 — Phase 112 Plan 01

Decisions Made

Decision Rationale Impact
Skip replaceAddresses/Items/Notes na re-imporcie Pozycje/adresy/notatki sa de facto immutable ze zrodla; orderPRO jest narzedziem zarzadzania — edycja po stronie aplikacji, nie zrodla Stabilne order_items.id i ochrona flag lokalnych (project_generated, przyszle pola)
updateOrderDelta z 7 kolumnami Tylko payment_status/total_paid/is_canceled_by_buyer/source_updated_at/payload_json/fetched_at + status_code (warunkowo) realnie zmieniaja sie miedzy syncami Eliminacja nadpisywania pol typu delivery_price, send_date_*, customer_login
Override anulowania niezalezny od statusOverwriteAllowed Anulowanie ze zrodla musi przejsc nawet gdy status lokalny zostal recznie zmieniony Spojnosc z business logic — anulowane zamowienie nie powinno wisiec w w_realizacji
Identical-payload guard via normalize→compare Tani check eliminujacy niepotrzebne write'y; nie wymaga schema change Zerowa praca dla cyklicznego importu identycznych zamowien
replacePayments przy paymentTransition zostaje Decyzja "nie wiem" od uzytkownika; zachowanie z Phase 111 minimalizuje zmiany Ryzyko nadpisania recznych platnosci (Phase 56) — odlozone jako deferred

Deviations from Plan

Summary

Type Count Impact
Auto-fixed 0 Brak
Scope additions 0 Plan wykonany 1:1
Deferred 2 Manualne testy na DB, ryzyko replacePayments

Total impact: Plan wykonany zgodnie z PLAN.md, bez scope creep. Manualne testy AC pending (XAMPP offline).

Deferred Items

  • Manualne testy AC-1..AC-7 na zywej bazie — wymagaja MySQL/XAMPP online; do przeprowadzenia przez operatora po wdrozeniu. Punkty wyjscia w PLAN.md <verify> blokach Task 1 i Task 2.
  • Backfill #882 — operator wykonuje recznie po wdrozeniu (decyzja uzytkownika z PLAN.md <clarifications>). Sugerowane query: UPDATE order_items SET project_generated=1, project_generated_at=NOW() WHERE order_id=882 AND id IN (...); po identyfikacji pozycji z fizycznie wygenerowanymi PSD.
  • replacePayments przy paymentTransition — DELETE+INSERT moze nadpisac recznie dodane platnosci (Phase 56). Odlozone do oceny po wdrozeniu Phase 112; ewentualny fix w przyszlym planie (np. append po (order_id, source_payment_id) UNIQUE).

Issues Encountered

Issue Resolution
MySQL/XAMPP offline w sesji — brak mozliwosci weryfikacji manualnej AC zweryfikowane na poziomie kodu + php -l; manualne testy odlozone do operatora

Next Phase Readiness

Ready:

  • Re-import delta-only dziala — Phase 111 chain (payment.status_changed → automatyzacja #7) zachowany.
  • order_items.id jest stabilny — skrypt tools/generowanie/_batch_run.sh moze polegac na id miedzy re-importami.
  • Schema DB nieruszane — bez migracji.

Concerns:

  • replacePayments nadal DELETE+INSERT przy paymentTransition — moze wymagac patch w przyszlosci.
  • Manualne AC pending — jezeli ktorys nie przejdzie na zywej bazie, wymagany hotfix.
  • Identical-payload guard zaklada deterministyczny porzadek kluczy w JSON. Jezeli zrodlo (Allegro/shopPRO) reorderuje klucze miedzy syncami, guard nie bedzie blokowac — fail-open, bezpieczny.

Blockers:

  • None (manualne testy nie blokuja transition; sa standardowym deferred follow-up).

Phase: 112-reimport-data-protection, Plan: 01 Completed: 2026-05-07