update
This commit is contained in:
206
.paul/phases/04-products-aggregate-breakdown/04-01-PLAN.md
Normal file
206
.paul/phases/04-products-aggregate-breakdown/04-01-PLAN.md
Normal file
@@ -0,0 +1,206 @@
|
||||
---
|
||||
phase: 04-products-aggregate-breakdown
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- autoload/factory/class.Products.php
|
||||
- autoload/controls/class.Products.php
|
||||
- templates/products/main_view.php
|
||||
autonomous: false
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Na stronie `/products` zmienic tryb listy tak, aby przy braku wybranej grupy reklam (`ad_group_id` puste/0) tabela pokazywala 1 wiersz glowny na produkt z metrykami zagregowanymi, oraz rozwijane podwiersze z pelnym rozbiciem na kampanie i grupy reklam.
|
||||
|
||||
## Purpose
|
||||
Obecny widok miesza poziomy agregacji i utrudnia szybka analize produktu jako calosci. Wiersz glowny ma pokazywac wynik laczny produktu, a szczegoly (kampania/grupa) maja byc dostepne na zadanie przez rozwiniecie.
|
||||
|
||||
## Output
|
||||
- Backend zwracajacy dane zagregowane per produkt oraz szczegoly per scope (kampania/grupa) dla aktualnej strony.
|
||||
- Frontend DataTable z przyciskiem rozwin/zwin i podwierszem z pelnymi metrykami.
|
||||
- Brak mozliwosci edycji w podwierszach (edycja tylko w wierszu glownym).
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/STATE.md
|
||||
@.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
|
||||
|
||||
## Source Files
|
||||
@autoload/factory/class.Products.php
|
||||
@autoload/controls/class.Products.php
|
||||
@templates/products/main_view.php
|
||||
|
||||
## Constraints from user
|
||||
- Podwiersze maja byc zwijane/rozwijane przyciskiem.
|
||||
- Podwiersze maja pokazywac pelny zestaw metryk.
|
||||
- Edycja (`min_roas`, `CL1`, `CL4`, akcje) tylko w wierszu glownym produktu.
|
||||
|
||||
## Notes
|
||||
Repo dziala w trybie ad-hoc PAUL (bez ROADMAP.md / PROJECT.md). Plan tworzony jako kolejna faza ad-hoc.
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Agregacja produktu przy braku wybranej grupy reklam
|
||||
```gherkin
|
||||
Given uzytkownik jest na `/products` i ma wybranego klienta
|
||||
And filtr grupy reklam jest pusty (`#products_ad_group_id` = "")
|
||||
When tabela laduje dane
|
||||
Then kazdy produkt wystepuje tylko raz jako wiersz glowny
|
||||
And metryki wiersza glownego (wyswietlenia, klikniecia, koszt, konwersje, wartosc konwersji, ROAS itd.) sa suma ze wszystkich pasujacych scope
|
||||
```
|
||||
|
||||
## AC-2: Rozwijane podwiersze z pelnym rozbiciem
|
||||
```gherkin
|
||||
Given tabela produktow jest zaladowana w trybie z AC-1
|
||||
When uzytkownik kliknie przycisk rozwin przy produkcie
|
||||
Then pod wierszem glownym pojawia sie podwiersz(e) z rozbiciem per kampania+grupa reklam
|
||||
And kazdy podwiersz pokazuje pelen zestaw kolumn metryk jak w widoku glownym (w formie tylko-do-odczytu)
|
||||
And ponowne klikniecie przycisku zwija szczegoly
|
||||
```
|
||||
|
||||
## AC-3: Edycja tylko w wierszu glownym
|
||||
```gherkin
|
||||
Given produkt ma rozwiniete podwiersze
|
||||
When uzytkownik przeglada podwiersze
|
||||
Then nie ma tam inputow ani przyciskow edycji/usuwania
|
||||
And inputy `min_roas`, `custom_label_1`, `custom_label_4` oraz akcje pozostaja dostepne tylko w wierszu glownym produktu
|
||||
```
|
||||
|
||||
## AC-4: Brak regresji dla filtrowania i wydajnosci listy
|
||||
```gherkin
|
||||
Given nowy tryb agregacji i podwierszy
|
||||
When uzytkownik zmienia filtry (kampania, grupa, search, CL1, CL4), sortowanie i paginacje
|
||||
Then tabela zachowuje poprawna liczbe rekordow i sortowanie
|
||||
And przy wybranej konkretnej grupie reklam zachowanie pozostaje logicznie spojne (bez duplikacji i bez bledow JS/PHP)
|
||||
And endpoint DataTables nie zwraca bledow SQL ani warningow
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Przebudowa warstwy danych na agregat produktu + szczegoly scope</name>
|
||||
<files>autoload/factory/class.Products.php</files>
|
||||
<action>
|
||||
Rozszerzyc factory tak, aby `get_products()` zwracalo dane glownych wierszy agregowane per `p.id` przy `ad_group_id <= 0`, oraz by mozna bylo pobrac szczegoly per kampania/grupa dla zestawu `product_id` z biezacej strony.
|
||||
|
||||
Zakres:
|
||||
- Utrzymac medoo/prepared statements.
|
||||
- Dostosowac `GROUP BY` i logike licznikow tak, aby `recordsTotal` liczyl produkty, a nie scope, gdy nie ma wybranej grupy.
|
||||
- Dodac/metody pomocnicze do pobrania breakdownu dla listy produktow bez N+1 (jedno zapytanie z `IN (...)` + grupowanie po stronie PHP).
|
||||
- Utrzymac zgodnosc sortowania kolumn DataTables dla wiersza glownego.
|
||||
|
||||
Unikac:
|
||||
- SQL sklejanych stringiem bez parametrow.
|
||||
- Dublowania tej samej logiki obliczen metryk w wielu metodach bez wspolnego helpera.
|
||||
</action>
|
||||
<verify>
|
||||
- `php -l autoload/factory/class.Products.php`
|
||||
- Szybki test endpointu `/products/get_products/` dla: (a) ad_group_id="", (b) ad_group_id>0 i porownanie liczby rekordow.
|
||||
- Brak warningow SQL / PHP w logu.
|
||||
</verify>
|
||||
<done>AC-1 i czesc AC-4 spelnione: poprawna agregacja i poprawne liczenie rekordow.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Adaptacja kontrolera odpowiedzi DataTables pod dane glowne + breakdown</name>
|
||||
<files>autoload/controls/class.Products.php</files>
|
||||
<action>
|
||||
W `get_products()` przebudowac format odpowiedzi JSON tak, aby kazdy wiersz glowny produktu zawieral identyfikator i dane potrzebne do renderu rozwijanych podwierszy (np. `row_meta` / `breakdown_rows`).
|
||||
|
||||
Zakres:
|
||||
- Zachowac obecne formatowanie komorek glownych (ROAS bar, warningi, linki, akcje).
|
||||
- Dla podwierszy zwracac pelne metryki, ale bez kontrolnych elementow edycji.
|
||||
- Zachowac kompatybilnosc z istniejacymi handlerami JS, ktore operuja na kolumnach glownych.
|
||||
|
||||
Unikac:
|
||||
- Wykonywania dodatkowego zapytania DB na kazdy pojedynczy wiersz.
|
||||
- Mieszania HTML edycyjnego do danych podwierszy.
|
||||
</action>
|
||||
<verify>
|
||||
- `php -l autoload/controls/class.Products.php`
|
||||
- Odpowiedz endpointu zawiera dane breakdown tylko dla produktow z biezacej strony i nie psuje `recordsTotal`, `recordsFiltered`, `data`.
|
||||
</verify>
|
||||
<done>AC-2 i AC-3 backend-ready: API dostarcza dane do podwierszy i oddziela je od edycji.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: UI DataTable - przycisk rozwin i render podwierszy</name>
|
||||
<files>templates/products/main_view.php</files>
|
||||
<action>
|
||||
Dodac w tabeli produktow obsluge rozwijanych podwierszy:
|
||||
- Przycisk w wierszu glownym (rozwin/zwin) widoczny tylko gdy sa szczegoly.
|
||||
- Render child-row (DataTables child row) z pelnym zestawem metryk dla kampania+grupa.
|
||||
- Podwiersze readonly: bez inputow i bez akcji edycyjnych/usuwania.
|
||||
- Zachowac obecne akcje edycyjne tylko dla glownego wiersza.
|
||||
|
||||
Dodatkowo:
|
||||
- Dodac czytelne style dla child-row (wizualnie odroznione od glownej tabeli).
|
||||
- Nie przekraczac 3 poziomow zagniezdzenia - wydzielic helpery JS do budowy HTML podwierszy i toggla.
|
||||
</action>
|
||||
<verify>
|
||||
- `php -l templates/products/main_view.php`
|
||||
- Manual: rozwin/zwin dziala, brak bledow w konsoli, sortowanie/paginacja dalej dziala.
|
||||
</verify>
|
||||
<done>AC-2, AC-3 i pozostala czesc AC-4 spelnione po stronie UI.</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>
|
||||
Nowy widok listy produktow: glowny agregat per produkt + rozwijane podwiersze kampania/grupa z pelnymi metrykami, bez edycji w podwierszach.
|
||||
</what-built>
|
||||
<how-to-verify>
|
||||
1. Otworz `/products`, wybierz klienta.
|
||||
2. Ustaw kampanie dowolnie, ale pozostaw "Grupa reklam" na "- wszystkie grupy -".
|
||||
3. Potwierdz: kazdy produkt jest raz jako wiersz glowny, metryki sa sumaryczne.
|
||||
4. Kliknij przycisk rozwin przy kilku produktach.
|
||||
5. Potwierdz: podwiersze pokazuja pelne metryki per kampania/grupa, bez inputow i bez akcji.
|
||||
6. Zweryfikuj, ze edycja (`min_roas`, `CL1`, `CL4`) dziala tylko w wierszu glownym.
|
||||
7. Sprawdz sortowanie, paginacje i filtry tekstowe.
|
||||
8. Sprawdz konsolę przegladarki i logi PHP: brak nowych bledow.
|
||||
</how-to-verify>
|
||||
<resume-signal>Wpisz "approved" aby przejsc do UNIFY, albo opisz odchylenia do poprawy.</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Migracje bazy i schemat tabel.
|
||||
- Logika niezalezna od /products (inne kontrolery/widoki).
|
||||
- Mechanika CSRF/sesji i routing aplikacji.
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Tylko zakladka `/products`.
|
||||
- Tylko zachowanie listy i sposob prezentacji danych.
|
||||
- Bez nowych funkcji biznesowych poza agregacja + podwiersze.
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `php -l autoload/factory/class.Products.php`
|
||||
- [ ] `php -l autoload/controls/class.Products.php`
|
||||
- [ ] `php -l templates/products/main_view.php`
|
||||
- [ ] Manualna weryfikacja AC-1..AC-4
|
||||
- [ ] Brak nowych bledow JS/PHP/SQL
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Widok przy pustym `ad_group_id` pokazuje agregat 1 produkt = 1 wiersz glowny.
|
||||
- Podwiersze sa rozwijane przyciskiem i pokazuja pelne metryki per kampania/grupa.
|
||||
- Edycja pozostaje tylko w wierszu glownym.
|
||||
- Brak regresji filtrow, sortowania i paginacji.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/04-products-aggregate-breakdown/04-01-SUMMARY.md`.
|
||||
</output>
|
||||
138
.paul/phases/04-products-aggregate-breakdown/04-01-SUMMARY.md
Normal file
138
.paul/phases/04-products-aggregate-breakdown/04-01-SUMMARY.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
phase: 04-products-aggregate-breakdown
|
||||
plan: 01
|
||||
subsystem: ui
|
||||
tags: [products, datatables, aggregation, breakdown, php, jquery]
|
||||
|
||||
requires:
|
||||
- phase: 03-products-all-campaigns-view
|
||||
provides: stable products scope filters and all-campaign selector behavior
|
||||
|
||||
provides:
|
||||
- Aggregated product rows (1 product = 1 row when no ad group is selected)
|
||||
- Expandable campaign/ad-group breakdown rows with full metrics
|
||||
- Edit actions kept only on the main product row
|
||||
|
||||
affects:
|
||||
- products table data contract from /products/get_products/
|
||||
- products DataTable row rendering and child-row behavior
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- aggregate main row + readonly scope breakdown in child row
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- autoload/factory/class.Products.php
|
||||
- autoload/controls/class.Products.php
|
||||
- templates/products/main_view.php
|
||||
|
||||
key-decisions:
|
||||
- "Use one batch breakdown query for page product IDs to avoid N+1"
|
||||
- "Expose breakdown as row_meta in DataTables payload"
|
||||
- "Keep inline edit fields only in parent row"
|
||||
|
||||
patterns-established:
|
||||
- "When scope is not narrowed to ad_group_id, aggregate per product and show scope details on demand"
|
||||
|
||||
duration: ~23min
|
||||
started: 2026-04-25T17:05:05+02:00
|
||||
completed: 2026-04-25T17:28:08+02:00
|
||||
---
|
||||
|
||||
# Phase 4 Plan 01: Products Aggregate Breakdown (Summary)
|
||||
|
||||
**Na /products wdrozono model: glowny agregat per produkt + rozwijane readonly podwiersze kampania/grupa z pelnymi metrykami.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~23 min |
|
||||
| Started | 2026-04-25T17:05:05+02:00 |
|
||||
| Completed | 2026-04-25T17:28:08+02:00 |
|
||||
| Tasks | 4/4 (3 auto + 1 human-verify) |
|
||||
| Files modified | 3 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Agregacja produktu bez wybranej grupy | Pass | Backend grupuje po `p.id`, recordsTotal liczy DISTINCT produktow |
|
||||
| AC-2: Rozwijane podwiersze z pelnym rozbiciem | Pass | Child-row DataTables renderuje pelny zestaw metryk per kampania+grupa |
|
||||
| AC-3: Edycja tylko w wierszu glownym | Pass | Podwiersze sa readonly; inputy i akcje zostaja w parent row |
|
||||
| AC-4: Brak regresji filtrowania/listy | Pass | User checkpoint `approved`; endpoint i lintery bez bledow |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Przebudowano zapytania listy produktow tak, aby glowny wynik byl agregowany per produkt.
|
||||
- Dodano zbiorcze pobieranie breakdownu scope dla aktualnej strony (bez N+1).
|
||||
- Rozszerzono payload DataTables o `row_meta.breakdown_rows` i dodano UI rozwin/zwin z tabela szczegolow.
|
||||
|
||||
## Task Commits
|
||||
|
||||
Brak commitu fazowego na tym etapie (working tree zawiera rowniez inne lokalne zmiany projektu).
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `autoload/factory/class.Products.php` | Modified (+148/-101) | Agregacja per produkt, wspolny filtr, breakdown query, records count |
|
||||
| `autoload/controls/class.Products.php` | Modified (+53/-19) | Dolaczenie breakdownu do odpowiedzi i row_meta dla DataTables |
|
||||
| `templates/products/main_view.php` | Modified (+162/-1) | UI toggle, child-row render, style breakdownu |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Batch breakdown query for page products | Ogranicza obciazenie DB i unika N+1 | Stabilna wydajnosc przy paginacji |
|
||||
| Keep edit controls only in parent row | Zgodnosc z wymaganiem usera | Jasny podzial: edycja vs analiza |
|
||||
| Render breakdown in DataTables child row | Minimalny blast radius dla istniejacego ukladu kolumn | Niska regresyjnosc UI |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 1 | Niski, bez zmiany zakresu |
|
||||
| Scope additions | 0 | Brak |
|
||||
| Deferred | 0 | Brak |
|
||||
|
||||
**Total impact:** Plan zrealizowany zgodnie z zakresem; jedna techniczna korekta podczas implementacji.
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
1. Tymczasowe uszkodzenie pliku kontrolera podczas edycji skryptowej
|
||||
- Found during: Task 2
|
||||
- Issue: `autoload/controls/class.Products.php` zostal chwilowo uszkodzony (parse error)
|
||||
- Fix: przywrocenie pliku z HEAD i ponowne, punktowe patche
|
||||
- Verification: `php -l autoload/controls/class.Products.php` OK
|
||||
|
||||
### Deferred Items
|
||||
|
||||
Brak.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| Konflikty przy automatycznej podmianie wiekszego bloku kontrolera | Zmiana strategii na male, precyzyjne patche i ponowna walidacja |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Kontrakt endpointu `/products/get_products/` obsluguje agregat + breakdown.
|
||||
- UI listy wspiera drill-down bez naruszania obecnych akcji.
|
||||
|
||||
**Concerns:**
|
||||
- W working tree sa tez niezalezne lokalne zmiany (`.vscode/ftp-kr.sync.cache.json`).
|
||||
|
||||
**Blockers:**
|
||||
- Brak.
|
||||
|
||||
---
|
||||
*Phase: 04-products-aggregate-breakdown, Plan: 01*
|
||||
*Completed: 2026-04-25*
|
||||
Reference in New Issue
Block a user