diff --git a/CHANGELOG.md b/CHANGELOG.md index 702bd031..feda4457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ ### Added +- Added service `CRM\Deal\Service\DealDetailsConfiguration` with support methods, + see [add crm.deal.details.* methods](https://github.com/bitrix24/b24phpsdk/issues/158): + - `getPersonal` method retrieves the settings of deal cards for personal user + - `getGeneral` method retrieves the settings of deal cards for all users + - `resetPersonal` method reset for item user settings + - `resetGeneral` method reset all card settings for all users + - `setPersonal` method set card configuration + - `setGeneral` method set card configuration for all users + - `setForceCommonConfigForAll` method set common detail form for All Users - Added service `CRM\Lead\Service\LeadDetailsConfiguration` with support methods, see [add crm.lead.details.* methods](https://github.com/bitrix24/b24phpsdk/issues/172): - `getPersonal` method retrieves the settings of lead cards for personal user diff --git a/Makefile b/Makefile index 4c03d6bd..704c88e8 100644 --- a/Makefile +++ b/Makefile @@ -183,6 +183,10 @@ test-integration-scope-entity: test-integration-scope-ai-admin: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_ai_admin +.PHONY: integration_tests_scope_crm_deal_details +integration_tests_scope_crm_deal_details: + docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_crm_deal_details + .PHONY: integration_tests_scope_crm_contact_details integration_tests_scope_crm_contact_details: docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_scope_crm_contact_details diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e92ac81a..1cfbf1ca 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,6 +11,7 @@ parameters: - tests/Integration/Services/IMOpenLines - tests/Integration/Services/Main - tests/Integration/Services/Placement + - tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php - tests/Integration/Services/CRM/Lead/Service/LeadDetailsConfigurationTest.php - tests/Integration/Services/CRM/Contact/Service/ContactDetailsConfigurationTest.php - tests/Integration/Services/CRM/Lead/Service/LeadProductRowsTest.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 97888bec..2fd01198 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -43,6 +43,9 @@ ./tests/Integration/Services/AI/ + + ./tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php + ./tests/Integration/Services/CRM/Contact/Service/ContactDetailsConfigurationTest.php diff --git a/rector.php b/rector.php index 1b914b95..c7731d54 100644 --- a/rector.php +++ b/rector.php @@ -36,6 +36,8 @@ __DIR__ . '/tests/Integration/Services/Main', __DIR__ . '/src/Services/Placement', __DIR__ . '/tests/Integration/Services/Placement', + __DIR__ . '/src/Services/CRM/Deal/Service/DealDetailsConfiguration.php', + __DIR__ . '/tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php', __DIR__ . '/src/Services/CRM/Contact/Service/ContactDetailsConfiguration.php', __DIR__ . '/tests/Integration/Services/CRM/Contact/Service/ContactDetailsConfigurationTest.php', __DIR__ . '/src/Services/CRM/Lead', diff --git a/src/Services/CRM/CRMServiceBuilder.php b/src/Services/CRM/CRMServiceBuilder.php index e70e39b9..485625e4 100644 --- a/src/Services/CRM/CRMServiceBuilder.php +++ b/src/Services/CRM/CRMServiceBuilder.php @@ -72,6 +72,18 @@ public function companyDetailsConfiguration(): Company\Service\CompanyDetailsCon return $this->serviceCache[__METHOD__]; } + public function dealDetailsConfiguration(): Deal\Service\DealDetailsConfiguration + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Deal\Service\DealDetailsConfiguration( + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } + public function leadDetailsConfiguration(): Lead\Service\LeadDetailsConfiguration { if (!isset($this->serviceCache[__METHOD__])) { diff --git a/src/Services/CRM/Deal/Service/DealDetailsConfiguration.php b/src/Services/CRM/Deal/Service/DealDetailsConfiguration.php new file mode 100644 index 00000000..cf0d705f --- /dev/null +++ b/src/Services/CRM/Deal/Service/DealDetailsConfiguration.php @@ -0,0 +1,184 @@ + + * + * 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\Deal\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Result\UpdatedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\CRM\Common\CardFieldConfiguration; +use Bitrix24\SDK\Services\CRM\Common\CardSectionConfiguration; +use Bitrix24\SDK\Services\CRM\Common\Result\ElementCardConfiguration\CardConfigurationsResult; + +#[ApiServiceMetadata(new Scope(['crm']))] +class DealDetailsConfiguration extends AbstractService +{ + /** + * The method retrieves the settings of deal cards for personal user. + * + * @param non-negative-int|null $userId + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-get.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.get', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-get.html', + 'The method crm.deal.details.configuration.get retrieves the settings of deal cards for personal user.' + )] + public function getPersonal(?int $userId = null): CardConfigurationsResult + { + return new CardConfigurationsResult($this->core->call('crm.deal.details.configuration.get', [ + 'scope' => 'P', + 'userId' => $userId + ])); + } + + /** + * The method retrieves the settings of deal cards for all users. + * + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-get.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.get', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-get.html', + 'The method crm.deal.details.configuration.get retrieves the settings of deal cards for all users.' + )] + public function getGeneral(): CardConfigurationsResult + { + return new CardConfigurationsResult($this->core->call('crm.deal.details.configuration.get', [ + 'scope' => 'C', + ])); + } + + /** + * The method resets the settings of deal cards for personal user. + * + * @param non-negative-int|null $userId + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-reset.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.reset', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-reset.html', + 'The method crm.deal.details.configuration.get retrieves the settings of deal cards for personal user.' + )] + public function resetPersonal(?int $userId = null): UpdatedItemResult + { + return new UpdatedItemResult($this->core->call('crm.deal.details.configuration.reset', [ + 'scope' => 'P', + 'userId' => $userId + ])); + } + + /** + * The method resets the settings of deal cards for all users. + * + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-reset.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.reset', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-reset.html', + 'The method crm.deal.details.configuration.get retrieves the settings of deal cards for all users.' + )] + public function resetGeneral(): UpdatedItemResult + { + return new UpdatedItemResult($this->core->call('crm.deal.details.configuration.reset', [ + 'scope' => 'C', + ])); + } + + /** + * Set Parameters for Individual CRM Company Detail Card Configuration + * @param CardSectionConfiguration[] $cardConfiguration + * @throws InvalidArgumentException + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-set.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.set', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-set.html', + 'Set Parameters for Individual CRM Deal Detail Card Configuration.' + )] + public function setPersonal(array $cardConfiguration, ?int $userId = null): UpdatedItemResult + { + $rawData = []; + foreach ($cardConfiguration as $sectionItem) { + if (!$sectionItem instanceof CardSectionConfiguration) { + throw new InvalidArgumentException( + sprintf( + 'card configuration section mus be «%s» type, current type «%s»', + CardFieldConfiguration::class, + gettype($sectionItem) + ) + ); + } + + $rawData[] = $sectionItem->toArray(); + } + + return new UpdatedItemResult($this->core->call('crm.deal.details.configuration.set', [ + 'scope' => 'P', + 'userId' => $userId, + 'data' => $rawData + ])); + } + + /** + * Set CRM Deal Detail Card Configuration for all users. + * @param CardSectionConfiguration[] $cardConfiguration + * @throws InvalidArgumentException + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-set.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.set', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-set.html', + 'Set CRM Deal Detail Card Configuration for all users.' + )] + public function setGeneral(array $cardConfiguration): UpdatedItemResult + { + $rawData = []; + foreach ($cardConfiguration as $sectionItem) { + if (!$sectionItem instanceof CardSectionConfiguration) { + throw new InvalidArgumentException( + sprintf( + 'card configuration section mus be «%s» type, current type «%s»', + CardFieldConfiguration::class, + gettype($sectionItem) + ) + ); + } + + $rawData[] = $sectionItem->toArray(); + } + + return new UpdatedItemResult($this->core->call('crm.deal.details.configuration.set', [ + 'scope' => 'C', + 'data' => $rawData + ])); + } + + /** + * Set Common Detail Form for All Users + * @throws InvalidArgumentException + * @link https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-force-common-scope-for-all.html + */ + #[ApiEndpointMetadata( + 'crm.deal.details.configuration.forceCommonScopeForAll', + 'https://apidocs.bitrix24.com/api-reference/crm/deals/custom-form/crm-deal-details-configuration-force-common-scope-for-all.html', + 'Set Common Detail Form for All Users.' + )] + public function setForceCommonConfigForAll(): UpdatedItemResult + { + return new UpdatedItemResult($this->core->call('crm.deal.details.configuration.forceCommonScopeForAll')); + } +} diff --git a/tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php b/tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php new file mode 100644 index 00000000..d6ee746e --- /dev/null +++ b/tests/Integration/Services/CRM/Deal/Service/DealDetailsConfigurationTest.php @@ -0,0 +1,166 @@ + + * + * 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\Deal\Service; + + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\CRM\Common\CardFieldConfiguration; +use Bitrix24\SDK\Services\CRM\Common\CardSectionConfiguration; +use Bitrix24\SDK\Services\CRM\Deal\Service\DealDetailsConfiguration; +use Bitrix24\SDK\Services\ServiceBuilder; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\CoversMethod; +use PHPUnit\Framework\TestCase; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; + +#[CoversClass(DealDetailsConfiguration::class)] +#[CoversMethod(DealDetailsConfiguration::class, 'getPersonal')] +#[CoversMethod(DealDetailsConfiguration::class, 'resetGeneral')] +#[CoversMethod(DealDetailsConfiguration::class, 'resetPersonal')] +#[CoversMethod(DealDetailsConfiguration::class, 'setPersonal')] +#[CoversMethod(DealDetailsConfiguration::class, 'setGeneral')] +#[CoversMethod(DealDetailsConfiguration::class, 'setForceCommonConfigForAll')] +class DealDetailsConfigurationTest extends TestCase +{ + use CustomBitrix24Assertions; + + private ServiceBuilder $sb; + + private DealDetailsConfiguration $dealConfig; + + protected function setUp(): void + { + $this->sb = Fabric::getServiceBuilder(); + $this->dealConfig = $this->sb->getCRMScope()->dealDetailsConfiguration(); + } + + protected function tearDown(): void + { + $this->dealConfig->resetGeneral(); + } + + public function testResetGeneral(): void + { + $this->assertTrue($this->dealConfig->resetGeneral()->isSuccess()); + } + + public function testResetPersonal(): void + { + $currentUserId = $this->sb->getMainScope()->main()->getCurrentUserProfile()->getUserProfile()->ID; + $this->assertTrue( + $this->dealConfig->resetPersonal($currentUserId)->isSuccess() + ); + } + + /** + * @throws TransportException + * @throws InvalidArgumentException + * @throws BaseException + */ + public function testSetPersonal(): void + { + $config = [ + new CardSectionConfiguration('main', 'About the Deal', [ + new CardFieldConfiguration('TITLE'), + new CardFieldConfiguration('OPPORTUNITY_WITH_CURRENCY'), + new CardFieldConfiguration('STAGE_ID'), + new CardFieldConfiguration('BEGINDATE'), + new CardFieldConfiguration('CLOSEDATE'), + new CardFieldConfiguration('CLIENT'), + ]), + new CardSectionConfiguration('additional', 'Additional Information', [ + new CardFieldConfiguration('TYPE_ID'), + new CardFieldConfiguration('SOURCE_ID'), + new CardFieldConfiguration('ASSIGNED_BY_ID'), + new CardFieldConfiguration('COMMENTS'), + ]) + ]; + + $currentUserId = $this->sb->getMainScope()->main()->getCurrentUserProfile()->getUserProfile()->ID; + $this->assertTrue( + $this->dealConfig->setPersonal( + $config, + $currentUserId + )->isSuccess() + ); + } + + /** + * @throws TransportException + * @throws InvalidArgumentException + * @throws BaseException + */ + public function testSetGeneral(): void + { + $config = [ + new CardSectionConfiguration('main', 'About the Deal', [ + new CardFieldConfiguration('TITLE'), + new CardFieldConfiguration('OPPORTUNITY_WITH_CURRENCY'), + new CardFieldConfiguration('STAGE_ID'), + new CardFieldConfiguration('BEGINDATE'), + new CardFieldConfiguration('CLOSEDATE'), + new CardFieldConfiguration('CLIENT'), + ]), + new CardSectionConfiguration('additional', 'Additional Information', [ + new CardFieldConfiguration('TYPE_ID'), + new CardFieldConfiguration('SOURCE_ID'), + new CardFieldConfiguration('ASSIGNED_BY_ID'), + new CardFieldConfiguration('COMMENTS'), + ]) + ]; + + $this->assertTrue($this->dealConfig->setGeneral($config)->isSuccess()); + } + + public function testForceConfigForAll(): void + { + $this->assertTrue($this->dealConfig->setForceCommonConfigForAll()->isSuccess()); + } + + public function testGetPersonal(): void + { + $config = [ + new CardSectionConfiguration('main', 'About the Deal', [ + new CardFieldConfiguration('TITLE'), + new CardFieldConfiguration('OPPORTUNITY_WITH_CURRENCY'), + new CardFieldConfiguration('STAGE_ID'), + new CardFieldConfiguration('BEGINDATE'), + new CardFieldConfiguration('CLOSEDATE'), + new CardFieldConfiguration('CLIENT'), + ]), + new CardSectionConfiguration('additional', 'Additional Information', [ + new CardFieldConfiguration('TYPE_ID'), + new CardFieldConfiguration('SOURCE_ID'), + new CardFieldConfiguration('ASSIGNED_BY_ID'), + new CardFieldConfiguration('COMMENTS'), + ]) + ]; + + $currentUserId = $this->sb->getMainScope()->main()->getCurrentUserProfile()->getUserProfile()->ID; + $this->assertTrue( + $this->dealConfig->setPersonal( + $config, + $currentUserId + )->isSuccess() + ); + + + $currentUserId = $this->sb->getMainScope()->main()->getCurrentUserProfile()->getUserProfile()->ID; + $cardConfigurationsResult = $this->dealConfig->getPersonal($currentUserId); + $this->assertIsArray($cardConfigurationsResult->getSections()); + } +}