diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 26d3a1eb..6c868f23 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -15,12 +15,12 @@ ->in(__DIR__ . '/src/Services/CRM/Requisites/') ->in(__DIR__ . '/src/Services/CRM/Status/') ->in(__DIR__ . '/src/Services/CRM/Timeline/') + ->in(__DIR__ . '/src/Services/CRM/Documentgenerator/Numerator/') ->in(__DIR__ . '/src/Services/Entity/Section/') ->in(__DIR__ . '/src/Services/Department/') ->in(__DIR__ . '/src/Services/Paysystem/') ->in(__DIR__ . '/src/Services/Sale/') ->in(__DIR__ . '/src/Services/Task/') - ->in(__DIR__ . '/src/Services/Sale/') ->name('*.php') ->exclude(['vendor', 'storage', 'docker', 'docs']) // Exclude directories ->ignoreDotFiles(true) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc877103..756cdacb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ ### Added +- Added service `Services\CRM\Documentgenerator\Numerator` with support methods, + see [crm.documentgenerator.numerator.* methods](https://github.com/bitrix24/b24phpsdk/issues/215): + - `add` adds a new numerator, with batch calls support + - `list` gets the list of numerators, with batch calls support + - `update` updates an existing numbering with new values, with batch calls support + - `delete` deletes a numerator, with batch calls support + - `get` gets information about the numerator by its identifier + - `count` count numerators - Added service `Services\Paysystem\Handler\Service\Handler` with support methods, see [pay_system.handler.* methods](https://github.com/bitrix24/b24phpsdk/issues/260): - `add` adds a payment system handler diff --git a/Makefile b/Makefile index 0e8a2f70..de1df352 100644 --- a/Makefile +++ b/Makefile @@ -259,7 +259,7 @@ test-integration-sale-payment-item-shipment: .PHONY: test-integration-sale-property-relation test-integration-sale-property-relation: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_sale_property_relation - + .PHONY: test-integration-scope-crm test-integration-scope-crm: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_crm @@ -356,6 +356,10 @@ integration_tests_sale_payment: integration_tests_sale_payment_item_basket: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_sale_payment_item_basket +.PHONY: integration_tests_crm_documentgenerator_numerator +integration_tests_crm_documentgenerator_numerator: + docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_crm_documentgenerator_numerator + # work dev environment .PHONY: php-dev-server-up php-dev-server-up: @@ -411,4 +415,3 @@ build-examples-for-documentation: --example-template=docs/api/file-templates/examples/master-example.php \ --openai-api-key=$(DOCUMENTATION_OPEN_AI_API_KEY) \ --docs-repo-folder=$(DOCUMENTATION_REPOSITORY_FOLDER) - diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c4d6b7ba..7e824f28 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -30,6 +30,7 @@ parameters: - tests/Integration/Services/CRM/Requisites - tests/Integration/Services/Task - tests/Integration/Services/Sale + - tests/Integration/Services/CRM/Documentgenerator/Numerator excludePaths: - tests/Integration/Services/CRM/Requisites/Service/RequisiteUserfieldUseCaseTest.php - tests/Integration/Services/CRM/Status diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 50f79e31..46101756 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -169,6 +169,9 @@ ./tests/Integration/Services/Sale/ShipmentItem/ + + ./tests/Integration/Services/CRM/Documentgenerator/Numerator/ + diff --git a/rector.php b/rector.php index 892855ab..bd486ee8 100644 --- a/rector.php +++ b/rector.php @@ -64,6 +64,8 @@ __DIR__ . '/tests/Integration/Services/Task', __DIR__ . '/src/Services/Sale', __DIR__ . '/tests/Integration/Services/Sale', + __DIR__ . '/src/Services/CRM/Documentgenerator/Numerator', + __DIR__ . '/tests/Integration/Services/CRM/Documentgenerator/Numerator', __DIR__ . '/tests/Unit/', ]) ->withCache(cacheDirectory: __DIR__ . '.cache/rector') diff --git a/src/Services/CRM/CRMServiceBuilder.php b/src/Services/CRM/CRMServiceBuilder.php index d72be5ce..b4905fc3 100644 --- a/src/Services/CRM/CRMServiceBuilder.php +++ b/src/Services/CRM/CRMServiceBuilder.php @@ -653,4 +653,22 @@ public function timelineBindings(): Timeline\Bindings\Service\Bindings return $this->serviceCache[__METHOD__]; } + + public function documentgeneratorNumerator(): Documentgenerator\Numerator\Service\Numerator + { + if (!isset($this->serviceCache[__METHOD__])) { + // Use specialized Batch for Numerator to ensure correct REST parameter mapping (e.g., 'id') + $numeratorBatch = new Documentgenerator\Numerator\Batch( + $this->core, + $this->log + ); + $this->serviceCache[__METHOD__] = new Documentgenerator\Numerator\Service\Numerator( + new Documentgenerator\Numerator\Service\Batch($numeratorBatch, $this->log), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } } diff --git a/src/Services/CRM/Documentgenerator/Numerator/Batch.php b/src/Services/CRM/Documentgenerator/Numerator/Batch.php new file mode 100644 index 00000000..6a9a6c71 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Batch.php @@ -0,0 +1,93 @@ + + * + * 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\CRM\Documentgenerator\Numerator; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Delete entity items with batch call + * + * + * @return Generator|ResponseData[] + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + */ + 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 => $code) { + if (!is_int($code)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of numerator id «%s» at position %s, id must be integer type', + gettype($code), + $code, + $cnt + ) + ); + } + + $parameters = ['id' => $code]; + $this->registerCommand($apiMethod, $parameters); + } + + foreach ($this->getTraversable(true) as $cnt => $deletedItemResult) { + yield $cnt => $deletedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch delete entity items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch delete entity 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/CRM/Documentgenerator/Numerator/Result/AddedNumeratorBatchResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/AddedNumeratorBatchResult.php new file mode 100644 index 00000000..f770ba94 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/AddedNumeratorBatchResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Result\AddedItemBatchResult; + +/** + * Class AddedNumeratorBatchResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class AddedNumeratorBatchResult extends AddedItemBatchResult +{ + public function getId(): int + { + return (int)$this->getResponseData()->getResult()['numerator']['id']; + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/AddedNumeratorResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/AddedNumeratorResult.php new file mode 100644 index 00000000..ac11cbbe --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/AddedNumeratorResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Result\AddedItemResult; +use Bitrix24\SDK\Core\Exceptions\BaseException; + +/** + * Class AddedNumeratorResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class AddedNumeratorResult extends AddedItemResult +{ + /** + * @throws BaseException + */ + public function getId(): int + { + return (int)$this->getCoreResponse()->getResponseData()->getResult()['numerator']['id']; + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorBatchResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorBatchResult.php new file mode 100644 index 00000000..aa7f9f50 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorBatchResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; + +/** + * Class DeletedNumeratorBatchResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class DeletedNumeratorBatchResult extends DeletedItemBatchResult +{ + public function isSuccess(): bool + { + return (bool)$this->getResponseData()->getResult(); + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorResult.php new file mode 100644 index 00000000..f760244f --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/DeletedNumeratorResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemResult; + +/** + * Class DeletedNumeratorResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class DeletedNumeratorResult extends DeletedItemResult +{ + /** + * @throws BaseException + */ + public function isSuccess(): bool + { + return (bool)$this->getCoreResponse()->getResponseData()->getResult(); + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorItemResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorItemResult.php new file mode 100644 index 00000000..241cb6d0 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorItemResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Services\CRM\Common\Result\AbstractCrmItem; + +/** + * Class NumeratorItemResult + * + * @property-read int $id + * @property-read string $name + * @property-read string $template + * @property-read array|null $settings + */ +class NumeratorItemResult extends AbstractCrmItem +{ +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorResult.php new file mode 100644 index 00000000..717ad45f --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +/** + * Class NumeratorResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class NumeratorResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function numerator(): NumeratorItemResult + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + // Be tolerant to different API payload shapes + if (!empty($result['numerator']) && is_array($result['numerator'])) { + $result = $result['numerator']; + } + + return new NumeratorItemResult($result); + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorsResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorsResult.php new file mode 100644 index 00000000..465674fc --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/NumeratorsResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +/** + * Class NumeratorsResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class NumeratorsResult extends AbstractResult +{ + /** + * @return NumeratorItemResult[] + * @throws BaseException + */ + public function getNumerators(): array + { + $items = []; + $source = []; + + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + if (!empty($result['numerators']) && is_array($result['numerators'])) { + $source = $result['numerators']; + } elseif (!empty($result['items']) && is_array($result['items'])) { + $source = $result['items']; + } + + foreach ($source as $item) { + $items[] = new NumeratorItemResult($item); + } + + return $items; + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorBatchResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorBatchResult.php new file mode 100644 index 00000000..b73b514c --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorBatchResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Result\UpdatedItemBatchResult; + +/** + * Class UpdatedNumeratorBatchResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class UpdatedNumeratorBatchResult extends UpdatedItemBatchResult +{ + public function isSuccess(): bool + { + return (bool)$this->getResponseData()->getResult(); + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorResult.php b/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorResult.php new file mode 100644 index 00000000..fbf08705 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Result/UpdatedNumeratorResult.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\CRM\Documentgenerator\Numerator\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\UpdatedItemResult; + +/** + * Class UpdatedNumeratorResult + * + * @package Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result + */ +class UpdatedNumeratorResult extends UpdatedItemResult +{ + /** + * @throws BaseException + */ + public function isSuccess(): bool + { + return (bool)$this->getCoreResponse()->getResponseData()->getResult(); + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Service/Batch.php b/src/Services/CRM/Documentgenerator/Numerator/Service/Batch.php new file mode 100644 index 00000000..1139c41c --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Service/Batch.php @@ -0,0 +1,156 @@ + + * + * 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\CRM\Documentgenerator\Numerator\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Contracts\BatchOperationsInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\AddedNumeratorBatchResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\UpdatedNumeratorBatchResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\DeletedNumeratorBatchResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\NumeratorItemResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['crm']))] +class Batch +{ + /** + * Batch constructor + */ + public function __construct(protected BatchOperationsInterface $batch, protected LoggerInterface $log) + { + } + + /** + * Batch list method for numerators + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'crm.documentgenerator.numerator.list', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-list.html', + 'Batch list method for numerators' + )] + public function list(?int $limit = null): Generator + { + $this->log->debug( + 'batchList', + [ + 'limit' => $limit, + ] + ); + + // Use pagination-based traversable to avoid dependency on element ID field name + $numeratorListGenerator = $this->batch->getTraversableListWithCount( + 'crm.documentgenerator.numerator.list', + [], + [], + [], + $limit + ); + foreach ($numeratorListGenerator as $key => $value) { + yield $key => new NumeratorItemResult($value); + } + } + + /** + * Batch adding numerators + * + * @param array $numerators + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'crm.documentgenerator.numerator.add', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-add.html', + 'Batch adding numerators' + )] + public function add(array $numerators): Generator + { + $items = []; + foreach ($numerators as $item) { + $items[] = [ + 'fields' => $item, + ]; + } + + foreach ($this->batch->addEntityItems('crm.documentgenerator.numerator.add', $items) as $key => $item) { + yield $key => new AddedNumeratorBatchResult($item); + } + } + + /** + * Batch update numerators + * + * Update elements in array with structure + * id => [ // Numerator id + * 'fields' => [] // Numerator fields to update + * ] + * + * @param array $entityItems + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'crm.documentgenerator.numerator.update', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-update.html', + 'Update in batch mode a list of numerators' + )] + public function update(array $entityItems): Generator + { + foreach ( + $this->batch->updateEntityItems( + 'crm.documentgenerator.numerator.update', + $entityItems + ) as $key => $item + ) { + yield $key => new UpdatedNumeratorBatchResult($item); + } + } + + /** + * Batch delete numerators + * + * @param int[] $numeratorId + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'crm.documentgenerator.numerator.delete', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-delete.html', + 'Batch delete numerators' + )] + public function delete(array $numeratorId): Generator + { + foreach ( + $this->batch->deleteEntityItems( + 'crm.documentgenerator.numerator.delete', + $numeratorId + ) as $key => $item + ) { + yield $key => new DeletedNumeratorBatchResult($item); + } + } +} diff --git a/src/Services/CRM/Documentgenerator/Numerator/Service/Numerator.php b/src/Services/CRM/Documentgenerator/Numerator/Service/Numerator.php new file mode 100644 index 00000000..a0f73eb5 --- /dev/null +++ b/src/Services/CRM/Documentgenerator/Numerator/Service/Numerator.php @@ -0,0 +1,192 @@ + + * + * 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\CRM\Documentgenerator\Numerator\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\Services\AbstractService; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\AddedNumeratorResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\DeletedNumeratorResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\NumeratorResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\NumeratorsResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\UpdatedNumeratorResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['crm']))] +class Numerator extends AbstractService +{ + /** + * Numerator constructor + */ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Adds a new numerator + * + * @link https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-add.html + * + * @param array{ + * name: string, + * template: string, + * settings?: array + * } $fields + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.documentgenerator.numerator.add', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-add.html', + 'Adds a new numerator' + )] + public function add(array $fields): AddedNumeratorResult + { + return new AddedNumeratorResult( + $this->core->call( + 'crm.documentgenerator.numerator.add', + [ + 'fields' => $fields + ] + ) + ); + } + + /** + * Removes a numerator + * + * @link https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-delete.html + * + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.documentgenerator.numerator.delete', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-delete.html', + 'Removes a numerator' + )] + public function delete(int $id): DeletedNumeratorResult + { + $params = [ + 'id' => $id, + ]; + + return new DeletedNumeratorResult( + $this->core->call( + 'crm.documentgenerator.numerator.delete', + $params + ) + ); + } + + /** + * Returns information about the numerator by its identifier + * + * @link https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-get.html + * + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.documentgenerator.numerator.get', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-get.html', + 'Returns information about the numerator by its identifier' + )] + public function get(int $id): NumeratorResult + { + return new NumeratorResult($this->core->call('crm.documentgenerator.numerator.get', ['id' => $id])); + } + + /** + * Returns a list of numerators + * + * @link https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-list.html + * + * @param int $start - offset for pagination + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.documentgenerator.numerator.list', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-list.html', + 'Returns a list of numerators' + )] + public function list(int $start = 0): NumeratorsResult + { + return new NumeratorsResult( + $this->core->call( + 'crm.documentgenerator.numerator.list', + [ + 'start' => $start + ] + ) + ); + } + + /** + * Updates an existing numbering with new values + * + * The method crm.documentgenerator.numerator.update updates an existing numbering with new values + * + * @link https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-update.html + * + * @param array{ + * name: string, + * template: string, + * settings?: array + * } $fields + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.documentgenerator.numerator.update', + 'https://apidocs.bitrix24.com/api-reference/crm/document-generator/numerator/crm-document-generator-numerator-update.html', + 'Updates an existing numbering with new values' + )] + public function update(int $id, array $fields): UpdatedNumeratorResult + { + $params = [ + 'id' => $id, + 'fields' => $fields + ]; + + return new UpdatedNumeratorResult( + $this->core->call( + 'crm.documentgenerator.numerator.update', + $params + ) + ); + } + + /** + * Count numerators + * + * @throws BaseException + * @throws TransportException + */ + public function count(): int + { + return $this->list()->getCoreResponse()->getResponseData()->getPagination()->getTotal(); + } +} diff --git a/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/BatchTest.php b/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/BatchTest.php new file mode 100644 index 00000000..f9a8f270 --- /dev/null +++ b/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/BatchTest.php @@ -0,0 +1,165 @@ + + * 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\CRM\Documentgenerator\Numerator\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Service\Numerator; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\TestCase; +use Faker; + +/** + * Class BatchTest + * + * @package Bitrix24\SDK\Tests\Integration\Services\CRM\Documentgenerator\Numerator\Service + */ +#[\PHPUnit\Framework\Attributes\CoversClass(\Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Service\Batch::class)] +class BatchTest extends TestCase +{ + protected Numerator $numeratorService; + + private Faker\Generator $faker; + + /** + * @throws InvalidArgumentException + */ + protected function setUp(): void + { + $this->numeratorService = Fabric::getServiceBuilder()->getCRMScope()->documentgeneratorNumerator(); + $this->faker = Faker\Factory::create(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch list numerators')] + public function testBatchList(): void + { + $id = $this->numeratorService->add([ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'BL-{NUMBER}', + ])->getId(); + + $cnt = 0; + foreach ($this->numeratorService->batch->list(1) as $item) { + $cnt++; + } + + self::assertGreaterThanOrEqual(1, $cnt); + + // Cleanup + $this->numeratorService->delete($id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch add numerators')] + public function testBatchAdd(): void + { + $items = []; + for ($i = 1; $i <= 5; $i++) { + $items[] = [ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'BA-{NUMBER}', + ]; + } + + $ids = []; + $cnt = 0; + foreach ($this->numeratorService->batch->add($items) as $added) { + $cnt++; + $ids[] = $added->getId(); + } + + self::assertEquals(count($items), $cnt); + + $delCnt = 0; + foreach ($this->numeratorService->batch->delete($ids) as $deleted) { + $delCnt++; + } + + self::assertEquals(count($items), $delCnt); + } + + /** + * @throws BaseException + */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch delete numerators')] + public function testBatchDelete(): void + { + $items = []; + for ($i = 1; $i <= 5; $i++) { + $items[] = [ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'BD-{NUMBER}', + ]; + } + + $ids = []; + foreach ($this->numeratorService->batch->add($items) as $added) { + $ids[] = $added->getId(); + } + + $delCnt = 0; + foreach ($this->numeratorService->batch->delete($ids) as $deleted) { + $delCnt++; + } + + self::assertEquals(count($items), $delCnt); + } + + /** + * @throws BaseException + */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch update numerators')] + public function testBatchUpdate(): void + { + $items = []; + for ($i = 1; $i <= 5; $i++) { + $items[] = [ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'BU-{NUMBER}', + ]; + } + + $updatePayload = []; + foreach ($this->numeratorService->batch->add($items) as $added) { + $id = $added->getId(); + $updatePayload[$id] = [ + 'fields' => [ + 'name' => 'updated-' . $id, + 'template' => 'BU2-{NUMBER}', + ], + ]; + } + + foreach ($this->numeratorService->batch->update($updatePayload) as $updated) { + $this->assertTrue($updated->isSuccess()); + } + + // Cleanup + $ids = array_keys($updatePayload); + $deletedCount = 0; + foreach ($this->numeratorService->batch->delete($ids) as $deleted) { + $deletedCount++; + } + + self::assertEquals(count($ids), $deletedCount); + + self::assertTrue(true); + } +} diff --git a/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/NumeratorTest.php b/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/NumeratorTest.php new file mode 100644 index 00000000..26485191 --- /dev/null +++ b/tests/Integration/Services/CRM/Documentgenerator/Numerator/Service/NumeratorTest.php @@ -0,0 +1,173 @@ + + * + * 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\CRM\Documentgenerator\Numerator\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Result\NumeratorItemResult; +use Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Service\Numerator; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversMethod; +use PHPUnit\Framework\TestCase; +use Faker; + +/** + * Class NumeratorTest + * + * @package Bitrix24\SDK\Tests\Integration\Services\CRM\Documentgenerator\Numerator\Service + */ +#[CoversMethod(Numerator::class, 'add')] +#[CoversMethod(Numerator::class, 'delete')] +#[CoversMethod(Numerator::class, 'get')] +#[CoversMethod(Numerator::class, 'list')] +#[CoversMethod(Numerator::class, 'update')] +#[\PHPUnit\Framework\Attributes\CoversClass(\Bitrix24\SDK\Services\CRM\Documentgenerator\Numerator\Service\Numerator::class)] +class NumeratorTest extends TestCase +{ + use CustomBitrix24Assertions; + + private Numerator $numeratorService; + + private Faker\Generator $faker; + + /** + * @throws InvalidArgumentException + */ + protected function setUp(): void + { + $this->numeratorService = Fabric::getServiceBuilder()->getCRMScope()->documentgeneratorNumerator(); + $this->faker = Faker\Factory::create(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testAdd(): void + { + $name = 'num-' . $this->faker->uuid(); + $id = $this->numeratorService->add([ + 'name' => $name, + 'template' => 'N-{NUMBER}', + ])->getId(); + + self::assertGreaterThanOrEqual(1, $id); + + // Cleanup + $this->numeratorService->delete($id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testGet(): void + { + $name = 'num-' . $this->faker->uuid(); + $id = $this->numeratorService->add([ + 'name' => $name, + 'template' => 'G-{NUMBER}', + ])->getId(); + + $numeratorItemResult = $this->numeratorService->get($id)->numerator(); + self::assertInstanceOf(NumeratorItemResult::class, $numeratorItemResult); + self::assertEquals($id, $numeratorItemResult->id); + self::assertEquals($name, $numeratorItemResult->name); + + // Cleanup + $this->numeratorService->delete($id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testList(): void + { + $name = 'num-' . $this->faker->uuid(); + $id = $this->numeratorService->add([ + 'name' => $name, + 'template' => 'L-{NUMBER}', + ])->getId(); + + $list = $this->numeratorService->list()->getNumerators(); + self::assertIsArray($list); + self::assertGreaterThanOrEqual(1, count($list)); + + // Cleanup + $this->numeratorService->delete($id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testUpdate(): void + { + $name = 'num-' . $this->faker->uuid(); + $id = $this->numeratorService->add([ + 'name' => $name, + 'template' => 'U-{NUMBER}', + ])->getId(); + + $newName = $name . '-updated'; + self::assertTrue( + $this->numeratorService->update($id, [ + 'name' => $newName, + 'template' => 'U2-{NUMBER}', + ])->isSuccess() + ); + + self::assertEquals($newName, $this->numeratorService->get($id)->numerator()->name); + + // Cleanup + $this->numeratorService->delete($id); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testDelete(): void + { + $id = $this->numeratorService->add([ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'D-{NUMBER}', + ])->getId(); + + self::assertTrue($this->numeratorService->delete($id)->isSuccess()); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testCount(): void + { + $countBefore = $this->numeratorService->count(); + + $id = $this->numeratorService->add([ + 'name' => 'num-' . $this->faker->uuid(), + 'template' => 'C-{NUMBER}', + ])->getId(); + + $countAfter = $this->numeratorService->count(); + self::assertEquals($countBefore + 1, $countAfter); + + // Cleanup + $this->numeratorService->delete($id); + } +}