--- phase: 17-cart-summary-transport-cost-fix plan: 01 type: execute wave: 1 depends_on: [] files_modified: - autoload/front/Controllers/ShopBasketController.php - templates/shop-basket/summary-view.php - tests/Unit/front/Controllers/ShopBasketControllerSummaryViewTest.php autonomous: false delegation: off --- ## Goal Naprawic blad na stronie /koszyk-podsumowanie, gdzie wybrana forma wysylki oraz laczna kwota zamowienia pokazywane sa za 0,00 zl, mimo ze koszyk nie osiagnal progu darmowej dostawy. ## Purpose Klient widzi nieprawidlowe podsumowanie zamowienia. Koszt transportu w szablonie summary-view.php jest redukowany do zera zawsze, gdy transport ma flage `delivery_free = 1`, bez sprawdzenia czy wartosc koszyka przekroczyla prog `$settings['free_delivery']`. W efekcie klient widzi "0,00 zl" i zaniżona sume zamowienia. Po zlozeniu zamowienia dane w bazie i ostatecznej cenie moga sie roznic, co psuje zaufanie i ksiegowosc. ## Output - ShopBasketController::summaryView() przekazuje do szablonu koszt transportu po uwzglednieniu progu darmowej dostawy (nowy klucz `transport_cost_effective` oraz `free_delivery_applies`). - Szablon summary-view.php pokazuje koszt transportu i sume koncowa na podstawie tych kluczy zamiast surowej flagi `delivery_free`. - Nowy test jednostkowy potwierdza logike wyliczania kosztu w kontrolerze dla 3 scenariuszy (basket ponizej progu, basket rowny progowi, transport bez `delivery_free`). ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Source Files @autoload/front/Controllers/ShopBasketController.php @autoload/Domain/Transport/TransportRepository.php @autoload/Domain/Basket/BasketCalculator.php @templates/shop-basket/summary-view.php @templates/shop-basket/basket-transport-methods.php ## Powiazane pliki (do odwolania) - settings.free_delivery w `pp_settings` (globalny prog darmowej dostawy) - Helpers::normalize_decimal / Helpers::decimal (format kwot) ## AC-1: Transport z flaga delivery_free ponizej progu pokazuje rzeczywisty koszt ```gherkin Given transport ma `delivery_free = 1`, cost = 15.00 zl, a `$settings['free_delivery']` = 300 zl And wartosc koszyka (po kuponie) wynosi 150 zl When klient wchodzi na /koszyk-podsumowanie Then linia transportu pokazuje "15,00 zl" And laczna kwota zamowienia zawiera te 15,00 zl ``` ## AC-2: Transport z flaga delivery_free powyzej progu pokazuje 0,00 zl ```gherkin Given transport ma `delivery_free = 1`, cost = 15.00 zl, a `$settings['free_delivery']` = 300 zl And wartosc koszyka (po kuponie) wynosi 350 zl When klient wchodzi na /koszyk-podsumowanie Then linia transportu pokazuje "0,00 zl" And laczna kwota nie zawiera kosztu transportu ``` ## AC-3: Transport bez flagi delivery_free zawsze pokazuje swoj koszt ```gherkin Given transport ma `delivery_free = 0`, cost = 25.00 zl And wartosc koszyka wynosi 500 zl (powyzej dowolnego progu) When klient wchodzi na /koszyk-podsumowanie Then linia transportu pokazuje "25,00 zl" And laczna kwota zawiera te 25,00 zl ``` ## AC-4: Suma testow PHPUnit nie maleje, nowy test zielony ```gherkin Given istniejacy zestaw testow `./test.ps1` When uruchamiam pelna suite Then nowy test `ShopBasketControllerSummaryViewTest` przechodzi And zadne istniejace testy nie zaczynaja failowac ``` Task 1: Przekaz wyliczony koszt transportu do summary-view z kontrolera autoload/front/Controllers/ShopBasketController.php W metodzie `summaryView()` (ok. linia 270): - Po pobraniu `$transport` (findActiveByIdCached) wylicz kwote koszyka po kuponie uzywajac `\Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon )` - tak jak robi to `transportMethodsFront`. - Wczytaj `$settings['free_delivery']` z globala `$settings`. - Ustaw `free_delivery_applies = false` gdy transport nie istnieje; w przeciwnym razie `true` wtedy i tylko wtedy gdy `$transport['delivery_free'] == 1` ORAZ `normalize_decimal($products_summary) >= normalize_decimal($settings['free_delivery'])`. - Wylicz `transport_cost_effective` = `free_delivery_applies ? 0.0 : (float)$transport['cost']`. - Do `Tpl::view` przekaz dodatkowe klucze `transport_cost_effective` i `free_delivery_applies`. Nie zmieniaj istniejacych kluczy (transport, payment_method itd.) zeby nie zepsuc innych uzyc szablonu. Nie modyfikuj logiki tokenu zamowienia ani guardow. Unikaj: dodawania nowych metod do TransportRepository (kalkulacja nalezy do warstwy koszyka, nie transportu). Recznie odczytaj plik, upewnij sie ze dane sa w tablicy Tpl::view i sa uzywane deterministycznie dla transport === null. AC-1, AC-2 i AC-3 zaspokojone po stronie danych; AC-4 kontrolera. Task 2: Zaktualizuj summary-view.php aby uzywal wyliczonych kluczy templates/shop-basket/summary-view.php W bloku "basket-summary" (ok. linii 97-115): - Zamien warunek `$this->transport['delivery_free'] == 1` na `$this->free_delivery_applies`. - Zamiast `$this->transport['cost']` wyswietlaj `$this->transport_cost_effective` w galezi "else" oraz w kwocie koncowej. - Linia koncowej kwoty (order-summary): `$this->free_delivery_applies ? decimal($summary) : decimal($summary + $this->transport_cost_effective)`. - Zadbaj o poprawne wyswietlenie gdy `transport` jest `null` (skeleton: zachowaj stary fallback - brak kosztu dodawanego). Nie modyfikuj pozostalych fragmentow (produkty, adres, GTM itd.). Unikaj: duplikowania logiki progu w szablonie - szablon ma wyswietlac, nie liczyc. W szablonie nie wystepuje juz `$this->transport['delivery_free']` w tym bloku; nowe klucze sa uzyte dwukrotnie (linia transportu + suma). AC-1, AC-2, AC-3 zaspokojone po stronie prezentacji. Task 3: Test jednostkowy dla logiki kontrolera tests/Unit/front/Controllers/ShopBasketControllerSummaryViewTest.php Utworz nowy plik testow PHPUnit extending `PHPUnit\Framework\TestCase`. Testuj publiczna metode pomocnicza lub kalkulacje w `summaryView()` przez refleksje/helper - preferowane: wyodrebnic wyliczenie do prywatnej metody i wyeksponowac prywatna metode przez ReflectionMethod (bez zmiany publicznego API). Alternatywa: utworz w kontrolerze protected method `calculateTransportCostForSummary(array $transport = null, array $basket, $coupon, float $freeDeliveryThreshold): array` zwracajaca `['transport_cost_effective' => float, 'free_delivery_applies' => bool]` i pokryj ja testami bezposrednio. Trzy scenariusze (AC-1, AC-2, AC-3) + czwarty: transport === null -> cost 0.0, applies false. Mock `\Domain\Basket\BasketCalculator::summaryPrice` nie jest wymagany - podaj gotowa liczbe w tescie. Test musi sie uruchamiac pod `./test.ps1`. Unikaj: testowania na realnej bazie - stub Medoo zaslugujac na AAA. Uruchom `./test.ps1 tests/Unit/front/Controllers/ShopBasketControllerSummaryViewTest.php` - 4 testy zielone. Potem `./test.ps1` pelna suite - liczba testow >= 825 (pelna, bez regresji). AC-4 zaspokojone. Poprawka koszt transportu na /koszyk-podsumowanie. 1. W panelu admina upewnij sie, ze co najmniej jedna metoda transportu ma `delivery_free = 1` i niezerowy `cost` (np. 15 zl). 2. Ustaw `settings.free_delivery` na np. 300 zl. 3. Dodaj do koszyka produkty o wartosci PONIZEJ progu (np. 150 zl). 4. Wejdz na /koszyk, wybierz transport z `delivery_free = 1`, przejdz do /koszyk-podsumowanie. 5. Potwierdz, ze linia transportu pokazuje "15,00 zl" (nie "0,00 zl") i suma zawiera ten koszt. 6. Dolow koszyk do wartosci POWYZEJ progu (>300 zl), odswiez /koszyk-podsumowanie. 7. Potwierdz, ze linia transportu pokazuje "0,00 zl" i suma NIE zawiera kosztu transportu. 8. Wybierz transport bez `delivery_free = 1` (np. kurier 25 zl), potwierdz ze zawsze pokazuje 25,00 zl. Wpisz "approved" aby zakonczyc, lub opisz niezgodnosc do poprawy. ## DO NOT CHANGE - autoload/Domain/Transport/TransportRepository.php (kalkulacja kosztu transportu juz jest w `transportMethodsFront`; nie duplikujemy logiki tam). - autoload/Domain/Basket/BasketCalculator.php (wyliczenie wartosci koszyka pozostaje bez zmian). - templates/shop-basket/basket-transport-methods.php (lista metod na /koszyk dziala poprawnie). - Logika tokenu zamowienia w ShopBasketController (createOrderSubmitToken, consumeOrderSubmitToken). - Struktura bazy danych (brak migracji). ## SCOPE LIMITS - Plan naprawia WYLACZNIE wyswietlanie kosztu na /koszyk-podsumowanie. - Nie refaktoryzujemy summary-view.php poza blokiem transportu. - Nie zmieniamy mechanizmu cache transportu. - Nie dodajemy nowych ustawien/kolumn w bazie. Przed zamknieciem planu: - [ ] `./test.ps1` pelna suite zielona (wszystkie >=824 + 4 nowe testy). - [ ] Recznie zweryfikowano 3 scenariusze na /koszyk-podsumowanie (checkpoint human-verify). - [ ] W summary-view.php nie wystepuje juz `$this->transport['delivery_free']` w sekcji podsumowania. - [ ] Nowy plik testu istnieje i jest w strukturze `tests/Unit/front/Controllers/`. - [ ] Kod zgodny z PHP 7.4 (brak `match`, named arguments itd.). - Wszystkie 4 AC zaspokojone. - Suita PHPUnit zielona bez regresji. - Checkpoint human-verify zaakceptowany. - Brak nowych ostrzezen/bledow w logach. Po zakonczeniu utworz `.paul/phases/17-cart-summary-transport-cost-fix/17-01-SUMMARY.md`