63 private $groupQueueService;
68 private $messageConfiguration;
95 $this->result = $result;
130 'MESSAGE_TYPE' =>
'MAILING_CHAIN.MESSAGE_CODE',
131 'WAITING_RECIPIENT' =>
'MAILING_CHAIN.WAITING_RECIPIENT',
132 'MAILING_STATUS' =>
'MAILING_CHAIN.STATUS',
133 'MESSAGE_ID' =>
'MAILING_CHAIN.MESSAGE_ID'
144 if (
$postingData[
'MAILING_STATUS'] === Model\LetterTable::STATUS_END)
146 Model\LetterTable::update(
$postingData[
'MAILING_CHAIN_ID'], [
147 'WAITING_RECIPIENT' =>
'N'
165 $this->groupCount = array();
169 $this->messageConfiguration = Message\Adapter::getInstance(
$postingData[
'MESSAGE_TYPE'])
182 $this->checkDuplicates =
false;
186 $messageFields = Model\MessageFieldTable::getList(
187 [
'filter' => [
'=MESSAGE_ID' =>
$postingData[
'MESSAGE_ID']]]
190 $personalizeFields = [];
191 foreach ($messageFields as $messageField)
194 $messageField[
'CODE'],
196 'MESSAGE_PERSONALIZE',
197 'SUBJECT_PERSONALIZE',
205 $personalizeFields[$messageField[
'CODE']] =
206 json_decode($messageField[
'VALUE'],
true)[1];
212 $message = Message\Adapter::create($this->postingData[
'MESSAGE_TYPE']);
213 foreach ($message->getSupportedRecipientTypes() as
$typeId)
229 Model\PostingTable::update(
232 'COUNT_SEND_ALL' => PostingRecipientTable::getCount(array(
'POSTING_ID' =>
$postingId))
237 foreach ($groups as $group)
239 if ($group[
'GROUP_ID'] && !isset($usedGroups[$group[
'GROUP_ID']]))
243 $this->groupQueueService->releaseGroup(
248 $usedGroups[$group[
'GROUP_ID']] = $group[
'GROUP_ID'];
252 $this->postingData[
'WAITING_RECIPIENT'] =
'N';
253 Model\LetterTable::update($this->postingData[
'MAILING_CHAIN_ID'], [
254 'WAITING_RECIPIENT' => $this->postingData[
'WAITING_RECIPIENT']
264 $groups = array_merge($groups, $this->
getLetterConnectors($this->postingData[
'MAILING_CHAIN_ID']));
266 Model\LetterTable::update($this->postingData[
'MAILING_CHAIN_ID'], [
267 'WAITING_RECIPIENT' =>
'N'
270 foreach ($groups as $group)
272 if ($group[
'GROUP_ID'] && !GroupTable::getById($group[
'GROUP_ID'])->fetch())
277 if ($group[
'GROUP_ID'])
279 $this->groupQueueService
300 $group[
'INCLUDE'] = (bool)$group[
'INCLUDE'];
309 if ($a[
'INCLUDE'] == $b[
'INCLUDE'])
314 return ($a[
'INCLUDE'] > $b[
'INCLUDE']) ? -1 : 1;
324 foreach($groups as $group)
326 if (is_array($group[
'ENDPOINT']) && !(isset($group[
'CONNECTOR']) && $group[
'CONNECTOR'] instanceof Connector\
Base))
328 $group[
'CONNECTOR'] = Connector\Manager::getConnector($group[
'ENDPOINT']);
331 if(empty($group[
'CONNECTOR']))
338 if (is_array($group[
'ENDPOINT'][
'FIELDS']))
341 $connector->setFieldValues($group[
'ENDPOINT'][
'FIELDS']);
347 $usedPersonalizeFields
357 Model\LetterTable::update($this->postingData[
'MAILING_CHAIN_ID'], [
358 'WAITING_RECIPIENT' => $this->postingData[
'MAILING_STATUS'] !== Model\LetterTable::STATUS_END ?
'Y' :
'N'
367 Model\PostingTable::update(
370 'COUNT_SEND_ALL' => 0,
371 'COUNT_SEND_NONE' => 0,
372 'COUNT_SEND_ERROR' => 0,
373 'COUNT_SEND_SUCCESS' => 0,
380 return Recipient\Type::getCode($this->typeId);
388 'ENDPOINT' => array(
'FIELDS' => array(
'MAILING_ID' => $campaignId)),
392 'CONNECTOR' =>
new Integration\
Sender\Connectors\Subscriber
396 'ENDPOINT' => array(
'FIELDS' => array(
'MAILING_ID' => $campaignId)),
400 'CONNECTOR' =>
new Integration\
Sender\Connectors\UnSubscribers
413 return (!isset($data[$typeCode]) || !$data[$typeCode])
415 isset($data[
'FIELDS'])
417 (int)$data[
'FIELDS'][
'CRM_ENTITY_TYPE_ID'] === \CCrmOwnerType::Lead
418 || ($data[
'FIELDS'][
'CRM_ENTITY_TYPE'] === \CCrmOwnerType::LeadName)
420 && !empty($data[
'FIELDS'][
'CRM_ENTITY_ID'])
421 && ((int)$this->typeId === \
Bitrix\
Sender\Recipient\Type::CRM_LEAD_ID)
428 $groupConnectorDb = MailingGroupTable::getList(array(
431 'CONNECTOR_ENDPOINT' =>
'GROUP.GROUP_CONNECTOR.ENDPOINT',
435 '=MAILING_ID' => $campaignId,
437 'order' => array(
'INCLUDE' =>
'DESC',
'GROUP_ID' =>
'ASC')
439 while($group = $groupConnectorDb->fetch())
442 'INCLUDE' => $group[
'INCLUDE'],
443 'ENDPOINT' => $group[
'CONNECTOR_ENDPOINT'],
444 'GROUP_ID' => $group[
'GROUP_ID'],
455 $groupConnectors = Model\LetterSegmentTable::getList(array(
458 'STATUS' =>
'SEGMENT.STATUS',
459 'FILTER_ID' =>
'SEGMENT.GROUP_CONNECTOR.FILTER_ID',
460 'CONNECTOR_ENDPOINT' =>
'SEGMENT.GROUP_CONNECTOR.ENDPOINT',
464 '=LETTER_ID' => $letterId,
466 'order' => array(
'INCLUDE' =>
'DESC',
'LETTER_ID' =>
'ASC')
468 while($group = $groupConnectors->fetch())
471 'INCLUDE' => $group[
'INCLUDE'],
472 'ENDPOINT' => $group[
'CONNECTOR_ENDPOINT'],
473 'GROUP_ID' => $group[
'SEGMENT_ID'],
474 'FILTER_ID' => $group[
'FILTER_ID'],
475 'STATUS' => $group[
'STATUS'],
483 private function isExcluded(
bool $include, $row): bool
487 $row[
'BLACKLISTED'] ===
'Y' ||
488 $row[
'IS_UNSUB'] ===
'Y' ||
489 $row[
'IS_MAILING_UNSUB'] ===
'Y' ||
491 $this->messageConfiguration->get(
'APPROVE_CONFIRMATION',
'N') ===
'Y' &&
493 $row[
'CONSENT_STATUS'],
494 $row[
'CONSENT_REQUEST'],
495 $this->postingData[
'MESSAGE_TYPE']
503 if (count($dataList) === 0)
508 $codes = array_keys($dataList);
513 $contactCodeFilter = [];
516 $primariesString = SqlBatch::getInString($codes);
518 $recipientDb = $connection->query(
527 s.IS_UNSUB as IS_MAILING_UNSUB " .
528 "from $tableName c " .
529 "left join $subsTableName s on " .
530 "c.ID = s.CONTACT_ID " .
531 "and s.MAILING_ID=" . (
int) $this->postingData[
'MAILING_ID'] .
" " .
532 "where c.TYPE_ID = " . (
int) $this->typeId .
" and c.CODE in ($primariesString)"
534 while ($row = $recipientDb->fetch())
536 $existed[] = $row[
'CODE'];
537 $dataList[$row[
'CODE']][
'CONTACT_ID'] = $row[
'ID'];
538 $dataList[$row[
'CODE']][
'EXCLUDED'] = $this->isExcluded($include, $row);
540 $name = $dataList[$row[
'CODE']][
'NAME'] ??
null;
541 if ($name && $name !== $row[
'NAME'])
543 $contactCodeFilter[] = $row[
'CODE'];
551 if (count($existed) === count($codes))
557 $list = array_diff($codes, $existed);
560 $updateFieldsOnDuplicate = [
'DATE_UPDATE'];
561 foreach ($list as $code)
566 'DATE_INSERT' => $insertDate,
567 'DATE_UPDATE' => $insertDate,
571 if (isset($dataList[$key]) && $dataList[$key])
573 $batchItem[$key] = $dataList[$key];
574 if (!in_array($key, $updateFieldsOnDuplicate))
576 $updateFieldsOnDuplicate[] = $key;
580 $batch[] = $batchItem;
587 $recipientDb = $connection->query(
590 "where TYPE_ID = " . (
int) $this->typeId .
" and CODE in ($primariesString)"
592 while ($row = $recipientDb->fetch())
594 $dataList[$row[
'CODE']][
'CONTACT_ID'] = $row[
'ID'];
598 protected function checkUsedFields($entityType, $ids, $usedPersonalizeFields, &$dataList)
601 foreach ($usedPersonalizeFields as $personalizeField)
603 foreach ($personalizeField as $usedField)
605 $usedFieldExploded = explode(
'.', $usedField);
607 $entityType == $usedFieldExploded[0] &&
610 $usedFieldExploded[1]
613 unset($usedFieldExploded[0]);
614 $usedFields[$usedField] = implode(
'.', $usedFieldExploded);
618 $fields = Integration\Crm\Connectors\Helper::getData(
619 $entityType, $ids, $usedFields
622 foreach ($fields as &$entity)
624 foreach ($entity as $key => $field)
626 $entity[$entityType.
'.'.$key] = $field;
627 unset($entity[$key]);
631 foreach($dataList as &$data)
634 isset($fields[(
int)$data[
'FIELDS'][
'CRM_ENTITY_ID']])
635 && $data[
'FIELDS'][
'CRM_ENTITY_TYPE'] === $entityType
638 $data[
'FIELDS'] = array_merge(
640 $fields[$data[
'FIELDS'][
'CRM_ENTITY_ID']]
655 if ($isIncrementally)
657 $segmentBuilder =
new SegmentDataBuilder($group[
'GROUP_ID'], $group[
'FILTER_ID'], $group[
'ENDPOINT']);
659 if (!$segmentBuilder->isBuildingCompleted())
665 $result = $isIncrementally
666 ? $segmentBuilder->getPreparedData()
674 while ($data = $result->fetch())
681 if (!isset($data[$typeCode]) && ((
int)$this->typeId === Recipient\Type::CRM_LEAD_ID))
683 $data[$typeCode] = $data[
'FIELDS'][
'CRM_ENTITY_ID'];
686 $primary = Recipient\Normalizer::normalize($data[$typeCode], $this->typeId);
691 $dataList[$primary] = $data;
702 if (count($dataList) === 0)
708 if ($group[
'INCLUDE'])
711 if ($this->checkDuplicates)
713 $primariesString = SqlBatch::getInString(array_keys($dataList));
715 $rowDb = $connection->query(
717 "from b_sender_posting_recipient pr, b_sender_contact r " .
718 "where pr.CONTACT_ID = r.ID " .
719 "and pr.POSTING_ID = " . (
int) $this->postingId .
" " .
720 "and r.TYPE_ID = " . (
int) $this->typeId .
" " .
721 "and r.CODE in ($primariesString)"
723 while ($row = $rowDb->fetch())
725 unset($dataList[$row[
'CODE']]);
729 if (empty($dataList))
735 count($usedPersonalizeFields) > 0
738 $preparedFields = [];
740 foreach($dataList as $data)
742 if(!isset($data[
'FIELDS']))
747 $field = $data[
'FIELDS'];
748 if(!isset($preparedFields[$field[
'CRM_ENTITY_TYPE']]))
750 $preparedFields[$field[
'CRM_ENTITY_TYPE']] = [];
752 $preparedFields[$field[
'CRM_ENTITY_TYPE']][] = $field[
'CRM_ENTITY_ID'];
755 foreach ($preparedFields as $entityType => $ids)
758 $entityType, $ids, $usedPersonalizeFields, $dataList
771 if (!$group[
'GROUP_ID'])
781 $primaries = array();
782 foreach($list as $code => $data)
784 if (!isset($data[
'CONTACT_ID']) || !$data[
'CONTACT_ID'])
788 $primaries[] = (int) $data[
'CONTACT_ID'];
791 if (count($primaries) === 0)
797 $primariesString = implode(
',', $primaries);
800 "from b_sender_posting_recipient " .
801 "where POSTING_ID = " . (
int) $this->postingId .
" " .
802 "and CONTACT_ID in (" . $primariesString .
")"
809 foreach ($codeFilter as $code)
811 if (!isset($list[$code]))
816 $item = $list[$code];
817 $fields[] = [
'ID' => $item[
'CONTACT_ID'],
'NAME' => $item[
'NAME']];
826 foreach($list as $code => $data)
828 if (!isset($data[
'EXCLUDED']) || $data[
'EXCLUDED'])
833 $recipientInsert = array(
834 'CONTACT_ID' => (
int) $data[
'CONTACT_ID'],
836 'POSTING_ID' => (
int) $this->postingId,
841 if (array_key_exists(
'USER_ID', $data) && intval($data[
'USER_ID']) > 0)
843 $recipientInsert[
'USER_ID'] = intval($data[
'USER_ID']);
846 if (array_key_exists(
'FIELDS', $data) && count($data[
'FIELDS']) > 0)
848 $recipientInsert[
'FIELDS'] = serialize($data[
'FIELDS']);
851 $dataList[] = $recipientInsert;
854 if(count($dataList) == 0)
862 [
'USER_ID',
'FIELDS'],
874 if (array_key_exists($groupId, $this->groupCount))
876 $this->groupCount[$groupId] += $count;
880 $this->groupCount[$groupId] = $count;
static getConnection($name="")
static loadMessages($file)
const STATUS_READY_TO_USE
setRecipientIdentificators(array &$dataList, bool $include=true)
fill(Connector\Base $connector, $group, $usedPersonalizeFields=[])
__construct($postingId=null, $checkDuplicates=true)
getCampaignGroups($campaignId)
isCorrectData(array $data, ?string $typeCode)
incGroupCounters($groupId=null, $count=0)
updateContacts(array &$list, array $codeFilter)
getSubscriptionConnectors($campaignId)
removePostingRecipients(array &$list)
addPostingRecipients(array &$list)
stopRecipientListBuilding()
run($postingId, $checkDuplicates=true)
getLetterConnectors($letterId)
checkUsedFields($entityType, $ids, $usedPersonalizeFields, &$dataList)
runForRecipientType($usedPersonalizeFields=[], $groups=[])
static actualize(int $groupId, bool $rebuild=false)
static checkIsSegmentPrepared(int $groupId)
static getConflictFields()
static deleteList(array $filter)
static removeAgentFromDB(int $postingId)
static addEventAgent(int $postingId)