• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/classes/general/crm_lead.php
  • Класс: \CAllCrmLead
  • Вызов: CAllCrmLead::Add
public function Add(array &$arFields, $bUpdateSearch = true, $options = array())
{
	global $DB;

	if(!is_array($options))
	{
		$options = array();
	}

	if ($this->isUseOperation())
	{
		return $this->getCompatibilityAdapter()->performAdd($arFields, $options);
	}

	$this->LAST_ERROR = '';
	$this->checkExceptions = array();

	$isRestoration = isset($options['IS_RESTORATION']) && $options['IS_RESTORATION'];

	$userID = isset($options['CURRENT_USER'])
		? (int)$options['CURRENT_USER'] : CCrmSecurityHelper::GetCurrentUserID();

	if($userID <= 0 && $this->bCheckPermission)
	{
		$arFields['RESULT_MESSAGE'] = $this->LAST_ERROR = GetMessage('CRM_PERMISSION_USER_NOT_DEFINED');
		return false;
	}

	unset($arFields['ID']);

	if(!($isRestoration && isset($arFields['DATE_CREATE'])))
	{
		unset($arFields['DATE_CREATE']);
		$arFields['~DATE_CREATE'] = $DB->CurrentTimeFunction();
	}

	if(!($isRestoration && isset($arFields['DATE_MODIFY'])))
	{
		unset($arFields['DATE_MODIFY']);
		$arFields['~DATE_MODIFY'] = $DB->CurrentTimeFunction();
	}

	if(!($isRestoration && isset($arFields['MOVED_TIME'])))
	{
		unset($arFields['MOVED_TIME']);
	}
	if(!($isRestoration && isset($arFields['MOVED_BY_ID'])))
	{
		unset($arFields['MOVED_BY_ID']);
	}

	if($userID > 0)
	{
		if(!(isset($arFields['CREATED_BY_ID']) && $arFields['CREATED_BY_ID'] > 0))
		{
			$arFields['CREATED_BY_ID'] = $userID;
		}

		if(!(isset($arFields['MODIFY_BY_ID']) && $arFields['MODIFY_BY_ID'] > 0))
		{
			$arFields['MODIFY_BY_ID'] = $userID;
		}

		if(!(isset($arFields['ASSIGNED_BY_ID']) && $arFields['ASSIGNED_BY_ID'] > 0))
		{
			$arFields['ASSIGNED_BY_ID'] = $userID;
		}
	}

	if(!isset($arFields['OPPORTUNITY']))
	{
		$arFields['OPPORTUNITY'] = 0.0;
	}

	if(!isset($arFields['TITLE']) || !is_string($arFields['TITLE']) || trim($arFields['TITLE']) === '')
	{
		$arFields['TITLE'] = self::GetDefaultTitle();
	}

	$fields = self::GetUserFields();
	$this->fillEmptyFieldValues($arFields, $fields);

	if(!$this->CheckFields($arFields, false, $options))
	{
		$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
		return false;
	}

	if(isset($arFields['BIRTHDATE']))
	{
		if($arFields['BIRTHDATE'] !== '')
		{
			$birthDate = $arFields['BIRTHDATE'];
			$arFields['~BIRTHDATE'] = $DB->CharToDateFunction($birthDate, 'SHORT', false);
			$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting($birthDate);
		}
		else
		{
			$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting('');
		}
		unset($arFields['BIRTHDATE']);
	}
	else
	{
		$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting('');
	}

	if (!isset($arFields['MOVED_BY_ID']))
	{
		$arFields['MOVED_BY_ID'] = (int)$userID;
	}
	if (!isset($arFields['MOVED_TIME']))
	{
		$arFields['MOVED_TIME'] = (new \Bitrix\Main\Type\DateTime())->toString();
	}

	self::getLastActivityAdapter()->performAdd($arFields, $options);
	self::getCommentsAdapter()->normalizeFields(null, $arFields);

	$permissionTypeId = (
		$this->bCheckPermission
			? Bitrix\Crm\Security\EntityPermissionType::CREATE
			: Bitrix\Crm\Security\EntityPermissionType::UNDEFINED
	);

	if(!isset($arFields['STATUS_ID']) || (string)$arFields['STATUS_ID'] === '')
	{
		$arFields['STATUS_ID'] = self::GetStartStatusID($permissionTypeId);
	}

	$viewMode = ($options['ITEM_OPTIONS']['VIEW_MODE'] ?? null);

	$viewModeActivitiesStatusId = null;
	if ($viewMode === ViewMode::MODE_ACTIVITIES)
	{
		$viewModeActivitiesStatusId = $arFields['STATUS_ID'];
		$arFields['STATUS_ID'] = self::GetStartStatusID($permissionTypeId);
	}

	$isStatusExist = self::IsStatusExists($arFields['STATUS_ID']);
	$arFields['STATUS_SEMANTIC_ID'] = $isStatusExist
		? self::GetSemanticID($arFields['STATUS_ID'])
		: Bitrix\Crm\PhaseSemantics::UNDEFINED
	;

	if (isset($arFields['DATE_CLOSED']))
		unset($arFields['DATE_CLOSED']);
	self::EnsureStatusesLoaded();
	if (in_array($arFields['STATUS_ID'], self::$LEAD_STATUSES_BY_GROUP['FINISHED']))
		$arFields['~DATE_CLOSED'] = $DB->CurrentTimeFunction();

	$observerIDs = isset($arFields['OBSERVER_IDS']) && is_array($arFields['OBSERVER_IDS'])
		? $arFields['OBSERVER_IDS'] : null;
	unset($arFields['OBSERVER_IDS']);

	$arAttr = array();

	$arAttr['STATUS_ID'] = $arFields['STATUS_ID'];
	if (!empty($arFields['OPENED']))
	{
		$arAttr['OPENED'] = $arFields['OPENED'];
	}

	if(!empty($observerIDs))
	{
		$arAttr['CONCERNED_USER_IDS'] = $observerIDs;
	}

	$sPermission = 'ADD';
	if (isset($arFields['PERMISSION']))
	{
		if ($arFields['PERMISSION'] == 'IMPORT')
			$sPermission = 'IMPORT';
		unset($arFields['PERMISSION']);
	}

	$assignedByID = (int)$arFields['ASSIGNED_BY_ID'];
	if($this->bCheckPermission)
	{
		$arEntityAttr = self::BuildEntityAttr($userID, $arAttr);
		$userPerms =  $userID == CCrmPerms::GetCurrentUserID() ? $this->cPerms : CCrmPerms::GetUserPermissions($userID);
		$sEntityPerm = $userPerms->GetPermType('LEAD', $sPermission, $arEntityAttr);
		if ($sEntityPerm == BX_CRM_PERM_NONE)
		{
			$this->LAST_ERROR = GetMessage('CRM_PERMISSION_DENIED');
			$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
			return false;
		}

		if ($sEntityPerm == BX_CRM_PERM_SELF && $assignedByID != $userID)
		{
			$arFields['ASSIGNED_BY_ID'] = $assignedByID = $userID;
		}
		if ($sEntityPerm == BX_CRM_PERM_OPEN && $userID == $assignedByID)
		{
			$arFields['OPENED'] = 'Y';
		}
	}

	$assignedByID = (int)$arFields['ASSIGNED_BY_ID'];
	$arEntityAttr = self::BuildEntityAttr($assignedByID, $arAttr);
	$userPerms =  $assignedByID == CCrmPerms::GetCurrentUserID() ? $this->cPerms : CCrmPerms::GetUserPermissions($assignedByID);
	$sEntityPerm = $userPerms->GetPermType(self::$TYPE_NAME, $sPermission, $arEntityAttr);
	$this->PrepareEntityAttrs($arEntityAttr, $sEntityPerm);

	//Prepare currency & exchange rate
	if(!isset($arFields['CURRENCY_ID']))
	{
		$arFields['CURRENCY_ID'] = CCrmCurrency::GetBaseCurrencyID();
	}

	if(!isset($arFields['EXCH_RATE']))
	{
		$arFields['EXCH_RATE'] = CCrmCurrency::GetExchangeRate($arFields['CURRENCY_ID']);
	}

	$arFields = array_merge($arFields, \CCrmAccountingHelper::calculateAccountingData($arFields));

	if (isset($arFields['NAME']) || isset($arFields['LAST_NAME']))
	{
		$arFields['FULL_NAME'] = trim((isset($arFields['NAME'])? $arFields['NAME']: '').' '.(isset($arFields['LAST_NAME'])? $arFields['LAST_NAME']: ''));
	}

	//region Setup HAS_EMAIL & HAS_PHONE & HAS_IMOL fields
	$arFields['HAS_EMAIL'] = $arFields['HAS_PHONE'] = $arFields['HAS_IMOL'] = 'N';
	if(isset($arFields['FM']) && is_array($arFields['FM']))
	{
		if(CCrmFieldMulti::HasValues($arFields['FM'], CCrmFieldMulti::EMAIL))
		{
			$arFields['HAS_EMAIL'] = 'Y';
		}

		if(CCrmFieldMulti::HasValues($arFields['FM'], CCrmFieldMulti::PHONE))
		{
			$arFields['HAS_PHONE'] = 'Y';
		}

		if(CCrmFieldMulti::HasImolValues($arFields['FM']))
		{
			$arFields['HAS_IMOL'] = 'Y';
		}
	}
	//endregion

	//region Preparation of contacts
	$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']);
	//For backward compatibility only
	$contactID = isset($arFields['CONTACT_ID']) ? max((int)$arFields['CONTACT_ID'], 0) : null;
	if($contactID !== null && $contactIDs === null && $contactBindings === null)
	{
		$contactIDs = array();
		if($contactID > 0)
		{
			$contactIDs[] = $contactID;
		}
	}
	unset($arFields['CONTACT_ID']);

	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
		);
	}
	//endregion

	//region Synchronize CustomerType
	$customerType = isset($arFields['IS_RETURN_CUSTOMER']) && $arFields['IS_RETURN_CUSTOMER'] === 'Y'
		? CustomerType::RETURNING : CustomerType::GENERAL;

	$effectiveCustomerType = CustomerType::GENERAL;

	$companyID = isset($arFields['COMPANY_ID']) ? (int)$arFields['COMPANY_ID'] : 0;
	if($companyID > 0)
	{
		$effectiveCustomerType = CustomerType::RETURNING;
	}
	elseif((is_array($contactIDs) && !empty($contactIDs))
		|| !is_array($contactIDs) && !empty($originalContactIDs)
	)
	{
		$effectiveCustomerType = CustomerType::RETURNING;
	}

	if($customerType !== $effectiveCustomerType)
	{
		$arFields['IS_RETURN_CUSTOMER'] = $effectiveCustomerType === CustomerType::RETURNING ? 'Y' : 'N';
	}
	//endregion

	//region Rise BeforeAdd event
	$beforeEvents = GetModuleEvents('crm', 'OnBeforeCrmLeadAdd');
	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_LEAD_CREATION_CANCELED', array('#NAME#' => $arEvent['TO_NAME']));
				$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
			}
			return false;
		}
	}
	//endregion

	unset($arFields['ID']);

	$this->normalizeEntityFields($arFields);
	$ID = (int) $DB->Add(self::TABLE_NAME, $arFields, [], '', false, 'FILE: '.__FILE__.'
LINE: '.__LINE__); //Append ID to TITLE if required if($ID > 0 && $arFields['TITLE'] === self::GetDefaultTitle()) { $arFields['TITLE'] = self::GetDefaultTitle($ID); $sUpdate = $DB->PrepareUpdate('b_crm_lead', array('TITLE' => $arFields['TITLE'])); if($sUpdate <> '') { $DB->Query("UPDATE b_crm_lead SET {$sUpdate} WHERE ID = {$ID}", false, 'FILE: '.__FILE__.'
LINE: '.__LINE__); }; } if(defined('BX_COMP_MANAGED_CACHE')) { $GLOBALS['CACHE_MANAGER']->CleanDir('b_crm_lead'); } $arFields['ID'] = $ID; $arFields['DATE_CREATE'] = $arFields['DATE_MODIFY'] = ConvertTimeStamp(time() + CTimeZone::GetOffset(), 'FULL'); //region Save Observers if(!empty($observerIDs)) { Crm\Observer\ObserverManager::registerBulk($observerIDs, \CCrmOwnerType::Lead, $ID); } //endregion $securityRegisterOptions = (new \Bitrix\Crm\Security\Controller\RegisterOptions()) ->setEntityAttributes($arEntityAttr) ; Crm\Security\Manager::getEntityController(CCrmOwnerType::Lead) ->register(self::$TYPE_NAME, $ID, $securityRegisterOptions) ; $addressFields = array( 'ADDRESS_1' => isset($arFields['ADDRESS']) ? $arFields['ADDRESS'] : null, 'ADDRESS_2' => isset($arFields['ADDRESS_2']) ? $arFields['ADDRESS_2'] : null, 'CITY' => isset($arFields['ADDRESS_CITY']) ? $arFields['ADDRESS_CITY'] : null, 'POSTAL_CODE' => isset($arFields['ADDRESS_POSTAL_CODE']) ? $arFields['ADDRESS_POSTAL_CODE'] : null, 'REGION' => isset($arFields['ADDRESS_REGION']) ? $arFields['ADDRESS_REGION'] : null, 'PROVINCE' => isset($arFields['ADDRESS_PROVINCE']) ? $arFields['ADDRESS_PROVINCE'] : null, 'COUNTRY' => isset($arFields['ADDRESS_COUNTRY']) ? $arFields['ADDRESS_COUNTRY'] : null, 'COUNTRY_CODE' => isset($arFields['ADDRESS_COUNTRY_CODE']) ? $arFields['ADDRESS_COUNTRY_CODE'] : null, 'LOC_ADDR_ID' => isset($arFields['ADDRESS_LOC_ADDR_ID']) ? (int)$arFields['ADDRESS_LOC_ADDR_ID'] : 0, 'LOC_ADDR' => isset($arFields['ADDRESS_LOC_ADDR']) ? $arFields['ADDRESS_LOC_ADDR'] : null ); if(!\Bitrix\Crm\EntityAddress::isEmpty($addressFields) || $addressFields['LOC_ADDR']) { \Bitrix\Crm\EntityAddress::register( CCrmOwnerType::Lead, $ID, EntityAddressType::Primary, $addressFields ); } CCrmEntityHelper::NormalizeUserFields($arFields, self::$sUFEntityID, $GLOBALS['USER_FIELD_MANAGER'], array('IS_NEW' => true)); $GLOBALS['USER_FIELD_MANAGER']->Update(self::$sUFEntityID, $ID, $arFields); //Statistics & History --> Bitrix\Crm\Statistics\LeadSumStatisticEntry::register($ID, $arFields); Bitrix\Crm\History\LeadStatusHistoryEntry::register($ID, $arFields, array('IS_NEW' => !$isRestoration)); if($arFields['STATUS_ID'] === 'CONVERTED') { Bitrix\Crm\Statistics\LeadConversionStatisticsEntry::register($ID, $arFields, array('IS_NEW' => !$isRestoration)); } //Bitrix\Crm\Statistics\LeadProcessStatisticsEntry::register($ID, $arFields, array('IS_NEW' => true)); //<-- Statistics & History if($isRestoration) { Bitrix\Crm\Timeline\LeadController::getInstance()->onRestore($ID, array('FIELDS' => $arFields)); } else { Bitrix\Crm\Timeline\LeadController::getInstance()->onCreate($ID, array('FIELDS' => $arFields)); } CCrmEntityHelper::registerAdditionalTimelineEvents([ 'entityTypeId' => \CCrmOwnerType::Lead, 'entityId' => $ID, 'fieldsInfo' => static::GetFieldsInfo(), 'previousFields' => [], 'currentFields' => $arFields, 'previousStageSemantics' => Crm\PhaseSemantics::UNDEFINED, 'currentStageSemantics' => $arFields['STATUS_SEMANTIC_ID'] ?? Crm\PhaseSemantics::UNDEFINED, 'options' => $options, 'bindings' => [ 'entityTypeId' => \CCrmOwnerType::Contact, 'previous' => [], 'current' => $contactBindings, ], 'isMarkEventRegistrationEnabled' => false, ]); //region Duplicate communication data if (isset($arFields['FM']) && is_array($arFields['FM'])) { $CCrmFieldMulti = new CCrmFieldMulti(); $CCrmFieldMulti->SetFields('LEAD', $ID, $arFields['FM']); } //endregion $duplicateCriterionRegistrar = DuplicateManager::getCriterionRegistrar(\CCrmOwnerType::Lead); $data = (new Crm\Integrity\CriterionRegistrar\Data()) ->setEntityTypeId(\CCrmOwnerType::Lead) ->setEntityId($ID) ->setCurrentFields($arFields) ; $duplicateCriterionRegistrar->register($data); \Bitrix\Crm\Counter\Monitor::getInstance()->onEntityAdd(CCrmOwnerType::Lead, $arFields); // tracking of entity Tracking\Entity::onAfterAdd(CCrmOwnerType::Lead, $ID, $arFields); //region Save contacts if(!empty($contactBindings)) { LeadContactTable::bindContacts($ID, $contactBindings); if(isset($GLOBALS['USER']) && !empty($contactIDs)) { CUserOptions::SetOption( 'crm', 'crm_contact_search', array('last_selected' => $contactIDs[count($contactIDs) - 1]) ); } } //endregion //region save parent relations Crm\Service\Container::getInstance()->getParentFieldManager()->saveParentRelationsForIdentifier( new Crm\ItemIdentifier(\CCrmOwnerType::Lead, $ID), $arFields ); //endregion if($bUpdateSearch) { CCrmSearch::UpdateSearch(array('ID' => $ID, 'CHECK_PERMISSIONS' => 'N'), 'LEAD', true); } //region Search content index Bitrix\Crm\Search\SearchContentBuilderFactory::create( CCrmOwnerType::Lead )->build($ID, ['checkExist' => true]); //endregion self::getCommentsAdapter()->performAdd($arFields, $options); if(isset($options['REGISTER_SONET_EVENT']) && $options['REGISTER_SONET_EVENT'] === true) { $opportunity = round((isset($arFields['OPPORTUNITY']) ? doubleval($arFields['OPPORTUNITY']) : 0.0), 2); $currencyID = isset($arFields['CURRENCY_ID']) ? $arFields['CURRENCY_ID'] : ''; if($currencyID === '') { $currencyID = CCrmCurrency::GetBaseCurrencyID(); } $assignedByID = intval($arFields['ASSIGNED_BY_ID']); $createdByID = intval($arFields['CREATED_BY_ID']); $liveFeedFields = array( 'USER_ID' => $createdByID, 'ENTITY_TYPE_ID' => CCrmOwnerType::Lead, 'ENTITY_ID' => $ID, //'EVENT_ID' => $eventID, 'TITLE' => GetMessage('CRM_LEAD_EVENT_ADD'), 'MESSAGE' => '', 'PARAMS' => array( 'TITLE' => $arFields['TITLE'], 'NAME' => isset($arFields['NAME']) ? $arFields['NAME'] : '', 'SECOND_NAME' => isset($arFields['SECOND_NAME']) ? $arFields['SECOND_NAME'] : '', 'LAST_NAME' => isset($arFields['LAST_NAME']) ? $arFields['LAST_NAME'] : '', 'HONORIFIC' => isset($arFields['HONORIFIC']) ? $arFields['HONORIFIC'] : '', 'COMPANY_TITLE' => isset($arFields['COMPANY_TITLE']) ? $arFields['COMPANY_TITLE'] : '', 'STATUS_ID' => $arFields['STATUS_ID'], 'OPPORTUNITY' => strval($opportunity), 'CURRENCY_ID' => $currencyID, 'AUTHOR_ID' => intval($arFields['CREATED_BY_ID']), 'RESPONSIBLE_ID' => $assignedByID ) ); if (Crm\Settings\Crm::isLiveFeedRecordsGenerationEnabled()) { CCrmSonetSubscription::RegisterSubscription( CCrmOwnerType::Lead, $ID, CCrmSonetSubscriptionType::Responsibility, $assignedByID ); } $logEventID = CCrmLiveFeed::CreateLogEvent($liveFeedFields, CCrmLiveFeedEvent::Add, ['CURRENT_USER' => $userID]); if ( $logEventID !== false && $assignedByID != $createdByID && CModule::IncludeModule("im") && \Bitrix\Crm\Settings\LeadSettings::isEnabled() ) { $url = CCrmOwnerType::GetEntityShowPath(CCrmOwnerType::Lead, $ID); $serverName = (CMain::IsHTTPS() ? "https" : "http")."://".((defined("SITE_SERVER_NAME") && SITE_SERVER_NAME <> '') ? SITE_SERVER_NAME : COption::GetOptionString("main", "server_name", "")); $arMessageFields = array( "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "TO_USER_ID" => $assignedByID, "FROM_USER_ID" => $createdByID, "NOTIFY_TYPE" => IM_NOTIFY_FROM, "NOTIFY_MODULE" => "crm", "LOG_ID" => $logEventID, //"NOTIFY_EVENT" => "lead_add", "NOTIFY_EVENT" => "changeAssignedBy", "NOTIFY_TAG" => "CRM|LEAD|".$ID, "NOTIFY_MESSAGE" => GetMessage("CRM_LEAD_RESPONSIBLE_IM_NOTIFY", Array("#title#" => "".htmlspecialcharsbx($arFields['TITLE'])."")), "NOTIFY_MESSAGE_OUT" => GetMessage("CRM_LEAD_RESPONSIBLE_IM_NOTIFY", Array("#title#" => htmlspecialcharsbx($arFields['TITLE'])))." (".$serverName.$url.")" ); CIMNotify::Add($arMessageFields); } } //region Rise AfterAdd event $afterEvents = GetModuleEvents('crm', 'OnAfterCrmLeadAdd'); while ($arEvent = $afterEvents->Fetch()) { ExecuteModuleEventEx($arEvent, array(&$arFields)); } //endregion if(isset($arFields['ORIGIN_ID']) && $arFields['ORIGIN_ID'] !== '') { $afterEvents = GetModuleEvents('crm', 'OnAfterExternalCrmLeadAdd'); while ($arEvent = $afterEvents->Fetch()) { ExecuteModuleEventEx($arEvent, array(&$arFields)); } } if ($ID>0) { if ( $viewMode === ViewMode::MODE_ACTIVITIES && $viewModeActivitiesStatusId ) { $deadline = (new Crm\Kanban\EntityActivityDeadline())->getDeadline($viewModeActivitiesStatusId); if ($deadline) { \Bitrix\Crm\Activity\Entity\ToDo::createWithDefaultDescription( \CCrmOwnerType::Lead, $ID, $deadline ); } } $item = Crm\Kanban\Entity::getInstance(self::$TYPE_NAME) ->createPullItem($arFields); PullManager::getInstance()->sendItemAddedEvent( $item, [ 'TYPE' => self::$TYPE_NAME, 'SKIP_CURRENT_USER' => ($userID !== 0), ] ); } return $ID; }