---
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>
