diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md index 1644a22..da038db 100644 --- a/.paul/PROJECT.md +++ b/.paul/PROJECT.md @@ -14,7 +14,7 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzedażą online - |-----------|-------| | Version | 0.333 | | Status | Production | -| Last Updated | 2026-04-20 | +| Last Updated | 2026-04-30 | ## Requirements @@ -32,6 +32,7 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzedażą online - - [x] Domain-Driven Architecture (migracja z legacy zakończona) - [x] Szybka edycja custom_label_0..4 na liscie produktow admina (toggle sesyjny + autocomplete) - [x] Poprawna kalkulacja kosztu transportu na /koszyk-podsumowanie (fix delivery_free bez uwzglednienia progu) +- [x] Linki produktów z permutacją w feedzie Google działają (separator `_` w URL, konwersja `_`→`|` w warstwie front, regex `[0-9_-]+` w pp_routes) ### Active (In Progress) @@ -83,12 +84,13 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzedażą online - | `id` w tabbed FormEdit przez `hiddenFields` | Zapobiega insert zamiast update przy edycji encji | 2026-04-18 | Active | | Inline custom labels w product list przez sesyjny toggle | Szybszy workflow dla Google XML bez wejscia w edycje produktu | 2026-04-19 | Active | | Kalkulacja kosztu transportu na /koszyk-podsumowanie w kontrolerze (nie w szablonie) | Spojnosc logiki progu darmowej dostawy miedzy /koszyk i /koszyk-podsumowanie | 2026-04-20 | Active | +| Separator URL permutacji `_` zamiast `/` (DB pozostaje `|`) | Jeden segment URL dopasowywalny przez pp_routes; konwersja `_`→`|` w warstwie front | 2026-04-30 | Active | ## Success Metrics | Metric | Target | Current | Status | |--------|--------|---------|--------| -| Testy | >800 | 834 | On track | +| Testy | >800 | 841 | On track | | Pokrycie architektury DDD | 100% | 100% | Achieved | ## Tech Stack @@ -117,4 +119,4 @@ Quick Reference: --- *PROJECT.md - Updated when requirements or context change* -*Last updated: 2026-04-20 after Phase 17* +*Last updated: 2026-04-30 after Phase 18* diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index e40d850..449472b 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -38,6 +38,7 @@ Status: Planning | 9 | Apilo email notification + infinite retry | 1 | Done | 2026-03-19 | | 15 | Scontainers edit saves as new record | 1 | Done | 2026-04-18 | | 17 | Cart summary transport cost fix | 1 | Done | 2026-04-20 | +| 18 | Google feed permutation URL fix | 1 | Done | 2026-04-30 | ## Feature @@ -125,5 +126,11 @@ Status: Planning **Scope:** Przekazac z `ShopBasketController::summaryView()` do szablonu wyliczony `transport_cost_effective` i flage `free_delivery_applies` uwzgledniajaca prog. Zaktualizowac summary-view.php aby uzywal tych kluczy zamiast surowej flagi `delivery_free`. Test jednostkowy dla logiki wyliczenia. +### Phase 18 — Google feed permutation URL fix + +**Problem:** URL produktu z permutacją atrybutów w feedzie Google miał format `/slug/20-170/21-175` (slash między parami). Wzorzec routingu `pp_routes` używa `[0-9-]+`, który nie obejmuje `/`, więc URL nie matchuje żadnej trasy i `index.php` ładuje stronę główną. Klienci z GMC trafiają na home zamiast na produkt z wybraną kombinacją. + +**Scope:** Zmienić separator z `/` na `_` w generatorze feedu (`ProductRepository::appendCombinationToXml`), rozszerzyć regex routingu o `_` (`Helpers`), dodać konwersję `_` → `|` w warstwie front (`LayoutEngine`), preselekcja wartości atrybutu w partialu na podstawie `permutation_hash` z URL. Plus unit testy regex + generator linku. + --- -*Last updated: 2026-04-20 (Phase 17 complete)* +*Last updated: 2026-04-30 (Phase 18 complete)* diff --git a/.paul/STATE.md b/.paul/STATE.md index affd51e..c80b6ce 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -2,22 +2,23 @@ ## Project Reference -See: .paul/PROJECT.md (updated 2026-04-18) +See: .paul/PROJECT.md (updated 2026-04-30) **Core value:** Właściciel sklepu ma pełną kontrolę nad sprzedażą online w jednym systemie pisanym od podstaw, bez narzutów zewnętrznych platform. -**Current focus:** Phase 17 complete - loop closed +**Current focus:** Phase 18 complete - loop closed ## Current Position Milestone: Hotfix -Phase: 17 of 17 (Cart summary transport cost fix) - Complete -Plan: 17-01 complete -Status: UNIFY complete, ready for next PLAN loop (transition-phase pending) -Last activity: 2026-04-20 - Closed loop for .paul/phases/17-cart-summary-transport-cost-fix/17-01-PLAN.md +Milestone: Hotfix +Phase: 18 of 18 (Google feed permutation URL fix) - Complete +Plan: 18-01 complete +Status: UNIFY complete, ready for next PLAN loop (transition-phase git commit pending) +Last activity: 2026-04-30 - Closed loop for .paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md Progress: -- Milestone: [##########] 100% -- Phase 17: [##########] 100% +- Milestone: [##########] 100% (Hotfix rolling) +- Phase 18: [##########] 100% ## Loop Position @@ -43,10 +44,17 @@ Phase 14: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-16] Phase 15: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-18] Phase 16: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-19] Phase 17: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-20] +Phase 18: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-30] ``` ## Accumulated Context ### Decisions +- 2026-04-30: Phase 18 loop closed with SUMMARY at .paul/phases/18-google-feed-permutation-url-fix/18-01-SUMMARY.md +- 2026-04-30: Transition-phase git commit for Phase 18 not executed in this UNIFY run (deferred — pattern z faz 15/16/17) +- 2026-04-30: Phase 18 APPLY complete — 4 pliki silnika + 2 nowe pliki testów (HelpersRoutingTest 4 testy, ProductFeedLinkTest 3 testy); suita 841 zielona +- 2026-04-30: Created Phase 18 plan at .paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md +- 2026-04-30: Phase 18 — separator URL permutacji `/` → `_`; konwersja `_` → `|` w warstwie front; regex `[0-9_-]+` w pp_routes +- 2026-04-30: Phase 18 — override /feature-dev (hotfix z konkretną instrukcją), brak redirectów 301, brak automatycznych akcji post-deploy - 2026-04-20: Phase 17 loop closed with SUMMARY at .paul/phases/17-cart-summary-transport-cost-fix/17-01-SUMMARY.md - 2026-04-20: Transition-phase git commit for Phase 17 not executed in this UNIFY run (deferred) - 2026-04-20: Phase 17 APPLY complete - human-verify checkpoint approved, 834 testow zielonych (6 nowych) @@ -89,17 +97,17 @@ None. ### Blockers/Concerns None. -### Skill Audit (Phase 16) +### Skill Audit (Phase 18) | Expected | Invoked | Notes | |----------|---------|-------| -| /feature-dev | ○ | User-approved override during APPLY | -| /koniec-pracy | ○ | Marked as available by user; execute on session close workflow | +| /feature-dev | ○ | User-approved override (hotfix z konkretną instrukcją) | +| /koniec-pracy | ○ | Pending — uruchomić przy zakończeniu sesji jeśli release wchodzi do update package | ## Session Continuity -Last session: 2026-04-20 -Stopped at: Phase 17 complete, loop closed -Next action: Start next milestone or create next phase plan (transition-phase commit pending) -Resume file: .paul/phases/17-cart-summary-transport-cost-fix/17-01-SUMMARY.md +Last session: 2026-04-30 +Stopped at: Phase 18 complete, loop closed +Next action: Start next phase plan (transition-phase git commit pending), lub uruchomić /koniec-pracy jeśli zamykamy sesję +Resume file: .paul/phases/18-google-feed-permutation-url-fix/18-01-SUMMARY.md --- *STATE.md — Updated after every significant action* diff --git a/.paul/changelog/2026-04-30.md b/.paul/changelog/2026-04-30.md new file mode 100644 index 0000000..aec87eb --- /dev/null +++ b/.paul/changelog/2026-04-30.md @@ -0,0 +1,25 @@ +# 2026-04-30 + +## Co zrobiono + +- [Phase 18, Plan 01] Fix linków produktów z permutacją atrybutów w feedzie Google +- Separator URL między parami `attr-val` zmieniony z `/` na `_` w `ProductRepository::appendCombinationToXml` +- Wzorzec routingu `pp_routes` rozszerzony o `_` (`[0-9-]+` → `[0-9_-]+`) w `Helpers::htacces` +- Konwersja `_` → `|` w `LayoutEngine` przed wywołaniem `ProductRepository::findCached` +- Preselekcja wartości atrybutu na podstawie `permutation_hash` z URL w partialu `product-attribute.php` +- 2 nowe pliki testów: `HelpersRoutingTest` (4 testy) + `ProductFeedLinkTest` (3 testy via Reflection) +- Suita PHPUnit: 834 → 841 zielonych + +## Zmienione pliki + +- `autoload/Domain/Product/ProductRepository.php` +- `autoload/Shared/Helpers/Helpers.php` +- `autoload/front/LayoutEngine.php` +- `templates/shop-product/_partial/product-attribute.php` +- `tests/Unit/Shared/Helpers/HelpersRoutingTest.php` +- `tests/Unit/Domain/Product/ProductFeedLinkTest.php` +- `.paul/STATE.md` +- `.paul/PROJECT.md` +- `.paul/ROADMAP.md` +- `.paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md` +- `.paul/phases/18-google-feed-permutation-url-fix/18-01-SUMMARY.md` diff --git a/.paul/codebase/testing.md b/.paul/codebase/testing.md index 7a67a5b..32346c2 100644 --- a/.paul/codebase/testing.md +++ b/.paul/codebase/testing.md @@ -4,8 +4,8 @@ | Metric | Value | |--------|-------| -| Total tests | **828** | -| Total assertions | **2306** | +| Total tests | **841** | +| Total assertions | **2330** | | Framework | PHPUnit 9.6 (`phpunit.phar`) | | Bootstrap | `tests/bootstrap.php` | | Config | `phpunit.xml` | diff --git a/.paul/docs/TECH_CHANGELOG.md b/.paul/docs/TECH_CHANGELOG.md index 58bf49c..ce12c11 100644 --- a/.paul/docs/TECH_CHANGELOG.md +++ b/.paul/docs/TECH_CHANGELOG.md @@ -2,6 +2,16 @@ > Chronologiczny log zmian technicznych — co i dlaczego. +## v0.350 (2026-04-30) + +- Naprawiono linki produktow z permutacja atrybutow w feedzie Google: separator par `attr-val` w URL zmieniony z `/` na `_`. Stary format `/slug/20-170/21-175` nie matchowal sie w `pp_routes` (regex `[0-9-]+` nie obejmuje `/`), wiec klienci z GMC ladowali na strone glowna zamiast na produkt. +- `ProductRepository::appendCombinationToXml`: `str_replace('|', '/', ...)` -> `str_replace('|', '_', ...)` w obu galeziach (z `seo_link` i fallback `p-id-name`). +- `Helpers::htacces`: regex routingu produktow z permutacja rozszerzony do `/([0-9_-]+)$` w obu wariantach. +- `LayoutEngine.php` (// PRODUKT): konwersja `_` -> `|` przed wywolaniem `ProductRepository::findCached` — format DB pozostaje bez zmian (`attr-val|attr-val`). +- `templates/shop-product/_partial/product-attribute.php`: preselekcja wartosci atrybutu na podstawie `permutation_hash` z URL (`$forced_value_id`); wartosc `is_default` uzywana tylko gdy URL nie wymusza wyboru. Dotyczy `checked` na inpucie i emisji bloku `fradio_label_click(...)`. +- Dodano 7 testow jednostkowych: `HelpersRoutingTest` (4 testy regex + assercje na zawartosci pliku) i `ProductFeedLinkTest` (3 testy `appendCombinationToXml` via `ReflectionMethod` z mockiem `TransportRepository`). Suita: 841 testow / 2330 assertions. +- Wymagane akcje na produkcji po deployu: regeneracja `pp_routes` (`Helpers::htacces()`), wyczyszczenie klucza `pp_routes:all` w Redis, regeneracja `google-feed.xml`, resubmit feedu w GMC. + ## v0.349 (2026-04-20) - Naprawiono wyswietlanie kosztu transportu na /koszyk-podsumowanie: transporty z `delivery_free=1` pokazuja teraz rzeczywisty koszt ponizej progu `settings.free_delivery`, a 0,00 zl dopiero po osiagnieciu progu (spojnie z lista na /koszyk). diff --git a/.paul/docs/TODO.md b/.paul/docs/TODO.md index e9bb9d3..5cda327 100644 --- a/.paul/docs/TODO.md +++ b/.paul/docs/TODO.md @@ -3688,3 +3688,6 @@ Dodać możliwość ustawienia limitu znaków w wiadomościach do produktu ## SonarQube - v0.349 - brak nowych issues + + +## SonarQube - v0.350 - brak nowych issues diff --git a/.paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md b/.paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md new file mode 100644 index 0000000..7a59d91 --- /dev/null +++ b/.paul/phases/18-google-feed-permutation-url-fix/18-01-PLAN.md @@ -0,0 +1,258 @@ +--- +phase: 18-google-feed-permutation-url-fix +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - autoload/Domain/Product/ProductRepository.php + - autoload/Shared/Helpers/Helpers.php + - autoload/front/LayoutEngine.php + - templates/shop-product/_partial/product-attribute.php + - tests/Unit/Domain/Product/ProductRepositoryTest.php + - tests/Unit/Shared/Helpers/HelpersTest.php +autonomous: true +delegation: off +--- + + +## Goal +Naprawić linki produktów z permutacją atrybutów w feedzie Google: zamienić separator `/` na `_` między parami `attr-val`, dopasować routing `pp_routes`, konwersję `_` → `|` w warstwie front oraz preselekcję wartości atrybutów na podstawie `permutation_hash` z URL. + +## Purpose +URL z formatu `/slug/20-170/21-175` nie matchował się w `pp_routes` (wzorzec `[0-9-]+` nie obejmuje `/`), więc Google Merchant Center prowadził klientów na stronę główną zamiast na produkt z wybraną kombinacją atrybutów. Strata ruchu komercyjnego z feedu. + +## Output +- 4 pliki silnika z nowym separatorem `_` +- Unit testy: regex routingu (Helpers) + generator linku (ProductRepository::appendCombinationToXml) +- SUMMARY z listą akcji post-deploy do wykonania ręcznie na produkcji + + + +## Project Context +@.paul/PROJECT.md +@.paul/ROADMAP.md +@.paul/STATE.md +@.paul/codebase/architecture.md + +## Source Files +@autoload/Domain/Product/ProductRepository.php +@autoload/Shared/Helpers/Helpers.php +@autoload/front/LayoutEngine.php +@templates/shop-product/_partial/product-attribute.php + + +- **Testy** — Czy dodać unit testy dla zmian? + → Odpowiedź: Tak — pełne pokrycie (Helpers regex + ProductRepository::appendCombinationToXml) +- **Post-deploy** — Czy wykonać regenerację routes/cache/feedu w ramach fazy? + → Odpowiedź: Nic — tylko kod; akcje produkcyjne udokumentowane w SUMMARY +- **Redirect 301** — Czy dodać redirecty ze starych URL-i? + → Odpowiedź: Nie — Google sam zaktualizuje linki z feedu +- **Skills** — /feature-dev required w SPECIAL-FLOWS? + → Odpowiedź: Override — pomiń (hotfix z konkretną instrukcją, jak w fazach 15/16/17) + + + + + +## AC-1: Generator linku w feedzie używa `_` +```gherkin +Given produkt z permutacją atrybutów (permutation_hash = "20-170|21-175") +When wywołany jest ProductRepository::appendCombinationToXml dla feedu Google +Then wygenerowany URL zawiera segment `20-170_21-175` (jeden segment, separator `_`) +And nie zawiera `/` między parami atrybutów +And dotyczy obu gałęzi (z seo_link i fallback p-id-name) +``` + +## AC-2: Routing `pp_routes` matchuje URL z `_` +```gherkin +Given wzorzec routingu wygenerowany przez Helpers dla produktu z permutacją +When URI to `slug-produktu/20-170_21-175` +Then regex `[0-9_-]+` dopasowuje cały segment permutacji +And `permutation_hash` w wynikowych GET to `20-170_21-175` +And dotyczy obu wariantów (z seo_link i fallback p-id-name) +``` + +## AC-3: Front konwertuje `_` z URL na `|` przed zapytaniem do bazy +```gherkin +Given GET['permutation_hash'] = "20-170_21-175" +When LayoutEngine renderuje blok PRODUKT +Then ProductRepository::findCached otrzymuje argument "20-170|21-175" +And gdy GET['permutation_hash'] nie istnieje, findCached otrzymuje null +``` + +## AC-4: Partial atrybutu preselectuje wartość z URL +```gherkin +Given URL produktu z permutation_hash zawierającym parę dla bieżącego atrybutu +When renderuje się templates/shop-product/_partial/product-attribute.php +Then aktywna (checked) jest wartość z URL, nie z is_default +And gdy atrybut nie występuje w hashu, zachowane jest stare zachowanie (is_default) +And blok