static function Add($params)
{
$callId = (string)$params["CALL_ID"];
if($callId == '')
{
CHTTP::SetStatus('400 Bad Request');
return false;
}
$lockAcquired = static::getLock($callId);
if(!$lockAcquired)
{
CHTTP::SetStatus('409 Conflict');
return false;
}
$statisticRecord = VIStatisticTable::getByCallId($params['CALL_ID']);
if($statisticRecord)
{
self::WriteToLog('Duplicating statistic record, skipping');
return false;
}
$call = VICall::load($params['CALL_ID']);
if(!$call)
{
$call = static::recreateCall($params);
}
$config = $call->getConfig();
$arFields = array(
"ACCOUNT_ID" => $params["ACCOUNT_ID"],
"APPLICATION_ID" => $params["APPLICATION_ID"],
"APPLICATION_NAME" => isset($params["APPLICATION_NAME"])?$params["APPLICATION_NAME"]: '-',
"INCOMING" => $params["INCOMING"],
"CALL_START_DATE" => $call->getDateCreate(),
"CALL_DURATION" => isset($params["CALL_DURATION"])? $params["CALL_DURATION"]: $params["DURATION"],
"CALL_RECORD_URL" => $params["URL"],
"CALL_STATUS" => $params["CALL_STATUS"],
"CALL_FAILED_CODE" => $params["CALL_FAILED_CODE"],
"CALL_FAILED_REASON" => $params["CALL_FAILED_REASON"],
"COST" => $params["COST_FINAL"],
"COST_CURRENCY" => $params["COST_CURRENCY"],
"CALL_VOTE" => intval($params["CALL_VOTE"]),
"CALL_ID" => $params["CALL_ID"],
"CALL_CATEGORY" => $params["CALL_CATEGORY"],
"SESSION_ID" => $call->getSessionId(),
"TRANSCRIPT_PENDING" => $params['TRANSCRIPT_PENDING'] === 'Y' ? 'Y' : 'N',
);
if ($params["PHONE_NUMBER"] <> '')
$arFields["PHONE_NUMBER"] = $params["PHONE_NUMBER"];
if ($params["CALL_DIRECTION"] <> '')
$arFields["CALL_DIRECTION"] = $params["CALL_DIRECTION"];
if ($call->getExternalLineId() && $externalLine = VIModelExternalLineTable::getRowById($call->getExternalLineId()))
{
$arFields["PORTAL_NUMBER"] = $externalLine["NORMALIZED_NUMBER"];
}
else if ($params["PORTAL_NUMBER"] <> '')
{
$arFields["PORTAL_NUMBER"] = $params["PORTAL_NUMBER"];
}
else if ($params["ACCOUNT_SEARCH_ID"] <> '')
{
$arFields["PORTAL_NUMBER"] = $params["ACCOUNT_SEARCH_ID"];
}
if($arFields['CALL_VOTE'] < 1 || $arFields['CALL_VOTE'] > 5)
$arFields['CALL_VOTE'] = null;
if ($params["CALL_LOG"] <> '')
$arFields["CALL_LOG"] = $params["CALL_LOG"];
if ($arFields["INCOMING"] == CVoxImplantMain::CALL_INFO)
{
// infocalls have no responsible
$arFields["PORTAL_USER_ID"] = null;
}
else if ($arFields["CALL_FAILED_CODE"] == 304 && (int)$params["PORTAL_USER_ID"] > 0)
{
$arFields["PORTAL_USER_ID"] = (int)$params["PORTAL_USER_ID"];
}
else if (
$arFields["CALL_FAILED_CODE"] == 304
&& (in_array($call->getIncoming(), [CVoxImplantMain::CALL_INCOMING, CVoxImplantMain::CALL_INCOMING_REDIRECT, CVoxImplantMain::CALL_CALLBACK]))
&& $call->getPrimaryEntityType() != ''
&& $call->getPrimaryEntityId() > 0
&& ($crmResponsibleId = CVoxImplantCrmHelper::getResponsible($call->getPrimaryEntityType(), $call->getPrimaryEntityId()))
)
{
// missed call should be assigned to a responsible user, if a client is found in CRM
$arFields["PORTAL_USER_ID"] = $crmResponsibleId;
}
else if($call->getUserId() > 0)
{
$arFields["PORTAL_USER_ID"] = $call->getUserId();
}
else
{
$arFields["PORTAL_USER_ID"] = intval(self::detectResponsible($call));
}
$registerInCrmByBlacklist = (
$arFields["INCOMING"] != CVoxImplantMain::CALL_INCOMING
|| $arFields["CALL_FAILED_CODE"] != 423
|| BitrixMainConfigOption::get("voximplant", "blacklist_register_in_crm", "N") == "Y"
);
if(CVoxImplantCrmHelper::shouldCreateLead($call) && $registerInCrmByBlacklist)
{
// Create lead if the call was finished too early and a lead was not created (but should have been created)
if(!$call->getUserId() && $arFields["PORTAL_USER_ID"])
{
$call->updateUserId($arFields["PORTAL_USER_ID"]);
}
if($call->getUserId())
{
CVoxImplantCrmHelper::registerCallInCrm($call);
if(CVoxImplantConfig::GetLeadWorkflowExecution() == CVoxImplantConfig::WORKFLOW_START_IMMEDIATE)
{
CVoxImplantCrmHelper::StartCallTrigger($call);
}
}
}
if($call->getPrimaryEntityType() != '' && $call->getPrimaryEntityId() > 0)
{
$arFields['CRM_ENTITY_TYPE'] = $call->getPrimaryEntityType();
$arFields['CRM_ENTITY_ID'] = $call->getPrimaryEntityId();
}
if(CVoxImplantConfig::GetLeadWorkflowExecution() == CVoxImplantConfig::WORKFLOW_START_DEFERRED)
{
CVoxImplantCrmHelper::StartCallTrigger($call);
}
if($arFields["CALL_FAILED_CODE"] == 304 && ($call->getIncoming() == CVoxImplantMain::CALL_INCOMING || $call->getIncoming() == CVoxImplantMain::CALL_INCOMING_REDIRECT))
{
CVoxImplantCrmHelper::StartMissedCallTrigger($call);
}
$arFields['COMMENT'] = $call->getComment() ?: null;
$insertResult = BitrixVoxImplantStatisticTable::add($arFields);
if (!$insertResult->isSuccess())
{
static::releaseLock($callId);
return false;
}
if($arFields['COST'] > 0)
{
static::setLastPaidCallTimestamp(time());
}
$arFields['ID'] = $insertResult->getId();
//recording a missed call
if (
$arFields["CALL_FAILED_CODE"] == 304
&& (
$call->getIncoming() == CVoxImplantMain::CALL_INCOMING
|| $call->getIncoming() == CVoxImplantMain::CALL_INCOMING_REDIRECT
)
)
{
$missedCall = [
'ID' => $arFields['ID'],
'CALL_START_DATE' => $arFields['CALL_START_DATE'],
'PHONE_NUMBER' => $arFields['PHONE_NUMBER'],
'PORTAL_USER_ID' => $arFields['PORTAL_USER_ID']
];
$insertMissedCallResult = VIModelStatisticMissedTable::add($missedCall);
if (!$insertMissedCallResult->isSuccess())
{
static::releaseLock($callId);
return false;
}
} //if our call answering any missed calls
elseif (
$arFields["CALL_FAILED_CODE"] == 200
&& $call->getIncoming() == CVoxImplantMain::CALL_OUTGOING
)
{
$missedCalls = VIModelStatisticMissedTable::getList([
'select' => ['ID'],
'filter' => [
'=PHONE_NUMBER' => $arFields['PHONE_NUMBER'],
'=CALLBACK_ID' => null
],
])->fetchAll();
if ($missedCalls)
{
foreach ($missedCalls as $missedCall)
{
VIModelStatisticMissedTable::update($missedCall['ID'], [
'CALLBACK_ID' => $arFields['ID'],
'CALLBACK_CALL_START_DATE' => $arFields['CALL_START_DATE']
]
);
}
}
}
if (!$call->isInternalCall() && $call->isCrmEnabled() && $registerInCrmByBlacklist)
{
if($call->getCrmActivityId() > 0 && CVoxImplantCrmHelper::shouldAttachCallToActivity($arFields, $call->getCrmActivityId()))
{
CVoxImplantCrmHelper::attachCallToActivity($arFields, $call->getCrmActivityId());
$arFields['CRM_ACTIVITY_ID'] = $call->getCrmActivityId();
}
else
{
$arFields['CRM_ACTIVITY_ID'] = CVoxImplantCrmHelper::AddCall($arFields, array(
'WORKTIME_SKIPPED' => $call->isWorktimeSkipped() ? 'Y' : 'N',
'CRM_BINDINGS' => $call->getCrmBindings()
));
if($call->getCrmActivityId() && CVoxImplantCrmHelper::shouldCompleteActivity($arFields))
{
CVoxImplantCrmHelper::completeActivity($call->getCrmActivityId());
}
}
VIStatisticTable::update($arFields['ID'], array(
'CRM_ACTIVITY_ID' => $arFields['CRM_ACTIVITY_ID']
));
if($call->getPrimaryEntityType() != '' && $call->getPrimaryEntityId() > 0)
{
$viMain = new CVoxImplantMain($arFields["PORTAL_USER_ID"]);
$dialogData = $viMain->GetDialogInfo($arFields['PHONE_NUMBER'], '', false);
if(!$dialogData['UNIFIED'])
{
CVoxImplantMain::UpdateChatInfo(
$dialogData['DIALOG_ID'],
array(
'CRM' => $call->isCrmEnabled() ? 'Y' : 'N',
'CRM_ENTITY_TYPE' => $call->getPrimaryEntityType(),
'CRM_ENTITY_ID' => $call->getPrimaryEntityId(),
'PHONE_NUMBER' => $arFields['PHONE_NUMBER']
)
);
}
}
}
$chatMessage = self::GetMessageForChat($arFields, $params['URL'] != '');
if($chatMessage != '')
{
$attach = null;
if(CVoxImplantConfig::GetChatAction() == CVoxImplantConfig::INTERFACE_CHAT_APPEND)
{
$attach = static::GetAttachForChat($arFields, $params['URL'] != '');
}
if($attach)
self::SendMessageToChat($arFields["PORTAL_USER_ID"], $arFields["PHONE_NUMBER"], $arFields["INCOMING"], null, $attach);
else
self::SendMessageToChat($arFields["PORTAL_USER_ID"], $arFields["PHONE_NUMBER"], $arFields["INCOMING"], $chatMessage);
}
if ($params['URL'] != '')
{
$attachToCrm = $call->isCrmEnabled();
$recordUrl = BitrixMainWebUri::urnEncode((string)$params['URL']);
self::DownloadAgent($insertResult->getId(), $recordUrl, $attachToCrm);
}
if ($params["ACCOUNT_PAYED"] <> '' && in_array($params["ACCOUNT_PAYED"], Array('Y', 'N')))
{
CVoxImplantAccount::SetPayedFlag($params["ACCOUNT_PAYED"]);
}
if(CVoxImplantConfig::GetLeadWorkflowExecution() == CVoxImplantConfig::WORKFLOW_START_DEFERRED)
{
$createdCrmEntities = $call->getCreatedCrmEntities();
foreach ($createdCrmEntities as $entity)
{
if($entity['ENTITY_TYPE'] === 'LEAD')
{
CVoxImplantCrmHelper::StartLeadWorkflow($entity['ENTITY_ID']);
}
}
}
if($call->getCrmCallList() > 0)
{
try
{
CVoxImplantCrmHelper::attachCallToCallList($call->getCrmCallList(), $arFields);
}
catch (Exception $exception)
{
Application::getInstance()->getExceptionHandler()->writeToLog($exception);
}
}
/* repeat missed callback, if neeeded */
if($call->getIncoming() == CVoxImplantMain::CALL_CALLBACK && $params["CALL_FAILED_CODE"] == '304')
{
if(self::shouldRepeatCallback($call->toArray(), $config))
{
self::repeatCallback($call->toArray(), $config);
}
}
static::sendCallEndEvent($arFields);
if($arFields['INCOMING'] == CVoxImplantMain::CALL_INFO)
{
$callEvent = new Event(
'voximplant',
'OnInfoCallResult',
array(
$arFields['CALL_ID'],
array(
'RESULT' => ($arFields['CALL_FAILED_CODE'] == '200'),
'CODE' => $arFields['CALL_FAILED_CODE'],
'REASON' => $arFields['CALL_FAILED_REASON']
)
)
);
EventManager::getInstance()->send($callEvent);
}
VICall::delete($callId);
static::releaseLock($callId);
return true;
}