--- phase: 62-import-reimport-safety plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/Modules/Settings/ShopproOrdersSyncService.php - src/Modules/Orders/OrderImportRepository.php autonomous: true --- ## Goal Naprawa dwóch problemów z re-importem zamówień: 1. Rozróżnienie "Import" vs "Aktualizacja" w activity log dla shopPRO (analogicznie do Allegro) + deduplikacja 2. Ochrona danych lokalnych (płatności, historia statusów, przesyłki) przed nadpisaniem przy re-imporcie — dla obu źródeł (shopPRO i Allegro) ## Purpose Obecnie re-import zamówienia kasuje DELETE+INSERT dane, które mogły zostać dodane lokalnie w orderPRO (ręczna płatność, zmiana statusu, przesyłka). Dodatkowo shopPRO loguje identyczne wpisy "Import zamówienia" przy każdym re-imporcie zamiast rozróżniać import od aktualizacji. ## Output - shopPRO activity log: "Import zamowienia z shopPRO" vs "Zaktualizowano zamowienie z shopPRO (re-import)" + deduplikacja jak Allegro - `upsertOrderAggregate` przy UPDATE pomija replace płatności, historii statusów i przesyłek (chroni dane lokalne) ## Source Files @src/Modules/Settings/ShopproOrdersSyncService.php (linia 205-259: importOneOrder — brak rozróżnienia create/update w activity log) @src/Modules/Settings/AllegroOrderImportService.php (linia 58-103: wzorcowa implementacja — rozróżnia import/aktualizacja + shouldSkipDuplicate) @src/Modules/Orders/OrderImportRepository.php (linia 25-64: upsertOrderAggregate — zawsze DELETE+INSERT na wszystkich relacjach) @src/Modules/Orders/OrdersRepository.php (linia 765-813: shouldSkipDuplicateImportActivity — istniejąca logika deduplikacji) ## AC-1: shopPRO activity log rozróżnia import od aktualizacji ```gherkin Given zamówienie z shopPRO już istnieje w orderPRO When cron re-importuje to zamówienie (source_updated_at się zmieniło) Then w activity log pojawia się "Zaktualizowano zamowienie z shopPRO (re-import)" zamiast "Import zamowienia z shopPRO" ``` ## AC-2: shopPRO activity log deduplikuje identyczne wpisy ```gherkin Given zamówienie z shopPRO zostało właśnie zaimportowane/zaktualizowane When cron próbuje re-importować z tym samym source_updated_at Then nowy wpis w activity log NIE jest tworzony (shouldSkipDuplicateImportActivity) ``` ## AC-3: Re-import nie kasuje lokalnych płatności ```gherkin Given zamówienie ma płatność dodaną ręcznie w orderPRO When cron re-importuje to zamówienie z shopPRO lub Allegro Then ręcznie dodana płatność nie jest usunięta And płatności z importu są nadal poprawnie zapisywane przy pierwszym imporcie ``` ## AC-4: Re-import nie kasuje lokalnej historii statusów ```gherkin Given zamówienie ma zmianę statusu wykonaną w orderPRO When cron re-importuje to zamówienie Then lokalna historia statusów nie jest usunięta And historia statusów z importu jest poprawnie zapisywana przy pierwszym imporcie ``` ## AC-5: Re-import nie kasuje lokalnych przesyłek importowych ```gherkin Given zamówienie ma przesyłki zaimportowane lub utworzone w orderPRO When cron re-importuje to zamówienie Then przesyłki z order_shipments nie są usunięte And przesyłki z importu są poprawnie zapisywane przy pierwszym imporcie ``` Task 1: Activity log shopPRO — rozróżnienie import/aktualizacja + deduplikacja src/Modules/Settings/ShopproOrdersSyncService.php W metodzie `importOneOrder()` (linia 239-246) zmienić blok activity log analogicznie do AllegroOrderImportService (linia 71-94): 1. Po linii 234 (po sprawdzeniu `$save['created']`) dodać logikę: - Ustalić `$wasCreated = !empty($save['created'])` - Ustalić `$summary`: - Jeśli `$wasCreated`: `'Import zamowienia z shopPRO'` - Jeśli nie: `'Zaktualizowano zamowienie z shopPRO (re-import)'` 2. Rozszerzyć `$details` o pola potrzebne do deduplikacji: - `'source_updated_at' => $sourceUpdatedAt` - `'created' => $wasCreated` - `'trigger' => 'orders_sync'` - `'trigger_label' => 'Synchronizacja zamowien'` 3. Owinąć `recordActivity()` w warunek `shouldSkipDuplicateImportActivity()`: ```php if (!$this->orders->shouldSkipDuplicateImportActivity((int) ($save['order_id'] ?? 0), $details)) { $this->orders->recordActivity(...); } ``` Wzorzec: AllegroOrderImportService linia 71-94. Przegląd kodu: shopPRO importOneOrder używa shouldSkipDuplicateImportActivity i rozróżnia summary AC-1 i AC-2 satisfied Task 2: upsertOrderAggregate — pominięcie replace płatności/historii/przesyłek przy UPDATE src/Modules/Orders/OrderImportRepository.php W metodzie `upsertOrderAggregate()` (linia 25-64): 1. Przenieść wywołania `replacePayments`, `replaceShipments` i `replaceStatusHistory` do bloku warunkowego `if ($created)`: ```php $this->replaceAddresses($orderId, $addresses); $this->replaceItems($orderId, $items); $this->replaceNotes($orderId, $notes); if ($created) { $this->replacePayments($orderId, $payments); $this->replaceShipments($orderId, $shipments); $this->replaceStatusHistory($orderId, $statusHistory); } ``` 2. Logika: - Adresy i pozycje (items) — nadpisywane ZAWSZE (dane pochodzą ze źródła, nie są edytowane lokalnie) - Notatki — nadpisywane ZAWSZE (pochodzą ze źródła) - Płatności — tylko przy INSERT (ręczne płatności dodane w orderPRO nie zostaną skasowane) - Przesyłki (order_shipments) — tylko przy INSERT (lokalne przesyłki nie zostaną skasowane) - Historia statusów — tylko przy INSERT (lokalne zmiany statusów nie zostaną skasowane) Ta zmiana dotyczy OBIE źródeł (shopPRO i Allegro) bo obie korzystają z tego samego repozytorium. Przegląd kodu: replacePayments, replaceShipments, replaceStatusHistory wywoływane tylko gdy $created === true AC-3, AC-4 i AC-5 satisfied ## DO NOT CHANGE - AllegroOrderImportService.php — Allegro już ma poprawną logikę activity log, nie modyfikować - OrdersRepository.php — shouldSkipDuplicateImportActivity() działa poprawnie, reuse bez zmian - Logika kursora (ShopproOrderMapper, ShopproOrderSyncStateRepository) — nie modyfikować - Tabele DB — brak migracji ## SCOPE LIMITS - Brak kolumny `origin` w tabelach (to byłby etap 2, poza zakresem) - Nie zmieniamy logiki replace dla adresów, pozycji ani notatek (te dane pochodzą wyłącznie ze źródła) - Nie dodajemy nowego merge/diff — po prostu pomijamy replace przy update Before declaring plan complete: - [ ] shopPRO importOneOrder rozróżnia "Import" vs "Zaktualizowano (re-import)" w summary - [ ] shopPRO importOneOrder używa shouldSkipDuplicateImportActivity - [ ] upsertOrderAggregate: replacePayments/replaceShipments/replaceStatusHistory wywołane tylko przy $created - [ ] upsertOrderAggregate: replaceAddresses/replaceItems/replaceNotes wywołane zawsze (bez zmian) - [ ] Brak zmian w AllegroOrderImportService - Activity log shopPRO rozróżnia import od aktualizacji - Duplikaty activity log eliminowane przez shouldSkipDuplicateImportActivity - Re-import nie kasuje lokalnych płatności, przesyłek ani historii statusów - Pierwsze importowanie zapisuje wszystkie dane normalnie - Brak regresji w imporcie Allegro After completion, create `.paul/phases/62-import-reimport-safety/62-01-SUMMARY.md`