From cad3a20bb58460f15771f87b6a481b1d6446d312 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Wed, 11 Mar 2026 00:11:24 +0100 Subject: [PATCH] feat: Add custom_label_4 handling in API and update documentation for new endpoints --- .serena/project.yml | 5 +++ .vscode/ftp-kr.sync.cache.json | 32 +++++++++++--- api.php | 59 ++++++++++++++++++++++---- docs/api-public-product-management.md | 61 +++++++++++++++++++++++++-- 4 files changed, 138 insertions(+), 19 deletions(-) diff --git a/.serena/project.yml b/.serena/project.yml index 80c46cd..f88471b 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -127,3 +127,8 @@ language_backend: # list of regex patterns which, when matched, mark a memory entry as read‑only. # Extends the list from the global configuration, merging the two lists. read_only_memory_patterns: [] + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index 885e133..fad2102 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -71,8 +71,8 @@ }, "class.Api.php": { "type": "-", - "size": 25694, - "lmtime": 1772667215646, + "size": 24772, + "lmtime": 1773134827335, "modified": false }, "class.CampaignAlerts.php": { @@ -101,8 +101,8 @@ }, "class.Cron.php": { "type": "-", - "size": 185177, - "lmtime": 1772899996837, + "size": 184735, + "lmtime": 1773134833337, "modified": false }, "class.FacebookAds.php": { @@ -854,6 +854,12 @@ "lmtime": 0, "modified": false }, + "check_active_date_logs.php": { + "type": "-", + "size": 928, + "lmtime": 1771850708365, + "modified": false + }, "__check_adgroups.php": { "type": "-", "size": 1579, @@ -884,6 +890,18 @@ "lmtime": 1771850676855, "modified": false }, + "debug_bestseller_client5.php": { + "type": "-", + "size": 4319, + "lmtime": 1773133921091, + "modified": false + }, + "debug_bestseller_client5_remote.php": { + "type": "-", + "size": 5426, + "lmtime": 1773133998372, + "modified": false + }, "debug_clients.php": { "type": "-", "size": 1274, @@ -914,10 +932,10 @@ "lmtime": 0, "modified": false }, - "check_active_date_logs.php": { + "debug_bestseller_roas_compare.php": { "type": "-", - "size": 928, - "lmtime": 1771850708365, + "size": 1114, + "lmtime": 1773134018725, "modified": false } }, diff --git a/api.php b/api.php index 15f1647..5316ed8 100644 --- a/api.php +++ b/api.php @@ -58,7 +58,7 @@ function api_validate_api_key( $mdb ) function api_get_product_by_offer_and_client( $mdb, $offer_id, $client_id ) { return $mdb -> query( - 'SELECT p.id, p.name, p.title, p.google_product_category + 'SELECT p.id, p.name, p.title, p.google_product_category, p.custom_label_4 FROM products p JOIN clients cl ON p.client_id = cl.id WHERE p.offer_id = :offer_id @@ -203,26 +203,67 @@ if ( \S::get( 'action' ) == 'product_custom_label_4_set' ) { api_validate_api_key( $mdb ); - $offer_id = trim( \S::get( 'offer_id' ) ); - $client_id_param = trim( \S::get( 'client_id' ) ); - $custom_label_4 = trim( \S::get( 'custom_label_4' ) ); + $offer_id = trim( (string) \S::get( 'offer_id' ) ); + $client_id_param = (int) \S::get( 'client_id' ); + $custom_label_4 = trim( (string) ( \S::get( 'custom_label_4' ) ?? \S::get( 'value' ) ?? '' ) ); - if ( !$offer_id || !$client_id_param ) + if ( $offer_id === '' || $client_id_param <= 0 ) { api_json_response( [ 'result' => 'error', 'message' => 'Missing required params: offer_id, client_id' ], 422 ); } - $product = api_get_product_by_offer_and_client( $mdb, $offer_id, (int) $client_id_param ); + $product = api_get_product_by_offer_and_client( $mdb, $offer_id, $client_id_param ); if ( !$product ) { api_json_response( [ 'result' => 'error', 'message' => 'Product not found' ], 404 ); } - \factory\Products::set_product_data( $product['id'], 'custom_label_4', $custom_label_4 ); - \factory\Products::add_product_comment( $product['id'], 'Zmiana etykiety 4 na: ' . $custom_label_4 . ' (API)' ); + $update_result = \factory\Products::set_product_data( (int) $product['id'], 'custom_label_4', $custom_label_4 ); - api_json_response( [ 'result' => 'ok' ] ); + if ( !$update_result ) + { + api_json_response( [ 'result' => 'error', 'message' => 'Failed to update custom_label_4' ], 500 ); + } + + \factory\Products::add_product_comment( (int) $product['id'], 'Zmiana etykiety 4 na: ' . ( $custom_label_4 !== '' ? $custom_label_4 : '(puste)' ) . ' (API)' ); + + api_json_response( [ + 'result' => 'ok', + 'product_id' => (int) $product['id'], + 'offer_id' => $offer_id, + 'client_id' => $client_id_param, + 'custom_label_4' => $custom_label_4 + ] ); +} + +// Odczyt custom_label_4 dla produktu przez API +if ( \S::get( 'action' ) == 'product_custom_label_4_get' ) +{ + api_validate_api_key( $mdb ); + + $offer_id = trim( (string) \S::get( 'offer_id' ) ); + $client_id_param = (int) \S::get( 'client_id' ); + + if ( $offer_id === '' || $client_id_param <= 0 ) + { + api_json_response( [ 'result' => 'error', 'message' => 'Missing required params: offer_id, client_id' ], 422 ); + } + + $product = api_get_product_by_offer_and_client( $mdb, $offer_id, $client_id_param ); + + if ( !$product ) + { + api_json_response( [ 'result' => 'error', 'message' => 'Product not found' ], 404 ); + } + + api_json_response( [ + 'result' => 'ok', + 'product_id' => (int) $product['id'], + 'offer_id' => $offer_id, + 'client_id' => $client_id_param, + 'custom_label_4' => trim( (string) ( $product['custom_label_4'] ?? '' ) ) + ] ); } // Zmiana tytulu produktu przez API diff --git a/docs/api-public-product-management.md b/docs/api-public-product-management.md index 9a1e713..df856af 100644 --- a/docs/api-public-product-management.md +++ b/docs/api-public-product-management.md @@ -304,7 +304,7 @@ Bledy specyficzne: - Brak parametru identyfikujacego klienta: `422` z `"Missing required param: client_id, google_ads_id or merchant_id"` - Klient nie znaleziony: `404` z `"Client not found"` -### 4.6 Ustawienie custom_label_4 (istniejacy endpoint) +### 4.6 Ustawienie custom_label_4 - `action=product_custom_label_4_set` - Cel: zapisuje `products.custom_label_4` @@ -313,7 +313,13 @@ Parametry: - `api_key` (string, wymagany) - `offer_id` (string, wymagany) - `client_id` (int, wymagany) -- `custom_label_4` (string, opcjonalny) +- `custom_label_4` (string, opcjonalny) - wartosc etykiety; alias: `value` + +Uwagi: +- wartosc jest przycinana (`trim`) +- pusta wartosc ustawia pusty string (czyszczenie pola) +- zmiana zapisuje komentarz techniczny w `products_comments` +- jesli zapis sie nie powiedzie, API zwraca blad 500 Przyklad: @@ -330,7 +336,55 @@ Przyklad odpowiedzi: ```json { - "result": "ok" + "result": "ok", + "product_id": 987, + "offer_id": "SKU-123", + "client_id": 12, + "custom_label_4": "bestseller" +} +``` + +### 4.6b Odczyt custom_label_4 + +- `action=product_custom_label_4_get` +- Cel: odczytuje `products.custom_label_4` + +Parametry: +- `api_key` (string, wymagany) +- `offer_id` (string, wymagany) +- `client_id` (int, wymagany) + +Przyklad: + +```bash +curl -G "https://example.com/api.php" \ + --data-urlencode "action=product_custom_label_4_get" \ + --data-urlencode "api_key=YOUR_API_KEY" \ + --data-urlencode "client_id=12" \ + --data-urlencode "offer_id=SKU-123" +``` + +Przyklad odpowiedzi: + +```json +{ + "result": "ok", + "product_id": 987, + "offer_id": "SKU-123", + "client_id": 12, + "custom_label_4": "bestseller" +} +``` + +Jesli etykieta nie jest ustawiona: + +```json +{ + "result": "ok", + "product_id": 987, + "offer_id": "SKU-123", + "client_id": 12, + "custom_label_4": "" } ``` @@ -478,6 +532,7 @@ Przy integracji AI zawsze ustawiaj jawnie `action` i weryfikuj, czy odpowiedz to - Zawsze wysylaj `api_key`, `action`, `client_id`, `offer_id`. - Po `product_title_set` od razu wywolaj `product_title_changed_check`. - Po `product_google_category_set` od razu wywolaj `product_google_category_get`. +- Po `product_custom_label_4_set` od razu wywolaj `product_custom_label_4_get`. - Traktuj `null` jako brak wartosci. - Przy statusach `401`, `404`, `422` przerywaj workflow i zwracaj czytelny blad operatorowi.