From c52fedcf07720f4cf6d91b1297cd85e4a9da069e Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 23 Feb 2023 16:11:11 +0200 Subject: [PATCH] ref --- .../Opportunity/AmountWeightedConverted.php | 61 +++++++ .../Crm/Hooks/Opportunity/Contacts.php | 90 +++++++++ .../Crm/Hooks/Opportunity/LastStage.php | 146 +++++++++++++++ .../Crm/Hooks/Opportunity/Probability.php | 75 ++++++++ .../Modules/Crm/Repositories/Opportunity.php | 171 +----------------- 5 files changed, 373 insertions(+), 170 deletions(-) create mode 100644 application/Espo/Modules/Crm/Hooks/Opportunity/AmountWeightedConverted.php create mode 100644 application/Espo/Modules/Crm/Hooks/Opportunity/Contacts.php create mode 100644 application/Espo/Modules/Crm/Hooks/Opportunity/LastStage.php create mode 100644 application/Espo/Modules/Crm/Hooks/Opportunity/Probability.php diff --git a/application/Espo/Modules/Crm/Hooks/Opportunity/AmountWeightedConverted.php b/application/Espo/Modules/Crm/Hooks/Opportunity/AmountWeightedConverted.php new file mode 100644 index 0000000000..d11672c8df --- /dev/null +++ b/application/Espo/Modules/Crm/Hooks/Opportunity/AmountWeightedConverted.php @@ -0,0 +1,61 @@ + + */ +class AmountWeightedConverted implements AfterSave +{ + /** + * @param Opportunity $entity + */ + public function afterSave(Entity $entity, SaveOptions $options): void + { + if ( + !$entity->isAttributeChanged('amount') && + !$entity->isAttributeChanged('probability') + ) { + return; + } + + $amountConverted = $entity->get('amountConverted'); + $probability = $entity->get('probability'); + + $amountWeightedConverted = round($amountConverted * $probability / 100, 2); + + $entity->set('amountWeightedConverted', $amountWeightedConverted); + } +} diff --git a/application/Espo/Modules/Crm/Hooks/Opportunity/Contacts.php b/application/Espo/Modules/Crm/Hooks/Opportunity/Contacts.php new file mode 100644 index 0000000000..99589c1d22 --- /dev/null +++ b/application/Espo/Modules/Crm/Hooks/Opportunity/Contacts.php @@ -0,0 +1,90 @@ + + */ +class Contacts implements AfterSave +{ + public function __construct(private EntityManager $entityManager) {} + + /** + * @param Opportunity $entity + */ + public function afterSave(Entity $entity, SaveOptions $options): void + { + if (!$entity->isAttributeChanged('contactId')) { + return; + } + + /** @var ?string $contactId */ + $contactId = $entity->get('contactId'); + $contactIdList = $entity->get('contactsIds') ?? []; + $fetchedContactId = $entity->getFetched('contactId'); + + $relation = $this->entityManager + ->getRDBRepositoryByClass(Opportunity::class) + ->getRelation($entity, 'contacts'); + + if (!$contactId) { + if ($fetchedContactId) { + $relation->unrelateById($fetchedContactId); + } + + return; + } + + if (in_array($contactId, $contactIdList)) { + return; + } + + $contact = $this->entityManager + ->getRDBRepositoryByClass(Contact::class) + ->getById($contactId); + + if (!$contact) { + return; + } + + if ($relation->isRelated($contact)) { + return; + } + + $relation->relateById($contactId); + } +} diff --git a/application/Espo/Modules/Crm/Hooks/Opportunity/LastStage.php b/application/Espo/Modules/Crm/Hooks/Opportunity/LastStage.php new file mode 100644 index 0000000000..355b8ecea8 --- /dev/null +++ b/application/Espo/Modules/Crm/Hooks/Opportunity/LastStage.php @@ -0,0 +1,146 @@ + + */ +class LastStage implements BeforeSave +{ + public static int $order = 8; + + public function __construct(private Metadata $metadata) {} + + /** + * @param Opportunity $entity + */ + public function beforeSave(Entity $entity, SaveOptions $options): void + { + if ( + $entity->isAttributeChanged('lastStage') || + !$entity->isAttributeChanged('stage') + ) { + return; + } + + $probability = $this->metadata + ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap', $entity->getStage() ?? '']) ?? 0; + + if ($probability) { + $entity->set('lastStage', $entity->getStage()); + + return; + } + + $probabilityMap = $this->metadata + ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap']) ?? []; + + $stageList = $this->metadata->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'options']) ?? []; + + if (!count($stageList)) { + return; + } + + if ($entity->isNew()) { + // Created as Lost. + + $min = 100; + $minStage = null; + + foreach ($stageList as $stage) { + $itemProbability = $probabilityMap[$stage] ?? null; + + if ( + $itemProbability === null || + $itemProbability === 100 || + $itemProbability === 0 || + $itemProbability >= $min + ) { + continue; + } + + $min = $itemProbability; + $minStage = $stage; + } + + if (!$minStage) { + return; + } + + $entity->set('lastStage', $minStage); + + return; + } + + // Won changed to Lost. + + if (!$entity->getLastStage()) { + return; + } + + $lastStageProbability = $this->metadata + ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap', $entity->getLastStage()]) ?? 0; + + if ($lastStageProbability !== 100) { + return; + } + + $max = 0; + $maxStage = null; + + foreach ($stageList as $stage) { + $itemProbability = $probabilityMap[$stage] ?? null; + + if ( + $itemProbability === null || + $itemProbability === 100 || + $itemProbability === 0 || + $itemProbability <= $max + ) { + continue; + } + + $max = $itemProbability; + $maxStage = $stage; + } + + if (!$maxStage) { + return; + } + + $entity->set('lastStage', $maxStage); + } +} diff --git a/application/Espo/Modules/Crm/Hooks/Opportunity/Probability.php b/application/Espo/Modules/Crm/Hooks/Opportunity/Probability.php new file mode 100644 index 0000000000..6a1f0b87d3 --- /dev/null +++ b/application/Espo/Modules/Crm/Hooks/Opportunity/Probability.php @@ -0,0 +1,75 @@ + + */ +class Probability implements BeforeSave +{ + public static int $order = 7; + + public function __construct(private Metadata $metadata) {} + + /** + * @param Opportunity $entity + */ + public function beforeSave(Entity $entity, SaveOptions $options): void + { + if (!$entity->isNew()) { + return; + } + + if ($entity->has('probability')) { + return; + } + + $stage = $entity->getStage(); + + if (!$stage) { + return; + } + + $probability = $this->metadata + ->get('entityDefs.Opportunity.fields.stage.probabilityMap.' . $stage) ?? 0; + + if ($probability === null) { + return; + } + + $entity->setProbability($probability); + } +} diff --git a/application/Espo/Modules/Crm/Repositories/Opportunity.php b/application/Espo/Modules/Crm/Repositories/Opportunity.php index 0779063563..3e640861f9 100644 --- a/application/Espo/Modules/Crm/Repositories/Opportunity.php +++ b/application/Espo/Modules/Crm/Repositories/Opportunity.php @@ -30,179 +30,10 @@ namespace Espo\Modules\Crm\Repositories; use Espo\Modules\Crm\Entities\Opportunity as OpportunityEntity; -use Espo\ORM\Entity; use Espo\Core\Repositories\Database; /** * @extends Database */ class Opportunity extends Database -{ - public function beforeSave(Entity $entity, array $options = []) - { - $this->processProbability($entity); - $this->processLastStage($entity); - - parent::beforeSave($entity, $options); - } - - public function afterSave(Entity $entity, array $options = []) - { - parent::afterSave($entity, $options); - - if ($entity->isAttributeChanged('amount') || $entity->isAttributeChanged('probability')) { - $amountConverted = $entity->get('amountConverted'); - $probability = $entity->get('probability'); - - $amountWeightedConverted = round($amountConverted * $probability / 100, 2); - - $entity->set('amountWeightedConverted', $amountWeightedConverted); - } - - $this->handleAfterSaveContacts($entity); - } - - protected function handleAfterSaveContacts(OpportunityEntity $entity): void - { - if (!$entity->isAttributeChanged('contactId')) { - return; - } - - $contactId = $entity->get('contactId'); - $contactIdList = $entity->get('contactsIds') ?? []; - $fetchedContactId = $entity->getFetched('contactId'); - - if (!$contactId) { - if ($fetchedContactId) { - $this->unrelate($entity, 'contacts', $fetchedContactId); - } - - return; - } - - if (!in_array($contactId, $contactIdList) && !$this->isRelated($entity, 'contacts', $contactId)) { - $this->relate($entity, 'contacts', $contactId); - } - } - - private function processProbability(OpportunityEntity $entity): void - { - if (!$entity->isNew()) { - return; - } - - if ($entity->has('probability')) { - return; - } - - if (!$entity->getStage()) { - return; - } - - $probability = $this->metadata - ->get('entityDefs.Opportunity.fields.stage.probabilityMap.' . $entity->getStage()) ?? 0; - - if ($probability === null) { - return; - } - - $entity->setProbability($probability); - } - - private function processLastStage(OpportunityEntity $entity): void - { - if ( - $entity->isAttributeChanged('lastStage') || - !$entity->isAttributeChanged('stage') - ) { - return; - } - - $probability = $this->metadata - ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap', $entity->getStage() ?? '']) ?? 0; - - if ($probability) { - $entity->set('lastStage', $entity->getStage()); - - return; - } - - $probabilityMap = $this->metadata - ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap']) ?? []; - - $stageList = $this->metadata->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'options']) ?? []; - - if (!count($stageList)) { - return; - } - - if ($entity->isNew()) { - // Created as Lost. - - $min = 100; - $minStage = null; - - foreach ($stageList as $stage) { - $itemProbability = $probabilityMap[$stage] ?? null; - - if ( - $itemProbability === null || - $itemProbability === 100 || - $itemProbability === 0 || - $itemProbability >= $min - ) { - continue; - } - - $min = $itemProbability; - $minStage = $stage; - } - - if (!$minStage) { - return; - } - - $entity->set('lastStage', $minStage); - - return; - } - - // Won changed to Lost. - - if (!$entity->getLastStage()) { - return; - } - - $lastStageProbability = $this->metadata - ->get(['entityDefs', 'Opportunity', 'fields', 'stage', 'probabilityMap', $entity->getLastStage()]) ?? 0; - - if ($lastStageProbability !== 100) { - return; - } - - $max = 0; - $maxStage = null; - - foreach ($stageList as $stage) { - $itemProbability = $probabilityMap[$stage] ?? null; - - if ( - $itemProbability === null || - $itemProbability === 100 || - $itemProbability === 0 || - $itemProbability <= $max - ) { - continue; - } - - $max = $itemProbability; - $maxStage = $stage; - } - - if (!$maxStage) { - return; - } - - $entity->set('lastStage', $maxStage); - } -} +{}