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