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;
+ }
+}