--- 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 --- ## 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). ## 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. ## 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 ``` Task 1: Przebudowa warstwy danych na agregat produktu + szczegoly scope autoload/factory/class.Products.php 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. - `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. AC-1 i czesc AC-4 spelnione: poprawna agregacja i poprawne liczenie rekordow. Task 2: Adaptacja kontrolera odpowiedzi DataTables pod dane glowne + breakdown autoload/controls/class.Products.php 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. - `php -l autoload/controls/class.Products.php` - Odpowiedz endpointu zawiera dane breakdown tylko dla produktow z biezacej strony i nie psuje `recordsTotal`, `recordsFiltered`, `data`. AC-2 i AC-3 backend-ready: API dostarcza dane do podwierszy i oddziela je od edycji. Task 3: UI DataTable - przycisk rozwin i render podwierszy templates/products/main_view.php 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. - `php -l templates/products/main_view.php` - Manual: rozwin/zwin dziala, brak bledow w konsoli, sortowanie/paginacja dalej dziala. AC-2, AC-3 i pozostala czesc AC-4 spelnione po stronie UI. Nowy widok listy produktow: glowny agregat per produkt + rozwijane podwiersze kampania/grupa z pelnymi metrykami, bez edycji w podwierszach. 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. Wpisz "approved" aby przejsc do UNIFY, albo opisz odchylenia do poprawy. ## 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. 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 - 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. After completion, create `.paul/phases/04-products-aggregate-breakdown/04-01-SUMMARY.md`.