public function Update($ID, &$arFields, $bCompare = true, $bUpdateSearch = true, $options = array())
{
$ID = (int) $ID;
if (!is_array($arFields))
{
$arFields = (array)$arFields;
}
if(!is_array($options))
{
$options = array();
}
$this->lastErrors = null;
if($this->isUseOperation())
{
return $this->getCompatibilityAdapter()->performUpdate($ID, $arFields, $options);
}
global $DB;
$this->LAST_ERROR = '';
$arFilterTmp = array('ID' => $ID);
if (!$this->bCheckPermission)
$arFilterTmp['CHECK_PERMISSIONS'] = 'N';
$obRes = self::GetList(array(), $arFilterTmp);
if (!($arRow = $obRes->Fetch()))
return false;
$iUserId = CCrmSecurityHelper::GetCurrentUserID();
if (isset($arFields['DATE_CREATE']))
unset($arFields['DATE_CREATE']);
if (isset($arFields['DATE_MODIFY']))
unset($arFields['DATE_MODIFY']);
$arFields['~DATE_MODIFY'] = $DB->CurrentTimeFunction();
$arFields['MODIFY_BY_ID'] = $iUserId;
if (isset($arFields['ASSIGNED_BY_ID']) && $arFields['ASSIGNED_BY_ID'] <= 0)
unset($arFields['ASSIGNED_BY_ID']);
// number
if (!isset($arFields['QUOTE_NUMBER']) || empty($arFields['QUOTE_NUMBER']))
{
$arFields['QUOTE_NUMBER'] = isset($arRow['QUOTE_NUMBER']) ? $arRow['QUOTE_NUMBER'] : '';
if (empty($arFields['QUOTE_NUMBER']))
$arFields['QUOTE_NUMBER'] = strval($ID);
}
// person type
if (!isset($arFields['PERSON_TYPE_ID']) || intval($arFields['PERSON_TYPE_ID']) <= 0)
{
$companyId = isset($arFields['COMPANY_ID']) ? intval($arFields['COMPANY_ID']) : (isset($arRow['COMPANY_ID']) ? intval($arRow['COMPANY_ID']) : 0);
$arFields['PERSON_TYPE_ID'] = intval($arRow['PERSON_TYPE_ID']);
$arPersonTypes = CCrmPaySystem::getPersonTypeIDs();
if (isset($arPersonTypes['CONTACT']) && isset($arPersonTypes['COMPANY']))
{
if ($companyId <= 0)
$arFields['PERSON_TYPE_ID'] = intval($arPersonTypes['CONTACT']);
else
$arFields['PERSON_TYPE_ID'] = intval($arPersonTypes['COMPANY']);
}
unset($companyId, $arPersonTypes);
}
// storage type id
$storageTypeID = isset($arFields['STORAGE_TYPE_ID'])
? intval($arFields['STORAGE_TYPE_ID']) : CCrmQuoteStorageType::Undefined;
if($storageTypeID === CCrmQuoteStorageType::Undefined
|| !CCrmQuoteStorageType::IsDefined($storageTypeID))
{
$storageTypeID = isset($arRow['STORAGE_TYPE_ID'])
? $arRow['STORAGE_TYPE_ID'] : CCrmQuoteStorageType::Undefined;
if($storageTypeID === CCrmQuoteStorageType::Undefined
|| !CCrmQuoteStorageType::IsDefined($storageTypeID))
{
$storageTypeID = CCrmQuote::GetDefaultStorageTypeID();
}
}
$arFields['STORAGE_TYPE_ID'] = $storageTypeID;
// storage elements
$storageElementIDs = (isset($arFields['STORAGE_ELEMENT_IDS']) && is_array($arFields['STORAGE_ELEMENT_IDS']))
? $arFields['STORAGE_ELEMENT_IDS'] : null;
$arFields['STORAGE_ELEMENT_IDS'] = null;
if ($storageElementIDs !== null)
{
$storageElementIDs = self::NormalizeStorageElementIDs($storageElementIDs);
$arFields['STORAGE_ELEMENT_IDS'] = serialize($storageElementIDs);
}
$assignedByID = (int)(isset($arFields['ASSIGNED_BY_ID']) ? $arFields['ASSIGNED_BY_ID'] : $arRow['ASSIGNED_BY_ID']);
$bResult = false;
if (!$this->CheckFields($arFields, $ID, $options))
$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
else
{
if($this->bCheckPermission && !CCrmAuthorizationHelper::CheckUpdatePermission(self::$TYPE_NAME, $ID, $this->cPerms))
{
$this->LAST_ERROR = GetMessage('CRM_PERMISSION_DENIED');
$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
return false;
}
$arAttr = array();
$arAttr['STATUS_ID'] = !empty($arFields['STATUS_ID']) ? $arFields['STATUS_ID'] : $arRow['STATUS_ID'];
$arAttr['OPENED'] = !empty($arFields['OPENED']) ? $arFields['OPENED'] : $arRow['OPENED'];
$arEntityAttr = self::BuildEntityAttr($assignedByID, $arAttr);
if($this->bCheckPermission)
{
$sEntityPerm = $this->cPerms->GetPermType(self::$TYPE_NAME, 'WRITE', $arEntityAttr);
//HACK: Ensure that entity accessible for user restricted by BX_CRM_PERM_OPEN
$this->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 !== $iUserId)
{
$arFields['OPENED'] = 'Y';
}
}
if (isset($arFields['ASSIGNED_BY_ID']) && $arRow['ASSIGNED_BY_ID'] != $arFields['ASSIGNED_BY_ID'])
CCrmEvent::SetAssignedByElement($arFields['ASSIGNED_BY_ID'], 'QUOTE', $ID);
//region Preparation of contacts
$originalContactBindings = QuoteContactTable::getQuoteBindings($ID);
$originalContactIDs = \Bitrix\Crm\Binding\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 = \Bitrix\Crm\Binding\EntityBinding::prepareEntityBindings(
\CCrmOwnerType::Contact,
$contactIDs
);
\Bitrix\Crm\Binding\EntityBinding::markFirstAsPrimary($contactBindings);
}
/* Please uncomment if required
elseif(is_array($contactBindings) && !is_array($contactIDs))
{
$contactIDs = \Bitrix\Crm\Binding\EntityBinding::prepareEntityIDs(
CCrmOwnerType::Contact,
$contactBindings
);
}
*/
if(is_array($contactBindings))
{
$removedContactBindings = array();
$addedContactBindings = array();
\Bitrix\Crm\Binding\EntityBinding::prepareBindingChanges(
CCrmOwnerType::Contact,
QuoteContactTable::getQuoteBindings($ID),
$contactBindings,
$addedContactBindings,
$removedContactBindings
);
$addedContactIDs = \Bitrix\Crm\Binding\EntityBinding::prepareEntityIDs(
CCrmOwnerType::Contact,
$addedContactBindings
);
$removedContactIDs = \Bitrix\Crm\Binding\EntityBinding::prepareEntityIDs(
CCrmOwnerType::Contact,
$removedContactBindings
);
}
//endregion
if ($bCompare)
{
$compareOptions = array();
if(!empty($addedContactIDs) || !empty($removedContactIDs))
{
$compareOptions['CONTACTS'] = array('ADDED' => $addedContactIDs, 'REMOVED' => $removedContactIDs);
}
$arEvents = self::CompareFields($arRow, $arFields, $this->bCheckPermission, $compareOptions);
foreach($arEvents as $arEvent)
{
$arEvent['ENTITY_TYPE'] = 'QUOTE';
$arEvent['ENTITY_ID'] = $ID;
$arEvent['EVENT_TYPE'] = 1;
if (!isset($arEvent['USER_ID']))
$arEvent['USER_ID'] = $iUserId;
$isRelationEvent = in_array(
$arEvent['ENTITY_FIELD'],
['DEAL_ID', 'COMPANY_ID', 'CONTACT_ID', 'MYCOMPANY_ID', 'LEAD_ID'],
true,
);
if (!$isRelationEvent)
{
$CCrmEvent = new CCrmEvent();
$CCrmEvent->Add($arEvent, $this->bCheckPermission);
}
}
}
$arFields = array_merge($arFields, \CCrmAccountingHelper::calculateAccountingData($arFields, $arRow, true));
if(isset($arFields['STATUS_ID']))
{
$arFields['CLOSED'] = self::GetStatusSemantics($arFields['STATUS_ID']) === 'process' ? 'N' : 'Y';
}
if (isset($arFields['BEGINDATE']) && !isset($arFields['BEGINDATE'][0]))
{
unset($arFields['BEGINDATE']);
}
if(isset($arFields['CLOSED'])
&& $arFields['CLOSED'] === 'Y'
&& (!isset($arFields['CLOSEDATE'])
|| $arFields['CLOSEDATE'] === ''))
{
$arFields['CLOSEDATE'] = ConvertTimeStamp(time() + CTimeZone::GetOffset(), 'FULL', SITE_ID);
}
if(!isset($arFields['ID']))
{
$arFields['ID'] = $ID;
}
self::getLastActivityAdapter()->performUpdate((int)$ID, $arFields, $options);
self::getCommentsAdapter()
->setPreviousFields((int)$ID, $arRow)
->normalizeFields((int)$ID, $arFields)
;
foreach (GetModuleEvents('crm', 'OnBeforeCrmQuoteUpdate', true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arFields)) === false)
{
if(isset($arFields['RESULT_MESSAGE']))
{
$this->LAST_ERROR = $arFields['RESULT_MESSAGE'];
}
else
{
$this->LAST_ERROR = GetMessage('CRM_QUOTE_UPDATE_CANCELED_MSGVER_1', ['#NAME#' => $arEvent['TO_NAME']]);
$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
}
return false;
}
}
unset($arFields['ID']);
$this->normalizeEntityFields($arFields);
$sUpdate = $DB->PrepareUpdate(self::TABLE_NAME, $arFields);
if ($sUpdate <> '')
{
$clobFieldNames = array('COMMENTS', 'CONTENT', 'STORAGE_ELEMENT_IDS');
$arBinds = array();
foreach ($clobFieldNames as $fieldName)
{
if (array_key_exists($fieldName, $arFields))
$arBinds[$fieldName] = $arFields[$fieldName];
}
unset($fieldName);
$sql = "UPDATE b_crm_quote SET {$sUpdate} WHERE ID = {$ID}";
if(!empty($arBinds))
{
$DB->QueryBind($sql, $arBinds, false);
}
else
{
$DB->Query($sql, false, 'File: '.__FILE__.'
Line: '.__LINE__);
}
$bResult = true;
}
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::Quote."_".$ID);
}
}
$securityRegisterOptions = (new \Bitrix\Crm\Security\Controller\RegisterOptions())
->setEntityAttributes($arEntityAttr)
;
Crm\Security\Manager::getEntityController(CCrmOwnerType::Quote)
->register(self::$TYPE_NAME, $ID, $securityRegisterOptions)
;
//region Save contacts
if(!empty($removedContactBindings))
{
QuoteContactTable::unbindContacts($ID, $removedContactBindings);
}
if(!empty($addedContactBindings))
{
QuoteContactTable::bindContacts($ID, $addedContactBindings);
}
//endregion
CCrmEntityHelper::NormalizeUserFields($arFields, self::$sUFEntityID, $GLOBALS['USER_FIELD_MANAGER'], array('IS_NEW' => false));
$GLOBALS['USER_FIELD_MANAGER']->Update(self::$sUFEntityID, $ID, $arFields);
if(is_array($storageElementIDs))
{
CCrmQuote::DoSaveElementIDs($ID, $storageTypeID, $storageElementIDs);
}
unset($storageTypeID, $storageElementIDs);
// update utm fields
UtmTable::updateEntityUtmFromFields(CCrmOwnerType::Quote, $ID, $arFields);
if($bUpdateSearch)
{
$arFilterTmp = Array('ID' => $ID);
if (!$this->bCheckPermission)
$arFilterTmp["CHECK_PERMISSIONS"] = "N";
CCrmSearch::UpdateSearch($arFilterTmp, 'QUOTE', true);
}
//region Search content index
Bitrix\Crm\Search\SearchContentBuilderFactory::create(CCrmOwnerType::Quote)->build($ID);
//endregion
$arFields['ID'] = $ID;
if (isset($arFields['FM']) && is_array($arFields['FM']))
{
$CCrmFieldMulti = new CCrmFieldMulti();
$CCrmFieldMulti->SetFields('QUOTE', $ID, $arFields['FM']);
}
// Responsible user sync
//CCrmActivity::Synchronize(CCrmOwnerType::Quote, $ID);
self::getCommentsAdapter()
->setPreviousFields((int)$ID, $arRow)
->performUpdate((int)$ID, $arFields, $options)
;
if($bResult)
{
foreach (GetModuleEvents('crm', 'OnAfterCrmQuoteUpdate', true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arFields));
}
}
return $bResult;
}