...Человеческий поиск в разработке...
- Модуль: crm
- Путь к файлу: ~/bitrix/modules/crm/classes/general/crm_deal.php
- Класс: \CAllCrmDeal
- Вызов: CAllCrmDeal::Update
public function Update($ID, array &$arFields, $bCompare = true, $bUpdateSearch = true, $options = array()) { global $DB; $ID = (int) $ID; if(!is_array($options)) { $options = array(); } $options['IS_COMPARE_ENABLED'] = $bCompare; $isSystemAction = isset($options['IS_SYSTEM_ACTION']) && $options['IS_SYSTEM_ACTION']; $this->LAST_ERROR = ''; $this->checkExceptions = array(); if ($this->isUseOperation()) { return $this->getCompatibilityAdapter()->performUpdate($ID, $arFields, $options); } if(isset($options['CURRENT_USER'])) { $userID = intval($options['CURRENT_USER']); } else { $userID = CCrmSecurityHelper::GetCurrentUserID(); } $arFilterTmp = array('ID' => $ID); if (!$this->bCheckPermission) $arFilterTmp['CHECK_PERMISSIONS'] = 'N'; $obRes = self::GetListEx(array(), $arFilterTmp, false, false, array('*', 'UF_*')); if (!($arRow = $obRes->Fetch())) return false; unset( $arFields['DATE_CREATE'], $arFields['DATE_MODIFY'], $arFields['CATEGORY_ID'], $arFields['MOVED_BY_ID'], $arFields['MOVED_TIME'] ); if(!$isSystemAction) { $arFields['~DATE_MODIFY'] = $DB->CurrentTimeFunction(); if(!isset($arFields['MODIFY_BY_ID']) || $arFields['MODIFY_BY_ID'] <= 0) { $arFields['MODIFY_BY_ID'] = $userID; } } if(isset($arFields['TITLE']) && (!is_scalar($arFields['TITLE']) || trim($arFields['TITLE']) === '')) { unset($arFields['TITLE']); } //Scavenging if(isset($arFields['BEGINDATE']) && (!is_string($arFields['BEGINDATE']) || trim($arFields['BEGINDATE']) === '')) { unset($arFields['BEGINDATE']); } if(isset($arFields['CLOSEDATE']) && (!is_string($arFields['CLOSEDATE']) || trim($arFields['CLOSEDATE']) === '')) { unset($arFields['CLOSEDATE']); } if (isset($arFields['ASSIGNED_BY_ID']) && $arFields['ASSIGNED_BY_ID'] <= 0) { unset($arFields['ASSIGNED_BY_ID']); } $assignedByID = (int)(isset($arFields['ASSIGNED_BY_ID']) ? $arFields['ASSIGNED_BY_ID'] : $arRow['ASSIGNED_BY_ID']); $bResult = false; $options['CURRENT_FIELDS'] = $arRow; if (!$this->CheckFields($arFields, $ID, $options)) { $arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR; } else { //region Category, SemanticID and IsNew //Semantic ID depends on Stage ID and can't be assigned directly $syncStageSemantics = isset($options['SYNCHRONIZE_STAGE_SEMANTICS']) && $options['SYNCHRONIZE_STAGE_SEMANTICS']; if(isset($arFields['STAGE_ID']) && ($syncStageSemantics || $arFields['STAGE_ID'] !== $arRow['STAGE_ID'])) { $arFields['STAGE_SEMANTIC_ID'] = self::IsStageExists($arFields['STAGE_ID'], $arRow['CATEGORY_ID']) ? self::GetSemanticID($arFields['STAGE_ID'], $arRow['CATEGORY_ID']) : Bitrix\Crm\PhaseSemantics::UNDEFINED; $arFields['IS_NEW'] = $arFields['STAGE_ID'] === self::GetStartStageID($arRow['CATEGORY_ID']) ? 'Y' : 'N'; if ($arFields['STAGE_ID'] !== $arRow['STAGE_ID']) { $arFields['MOVED_BY_ID'] = (int)$userID; $arFields['MOVED_TIME'] = (new \Bitrix\Main\Type\DateTime())->toString(); } } else { unset($arFields['STAGE_SEMANTIC_ID'], $arFields['IS_NEW']); } //endregion $permissionEntityType = DealCategory::convertToPermissionEntityType($arRow['CATEGORY_ID']); if($this->bCheckPermission && !CCrmAuthorizationHelper::CheckUpdatePermission($permissionEntityType, $ID, $this->cPerms)) { $this->LAST_ERROR = GetMessage('CRM_PERMISSION_DENIED'); $arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR; return false; } $updateOperationRestriction = Crm\Restriction\RestrictionManager::getUpdateOperationRestriction(new Crm\ItemIdentifier( \CCrmOwnerType::Deal, (int)$ID )); if (!$isSystemAction && !$updateOperationRestriction->hasPermission()) { $this->LAST_ERROR = $updateOperationRestriction->getErrorMessage(); $arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR; return false; } if(!isset($arFields['ID'])) { $arFields['ID'] = $ID; } $enableSystemEvents = !isset($options['ENABLE_SYSTEM_EVENTS']) || $options['ENABLE_SYSTEM_EVENTS'] === true; //region Before update event if($enableSystemEvents) { $beforeEvents = GetModuleEvents('crm', 'OnBeforeCrmDealUpdate'); while ($arEvent = $beforeEvents->Fetch()) { if(ExecuteModuleEventEx($arEvent, array(&$arFields)) === false) { if(isset($arFields['RESULT_MESSAGE'])) { $this->LAST_ERROR = $arFields['RESULT_MESSAGE']; } else { $this->LAST_ERROR = GetMessage('CRM_DEAL_UPDATE_CANCELED', array('#NAME#' => $arEvent['TO_NAME'])); $arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR; } return false; } } } //endregion $arAttr = array(); $arAttr['STAGE_ID'] = !empty($arFields['STAGE_ID']) ? $arFields['STAGE_ID'] : $arRow['STAGE_ID']; $arAttr['OPENED'] = !empty($arFields['OPENED']) ? $arFields['OPENED'] : $arRow['OPENED']; $originalObserverIDs = Crm\Observer\ObserverManager::getEntityObserverIDs(CCrmOwnerType::Deal, $ID); $observerIDs = isset($arFields['OBSERVER_IDS']) && is_array($arFields['OBSERVER_IDS']) ? $arFields['OBSERVER_IDS'] : null; if($observerIDs !== null && count($observerIDs) > 0) { $arAttr['CONCERNED_USER_IDS'] = $observerIDs; } elseif($observerIDs === null && count($originalObserverIDs) > 0) { $arAttr['CONCERNED_USER_IDS'] = $originalObserverIDs; } $arEntityAttr = self::BuildEntityAttr($assignedByID, $arAttr); if($this->bCheckPermission) { $sEntityPerm = $this->cPerms->GetPermType($permissionEntityType, 'WRITE', $arEntityAttr); //HACK: Ensure that entity accessible for user restricted by BX_CRM_PERM_OPEN self::PrepareEntityAttrs($arEntityAttr, $sEntityPerm); //HACK: Prevent 'OPENED' field change by user restricted by BX_CRM_PERM_OPEN permission if($sEntityPerm === BX_CRM_PERM_OPEN && isset($arFields['OPENED']) && $arFields['OPENED'] !== 'Y' && $assignedByID !== $userID) { $arFields['OPENED'] = 'Y'; } } if (isset($arFields['ASSIGNED_BY_ID']) && $arRow['ASSIGNED_BY_ID'] != $arFields['ASSIGNED_BY_ID']) CCrmEvent::SetAssignedByElement($arFields['ASSIGNED_BY_ID'], 'DEAL', $ID); //region Preparation of contacts $originalContactBindings = DealContactTable::getDealBindings($ID); $originalContactIDs = EntityBinding::prepareEntityIDs(CCrmOwnerType::Contact, $originalContactBindings); $contactBindings = isset($arFields['CONTACT_BINDINGS']) && is_array($arFields['CONTACT_BINDINGS']) ? $arFields['CONTACT_BINDINGS'] : null; $contactIDs = isset($arFields['CONTACT_IDS']) && is_array($arFields['CONTACT_IDS']) ? $arFields['CONTACT_IDS'] : null; unset($arFields['CONTACT_IDS']); //region Backward compatibility $contactID = isset($arFields['CONTACT_ID']) ? max((int)$arFields['CONTACT_ID'], 0) : null; if($contactBindings === null && $contactIDs === null && $contactID !== null && !in_array($contactID, $originalContactIDs, true)) { //Compatibility mode. Trying to simulate single binding mode if contact is not found in bindings. $contactIDs = array(); if($contactID > 0) { $contactIDs[] = $contactID; } } unset($arFields['CONTACT_ID']); //endregion $addedContactIDs = null; $removedContactIDs = null; $addedContactBindings = null; $removedContactBindings = null; if(is_array($contactIDs) && !is_array($contactBindings)) { $contactBindings = EntityBinding::prepareEntityBindings( \CCrmOwnerType::Contact, $contactIDs ); EntityBinding::markFirstAsPrimary($contactBindings); } elseif(is_array($contactBindings)) { if(EntityBinding::findPrimaryBinding($contactBindings) === null) { EntityBinding::markFirstAsPrimary($contactBindings); } $contactIDs = EntityBinding::prepareEntityIDs( CCrmOwnerType::Contact, $contactBindings ); } if(is_array($contactBindings)) { $removedContactBindings = array(); $addedContactBindings = array(); EntityBinding::prepareBindingChanges( CCrmOwnerType::Contact, $originalContactBindings, $contactBindings, $addedContactBindings, $removedContactBindings ); $addedContactIDs = EntityBinding::prepareEntityIDs( CCrmOwnerType::Contact, $addedContactBindings ); $removedContactIDs = EntityBinding::prepareEntityIDs( CCrmOwnerType::Contact, $removedContactBindings ); } //endregion //region Observers $addedObserverIDs = null; $removedObserverIDs = null; if(is_array($observerIDs)) { $addedObserverIDs = array_diff($observerIDs, $originalObserverIDs); $removedObserverIDs = array_diff($originalObserverIDs, $observerIDs); } //endregion self::getLastActivityAdapter()->performUpdate((int)$ID, $arFields, $options); self::getCommentsAdapter() ->setPreviousFields((int)$ID, $arRow) ->normalizeFields((int)$ID, $arFields) ; $sonetEventData = array(); if ($bCompare) { $compareOptions = array(); if(!empty($addedContactIDs) || !empty($removedContactIDs)) { $compareOptions['CONTACTS'] = array('ADDED' => $addedContactIDs, 'REMOVED' => $removedContactIDs); } $arEvents = self::CompareFields($arRow, $arFields, $this->bCheckPermission, array_merge($compareOptions, $options)); foreach($arEvents as $arEvent) { $arEvent['ENTITY_TYPE'] = 'DEAL'; $arEvent['ENTITY_ID'] = $ID; $arEvent['EVENT_TYPE'] = 1; if(!isset($arEvent['USER_ID'])) { if($userID > 0) { $arEvent['USER_ID'] = $userID; } else if(isset($arFields['MODIFY_BY_ID']) && $arFields['MODIFY_BY_ID'] > 0) { $arEvent['USER_ID'] = $arFields['MODIFY_BY_ID']; } else if(isset($options['CURRENT_USER'])) { $arEvent['USER_ID'] = (int)$options['CURRENT_USER']; } } if ($arEvent['ENTITY_FIELD'] !== 'CONTACT_ID' && $arEvent['ENTITY_FIELD'] !== 'COMPANY_ID') { $CCrmEvent = new CCrmEvent(); $eventID = $CCrmEvent->Add($arEvent, $this->bCheckPermission); } $fieldID = isset($arEvent['ENTITY_FIELD']) ? $arEvent['ENTITY_FIELD'] : ''; if($fieldID === '') { continue; } switch($fieldID) { case 'STAGE_ID': { $sonetEventData[CCrmLiveFeedEvent::Progress] = array( 'TYPE' => CCrmLiveFeedEvent::Progress, 'FIELDS' => array( //'EVENT_ID' => $eventID, 'TITLE' => GetMessage('CRM_DEAL_EVENT_UPDATE_STAGE'), 'MESSAGE' => '', 'PARAMS' => array( 'START_STATUS_ID' => $arRow['STAGE_ID'], 'FINAL_STATUS_ID' => $arFields['STAGE_ID'], 'CATEGORY_ID' => intval($arRow['CATEGORY_ID']) ) ) ); } break; case 'ASSIGNED_BY_ID': { $sonetEventData[CCrmLiveFeedEvent::Responsible] = array( 'TYPE' => CCrmLiveFeedEvent::Responsible, 'FIELDS' => array( //'EVENT_ID' => $eventID, 'TITLE' => GetMessage('CRM_DEAL_EVENT_UPDATE_ASSIGNED_BY'), 'MESSAGE' => '', 'PARAMS' => array( 'START_RESPONSIBLE_ID' => $arRow['ASSIGNED_BY_ID'], 'FINAL_RESPONSIBLE_ID' => $arFields['ASSIGNED_BY_ID'] ) ) ); } break; case 'CONTACT_ID': case 'COMPANY_ID': { if(!isset($sonetEventData[CCrmLiveFeedEvent::Client])) { $oldCompanyID = isset($arRow['COMPANY_ID']) ? intval($arRow['COMPANY_ID']) : 0; $sonetEventData[CCrmLiveFeedEvent::Client] = array( 'CODE'=> 'CLIENT', 'TYPE' => CCrmLiveFeedEvent::Client, 'FIELDS' => array( //'EVENT_ID' => $eventID, 'TITLE' => GetMessage('CRM_DEAL_EVENT_UPDATE_CLIENT'), 'MESSAGE' => '', 'PARAMS' => array( 'REMOVED_CLIENT_CONTACT_IDS' => is_array($removedContactIDs) ? $removedContactIDs : array(), 'ADDED_CLIENT_CONTACT_IDS' => is_array($addedContactIDs) ? $addedContactIDs : array(), //Todo: Remove START_CLIENT_CONTACT_ID and FINAL_CLIENT_CONTACT_ID when log template will be ready 'START_CLIENT_CONTACT_ID' => is_array($removedContactIDs) && isset($removedContactIDs[0]) ? $removedContactIDs[0] : 0, 'FINAL_CLIENT_CONTACT_ID' => is_array($addedContactIDs) && isset($addedContactIDs[0]) ? $addedContactIDs[0] : 0, 'START_CLIENT_COMPANY_ID' => $oldCompanyID, 'FINAL_CLIENT_COMPANY_ID' => isset($arFields['COMPANY_ID']) ? intval($arFields['COMPANY_ID']) : $oldCompanyID ) ) ); } } break; case 'TITLE': { $sonetEventData[CCrmLiveFeedEvent::Denomination] = array( 'TYPE' => CCrmLiveFeedEvent::Denomination, 'FIELDS' => array( //'EVENT_ID' => $eventID, 'TITLE' => GetMessage('CRM_DEAL_EVENT_UPDATE_TITLE'), 'MESSAGE' => '', 'PARAMS' => array( 'START_TITLE' => $arRow['TITLE'], 'FINAL_TITLE' => $arFields['TITLE'] ) ) ); } break; } } } $arFields = array_merge($arFields, \CCrmAccountingHelper::calculateAccountingData($arFields, $arRow, true)); $currentDate = ConvertTimeStamp(time() + \CTimeZone::GetOffset(), 'SHORT', SITE_ID); $enableCloseDateSync = DealSettings::getCurrent()->isCloseDateSyncEnabled(); if(isset($options['ENABLE_CLOSE_DATE_SYNC']) && is_bool($options['ENABLE_CLOSE_DATE_SYNC'])) { $enableCloseDateSync = $options['ENABLE_CLOSE_DATE_SYNC']; } $categoryID = isset($arRow['CATEGORY_ID']) ? (int)$arRow['CATEGORY_ID'] : 0; if(isset($arFields['STAGE_ID'])) { $isFinalStage = self::GetStageSemantics($arFields['STAGE_ID'], $categoryID) !== 'process'; $isStageChanged = !isset($arRow['STAGE_ID']) || $arRow['STAGE_ID'] !== $arFields['STAGE_ID']; $arFields['CLOSED'] = $isFinalStage ? 'Y' : 'N'; if($enableCloseDateSync && $isFinalStage && $isStageChanged) { $arFields['CLOSEDATE'] = $currentDate; $arFields['~CLOSEDATE'] = $DB->CharToDateFunction($currentDate, 'SHORT', false); } elseif(isset($arFields['CLOSEDATE'])) { $arFields['~CLOSEDATE'] = $DB->CharToDateFunction($arFields['CLOSEDATE'], 'SHORT', false); } } elseif(isset($arFields['CLOSEDATE'])) { $arFields['~CLOSEDATE'] = $DB->CharToDateFunction($arFields['CLOSEDATE'], 'SHORT', false); } if(isset($arFields['BEGINDATE'])) { $arFields['~BEGINDATE'] = $DB->CharToDateFunction($arFields['BEGINDATE'], 'SHORT', false); } if(isset($arFields['BEGINDATE'])) { $arFields['__BEGINDATE'] = $arFields['BEGINDATE']; unset($arFields['BEGINDATE']); } if(isset($arFields['CLOSEDATE'])) { $arFields['__CLOSEDATE'] = $arFields['CLOSEDATE']; unset($arFields['CLOSEDATE']); } unset($arFields['ID']); $this->normalizeEntityFields($arFields); $sUpdate = $DB->PrepareUpdate(self::TABLE_NAME, $arFields); if ($sUpdate <> '') { $DB->Query("UPDATE b_crm_deal SET {$sUpdate} WHERE ID = {$ID}", false, 'FILE: '.__FILE__.'
LINE: '.__LINE__); $bResult = true; } //Restore BEGINDATE and CLOSEDATE if(isset($arFields['__BEGINDATE'])) { $arFields['BEGINDATE'] = $arFields['__BEGINDATE']; unset($arFields['__BEGINDATE']); } if(isset($arFields['__CLOSEDATE'])) { $arFields['CLOSEDATE'] = $arFields['__CLOSEDATE']; unset($arFields['__CLOSEDATE']); } if(defined("BX_COMP_MANAGED_CACHE")) { static $arNameFields = array("TITLE"); $bClear = false; foreach($arNameFields as $val) { if(isset($arFields[$val])) { $bClear = true; break; } } if ($bClear) { $GLOBALS["CACHE_MANAGER"]->ClearByTag("crm_entity_name_".CCrmOwnerType::Deal."_".$ID); } } //region User Field CCrmEntityHelper::NormalizeUserFields($arFields, self::$sUFEntityID, $GLOBALS['USER_FIELD_MANAGER'], array('IS_NEW' => false)); $GLOBALS['USER_FIELD_MANAGER']->Update(self::$sUFEntityID, $ID, $arFields); //endregion //region Ensure entity has not been deleted yet by concurrent process $currentDbResult = \CCrmDeal::GetListEx( array(), array('=ID' => $ID, 'CHECK_PERMISSIONS' => 'N'), false, false, array('*', 'UF_*') ); $currentFields = $currentDbResult->Fetch(); if(!is_array($currentFields)) { return false; } //endregion //region Save contacts if(!empty($removedContactBindings)) { DealContactTable::unbindContacts($ID, $removedContactBindings); } if(!empty($addedContactBindings)) { DealContactTable::bindContacts($ID, $addedContactBindings); } //endregion //region Save Observers if(!empty($addedObserverIDs)) { Crm\Observer\ObserverManager::registerBulk( $addedObserverIDs, \CCrmOwnerType::Deal, $ID, count($originalObserverIDs) ); } if(!empty($removedObserverIDs)) { Crm\Observer\ObserverManager::unregisterBulk( $removedObserverIDs, \CCrmOwnerType::Deal, $ID ); } //endregion //region Save access rights for owner and observers $securityRegisterOptions = (new \Bitrix\Crm\Security\Controller\RegisterOptions()) ->setEntityAttributes($arEntityAttr) ->setEntityFields($currentFields) ; Crm\Security\Manager::getEntityController(CCrmOwnerType::Deal) ->register($permissionEntityType, $ID, $securityRegisterOptions) ; //endregion self::SynchronizeCustomerData($ID, $arRow, array('ENABLE_SOURCE' => false)); self::SynchronizeCustomerData($ID, $currentFields); if (isset($GLOBALS['USER']) && isset($arFields['COMPANY_ID']) && $arFields['COMPANY_ID'] > 0) { CUserOptions::SetOption('crm', 'crm_company_search', array('last_selected' => $arFields['COMPANY_ID'])); } //region Complete activities if entity is closed if($arRow['STAGE_SEMANTIC_ID'] !== $currentFields['STAGE_SEMANTIC_ID'] && $currentFields['STAGE_SEMANTIC_ID'] !== Bitrix\Crm\PhaseSemantics::PROCESS) { CCrmActivity::SetAutoCompletedByOwner(CCrmOwnerType::Deal, $ID); } //endregion //region Statistics & History if(!isset($options['REGISTER_STATISTICS']) || $options['REGISTER_STATISTICS'] === true) { DealSumStatisticEntry::register($ID, $currentFields); DealStageHistoryEntry::synchronize($ID, $currentFields); DealInvoiceStatisticEntry::synchronize($ID, $currentFields); DealActivityStatisticEntry::synchronize($ID, $currentFields); DealChannelBinding::synchronize($ID, $currentFields); if(isset($arFields['STAGE_ID'])) { DealStageHistoryEntry::register($ID, $currentFields, array('IS_NEW' => false)); } $oldLeadID = isset($arRow['LEAD_ID']) ? (int)$arRow['LEAD_ID'] : 0; $curLeadID = isset($arFields['LEAD_ID']) ? (int)$arFields['LEAD_ID'] : $oldLeadID; if($oldLeadID != $curLeadID) { if($oldLeadID > 0) { LeadConversionStatisticsEntry::processBindingsChange($oldLeadID); } if($curLeadID > 0) { LeadConversionStatisticsEntry::processBindingsChange($curLeadID); } } } //endregion self::getCommentsAdapter() ->setPreviousFields((int)$ID, $arRow) ->performUpdate((int)$ID, $arFields, $options) ; if ($bResult) { \Bitrix\Crm\Counter\Monitor::getInstance()->onEntityUpdate(CCrmOwnerType::Deal, $arRow, $currentFields); } // update utm fields UtmTable::updateEntityUtmFromFields(CCrmOwnerType::Deal, $ID, $arFields); //region save parent relations Crm\Service\Container::getInstance()->getParentFieldManager()->saveParentRelationsForIdentifier( new Crm\ItemIdentifier(\CCrmOwnerType::Deal, $ID), $arFields ); //endregion if($bUpdateSearch) { $arFilterTmp = Array('ID' => $ID); if (!$this->bCheckPermission) $arFilterTmp['CHECK_PERMISSIONS'] = 'N'; CCrmSearch::UpdateSearch($arFilterTmp, 'DEAL', true); } //region Search content index Bitrix\Crm\Search\SearchContentBuilderFactory::create(CCrmOwnerType::Deal) ->build($ID, ['checkExist' => true]); //endregion Bitrix\Crm\Timeline\DealController::getInstance()->onModify( $ID, array( 'CURRENT_FIELDS' => $arFields, 'PREVIOUS_FIELDS' => $arRow, 'CONTACT_BINDINGS' => $contactBindings, 'ADDED_CONTACT_BINDINGS' => $addedContactBindings ) ); CCrmEntityHelper::registerAdditionalTimelineEvents([ 'entityTypeId' => \CCrmOwnerType::Deal, 'entityId' => $ID, 'fieldsInfo' => static::GetFieldsInfo(), 'previousFields' => $arRow, 'currentFields' => $arFields, 'previousStageSemantics' => $arRow['STAGE_SEMANTIC_ID'] ?? Crm\PhaseSemantics::UNDEFINED, 'currentStageSemantics' => $arFields['STAGE_SEMANTIC_ID'] ?? Crm\PhaseSemantics::UNDEFINED, 'options' => $options, 'bindings' => [ 'entityTypeId' => \CCrmOwnerType::Contact, 'previous' => $originalContactBindings, 'current' => $contactBindings, ] ]); Bitrix\Crm\Integration\Im\Chat::onEntityModification( CCrmOwnerType::Deal, $ID, array( 'CURRENT_FIELDS' => $arFields, 'PREVIOUS_FIELDS' => $arRow, 'ADDED_OBSERVER_IDS' => $addedObserverIDs, 'REMOVED_OBSERVER_IDS' => $removedObserverIDs ) ); $arFields['ID'] = $ID; if (isset($arFields['FM']) && is_array($arFields['FM'])) { $CCrmFieldMulti = new CCrmFieldMulti(); $CCrmFieldMulti->SetFields('DEAL', $ID, $arFields['FM']); } // Responsible user sync //CCrmActivity::Synchronize(CCrmOwnerType::Deal, $ID); $registerSonetEvent = isset($options['REGISTER_SONET_EVENT']) && $options['REGISTER_SONET_EVENT'] === true; if ( $bResult && isset($arFields['ASSIGNED_BY_ID']) && Crm\Settings\Crm::isLiveFeedRecordsGenerationEnabled() ) { CCrmSonetSubscription::ReplaceSubscriptionByEntity( CCrmOwnerType::Deal, $ID, CCrmSonetSubscriptionType::Responsibility, $arFields['ASSIGNED_BY_ID'], $arRow['ASSIGNED_BY_ID'], $registerSonetEvent ); } if($bResult && $bCompare && $registerSonetEvent && !empty($sonetEventData)) { //region Preparation of Parent Contact IDs $parentContactIDs = is_array($contactIDs) ? $contactIDs : DealContactTable::getDealContactIDs($ID); //endregion //COMPANY $newCompanyID = isset($arFields['COMPANY_ID']) ? (int)$arFields['COMPANY_ID'] : 0; $oldCompanyID = isset($arRow['COMPANY_ID']) ? (int)$arRow['COMPANY_ID'] : 0; $companyID = $newCompanyID > 0 ? $newCompanyID : $oldCompanyID; $modifiedByID = (int)$arFields['MODIFY_BY_ID']; foreach($sonetEventData as &$sonetEvent) { $sonetEventType = $sonetEvent['TYPE']; $sonetEventFields = &$sonetEvent['FIELDS']; $sonetEventFields['ENTITY_TYPE_ID'] = CCrmOwnerType::Deal; $sonetEventFields['ENTITY_ID'] = $ID; $sonetEventFields['USER_ID'] = $modifiedByID; $parents = array(); //Register company relation if($companyID > 0) { CCrmLiveFeed::PrepareOwnershipRelations( CCrmOwnerType::Company, array($companyID), $parents ); } //Register contact relation CCrmLiveFeed::PrepareOwnershipRelations( CCrmOwnerType::Contact, $parentContactIDs, $parents ); if(!empty($parents)) { $sonetEventFields['PARENTS'] = array_values($parents); } $logEventID = CCrmLiveFeed::CreateLogEvent($sonetEventFields, $sonetEventType, ['CURRENT_USER' => $userID]); if ( $logEventID !== false && CModule::IncludeModule("im") ) { $title = CCrmOwnerType::GetCaption(CCrmOwnerType::Deal, $ID, false); $url = CCrmOwnerType::GetEntityShowPath(CCrmOwnerType::Deal, $ID); $serverName = (CMain::IsHTTPS() ? "https" : "http")."://".((defined("SITE_SERVER_NAME") && SITE_SERVER_NAME <> '') ? SITE_SERVER_NAME : COption::GetOptionString("main", "server_name", "")); if ( $sonetEvent['TYPE'] == CCrmLiveFeedEvent::Responsible && $sonetEventFields['PARAMS']['FINAL_RESPONSIBLE_ID'] != $modifiedByID ) { $arMessageFields = array( "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "TO_USER_ID" => $sonetEventFields['PARAMS']['FINAL_RESPONSIBLE_ID'], "FROM_USER_ID" => $modifiedByID, "NOTIFY_TYPE" => IM_NOTIFY_FROM, "NOTIFY_MODULE" => "crm", "LOG_ID" => $logEventID, //"NOTIFY_EVENT" => "deal_update", "NOTIFY_EVENT" => "changeAssignedBy", "NOTIFY_TAG" => "CRM|DEAL_RESPONSIBLE|".$ID, "NOTIFY_MESSAGE" => GetMessage("CRM_DEAL_RESPONSIBLE_IM_NOTIFY", Array("#title#" => "".htmlspecialcharsbx($title)."")), "NOTIFY_MESSAGE_OUT" => GetMessage("CRM_DEAL_RESPONSIBLE_IM_NOTIFY", Array("#title#" => htmlspecialcharsbx($title)))." (".$serverName.$url.")" ); CIMNotify::Add($arMessageFields); } if ( $sonetEvent['TYPE'] == CCrmLiveFeedEvent::Responsible && $sonetEventFields['PARAMS']['START_RESPONSIBLE_ID'] != $modifiedByID ) { $arMessageFields = array( "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "TO_USER_ID" => $sonetEventFields['PARAMS']['START_RESPONSIBLE_ID'], "FROM_USER_ID" => $modifiedByID, "NOTIFY_TYPE" => IM_NOTIFY_FROM, "NOTIFY_MODULE" => "crm", "LOG_ID" => $logEventID, //"NOTIFY_EVENT" => "deal_update", "NOTIFY_EVENT" => "changeAssignedBy", "NOTIFY_TAG" => "CRM|DEAL_RESPONSIBLE|".$ID, "NOTIFY_MESSAGE" => GetMessage("CRM_DEAL_NOT_RESPONSIBLE_IM_NOTIFY", Array("#title#" => "".htmlspecialcharsbx($title)."")), "NOTIFY_MESSAGE_OUT" => GetMessage("CRM_DEAL_NOT_RESPONSIBLE_IM_NOTIFY", Array("#title#" => htmlspecialcharsbx($title)))." (".$serverName.$url.")" ); CIMNotify::Add($arMessageFields); } if ( $sonetEvent['TYPE'] == CCrmLiveFeedEvent::Progress && $sonetEventFields['PARAMS']['START_STATUS_ID'] && $sonetEventFields['PARAMS']['FINAL_STATUS_ID'] ) { $assignedByID = (isset($arFields['ASSIGNED_BY_ID']) ? $arFields['ASSIGNED_BY_ID'] : $arRow['ASSIGNED_BY_ID']); $infos = self::GetStages($categoryID); if ( $assignedByID != $modifiedByID && isset($infos[$sonetEventFields['PARAMS']['START_STATUS_ID']]) && isset($infos[$sonetEventFields['PARAMS']['FINAL_STATUS_ID']]) ) { $arMessageFields = array( "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "TO_USER_ID" => $assignedByID, "FROM_USER_ID" => $modifiedByID, "NOTIFY_TYPE" => IM_NOTIFY_FROM, "NOTIFY_MODULE" => "crm", "LOG_ID" => $logEventID, //"NOTIFY_EVENT" => "deal_update", "NOTIFY_EVENT" => "changeStage", "NOTIFY_TAG" => "CRM|DEAL_PROGRESS|".$ID, "NOTIFY_MESSAGE" => GetMessage("CRM_DEAL_PROGRESS_IM_NOTIFY_2", Array( "#title#" => "".htmlspecialcharsbx($title)."", "#start_status_title#" => htmlspecialcharsbx($infos[$sonetEventFields['PARAMS']['START_STATUS_ID']]['NAME']), "#final_status_title#" => htmlspecialcharsbx($infos[$sonetEventFields['PARAMS']['FINAL_STATUS_ID']]['NAME']) )), "NOTIFY_MESSAGE_OUT" => GetMessage("CRM_DEAL_PROGRESS_IM_NOTIFY_2", Array( "#title#" => htmlspecialcharsbx($title), "#start_status_title#" => htmlspecialcharsbx($infos[$sonetEventFields['PARAMS']['START_STATUS_ID']]['NAME']), "#final_status_title#" => htmlspecialcharsbx($infos[$sonetEventFields['PARAMS']['FINAL_STATUS_ID']]['NAME']) ))." (".$serverName.$url.")" ); CIMNotify::Add($arMessageFields); } } } unset($sonetEventFields); } unset($sonetEvent); } //region After update event if($bResult && $enableSystemEvents) { $afterEvents = GetModuleEvents('crm', 'OnAfterCrmDealUpdate'); while ($arEvent = $afterEvents->Fetch()) ExecuteModuleEventEx($arEvent, array(&$arFields)); } //endregion self::PullChange('UPDATE', array('ID' => $ID)); if(!$isSystemAction) { $stageSemanticsId = ($arFields['STAGE_SEMANTIC_ID'] ?? null) ?: $arRow['STAGE_SEMANTIC_ID']; if(Crm\Ml\Scoring::isMlAvailable() && !Crm\PhaseSemantics::isFinal($stageSemanticsId)) { Crm\Ml\Scoring::queuePredictionUpdate(CCrmOwnerType::Deal, $ID, [ 'EVENT_TYPE' => Crm\Ml\Scoring::EVENT_ENTITY_UPDATE ]); } } if ($bResult && !$syncStageSemantics) { $item = Crm\Kanban\Entity::getInstance(self::$TYPE_NAME) ->createPullItem(array_merge($arRow, $arFields)); PullManager::getInstance()->sendItemUpdatedEvent( $item, [ 'TYPE' => self::$TYPE_NAME, 'CATEGORY_ID' => \CCrmDeal::GetCategoryID($ID), 'SKIP_CURRENT_USER' => ($userID !== 0), 'IGNORE_DELAY' => \CCrmBizProcHelper::isActiveDebugEntity(\CCrmOwnerType::Deal, $ID), ] ); } } return $bResult; }