From ec242152e70935881fd8bf32696c9d477b399636 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 22 Oct 2025 08:49:51 +0300 Subject: [PATCH] fix convert lead duplicate --- .../Modules/Crm/Tools/Lead/ConvertService.php | 164 +++++++----------- 1 file changed, 66 insertions(+), 98 deletions(-) diff --git a/application/Espo/Modules/Crm/Tools/Lead/ConvertService.php b/application/Espo/Modules/Crm/Tools/Lead/ConvertService.php index 414202ec27..b7ccda8408 100644 --- a/application/Espo/Modules/Crm/Tools/Lead/ConvertService.php +++ b/application/Espo/Modules/Crm/Tools/Lead/ConvertService.php @@ -84,25 +84,18 @@ class ConvertService { $lead = $this->getLead($id); - $duplicateList = []; - $skipSave = false; - - $duplicateCheck = !$params->skipDuplicateCheck(); + if (!$params->skipDuplicateCheck()) { + $this->processDuplicateCheck($records); + } $account = $this->processAccount( lead: $lead, records: $records, - duplicateCheck: $duplicateCheck, - duplicateList: $duplicateList, - skipSave: $skipSave, ); $contact = $this->processContact( lead: $lead, records: $records, - duplicateCheck: $duplicateCheck, - duplicateList: $duplicateList, - skipSave: $skipSave, account: $account, ); @@ -111,17 +104,10 @@ class ConvertService $opportunity = $this->processOpportunity( lead: $lead, records: $records, - duplicateCheck: $duplicateCheck, - duplicateList: $duplicateList, - skipSave: $skipSave, account: $account, contact: $contact, ); - if ($duplicateCheck && count($duplicateList)) { - throw ConflictSilent::createWithBody('duplicate', Json::encode($duplicateList)); - } - $lead->setStatus(Lead::STATUS_CONVERTED); $this->entityManager->saveEntity($lead); @@ -280,19 +266,12 @@ class ConvertService } /** - * @param object[] $duplicateList * @throws Forbidden * @throws BadRequest * @throws Conflict */ - private function processAccount( - Lead $lead, - Values $records, - bool $duplicateCheck, - array &$duplicateList, - bool &$skipSave, - ): ?Account { - + private function processAccount(Lead $lead, Values $records): ?Account + { if (!$records->has(Account::ENTITY_TYPE)) { return null; } @@ -305,35 +284,14 @@ class ConvertService $service = $this->recordServiceContainer->getByClass(Account::class); - $account = $this->entityManager->getRDBRepositoryByClass(Account::class)->getNew(); - $account->set($values); - - if ($duplicateCheck) { - foreach ($service->findDuplicates($account) ?? [] as $e) { - $duplicateList[] = (object) [ - 'id' => $e->getId(), - 'name' => $e->getName(), - '_entityType' => $e->getEntityType(), - ]; - - $skipSave = true; - } - } - - if ($skipSave) { - return null; - } - - $account = $service->create($values, CreateParams::create()->withSkipDuplicateCheck()); - $lead->set('createdAccountId', $account->getId()); + $lead->setCreatedAccount($account); return $account; } /** - * @param object[] $duplicateList * @throws Forbidden * @throws BadRequest * @throws Conflict @@ -341,9 +299,6 @@ class ConvertService private function processContact( Lead $lead, Values $records, - bool $duplicateCheck, - array &$duplicateList, - bool &$skipSave, ?Account $account, ): ?Contact { @@ -363,25 +318,6 @@ class ConvertService $service = $this->recordServiceContainer->getByClass(Contact::class); - $contact = $this->entityManager->getRDBRepositoryByClass(Contact::class)->getNew(); - $contact->set($values); - - if ($duplicateCheck) { - foreach ($service->findDuplicates($contact) ?? [] as $e) { - $duplicateList[] = (object) [ - 'id' => $e->getId(), - 'name' => $e->getName(), - '_entityType' => $e->getEntityType(), - ]; - - $skipSave = true; - } - } - - if ($skipSave) { - return null; - } - $contact = $service->create($values, CreateParams::create()->withSkipDuplicateCheck()); $lead->set('createdContactId', $contact->getId()); @@ -391,14 +327,13 @@ class ConvertService $contact->getAccount() && !$contact->getAccount()->get('originalLeadId') ) { - $lead->set('createdAccountId', $contact->getAccount()->getId()); + $lead->setCreatedAccount($contact->getAccount()); } return $contact; } /** - * @param object[] $duplicateList * @throws Forbidden * @throws BadRequest * @throws Conflict @@ -406,9 +341,6 @@ class ConvertService private function processOpportunity( Lead $lead, Values $records, - bool $duplicateCheck, - array &$duplicateList, - bool &$skipSave, ?Account $account, ?Contact $contact, ): ?Opportunity { @@ -433,30 +365,10 @@ class ConvertService $service = $this->recordServiceContainer->getByClass(Opportunity::class); - $opportunity = $this->entityManager->getRDBRepositoryByClass(Opportunity::class)->getNew(); - $opportunity->set($values); - - if ($duplicateCheck) { - foreach ($service->findDuplicates($opportunity) ?? [] as $e) { - $duplicateList[] = (object) [ - 'id' => $e->getId(), - 'name' => $e->getName(), - '_entityType' => $e->getEntityType(), - ]; - - $skipSave = true; - } - } - - if ($skipSave) { - return null; - } - $opportunity = $service->create($values, CreateParams::create()->withSkipDuplicateCheck()); if ($contact) { $this->entityManager - ->getRDBRepository(Contact::ENTITY_TYPE) ->getRelation($contact, 'opportunities') ->relate($opportunity); } @@ -532,7 +444,6 @@ class ConvertService foreach ($calls as $call) { if ($contact && $contact->hasId()) { $this->entityManager - ->getRDBRepository(Call::ENTITY_TYPE) ->getRelation($call, 'contacts') ->relate($contact); } @@ -579,14 +490,12 @@ class ConvertService foreach ($documents as $document) { if ($account && $account->hasId()) { $this->entityManager - ->getRDBRepository(Document::ENTITY_TYPE) ->getRelation($document, 'accounts') ->relate($account); } if ($opportunity && $opportunity->hasId()) { $this->entityManager - ->getRDBRepository(Document::ENTITY_TYPE) ->getRelation($document, 'opportunities') ->relate($opportunity); } @@ -637,4 +546,63 @@ class ConvertService return $account; } + + /** + * @throws Conflict + */ + private function processDuplicateCheck(Values $records): void + { + $duplicateList = []; + + if ($records->has(Account::ENTITY_TYPE)) { + $accountService = $this->recordServiceContainer->getByClass(Account::class); + + $account = $this->entityManager->getRDBRepositoryByClass(Account::class)->getNew(); + $account->set($records->get(Account::ENTITY_TYPE)); + + foreach ($accountService->findDuplicates($account) ?? [] as $e) { + $duplicateList[] = (object) [ + 'id' => $e->getId(), + 'name' => $e->getName(), + '_entityType' => $e->getEntityType(), + ]; + } + } + + if ($records->has(Contact::ENTITY_TYPE)) { + $contactService = $this->recordServiceContainer->getByClass(Contact::class); + + $contact = $this->entityManager->getRDBRepositoryByClass(Contact::class)->getNew(); + $contact->set($records->get(Contact::ENTITY_TYPE)); + + foreach ($contactService->findDuplicates($contact) ?? [] as $e) { + $duplicateList[] = (object) [ + 'id' => $e->getId(), + 'name' => $e->getName(), + '_entityType' => $e->getEntityType(), + ]; + } + } + + if ($records->has(Opportunity::ENTITY_TYPE)) { + $opportunityService = $this->recordServiceContainer->getByClass(Opportunity::class); + + $opportunity = $this->entityManager->getRDBRepositoryByClass(Opportunity::class)->getNew(); + $opportunity->set($records->get(Opportunity::ENTITY_TYPE)); + + foreach ($opportunityService->findDuplicates($opportunity) ?? [] as $e) { + $duplicateList[] = (object) [ + 'id' => $e->getId(), + 'name' => $e->getName(), + '_entityType' => $e->getEntityType(), + ]; + } + } + + if (!count($duplicateList)) { + return; + } + + throw ConflictSilent::createWithBody('duplicate', Json::encode($duplicateList)); + } }