--- phase: 74-reverse-status-mapping plan: 01 type: execute wave: 1 depends_on: [] files_modified: - resources/views/settings/shoppro.php - resources/views/settings/allegro.php - src/Modules/Settings/ShopproIntegrationsController.php - src/Modules/Settings/AllegroStatusMappingController.php - src/Modules/Settings/AllegroIntegrationController.php - src/Modules/Settings/ShopproStatusMappingRepository.php - src/Modules/Settings/AllegroStatusMappingRepository.php - src/Modules/Settings/ShopproOrdersSyncService.php - src/Modules/Settings/ShopproStatusSyncService.php - src/Modules/Settings/AllegroStatusSyncService.php - database/migrations/20260407_000074_reverse_status_mapping_keys.sql - resources/lang/pl/settings.php autonomous: true --- ## Goal Odwrocic logike mapowania statusow w integracjach shopPRO i Allegro: zamiast "status zewnetrzny -> status orderPRO", pokazac "status orderPRO -> status zewnetrzny". Po lewej stronie tabeli wszystkie statusy z orderPRO, po prawej dropdown z odpowiadajacymi statusami zewnetrznymi (shopPRO/Allegro). ## Purpose Intuicyjniejszy interfejs — uzytkownik mysli kategoriami wlasnych statusow orderPRO i przypisuje im odpowiedniki w zewnetrznych systemach. Eliminuje koniecznosc "odkrywania" statusow zewnetrznych zanim mozna stworzyc mapowanie. ## Output - Zmieniony UI tab "Statusy" w ustawieniach shopPRO i Allegro - Zmieniona logika zapisu i odczytu mapowan w kontrolerach i repozytoriach - Migracja DB zmieniajaca unique constraint z external_code na orderpro_status_code - Zaktualizowane serwisy sync (pull/push) do pracy z odwroconą mapą ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Source Files @resources/views/settings/shoppro.php (linie 192-265 — tab Statusy) @resources/views/settings/allegro.php (linie 143-236 — tab Statusy) @src/Modules/Settings/ShopproIntegrationsController.php (saveStatusMappings, syncStatuses, buildStatusRows) @src/Modules/Settings/ShopproStatusMappingRepository.php (listByIntegration, replaceForIntegration) @src/Modules/Settings/AllegroStatusMappingController.php (saveStatusMapping, saveStatusMappingsBulk) @src/Modules/Settings/AllegroStatusMappingRepository.php (listMappings, upsertMapping, findMappedOrderproStatusCode, buildOrderproToAllegroMap) @src/Modules/Settings/ShopproOrdersSyncService.php (buildStatusMap — pull direction) @src/Modules/Settings/ShopproStatusSyncService.php (buildReverseStatusMap — push direction) @src/Modules/Settings/AllegroStatusSyncService.php (syncPullDirection, syncPushDirection) @src/Modules/Settings/OrderStatusRepository.php (listStatuses — zrodlo statusow orderPRO) No specialized flows required — standard execute plan. ## AC-1: UI shopPRO — orderPRO statusy po lewej, shopPRO po prawej ```gherkin Given uzytkownik otwiera Ustawienia > Integracje > shopPRO > tab Statusy When strona sie laduje Then po lewej stronie tabeli widac nazwy i kody wszystkich statusow orderPRO And po prawej stronie dropdown z opcjami statusow shopPRO (pobranymi z API + juz zapisanymi) And kazdy status orderPRO moze miec przypisany co najwyzej jeden status shopPRO ``` ## AC-2: UI Allegro — orderPRO statusy po lewej, Allegro po prawej ```gherkin Given uzytkownik otwiera Ustawienia > Integracje > Allegro > tab Statusy When strona sie laduje Then po lewej stronie tabeli widac nazwy i kody wszystkich statusow orderPRO And po prawej stronie dropdown z opcjami statusow Allegro (znane + odkryte sync) And kazdy status orderPRO moze miec przypisany co najwyzej jeden status Allegro ``` ## AC-3: Zapis mapowan dziala poprawnie w obu kierunkach sync ```gherkin Given uzytkownik zapisal mapowanie statusu orderPRO "w realizacji" -> shopPRO status "3" When cron wykonuje sync w kierunku pull (shoppro_to_orderpro) Then zamowienie z shopPRO status "3" otrzymuje status orderPRO "w realizacji" When cron wykonuje sync w kierunku push (orderpro_to_shoppro) Then zamowienie ze statusem orderPRO "w realizacji" pushuje status "3" do shopPRO ``` ## AC-4: Przycisk Sync pobiera statusy zewnetrzne do dropdowna ```gherkin Given uzytkownik jest na tab Statusy w shopPRO When kliknie "Synchronizuj statusy z API" Then opcje w dropdownach po prawej stronie zostaja uzupelnione o nowo odkryte statusy shopPRO And istniejace mapowania nie sa tracone ``` ## AC-5: Migracja DB zmienia unique constraint ```gherkin Given baza danych zawiera istniejace mapowania When migracja zostanie wykonana Then unique key w order_status_mappings zmienia sie z (integration_id, shoppro_status_code) na (integration_id, orderpro_status_code) And unique key w allegro_order_status_mappings zmienia sie z allegro_status_code na orderpro_status_code And istniejace dane nie sa usuwane ``` Task 1: Migracja DB + repozytoria + serwisy sync database/migrations/20260407_000074_reverse_status_mapping_keys.sql, src/Modules/Settings/ShopproStatusMappingRepository.php, src/Modules/Settings/AllegroStatusMappingRepository.php, src/Modules/Settings/ShopproOrdersSyncService.php, src/Modules/Settings/ShopproStatusSyncService.php, src/Modules/Settings/AllegroStatusSyncService.php 1. Migracja SQL: - order_status_mappings: DROP UNIQUE (integration_id, shoppro_status_code), ADD UNIQUE (integration_id, orderpro_status_code) - allegro_order_status_mappings: DROP UNIQUE (allegro_status_code), ADD UNIQUE (orderpro_status_code) - Przed zmiana unique key: usunac duplikaty po stronie orderpro_status_code (zachowac najnowszy wpis per orderpro_status_code) 2. ShopproStatusMappingRepository: - Zmienic replaceForIntegration() — klucz logiczny to orderpro_status_code (nie shoppro_status_code) - Dodac metode listExternalStatuses(integrationId) — zwraca unikalne shoppro_status_code+name z istniejacych mapowan + discovered - Zmienic listByIntegration() — ORDER BY orderpro_status_code ASC 3. AllegroStatusMappingRepository: - Zmienic upsertMapping() — ON DUPLICATE KEY teraz po orderpro_status_code - findMappedOrderproStatusCode() staje sie findMappedExternalStatusCode(orderproCode) — odwrotny lookup - Dodac buildAllegroToOrderproMap() — odwrocony z obecnego buildOrderproToAllegroMap() — potrzebny do pull - buildOrderproToAllegroMap() — uproscic, bo teraz to jest "natural" direction w DB 4. ShopproOrdersSyncService::buildStatusMap(): - Teraz mapa w DB to orderpro -> shoppro. Pull potrzebuje shoppro -> orderpro. - Zbudowac odwrocona mape (iterate rows, $map[$shopCode] = $orderCode) 5. ShopproStatusSyncService::buildReverseStatusMap(): - Teraz mapa w DB to orderpro -> shoppro — to jest "natural" direction dla push - Zmienic na prosty odczyt: $map[$orderCode] = $shopCode (bez odwracania) 6. AllegroStatusSyncService: - Pull: uzyc nowego buildAllegroToOrderproMap() zamiast findMappedOrderproStatusCode() - Push: buildOrderproToAllegroMap() — teraz to jest prosty odczyt z DB Unikac: zmiany nazw kolumn w DB (shoppro_status_code i orderpro_status_code zostaja — zmienia sie tylko unique key i logika) - Migracja SQL wykonuje sie bez bledow - php -l na wszystkich zmodyfikowanych plikach PHP - Sprawdzic ze istniejace sync serwisy nadal buduja poprawne mapy w obu kierunkach AC-3 satisfied (sync dziala w obu kierunkach), AC-5 satisfied (migracja unique key) Task 2: UI i kontrolery — odwrocone mapowanie resources/views/settings/shoppro.php, resources/views/settings/allegro.php, src/Modules/Settings/ShopproIntegrationsController.php, src/Modules/Settings/AllegroStatusMappingController.php, src/Modules/Settings/AllegroIntegrationController.php, resources/lang/pl/settings.php 1. ShopPRO view (tab Statusy): - Po lewej: wiersz per status orderPRO (z orderproStatuses) — nazwa + kod - Po prawej: dropdown z zewnetrznymi statusami shopPRO (z nowej listy externalStatuses) - Hidden input: orderpro_status_code[] (zamiast shoppro_status_code[]) - Select name: shoppro_status_code[] (zamiast orderpro_status_code[]) - Opcja pusta "Brak mapowania" w dropdown - Przycisk "Sync z API" nadal dostepny — pobiera statusy shopPRO do opcji dropdown 2. ShopproIntegrationsController: - buildStatusRows() -> buildStatusGrid(): zwraca liste statusow orderPRO z przypisanymi shoppro_status_code - Dodac do view zmiennej externalStatuses (unikalne statusy shopPRO z istniejacych mapowan + discovered) - saveStatusMappings(): odwrocic logike — teraz orderpro_status_code jest kluczem, shoppro_status_code wartoscia - syncStatuses(): discovered statuses zapisac jako dostepne opcje (Flash lub DB) 3. Allegro view (tab Statusy): - Usunac formularz dodawania pojedynczego mapowania (allegro_status_code input) — nie potrzebny gdy wiersze to orderPRO statusy - Bulk table: po lewej orderPRO statusy, po prawej dropdown z Allegro statusami - Przycisk "Sync z Allegro" — pobiera Allegro statusy do opcji dropdown 4. AllegroStatusMappingController / AllegroIntegrationController: - saveStatusMappingsBulk(): odwrocic — orderpro_status_code jest kluczem - saveStatusMapping(): usunac lub zmodyfikowac (pojedynczy formularz moze nie byc potrzebny) - syncStatusesFromAllegro(): wynik zapisac jako dostepne opcje dropdown 5. Tlumaczenia (settings.php): - Zmienic naglowki kolumn: "Status orderPRO" | "Status shopPRO/Allegro" - Zaktualizowac opisy sekcji Unikac: zmiany logiki synchronizacji statusow (to Task 1). Tutaj tylko UI i walidacja formularza. - Otworzyc /settings/integrations/shoppro?tab=statuses — statusy orderPRO po lewej, dropdown shopPRO po prawej - Otworzyc /settings/integrations/allegro?tab=statuses — statusy orderPRO po lewej, dropdown Allegro po prawej - Zapisac mapowanie — brak bledow, dane poprawnie w DB - Sync z API — dropdown uzupelnia sie o nowe opcje AC-1 satisfied (shopPRO UI), AC-2 satisfied (Allegro UI), AC-4 satisfied (sync do dropdown) ## DO NOT CHANGE - src/Modules/Settings/OrderStatusRepository.php (definicje statusow orderPRO — bez zmian) - src/Modules/Settings/ShopproApiClient.php (klient API — bez zmian) - src/Modules/Settings/AllegroApiClient.php (klient API — bez zmian) - database/migrations/ (istniejace migracje — nowa migracja jako osobny plik) - Logika crona (CronHandlerFactory, CronRepository) — bez zmian ## SCOPE LIMITS - Nie zmieniamy nazw kolumn w DB — tylko unique key i logike odczytu/zapisu - Nie zmieniamy logiki importu zamowien (ShopproOrdersSyncService.sync, AllegroOrderImportService) - Nie dodajemy nowych tabel — modyfikujemy istniejace - Nie ruszamy tab "Ustawienia" (sync direction dropdown) ani tab "Dostawy" Before declaring plan complete: - [ ] Migracja SQL wykonuje sie bez bledow na istniejacych danych - [ ] php -l na wszystkich zmodyfikowanych plikach PHP — brak syntax errors - [ ] UI shopPRO tab Statusy: orderPRO po lewej, shopPRO dropdown po prawej - [ ] UI Allegro tab Statusy: orderPRO po lewej, Allegro dropdown po prawej - [ ] Zapis mapowania shopPRO — dane poprawnie w DB z nowym unique key - [ ] Zapis mapowania Allegro — dane poprawnie w DB z nowym unique key - [ ] buildStatusMap() w ShopproOrdersSyncService nadal zwraca shoppro->orderpro map - [ ] buildReverseStatusMap() w ShopproStatusSyncService nadal zwraca orderpro->shoppro map - [ ] buildOrderproToAllegroMap() nadal zwraca orderpro->allegro map - [ ] All acceptance criteria met - Oba taby Statusy (shopPRO i Allegro) wyswietlaja orderPRO statusy po lewej - Mapowania zapisuja sie poprawnie z nowym unique key - Sync pull i push dzialaja bez zmian w zachowaniu - Brak regresji w imporcie zamowien After completion, create `.paul/phases/74-reverse-status-mapping/74-01-SUMMARY.md`