From 9a70fd654648fb76c9146e269f989a215b319cd0 Mon Sep 17 00:00:00 2001 From: Vadim Soluyanov Date: Tue, 17 Jun 2025 13:18:59 +0400 Subject: [PATCH 1/2] add methods and tests --- .php-cs-fixer.php | 2 +- CHANGELOG.md | 4 + Makefile | 4 + phpstan.neon.dist | 2 +- phpunit.xml.dist | 4 +- rector.php | 4 +- src/Services/CRM/CRMServiceBuilder.php | 12 ++ .../Lead/Result/LeadProductRowItemResult.php | 54 +++++++ .../Lead/Result/LeadProductRowItemsResult.php | 53 +++++++ .../CRM/Lead/Service/LeadProductRows.php | 119 ++++++++++++++ .../CRM/Lead/Service/LeadProductRowsTest.php | 146 ++++++++++++++++++ 11 files changed, 398 insertions(+), 6 deletions(-) create mode 100644 src/Services/CRM/Lead/Result/LeadProductRowItemResult.php create mode 100644 src/Services/CRM/Lead/Result/LeadProductRowItemsResult.php create mode 100644 src/Services/CRM/Lead/Service/LeadProductRows.php create mode 100644 tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 98e2153c..73e4d8d8 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -6,7 +6,7 @@ $finder = Finder::create() ->in(__DIR__ . '/src/Infrastructure/Console/Commands/') - ->in(__DIR__ . '/src/Services/CRM/Deal/') + ->in(__DIR__ . '/src/Services/CRM/Lead/') ->name('*.php') ->exclude(['vendor', 'storage', 'docker', 'docs']) // Exclude directories ->ignoreDotFiles(true) diff --git a/CHANGELOG.md b/CHANGELOG.md index 538644ae..7cc2df98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Added +- Added service `Services\CRM\Lead\Service\LeadProductRows` with support methods, + see [add crm.lead.productrows* methods](https://github.com/bitrix24/b24phpsdk/issues/175): + - `set` Adds products to a lead + - `get` Returns the products of a lead - Added service `Services\CRM\Deal\Service\DealRecurring` with support methods, see [crm.deal.recurring.* methods](https://github.com/bitrix24/b24phpsdk/issues/160): - `fields` returns a list of fields for the recurring deal template diff --git a/Makefile b/Makefile index 54988e90..3726f0c3 100644 --- a/Makefile +++ b/Makefile @@ -186,6 +186,10 @@ integration_tests_deal_recurring: .PHONY: integration_tests_scope_automation integration_tests_scope_automation: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_automation + +.PHONY: integration_tests_lead_productrows +integration_tests_lead_productrows: + docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_lead_productrows # work dev environment .PHONY: php-dev-server-up diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b221d630..039f55d7 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,7 +11,7 @@ parameters: - tests/Integration/Services/IMOpenLines - tests/Integration/Services/Main - tests/Integration/Services/Placement - - tests/Integration/Services/CRM/Deal/Service/DealRecurringTest.php + - tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php bootstrapFiles: - tests/bootstrap.php parallel: diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e96ed8b0..149b7129 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -43,8 +43,8 @@ ./tests/Integration/Services/AI/ - - ./tests/Integration/Services/CRM/Deal/Service/DealRecurringTest.php + + ./tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php ./tests/Integration/Services/CRM/Automation/ diff --git a/rector.php b/rector.php index e7039434..a94f53ed 100644 --- a/rector.php +++ b/rector.php @@ -36,8 +36,8 @@ __DIR__ . '/tests/Integration/Services/Main', __DIR__ . '/src/Services/Placement', __DIR__ . '/tests/Integration/Services/Placement', - __DIR__ . '/src/Services/CRM/Deal', - __DIR__ . '/tests/Integration/Services/CRM/Deal/Service', + __DIR__ . '/src/Services/CRM/Lead', + __DIR__ . '/tests/Integration/Services/CRM/Lead/Service', __DIR__ . '/tests/Unit/', ]) ->withCache(cacheDirectory: __DIR__ . '.cache/rector') diff --git a/src/Services/CRM/CRMServiceBuilder.php b/src/Services/CRM/CRMServiceBuilder.php index 0ef92763..b6cf8a9f 100644 --- a/src/Services/CRM/CRMServiceBuilder.php +++ b/src/Services/CRM/CRMServiceBuilder.php @@ -277,6 +277,18 @@ public function lead(): Lead\Service\Lead return $this->serviceCache[__METHOD__]; } + + /** + * @return Lead\Service\LeadProductRows + */ + public function leadProductRows(): Lead\Service\LeadProductRows + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Lead\Service\LeadProductRows($this->core, $this->log); + } + + return $this->serviceCache[__METHOD__]; + } public function activity(): Activity\Service\Activity { diff --git a/src/Services/CRM/Lead/Result/LeadProductRowItemResult.php b/src/Services/CRM/Lead/Result/LeadProductRowItemResult.php new file mode 100644 index 00000000..08a89e37 --- /dev/null +++ b/src/Services/CRM/Lead/Result/LeadProductRowItemResult.php @@ -0,0 +1,54 @@ + + * + * 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\Lead\Result; + +use Money\Money; +use MoneyPHP\Percentage\Percentage; +use Bitrix24\SDK\Services\CRM\Common\Result\DiscountType; +use Carbon\CarbonImmutable; +use Bitrix24\SDK\Services\CRM\Common\Result\AbstractCrmItem; + +/** + * @property-read int $ID + * @property-read int $OWNER_ID + * @property-read string $OWNER_TYPE + * @property-read int $PRODUCT_ID + * @property-read string $PRODUCT_NAME + * @property-read string|null $ORIGINAL_PRODUCT_NAME + * @property-read string|null $PRODUCT_DESCRIPTION + * @property-read Money $PRICE price with taxes and discounts + * @property-read Money $PRICE_EXCLUSIVE without taxes but with discounts + * @property-read Money $PRICE_NETTO without taxes and discounts + * @property-read Money $PRICE_BRUTTO without discounts but with taxes + * @property-read Money $PRICE_ACCOUNT formatted price + * @property-read string $QUANTITY + * @property-read DiscountType $DISCOUNT_TYPE_ID + * @property-read Percentage $DISCOUNT_RATE + * @property-read Money $DISCOUNT_SUM + * @property-read string $TAX_RATE + * @property-read bool $TAX_INCLUDED + * @property-read string $CUSTOMIZED + * @property-read int $MEASURE_CODE + * @property-read string $MEASURE_NAME + * @property-read int $SORT + * @property-read string|null $XML_ID + * @property-read int $TYPE + * @property-read int|null $STORE_ID + * @property-read int|null $RESERVE_ID + * @property-read CarbonImmutable|null $DATE_RESERVE_END + * @property-read int|null $RESERVE_QUANTITY + */ +class LeadProductRowItemResult extends AbstractCrmItem +{ +} diff --git a/src/Services/CRM/Lead/Result/LeadProductRowItemsResult.php b/src/Services/CRM/Lead/Result/LeadProductRowItemsResult.php new file mode 100644 index 00000000..e43ae6fa --- /dev/null +++ b/src/Services/CRM/Lead/Result/LeadProductRowItemsResult.php @@ -0,0 +1,53 @@ + + * + * 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\Lead\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Response\Response; +use Bitrix24\SDK\Core\Result\AbstractResult; +use Money\Currency; + +/** + * Class LeadProductRowItemsResult + * + * @package Bitrix24\SDK\Services\CRM\Lead\Result + */ +class LeadProductRowItemsResult extends AbstractResult +{ + public function __construct(Response $coreResponse, private readonly Currency $currency) + { + parent::__construct($coreResponse); + } + + /** + * @return LeadProductRowItemResult[] + * @throws BaseException + */ + public function getProductRows(): array + { + $res = []; + if (!empty($this->getCoreResponse()->getResponseData()->getResult()['result']['rows'])) { + foreach ($this->getCoreResponse()->getResponseData()->getResult()['result']['rows'] as $productRow) { + $res[] = new LeadProductRowItemResult($productRow, $this->currency); + } + } else { + foreach ($this->getCoreResponse()->getResponseData()->getResult() as $productRow) { + $res[] = new LeadProductRowItemResult($productRow, $this->currency); + } + } + + return $res; + } +} diff --git a/src/Services/CRM/Lead/Service/LeadProductRows.php b/src/Services/CRM/Lead/Service/LeadProductRows.php new file mode 100644 index 00000000..83aa094e --- /dev/null +++ b/src/Services/CRM/Lead/Service/LeadProductRows.php @@ -0,0 +1,119 @@ + + * + * 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\Lead\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\UpdatedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\CRM\Lead\Result\LeadProductRowItemsResult; +use Money\Currency; + +#[ApiServiceMetadata(new Scope(['crm']))] +class LeadProductRows extends AbstractService +{ + /** + * Returns products inside the specified lead. + * + * @link https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-get.html + * + * @param int $leadId + * @param Currency|null $currency + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.lead.productrows.get', + 'https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-get.html', + 'Returns products inside the specified lead.' + )] + public function get(int $leadId, Currency $currency = null): LeadProductRowItemsResult + { + if (!$currency instanceof \Money\Currency) { + $res = $this->core->call('batch', [ + 'halt' => 0, + 'cmd' => [ + 'lead' => sprintf('crm.lead.get?ID=%s', $leadId), + 'rows' => sprintf('crm.lead.productrows.get?ID=%s', $leadId) + ], + ]); + $data = $res->getResponseData()->getResult(); + $currency = new Currency($data['result']['lead']['CURRENCY_ID']); + return new LeadProductRowItemsResult($res, $currency); + } + + return new LeadProductRowItemsResult( + $this->core->call( + 'crm.lead.productrows.get', + [ + 'id' => $leadId, + ] + ), + $currency + ); + } + + + /** + * Creates or updates product entries inside the specified lead. + * + * @link https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-productrows-set.html + * + * @param int $leadId + * @param array $productRows + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'crm.lead.productrows.set', + 'https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-productrows-set.html', + 'Creates or updates product entries inside the specified lead.' + )] + public function set(int $leadId, array $productRows): UpdatedItemResult + { + return new UpdatedItemResult( + $this->core->call( + 'crm.lead.productrows.set', + [ + 'id' => $leadId, + 'rows' => $productRows, + ] + ) + ); + } +} diff --git a/tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php b/tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php new file mode 100644 index 00000000..02963a86 --- /dev/null +++ b/tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php @@ -0,0 +1,146 @@ + + * + * 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\Lead\Service; + +use Money\Currencies\ISOCurrencies; +use Money\Currency; +use Money\Formatter\DecimalMoneyFormatter; +use Money\Money; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\CRM\Common\Result\DiscountType; +use Bitrix24\SDK\Services\CRM\Lead\Result\LeadProductRowItemResult; +use Bitrix24\SDK\Services\CRM\Lead\Service\Lead; +use Bitrix24\SDK\Services\CRM\Lead\Service\LeadProductRows; +use Bitrix24\SDK\Tests\Builders\DemoDataGenerator; +use Bitrix24\SDK\Tests\Integration\Fabric; +use MoneyPHP\Percentage\Percentage; +use PHPUnit\Framework\TestCase; +use Typhoon\Reflection\TyphoonReflector; + +#[\PHPUnit\Framework\Attributes\CoversClass(\Bitrix24\SDK\Services\CRM\Lead\Service\LeadProductRows::class)] +class LeadProductRowsTest extends TestCase +{ + private Lead $leadService; + + private LeadProductRows $leadProductRowsService; + + private DecimalMoneyFormatter $decimalMoneyFormatter; + + private TyphoonReflector $typhoonReflector; + + public function testAllSystemPropertiesAnnotated(): void + { + $leadId = $this->leadService->add(['TITLE' => 'test lead'])->getId(); + $this->leadProductRowsService->set( + $leadId, + [ + [ + 'PRODUCT_NAME' => sprintf('product name %s', time()), + 'PRICE' => $this->decimalMoneyFormatter->format(new Money(100000, DemoDataGenerator::getCurrency())), + ], + ] + ); + // get response from server with actual keys + $propListFromApi = array_keys($this->leadProductRowsService->get($leadId)->getCoreResponse()->getResponseData()->getResult()['result']['rows'][0]); + // parse keys from phpdoc annotation + $collection = $this->typhoonReflector->reflectClass(LeadProductRowItemResult::class)->properties(); + $propsFromAnnotations = []; + foreach ($collection as $meta) { + if ($meta->isAnnotated() && !$meta->isNative()) { + $propsFromAnnotations[] = $meta->id->name; + } + } + + $this->assertEquals($propListFromApi, $propsFromAnnotations, + sprintf('in phpdocs annotations for class %s cant find fields from actual api response: %s', + LeadProductRowItemResult::class, + implode(', ', array_values(array_diff($propListFromApi, $propsFromAnnotations))) + )); + + $this->leadService->delete($leadId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + public function testSet(): void + { + $leadId = $this->leadService->add(['TITLE' => sprintf('test lead %s', time())])->getId(); + $lead = $this->leadService->get($leadId)->lead(); + $price = new Money(100000, $lead->CURRENCY_ID); + $discount = new Money(50012, $lead->CURRENCY_ID); + $this::assertTrue( + $this->leadProductRowsService->set( + $leadId, + [ + [ + 'PRODUCT_NAME' => sprintf('product name %s', time()), + 'PRICE' => $this->decimalMoneyFormatter->format($price), + 'DISCOUNT_TYPE_ID' => 1, + 'DISCOUNT_SUM' => $this->decimalMoneyFormatter->format($discount) + ], + ] + )->isSuccess() + ); + $leadProductRowItemsResult = $this->leadProductRowsService->get($leadId); + $this->assertCount(1, $leadProductRowItemsResult->getProductRows()); + $productRow = $leadProductRowItemsResult->getProductRows()[0]; + $this->assertEquals($price, $productRow->PRICE); + $this->assertEquals(DiscountType::monetary, $productRow->DISCOUNT_TYPE_ID); + $this->assertEquals($discount, $productRow->DISCOUNT_SUM); + $discount = $discount->multiply(100)->divide($this->decimalMoneyFormatter->format($price->add($discount))); + $calculatedPercentage = new Percentage((string)((int)$discount->getAmount() / 100)); + $this->assertEquals($calculatedPercentage, $productRow->DISCOUNT_RATE); + + $this->leadService->delete($leadId); + } + + public function testGet(): void + { + $leadId = $this->leadService->add(['TITLE' => sprintf('test lead %s', time())])->getId(); + $lead = $this->leadService->get($leadId)->lead(); + $price = new Money(100000, $lead->CURRENCY_ID); + $discount = new Money(0, $lead->CURRENCY_ID); + $this::assertTrue( + $this->leadProductRowsService->set( + $leadId, + [ + [ + 'PRODUCT_NAME' => sprintf('product name %s', time()), + 'PRICE' => $this->decimalMoneyFormatter->format($price), + ], + ] + )->isSuccess() + ); + $leadProductRowItemsResult = $this->leadProductRowsService->get($leadId); + $this->assertCount(1, $leadProductRowItemsResult->getProductRows()); + $productRow = $leadProductRowItemsResult->getProductRows()[0]; + $this->assertEquals($price, $productRow->PRICE); + $this->assertEquals(DiscountType::percentage, $productRow->DISCOUNT_TYPE_ID); + $this->assertEquals($discount, $productRow->DISCOUNT_SUM); + $this->assertEquals(Percentage::zero(), $productRow->DISCOUNT_RATE); + + $this->leadService->delete($leadId); + } + + protected function setUp(): void + { + $this->leadService = Fabric::getServiceBuilder()->getCRMScope()->lead(); + $this->leadProductRowsService = Fabric::getServiceBuilder()->getCRMScope()->leadProductRows(); + $this->decimalMoneyFormatter = new DecimalMoneyFormatter(new ISOCurrencies()); + $this->typhoonReflector = TyphoonReflector::build(); + } +} \ No newline at end of file From c49b39f3b88cc46cfe3cc2add60af37b8f0282f2 Mon Sep 17 00:00:00 2001 From: Vadim Soluyanov Date: Tue, 17 Jun 2025 13:30:48 +0400 Subject: [PATCH 2/2] after linters --- .../CRM/Lead/Result/LeadItemResult.php | 3 +- src/Services/CRM/Lead/Result/LeadResult.php | 2 +- src/Services/CRM/Lead/Result/LeadsResult.php | 2 +- src/Services/CRM/Lead/Service/Batch.php | 14 ++------- src/Services/CRM/Lead/Service/Lead.php | 24 +++------------ .../CRM/Lead/Service/LeadProductRows.php | 2 -- .../Services/CRM/Lead/Service/BatchTest.php | 29 +++++++++++-------- .../Services/CRM/Lead/Service/LeadTest.php | 21 +++++--------- 8 files changed, 35 insertions(+), 62 deletions(-) diff --git a/src/Services/CRM/Lead/Result/LeadItemResult.php b/src/Services/CRM/Lead/Result/LeadItemResult.php index a6afa868..32097fa1 100644 --- a/src/Services/CRM/Lead/Result/LeadItemResult.php +++ b/src/Services/CRM/Lead/Result/LeadItemResult.php @@ -86,7 +86,6 @@ class LeadItemResult extends AbstractCrmItem { /** - * @param string $userfieldName * * @return mixed|null * @throws \Bitrix24\SDK\Services\CRM\Userfield\Exceptions\UserfieldNotFoundException @@ -95,4 +94,4 @@ public function getUserfieldByFieldName(string $userfieldName) { return $this->getKeyWithUserfieldByFieldName($userfieldName); } -} \ No newline at end of file +} diff --git a/src/Services/CRM/Lead/Result/LeadResult.php b/src/Services/CRM/Lead/Result/LeadResult.php index 7f4d0f86..872f4f0b 100644 --- a/src/Services/CRM/Lead/Result/LeadResult.php +++ b/src/Services/CRM/Lead/Result/LeadResult.php @@ -30,4 +30,4 @@ public function lead(): LeadItemResult { return new LeadItemResult($this->getCoreResponse()->getResponseData()->getResult()); } -} \ No newline at end of file +} diff --git a/src/Services/CRM/Lead/Result/LeadsResult.php b/src/Services/CRM/Lead/Result/LeadsResult.php index 203a5b54..17aec251 100644 --- a/src/Services/CRM/Lead/Result/LeadsResult.php +++ b/src/Services/CRM/Lead/Result/LeadsResult.php @@ -37,4 +37,4 @@ public function getLeads(): array return $items; } -} \ No newline at end of file +} diff --git a/src/Services/CRM/Lead/Service/Batch.php b/src/Services/CRM/Lead/Service/Batch.php index 7b6e546c..7bea200c 100644 --- a/src/Services/CRM/Lead/Service/Batch.php +++ b/src/Services/CRM/Lead/Service/Batch.php @@ -27,19 +27,11 @@ #[ApiBatchServiceMetadata(new Scope(['crm']))] class Batch { - protected BatchOperationsInterface $batch; - protected LoggerInterface $log; - /** * Batch constructor. - * - * @param BatchOperationsInterface $batch - * @param LoggerInterface $log */ - public function __construct(BatchOperationsInterface $batch, LoggerInterface $log) + public function __construct(protected BatchOperationsInterface $batch, protected LoggerInterface $log) { - $this->batch = $batch; - $this->log = $log; } /** @@ -133,7 +125,6 @@ public function __construct(BatchOperationsInterface $batch, LoggerInterface $lo * UTM_TERM?: string, * } $filter * @param array $select = ['ID','TITLE','TYPE_ID','CATEGORY_ID','STAGE_ID','STAGE_SEMANTIC_ID','IS_NEW','IS_RECURRING','IS_RETURN_CUSTOMER','IS_REPEATED_APPROACH','PROBABILITY','CURRENCY_ID','OPPORTUNITY','IS_MANUAL_OPPORTUNITY','TAX_VALUE','COMPANY_ID','CONTACT_ID','CONTACT_IDS','QUOTE_ID','BEGINDATE','CLOSEDATE','OPENED','CLOSED','COMMENTS','ASSIGNED_BY_ID','CREATED_BY_ID','MODIFY_BY_ID','DATE_CREATE','DATE_MODIFY','SOURCE_ID','SOURCE_DESCRIPTION','LEAD_ID','ADDITIONAL_INFO','LOCATION_ID','ORIGINATOR_ID','ORIGIN_ID','UTM_SOURCE','UTM_MEDIUM','UTM_CAMPAIGN','UTM_CONTENT','UTM_TERM'] - * @param int|null $limit * * @return Generator * @throws BaseException @@ -222,6 +213,7 @@ public function add(array $leads): Generator 'fields' => $lead, ]; } + foreach ($this->batch->addEntityItems('crm.lead.add', $items) as $key => $item) { yield $key => new AddedItemBatchResult($item); } @@ -246,4 +238,4 @@ public function delete(array $leadId): Generator yield $key => new DeletedItemBatchResult($item); } } -} \ No newline at end of file +} diff --git a/src/Services/CRM/Lead/Service/Lead.php b/src/Services/CRM/Lead/Service/Lead.php index 02d9716c..c0eea108 100644 --- a/src/Services/CRM/Lead/Service/Lead.php +++ b/src/Services/CRM/Lead/Service/Lead.php @@ -27,22 +27,16 @@ use Bitrix24\SDK\Services\CRM\Lead\Result\LeadResult; use Bitrix24\SDK\Services\CRM\Lead\Result\LeadsResult; use Psr\Log\LoggerInterface; + #[ApiServiceMetadata(new Scope(['crm']))] class Lead extends AbstractService { - public Batch $batch; - /** * Lead constructor. - * - * @param Batch $batch - * @param CoreInterface $core - * @param LoggerInterface $log */ - public function __construct(Batch $batch, CoreInterface $core, LoggerInterface $log) + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) { - parent::__construct($core, $log); - $this->batch = $batch; + parent::__construct($core, $logger); } /** @@ -112,7 +106,6 @@ public function __construct(Batch $batch, CoreInterface $core, LoggerInterface $ * REGISTER_SONET_EVENT?: string * } $params * - * @return AddedItemResult * @throws BaseException * @throws TransportException */ @@ -139,9 +132,7 @@ public function add(array $fields, array $params = []): AddedItemResult * * @link https://training.bitrix24.com/rest_help/crm/leads/crm_lead_delete.php * - * @param int $id * - * @return DeletedItemResult * @throws BaseException * @throws TransportException */ @@ -167,7 +158,6 @@ public function delete(int $id): DeletedItemResult * * @link https://training.bitrix24.com/rest_help/crm/leads/crm_lead_fields.php * - * @return FieldsResult * @throws BaseException * @throws TransportException */ @@ -186,9 +176,7 @@ public function fields(): FieldsResult * * @link https://training.bitrix24.com/rest_help/crm/leads/crm_lead_get.php * - * @param int $id * - * @return LeadResult * @throws BaseException * @throws TransportException */ @@ -214,7 +202,6 @@ public function get(int $id): LeadResult * * @throws BaseException * @throws TransportException - * @return LeadsResult */ #[ApiEndpointMetadata( 'crm.lead.list', @@ -241,7 +228,6 @@ public function list(array $order, array $filter, array $select, int $startItem * * @link https://training.bitrix24.com/rest_help/crm/leads/crm_lead_update.php * - * @param int $id * @param array{ * ID?: int, * TITLE?: string, @@ -304,7 +290,6 @@ public function list(array $order, array $filter, array $select, int $startItem * REGISTER_SONET_EVENT?: string * } $params * - * @return UpdatedItemResult * @throws BaseException * @throws TransportException */ @@ -388,7 +373,6 @@ public function update(int $id, array $fields, array $params = []): UpdatedItemR * LINK?: string * } $filter * - * @return int * @throws \Bitrix24\SDK\Core\Exceptions\BaseException * @throws \Bitrix24\SDK\Core\Exceptions\TransportException */ @@ -396,4 +380,4 @@ public function countByFilter(array $filter = []): int { return $this->list([], $filter, ['ID'], 1)->getCoreResponse()->getResponseData()->getPagination()->getTotal(); } -} \ No newline at end of file +} diff --git a/src/Services/CRM/Lead/Service/LeadProductRows.php b/src/Services/CRM/Lead/Service/LeadProductRows.php index 83aa094e..256352e6 100644 --- a/src/Services/CRM/Lead/Service/LeadProductRows.php +++ b/src/Services/CRM/Lead/Service/LeadProductRows.php @@ -31,7 +31,6 @@ class LeadProductRows extends AbstractService * * @link https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-get.html * - * @param int $leadId * @param Currency|null $currency * @throws BaseException * @throws TransportException @@ -73,7 +72,6 @@ public function get(int $leadId, Currency $currency = null): LeadProductRowItems * * @link https://apidocs.bitrix24.com/api-reference/crm/leads/crm-lead-productrows-set.html * - * @param int $leadId * @param arrayleadService->add(['TITLE' => 'test lead'])->getId(); @@ -42,64 +42,69 @@ public function testBatchList(): void foreach ($this->leadService->batch->list([], ['ID' => $itemId], ['ID', 'NAME'], 1) as $item) { $cnt++; } + self::assertGreaterThanOrEqual(1, $cnt); $this->leadService->delete($itemId); } /** - * @testdox Batch add lead - * @covers \Bitrix24\SDK\Services\CRM\Lead\Service\Batch::add() * @throws \Bitrix24\SDK\Core\Exceptions\BaseException */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch add lead')] public function testBatchAdd(): void { $items = []; for ($i = 1; $i < 60; $i++) { $items[] = ['TITLE' => 'TITLE-' . $i]; } + $cnt = 0; $itemId = []; foreach ($this->leadService->batch->add($items) as $item) { $cnt++; $itemId[] = $item->getId(); } + self::assertEquals(count($items), $cnt); $cnt = 0; foreach ($this->leadService->batch->delete($itemId) as $cnt => $deleteResult) { $cnt++; } + self::assertEquals(count($items), $cnt); } /** - * @testdox Batch delete deals - * @covers \Bitrix24\SDK\Services\CRM\Deal\Service\Batch::add() * @throws \Bitrix24\SDK\Core\Exceptions\BaseException */ + #[\PHPUnit\Framework\Attributes\TestDox('Batch delete leads')] public function testBatchDelete(): void { - $deals = []; + $leads = []; for ($i = 1; $i < 60; $i++) { - $deals[] = ['TITLE' => 'TITLE-' . $i]; + $leads[] = ['TITLE' => 'TITLE-' . $i]; } + $cnt = 0; $dealId = []; - foreach ($this->leadService->batch->add($deals) as $item) { + foreach ($this->leadService->batch->add($leads) as $item) { $cnt++; $dealId[] = $item->getId(); } - self::assertEquals(count($deals), $cnt); + + self::assertEquals(count($leads), $cnt); $cnt = 0; foreach ($this->leadService->batch->delete($dealId) as $cnt => $deleteResult) { $cnt++; } - self::assertEquals(count($deals), $cnt); + + self::assertEquals(count($leads), $cnt); } - public function setUp(): void + protected function setUp(): void { $this->leadService = Fabric::getServiceBuilder()->getCRMScope()->lead(); } diff --git a/tests/Integration/Services/CRM/Lead/Service/LeadTest.php b/tests/Integration/Services/CRM/Lead/Service/LeadTest.php index 2c356d7a..eb020fa0 100644 --- a/tests/Integration/Services/CRM/Lead/Service/LeadTest.php +++ b/tests/Integration/Services/CRM/Lead/Service/LeadTest.php @@ -36,6 +36,7 @@ #[CoversMethod(Lead::class,'list')] #[CoversMethod(Lead::class,'fields')] #[CoversMethod(Lead::class,'update')] +#[\PHPUnit\Framework\Attributes\CoversClass(\Bitrix24\SDK\Services\CRM\Lead\Service\Lead::class)] class LeadTest extends TestCase { use CustomBitrix24Assertions; @@ -51,9 +52,7 @@ public function testAllSystemFieldsHasValidTypeAnnotation():void { $allFields = $this->leadService->fields()->getFieldsDescription(); $systemFieldsCodes = (new Core\Fields\FieldsFilter())->filterSystemFields(array_keys($allFields)); - $systemFields = array_filter($allFields, static function ($code) use ($systemFieldsCodes) { - return in_array($code, $systemFieldsCodes, true); - }, ARRAY_FILTER_USE_KEY); + $systemFields = array_filter($allFields, static fn($code): bool => in_array($code, $systemFieldsCodes, true), ARRAY_FILTER_USE_KEY); $this->assertBitrix24AllResultItemFieldsHasValidTypeAnnotation( $systemFields, @@ -72,7 +71,6 @@ public function testAdd(): void /** * @throws BaseException * @throws TransportException - * @covers Lead::delete */ public function testDelete(): void { @@ -80,7 +78,6 @@ public function testDelete(): void } /** - * @covers Lead::fields * @throws BaseException * @throws TransportException */ @@ -92,7 +89,6 @@ public function testFields(): void /** * @throws BaseException * @throws TransportException - * @covers Lead::get */ public function testGet(): void { @@ -105,7 +101,6 @@ public function testGet(): void /** * @throws BaseException * @throws TransportException - * @covers Lead::list */ public function testList(): void { @@ -116,21 +111,19 @@ public function testList(): void /** * @throws BaseException * @throws TransportException - * @covers Lead::update */ public function testUpdate(): void { - $deal = $this->leadService->add(['TITLE' => 'test lead']); + $addedItemResult = $this->leadService->add(['TITLE' => 'test lead']); $newTitle = 'test2'; - self::assertTrue($this->leadService->update($deal->getId(), ['TITLE' => $newTitle], [])->isSuccess()); - self::assertEquals($newTitle, $this->leadService->get($deal->getId())->lead()->TITLE); + self::assertTrue($this->leadService->update($addedItemResult->getId(), ['TITLE' => $newTitle], [])->isSuccess()); + self::assertEquals($newTitle, $this->leadService->get($addedItemResult->getId())->lead()->TITLE); } /** * @throws \Bitrix24\SDK\Core\Exceptions\BaseException * @throws \Bitrix24\SDK\Core\Exceptions\TransportException - * @covers \Bitrix24\SDK\Services\CRM\Deal\Service\Deal::countByFilter */ public function testCountByFilter(): void { @@ -141,10 +134,12 @@ public function testCountByFilter(): void for ($i = 1; $i <= $newItemsCount; $i++) { $items[] = ['TITLE' => 'TITLE-' . $i]; } + $cnt = 0; foreach ($this->leadService->batch->add($items) as $item) { $cnt++; } + self::assertEquals(count($items), $cnt); $after = $this->leadService->countByFilter(); @@ -152,7 +147,7 @@ public function testCountByFilter(): void $this->assertEquals($before + $newItemsCount, $after); } - public function setUp(): void + protected function setUp(): void { $this->leadService = Fabric::getServiceBuilder()->getCRMScope()->lead(); }