diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md index 36b52fc..374fe7c 100644 --- a/.paul/PROJECT.md +++ b/.paul/PROJECT.md @@ -76,6 +76,7 @@ Sprzedawca moĹĽe obsĹ‚ugiwać zamĂłwienia ze wszystkich kanałów - [x] Koszt wysylki jako pozycja paragonu (bugfix buildItemsSnapshot + delivery_price) — Phase 70 - [x] Import atrybutow produktow z shopPRO (attributes + custom_fields w personalizacji) — Phase 71 - [x] Zapamiętywanie wybranej liczby wierszy na stronie (per_page) w localStorage — Phase 72 +- [x] Wyszukiwanie zamowien po nazwie produktu (EXISTS subquery) — Phase 73 - [ ] Eliminacja zduplikowanego kodu: SslCertificateResolver, ToggleableRepositoryTrait, RedirectPathResolver, ReceiptService — Phase 68 ### Active (In Progress) diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index e4336da..afd9ae4 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -33,6 +33,7 @@ Wersja mobilna aplikacji, modul po module. Cel: pelna uzywalnosc orderPRO na tel | 70 | Receipt Shipping Cost | 1/1 | Complete | | 71 | Attributes Import | 1/1 | Complete | | 72 | Per Page Persistence | 1/1 | Complete | +| 73 | Search by Product | 1/1 | Complete | | TBD | Mobile Orders List | - | Not started | | TBD | Mobile Order Details | - | Not started | | TBD | Mobile Settings | - | Not started | diff --git a/.paul/STATE.md b/.paul/STATE.md index 1cea329..1f008cc 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -5,19 +5,19 @@ See: .paul/PROJECT.md (updated 2026-04-07) **Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami. -**Current focus:** Milestone v3.0 - Phase 72 complete, ready for next PLAN +**Current focus:** Milestone v3.0 - Phase 73 complete, ready for next PLAN ## Current Position Milestone: v3.0 Mobile Responsive - In progress -Phase: 72 (Per Page Persistence) — Complete -Plan: 72-01 unified +Phase: 73 (Search by Product) — Complete +Plan: 73-01 unified Status: Loop complete, ready for next PLAN -Last activity: 2026-04-07 — Unified .paul/phases/72-per-page-persistence/72-01-PLAN.md +Last activity: 2026-04-07 — Unified .paul/phases/73-search-by-product/73-01-PLAN.md Progress: -- Milestone: [########..] ~75% -- Phase 72: [##########] 100% +- Milestone: [########..] ~76% +- Phase 73: [##########] 100% ## Loop Position @@ -30,11 +30,11 @@ PLAN --> APPLY --> UNIFY ## Session Continuity Last session: 2026-04-07 -Stopped at: Plan 72-01 unified +Stopped at: Plan 73-01 unified Next action: Run /paul:plan for the next prioritized phase -Resume file: .paul/phases/72-per-page-persistence/72-01-SUMMARY.md +Resume file: .paul/phases/73-search-by-product/73-01-SUMMARY.md ## Git State -Last commit: 6d0905d +Last commit: 24df01c Branch: main diff --git a/.paul/phases/73-search-by-product/73-01-PLAN.md b/.paul/phases/73-search-by-product/73-01-PLAN.md new file mode 100644 index 0000000..c53d7cb --- /dev/null +++ b/.paul/phases/73-search-by-product/73-01-PLAN.md @@ -0,0 +1,129 @@ +--- +phase: 73-search-by-product +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: [src/Modules/Orders/OrdersRepository.php, resources/views/orders/list.php] +autonomous: true +--- + + +## Goal +Rozszerzenie wyszukiwarki na liscie zamowien o wyszukiwanie po nazwie produktu z zamowienia. + +## Purpose +Uzytkownik nie moze znalezc zamowienia po nazwie produktu — musi znac numer zamowienia, login lub email klienta. Wyszukiwanie po produkcie jest naturalnym sposobem szukania zamowien. + +## Output +Zmodyfikowane zapytanie SQL w `buildPaginateFilters()` — istniejace pole szukaj obsluguje rowniez nazwy produktow. Zaktualizowany placeholder inputa. + + + +## Source Files +@src/Modules/Orders/OrdersRepository.php (linie 91-105 buildPaginateFilters, 48-54 countSql) +@resources/views/orders/list.php + + + + +## AC-1: Wyszukiwanie po nazwie produktu +```gherkin +Given zamowienie zawiera produkt "Tabliczki z miesiacami do zdjec - Serduszko" +When uzytkownik wpisze "Tabliczki" w pole szukaj +Then zamowienie pojawi sie w wynikach +``` + +## AC-2: Istniejace wyszukiwanie dziala bez zmian +```gherkin +Given zamowienie ma source_order_id = "11776" +When uzytkownik wpisze "11776" w pole szukaj +Then zamowienie pojawi sie w wynikach (brak regresji) +``` + +## AC-3: Brak duplikatow wynikow +```gherkin +Given zamowienie zawiera 3 produkty pasujace do frazy +When uzytkownik wyszuka te fraze +Then zamowienie pojawi sie dokladnie raz w wynikach +``` + +## AC-4: Placeholder inputa zaktualizowany +```gherkin +Given uzytkownik widzi pole szukaj na liscie zamowien +Then placeholder zawiera informacje o wyszukiwaniu po produkcie +``` + + + + + + + Task 1: Dodanie wyszukiwania po nazwie produktu + src/Modules/Orders/OrdersRepository.php + + W metodzie `buildPaginateFilters()` (linia 97-104): + + 1. Dodac do warunku search EXISTS subquery na order_items: + ``` + OR EXISTS (SELECT 1 FROM order_items oi WHERE oi.order_id = o.id AND oi.original_name LIKE :s6) + ``` + 2. Dodac parametr `$params['s6'] = $searchVal;` + + Uzyc EXISTS zamiast JOIN — zapobiega duplikatom i nie wymaga zmian w countSql ani buildListSql. + + 3. W countSql (linia 49-52) — NIE dodawac JOINa. EXISTS w WHERE jest samowystarczalny. + + + Zapytanie SQL wykonuje sie poprawnie. Test: wyszukanie "Tabliczki" zwraca zamowienia z takim produktem. + + AC-1, AC-2, AC-3 satisfied + + + + Task 2: Aktualizacja placeholder inputa + resources/views/orders/list.php + + Znalezc input szukaj na liscie zamowien i zaktualizowac placeholder: + - Z: "numer, ID, login, email, klient" (lub podobny) + - Na: "numer, klient, email, produkt" + + Sprawdzic czy placeholder jest w list.php czy w komponencie table-list.php — prawdopodobnie jest przekazywany z kontrolera lub widoku. + + Placeholder inputa zawiera slowo "produkt" + AC-4 satisfied + + + + + + +## DO NOT CHANGE +- buildListSql() — struktura SELECT i JOINy +- Inne filtry w buildPaginateFilters (source, status, payment_status, date) +- Komponent table-list.php (poza ewentualnym placeholder jesli tam jest) + +## SCOPE LIMITS +- Tylko rozszerzenie istniejacego pola szukaj — bez osobnego pola produktowego +- Bez indeksu FULLTEXT (LIKE wystarczy przy obecnej skali) + + + + +Before declaring plan complete: +- [ ] PHP syntax OK +- [ ] Wyszukanie "Tabliczki" zwraca zamowienia z produktem Tabliczki +- [ ] Wyszukanie "11776" nadal zwraca zamowienie po numerze +- [ ] Brak duplikatow przy wyszukiwaniu po produkcie +- [ ] Placeholder inputa zawiera "produkt" + + + +- Pole szukaj obsluguje nazwy produktow +- Brak regresji w istniejacym wyszukiwaniu +- Brak duplikatow wynikow + + + +After completion, create `.paul/phases/73-search-by-product/73-01-SUMMARY.md` + diff --git a/.paul/phases/73-search-by-product/73-01-SUMMARY.md b/.paul/phases/73-search-by-product/73-01-SUMMARY.md new file mode 100644 index 0000000..80cdca9 --- /dev/null +++ b/.paul/phases/73-search-by-product/73-01-SUMMARY.md @@ -0,0 +1,99 @@ +--- +phase: 73-search-by-product +plan: 01 +subsystem: api +tags: [search, orders, order_items, EXISTS] + +requires: [] +provides: + - Wyszukiwanie zamowien po nazwie produktu +affects: [] + +tech-stack: + added: [] + patterns: [EXISTS subquery for search without JOIN duplicates] + +key-files: + created: [] + modified: [src/Modules/Orders/OrdersRepository.php, resources/lang/pl.php] + +key-decisions: + - "EXISTS subquery zamiast JOIN — brak duplikatow, brak zmian w countSql/buildListSql" + - "Rozszerzenie istniejacego pola szukaj zamiast osobnego pola produktowego" + +patterns-established: [] + +duration: 5min +started: 2026-04-07T12:30:00Z +completed: 2026-04-07T12:35:00Z +--- + +# Phase 73 Plan 01: Search by Product Summary + +**Rozszerzenie wyszukiwarki zamowien o nazwe produktu — EXISTS subquery na order_items.original_name.** + +## Performance + +| Metric | Value | +|--------|-------| +| Duration | ~5min | +| Tasks | 2 completed | +| Files modified | 2 | + +## Acceptance Criteria Results + +| Criterion | Status | Notes | +|-----------|--------|-------| +| AC-1: Wyszukiwanie po nazwie produktu | Pass | "Tabliczki" → 10 zamowien | +| AC-2: Istniejace wyszukiwanie bez zmian | Pass | "11776" → 1 zamowienie | +| AC-3: Brak duplikatow wynikow | Pass | EXISTS gwarantuje 0 duplikatow | +| AC-4: Placeholder zaktualizowany | Pass | "Szukaj (numer, klient, email, produkt)" | + +## Accomplishments + +- Dodano EXISTS subquery `order_items oi_s` do warunku search w buildPaginateFilters +- Zaktualizowano placeholder w tlumaczeniach pl.php +- Zweryfikowano na zdalnej bazie: brak regresji, brak duplikatow + +## Files Created/Modified + +| File | Change | Purpose | +|------|--------|---------| +| `src/Modules/Orders/OrdersRepository.php` | Modified | EXISTS subquery + parametr :s6 w search | +| `resources/lang/pl.php` | Modified | Placeholder "produkt" w filtrze search | + +## Decisions Made + +| Decision | Rationale | Impact | +|----------|-----------|--------| +| EXISTS zamiast JOIN | Brak duplikatow, brak zmian w countSql/buildListSql | Czystsza implementacja | +| Alias oi_s dla subquery | Unikniecie konfliktu z istniejacym oi_agg w buildListSql | Brak ryzyka kolizji nazw | + +## Deviations from Plan + +### Summary + +| Type | Count | Impact | +|------|-------|--------| +| Scope additions | 1 | Minimalny — plik tlumaczen zamiast widoku | + +Placeholder byl w `resources/lang/pl.php` a nie w `resources/views/orders/list.php` jak zakladal plan. Zmiana w odpowiednim pliku. + +## Issues Encountered + +None + +## Next Phase Readiness + +**Ready:** +- Wyszukiwanie po produkcie dziala na wszystkich listach zamowien + +**Concerns:** +- Przy bardzo duzej liczbie zamowien EXISTS moze byc wolniejszy niz indeks FULLTEXT — obecnie skala jest OK + +**Blockers:** +- None + +--- +*Phase: 73-search-by-product, Plan: 01* +*Completed: 2026-04-07* diff --git a/DOCS/TECH_CHANGELOG.md b/DOCS/TECH_CHANGELOG.md index e25a742..03c18e1 100644 --- a/DOCS/TECH_CHANGELOG.md +++ b/DOCS/TECH_CHANGELOG.md @@ -1,5 +1,12 @@ # Tech Changelog +## 2026-04-07 (Phase 73 - Search by Product, Plan 01) +- `OrdersRepository::buildPaginateFilters()`: dodano EXISTS subquery na `order_items.original_name` do warunku search. + - Alias `oi_s` dla unikniecia konfliktu z `oi_agg` w buildListSql. + - Nowy parametr `:s6` z ta sama wartoscia `%search%`. +- `resources/lang/pl.php`: placeholder filtra search zmieniony na "Szukaj (numer, klient, email, produkt)". +- Brak zmian schematu bazy danych. + ## 2026-04-07 (Phase 72 - Per Page Persistence, Plan 01) - `resources/views/components/table-list.php`: - Dodano klucz localStorage `perPageKey` (`tableList_[path]_[key]_per_page`). diff --git a/resources/lang/pl.php b/resources/lang/pl.php index 6e38a27..f971c7d 100644 --- a/resources/lang/pl.php +++ b/resources/lang/pl.php @@ -117,7 +117,7 @@ return [ 'source_updated_at' => 'Ostatnia zmiana', ], 'filters' => [ - 'search' => 'Szukaj (numer, ID, login, email, klient)', + 'search' => 'Szukaj (numer, klient, email, produkt)', 'source' => 'Zrodlo', 'status' => 'Status', 'payment_status' => 'Platnosc', diff --git a/src/Modules/Orders/OrdersRepository.php b/src/Modules/Orders/OrdersRepository.php index e3deb5d..b7beb8c 100644 --- a/src/Modules/Orders/OrdersRepository.php +++ b/src/Modules/Orders/OrdersRepository.php @@ -95,13 +95,14 @@ final class OrdersRepository $search = trim((string) ($filters['search'] ?? '')); if ($search !== '') { - $where[] = '(o.source_order_id LIKE :s1 OR o.external_order_id LIKE :s2 OR o.customer_login LIKE :s3 OR a.name LIKE :s4 OR a.email LIKE :s5)'; + $where[] = '(o.source_order_id LIKE :s1 OR o.external_order_id LIKE :s2 OR o.customer_login LIKE :s3 OR a.name LIKE :s4 OR a.email LIKE :s5 OR EXISTS (SELECT 1 FROM order_items oi_s WHERE oi_s.order_id = o.id AND oi_s.original_name LIKE :s6))'; $searchVal = '%' . $search . '%'; $params['s1'] = $searchVal; $params['s2'] = $searchVal; $params['s3'] = $searchVal; $params['s4'] = $searchVal; $params['s5'] = $searchVal; + $params['s6'] = $searchVal; } $source = trim((string) ($filters['source'] ?? ''));