diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 6e5393c3..15e131ad 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -29,6 +29,7 @@ ->in(__DIR__ . '/src/Services/SonetGroup/') ->in(__DIR__ . '/src/Services/IMOpenLines/') ->in(__DIR__ . '/src/Services/Landing/') + ->in(__DIR__ . '/src/Services/Catalog/') ->name('*.php') ->exclude(['vendor', 'storage', 'docker', 'docs']) // Exclude directories ->ignoreDotFiles(true) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4bc3b52..1fb6d24c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ ### Added +- Added services `Services\Catalog\Price\Service\Price`, `Services\Catalog\PriceType\Service\PriceType`, + `Services\Catalog\PriceTypeLang\Service\PriceTypeLang`, `Services\Catalog\PriceTypeGroup\Service\PriceTypeGroup` + with support methods, see [catalog.price.* methods](https://apidocs.bitrix24.com/api-reference/catalog/price/index.html) + and [catalog.priceType.* methods](https://apidocs.bitrix24.com/api-reference/catalog/price-type/index.html) + ([#536](https://github.com/bitrix24/b24phpsdk/issues/536)): + - `Price::add` / `update` / `modify` / `get` / `list` / `delete` / `getFields`, with batch calls support + - `PriceType::add` / `update` / `get` / `list` / `delete` / `getFields`, with batch calls support + - `PriceTypeLang::add` / `update` / `get` / `list` / `delete` / `getLanguages` / `getFields`, with batch calls support + - `PriceTypeGroup::add` / `list` / `delete` / `getFields`, with batch calls support - Added service `Services\Landing\Site\Service\Site` with support methods, see [landing.site.* methods](https://github.com/bitrix24/b24phpsdk/issues/267): - `add` adds a site diff --git a/Makefile b/Makefile index c2fc4a9a..ec4bcca1 100644 --- a/Makefile +++ b/Makefile @@ -492,6 +492,22 @@ test-integration-landing-role: test-integration-landing-repowidget: docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_landing_repowidget +.PHONY: test-integration-catalog-price +test-integration-catalog-price: + docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_catalog_price + +.PHONY: test-integration-catalog-price-type +test-integration-catalog-price-type: + docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_catalog_price_type + +.PHONY: test-integration-catalog-price-type-lang +test-integration-catalog-price-type-lang: + docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_catalog_price_type_lang + +.PHONY: test-integration-catalog-price-type-group +test-integration-catalog-price-type-group: + docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_catalog_price_type_group + # work dev environment .PHONY: php-dev-server-up php-dev-server-up: diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d0187ae5..d0c04e7a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -262,6 +262,18 @@ ./tests/Integration/Services/Landing/RepoWidget/ + + ./tests/Integration/Services/Catalog/Price/ + + + ./tests/Integration/Services/Catalog/PriceType/ + + + ./tests/Integration/Services/Catalog/PriceTypeLang/ + + + ./tests/Integration/Services/Catalog/PriceTypeGroup/ + diff --git a/src/Services/Catalog/Catalog/Result/CatalogItemResult.php b/src/Services/Catalog/Catalog/Result/CatalogItemResult.php index e62fc7cb..189852bb 100644 --- a/src/Services/Catalog/Catalog/Result/CatalogItemResult.php +++ b/src/Services/Catalog/Catalog/Result/CatalogItemResult.php @@ -29,4 +29,4 @@ */ class CatalogItemResult extends AbstractCatalogItem { -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog/Result/CatalogResult.php b/src/Services/Catalog/Catalog/Result/CatalogResult.php index aa468aa8..c5222f11 100644 --- a/src/Services/Catalog/Catalog/Result/CatalogResult.php +++ b/src/Services/Catalog/Catalog/Result/CatalogResult.php @@ -21,4 +21,4 @@ public function catalog(): CatalogItemResult { return new CatalogItemResult($this->getCoreResponse()->getResponseData()->getResult()['catalog']); } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog/Result/CatalogsResult.php b/src/Services/Catalog/Catalog/Result/CatalogsResult.php index add5f259..f721c3bb 100644 --- a/src/Services/Catalog/Catalog/Result/CatalogsResult.php +++ b/src/Services/Catalog/Catalog/Result/CatalogsResult.php @@ -32,4 +32,4 @@ public function getCatalogs(): array return $res; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog/Service/Catalog.php b/src/Services/Catalog/Catalog/Service/Catalog.php index d9cb55fe..0da76ea3 100644 --- a/src/Services/Catalog/Catalog/Service/Catalog.php +++ b/src/Services/Catalog/Catalog/Service/Catalog.php @@ -82,4 +82,4 @@ public function fields(): FieldsResult { return new FieldsResult($this->core->call('catalog.catalog.getFields')); } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/CatalogServiceBuilder.php b/src/Services/Catalog/CatalogServiceBuilder.php index 57c91b88..63c93a4e 100644 --- a/src/Services/Catalog/CatalogServiceBuilder.php +++ b/src/Services/Catalog/CatalogServiceBuilder.php @@ -17,6 +17,7 @@ use Bitrix24\SDK\Core\Credentials\Scope; use Bitrix24\SDK\Services\AbstractServiceBuilder; use Bitrix24\SDK\Services\Catalog; + #[ApiServiceBuilderMetadata(new Scope(['catalog']))] class CatalogServiceBuilder extends AbstractServiceBuilder { @@ -44,4 +45,68 @@ public function catalog(): Catalog\Catalog\Service\Catalog return $this->serviceCache[__METHOD__]; } -} \ No newline at end of file + + public function price(): Catalog\Price\Service\Price + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Catalog\Price\Service\Price( + new Catalog\Price\Service\Batch( + new Catalog\Price\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } + + public function priceType(): Catalog\PriceType\Service\PriceType + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Catalog\PriceType\Service\PriceType( + new Catalog\PriceType\Service\Batch( + new Catalog\PriceType\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } + + public function priceTypeLang(): Catalog\PriceTypeLang\Service\PriceTypeLang + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Catalog\PriceTypeLang\Service\PriceTypeLang( + new Catalog\PriceTypeLang\Service\Batch( + new Catalog\PriceTypeLang\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } + + public function priceTypeGroup(): Catalog\PriceTypeGroup\Service\PriceTypeGroup + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Catalog\PriceTypeGroup\Service\PriceTypeGroup( + new Catalog\PriceTypeGroup\Service\Batch( + new Catalog\PriceTypeGroup\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } +} diff --git a/src/Services/Catalog/Common/ProductType.php b/src/Services/Catalog/Common/ProductType.php index 0bf8ef09..ad568a47 100644 --- a/src/Services/Catalog/Common/ProductType.php +++ b/src/Services/Catalog/Common/ProductType.php @@ -20,4 +20,4 @@ enum ProductType: int case SKU = 3; case productOffer = 4; case genericOffer = 5; -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Common/Result/AbstractCatalogItem.php b/src/Services/Catalog/Common/Result/AbstractCatalogItem.php index e2929d73..9761daed 100644 --- a/src/Services/Catalog/Common/Result/AbstractCatalogItem.php +++ b/src/Services/Catalog/Common/Result/AbstractCatalogItem.php @@ -109,4 +109,4 @@ protected function getKeyWithUserfieldByFieldName(string $fieldName) return $this->$fieldName; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Price/Batch.php b/src/Services/Catalog/Price/Batch.php new file mode 100644 index 00000000..686093c1 --- /dev/null +++ b/src/Services/Catalog/Price/Batch.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * Overrides base Batch to handle parameter naming differences in catalog.price.* REST methods: + * - delete uses lowercase 'id' instead of 'ID' + * + * @see https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-delete.html + * @see https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-list.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Determines the ID key — lowercase 'id' for catalog price + */ + #[\Override] + protected function determineKeyId(string $apiMethod, ?array $additionalParameters): string + { + return 'id'; + } + + /** + * Delete entity items with batch call using lowercase 'id' parameter + * + * @param int[] $entityItemId + * @param array|null $additionalParameters + * + * @return Generator|ResponseData[] + * @throws BaseException + */ + #[\Override] + public function deleteEntityItems( + string $apiMethod, + array $entityItemId, + ?array $additionalParameters = null + ): Generator { + $this->logger->debug( + 'deleteEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItems' => $entityItemId, + 'additionalParameters' => $additionalParameters, + ] + ); + + try { + $this->clearCommands(); + foreach ($entityItemId as $cnt => $itemId) { + if (!is_int($itemId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of price id «%s» at position %s, price id must be integer type', + gettype($itemId), + $itemId, + $cnt + ) + ); + } + + $this->registerCommand($apiMethod, ['id' => $itemId]); + } + + foreach ($this->getTraversable(true) as $cnt => $deletedItemResult) { + yield $cnt => $deletedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch delete price items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch delete price items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + + throw new BaseException($errorMessage, $exception->getCode(), $exception); + } + + $this->logger->debug('deleteEntityItems.finish'); + } +} diff --git a/src/Services/Catalog/Price/Result/PriceAddedBatchResult.php b/src/Services/Catalog/Price/Result/PriceAddedBatchResult.php new file mode 100644 index 00000000..318eda19 --- /dev/null +++ b/src/Services/Catalog/Price/Result/PriceAddedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceAddedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function price(): PriceItemResult + { + return new PriceItemResult($this->responseData->getResult()['price']); + } +} diff --git a/src/Services/Catalog/Price/Result/PriceFieldsResult.php b/src/Services/Catalog/Price/Result/PriceFieldsResult.php new file mode 100644 index 00000000..98038f8c --- /dev/null +++ b/src/Services/Catalog/Price/Result/PriceFieldsResult.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceFieldsResult extends AbstractResult +{ + /** + * @return array> + * @throws BaseException + */ + public function getFieldsDescription(): array + { + return $this->getCoreResponse()->getResponseData()->getResult()['price']; + } +} diff --git a/src/Services/Catalog/Price/Result/PriceItemResult.php b/src/Services/Catalog/Price/Result/PriceItemResult.php new file mode 100644 index 00000000..6d7b54a2 --- /dev/null +++ b/src/Services/Catalog/Price/Result/PriceItemResult.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; +use Carbon\CarbonImmutable; + +/** + * @property-read int $id + * @property-read int $productId + * @property-read int $catalogGroupId + * @property-read float $price + * @property-read string $currency + * @property-read int|null $extraId + * @property-read int|null $quantityFrom + * @property-read int|null $quantityTo + * @property-read float|null $priceScale + * @property-read CarbonImmutable|null $timestampX + */ +class PriceItemResult extends AbstractItem +{ + /** + * @param int|string $offset + * + * @return CarbonImmutable|float|mixed|null + */ + public function __get($offset) + { + return match ($offset) { + 'price' => (float)$this->data[$offset], + 'priceScale' => $this->data[$offset] !== null ? (float)$this->data[$offset] : null, + 'timestampX' => $this->data[$offset] !== null && $this->data[$offset] !== '' + ? CarbonImmutable::createFromFormat(DATE_ATOM, $this->data[$offset]) + : null, + default => $this->data[$offset] ?? null, + }; + } +} diff --git a/src/Services/Catalog/Price/Result/PriceResult.php b/src/Services/Catalog/Price/Result/PriceResult.php new file mode 100644 index 00000000..ac6b9900 --- /dev/null +++ b/src/Services/Catalog/Price/Result/PriceResult.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function price(): PriceItemResult + { + return new PriceItemResult($this->getCoreResponse()->getResponseData()->getResult()['price']); + } +} diff --git a/src/Services/Catalog/Price/Result/PriceUpdatedBatchResult.php b/src/Services/Catalog/Price/Result/PriceUpdatedBatchResult.php new file mode 100644 index 00000000..048f18bc --- /dev/null +++ b/src/Services/Catalog/Price/Result/PriceUpdatedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceUpdatedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function price(): PriceItemResult + { + return new PriceItemResult($this->responseData->getResult()['price']); + } +} diff --git a/src/Services/Catalog/Price/Result/PricesResult.php b/src/Services/Catalog/Price/Result/PricesResult.php new file mode 100644 index 00000000..16949cee --- /dev/null +++ b/src/Services/Catalog/Price/Result/PricesResult.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PricesResult extends AbstractResult +{ + /** + * @return PriceItemResult[] + * @throws BaseException + */ + public function getPrices(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): PriceItemResult => new PriceItemResult($item), + $result['prices'] ?? [] + ); + } +} diff --git a/src/Services/Catalog/Price/Service/Batch.php b/src/Services/Catalog/Price/Service/Batch.php new file mode 100644 index 00000000..01ca0bdd --- /dev/null +++ b/src/Services/Catalog/Price/Service/Batch.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Services\Catalog\Price; +use Bitrix24\SDK\Services\Catalog\Price\Result\PriceAddedBatchResult; +use Bitrix24\SDK\Services\Catalog\Price\Result\PriceUpdatedBatchResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['catalog']))] +class Batch +{ + public function __construct(protected Price\Batch $batch, protected LoggerInterface $log) + { + } + + /** + * Batch adding product prices + * + * @param array $prices + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.price.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-add.html', + 'Batch adding product prices' + )] + public function add(array $prices): Generator + { + $items = []; + foreach ($prices as $price) { + $items[] = ['fields' => $price]; + } + + foreach ($this->batch->addEntityItems('catalog.price.add', $items) as $key => $item) { + yield $key => new PriceAddedBatchResult($item); + } + } + + /** + * Batch delete product prices + * + * @param int[] $priceId + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.price.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-delete.html', + 'Batch delete product prices' + )] + public function delete(array $priceId): Generator + { + foreach ($this->batch->deleteEntityItems('catalog.price.delete', $priceId) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } + + /** + * Batch update product prices + * + * @param array $prices keyed by price id + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.price.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-update.html', + 'Batch update product prices' + )] + public function update(array $prices): Generator + { + $items = []; + foreach ($prices as $id => $price) { + $items[$id] = ['fields' => $price]; + } + + foreach ($this->batch->updateEntityItems('catalog.price.update', $items) as $key => $item) { + yield $key => new PriceUpdatedBatchResult($item); + } + } +} diff --git a/src/Services/Catalog/Price/Service/Price.php b/src/Services/Catalog/Price/Service/Price.php new file mode 100644 index 00000000..47651424 --- /dev/null +++ b/src/Services/Catalog/Price/Service/Price.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\Price\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\Catalog\Price\Result\PriceFieldsResult; +use Bitrix24\SDK\Services\Catalog\Price\Result\PriceResult; +use Bitrix24\SDK\Services\Catalog\Price\Result\PricesResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['catalog']))] +class Price extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Adds a new product price + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-add.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-add.html', + 'Adds a new product price' + )] + public function add(array $fields): PriceResult + { + return new PriceResult($this->core->call('catalog.price.add', ['fields' => $fields])); + } + + /** + * Updates the price of a product by its identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-update.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-update.html', + 'Updates the price of a product by its identifier' + )] + public function update(int $id, array $fields): PriceResult + { + return new PriceResult($this->core->call('catalog.price.update', ['id' => $id, 'fields' => $fields])); + } + + /** + * Adds, updates and deletes a product price collection in a single request + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-modify.html + * + * @param array $prices + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.modify', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-modify.html', + 'Adds, updates and deletes a product price collection in a single request' + )] + public function modify(int $productId, array $prices): PricesResult + { + return new PricesResult( + $this->core->call( + 'catalog.price.modify', + ['fields' => ['product' => ['id' => $productId, 'prices' => $prices]]] + ) + ); + } + + /** + * Returns the fields of a product price + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-get-fields.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.getFields', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-get-fields.html', + 'Returns the fields of a product price' + )] + public function getFields(): PriceFieldsResult + { + return new PriceFieldsResult($this->core->call('catalog.price.getFields')); + } + + /** + * Returns a list of product prices by filter + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.list', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-list.html', + 'Returns a list of product prices by filter' + )] + public function list(array $select = [], array $filter = [], array $order = []): PricesResult + { + return new PricesResult( + $this->core->call( + 'catalog.price.list', + ['select' => $select, 'filter' => $filter, 'order' => $order] + ) + ); + } + + /** + * Returns product price information by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-get.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.get', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-get.html', + 'Returns product price information by identifier' + )] + public function get(int $id): PriceResult + { + return new PriceResult($this->core->call('catalog.price.get', ['id' => $id])); + } + + /** + * Deletes a product price by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-delete.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.price.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price/catalog-price-delete.html', + 'Deletes a product price by identifier' + )] + public function delete(int $id): DeletedItemResult + { + return new DeletedItemResult($this->core->call('catalog.price.delete', ['id' => $id])); + } +} diff --git a/src/Services/Catalog/PriceType/Batch.php b/src/Services/Catalog/PriceType/Batch.php new file mode 100644 index 00000000..9a43ba48 --- /dev/null +++ b/src/Services/Catalog/PriceType/Batch.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * Overrides base Batch to handle parameter naming differences in catalog.priceType.* REST methods: + * - delete uses lowercase 'id' instead of 'ID' + * + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-delete.html + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-list.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Determines the ID key — lowercase 'id' for catalog price type + */ + #[\Override] + protected function determineKeyId(string $apiMethod, ?array $additionalParameters): string + { + return 'id'; + } + + /** + * Delete entity items with batch call using lowercase 'id' parameter + * + * @param int[] $entityItemId + * @param array|null $additionalParameters + * + * @return Generator|ResponseData[] + * @throws BaseException + */ + #[\Override] + public function deleteEntityItems( + string $apiMethod, + array $entityItemId, + ?array $additionalParameters = null + ): Generator { + $this->logger->debug( + 'deleteEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItems' => $entityItemId, + 'additionalParameters' => $additionalParameters, + ] + ); + + try { + $this->clearCommands(); + foreach ($entityItemId as $cnt => $itemId) { + if (!is_int($itemId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of price type id «%s» at position %s, price type id must be integer type', + gettype($itemId), + $itemId, + $cnt + ) + ); + } + + $this->registerCommand($apiMethod, ['id' => $itemId]); + } + + foreach ($this->getTraversable(true) as $cnt => $deletedItemResult) { + yield $cnt => $deletedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch delete price type items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch delete price type items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + + throw new BaseException($errorMessage, $exception->getCode(), $exception); + } + + $this->logger->debug('deleteEntityItems.finish'); + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypeAddedBatchResult.php b/src/Services/Catalog/PriceType/Result/PriceTypeAddedBatchResult.php new file mode 100644 index 00000000..3ffe6b8d --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypeAddedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceTypeAddedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function priceType(): PriceTypeItemResult + { + return new PriceTypeItemResult($this->responseData->getResult()['priceType']); + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypeFieldsResult.php b/src/Services/Catalog/PriceType/Result/PriceTypeFieldsResult.php new file mode 100644 index 00000000..d27f735c --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypeFieldsResult.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeFieldsResult extends AbstractResult +{ + /** + * @return array> + * @throws BaseException + */ + public function getFieldsDescription(): array + { + return $this->getCoreResponse()->getResponseData()->getResult()['priceType']; + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypeItemResult.php b/src/Services/Catalog/PriceType/Result/PriceTypeItemResult.php new file mode 100644 index 00000000..a2036b40 --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypeItemResult.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; +use Carbon\CarbonImmutable; + +/** + * @property-read int $id + * @property-read string $name + * @property-read bool $base + * @property-read int $sort + * @property-read string|null $xmlId + * @property-read int|null $createdBy + * @property-read int|null $modifiedBy + * @property-read CarbonImmutable|null $dateCreate + * @property-read CarbonImmutable|null $timestampX + */ +class PriceTypeItemResult extends AbstractItem +{ + /** + * @param int|string $offset + * + * @return bool|CarbonImmutable|mixed|null + */ + public function __get($offset) + { + return match ($offset) { + 'base' => $this->data[$offset] === 'Y', + 'dateCreate', 'timestampX' => $this->data[$offset] !== null && $this->data[$offset] !== '' + ? CarbonImmutable::createFromFormat(DATE_ATOM, $this->data[$offset]) + : null, + default => $this->data[$offset] ?? null, + }; + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypeResult.php b/src/Services/Catalog/PriceType/Result/PriceTypeResult.php new file mode 100644 index 00000000..0bfdf183 --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypeResult.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function priceType(): PriceTypeItemResult + { + return new PriceTypeItemResult($this->getCoreResponse()->getResponseData()->getResult()['priceType']); + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypeUpdatedBatchResult.php b/src/Services/Catalog/PriceType/Result/PriceTypeUpdatedBatchResult.php new file mode 100644 index 00000000..3f343196 --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypeUpdatedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceTypeUpdatedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function priceType(): PriceTypeItemResult + { + return new PriceTypeItemResult($this->responseData->getResult()['priceType']); + } +} diff --git a/src/Services/Catalog/PriceType/Result/PriceTypesResult.php b/src/Services/Catalog/PriceType/Result/PriceTypesResult.php new file mode 100644 index 00000000..8a4b0e82 --- /dev/null +++ b/src/Services/Catalog/PriceType/Result/PriceTypesResult.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypesResult extends AbstractResult +{ + /** + * @return PriceTypeItemResult[] + * @throws BaseException + */ + public function getPriceTypes(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): PriceTypeItemResult => new PriceTypeItemResult($item), + $result['priceTypes'] ?? [] + ); + } +} diff --git a/src/Services/Catalog/PriceType/Service/Batch.php b/src/Services/Catalog/PriceType/Service/Batch.php new file mode 100644 index 00000000..10080f76 --- /dev/null +++ b/src/Services/Catalog/PriceType/Service/Batch.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Services\Catalog\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypeAddedBatchResult; +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypeUpdatedBatchResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['catalog']))] +class Batch +{ + public function __construct(protected PriceType\Batch $batch, protected LoggerInterface $log) + { + } + + /** + * Batch adding price types + * + * @param array $priceTypes + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceType.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-add.html', + 'Batch adding price types' + )] + public function add(array $priceTypes): Generator + { + $items = []; + foreach ($priceTypes as $priceType) { + $items[] = ['fields' => $priceType]; + } + + foreach ($this->batch->addEntityItems('catalog.priceType.add', $items) as $key => $item) { + yield $key => new PriceTypeAddedBatchResult($item); + } + } + + /** + * Batch delete price types + * + * @param int[] $priceTypeId + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceType.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-delete.html', + 'Batch delete price types' + )] + public function delete(array $priceTypeId): Generator + { + foreach ($this->batch->deleteEntityItems('catalog.priceType.delete', $priceTypeId) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } + + /** + * Batch update price types + * + * @param array $priceTypes keyed by price type id + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceType.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-update.html', + 'Batch update price types' + )] + public function update(array $priceTypes): Generator + { + $items = []; + foreach ($priceTypes as $id => $priceType) { + $items[$id] = ['fields' => $priceType]; + } + + foreach ($this->batch->updateEntityItems('catalog.priceType.update', $items) as $key => $item) { + yield $key => new PriceTypeUpdatedBatchResult($item); + } + } +} diff --git a/src/Services/Catalog/PriceType/Service/PriceType.php b/src/Services/Catalog/PriceType/Service/PriceType.php new file mode 100644 index 00000000..7bc8bb90 --- /dev/null +++ b/src/Services/Catalog/PriceType/Service/PriceType.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceType\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypeFieldsResult; +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypeResult; +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypesResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['catalog']))] +class PriceType extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Adds a new price type + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-add.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-add.html', + 'Adds a new price type' + )] + public function add(array $fields): PriceTypeResult + { + return new PriceTypeResult($this->core->call('catalog.priceType.add', ['fields' => $fields])); + } + + /** + * Updates a price type by its identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-update.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-update.html', + 'Updates a price type by its identifier' + )] + public function update(int $id, array $fields): PriceTypeResult + { + return new PriceTypeResult($this->core->call('catalog.priceType.update', ['id' => $id, 'fields' => $fields])); + } + + /** + * Returns price type information by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-get.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.get', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-get.html', + 'Returns price type information by identifier' + )] + public function get(int $id): PriceTypeResult + { + return new PriceTypeResult($this->core->call('catalog.priceType.get', ['id' => $id])); + } + + /** + * Returns a list of price types by filter + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.list', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-list.html', + 'Returns a list of price types by filter' + )] + public function list(array $select = [], array $filter = [], array $order = []): PriceTypesResult + { + return new PriceTypesResult( + $this->core->call( + 'catalog.priceType.list', + ['select' => $select, 'filter' => $filter, 'order' => $order] + ) + ); + } + + /** + * Deletes a price type by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-delete.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-delete.html', + 'Deletes a price type by identifier' + )] + public function delete(int $id): DeletedItemResult + { + return new DeletedItemResult($this->core->call('catalog.priceType.delete', ['id' => $id])); + } + + /** + * Returns the fields of a price type + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-get-fields.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceType.getFields', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/catalog-price-type-get-fields.html', + 'Returns the fields of a price type' + )] + public function getFields(): PriceTypeFieldsResult + { + return new PriceTypeFieldsResult($this->core->call('catalog.priceType.getFields')); + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Batch.php b/src/Services/Catalog/PriceTypeGroup/Batch.php new file mode 100644 index 00000000..9dc361e1 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Batch.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * Overrides base Batch to handle parameter naming differences in catalog.priceTypeGroup.* REST methods: + * - delete uses lowercase 'id' instead of 'ID' + * + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-delete.html + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-list.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Determines the ID key — lowercase 'id' for catalog price type group + */ + #[\Override] + protected function determineKeyId(string $apiMethod, ?array $additionalParameters): string + { + return 'id'; + } + + /** + * Delete entity items with batch call using lowercase 'id' parameter + * + * @param int[] $entityItemId + * @param array|null $additionalParameters + * + * @return Generator|ResponseData[] + * @throws BaseException + */ + #[\Override] + public function deleteEntityItems( + string $apiMethod, + array $entityItemId, + ?array $additionalParameters = null + ): Generator { + $this->logger->debug( + 'deleteEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItems' => $entityItemId, + 'additionalParameters' => $additionalParameters, + ] + ); + + try { + $this->clearCommands(); + foreach ($entityItemId as $cnt => $itemId) { + if (!is_int($itemId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of price type group id «%s» at position %s, price type group id must be integer type', + gettype($itemId), + $itemId, + $cnt + ) + ); + } + + $this->registerCommand($apiMethod, ['id' => $itemId]); + } + + foreach ($this->getTraversable(true) as $cnt => $deletedItemResult) { + yield $cnt => $deletedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch delete price type group items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch delete price type group items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + + throw new BaseException($errorMessage, $exception->getCode(), $exception); + } + + $this->logger->debug('deleteEntityItems.finish'); + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupAddedBatchResult.php b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupAddedBatchResult.php new file mode 100644 index 00000000..907e95c0 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupAddedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceTypeGroupAddedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function priceTypeGroup(): PriceTypeGroupItemResult + { + return new PriceTypeGroupItemResult($this->responseData->getResult()['priceTypeGroup']); + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupFieldsResult.php b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupFieldsResult.php new file mode 100644 index 00000000..3f67c74a --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupFieldsResult.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeGroupFieldsResult extends AbstractResult +{ + /** + * @return array> + * @throws BaseException + */ + public function getFieldsDescription(): array + { + return $this->getCoreResponse()->getResponseData()->getResult()['priceTypeGroup']; + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResult.php b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResult.php new file mode 100644 index 00000000..a236e176 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResult.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; + +/** + * @property-read int $id + * @property-read int $catalogGroupId + * @property-read int $groupId + * @property-read bool $access + */ +class PriceTypeGroupItemResult extends AbstractItem +{ + /** + * @param int|string $offset + * + * @return bool|mixed|null + */ + public function __get($offset) + { + if ($offset === 'access') { + return $this->data[$offset] === 'Y'; + } + + return $this->data[$offset] ?? null; + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupResult.php b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupResult.php new file mode 100644 index 00000000..984818e6 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupResult.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeGroupResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function priceTypeGroup(): PriceTypeGroupItemResult + { + return new PriceTypeGroupItemResult($this->getCoreResponse()->getResponseData()->getResult()['priceTypeGroup']); + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupsResult.php b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupsResult.php new file mode 100644 index 00000000..b6557694 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupsResult.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeGroupsResult extends AbstractResult +{ + /** + * @return PriceTypeGroupItemResult[] + * @throws BaseException + */ + public function getPriceTypeGroups(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): PriceTypeGroupItemResult => new PriceTypeGroupItemResult($item), + $result['priceTypeGroups'] ?? [] + ); + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Service/Batch.php b/src/Services/Catalog/PriceTypeGroup/Service/Batch.php new file mode 100644 index 00000000..c094ea01 --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Service/Batch.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result\PriceTypeGroupAddedBatchResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['catalog']))] +class Batch +{ + public function __construct(protected PriceTypeGroup\Batch $batch, protected LoggerInterface $log) + { + } + + /** + * Batch adding price type ↔ purchasing group bindings + * + * @param array $priceTypeGroups + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceTypeGroup.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-add.html', + 'Batch adding price type purchasing group bindings' + )] + public function add(array $priceTypeGroups): Generator + { + $items = []; + foreach ($priceTypeGroups as $priceTypeGroup) { + $items[] = ['fields' => $priceTypeGroup]; + } + + foreach ($this->batch->addEntityItems('catalog.priceTypeGroup.add', $items) as $key => $item) { + yield $key => new PriceTypeGroupAddedBatchResult($item); + } + } + + /** + * Batch delete price type ↔ purchasing group bindings + * + * @param int[] $priceTypeGroupId + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceTypeGroup.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-delete.html', + 'Batch delete price type purchasing group bindings' + )] + public function delete(array $priceTypeGroupId): Generator + { + foreach ($this->batch->deleteEntityItems('catalog.priceTypeGroup.delete', $priceTypeGroupId) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } +} diff --git a/src/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroup.php b/src/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroup.php new file mode 100644 index 00000000..e763dbea --- /dev/null +++ b/src/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroup.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result\PriceTypeGroupFieldsResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result\PriceTypeGroupResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result\PriceTypeGroupsResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['catalog']))] +class PriceTypeGroup extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Adds a price type binding to a purchasing group + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-add.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeGroup.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-add.html', + 'Adds a price type binding to a purchasing group' + )] + public function add(array $fields): PriceTypeGroupResult + { + return new PriceTypeGroupResult($this->core->call('catalog.priceTypeGroup.add', ['fields' => $fields])); + } + + /** + * Returns a list of price type ↔ purchasing group bindings by filter + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeGroup.list', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-list.html', + 'Returns a list of price type purchasing group bindings by filter' + )] + public function list(array $select = [], array $filter = [], array $order = [], int $start = 0): PriceTypeGroupsResult + { + return new PriceTypeGroupsResult( + $this->core->call( + 'catalog.priceTypeGroup.list', + ['select' => $select, 'filter' => $filter, 'order' => $order, 'start' => $start] + ) + ); + } + + /** + * Deletes a price type ↔ purchasing group binding by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-delete.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeGroup.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-delete.html', + 'Deletes a price type purchasing group binding by identifier' + )] + public function delete(int $id): DeletedItemResult + { + return new DeletedItemResult($this->core->call('catalog.priceTypeGroup.delete', ['id' => $id])); + } + + /** + * Returns the fields of a price type ↔ purchasing group binding + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-get-fields.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeGroup.getFields', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-group/catalog-price-type-group-get-fields.html', + 'Returns the fields of a price type purchasing group binding' + )] + public function getFields(): PriceTypeGroupFieldsResult + { + return new PriceTypeGroupFieldsResult($this->core->call('catalog.priceTypeGroup.getFields')); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Batch.php b/src/Services/Catalog/PriceTypeLang/Batch.php new file mode 100644 index 00000000..174fd150 --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Batch.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * Overrides base Batch to handle parameter naming differences in catalog.priceTypeLang.* REST methods: + * - delete uses lowercase 'id' instead of 'ID' + * + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-delete.html + * @see https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-list.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Determines the ID key — lowercase 'id' for catalog price type lang + */ + #[\Override] + protected function determineKeyId(string $apiMethod, ?array $additionalParameters): string + { + return 'id'; + } + + /** + * Delete entity items with batch call using lowercase 'id' parameter + * + * @param int[] $entityItemId + * @param array|null $additionalParameters + * + * @return Generator|ResponseData[] + * @throws BaseException + */ + #[\Override] + public function deleteEntityItems( + string $apiMethod, + array $entityItemId, + ?array $additionalParameters = null + ): Generator { + $this->logger->debug( + 'deleteEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItems' => $entityItemId, + 'additionalParameters' => $additionalParameters, + ] + ); + + try { + $this->clearCommands(); + foreach ($entityItemId as $cnt => $itemId) { + if (!is_int($itemId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of price type lang id «%s» at position %s, price type lang id must be integer type', + gettype($itemId), + $itemId, + $cnt + ) + ); + } + + $this->registerCommand($apiMethod, ['id' => $itemId]); + } + + foreach ($this->getTraversable(true) as $cnt => $deletedItemResult) { + yield $cnt => $deletedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch delete price type lang items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch delete price type lang items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + + throw new BaseException($errorMessage, $exception->getCode(), $exception); + } + + $this->logger->debug('deleteEntityItems.finish'); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/LanguageItemResult.php b/src/Services/Catalog/PriceTypeLang/Result/LanguageItemResult.php new file mode 100644 index 00000000..1527873d --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/LanguageItemResult.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; + +/** + * @property-read string $lid + * @property-read string $name + * @property-read bool $active + */ +class LanguageItemResult extends AbstractItem +{ + /** + * @param int|string $offset + * + * @return bool|mixed|null + */ + public function __get($offset) + { + if ($offset === 'active') { + return $this->data[$offset] === 'Y'; + } + + return $this->data[$offset] ?? null; + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/LanguagesResult.php b/src/Services/Catalog/PriceTypeLang/Result/LanguagesResult.php new file mode 100644 index 00000000..b07d531f --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/LanguagesResult.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class LanguagesResult extends AbstractResult +{ + /** + * @return LanguageItemResult[] + * @throws BaseException + */ + public function getLanguages(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): LanguageItemResult => new LanguageItemResult($item), + $result['languages'] ?? [] + ); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangAddedBatchResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangAddedBatchResult.php new file mode 100644 index 00000000..ce3087ce --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangAddedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceTypeLangAddedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function priceTypeLang(): PriceTypeLangItemResult + { + return new PriceTypeLangItemResult($this->responseData->getResult()['priceTypeLang']); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangFieldsResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangFieldsResult.php new file mode 100644 index 00000000..a3b0ea7c --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangFieldsResult.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeLangFieldsResult extends AbstractResult +{ + /** + * @return array> + * @throws BaseException + */ + public function getFieldsDescription(): array + { + return $this->getCoreResponse()->getResponseData()->getResult()['priceTypeLang']; + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResult.php new file mode 100644 index 00000000..9bc74f71 --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResult.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; + +/** + * @property-read int $id + * @property-read int $catalogGroupId + * @property-read string $lang + * @property-read string $name + */ +class PriceTypeLangItemResult extends AbstractItem +{ +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangResult.php new file mode 100644 index 00000000..805147ba --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangResult.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeLangResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function priceTypeLang(): PriceTypeLangItemResult + { + return new PriceTypeLangItemResult($this->getCoreResponse()->getResponseData()->getResult()['priceTypeLang']); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangUpdatedBatchResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangUpdatedBatchResult.php new file mode 100644 index 00000000..d88830cb --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangUpdatedBatchResult.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class PriceTypeLangUpdatedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function priceTypeLang(): PriceTypeLangItemResult + { + return new PriceTypeLangItemResult($this->responseData->getResult()['priceTypeLang']); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangsResult.php b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangsResult.php new file mode 100644 index 00000000..6f277cc2 --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Result/PriceTypeLangsResult.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PriceTypeLangsResult extends AbstractResult +{ + /** + * @return PriceTypeLangItemResult[] + * @throws BaseException + */ + public function getPriceTypeLangs(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): PriceTypeLangItemResult => new PriceTypeLangItemResult($item), + $result['priceTypeLangs'] ?? [] + ); + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Service/Batch.php b/src/Services/Catalog/PriceTypeLang/Service/Batch.php new file mode 100644 index 00000000..b3b68313 --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Service/Batch.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangAddedBatchResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangUpdatedBatchResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['catalog']))] +class Batch +{ + public function __construct(protected PriceTypeLang\Batch $batch, protected LoggerInterface $log) + { + } + + /** + * Batch adding price type name translations + * + * @param array $priceTypeLangs + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceTypeLang.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-add.html', + 'Batch adding price type name translations' + )] + public function add(array $priceTypeLangs): Generator + { + $items = []; + foreach ($priceTypeLangs as $priceTypeLang) { + $items[] = ['fields' => $priceTypeLang]; + } + + foreach ($this->batch->addEntityItems('catalog.priceTypeLang.add', $items) as $key => $item) { + yield $key => new PriceTypeLangAddedBatchResult($item); + } + } + + /** + * Batch delete price type name translations + * + * @param int[] $priceTypeLangId + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceTypeLang.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-delete.html', + 'Batch delete price type name translations' + )] + public function delete(array $priceTypeLangId): Generator + { + foreach ($this->batch->deleteEntityItems('catalog.priceTypeLang.delete', $priceTypeLangId) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } + + /** + * Batch update price type name translations + * + * @param array $priceTypeLangs keyed by translation id + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.priceTypeLang.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-update.html', + 'Batch update price type name translations' + )] + public function update(array $priceTypeLangs): Generator + { + $items = []; + foreach ($priceTypeLangs as $id => $priceTypeLang) { + $items[$id] = ['fields' => $priceTypeLang]; + } + + foreach ($this->batch->updateEntityItems('catalog.priceTypeLang.update', $items) as $key => $item) { + yield $key => new PriceTypeLangUpdatedBatchResult($item); + } + } +} diff --git a/src/Services/Catalog/PriceTypeLang/Service/PriceTypeLang.php b/src/Services/Catalog/PriceTypeLang/Service/PriceTypeLang.php new file mode 100644 index 00000000..648b5977 --- /dev/null +++ b/src/Services/Catalog/PriceTypeLang/Service/PriceTypeLang.php @@ -0,0 +1,167 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\LanguagesResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangFieldsResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangsResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['catalog']))] +class PriceTypeLang extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Adds a new price type name translation + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-add.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.add', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-add.html', + 'Adds a new price type name translation' + )] + public function add(array $fields): PriceTypeLangResult + { + return new PriceTypeLangResult($this->core->call('catalog.priceTypeLang.add', ['fields' => $fields])); + } + + /** + * Updates a price type name translation by its identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-update.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-update.html', + 'Updates a price type name translation by its identifier' + )] + public function update(int $id, array $fields): PriceTypeLangResult + { + return new PriceTypeLangResult( + $this->core->call('catalog.priceTypeLang.update', ['id' => $id, 'fields' => $fields]) + ); + } + + /** + * Returns price type name translation information by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.get', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get.html', + 'Returns price type name translation information by identifier' + )] + public function get(int $id): PriceTypeLangResult + { + return new PriceTypeLangResult($this->core->call('catalog.priceTypeLang.get', ['id' => $id])); + } + + /** + * Returns a list of price type name translations by filter + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.list', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-list.html', + 'Returns a list of price type name translations by filter' + )] + public function list(array $select = [], array $filter = []): PriceTypeLangsResult + { + return new PriceTypeLangsResult( + $this->core->call('catalog.priceTypeLang.list', ['select' => $select, 'filter' => $filter]) + ); + } + + /** + * Deletes a price type name translation by identifier + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-delete.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.delete', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-delete.html', + 'Deletes a price type name translation by identifier' + )] + public function delete(int $id): DeletedItemResult + { + return new DeletedItemResult($this->core->call('catalog.priceTypeLang.delete', ['id' => $id])); + } + + /** + * Returns the list of languages available for price type translation + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get-languages.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.getLanguages', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get-languages.html', + 'Returns the list of languages available for price type translation' + )] + public function getLanguages(): LanguagesResult + { + return new LanguagesResult($this->core->call('catalog.priceTypeLang.getLanguages')); + } + + /** + * Returns the fields of a price type name translation + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get-fields.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.priceTypeLang.getFields', + 'https://apidocs.bitrix24.com/api-reference/catalog/price-type/price-type-lang/catalog-price-type-lang-get-fields.html', + 'Returns the fields of a price type name translation' + )] + public function getFields(): PriceTypeLangFieldsResult + { + return new PriceTypeLangFieldsResult($this->core->call('catalog.priceTypeLang.getFields')); + } +} diff --git a/src/Services/Catalog/Product/Result/ProductItemResult.php b/src/Services/Catalog/Product/Result/ProductItemResult.php index c576d9b7..58c80851 100644 --- a/src/Services/Catalog/Product/Result/ProductItemResult.php +++ b/src/Services/Catalog/Product/Result/ProductItemResult.php @@ -52,4 +52,4 @@ */ class ProductItemResult extends AbstractCatalogItem { -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Product/Result/ProductResult.php b/src/Services/Catalog/Product/Result/ProductResult.php index 2751fda8..fc83fa8c 100644 --- a/src/Services/Catalog/Product/Result/ProductResult.php +++ b/src/Services/Catalog/Product/Result/ProductResult.php @@ -26,4 +26,4 @@ public function product(): ProductItemResult return new ProductItemResult($this->getCoreResponse()->getResponseData()->getResult()['product']); } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Product/Result/ProductsResult.php b/src/Services/Catalog/Product/Result/ProductsResult.php index aa644fa3..268d6d8f 100644 --- a/src/Services/Catalog/Product/Result/ProductsResult.php +++ b/src/Services/Catalog/Product/Result/ProductsResult.php @@ -31,4 +31,4 @@ public function getProducts(): array return $res; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Product/Service/Batch.php b/src/Services/Catalog/Product/Service/Batch.php index 45dddcb7..42970546 100644 --- a/src/Services/Catalog/Product/Service/Batch.php +++ b/src/Services/Catalog/Product/Service/Batch.php @@ -25,7 +25,7 @@ { public function __construct( protected BatchOperationsInterface $batch, - protected LoggerInterface $log) - { + protected LoggerInterface $log + ) { } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Product/Service/Product.php b/src/Services/Catalog/Product/Service/Product.php index 730fd7c9..d37d34f6 100644 --- a/src/Services/Catalog/Product/Service/Product.php +++ b/src/Services/Catalog/Product/Service/Product.php @@ -25,7 +25,6 @@ use Bitrix24\SDK\Services\Catalog\Common\ProductType; use Bitrix24\SDK\Services\Catalog\Product\Result\ProductResult; use Bitrix24\SDK\Services\Catalog\Product\Result\ProductsResult; - use Psr\Log\LoggerInterface; #[ApiServiceMetadata(new Scope(['catalog']))] @@ -35,8 +34,7 @@ public function __construct( public Batch $batch, CoreInterface $core, LoggerInterface $logger - ) - { + ) { parent::__construct($core, $logger); } @@ -71,7 +69,9 @@ public function get(int $productId): ProductResult )] public function add(array $productFields): ProductResult { - return new ProductResult($this->core->call('catalog.product.add', [ + return new ProductResult($this->core->call( + 'catalog.product.add', + [ 'fields' => $productFields ] )); @@ -140,4 +140,4 @@ public function fieldsByFilter(int $iblockId, ProductType $productType, ?array $ return new FieldsResult($this->core->call('catalog.product.getFieldsByFilter', ['filter' => $filter])); } -} \ No newline at end of file +} diff --git a/tests/Integration/Services/Catalog/Price/Result/PriceItemResultTest.php b/tests/Integration/Services/Catalog/Price/Result/PriceItemResultTest.php new file mode 100644 index 00000000..49fa9e78 --- /dev/null +++ b/tests/Integration/Services/Catalog/Price/Result/PriceItemResultTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\Price\Result; + +use Bitrix24\SDK\Services\Catalog\Catalog\Service\Catalog; +use Bitrix24\SDK\Services\Catalog\Price\Result\PriceItemResult; +use Bitrix24\SDK\Services\Catalog\Price\Service\Price; +use Bitrix24\SDK\Services\Catalog\Product\Service\Product; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceItemResult::class)] +class PriceItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private Price $priceService; + + private Product $productService; + + private int $productId; + + private int $priceId; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceService = $serviceBuilder->getCatalogScope()->price(); + $this->productService = $serviceBuilder->getCatalogScope()->product(); + + $catalogService = $serviceBuilder->getCatalogScope()->catalog(); + $iblockId = $catalogService->list([], [], [], 1)->getCatalogs()[0]->iblockId; + + $this->productId = $this->productService->add([ + 'iblockId' => $iblockId, + 'name' => sprintf('test product for price annotations %s', time()), + ])->product()->id; + + $this->priceId = $this->priceService->add([ + 'productId' => $this->productId, + 'catalogGroupId' => 1, + 'price' => 150.0, + 'currency' => 'USD', + ])->price()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceService->delete($this->priceId); + $this->productService->delete($this->productId); + } + + #[Test] + #[TestDox('all fields in PriceItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItem = $this->priceService->get($this->priceId)->getCoreResponse()->getResponseData()->getResult()['price']; + $this->assertBitrix24AllResultItemFieldsAnnotated(array_keys($rawItem), PriceItemResult::class); + } + + #[Test] + #[TestDox('all fields in PriceItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $priceItemResult = $this->priceService->get($this->priceId)->price(); + $this->assertIsInt($priceItemResult->id); + $this->assertIsInt($priceItemResult->productId); + $this->assertIsInt($priceItemResult->catalogGroupId); + $this->assertIsFloat($priceItemResult->price); + $this->assertIsString($priceItemResult->currency); + } +} diff --git a/tests/Integration/Services/Catalog/Price/Service/BatchTest.php b/tests/Integration/Services/Catalog/Price/Service/BatchTest.php new file mode 100644 index 00000000..44152703 --- /dev/null +++ b/tests/Integration/Services/Catalog/Price/Service/BatchTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\Price\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\Catalog\Service\Catalog; +use Bitrix24\SDK\Services\Catalog\Price\Service\Batch; +use Bitrix24\SDK\Services\Catalog\Price\Service\Price; +use Bitrix24\SDK\Services\Catalog\Product\Service\Product; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private Price $priceService; + + private Product $productService; + + private int $productId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceService = $serviceBuilder->getCatalogScope()->price(); + $this->productService = $serviceBuilder->getCatalogScope()->product(); + + $catalogService = $serviceBuilder->getCatalogScope()->catalog(); + $iblockId = $catalogService->list([], [], [], 1)->getCatalogs()[0]->iblockId; + + $this->productId = $this->productService->add([ + 'iblockId' => $iblockId, + 'name' => sprintf('test product for batch price %s', time()), + ])->product()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->productService->delete($this->productId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Batch::add, Batch::update, Batch::delete')] + public function testAddUpdateDelete(): void + { + $addedIds = []; + foreach ($this->priceService->batch->add([ + ['productId' => $this->productId, 'catalogGroupId' => 1, 'price' => 10.0, 'currency' => 'USD'], + ]) as $addedItemResult) { + $addedIds[] = $addedItemResult->price()->id; + } + + $this->assertCount(1, $addedIds); + + $updatePayload = []; + foreach ($addedIds as $addedId) { + $updatePayload[$addedId] = ['price' => 20.0, 'currency' => 'USD']; + } + + $updatedCount = 0; + foreach ($this->priceService->batch->update($updatePayload) as $updatedItemResult) { + $this->assertSame(20.0, $updatedItemResult->price()->price); + $updatedCount++; + } + + $this->assertSame(1, $updatedCount); + + $deletedCount = 0; + foreach ($this->priceService->batch->delete($addedIds) as $deletedItemResult) { + $this->assertTrue($deletedItemResult->isSuccess()); + $deletedCount++; + } + + $this->assertSame(1, $deletedCount); + } +} diff --git a/tests/Integration/Services/Catalog/Price/Service/PriceTest.php b/tests/Integration/Services/Catalog/Price/Service/PriceTest.php new file mode 100644 index 00000000..ef761eec --- /dev/null +++ b/tests/Integration/Services/Catalog/Price/Service/PriceTest.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\Price\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\Catalog\Service\Catalog; +use Bitrix24\SDK\Services\Catalog\Price\Service\Price; +use Bitrix24\SDK\Services\Catalog\Product\Service\Product; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Price::class)] +class PriceTest extends TestCase +{ + private Price $priceService; + + private Product $productService; + + private int $productId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceService = $serviceBuilder->getCatalogScope()->price(); + $this->productService = $serviceBuilder->getCatalogScope()->product(); + + $catalogService = $serviceBuilder->getCatalogScope()->catalog(); + $iblockId = $catalogService->list([], [], [], 1)->getCatalogs()[0]->iblockId; + + $this->productId = $this->productService->add([ + 'iblockId' => $iblockId, + 'name' => sprintf('test product for price %s', time()), + ])->product()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->productService->delete($this->productId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Price::add, Price::get, Price::delete')] + public function testAddGetDelete(): void + { + $priceResult = $this->priceService->add([ + 'productId' => $this->productId, + 'catalogGroupId' => 1, + 'price' => 100.5, + 'currency' => 'USD', + ]); + $priceId = $priceResult->price()->id; + $this->assertSame($this->productId, $priceResult->price()->productId); + $this->assertSame(100.5, $priceResult->price()->price); + + $getResult = $this->priceService->get($priceId); + $this->assertSame($priceId, $getResult->price()->id); + + $this->assertTrue($this->priceService->delete($priceId)->isSuccess()); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Price::update')] + public function testUpdate(): void + { + $priceId = $this->priceService->add([ + 'productId' => $this->productId, + 'catalogGroupId' => 1, + 'price' => 100.5, + 'currency' => 'USD', + ])->price()->id; + + $priceResult = $this->priceService->update($priceId, ['price' => 200.0, 'currency' => 'USD']); + $this->assertSame(200.0, $priceResult->price()->price); + + $this->priceService->delete($priceId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Price::list')] + public function testList(): void + { + $priceId = $this->priceService->add([ + 'productId' => $this->productId, + 'catalogGroupId' => 1, + 'price' => 100.5, + 'currency' => 'USD', + ])->price()->id; + + $pricesResult = $this->priceService->list([], ['productId' => $this->productId], ['id' => 'ASC']); + $this->assertGreaterThanOrEqual(1, count($pricesResult->getPrices())); + + $this->priceService->delete($priceId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Price::modify')] + public function testModify(): void + { + $pricesResult = $this->priceService->modify($this->productId, [ + ['catalogGroupId' => 1, 'currency' => 'USD', 'price' => 300.0], + ]); + $prices = $pricesResult->getPrices(); + $this->assertCount(1, $prices); + $this->assertSame(300.0, $prices[0]->price); + + $this->priceService->delete($prices[0]->id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Price::getFields')] + public function testGetFields(): void + { + $this->assertIsArray($this->priceService->getFields()->getFieldsDescription()); + } +} diff --git a/tests/Integration/Services/Catalog/PriceType/Result/PriceTypeItemResultTest.php b/tests/Integration/Services/Catalog/PriceType/Result/PriceTypeItemResultTest.php new file mode 100644 index 00000000..098892fb --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceType/Result/PriceTypeItemResultTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceType\Result; + +use Bitrix24\SDK\Services\Catalog\PriceType\Result\PriceTypeItemResult; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceTypeItemResult::class)] +class PriceTypeItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + #[\Override] + protected function setUp(): void + { + $this->priceTypeService = Fabric::getServiceBuilder()->getCatalogScope()->priceType(); + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type annotations %s', time()), + 'sort' => 50, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + #[Test] + #[TestDox('all fields in PriceTypeItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItem = $this->priceTypeService->get($this->priceTypeId)->getCoreResponse()->getResponseData()->getResult()['priceType']; + $this->assertBitrix24AllResultItemFieldsAnnotated(array_keys($rawItem), PriceTypeItemResult::class); + } + + #[Test] + #[TestDox('all fields in PriceTypeItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $priceTypeItemResult = $this->priceTypeService->get($this->priceTypeId)->priceType(); + $this->assertIsInt($priceTypeItemResult->id); + $this->assertIsString($priceTypeItemResult->name); + $this->assertIsBool($priceTypeItemResult->base); + $this->assertIsInt($priceTypeItemResult->sort); + } +} diff --git a/tests/Integration/Services/Catalog/PriceType/Service/BatchTest.php b/tests/Integration/Services/Catalog/PriceType/Service/BatchTest.php new file mode 100644 index 00000000..bcbfc49d --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceType/Service/BatchTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceType\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\Batch; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private PriceType $priceTypeService; + + #[\Override] + protected function setUp(): void + { + $this->priceTypeService = Fabric::getServiceBuilder()->getCatalogScope()->priceType(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Batch::add, Batch::update, Batch::delete')] + public function testAddUpdateDelete(): void + { + $addedIds = []; + foreach ($this->priceTypeService->batch->add([ + ['name' => sprintf('batch price type %s', time()), 'sort' => 60], + ]) as $addedItemResult) { + $addedIds[] = $addedItemResult->priceType()->id; + } + + $this->assertCount(1, $addedIds); + + $updatePayload = []; + foreach ($addedIds as $addedId) { + $updatePayload[$addedId] = ['sort' => 70]; + } + + $updatedCount = 0; + foreach ($this->priceTypeService->batch->update($updatePayload) as $updatedItemResult) { + $this->assertSame(70, $updatedItemResult->priceType()->sort); + $updatedCount++; + } + + $this->assertSame(1, $updatedCount); + + $deletedCount = 0; + foreach ($this->priceTypeService->batch->delete($addedIds) as $deletedItemResult) { + $this->assertTrue($deletedItemResult->isSuccess()); + $deletedCount++; + } + + $this->assertSame(1, $deletedCount); + } +} diff --git a/tests/Integration/Services/Catalog/PriceType/Service/PriceTypeTest.php b/tests/Integration/Services/Catalog/PriceType/Service/PriceTypeTest.php new file mode 100644 index 00000000..db0896c4 --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceType/Service/PriceTypeTest.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceType\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceType::class)] +class PriceTypeTest extends TestCase +{ + private PriceType $priceTypeService; + + #[\Override] + protected function setUp(): void + { + $this->priceTypeService = Fabric::getServiceBuilder()->getCatalogScope()->priceType(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceType::add, PriceType::get, PriceType::delete')] + public function testAddGetDelete(): void + { + $name = sprintf('test price type %s', time()); + $priceTypeResult = $this->priceTypeService->add([ + 'name' => $name, + 'base' => 'N', + 'sort' => 50, + 'xmlId' => sprintf('test-price-type-%s', time()), + ]); + $priceTypeId = $priceTypeResult->priceType()->id; + $this->assertSame($name, $priceTypeResult->priceType()->name); + $this->assertFalse($priceTypeResult->priceType()->base); + + $getResult = $this->priceTypeService->get($priceTypeId); + $this->assertSame($priceTypeId, $getResult->priceType()->id); + + $this->assertTrue($this->priceTypeService->delete($priceTypeId)->isSuccess()); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceType::update')] + public function testUpdate(): void + { + $priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type %s', time()), + 'sort' => 50, + ])->priceType()->id; + + $updatedName = sprintf('updated price type %s', time()); + $priceTypeResult = $this->priceTypeService->update($priceTypeId, ['name' => $updatedName]); + $this->assertSame($updatedName, $priceTypeResult->priceType()->name); + + $this->priceTypeService->delete($priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceType::list')] + public function testList(): void + { + $priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type %s', time()), + 'sort' => 50, + ])->priceType()->id; + + $priceTypesResult = $this->priceTypeService->list([], ['id' => $priceTypeId]); + $this->assertCount(1, $priceTypesResult->getPriceTypes()); + + $this->priceTypeService->delete($priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceType::getFields')] + public function testGetFields(): void + { + $this->assertIsArray($this->priceTypeService->getFields()->getFieldsDescription()); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResultTest.php b/tests/Integration/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResultTest.php new file mode 100644 index 00000000..5bd3d092 --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeGroup/Result/PriceTypeGroupItemResultTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeGroup\Result; + +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Result\PriceTypeGroupItemResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service\PriceTypeGroup; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceTypeGroupItemResult::class)] +class PriceTypeGroupItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private PriceTypeGroup $priceTypeGroupService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeGroupService = $serviceBuilder->getCatalogScope()->priceTypeGroup(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for group annotations %s', time()), + 'sort' => 90, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + #[Test] + #[TestDox('all fields in PriceTypeGroupItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItems = $this->priceTypeGroupService->list([], ['catalogGroupId' => $this->priceTypeId]) + ->getCoreResponse()->getResponseData()->getResult()['priceTypeGroups']; + $this->assertBitrix24AllResultItemFieldsAnnotated(array_keys($rawItems[0]), PriceTypeGroupItemResult::class); + } + + #[Test] + #[TestDox('all fields in PriceTypeGroupItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $bindings = $this->priceTypeGroupService->list([], ['catalogGroupId' => $this->priceTypeId])->getPriceTypeGroups(); + $this->assertIsInt($bindings[0]->id); + $this->assertIsInt($bindings[0]->catalogGroupId); + $this->assertIsInt($bindings[0]->groupId); + $this->assertIsBool($bindings[0]->access); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeGroup/Service/BatchTest.php b/tests/Integration/Services/Catalog/PriceTypeGroup/Service/BatchTest.php new file mode 100644 index 00000000..b6973ec7 --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeGroup/Service/BatchTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeGroup\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service\Batch; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service\PriceTypeGroup; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private PriceTypeGroup $priceTypeGroupService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeGroupService = $serviceBuilder->getCatalogScope()->priceTypeGroup(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for batch group %s', time()), + 'sort' => 90, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Batch::delete')] + public function testDelete(): void + { + $priceTypeGroupsResult = $this->priceTypeGroupService->list( + [], + ['catalogGroupId' => $this->priceTypeId] + ); + $bindingIds = array_map( + static fn ($binding): int => $binding->id, + $priceTypeGroupsResult->getPriceTypeGroups() + ); + $this->assertNotEmpty($bindingIds); + + $deletedCount = 0; + foreach ($this->priceTypeGroupService->batch->delete($bindingIds) as $deletedItemResult) { + $this->assertTrue($deletedItemResult->isSuccess()); + $deletedCount++; + } + + $this->assertSame(count($bindingIds), $deletedCount); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php b/tests/Integration/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php new file mode 100644 index 00000000..01ea6fde --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeGroup\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeGroup\Service\PriceTypeGroup; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceTypeGroup::class)] +class PriceTypeGroupTest extends TestCase +{ + private PriceTypeGroup $priceTypeGroupService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeGroupService = $serviceBuilder->getCatalogScope()->priceTypeGroup(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + // a newly created price type gets auto-generated bindings for groupId=1 and groupId=2 + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for group %s', time()), + 'sort' => 90, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeGroup::list, PriceTypeGroup::delete, PriceTypeGroup::add')] + public function testListDeleteAdd(): void + { + $priceTypeGroupsResult = $this->priceTypeGroupService->list( + [], + ['catalogGroupId' => $this->priceTypeId, 'groupId' => 1, 'access' => 'N'] + ); + $bindings = $priceTypeGroupsResult->getPriceTypeGroups(); + $this->assertCount(1, $bindings); + $bindingId = $bindings[0]->id; + + $this->assertTrue($this->priceTypeGroupService->delete($bindingId)->isSuccess()); + + $priceTypeGroupResult = $this->priceTypeGroupService->add([ + 'catalogGroupId' => $this->priceTypeId, + 'groupId' => 1, + 'access' => 'N', + ]); + $this->assertSame($this->priceTypeId, $priceTypeGroupResult->priceTypeGroup()->catalogGroupId); + $this->assertSame(1, $priceTypeGroupResult->priceTypeGroup()->groupId); + $this->assertFalse($priceTypeGroupResult->priceTypeGroup()->access); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeGroup::getFields')] + public function testGetFields(): void + { + $this->assertIsArray($this->priceTypeGroupService->getFields()->getFieldsDescription()); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeLang/Result/LanguageItemResultTest.php b/tests/Integration/Services/Catalog/PriceTypeLang/Result/LanguageItemResultTest.php new file mode 100644 index 00000000..82b4df5b --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeLang/Result/LanguageItemResultTest.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\LanguageItemResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service\PriceTypeLang; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(LanguageItemResult::class)] +class LanguageItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private PriceTypeLang $priceTypeLangService; + + #[\Override] + protected function setUp(): void + { + $this->priceTypeLangService = Fabric::getServiceBuilder()->getCatalogScope()->priceTypeLang(); + } + + #[Test] + #[TestDox('all fields in LanguageItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItems = $this->priceTypeLangService->getLanguages()->getCoreResponse()->getResponseData()->getResult()['languages']; + $this->assertBitrix24AllResultItemFieldsAnnotated(array_keys($rawItems[0]), LanguageItemResult::class); + } + + #[Test] + #[TestDox('all fields in LanguageItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $languages = $this->priceTypeLangService->getLanguages()->getLanguages(); + $this->assertIsString($languages[0]->lid); + $this->assertIsString($languages[0]->name); + $this->assertIsBool($languages[0]->active); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResultTest.php b/tests/Integration/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResultTest.php new file mode 100644 index 00000000..d7171e2b --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeLang/Result/PriceTypeLangItemResultTest.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeLang\Result; + +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Result\PriceTypeLangItemResult; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service\PriceTypeLang; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceTypeLangItemResult::class)] +class PriceTypeLangItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private PriceTypeLang $priceTypeLangService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + private int $priceTypeLangId; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeLangService = $serviceBuilder->getCatalogScope()->priceTypeLang(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for lang annotations %s', time()), + 'sort' => 50, + ])->priceType()->id; + + $this->priceTypeLangId = $this->priceTypeLangService->add([ + 'catalogGroupId' => $this->priceTypeId, + 'lang' => 'kz', + 'name' => 'PRICE', + ])->priceTypeLang()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeLangService->delete($this->priceTypeLangId); + $this->priceTypeService->delete($this->priceTypeId); + } + + #[Test] + #[TestDox('all fields in PriceTypeLangItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItem = $this->priceTypeLangService->get($this->priceTypeLangId) + ->getCoreResponse()->getResponseData()->getResult()['priceTypeLang']; + $this->assertBitrix24AllResultItemFieldsAnnotated(array_keys($rawItem), PriceTypeLangItemResult::class); + } + + #[Test] + #[TestDox('all fields in PriceTypeLangItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $priceTypeLangItemResult = $this->priceTypeLangService->get($this->priceTypeLangId)->priceTypeLang(); + $this->assertIsInt($priceTypeLangItemResult->id); + $this->assertIsInt($priceTypeLangItemResult->catalogGroupId); + $this->assertIsString($priceTypeLangItemResult->lang); + $this->assertIsString($priceTypeLangItemResult->name); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeLang/Service/BatchTest.php b/tests/Integration/Services/Catalog/PriceTypeLang/Service/BatchTest.php new file mode 100644 index 00000000..93c44782 --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeLang/Service/BatchTest.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeLang\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service\Batch; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service\PriceTypeLang; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private PriceTypeLang $priceTypeLangService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeLangService = $serviceBuilder->getCatalogScope()->priceTypeLang(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for batch lang %s', time()), + 'sort' => 50, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Batch::add, Batch::update, Batch::delete')] + public function testAddUpdateDelete(): void + { + $addedIds = []; + foreach ($this->priceTypeLangService->batch->add([ + ['catalogGroupId' => $this->priceTypeId, 'lang' => 'kz', 'name' => 'PRICE'], + ]) as $addedItemResult) { + $addedIds[] = $addedItemResult->priceTypeLang()->id; + } + + $this->assertCount(1, $addedIds); + + $updatePayload = []; + foreach ($addedIds as $addedId) { + $updatePayload[$addedId] = ['name' => 'Updated Price']; + } + + $updatedCount = 0; + foreach ($this->priceTypeLangService->batch->update($updatePayload) as $updatedItemResult) { + $this->assertSame('Updated Price', $updatedItemResult->priceTypeLang()->name); + $updatedCount++; + } + + $this->assertSame(1, $updatedCount); + + $deletedCount = 0; + foreach ($this->priceTypeLangService->batch->delete($addedIds) as $deletedItemResult) { + $this->assertTrue($deletedItemResult->isSuccess()); + $deletedCount++; + } + + $this->assertSame(1, $deletedCount); + } +} diff --git a/tests/Integration/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php b/tests/Integration/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php new file mode 100644 index 00000000..c366904a --- /dev/null +++ b/tests/Integration/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\Catalog\PriceTypeLang\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\PriceType\Service\PriceType; +use Bitrix24\SDK\Services\Catalog\PriceTypeLang\Service\PriceTypeLang; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PriceTypeLang::class)] +class PriceTypeLangTest extends TestCase +{ + private PriceTypeLang $priceTypeLangService; + + private PriceType $priceTypeService; + + private int $priceTypeId; + + /** + * @throws BaseException + * @throws TransportException + */ + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Fabric::getServiceBuilder(); + $this->priceTypeLangService = $serviceBuilder->getCatalogScope()->priceTypeLang(); + $this->priceTypeService = $serviceBuilder->getCatalogScope()->priceType(); + + $this->priceTypeId = $this->priceTypeService->add([ + 'name' => sprintf('test price type for lang %s', time()), + 'sort' => 50, + ])->priceType()->id; + } + + #[\Override] + protected function tearDown(): void + { + $this->priceTypeService->delete($this->priceTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeLang::add, PriceTypeLang::get, PriceTypeLang::delete')] + public function testAddGetDelete(): void + { + $priceTypeLangResult = $this->priceTypeLangService->add([ + 'catalogGroupId' => $this->priceTypeId, + 'lang' => 'kz', + 'name' => 'PRICE', + ]); + $langId = $priceTypeLangResult->priceTypeLang()->id; + $this->assertSame('PRICE', $priceTypeLangResult->priceTypeLang()->name); + $this->assertSame('kz', $priceTypeLangResult->priceTypeLang()->lang); + + $getResult = $this->priceTypeLangService->get($langId); + $this->assertSame($langId, $getResult->priceTypeLang()->id); + + $this->assertTrue($this->priceTypeLangService->delete($langId)->isSuccess()); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeLang::update')] + public function testUpdate(): void + { + $langId = $this->priceTypeLangService->add([ + 'catalogGroupId' => $this->priceTypeId, + 'lang' => 'kz', + 'name' => 'PRICE', + ])->priceTypeLang()->id; + + $priceTypeLangResult = $this->priceTypeLangService->update($langId, ['name' => 'Base Price']); + $this->assertSame('Base Price', $priceTypeLangResult->priceTypeLang()->name); + + $this->priceTypeLangService->delete($langId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeLang::list')] + public function testList(): void + { + $langId = $this->priceTypeLangService->add([ + 'catalogGroupId' => $this->priceTypeId, + 'lang' => 'kz', + 'name' => 'PRICE', + ])->priceTypeLang()->id; + + $priceTypeLangsResult = $this->priceTypeLangService->list([], ['catalogGroupId' => $this->priceTypeId]); + $this->assertCount(1, $priceTypeLangsResult->getPriceTypeLangs()); + + $this->priceTypeLangService->delete($langId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeLang::getLanguages')] + public function testGetLanguages(): void + { + $languages = $this->priceTypeLangService->getLanguages()->getLanguages(); + $this->assertNotEmpty($languages); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test PriceTypeLang::getFields')] + public function testGetFields(): void + { + $this->assertIsArray($this->priceTypeLangService->getFields()->getFieldsDescription()); + } +} diff --git a/tests/Unit/Services/Catalog/Price/Service/PriceTest.php b/tests/Unit/Services/Catalog/Price/Service/PriceTest.php new file mode 100644 index 00000000..836eabb5 --- /dev/null +++ b/tests/Unit/Services/Catalog/Price/Service/PriceTest.php @@ -0,0 +1,112 @@ +mockCore('catalog.price.add', [ + 'fields' => ['productId' => 1, 'catalogGroupId' => 1, 'price' => 100.0, 'currency' => 'USD'], + ]); + + self::assertInstanceOf( + PriceResult::class, + $this->makeService($core)->add(['productId' => 1, 'catalogGroupId' => 1, 'price' => 100.0, 'currency' => 'USD']) + ); + } + + public function testUpdateBuildsParameters(): void + { + $core = $this->mockCore('catalog.price.update', [ + 'id' => 1, + 'fields' => ['price' => 5000.0, 'currency' => 'RUB'], + ]); + + self::assertInstanceOf( + PriceResult::class, + $this->makeService($core)->update(1, ['price' => 5000.0, 'currency' => 'RUB']) + ); + } + + public function testModifyBuildsParameters(): void + { + $prices = [ + ['catalogGroupId' => 1, 'currency' => 'RUB', 'price' => 2001.0], + ]; + + $core = $this->mockCore('catalog.price.modify', [ + 'fields' => ['product' => ['id' => 8, 'prices' => $prices]], + ]); + + self::assertInstanceOf(PricesResult::class, $this->makeService($core)->modify(8, $prices)); + } + + public function testGetFieldsBuildsParameters(): void + { + $core = $this->mockCore('catalog.price.getFields', []); + + self::assertInstanceOf(PriceFieldsResult::class, $this->makeService($core)->getFields()); + } + + public function testListBuildsParameters(): void + { + $core = $this->mockCore('catalog.price.list', [ + 'select' => ['id', 'price'], + 'filter' => ['productId' => 1], + 'order' => ['id' => 'ASC'], + ]); + + self::assertInstanceOf( + PricesResult::class, + $this->makeService($core)->list(['id', 'price'], ['productId' => 1], ['id' => 'ASC']) + ); + } + + public function testGetBuildsParameters(): void + { + $core = $this->mockCore('catalog.price.get', ['id' => 1]); + + self::assertInstanceOf(PriceResult::class, $this->makeService($core)->get(1)); + } + + public function testDeleteBuildsParameters(): void + { + $core = $this->mockCore('catalog.price.delete', ['id' => 1]); + + self::assertInstanceOf(DeletedItemResult::class, $this->makeService($core)->delete(1)); + } + + private function makeService(CoreInterface $core): Price + { + return new Price(new Batch(new PriceBatch($core, new NullLogger()), new NullLogger()), $core, new NullLogger()); + } + + private function mockCore(string $method, array $parameters): CoreInterface + { + $response = $this->createStub(Response::class); + $core = $this->createMock(CoreInterface::class); + $core->expects($this->once()) + ->method('call') + ->with($method, $parameters) + ->willReturn($response); + + return $core; + } +} diff --git a/tests/Unit/Services/Catalog/PriceType/Service/PriceTypeTest.php b/tests/Unit/Services/Catalog/PriceType/Service/PriceTypeTest.php new file mode 100644 index 00000000..99ea0033 --- /dev/null +++ b/tests/Unit/Services/Catalog/PriceType/Service/PriceTypeTest.php @@ -0,0 +1,99 @@ +mockCore('catalog.priceType.add', [ + 'fields' => ['name' => 'Wholesale price', 'base' => 'N', 'sort' => 10, 'xmlId' => 'wholesale'], + ]); + + self::assertInstanceOf( + PriceTypeResult::class, + $this->makeService($core)->add(['name' => 'Wholesale price', 'base' => 'N', 'sort' => 10, 'xmlId' => 'wholesale']) + ); + } + + public function testUpdateBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceType.update', [ + 'id' => 2, + 'fields' => ['name' => 'Base wholesale price', 'base' => 'Y'], + ]); + + self::assertInstanceOf( + PriceTypeResult::class, + $this->makeService($core)->update(2, ['name' => 'Base wholesale price', 'base' => 'Y']) + ); + } + + public function testGetBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceType.get', ['id' => 1]); + + self::assertInstanceOf(PriceTypeResult::class, $this->makeService($core)->get(1)); + } + + public function testListBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceType.list', [ + 'select' => ['id', 'name'], + 'filter' => ['modifiedBy' => 1], + 'order' => ['id' => 'ASC'], + ]); + + self::assertInstanceOf( + PriceTypesResult::class, + $this->makeService($core)->list(['id', 'name'], ['modifiedBy' => 1], ['id' => 'ASC']) + ); + } + + public function testDeleteBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceType.delete', ['id' => 2]); + + self::assertInstanceOf(DeletedItemResult::class, $this->makeService($core)->delete(2)); + } + + public function testGetFieldsBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceType.getFields', []); + + self::assertInstanceOf(PriceTypeFieldsResult::class, $this->makeService($core)->getFields()); + } + + private function makeService(CoreInterface $core): PriceType + { + return new PriceType(new Batch(new PriceTypeBatch($core, new NullLogger()), new NullLogger()), $core, new NullLogger()); + } + + private function mockCore(string $method, array $parameters): CoreInterface + { + $response = $this->createStub(Response::class); + $core = $this->createMock(CoreInterface::class); + $core->expects($this->once()) + ->method('call') + ->with($method, $parameters) + ->willReturn($response); + + return $core; + } +} diff --git a/tests/Unit/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php b/tests/Unit/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php new file mode 100644 index 00000000..369cf868 --- /dev/null +++ b/tests/Unit/Services/Catalog/PriceTypeGroup/Service/PriceTypeGroupTest.php @@ -0,0 +1,84 @@ +mockCore('catalog.priceTypeGroup.add', [ + 'fields' => ['catalogGroupId' => 9, 'groupId' => 23, 'access' => 'Y'], + ]); + + self::assertInstanceOf( + PriceTypeGroupResult::class, + $this->makeService($core)->add(['catalogGroupId' => 9, 'groupId' => 23, 'access' => 'Y']) + ); + } + + public function testListBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeGroup.list', [ + 'select' => ['id', 'catalogGroupId'], + 'filter' => ['catalogGroupId' => 9], + 'order' => ['id' => 'ASC'], + 'start' => 0, + ]); + + self::assertInstanceOf( + PriceTypeGroupsResult::class, + $this->makeService($core)->list(['id', 'catalogGroupId'], ['catalogGroupId' => 9], ['id' => 'ASC'], 0) + ); + } + + public function testDeleteBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeGroup.delete', ['id' => 109]); + + self::assertInstanceOf(DeletedItemResult::class, $this->makeService($core)->delete(109)); + } + + public function testGetFieldsBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeGroup.getFields', []); + + self::assertInstanceOf(PriceTypeGroupFieldsResult::class, $this->makeService($core)->getFields()); + } + + private function makeService(CoreInterface $core): PriceTypeGroup + { + return new PriceTypeGroup( + new Batch(new PriceTypeGroupBatch($core, new NullLogger()), new NullLogger()), + $core, + new NullLogger() + ); + } + + private function mockCore(string $method, array $parameters): CoreInterface + { + $response = $this->createStub(Response::class); + $core = $this->createMock(CoreInterface::class); + $core->expects($this->once()) + ->method('call') + ->with($method, $parameters) + ->willReturn($response); + + return $core; + } +} diff --git a/tests/Unit/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php b/tests/Unit/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php new file mode 100644 index 00000000..18099f75 --- /dev/null +++ b/tests/Unit/Services/Catalog/PriceTypeLang/Service/PriceTypeLangTest.php @@ -0,0 +1,110 @@ +mockCore('catalog.priceTypeLang.add', [ + 'fields' => ['catalogGroupId' => 1, 'lang' => 'kz', 'name' => 'PRICE'], + ]); + + self::assertInstanceOf( + PriceTypeLangResult::class, + $this->makeService($core)->add(['catalogGroupId' => 1, 'lang' => 'kz', 'name' => 'PRICE']) + ); + } + + public function testUpdateBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.update', [ + 'id' => 6, + 'fields' => ['name' => 'Base Price'], + ]); + + self::assertInstanceOf( + PriceTypeLangResult::class, + $this->makeService($core)->update(6, ['name' => 'Base Price']) + ); + } + + public function testGetBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.get', ['id' => 2]); + + self::assertInstanceOf(PriceTypeLangResult::class, $this->makeService($core)->get(2)); + } + + public function testListBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.list', [ + 'select' => ['name', 'lang'], + 'filter' => ['catalogGroupId' => 1], + ]); + + self::assertInstanceOf( + PriceTypeLangsResult::class, + $this->makeService($core)->list(['name', 'lang'], ['catalogGroupId' => 1]) + ); + } + + public function testDeleteBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.delete', ['id' => 3]); + + self::assertInstanceOf(DeletedItemResult::class, $this->makeService($core)->delete(3)); + } + + public function testGetLanguagesBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.getLanguages', []); + + self::assertInstanceOf(LanguagesResult::class, $this->makeService($core)->getLanguages()); + } + + public function testGetFieldsBuildsParameters(): void + { + $core = $this->mockCore('catalog.priceTypeLang.getFields', []); + + self::assertInstanceOf(PriceTypeLangFieldsResult::class, $this->makeService($core)->getFields()); + } + + private function makeService(CoreInterface $core): PriceTypeLang + { + return new PriceTypeLang( + new Batch(new PriceTypeLangBatch($core, new NullLogger()), new NullLogger()), + $core, + new NullLogger() + ); + } + + private function mockCore(string $method, array $parameters): CoreInterface + { + $response = $this->createStub(Response::class); + $core = $this->createMock(CoreInterface::class); + $core->expects($this->once()) + ->method('call') + ->with($method, $parameters) + ->willReturn($response); + + return $core; + } +}