feat(search-by-product): extend order search to include product names
Added EXISTS subquery on order_items.original_name to the search filter in OrdersRepository::buildPaginateFilters(). Users can now find orders by typing a product name in the search field. Updated search placeholder to reflect the new capability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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] 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] 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] 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
|
- [ ] Eliminacja zduplikowanego kodu: SslCertificateResolver, ToggleableRepositoryTrait, RedirectPathResolver, ReceiptService — Phase 68
|
||||||
|
|
||||||
### Active (In Progress)
|
### Active (In Progress)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ Wersja mobilna aplikacji, modul po module. Cel: pelna uzywalnosc orderPRO na tel
|
|||||||
| 70 | Receipt Shipping Cost | 1/1 | Complete |
|
| 70 | Receipt Shipping Cost | 1/1 | Complete |
|
||||||
| 71 | Attributes Import | 1/1 | Complete |
|
| 71 | Attributes Import | 1/1 | Complete |
|
||||||
| 72 | Per Page Persistence | 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 Orders List | - | Not started |
|
||||||
| TBD | Mobile Order Details | - | Not started |
|
| TBD | Mobile Order Details | - | Not started |
|
||||||
| TBD | Mobile Settings | - | Not started |
|
| TBD | Mobile Settings | - | Not started |
|
||||||
|
|||||||
@@ -5,19 +5,19 @@
|
|||||||
See: .paul/PROJECT.md (updated 2026-04-07)
|
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.
|
**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
|
## Current Position
|
||||||
|
|
||||||
Milestone: v3.0 Mobile Responsive - In progress
|
Milestone: v3.0 Mobile Responsive - In progress
|
||||||
Phase: 72 (Per Page Persistence) — Complete
|
Phase: 73 (Search by Product) — Complete
|
||||||
Plan: 72-01 unified
|
Plan: 73-01 unified
|
||||||
Status: Loop complete, ready for next PLAN
|
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:
|
Progress:
|
||||||
- Milestone: [########..] ~75%
|
- Milestone: [########..] ~76%
|
||||||
- Phase 72: [##########] 100%
|
- Phase 73: [##########] 100%
|
||||||
|
|
||||||
## Loop Position
|
## Loop Position
|
||||||
|
|
||||||
@@ -30,11 +30,11 @@ PLAN --> APPLY --> UNIFY
|
|||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-07
|
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
|
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
|
## Git State
|
||||||
|
|
||||||
Last commit: 6d0905d
|
Last commit: 24df01c
|
||||||
Branch: main
|
Branch: main
|
||||||
|
|||||||
129
.paul/phases/73-search-by-product/73-01-PLAN.md
Normal file
129
.paul/phases/73-search-by-product/73-01-PLAN.md
Normal file
@@ -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
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
## 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.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
## Source Files
|
||||||
|
@src/Modules/Orders/OrdersRepository.php (linie 91-105 buildPaginateFilters, 48-54 countSql)
|
||||||
|
@resources/views/orders/list.php
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<acceptance_criteria>
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
||||||
|
|
||||||
|
</acceptance_criteria>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Dodanie wyszukiwania po nazwie produktu</name>
|
||||||
|
<files>src/Modules/Orders/OrdersRepository.php</files>
|
||||||
|
<action>
|
||||||
|
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.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Zapytanie SQL wykonuje sie poprawnie. Test: wyszukanie "Tabliczki" zwraca zamowienia z takim produktem.
|
||||||
|
</verify>
|
||||||
|
<done>AC-1, AC-2, AC-3 satisfied</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Aktualizacja placeholder inputa</name>
|
||||||
|
<files>resources/views/orders/list.php</files>
|
||||||
|
<action>
|
||||||
|
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.
|
||||||
|
</action>
|
||||||
|
<verify>Placeholder inputa zawiera slowo "produkt"</verify>
|
||||||
|
<done>AC-4 satisfied</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<boundaries>
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
</boundaries>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
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"
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- Pole szukaj obsluguje nazwy produktow
|
||||||
|
- Brak regresji w istniejacym wyszukiwaniu
|
||||||
|
- Brak duplikatow wynikow
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.paul/phases/73-search-by-product/73-01-SUMMARY.md`
|
||||||
|
</output>
|
||||||
99
.paul/phases/73-search-by-product/73-01-SUMMARY.md
Normal file
99
.paul/phases/73-search-by-product/73-01-SUMMARY.md
Normal file
@@ -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*
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
# Tech Changelog
|
# 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)
|
## 2026-04-07 (Phase 72 - Per Page Persistence, Plan 01)
|
||||||
- `resources/views/components/table-list.php`:
|
- `resources/views/components/table-list.php`:
|
||||||
- Dodano klucz localStorage `perPageKey` (`tableList_[path]_[key]_per_page`).
|
- Dodano klucz localStorage `perPageKey` (`tableList_[path]_[key]_per_page`).
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ return [
|
|||||||
'source_updated_at' => 'Ostatnia zmiana',
|
'source_updated_at' => 'Ostatnia zmiana',
|
||||||
],
|
],
|
||||||
'filters' => [
|
'filters' => [
|
||||||
'search' => 'Szukaj (numer, ID, login, email, klient)',
|
'search' => 'Szukaj (numer, klient, email, produkt)',
|
||||||
'source' => 'Zrodlo',
|
'source' => 'Zrodlo',
|
||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
'payment_status' => 'Platnosc',
|
'payment_status' => 'Platnosc',
|
||||||
|
|||||||
@@ -95,13 +95,14 @@ final class OrdersRepository
|
|||||||
|
|
||||||
$search = trim((string) ($filters['search'] ?? ''));
|
$search = trim((string) ($filters['search'] ?? ''));
|
||||||
if ($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 . '%';
|
$searchVal = '%' . $search . '%';
|
||||||
$params['s1'] = $searchVal;
|
$params['s1'] = $searchVal;
|
||||||
$params['s2'] = $searchVal;
|
$params['s2'] = $searchVal;
|
||||||
$params['s3'] = $searchVal;
|
$params['s3'] = $searchVal;
|
||||||
$params['s4'] = $searchVal;
|
$params['s4'] = $searchVal;
|
||||||
$params['s5'] = $searchVal;
|
$params['s5'] = $searchVal;
|
||||||
|
$params['s6'] = $searchVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
$source = trim((string) ($filters['source'] ?? ''));
|
$source = trim((string) ($filters['source'] ?? ''));
|
||||||
|
|||||||
Reference in New Issue
Block a user