fix(02-bug-fixes): fix 3 known bugs from CONCERNS.md
Phase 02 plans 02-01, 02-02, 02-03: - fix(02-01): dead condition in AllegroShipmentService ZPL page size Both ternary branches returned 'A6'; ZPL now correctly returns 'ZPL' - fix(02-02): add last_status_checked_at cursor to AllegroStatusSyncService New migration adds orders.last_status_checked_at DATETIME NULL with composite index (source, source_updated_at). findOrdersNeedingStatusSync() filters by cursor; markOrderStatusChecked() records timestamp on success. - fix(02-03): replace AllegroOrderSyncStateRepository in ShopproOrdersSyncService New ShopproOrderSyncStateRepository (same table, correct class name). Application.php wires correct repository to correct service. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
220
.paul/phases/02-bug-fixes/02-03-PLAN.md
Normal file
220
.paul/phases/02-bug-fixes/02-03-PLAN.md
Normal file
@@ -0,0 +1,220 @@
|
||||
---
|
||||
phase: 02-bug-fixes
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- src/Modules/Settings/ShopproOrderSyncStateRepository.php
|
||||
- src/Modules/Settings/ShopproOrdersSyncService.php
|
||||
- src/Core/Application.php
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Cel
|
||||
Wydzielenie dedykowanego `ShopproOrderSyncStateRepository` i zastąpienie nim błędnego wstrzyknięcia `AllegroOrderSyncStateRepository` w `ShopproOrdersSyncService`.
|
||||
|
||||
## Uzasadnienie
|
||||
`ShopproOrdersSyncService` zarządza kursorem synchronizacji shopPRO przez klasę nazwianą `AllegroOrderSyncStateRepository`. To błędna zależność — stan shopPRO jest zapisywany przez klasę Allegro. Przy dodaniu kolejnych integracji shopPRO problem się zwielokrotnia. Docelowo każda integracja ma własne, poprawnie nazwane repozytorium.
|
||||
|
||||
## Wyjście
|
||||
- Nowy `ShopproOrderSyncStateRepository` (ta sama tabela `integration_order_sync_state`, ta sama logika `integration_id`-scoped)
|
||||
- `ShopproOrdersSyncService` wstrzykuje `ShopproOrderSyncStateRepository` zamiast `AllegroOrderSyncStateRepository`
|
||||
- `Application.php` tworzy i przekazuje `ShopproOrderSyncStateRepository` do serwisu
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Kontekst projektu
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Pliki źródłowe
|
||||
@src/Modules/Settings/AllegroOrderSyncStateRepository.php
|
||||
@src/Modules/Settings/ShopproOrdersSyncService.php
|
||||
@src/Core/Application.php
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Wymagane skille (z SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priorytet | Kiedy wywołać | Załadowany? |
|
||||
|-------|-----------|---------------|-------------|
|
||||
| /code-review | required | Po implementacji, przed UNIFY | ○ |
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
|
||||
**BLOKUJĄCE:** Wymagane skille MUSZĄ być wywołane przed UNIFY.
|
||||
|
||||
## Checklist
|
||||
- [ ] /code-review wywołany po implementacji
|
||||
- [ ] sonar-scanner uruchomiony, wyniki sprawdzone i zaktualizowane w `DOCS/todo.md`
|
||||
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: `ShopproOrdersSyncService` nie zależy od `AllegroOrderSyncStateRepository`
|
||||
```gherkin
|
||||
Given plik `ShopproOrdersSyncService.php`
|
||||
When sprawdzam import i konstruktor
|
||||
Then nie ma żadnego odwołania do `AllegroOrderSyncStateRepository` — ani importu, ani typehinta
|
||||
```
|
||||
|
||||
## AC-2: `ShopproOrdersSyncService` korzysta z `ShopproOrderSyncStateRepository`
|
||||
```gherkin
|
||||
Given plik `ShopproOrdersSyncService.php`
|
||||
When sprawdzam konstruktor i metody wywołujące state
|
||||
Then zmienna `$syncState` ma typ `ShopproOrderSyncStateRepository` i jest poprawnie wstrzyknięta
|
||||
```
|
||||
|
||||
## AC-3: `ShopproOrderSyncStateRepository` ma identyczny kontrakt publiczny co `AllegroOrderSyncStateRepository`
|
||||
```gherkin
|
||||
Given nowy plik `ShopproOrderSyncStateRepository.php`
|
||||
When sprawdzam publiczne metody
|
||||
Then istnieją: `getState(int $integrationId)`, `markRunStarted(int, DateTimeImmutable)`, `markRunSuccess(int, DateTimeImmutable, ?string, ?string)`, `markRunFailed(int, DateTimeImmutable, string)`
|
||||
```
|
||||
|
||||
## AC-4: `Application.php` wstrzykuje `ShopproOrderSyncStateRepository`
|
||||
```gherkin
|
||||
Given plik `Application.php`, linia tworzenia `ShopproOrdersSyncService`
|
||||
When sprawdzam przekazywane zależności
|
||||
Then zamiast `new AllegroOrderSyncStateRepository($this->db)` jest `new ShopproOrderSyncStateRepository($this->db)`
|
||||
```
|
||||
|
||||
## AC-5: Brak regresji — zachowanie synchronizacji shopPRO nie zmienia się
|
||||
```gherkin
|
||||
Given działający mechanizm synchronizacji shopPRO (tabela `integration_order_sync_state`, logika kursorowa)
|
||||
When uruchamiam cron lub ręczną synchronizację shopPRO
|
||||
Then dane stanu są nadal poprawnie odczytywane i zapisywane do tej samej tabeli z tym samym `integration_id`
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Zadanie 1: Utwórz `ShopproOrderSyncStateRepository`</name>
|
||||
<files>src/Modules/Settings/ShopproOrderSyncStateRepository.php</files>
|
||||
<action>
|
||||
Utwórz nowy plik `src/Modules/Settings/ShopproOrderSyncStateRepository.php`.
|
||||
|
||||
Klasa ma być funkcjonalnie identyczna z `AllegroOrderSyncStateRepository` — ta sama tabela `integration_order_sync_state`, ta sama logika `resolveColumns()`, ten sam `upsertState()`. Skopiuj implementację i zmień tylko:
|
||||
- Nazwę klasy: `ShopproOrderSyncStateRepository` (zamiast `AllegroOrderSyncStateRepository`)
|
||||
- Namespace pozostaje `App\Modules\Settings`
|
||||
- Deklaracja `final class ShopproOrderSyncStateRepository`
|
||||
|
||||
Uwagi:
|
||||
- Zachowaj `final` — klasa nie jest przewidziana do dziedziczenia
|
||||
- Zachowaj identyczny kontrakt publiczny (te same sygnatury metod, te same typy zwracane)
|
||||
- Nie zmieniaj nazw kolumn w tabeli ani logiki `resolveColumns()` — tabela jest wspólna, ale dane są scopowane przez `integration_id`
|
||||
- Nie dodawaj żadnej nowej logiki — to tylko rename bez zmiany zachowania
|
||||
</action>
|
||||
<verify>
|
||||
Plik `src/Modules/Settings/ShopproOrderSyncStateRepository.php` istnieje i zawiera `final class ShopproOrderSyncStateRepository`.
|
||||
`php -l src/Modules/Settings/ShopproOrderSyncStateRepository.php` — brak błędów składni.
|
||||
Publiczne metody: `getState`, `markRunStarted`, `markRunSuccess`, `markRunFailed` — wszystkie obecne.
|
||||
</verify>
|
||||
<done>AC-3 spełnione: nowe repozytorium z poprawnym kontraktem istnieje</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Zadanie 2: Zaktualizuj `ShopproOrdersSyncService` — zamień zależność</name>
|
||||
<files>src/Modules/Settings/ShopproOrdersSyncService.php</files>
|
||||
<action>
|
||||
W `ShopproOrdersSyncService.php`:
|
||||
|
||||
1. Usuń import (use): `use App\Modules\Settings\AllegroOrderSyncStateRepository;`
|
||||
(jeśli istnieje jako osobna linia — plik jest w tym samym namespace więc może go nie mieć)
|
||||
|
||||
2. Zmień typ parametru w konstruktorze:
|
||||
```php
|
||||
// PRZED:
|
||||
private readonly AllegroOrderSyncStateRepository $syncState,
|
||||
// PO:
|
||||
private readonly ShopproOrderSyncStateRepository $syncState,
|
||||
```
|
||||
|
||||
3. Nie zmieniaj nazwy zmiennej `$syncState` — żaden inny kod w pliku nie wymaga zmian.
|
||||
|
||||
Uwagi:
|
||||
- Nie zmieniaj żadnych wywołań metod na `$this->syncState` — kontrakt jest identyczny
|
||||
- Nie zmieniaj kolejności parametrów konstruktora
|
||||
- Nie modyfikuj żadnej innej logiki w pliku
|
||||
</action>
|
||||
<verify>
|
||||
`grep -n "AllegroOrderSyncStateRepository" src/Modules/Settings/ShopproOrdersSyncService.php` — brak wyników.
|
||||
`grep -n "ShopproOrderSyncStateRepository" src/Modules/Settings/ShopproOrdersSyncService.php` — obecny w typehintie konstruktora.
|
||||
`php -l src/Modules/Settings/ShopproOrdersSyncService.php` — brak błędów składni.
|
||||
</verify>
|
||||
<done>AC-1, AC-2 spełnione: serwis używa poprawnego repozytorium</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Zadanie 3: Zaktualizuj `Application.php` — wstrzyknij `ShopproOrderSyncStateRepository`</name>
|
||||
<files>src/Core/Application.php</files>
|
||||
<action>
|
||||
W `Application.php`:
|
||||
|
||||
1. Dodaj import: `use App\Modules\Settings\ShopproOrderSyncStateRepository;`
|
||||
(w bloku use, razem z pozostałymi importami z Settings)
|
||||
|
||||
2. Znajdź miejsce tworzenia `ShopproOrdersSyncService` (linia ~296–301):
|
||||
```php
|
||||
$shopproSyncService = new ShopproOrdersSyncService(
|
||||
...
|
||||
new AllegroOrderSyncStateRepository($this->db),
|
||||
...
|
||||
);
|
||||
```
|
||||
Zamień `new AllegroOrderSyncStateRepository($this->db)` na `new ShopproOrderSyncStateRepository($this->db)` — tylko w tym jednym miejscu (przy tworzeniu `ShopproOrdersSyncService`).
|
||||
|
||||
3. Sprawdź, czy `AllegroOrderSyncStateRepository` jest nadal używane gdzie indziej w `Application.php` (przy tworzeniu `AllegroOrderImportService` lub podobnych). Jeśli tak — nie usuwaj jego importu. Usuń import tylko jeśli nie ma innych użyć.
|
||||
|
||||
Uwagi:
|
||||
- Zachowaj kolejność argumentów konstruktora `ShopproOrdersSyncService` bez zmian
|
||||
- Nie zmieniaj wierszy niezwiązanych z `ShopproOrdersSyncService`
|
||||
</action>
|
||||
<verify>
|
||||
W okolicach tworzenia `ShopproOrdersSyncService`: `new ShopproOrderSyncStateRepository($this->db)` jest obecne.
|
||||
Import `use App\Modules\Settings\ShopproOrderSyncStateRepository;` istnieje.
|
||||
`php -l src/Core/Application.php` — brak błędów składni.
|
||||
</verify>
|
||||
<done>AC-4 spełnione: Application.php tworzy poprawne repozytorium dla shopPRO</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## NIE ZMIENIAJ
|
||||
- `src/Modules/Settings/AllegroOrderSyncStateRepository.php` — nie modyfikuj oryginalnej klasy Allegro (inne serwisy mogą jej używać)
|
||||
- Tabela bazy danych `integration_order_sync_state` — nie dodawaj nowych kolumn, nie zmieniaj schematu
|
||||
- Logiki biznesowej synchronizacji w `ShopproOrdersSyncService` — wyłącznie zmiana zależności
|
||||
- Żadnych innych plików poza listą `files_modified`
|
||||
|
||||
## LIMITY ZAKRESU
|
||||
- Nie refaktoryzuj `ShopproOrdersSyncService` ponad wymaganą zmianę zależności (jest na to osobny concern — "1192 lines god class")
|
||||
- Nie wydzielaj interfejsu `OrderSyncStateRepositoryInterface` — to osobna praca poza zakresem planu
|
||||
- Nie przenoś klasy do innego namespace ani modułu
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Przed deklaracją zakończenia planu:
|
||||
- [ ] Plik `ShopproOrderSyncStateRepository.php` istnieje z poprawnymi metodami publicznymi
|
||||
- [ ] `ShopproOrdersSyncService.php` nie zawiera żadnego odwołania do `AllegroOrderSyncStateRepository`
|
||||
- [ ] `Application.php` wstrzykuje `ShopproOrderSyncStateRepository` przy tworzeniu `ShopproOrdersSyncService`
|
||||
- [ ] `php -l` wszystkich 3 zmienionych plików PHP — brak błędów składni
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 3 zadania ukończone
|
||||
- Wszystkie 5 kryteriów akceptacji spełnione
|
||||
- Brak błędów składni PHP
|
||||
- Wpis z CONCERNS.md (Tech Debt — ShopproOrdersSyncService Uses AllegroOrderSyncStateRepository) usunięty po naprawieniu
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po zakończeniu utwórz `.paul/phases/02-bug-fixes/02-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user