From 1c6ebd819f2e6ba6861cf579a6d678d13c320f87 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 19 Aug 2024 16:01:35 +0300 Subject: [PATCH] Add support for GET /api/v5/store/offers method (#203) Co-authored-by: Kirill Sukhorukov --- src/Model/Entity/Store/OfferProduct.php | 190 ++++++++++++++++++++ src/Model/Entity/Store/StoreOffer.php | 34 ++++ src/Model/Filter/Store/OfferFilterType.php | 86 +++++++++ src/Model/Request/Store/OffersRequest.php | 33 ++++ src/Model/Response/Store/OffersResponse.php | 30 ++++ src/ResourceGroup/Store.php | 64 +++++++ tests/src/ResourceGroup/StoreTest.php | 99 ++++++++++ 7 files changed, 536 insertions(+) create mode 100644 src/Model/Entity/Store/OfferProduct.php create mode 100644 src/Model/Entity/Store/StoreOffer.php create mode 100644 src/Model/Filter/Store/OfferFilterType.php create mode 100644 src/Model/Request/Store/OffersRequest.php create mode 100644 src/Model/Response/Store/OffersResponse.php diff --git a/src/Model/Entity/Store/OfferProduct.php b/src/Model/Entity/Store/OfferProduct.php new file mode 100644 index 0000000..821369c --- /dev/null +++ b/src/Model/Entity/Store/OfferProduct.php @@ -0,0 +1,190 @@ + + * + * @JMS\Type("array") + * @JMS\SerializedName("properties") + */ + public $properties; + + /** + * @var \RetailCrm\Api\Model\Entity\FixExternalRow[] + * + * @JMS\Type("array") + * @JMS\SerializedName("groups") + */ + public $groups; + + /** + * @var string + * + * @JMS\Type("string") + * @JMS\SerializedName("externalId") + */ + public $externalId; + + /** + * @var string + * + * @JMS\Type("string") + * @JMS\SerializedName("manufacturer") + */ + public $manufacturer; + + /** + * @var bool + * + * @JMS\Type("bool") + * @JMS\SerializedName("active") + */ + public $active; + + /** + * @var float + * + * @JMS\Type("float") + * @JMS\SerializedName("quantity") + */ + public $quantity; + + /** + * @var bool + * + * @JMS\Type("bool") + * @JMS\SerializedName("markable") + */ + public $markable; + + /** + * @var DateTime + * + * @JMS\Type("DateTime<'Y-m-d H:i:s'>") + * @JMS\SerializedName("updatedAt") + */ + public $updatedAt; + + /** + * @var string + * + * @JMS\Type("string") + * @JMS\SerializedName("type") + */ + public $type; +} diff --git a/src/Model/Entity/Store/StoreOffer.php b/src/Model/Entity/Store/StoreOffer.php new file mode 100644 index 0000000..5a9a2fd --- /dev/null +++ b/src/Model/Entity/Store/StoreOffer.php @@ -0,0 +1,34 @@ +") + * @JMS\SerializedName("offers") + */ + public $offers; +} diff --git a/src/ResourceGroup/Store.php b/src/ResourceGroup/Store.php index 8bf2ec5..c5e4990 100644 --- a/src/ResourceGroup/Store.php +++ b/src/ResourceGroup/Store.php @@ -12,6 +12,7 @@ namespace RetailCrm\Api\ResourceGroup; use RetailCrm\Api\Enum\RequestMethod; use RetailCrm\Api\Model\Request\Store\InventoriesRequest; use RetailCrm\Api\Model\Request\Store\InventoriesUploadRequest; +use RetailCrm\Api\Model\Request\Store\OffersRequest; use RetailCrm\Api\Model\Request\Store\PricesUploadRequest; use RetailCrm\Api\Model\Request\Store\ProductBatchEditRequest; use RetailCrm\Api\Model\Request\Store\ProductGroupsCreateRequest; @@ -24,6 +25,7 @@ use RetailCrm\Api\Model\Request\Store\ProductsRequest; use RetailCrm\Api\Model\Response\IdResponse; use RetailCrm\Api\Model\Response\Store\InventoriesResponse; use RetailCrm\Api\Model\Response\Store\InventoriesUploadResponse; +use RetailCrm\Api\Model\Response\Store\OffersResponse; use RetailCrm\Api\Model\Response\Store\PricesUploadResponse; use RetailCrm\Api\Model\Response\Store\ProductBatchEditResponse; use RetailCrm\Api\Model\Response\Store\ProductGroupsResponse; @@ -693,6 +695,68 @@ class Store extends AbstractApiResourceGroup return $response; } + /** + * Makes GET "/api/v5/store/offers" request. + * + * Example: + * ```php + * use RetailCrm\Api\Enum\NumericBoolean; + * use RetailCrm\Api\Factory\SimpleClientFactory; + * use RetailCrm\Api\Interfaces\ApiExceptionInterface; + * use RetailCrm\Api\Model\Filter\Store\OfferFilterType; + * use RetailCrm\Api\Model\Request\Store\OffersRequest; + * + * $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey'); + * + * $request = new OffersRequest(); + * $request->filter = new OfferFilterType(); + * $request->filter->active = NumericBoolean::TRUE; + * $request->filter->name = 'Test Offer'; + * + * try { + * $response = $client->store->offers($request); + * } catch (ApiExceptionInterface $exception) { + * echo sprintf( + * 'Error from RetailCRM API (status code: %d): %s', + * $exception->getStatusCode(), + * $exception->getMessage() + * ); + * + * if (count($exception->getErrorResponse()->errors) > 0) { + * echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors); + * } + * + * return; + * } + * + * echo 'Offers: ' . print_r($response->offers, true); + * ``` + * + * @param \RetailCrm\Api\Model\Request\Store\OffersRequest|null $request + * + * @return \RetailCrm\Api\Model\Response\Store\OffersResponse + * @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface + * @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface + * @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException + * @throws \RetailCrm\Api\Exception\Api\ApiErrorException + * @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException + * @throws \RetailCrm\Api\Exception\Api\MissingParameterException + * @throws \RetailCrm\Api\Exception\Api\ValidationException + * @throws \RetailCrm\Api\Exception\Client\HandlerException + * @throws \RetailCrm\Api\Exception\Client\HttpClientException + */ + public function offers(?OffersRequest $request = null): OffersResponse + { + /** @var OffersResponse $response */ + $response = $this->sendRequest( + RequestMethod::GET, + 'store/offers', + $request, + OffersResponse::class + ); + return $response; + } + /** * Makes GET "/api/v5/store/products/properties/values" request. * diff --git a/tests/src/ResourceGroup/StoreTest.php b/tests/src/ResourceGroup/StoreTest.php index 7a24ea6..57120cd 100644 --- a/tests/src/ResourceGroup/StoreTest.php +++ b/tests/src/ResourceGroup/StoreTest.php @@ -22,12 +22,14 @@ use RetailCrm\Api\Model\Entity\Store\ProductEditGroupInput; use RetailCrm\Api\Model\Entity\Store\ProductEditInput; use RetailCrm\Api\Model\Entity\Store\SerializedProductGroup; use RetailCrm\Api\Model\Filter\Store\InventoryFilterType; +use RetailCrm\Api\Model\Filter\Store\OfferFilterType; use RetailCrm\Api\Model\Filter\Store\ProductFilterType; use RetailCrm\Api\Model\Filter\Store\ProductGroupFilterType; use RetailCrm\Api\Model\Filter\Store\ProductPropertiesFilterType; use RetailCrm\Api\Model\Filter\Store\ProductPropertyValuesFilterType; use RetailCrm\Api\Model\Request\Store\InventoriesRequest; use RetailCrm\Api\Model\Request\Store\InventoriesUploadRequest; +use RetailCrm\Api\Model\Request\Store\OffersRequest; use RetailCrm\Api\Model\Request\Store\PricesUploadRequest; use RetailCrm\Api\Model\Request\Store\ProductBatchEditRequest; use RetailCrm\Api\Model\Request\Store\ProductGroupsCreateRequest; @@ -857,4 +859,101 @@ EOF; self::assertModelEqualsToResponse($json, $response); } + + public function testOffers(): void + { + $json = <<<'EOF' +{ + "success": true, + "pagination": { + "limit": 20, + "totalCount": 1, + "currentPage": 1, + "totalPageCount": 1 + }, + "offers": [ + { + "name": "Test Offer", + "images": [ + "https://example.com/image.jpg" + ], + "id": 1941833, + "externalId": "38311", + "xmlId": "38311", + "article": "38311", + "prices": [ + { + "priceType": "base", + "price": 624, + "ordering": 991 + } + ], + "purchasePrice": 272.64, + "vatRate": "none", + "properties": { + "ves": "33", + "brend": "Test", + "image": "https://example.com/image.jpg", + "ves_g": "33", + "artikul": "38311" + }, + "quantity": 0.0, + "weight": 33.0, + "active": true, + "unit": { + "code": "pc", + "name": "Штука", + "sym": "шт." + }, + "product": { + "minPrice": 624, + "maxPrice": 624, + "id": 828272, + "article": "38311", + "type": "product", + "name": "Test Product", + "url": "https://example.com", + "imageUrl": "https://example.com/image.jpg", + "description": "Test Description", + "groups": [ + { + "id": 4050, + "externalId": "368" + }, + { + "id": 4154, + "externalId": "391" + }, + { + "id": 4279, + "externalId": "394" + } + ], + "externalId": "38311", + "manufacturer": "Test", + "active": true, + "quantity": 0, + "markable": false + } + } + ] +} +EOF; + + $request = new OffersRequest(); + $request->filter = new OfferFilterType(); + $request->filter->active = NumericBoolean::TRUE; + $request->filter->name = 'Test Offer'; + + $mock = static::createApiMockBuilder('store/offers'); + $mock->matchMethod(RequestMethod::GET) + ->matchQuery(self::encodeFormArray($request)) + ->reply(200) + ->withBody($json); + + $client = TestClientFactory::createClient($mock->getClient()); + $response = $client->store->offers($request); + + self::assertModelEqualsToResponse($json, $response); + } }