Files
adsPRO/.paul/phases/01-products-cl1-column/01-01-SUMMARY.md
2026-04-22 00:38:23 +02:00

5.2 KiB

phase, plan, status, unified_at
phase plan status unified_at
01-products-cl1-column 01 completed 2026-04-22

Summary 01-01 — Products CL1 Column

Co zostało zrobione

Task 1 — Migracja DB

  • Utworzono migrations/028_products_custom_label_1.sql (idempotentna, wzorzec 016)
  • Dodaje products.custom_label_1 VARCHAR(255) NULL DEFAULT NULL AFTER min_roas

Task 2 — Factory (autoload/factory/class.Products.php)

  • is_product_core_field(): dodano custom_label_1 (obok zachowanych custom_label_3/custom_label_4)
  • get_products(): zmieniono sygnaturę o parametr $custom_label_1, SELECT/GROUP BY/order_map przepięte z custom_label_3 na custom_label_1, dodano LIKE search i WHERE filter dla CL1
  • get_roas_bounds(): nowy parametr $custom_label_1, analogiczny filtr WHERE
  • get_records_total_products(): nowy parametr $custom_label_1, analogiczny filtr WHERE
  • Dodano metodę get_distinct_custom_label_1( $client_id ) (kopia metody CL4)

Task 3 — Controller (autoload/controls/class.Products.php)

  • list():
    • Nowa zmienna $filter_cl1 z \S::get('filter_cl1')
    • Przekazana do get_roas_bounds, get_products, get_records_total_products
    • W pętli: pobiera $custom_label_1 przez get_product_data, wylicza $custom_label_1_color (analogiczna paleta: bestseller/deleted/zombie/pla_single/pla/paused)
    • Komórka CL3 (htmlspecialchars) zastąpiona inputem <input class="custom_label_1"> z kolorem
  • Dodano endpoint get_distinct_cl1() → zwraca unikalne wartości CL1 dla klienta
  • Dodano endpoint save_custom_label_1() → zapis + komentarz w historii produktu

Task 4 — Template (templates/products/main_view.php)

  • Nagłówek tabeli: <th>CL3</th><th>CL1</th>
  • Nowy filtr nagłówkowy #products_cl1 przed CL4
  • columnDefs: name: 'custom_label_3'name: 'custom_label_1'
  • ajax.data: dodano d.filter_cl1 = $('#products_cl1').val()
  • Debounce 400ms dla filtra CL1 + localStorage.setItem('products_cl1', ...)
  • Reset filtrów (change #client_id): dodano usuwanie products_cl1 z localStorage i czyszczenie pola
  • Odczyt na starcie: savedCl1 = localStorage.getItem('products_cl1') + load_cl1_suggestions()
  • Pełny blok autocomplete CL1: load_cl1_suggestions, render_cl1_datalist, bind_cl1_datalist, draw.dt hook, listener change #client_id, refresh_cl1_cache_after_save
  • Handler change .custom_label_1 → AJAX POST do /products/save_custom_label_1/ + toast

Zmienione pliki

  • migrations/028_products_custom_label_1.sql (nowy)
  • autoload/factory/class.Products.php
  • autoload/controls/class.Products.php
  • templates/products/main_view.php

Weryfikacja statyczna

  • php -l autoload/factory/class.Products.php — OK
  • php -l autoload/controls/class.Products.php — OK
  • Zero pozostałości custom_label_3 / CL3 w templates/products/main_view.php
  • Zero pozostałości custom_label_3 w rendererze listy kontrolera
  • custom_label_3 zachowany w SupplementalFeed.php (linie 166/171/190/199/202/212) — AC-4
  • custom_label_3 zachowany w is_product_core_field w factory (potrzebny dla get/set z merchant sync)
  • custom_label_1 w field_map GoogleAdsApi.php:438 — już istniało, bez zmian

Weryfikacja runtime (do wykonania)

  • php install.php — zaaplikuj migrację 028
  • Otwórz /products, wybierz klienta — nagłówek pokazuje CL1 zamiast CL3
  • Edytuj wartość CL1 → toast „Custom Label 1 zapisany", po F5 wartość utrzymana
  • Wpisz w filtrze nagłówkowym #products_cl1 — tabela zawęża wyniki po 400ms
  • Datalist (autocomplete) pokazuje poprzednie wartości CL1 dla klienta
  • Generowanie feedu: feeds/supplemental_{client_id}.tsv zawiera kolumnę custom_label_3 (bez zmian)
  • Regresja CL4: wszystkie funkcje CL4 działają jak wcześniej (edycja, filtr, autocomplete, color coding)

AC status

  • AC-1 (migracja) — kod gotowy, wymaga php install.php do aktywacji
  • AC-2 (CL1 zamiast CL3 w widoku) — zrealizowane
  • AC-3 (CL1 pełne zachowanie CL4) — zrealizowane
  • AC-4 (custom_label_3 w feed) — zachowane bez zmian, zweryfikowano grepem

Deviations (odchylenia od planu)

  • DEV-1: columnDefs szerokość CL1 zmieniona z 50px (plan: 1:1 z CL3) na 120px (zgodność z CL4 jako kolumna z inputem). Zasugerowane przez użytkownika po pierwszym renderze — wąski input CL3 był nieczytelny dla edytowalnego pola.
  • DEV-2: Pytanie diagnostyczne user nt. nadpisywania CL4 przez sync Google Ads — potwierdzono czytając Cron.php (linie 1366, 1401, 928) oraz Api.php (407): import GAds pisze tylko client_id/offer_id/name przy INSERT i product_url/merchant_url_not_found przy UPDATE. custom_label_* są nietykane. Jedyny automat piszący do CL4 — SupplementalFeed::refresh_bestseller_labels_for_client — respektuje ręczne etykiety (continue dla wartości ≠ '' i ≠ 'bestseller').

Odroczone / Known issues

  • Istniejące produkty mają pustą wartość custom_label_1 — spodziewane (nowa kolumna)
  • GoogleAdsApi field_map już obsługuje custom_label_1customLabel1, więc ewentualny push do Merchant Center zadziała bez dodatkowych zmian
  • Nie dodano automatyki label-owania dla CL1 (poza scope; bestseller rules nadal wiążą się wyłącznie z CL4)