From 8e2e070eb7018c555e8177e867ec6926228271f7 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Tue, 24 Feb 2026 13:32:25 +0100 Subject: [PATCH] =?UTF-8?q?ver.=200.320:=20API=20s=C5=82owniki=20=E2=80=94?= =?UTF-8?q?=20ensure=5Fproducer;=20ProductRepository=20=E2=80=94=20produce?= =?UTF-8?q?r=5Fname=20w=20odpowiedzi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DictionariesApiController: nowy endpoint POST ensure_producer (znajdź lub utwórz producenta) - ProducerRepository: metoda ensureProducerForApi() - ProductRepository: pole producer_name w odpowiedzi GET product - ApiRouter: wstrzyknięto ProducerRepository do DictionariesApiController - Zaktualizowano docs/API.md Co-Authored-By: Claude Sonnet 4.6 --- .../Domain/Producer/ProducerRepository.php | 30 ++++++++++++++++ autoload/Domain/Product/ProductRepository.php | 16 +++++++++ autoload/api/ApiRouter.php | 3 +- .../Controllers/DictionariesApiController.php | 36 ++++++++++++++++++- docs/API.md | 28 ++++++++++++++- .../DictionariesApiControllerTest.php | 6 +++- updates/versions.php | 2 +- 7 files changed, 116 insertions(+), 5 deletions(-) diff --git a/autoload/Domain/Producer/ProducerRepository.php b/autoload/Domain/Producer/ProducerRepository.php index 9bee873..d91abb7 100644 --- a/autoload/Domain/Producer/ProducerRepository.php +++ b/autoload/Domain/Producer/ProducerRepository.php @@ -357,4 +357,34 @@ class ProducerRepository return 0; } + + /** + * Znajdź producenta po nazwie lub utwórz nowego (dla API). + * + * @return array{id: int, created: bool} + */ + public function ensureProducerForApi(string $name): array + { + $name = trim($name); + if ($name === '') { + return ['id' => 0, 'created' => false]; + } + + $existing = $this->db->get('pp_shop_producer', 'id', ['name' => $name]); + if (!empty($existing)) { + return ['id' => (int)$existing, 'created' => false]; + } + + $this->db->insert('pp_shop_producer', [ + 'name' => $name, + 'status' => 1, + 'img' => null, + ]); + $id = (int)$this->db->id(); + if ($id <= 0) { + return ['id' => 0, 'created' => false]; + } + + return ['id' => $id, 'created' => true]; + } } diff --git a/autoload/Domain/Product/ProductRepository.php b/autoload/Domain/Product/ProductRepository.php index 3ab2683..b7884c3 100644 --- a/autoload/Domain/Product/ProductRepository.php +++ b/autoload/Domain/Product/ProductRepository.php @@ -657,6 +657,7 @@ class ProductRepository 'set_id' => $product['set_id'] !== null ? (int)$product['set_id'] : null, 'product_unit_id' => $product['product_unit_id'] !== null ? (int)$product['product_unit_id'] : null, 'producer_id' => $product['producer_id'] !== null ? (int)$product['producer_id'] : null, + 'producer_name' => $this->resolveProducerName($product['producer_id']), 'date_add' => $product['date_add'], 'date_modify' => $product['date_modify'], ]; @@ -1121,6 +1122,21 @@ class ProductRepository return $result; } + /** + * Zwraca nazwę producenta po ID (null jeśli brak). + * + * @param mixed $producerId + * @return string|null + */ + private function resolveProducerName($producerId): ?string + { + if (empty($producerId)) { + return null; + } + $name = $this->db->get('pp_shop_producer', 'name', ['id' => (int)$producerId]); + return ($name !== false && $name !== null) ? (string)$name : null; + } + /** * Szczegóły produktu (admin) — zastępuje factory product_details(). */ diff --git a/autoload/api/ApiRouter.php b/autoload/api/ApiRouter.php index ef8aedd..572d183 100644 --- a/autoload/api/ApiRouter.php +++ b/autoload/api/ApiRouter.php @@ -100,7 +100,8 @@ class ApiRouter $transportRepo = new \Domain\Transport\TransportRepository($db); $paymentRepo = new \Domain\PaymentMethod\PaymentMethodRepository($db); $attrRepo = new \Domain\Attribute\AttributeRepository($db); - return new Controllers\DictionariesApiController($statusRepo, $transportRepo, $paymentRepo, $attrRepo); + $producerRepo = new \Domain\Producer\ProducerRepository($db); + return new Controllers\DictionariesApiController($statusRepo, $transportRepo, $paymentRepo, $attrRepo, $producerRepo); }, ]; } diff --git a/autoload/api/Controllers/DictionariesApiController.php b/autoload/api/Controllers/DictionariesApiController.php index b431c4f..ff21ddc 100644 --- a/autoload/api/Controllers/DictionariesApiController.php +++ b/autoload/api/Controllers/DictionariesApiController.php @@ -3,6 +3,7 @@ namespace api\Controllers; use api\ApiRouter; use Domain\Attribute\AttributeRepository; +use Domain\Producer\ProducerRepository; use Domain\ShopStatus\ShopStatusRepository; use Domain\Transport\TransportRepository; use Domain\PaymentMethod\PaymentMethodRepository; @@ -13,17 +14,20 @@ class DictionariesApiController private $transportRepo; private $paymentRepo; private $attrRepo; + private $producerRepo; public function __construct( ShopStatusRepository $statusRepo, TransportRepository $transportRepo, PaymentMethodRepository $paymentRepo, - AttributeRepository $attrRepo + AttributeRepository $attrRepo, + ProducerRepository $producerRepo ) { $this->statusRepo = $statusRepo; $this->transportRepo = $transportRepo; $this->paymentRepo = $paymentRepo; $this->attrRepo = $attrRepo; + $this->producerRepo = $producerRepo; } public function statuses(): void @@ -171,4 +175,34 @@ class DictionariesApiController 'created' => !empty($result['created']), ]); } + + public function ensure_producer(): void + { + if (!ApiRouter::requireMethod('POST')) { + return; + } + + $body = ApiRouter::getJsonBody(); + if (!is_array($body)) { + ApiRouter::sendError('BAD_REQUEST', 'Missing or invalid JSON body', 400); + return; + } + + $name = trim((string) ($body['name'] ?? '')); + if ($name === '') { + ApiRouter::sendError('BAD_REQUEST', 'Missing name', 400); + return; + } + + $result = $this->producerRepo->ensureProducerForApi($name); + if ((int) ($result['id'] ?? 0) <= 0) { + ApiRouter::sendError('INTERNAL_ERROR', 'Failed to ensure producer', 500); + return; + } + + ApiRouter::sendSuccess([ + 'id' => (int) ($result['id'] ?? 0), + 'created' => !empty($result['created']), + ]); + } } diff --git a/docs/API.md b/docs/API.md index faf0601..963de7f 100644 --- a/docs/API.md +++ b/docs/API.md @@ -219,6 +219,7 @@ Odpowiedz: "set_id": null, "product_unit_id": 1, "producer_id": 3, + "producer_name": "Nike", "date_add": "2026-01-15 10:00:00", "date_modify": "2026-02-19 12:00:00", "languages": { @@ -472,6 +473,31 @@ GET api.php?endpoint=dictionaries&action=attributes Zwraca aktywne atrybuty z wartosciami i wielojezycznymi nazwami. +#### Znajdz lub utworz producenta +``` +POST api.php?endpoint=dictionaries&action=ensure_producer +Content-Type: application/json + +{ + "name": "Nike" +} +``` + +Zwraca istniejacego producenta po nazwie lub tworzy nowego. Uzyc przed tworzeniem produktu, jesli producent moze nie istniec. + +Odpowiedz: +```json +{ + "status": "ok", + "data": { + "id": 5, + "created": false + } +} +``` + +`created: true` gdy producent zostal nowo dodany, `false` gdy juz istnial. + Odpowiedz: ```json { @@ -518,4 +544,4 @@ UPDATE pp_settings SET value = 'twoj-klucz-api' WHERE param = 'api_key'; - Kontrolery: `autoload/api/Controllers/` - `OrdersApiController` — zamowienia (5 akcji) - `ProductsApiController` — produkty (8 akcji: list, get, create, update, variants, create_variant, update_variant, delete_variant) - - `DictionariesApiController` — slowniki (4 akcje: statuses, transports, payment_methods, attributes) + - `DictionariesApiController` — slowniki (5 akcji: statuses, transports, payment_methods, attributes, ensure_producer) diff --git a/tests/Unit/api/Controllers/DictionariesApiControllerTest.php b/tests/Unit/api/Controllers/DictionariesApiControllerTest.php index da4d3bb..ffa107b 100644 --- a/tests/Unit/api/Controllers/DictionariesApiControllerTest.php +++ b/tests/Unit/api/Controllers/DictionariesApiControllerTest.php @@ -4,6 +4,7 @@ namespace Tests\Unit\api\Controllers; use PHPUnit\Framework\TestCase; use api\Controllers\DictionariesApiController; use Domain\Attribute\AttributeRepository; +use Domain\Producer\ProducerRepository; use Domain\ShopStatus\ShopStatusRepository; use Domain\Transport\TransportRepository; use Domain\PaymentMethod\PaymentMethodRepository; @@ -14,6 +15,7 @@ class DictionariesApiControllerTest extends TestCase private $mockTransportRepo; private $mockPaymentRepo; private $mockAttrRepo; + private $mockProducerRepo; private $controller; protected function setUp(): void @@ -22,12 +24,14 @@ class DictionariesApiControllerTest extends TestCase $this->mockTransportRepo = $this->createMock(TransportRepository::class); $this->mockPaymentRepo = $this->createMock(PaymentMethodRepository::class); $this->mockAttrRepo = $this->createMock(AttributeRepository::class); + $this->mockProducerRepo = $this->createMock(ProducerRepository::class); $this->controller = new DictionariesApiController( $this->mockStatusRepo, $this->mockTransportRepo, $this->mockPaymentRepo, - $this->mockAttrRepo + $this->mockAttrRepo, + $this->mockProducerRepo ); $_SERVER['REQUEST_METHOD'] = 'GET'; diff --git a/updates/versions.php b/updates/versions.php index fae6520..ac6b5c3 100644 --- a/updates/versions.php +++ b/updates/versions.php @@ -1,5 +1,5 @@