> For the complete documentation index, see [llms.txt](https://endpoint-docs.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://endpoint-docs.gitbook.io/docs/readme/biznes-processy-bp.md).

# Бизнес-процессы (БП)

### План поступлений

БП формирует список счетов (159), который должны оплатить на этой неделе. Список формируется из счетов, которые находятся в стадии "Оплатят на этой неделе".

[Ссылка на БП - https://gkyw.ru/crm/configs/bp/CRM\_DYNAMIC\_159/edit/530/](https://gkyw.ru/crm/configs/bp/CRM_DYNAMIC_159/edit/530/)

Скрипт автоматически:

1. Собирает все счета в статусе "Оплатят на этой неделе" (DT159\_1:PREPARATION), у которых не указана дата оплаты
2. Группирует эти счета по сделкам
3. Суммирует сумму платежей по каждой сделке
4. Формирует сообщение с общей суммой всех платежей и детализацией по сделкам
5. Отправляет это сообщение в указанный чат с упоминанием ответственных сотрудников

Результат выглядит примерно так:

```
На этой неделе нам должны перечислить 123 456,78 ₽ в т.ч.:
45 000,00 ₽ по сделке Поставка оборудования (Иванов И.)
78 456,78 ₽ по сделке Консультационные услуги (Петров П.)
```

#### Информация для разработчика

Скрипт использует Bitrix API для работы с CRM-сущностями и мессенджером:

**1. Инициализация и подключение модулей:**

```php
<?php
#Подключение необходимых зависимостей
include_once($_SERVER['DOCUMENT_ROOT'] . "/constants.php");

\Bitrix\Main\Loader::IncludeModule('iblock');
\Bitrix\Main\Loader::IncludeModule('im');
\Bitrix\Main\Loader::IncludeModule('crm');
```

**2. Настройка идентификаторов чатов и бота:**

```php
$chatManagmentID = 22541; // 22541 - боевой чат,  143767 - тестовый чат
$chatPlanID = 145781; // 145781 - боевой чат, 143767 - тестовый чат
$botID = 3; // 3 - боевой, 487 - тестовый
$startDate = "2019-01-01"; // Постоянная дата
```

**3. Получение фабрик для работы с сущностями CRM:**

```php
$factoryBill = \Bitrix\Crm\Service\Container::getInstance()->getFactory(CRM_SCHETA_ID);
$factoryDeal = \Bitrix\Crm\Service\Container::getInstance()->getFactory(2);
```

**4. Получение дат текущей недели:**

```php
$date = strtotime('monday this week');

for ($i = 0; $i < 7; $i++) {
    $currentWeekDays[] =  date("d.m.Y", strtotime('+' . $i . ' day', $date));
}
```

**5. Получение счетов с фильтрацией и их обработка:**

```php
$filterBill = ["UF_PAY_DATE" => '', "STAGE_ID" => 'DT159_1:PREPARATION'];  // DT159_1:PREPARATION - счета со статусом "Оплатят на этой неделе"
$bills = $factoryBill->getItems(array('filter' => $filterBill));

if (!empty($bills)) {
    foreach ($bills as $bill) {
        $billID = $bill->get('ID');
        $billAmount = $bill->get('OPPORTUNITY');
        $dealID = $bill->get('PARENT_ID_2');

        $deal = $factoryDeal->getItem($dealID);
        $dealTitle = $deal->get('TITLE');
        $dealResponsibleID = $deal->get('ASSIGNED_BY_ID');

        $responsible = CUser::getById($dealResponsibleID)->fetch();

        $dealResponsible = $responsible['LAST_NAME'] . " " . mb_str_split($responsible['NAME'])[0] . ".";

        $dealsInfo[$dealID]['AMOUNT'] += $billAmount;

        if (empty($dealsInfo[$dealID]['TITLE'])) {
            $dealsInfo[$dealID]['TITLE'] = $dealTitle;
        }

        if (empty($dealsInfo[$dealID]['RESPONSIBLE'])) {
            $dealsInfo[$dealID]['RESPONSIBLE'] = $dealResponsible;
            $dealsInfo[$dealID]['RESPONSIBLE_ID'] = $dealResponsibleID;
        }

        $amount += $billAmount;
    }
}
```

**6. Формирование сообщения с детализацией по сделкам:**

```php
foreach ($dealsInfo as $dealID => $dealInfo) {
    $dealAmount = $dealInfo['AMOUNT'];
    $dealTitle = $dealInfo['TITLE'];

    $dealResponsibleID = $dealInfo['RESPONSIBLE_ID'];
    $dealResponsible = "[USER=$dealResponsibleID]" . $dealInfo['RESPONSIBLE'] . "[/USER]";

    $amountToMsg .= "[BR]" . number_format($dealAmount, 2, ",", " ") . " ₽ по сделке [URL=" . BITRIX_DOMAIN . "crm/deal/details/$dealID/]" . $dealTitle . "[/URL] ($dealResponsible)";
}

$amountToMsg = str_replace("_amount_", number_format($amount, 2, ",", " ") . " ₽", $amountToMsg);
```

**7. Отправка сообщения в чат:**

```php
$chat = new \CIMChat;
$chat->AddMessage(array(
    'TO_CHAT_ID' => $chatPlanID,
    'FROM_USER_ID' => $botID,
    'SYSTEM' => 'N',
    'MESSAGE' => $amountToMsg
));
```

Скрипт использует стандартные методы Bitrix API для работы с CRM и мессенджером, форматирует денежные значения и создает сообщение с тегами BBCode для форматирования и упоминания пользователей.

**Актуализация сроков закупки**

БП является частью процесса в ленте новостей, под названием "просроченные лиды", код находится в php блоке, под названием "Актуализация сроков закупки". Сам процесс настроен в приложение "Запуск БП по расписанию" и выполняется по расписанию(ежедневно, в 07:00).

**Что делает скрипт:**

* Подбирает все лиды с введеным реестровым номером

```php
$sql = "SELECT uf.VALUE_ID, uf.UF_CRM_PARSE_REESTR_NOMER_ZAKUPKI, l.STATUS_ID
        FROM b_uts_crm_lead uf
        INNER JOIN b_crm_lead l ON uf.VALUE_ID = l.ID
        WHERE uf.UF_CRM_PARSE_REESTR_NOMER_ZAKUPKI IS NOT NULL 
        AND uf.UF_CRM_PARSE_REESTR_NOMER_ZAKUPKI != ''
        AND (l.STATUS_ID = 'NEW' OR l.STATUS_ID = 'UC_3AFWHC' OR l.STATUS_ID = 'IN_PROCESS' OR l.STATUS_ID = '1' OR l.STATUS_ID = '2' OR l.STATUS_ID = 'PROCESSED')";

$recordset = $connection->query($sql);
```

* Отправляет реестровые номера на вьюшку приложения "госзакупки в лид", в формате:

{id\_лида: реестровый номер}

И ждет ответа в формате:

{id\_лида: актуальная дата окончания закупки}

```php
if (empty($recordset)) {
    exit;
} else {
    foreach ($recordset as $record) {
        $reestryNumber = $record["UF_CRM_PARSE_REESTR_NOMER_ZAKUPKI"];
        $leadId = $record["VALUE_ID"];
        $requestData[$leadId] = $reestryNumber;
    }
}

$jsonInput = json_encode($requestData);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://dev.vestrus.ru/marketplace/goszakup_app/api.php?action=update_lids');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonInput);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 350); //ограничение на время ожидания от приложения(5 минут)

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
```

* После чего, происходит обработка полученных данных, с последующим заполнением их в поля "Окончание сроков закупки\[endpoint]" *(UF\_CRM\_PARSE\_KONEC\_SPROKA\_ZAKUPKI)* и "Окончание приема заявок" *(UF\_DATE\_END)*.

```php
if ($httpCode == 200 && $response) {
    $responseData = json_decode($response, true);
    $updateCount = 0;
    if (is_array($responseData)) {
        foreach ($responseData as $valueId => $submissionDeadline) {
            $updateSql = "UPDATE b_uts_crm_lead 
                              SET UF_CRM_PARSE_KONEC_SPROKA_ZAKUPKI = '{$submissionDeadline}',
                                  UF_DATE_END = '{$submissionDeadline}'
                              WHERE VALUE_ID = {$valueId}";

            $result = $connection->query($updateSql);
        }
    }
}
```

Дополнительное заполнения поля "Окончание приема заявок" — необходимо, для работы следующего бп в процессе "просроченные лиды".
