From 140afb8637bd5e68fc71c7e918823ba2d0862faa Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Mon, 25 Aug 2025 09:52:46 +0400 Subject: [PATCH 1/3] add payer status classes and tests; run tests and linters --- .php-cs-fixer.php | 1 + Makefile | 4 + phpstan.neon.dist | 1 + phpunit.xml.dist | 3 + rector.php | 2 + .../Result/PersonTypeStatusAddResult.php | 29 ++++ .../Result/PersonTypeStatusFieldsResult.php | 28 ++++ .../Result/PersonTypeStatusItemResult.php | 27 ++++ .../Result/PersonTypeStatusesResult.php | 32 ++++ .../Service/PersonTypeStatus.php | 138 ++++++++++++++++++ src/Services/Sale/SaleServiceBuilder.php | 26 ++++ src/Services/ServiceBuilder.php | 17 ++- .../Service/PersonTypeStatusTest.php | 105 +++++++++++++ 13 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusAddResult.php create mode 100644 src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusFieldsResult.php create mode 100644 src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusItemResult.php create mode 100644 src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusesResult.php create mode 100644 src/Services/Sale/PersonTypeStatus/Service/PersonTypeStatus.php create mode 100644 src/Services/Sale/SaleServiceBuilder.php create mode 100644 tests/Integration/Services/Sale/PersonTypeStatus/Service/PersonTypeStatusTest.php diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index eb369907..95cc23a9 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -17,6 +17,7 @@ ->in(__DIR__ . '/src/Services/CRM/Timeline/') ->in(__DIR__ . '/src/Services/Entity/Section/') ->in(__DIR__ . '/src/Services/Department/') + ->in(__DIR__ . '/src/Services/Sale/') ->in(__DIR__ . '/src/Services/Task/') ->name('*.php') ->exclude(['vendor', 'storage', 'docker', 'docs']) // Exclude directories diff --git a/Makefile b/Makefile index 6c20a4c7..13d90efd 100644 --- a/Makefile +++ b/Makefile @@ -267,6 +267,10 @@ integration_tests_crm_timeline: integration_tests_department: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_department +.PHONY: test-integration-scope-sale +test-integration-scope-sale: + docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_sale + .PHONY: integration_tests_task integration_tests_task: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_task diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 53b8188f..7cf85982 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -28,6 +28,7 @@ parameters: - tests/Integration/Services/CRM/Currency - tests/Integration/Services/CRM/Requisites - tests/Integration/Services/Task + - tests/Integration/Services/Sale 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 616331db..f131db9c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -106,6 +106,9 @@ ./tests/Integration/Services/Department/ + + ./tests/Integration/Services/Sale/ + ./tests/Integration/Services/Task/ diff --git a/rector.php b/rector.php index e95257ff..4b458e5f 100644 --- a/rector.php +++ b/rector.php @@ -60,6 +60,8 @@ __DIR__ . '/tests/Integration/Services/Department', __DIR__ . '/src/Services/Task', __DIR__ . '/tests/Integration/Services/Task', + __DIR__ . '/src/Services/Sale', + __DIR__ . '/tests/Integration/Services/Sale', __DIR__ . '/tests/Unit/', ]) ->withCache(cacheDirectory: __DIR__ . '.cache/rector') diff --git a/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusAddResult.php b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusAddResult.php new file mode 100644 index 00000000..391ee13b --- /dev/null +++ b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusAddResult.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\Sale\PersonTypeStatus\Result; + +use Bitrix24\SDK\Core\Result\AddedItemResult; +use Bitrix24\SDK\Core\Exceptions\BaseException; + +class PersonTypeStatusAddResult extends AddedItemResult +{ + /** + * @throws BaseException + */ + public function isSuccess(): bool + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + return isset($result['businessValuePersonDomain']); + } +} diff --git a/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusFieldsResult.php b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusFieldsResult.php new file mode 100644 index 00000000..a370caf5 --- /dev/null +++ b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusFieldsResult.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\Sale\PersonTypeStatus\Result; + +use Bitrix24\SDK\Core\Result\FieldsResult; +use Bitrix24\SDK\Core\Exceptions\BaseException; + +class PersonTypeStatusFieldsResult extends FieldsResult +{ + /** + * @throws BaseException + */ + public function getFieldsDescription(): array + { + return $this->getCoreResponse()->getResponseData()->getResult()['businessValuePersonDomain']; + } +} diff --git a/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusItemResult.php b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusItemResult.php new file mode 100644 index 00000000..3aefb6d3 --- /dev/null +++ b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusItemResult.php @@ -0,0 +1,27 @@ + + * + * 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\Sale\PersonTypeStatus\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; + +/** + * Class PersonTypeStatusItemResult + * + * @property-read string|null $domain + * @property-read int|null $personTypeId + */ +class PersonTypeStatusItemResult extends AbstractItem +{ + // Access individual fields via magic getters, e.g. $item->domain, $item->personTypeId +} diff --git a/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusesResult.php b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusesResult.php new file mode 100644 index 00000000..726c3809 --- /dev/null +++ b/src/Services/Sale/PersonTypeStatus/Result/PersonTypeStatusesResult.php @@ -0,0 +1,32 @@ + + * + * 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\Sale\PersonTypeStatus\Result; + +use Bitrix24\SDK\Core\Result\AbstractResult; + +class PersonTypeStatusesResult extends AbstractResult +{ + /** + * @return PersonTypeStatusItemResult[] + */ + public function getPersonTypeStatuses(): array + { + $items = []; + foreach ($this->getCoreResponse()->getResponseData()->getResult()['businessValuePersonDomains'] as $item) { + $items[] = new PersonTypeStatusItemResult($item); + } + + return $items; + } +} diff --git a/src/Services/Sale/PersonTypeStatus/Service/PersonTypeStatus.php b/src/Services/Sale/PersonTypeStatus/Service/PersonTypeStatus.php new file mode 100644 index 00000000..70aed0e4 --- /dev/null +++ b/src/Services/Sale/PersonTypeStatus/Service/PersonTypeStatus.php @@ -0,0 +1,138 @@ + + * + * 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\Sale\PersonTypeStatus\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\Sale\PersonTypeStatus\Result\PersonTypeStatusesResult; +use Bitrix24\SDK\Services\Sale\PersonTypeStatus\Result\PersonTypeStatusFieldsResult; +use Bitrix24\SDK\Services\Sale\PersonTypeStatus\Result\PersonTypeStatusAddResult; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Psr\Log\LoggerInterface; + +class PersonTypeStatus extends AbstractService +{ + public function __construct(CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Add business value for person domain. + * + * @link https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-add.html + * + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + * @throws \Bitrix24\SDK\Core\Exceptions\TransportException + */ + #[ApiEndpointMetadata( + 'sale.businessValuePersonDomain.add', + 'https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-add.html', + 'Add business value for person domain' + )] + public function add(int $personTypeId, string $domain): PersonTypeStatusAddResult + { + return new PersonTypeStatusAddResult( + $this->core->call( + 'sale.businessValuePersonDomain.add', + [ + 'fields' => [ + 'personTypeId' => $personTypeId, + 'domain' => $domain + ] + ] + ) + ); + } + + /** + * Retrieves list of business values for person domain. + * + * @link https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-list.html + * + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + * @throws \Bitrix24\SDK\Core\Exceptions\TransportException + */ + #[ApiEndpointMetadata( + 'sale.businessValuePersonDomain.list', + 'https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-list.html', + 'List business values for person domain' + )] + public function list(array $filter = [], array $order = [], array $select = [], ?int $start = null): PersonTypeStatusesResult + { + $params = ['filter' => $filter, 'order' => $order, 'select' => $select]; + if ($start !== null) { + $params['start'] = $start; + } + + return new PersonTypeStatusesResult( + $this->core->call( + 'sale.businessValuePersonDomain.list', + $params + ) + ); + } + + /** + * Delete business values matching filter. + * + * @link https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-delete-by-filter.html + * + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + * @throws \Bitrix24\SDK\Core\Exceptions\TransportException + */ + #[ApiEndpointMetadata( + 'sale.businessValuePersonDomain.deleteByFilter', + 'https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-delete-by-filter.html', + 'Delete business values by filter' + )] + public function delete(int $personTypeId, string $domain): DeletedItemResult + { + return new DeletedItemResult( + $this->core->call( + 'sale.businessValuePersonDomain.deleteByFilter', + ['fields' => + [ + 'personTypeId' => $personTypeId, + 'domain' => $domain + ] + ] + ) + ); + } + + /** + * Get fields description for business value person domain. + * + * @link https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-getfields.html + * + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + * @throws \Bitrix24\SDK\Core\Exceptions\TransportException + */ + #[ApiEndpointMetadata( + 'sale.businessValuePersonDomain.getFields', + 'https://apidocs.bitrix24.com/api-reference/sale/business-value-person-domain/sale-business-value-person-domain-getfields.html', + 'Get fields for business value person domain' + )] + public function getFields(): PersonTypeStatusFieldsResult + { + return new PersonTypeStatusFieldsResult( + $this->core->call( + 'sale.businessValuePersonDomain.getFields', + [] + ) + ); + } +} diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php new file mode 100644 index 00000000..e4264774 --- /dev/null +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -0,0 +1,26 @@ +serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new PersonTypeStatus( + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } +} diff --git a/src/Services/ServiceBuilder.php b/src/Services/ServiceBuilder.php index 68937418..f852db9c 100644 --- a/src/Services/ServiceBuilder.php +++ b/src/Services/ServiceBuilder.php @@ -17,6 +17,7 @@ use Bitrix24\SDK\Core\Contracts\BulkItemsReaderInterface; use Bitrix24\SDK\Core\Contracts\CoreInterface; use Bitrix24\SDK\Services\AI\AIServiceBuilder; +use Bitrix24\SDK\Services\Sale\SaleServiceBuilder; use Bitrix24\SDK\Services\Catalog\CatalogServiceBuilder; use Bitrix24\SDK\Services\CRM\CRMServiceBuilder; use Bitrix24\SDK\Services\Entity\EntityServiceBuilder; @@ -259,4 +260,18 @@ public function getAiAdminScope(): AIServiceBuilder return $this->serviceCache[__METHOD__]; } -} \ No newline at end of file + + public function getSaleScope(): SaleServiceBuilder + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new SaleServiceBuilder( + $this->core, + $this->batch, + $this->bulkItemsReader, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } +} diff --git a/tests/Integration/Services/Sale/PersonTypeStatus/Service/PersonTypeStatusTest.php b/tests/Integration/Services/Sale/PersonTypeStatus/Service/PersonTypeStatusTest.php new file mode 100644 index 00000000..1174a2ad --- /dev/null +++ b/tests/Integration/Services/Sale/PersonTypeStatus/Service/PersonTypeStatusTest.php @@ -0,0 +1,105 @@ +service = Fabric::getServiceBuilder()->getSaleScope()->personTypeStatus(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testFields(): void + { + self::assertIsArray($this->service->getFields()->getFieldsDescription()); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testList(): void + { + $list = $this->service->list(); + $items = $list->getPersonTypeStatuses(); + if ($items !== []) { + self::assertInstanceOf(PersonTypeStatusItemResult::class, $items[0]); + } else { + self::assertIsArray($items); + } + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testAdd(): void + { + $personTypeId = $this->getPersonTypeId(); + + self::assertTrue($this->service->add($personTypeId, 'I')->isSuccess()); + + $items = $this->service->list(['personTypeId' => $personTypeId, 'domain' => 'I'])->getPersonTypeStatuses(); + self::assertNotEmpty($items); + self::assertEquals('I', $items[0]->domain); + self::assertEquals($personTypeId, $items[0]->personTypeId); + + // cleanup + $this->deletePersonType($personTypeId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testDelete(): void + { + $personTypeId = $this->getPersonTypeId(); + + $this->service->add($personTypeId, 'I'); + + $deletedItemResult = $this->service->delete($personTypeId, 'I'); + self::assertTrue($deletedItemResult->isSuccess()); + + $itemsAfter = $this->service->list(['personTypeId' => $personTypeId, 'domain' => 'I'])->getPersonTypeStatuses(); + self::assertEmpty($itemsAfter); + + // cleanup + $this->deletePersonType($personTypeId); + } + + protected function getPersonTypeId(): int + { + $core = Fabric::getCore(); + return (int)$core->call('sale.persontype.add', [ + 'fields' => [ + 'name' => 'Test Person Type', + 'sort' => 100, + ] + ])->getResponseData()->getResult()['personType']['id']; + } + + protected function deletePersonType(int $id): void + { + $core = Fabric::getCore(); + $core->call('sale.persontype.delete', [ + 'id' => $id + ]); + } + +} From 81ee3e63bd4a054443bc8666e3f8e99698fe8e3d Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Mon, 25 Aug 2025 10:24:25 +0400 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c742a0d..b8526458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ### Added +- Added service `Services\Sale\PersonTypeStatus\Service\PersonTypeStatus` with support methods, + see [sale.businessValuePersonDomain.* methods](https://github.com/bitrix24/b24phpsdk/issues/228): + - `add` adds business value for person domain + - `list` retrieves list of business values for person domain + - `delete` deletes business values by filter + - `getFields` gets fields description for business value person domain - Added service `Services\Task\Service\Task` with support methods, see [tasks.task.* methods](https://github.com/bitrix24/b24phpsdk/issues/214): - `add` creates a task, with batch calls support From 2ca36aa87bf5708d9ca15f5cb9b36c18a4a3a0a0 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Fri, 29 Aug 2025 10:05:21 +0400 Subject: [PATCH 3/3] fix conflicts with ServiceBuilder; add vscode ignoring --- .vscode/tasks.json | 16 ++++++++++++++++ Makefile | 4 ---- src/Services/Sale/SaleServiceBuilder.php | 6 ++---- src/Services/ServiceBuilder.php | 15 --------------- 4 files changed, 18 insertions(+), 23 deletions(-) create mode 100644 .vscode/tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..be621a7b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run integration tests for Sale scope", + "type": "shell", + "command": "make test-integration-scope-sale", + "args": [], + "isBackground": false, + "problemMatcher": [ + "$gcc" + ], + "group": "build" + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile index cffb9e5c..5d141c7b 100644 --- a/Makefile +++ b/Makefile @@ -267,10 +267,6 @@ integration_tests_crm_timeline: integration_tests_department: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_department -.PHONY: test-integration-scope-sale -test-integration-scope-sale: - docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_sale - .PHONY: integration_tests_task integration_tests_task: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_task diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php index d4aeb517..cae5ce0e 100644 --- a/src/Services/Sale/SaleServiceBuilder.php +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -16,13 +16,11 @@ use Bitrix24\SDK\Attributes\ApiServiceBuilderMetadata; use Bitrix24\SDK\Core\Credentials\Scope; use Bitrix24\SDK\Services\AbstractServiceBuilder; - use Bitrix24\SDK\Services\Sale\PersonTypeStatus\Service\PersonTypeStatus; #[ApiServiceBuilderMetadata(new Scope(['sale']))] class SaleServiceBuilder extends AbstractServiceBuilder { - public function personTypeStatus(): PersonTypeStatus { if (!isset($this->serviceCache[__METHOD__])) { @@ -33,8 +31,8 @@ public function personTypeStatus(): PersonTypeStatus } return $this->serviceCache[__METHOD__]; - } - + } + public function personType(): PersonType\Service\PersonType { if (!isset($this->serviceCache[__METHOD__])) { diff --git a/src/Services/ServiceBuilder.php b/src/Services/ServiceBuilder.php index e9416329..88656329 100644 --- a/src/Services/ServiceBuilder.php +++ b/src/Services/ServiceBuilder.php @@ -17,7 +17,6 @@ use Bitrix24\SDK\Core\Contracts\BulkItemsReaderInterface; use Bitrix24\SDK\Core\Contracts\CoreInterface; use Bitrix24\SDK\Services\AI\AIServiceBuilder; -use Bitrix24\SDK\Services\Sale\SaleServiceBuilder; use Bitrix24\SDK\Services\Catalog\CatalogServiceBuilder; use Bitrix24\SDK\Services\CRM\CRMServiceBuilder; use Bitrix24\SDK\Services\Entity\EntityServiceBuilder; @@ -275,18 +274,4 @@ public function getAiAdminScope(): AIServiceBuilder return $this->serviceCache[__METHOD__]; } - - public function getSaleScope(): SaleServiceBuilder - { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new SaleServiceBuilder( - $this->core, - $this->batch, - $this->bulkItemsReader, - $this->log - ); - } - - return $this->serviceCache[__METHOD__]; - } }