Files
shopPRO/.paul/phases/17-cart-summary-transport-cost-fix/17-01-PLAN.md
Jacek eee22ef1c4 fix: poprawny koszt transportu na /koszyk-podsumowanie
Na podstronie /koszyk-podsumowanie transport z flaga delivery_free=1
byl pokazywany zawsze za 0,00 zl, niezaleznie od wartosci koszyka.
Teraz kontroler wylicza transport_cost_effective i free_delivery_applies
uwzgledniajac prog settings.free_delivery, a szablon uzywa tych kluczy.

- Nowa chroniona metoda ShopBasketController::calculateTransportCostForSummary
- Dodane 6 testow jednostkowych (ShopBasketControllerSummaryViewTest)
- Suita: 834 testy / 2318 assertions OK

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:50:15 +02:00

192 lines
9.7 KiB
Markdown

---
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
---
<objective>
## 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`).
</objective>
<context>
## 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)
</context>
<acceptance_criteria>
## 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
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Przekaz wyliczony koszt transportu do summary-view z kontrolera</name>
<files>autoload/front/Controllers/ShopBasketController.php</files>
<action>
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).
</action>
<verify>Recznie odczytaj plik, upewnij sie ze dane sa w tablicy Tpl::view i sa uzywane deterministycznie dla transport === null.</verify>
<done>AC-1, AC-2 i AC-3 zaspokojone po stronie danych; AC-4 kontrolera.</done>
</task>
<task type="auto">
<name>Task 2: Zaktualizuj summary-view.php aby uzywal wyliczonych kluczy</name>
<files>templates/shop-basket/summary-view.php</files>
<action>
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.
</action>
<verify>W szablonie nie wystepuje juz `$this->transport['delivery_free']` w tym bloku; nowe klucze sa uzyte dwukrotnie (linia transportu + suma).</verify>
<done>AC-1, AC-2, AC-3 zaspokojone po stronie prezentacji.</done>
</task>
<task type="auto">
<name>Task 3: Test jednostkowy dla logiki kontrolera</name>
<files>tests/Unit/front/Controllers/ShopBasketControllerSummaryViewTest.php</files>
<action>
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.
</action>
<verify>Uruchom `./test.ps1 tests/Unit/front/Controllers/ShopBasketControllerSummaryViewTest.php` - 4 testy zielone. Potem `./test.ps1` pelna suite - liczba testow >= 825 (pelna, bez regresji).</verify>
<done>AC-4 zaspokojone.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>
Poprawka koszt transportu na /koszyk-podsumowanie.
</what-built>
<how-to-verify>
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.
</how-to-verify>
<resume-signal>Wpisz "approved" aby zakonczyc, lub opisz niezgodnosc do poprawy.</resume-signal>
</task>
</tasks>
<boundaries>
## 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.
</boundaries>
<verification>
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.).
</verification>
<success_criteria>
- Wszystkie 4 AC zaspokojone.
- Suita PHPUnit zielona bez regresji.
- Checkpoint human-verify zaakceptowany.
- Brak nowych ostrzezen/bledow w logach.
</success_criteria>
<output>
Po zakonczeniu utworz `.paul/phases/17-cart-summary-transport-cost-fix/17-01-SUMMARY.md`
</output>