События модуля eDost
Предупреждение!!!
Если у Вас нет опыта программирования и знаний по внутренней работе Битрикс, тогда не рекомендуем самостоятельно вносить какие-либо изменения - иначе можно получить непредсказуемый результат!
1. Подключение
в файле с константами модуля:
bitrix/modules/edost.delivery/classes/general/edost_const.php

установить:
define('DELIVERY_EDOST_FUNCTION', 'Y');

если необходимо, чтобы события AfterCalculate и AfterGetOffice вызывались еще раз после зарузки данных из кэша, установить:
define('DELIVERY_EDOST_FUNCTION_RUN_AFTER_CACHE', 'Y');
файл с функциями событий:

bitrix/modules/edost.delivery/classes/general/edost_function.php
рекомендации и предупреждения:

1. Файлы с константами и функциями модуля при обновлении НЕ переписываются, поэтому все модификации продолжат функционировать.
2. При использований функций из класса модуля (edost_class::... и CDeliveryEDOST::..), необходимо учитывать, что в новых версиях модуля логика работы этих функций может быть изменена (или они могут быть полностью удалены).
примеры:
2. BeforeCalculate
Вызывается перед расчетом доставки.

public static function BeforeCalculate(&$order, &$config) {
/*
$order - оригинальные параметры заказа
$config - настройки модуля
*/


// продолжить выполнение расчета
return false;

// отключить модуль (не производится запрос на сервер, не выводится ошибка)
return array('hide' => true);

// отменить расчет и вывести свои тарифы (формат должен соответствовать стандарту eDost)
return array('data' => array( тарифы доставки ));
изменить ид и пароль от сервера eDost
можно использовать, когда у магазина несколько филиалов в разных городах, и требуется изменять город отправки в зависимости от местонахождения покупателя

$config['id'] = '12345';
$config['ps'] = 'aaaaa';
изменить ид и пароль от сервера eDost по активному городу при мультирегиональности магазина Аспро по типу "на одном домене"
в начале файла перед "class edost_function {" добавить:
use Bitrix\Main\Loader, Bitrix\Main\Localization\Loc, Bitrix\Main\Config\Option, Bitrix\Main\SystemException, CMax as Solution, CMaxRegionality as Regionality, CMaxCache as Cache;

$aspro_region = Regionality::getCurrentLocation();
if (!empty($aspro_region['CITY_NAME'])) {
$s = [
[
'city' => 'Москва',
'edost_id' => '12345',
'edost_ps' => 'aaaaa',
],
[
'city' => 'Ростов-на-Дону',
'edost_id' => '12345',
'edost_ps' => 'aaaaa',
],
];
foreach ($s as $v) if ($v['city'] == $aspro_region['CITY_NAME']) {
$config['id'] = $v['edost_id'];
$config['ps'] = $v['edost_ps'];
}
}
одновременно несколько расчетов
например, с разных складов, чтобы найти самую дешевую/быструю доставку

if (!empty($config['function_disable'])) return; // обязатально, чтобы избежать зацикливания !!!

$o = new ArrayObject($order);
$order_copy = $o->getArrayCopy();
if (isset($order_copy['original'])) unset($order_copy['original']);
$o = new ArrayObject($config);
$config_copy = $o->getArrayCopy();
$config_copy['function_disable'] = true; // обязатально, чтобы избежать зацикливания !!!

$r = [];

// 1-й расчет
// $order_copy[...] = ... // изменить параметры заказа
// $config_copy[...] = ... // изменить настройки калькулятора
// $config_copy['id'] = '12345'; // задать другой ид/пароль от сервера eDost
// $config_copy['ps'] = 'aaaaa';
$config_copy['local_cache_key'] = 1;
$r[] = CDeliveryEDOST::EdostCalculate($order_copy, $config_copy);

// 2-й расчет
// $order_copy[...] = ... // изменить параметры заказа
// $config_copy[...] = ... // изменить настройки калькулятора
// $config_copy['id'] = '12345'; // задать другой ид/пароль от сервера eDost
// $config_copy['ps'] = 'aaaaa';
$order_copy['ITEMS'][0]['WEIGHT'] = 5000; // для примера изменяется вес первого товара на 5 кг
$config_copy['local_cache_key'] = 2;
$r[] = CDeliveryEDOST::EdostCalculate($order_copy, $config_copy);

// echo '<br><b>BeforeCalculate - arOrder:</b> <pre style="font-size: 12px">'.print_r($config_copy, true).'</pre>';
// echo '<br><b>BeforeCalculate - arOrder:</b> <pre style="font-size: 12px">'.print_r($r, true).'</pre>';

$r = $r[1]; // для примера на выход пойдет результат 2-го расчета (при необходимости результаты расчетов можно объединить, удалить или отредактировать)

foreach (['local_cache_key', 'function_disable'] as $v) if (!empty($r['order']['config'][$v])) unset($r['order']['config'][$v]); // удаление системных параметров временного расчета
$r['order']['original'] = $order['original']; // обязательно, чтобы результат привязался к первоначальному запросу (тогда он закэшируется и последующий запрос с такими же параметрами повторно обрабатываться не будет)

/*
Внимание!
В структуре $r['order'] сохранены параметры расчета, и они используются в дальнейшей обработке заказа, например, при фильтрации пунктов выдачи.
Т.е. если пункт выдачи принимает только грузы весом до 10 кг, тогда при параметре $r['order']['weight'] > 10 данный пункт выдачи будет скрыт. Поэтому если расчеты производились по разным параметрам и результат был объединен в один общий, тогда необходимо взять $r['order'] из расчета с заказом с максимальным весом и габаритами.
*/


return $r;
установить товарам вес по разделам
$block_section_weight = [6 => 100, 7 => 500]; // id раздела => вес в граммах
$product_id = [];
foreach ($order['ITEMS'] as $k => $item) $product_id[ $item['PRODUCT_ID'] ] = $item['PRODUCT_ID'];
$block_section = [];
$o = $product_id;
$main_id = [];
$s = CCatalogSKU::getProductList($product_id);
if (!empty($s)) foreach ($s as $k => $v) {
$o[$v['ID']] = $v['ID'];
$main_id[$k] = $v['ID'];
}
$u = [];
$s = CIBlockElement::GetElementGroups($o, true);
while ($v = $s->Fetch()) $u[$v['IBLOCK_ELEMENT_ID']] = $v['ID'];
foreach ($product_id as $k => $v)
if (isset($u[$k])) $block_section[$k] = $u[$k];
else if (isset($main_id[$k]) && isset($u[$main_id[$k]])) $block_section[$k] = $u[$main_id[$k]];
foreach ($order['ITEMS'] as $k => $item)
if (!empty($block_section[ $item['PRODUCT_ID'] ]) && !empty($block_section_weight[ $block_section[ $item['PRODUCT_ID'] ] ])) {
$order['ITEMS'][$k]['WEIGHT'] = $block_section_weight[ $block_section[ $item['PRODUCT_ID'] ] ];
}

// загрузить список всех разделов магазина (если требуется найти искомый раздел)
$u = array();
$s = CIBlockSection::GetList(['left_margin' => 'asc'], ['=ACTIVE' => 'Y', '=GLOBAL_ACTIVE' => 'Y'], false, ['ID', 'NAME', 'DEPTH_LEVEL']);
while ($v = $s->Fetch()) $u[$v['ID']] = $v;
$i = -1;
foreach ($u as $k => $v) {
if ($i >= 0 && $v['DEPTH_LEVEL'] > $u[$i]['DEPTH_LEVEL']) $u[$i]['all'] = true;
$i = $k;
}
// echo '<br><b>BeforeCalculate - BlockSection List:</b> <pre style="font-size: 12px">'.print_r($u, true).'</pre>';
отключить модуль на странице оформления заказа
if (strpos($_SERVER['REQUEST_URI'], '/personal/order/make') === 0 || strpos($_SERVER['REQUEST_URI'], '/bitrix/components/bitrix/sale.order.ajax/ajax.php') === 0) return array('hide' => true);
отключить модуль в карточке товара
if (strpos($_SERVER['REQUEST_URI'], '/catalog') === 0 || strpos($_SERVER['REQUEST_URI'], '/bitrix/components/edost/catalogdelivery') === 0) return array('hide' => true);
отключить модуль для указанных местоположений
$ar = array('0000073738', '0000103664'); // CODE местоположений: Москва, Санкт-Петербург
if (in_array($order['LOCATION_TO'], $ar)) return array('hide' => true);
}
3. BeforeCalculateRequest
Вызывается после обработки параметров заказа и перед запросом на сервер eDost.

public static function BeforeCalculateRequest(&$order, &$config) {
/*
$order - модифицированные параметры заказа (после обработки модулем eDost)
$config - настройки модуля

расчет производится по параметрам:
$order['LOCATION_TO'] - CODE местоположения битрикса
$order['LOCATION_ZIP'] - почтовый индекс (если пустой, тогда не передается на сервер расчета)
$order['WEIGHT'] - вес заказа в граммах
$order['PRICE'] - цена заказа в рублях
$order['size'] - массив с габаритами заказа (единица измерения должна совпадать с размерностью в личном кабинете eDost)
после изменения габариты должны быть отсортированы по возрастанию - пример:
$order['size'] = [30, 10, 20];
sort($order['size']);
*/


// продолжить выполнение расчета
return false;

// отключить модуль (не производится запрос на сервер, не выводится ошибка)
return array('hide' => true);

// отменить расчет и вывести свои тарифы (формат должен соответствовать стандарту eDost)
return array('data' => array( тарифы доставки ));
рассчитывать доставку для всех заказов по фиксированным параметрам
$order['size'] = [10, 20, 30];
$order['WEIGHT'] = 500;
$order['PRICE'] = 5000; // если требуется рассчитывать страховку также по фиксированному значению
добавить 1кг на упаковку для указанных местоположений
$ar = array('0000073738', '0000103664'); // CODE местоположений
if (in_array($order['LOCATION_TO'], $ar)) $order['WEIGHT'] += 1000;
}
4. AfterCalculate
Вызывается после расчета доставки (получен ответ от сервера eDost).

public static function AfterCalculate($order, $config, &$result) {
/*
$order - модифицированные параметры заказа (после обработки модулем eDost)
$config - настройки модуля
$result - результат расчета
*/

if (empty($result['cache'])) {
// первый расчет (данные получены с сервера eDost - результат будет закэширован)
if (!empty($result['data'])) $result['data_original'] = $result['data']; // сохранение в кэш оригинального расчета (если в дальнейшем требуется индивидуальный пересчет после загрузки из кэша)
echo 'new';
}
else {
// загрузка из кэша (модифицированные здесь данные пойдут на вывод, но следующий раз из кэша загрузится первый расчет)
if (isset($result['data_original'])) $result['data'] = $result['data_original']; // восстановление оригинального расчета
echo 'cache';
}
удаление тарифов почты, если есть любые другие тарифы
if (empty($result['cache']) && !empty($result['data'])) {
    $n = 0;
    foreach ($result['data'] as $k => $v) if ($v['format'] == 'post') $n++;
    if (count($result['data']) != $n) foreach ($result['data'] as $k => $v) if ($v['format'] == 'post') unset($result['data'][$k]);
}
удаление тарифов СДЭК, если есть тарифы boxberry
$company_id_delete = array(5); // id компаний которые необходимо удалить (СДЭК)
$company_id_exists = array(30); // id компаний которые должны остаться (boxberry)
if (empty($result['cache']) && !empty($result['data'])) {
    $ar = array(array('office'), array('door', 'house')); // формат доставки по которому проходит удаление
    foreach ($ar as $f) {
        $a = false;
        foreach ($result['data'] as $k => $v) if (in_array($v['company_id'], $company_id_exists) && in_array($v['format'], $f)) { $a = true; break; }
        if ($a) foreach ($result['data'] as $k => $v) if (in_array($v['company_id'], $company_id_delete) && in_array($v['format'], $f)) unset($result['data'][$k]);
    }
}
универсальная обработка тарифов
скидка на доставку (фиксированная стоимость, блокировка наложки) в зависимости от местоположения (региона, страны), тарифа и формата доставки
если не нужна прямая зависимость от параметров битрикса и не нужен сложный учет скидок или ограничений, тогда вместо данного кода, лучше использовать штатные функции обработки расчета (в личном кабинете eDost у магазина в разделе "функции")

$ar = array(
    array(
        'location_code' => array('0000073738'), // код местоположений битрикса для которых будет действовать скидка ('0000073738' - Москва, '0000103664' - Санкт-Петербург)
        'region_name' => array('Хабаровский край'), // названия регионов для которых будет действовать скидка - для работы данной настройки, текущий файл должен быть в кодировке магазина!
        'country_name' => array('Россия'), // названия стран для которых будет действовать скидка - для работы данной настройки, текущий файл должен быть в кодировке магазина!
        'tariff_id' => array(37), // id тарифа в системе eDost: https://edost.ru/kln/help.html#DeliveryCode - если указано, тогда параметры 'company_id' и 'format' игнорируются
        'company_id' => array(5), // id компаний стандарта eDost для которых будет действовать скида (5 - СДЭК) - если масив пустой, тогда скидка действует для всех компаний доставки
        'format' => array('office'), // формат доставки для которого будет действовать скидка ('office' - пункты выдачи) - если масив пустой, тогда скидка действует для всех форматов доставки
        'normal' => array( // скидка для указанных местоположений/регионов (если для указанных местоположений скидка не нужна, тогда данный массив необходимо удалить - оставить только 'invert')
            'price_from' => 0, // стоимость заказа ОТ которой действует скидка
            'price_to' => 5000, // стоимость заказа ДО которой действует скидка
            'discount_percent' => 20, // процент скидки
            'discount_fix' => 0, // фиксированная скидка
            'pricecash_discount_disable' => true, // не применять скидку для доставки с наложенным платежом
            'change' => array( // если указано, заменяет рассчитанную стоимость доставки этим значением (можно указывать оба значения, или только 'price', или только 'pricecash')
                'price' => 100, // стоимость доставки
                'pricecash' => -1 // стоимость доставки при наложенном платеже ('-1' - наложка отключена, можно использовать для блокировки наложки в интересующих регионах)
            )
        ),
        'invert' => array( // скидка для всех остальных местоположений/регионов (если для остальных местоположений скидка не нужна, тогда данный массив необходимо удалить - оставить только 'normal')
            'price_from' => 0, // стоимость заказа ОТ которой действует скидка
            'price_to' => 0, // стоимость заказа ДО которой действует скидка
            'discount_percent' => 100, // процент скидки
            'discount_fix' => 350, // фиксированная скидка
            'pricecash_discount_disable' => true, // не применять скидку для доставки с наложенным платежом
            'change' => array( // если указано, заменяет рассчитанную стоимость доставки этим значением (можно указывать оба значения, или только 'price', или только 'pricecash')
                'price' => 250, // стоимость доставки
                'pricecash' => -1 // стоимость доставки при наложенном платеже ('-1' - наложка отключена, можно использовать для блокировки наложки в интересующих регионах)
            )
        ),
    ),
    // блокировка наложки для всех стран, кроме России
    array(
        'country_name' => array('Россия'), // для работы данной настройки, текущий файл должен быть в кодировке магазина!
        'invert' => array(
            'change' => array(
                'pricecash' => -1 // стоимость доставки при наложенном платеже ('-1' - наложка отключена)
            )
        ),
    ),
//  array(... еще одна скидка с другими параметрами (скидок может быть сколько угодно)
);
if (empty($result['cache']) && !empty($result['data'])) {
    foreach ($ar as $param) {
        $a = (!empty($param['location_code']) && in_array($order['LOCATION_TO'], $param['location_code']) ||
            !empty($param['region_name']) && in_array($order['location']['region_name'], $param['region_name']) ||
            !empty($param['country_name']) && in_array($order['location']['country_name'], $param['country_name']) ? true : false);

        foreach ($result['data'] as $k => $v)
            if (!empty($param['tariff_id']) && in_array($v['id'], $param['tariff_id']) ||
                empty($param['tariff_id']) && (empty($param['company_id']) || !empty($param['company_id']) && in_array($v['company_id'], $param['company_id'])) && (empty($param['format']) || in_array($v['format'], $param['format']))) {

                $p = $s = $s2 = false;
                if ($a && isset($param['normal'])) $p = $param['normal'];
                if (!$a && isset($param['invert'])) $p = $param['invert'];
                if (empty($p) || isset($p['price_from']) && $order['PRICE'] <= $p['price_from'] || isset($p['price_to']) && $order['PRICE'] > $p['price_to']) continue;
                if (!empty($p['change'])) {
                    if (isset($p['change']['price'])) $s = $p['change']['price'];
                    if (isset($p['change']['pricecash'])) $s2 = $p['change']['pricecash'];
                }
                else {
                    $s = $v['price']*(!empty($p['discount_percent']) ? (100 - $p['discount_percent'])/100 : 1) - (!empty($p['discount_fix']) ? $p['discount_fix'] : 0);
                    if ($s < 0) $s = 0;
                    if ($v['pricecash'] >= 0 && !isset($p['pricecash_discount_disable'])) {
                        $s2 = $v['pricecash']*(!empty($p['discount_percent']) ? (100 - $p['discount_percent'])/100 : 1) - (!empty($p['discount_fix']) ? $p['discount_fix'] : 0);
                        if ($s2 < 0) $s2 = 0;
                    }
                }
                if ($s !== false) {
                    if ($result['data'][$k]['price'] > $s) $result['data'][$k]['priceoriginal']['price'] = $result['data'][$k]['price'];
                    $result['data'][$k]['price'] = $s;
                }
                if ($s2 !== false) {
                    if ($result['data'][$k]['pricecash'] != -1 && $result['data'][$k]['pricecash'] > $s2) $result['data'][$k]['priceoriginal']['pricecash'] = $result['data'][$k]['pricecash'];
                    $result['data'][$k]['pricecash'] = $s2;
                }
            }
    }
}
изменение формата доставки EMS с курьера на почту
$company_id = array(2); // id компаний которым необходимо изменить формат доставки (EMS)
$new_format = 'post'; // новый формат доставки (блок "почта")
if (empty($result['cache']) && !empty($result['data'])) foreach ($result['data'] as $k => $v) if (in_array($v['company_id'], $company_id)) $result['data'][$k]['format'] = $new_format;
изменение тарифа в зависимости от товаров на складе
при наличии товаров на складе поставщика в городе покупателя, пунктам выдачи СДЭК присваивается цена из тарифа "Самовывоз 4" (в заказе сохраняется самый дешевый тариф СДЭК из доступных)

if (empty($result['cache']) && !empty($result['data'])) $result['data_original'] = $result['data']; // сохранение оригинального расчета
else if (isset($result['data_original'])) $result['data'] = $result['data_original']; // восстановление оригинального расчета при загрузке из кэша

if (!empty($result['data'])) {
    $company = 5; // код "СДЭК"
    $shop = 's4'; // код "Самовывоз 4"
    $ar = array();
    if (!empty($order['ITEMS'])) foreach ($order['ITEMS'] as $v) $ar[] = $v['PRODUCT_ID'];
    if (!empty($ar)) {
        $store = false;
        $ar = CCatalogStore::GetList(array('SORT' => 'ASC'), array('PRODUCT_ID' => $ar, 'ACTIVE' => 'Y'), false, false, array('ID', 'TITLE', 'ADDRESS', 'PRODUCT_AMOUNT'));
        while ($v = $ar->fetch()) if ($v['TITLE'] == $order['location']['bitrix']['city']) { // название склада (TITLE) должно соответствовать названию города покупателя!!!
            if (!empty($v['PRODUCT_AMOUNT'])) $store = true;
            else { $store = false; break; }
        }
        if ($store) {
            $shop_k = false;
            foreach ($result['data'] as $k => $v) if ($v['company_id'] == $shop) $shop_k = $k;
            if ($shop_k !== false) {
                $p = false;
                foreach ($result['data'] as $k => $v) if ($v['company_id'] == $company && $v['format'] == 'office' && ($p === false || $v['price'] < $p)) { $company_k = $k; $p = $v['price']; }
                if ($p !== false) {
                    $ar = array('price', 'pricecash', 'day', 'insurance');
                    foreach ($ar as $v) $result['data'][$company_k][$v] = $result['data'][$shop_k][$v];
                    foreach ($result['data'] as $k => $v) if ($v['company_id'] == $company && $v['format'] == 'office' && $k != $company_k) unset($result['data'][$k]);
                }
            }
        }
    }
}
сбросить формат доставки в карточке товара
тарифы будут выводиться без разделения на "Курьером до двери", "До пункта выдачи" и т.д.)

if (strpos($_SERVER['REQUEST_URI'], '/catalog') === 0 || strpos($_SERVER['REQUEST_URI'], '/bitrix/components/edost/catalogdelivery') === 0)
    if (!empty($result['data'])) foreach ($result['data'] as $k => $v) $result['data'][$k]['format'] = '';
заменить 'дни' на 'рабочие дни'
if (empty($result['cache']) && !empty($result['data'])) foreach ($result['data'] as $k => $v) if (!empty($v['day'])) {
    $result['data'][$k]['day'] = str_replace(array('день', 'дня', 'дней'), array('рабочий день', 'рабочих дня', 'рабочих дней'), $v['day']);
}
исключение стоимости доставки из итого (для почты и EMS)
$id = array(1, 2, 3, 61, 62, 68); // id тарифов стандарта eDost
if (empty($result['cache']) && !empty($result['data'])) foreach ($result['data'] as $k => $v)
    if (in_array($v['id'], $id) && $v['price'] > 0) {
        $result['data'][$k]['priceinfo'] = $v['price'];
        $result['data'][$k]['price'] = 0;
    }
удаление из расчета тарифа "DPD (parcel до пункта выдачи)" (код 91)
if (isset($result['data']['91'])) unset($result['data']['91']);
50% скидка на тариф "Курьер 1" (код 61) при заказе в субботу-воскресенье
предупреждение: используется время сервера - оно может отличаться от часового пояса магазина и покупателя
if (isset($result['data']['61'])) {
    if (empty($result['cache'])) $result['data']['61']['price_original'] = $result['data']['61']['price'];
    $p = $result['data']['61']['price_original'];
    if (date('N') >= 6) $p = round($p*0.5);
    $result['data']['61']['price'] = $p;
}
изменение стоимости доставки тарифа "PickPoint"
$id = 57; // PickPoint
if (empty($result['cache']) && isset($result['data'][$id])) {
    // установка фиксированной стоимости доставки для указанных местоположений
    $ar = array('0000073738', '0000103664'); // CODE местоположений
    if (in_array($order['LOCATION_TO'], $ar)) {
        $result['data'][$id]['price'] = 250; // стоимость доставки
        $result['data'][$id]['pricecash'] = 250; // стоимость доставки при наложенном платеже (-1 - отключить наложенный платеж)
    }

    // установка эксклюзивной стоимости для пунктов выдачи с типом 5
    $result['data'][$id]['priceoffice'] = array(
        5 => array(
            'type' => 5,
            'price' => $result['data'][$id]['price'] + 100, // стандартная стоимость доставки + 100 руб.
            'priceinfo' => 0,
            'pricecash' => 800, // стоимость доставки при наложенном платеже
        ),
    );
}
}
5. AfterFormatTariff
Вызывается после форматирования тарифов (сортировка, разделение по типам, загрузка данных по пунктам выдачи и т.д.).

public static function AfterFormatTariff($bitrix_data, $currency, $order, $config, &$result) {
/*
Предупреждение!
1. Функция форматирования - это очень сложная система объединения тарифов доставки, пунктов выдачи, наложенного платежа, скидок, бонусов и многого другого, поэтому модифицировать результат необходимо очень осторожно и внимательно. Самый оптимальный вариант - это изменять только порядок вывода блоков или текстовую информацию (например, названия блоков, тарифов, описание).
2. Измененные здесь данные влияют только на внешний вид (т.е. на странице оформления изменения будет видно, но в итоговом заказе они НЕ сохранятся).

$bitrix_data - оригинальный массив битрикса со службами доставки
$currency - валюта шаблона
$order - заказ стандарта битрикса
$config - параметры модуля eDost
$result - результат
$result['map_json'] и $result['map_data'] - это системные данные необходимые для внутренней работы модуля - лучше их НЕ менять!
*/
изменение описания для тарифа "Почта (ЕКОМ)"
tariff_id: 78

if (!empty($result['data'])) foreach ($result['data'] as $f_key => $f) foreach ($f['tariff'] as $k => $v) if (isset($v['tariff_id']) && $v['tariff_id'] == 78)
    $result['data'][$f_key]['tariff'][$k]['description'] = 'Дешевая доставка до пункта выдачи или постамата.';
}
установка собственных тарифов в начало
в шаблоне eDost в компактном формате вывода
изменение названия "Другие способы доставки"
в шаблоне eDost в стандартном формате вывода

if (!empty($result['data']['general']['tariff'])) {
    $result['data']['general']['head'] = 'Собственная доставка магазина';
    if (count($result['data']) > 1) {
        $s = $result['data']['general'];
        unset($result['data']['general']);
        $result['data'] = array_merge(array('general' => $s), $result['data']);
    }
}
}
6. BeforeGetOffice
Вызывается перед загрузкой данных по пунктам выдачи.

public static function BeforeGetOffice($order, &$company) {
/*
$order - параметры заказа
$company - массив с кодами компаний доставки для которых требуется загрузить данные
*/
}
7. AfterGetOffice
Вызывается после загрузки данных по пунктам выдачи.

public static function AfterGetOffice($order, &$result) {
/*
$order - параметры заказа
$result - пункты выдачи
*/

if (empty($result['cache'])) {
// первый расчет (данные получены с сервера eDost - результат будет закэширован)
if (!empty($result['data'])) $result['data_original'] = $result['data']; // сохранение в кэш оригинального расчета (если в дальнейшем требуется индивидуальный пересчет после загрузки из кэша)
echo 'new';
}
else {
// загрузка из кэша (модифицированные здесь данные пойдут на вывод, но следующий раз из кэша загрузится первый расчет)
if (isset($result['data_original'])) $result['data'] = $result['data_original']; // восстановление оригинального расчета
echo 'cache';
}
сортировка пунктов выдачи по алфавиту
if (empty($result['cache']) && !empty($result['data'])) foreach ($result['data'] as $k => $v) {
    $ar = array();
    foreach ($v as $v2) $ar[] = trim(str_replace(array('ул.', 'проспект', 'переулок', 'площадь'), '', $v2['address']));
    array_multisort($ar, SORT_ASC, SORT_STRING, $v);
    $ar = array();
    foreach ($v as $v2) $ar[$v2['id']] = $v2;
    $result['data'][$k] = $ar;
}
удаление пунктов выдачи компании ПЭК и Деловые линии
останутся только терминалы

if (empty($result['cache']) && !empty($result['data'])) foreach ($result['data'] as $k => $v) if (in_array($k, array(19, 21))) foreach ($v as $k2 => $v2) if ($v2['type'] != 2) {
    unset($result['data'][$k][$k2]);
}
отключение у пунктов выдачи ссылки "подробнее..."
отключение/замену необходимо дублировать в функции "AfterGetOrderOffice" !!!

if (empty($result['cache'])) {
    $id = 5; // код одного из тарифов "СДЭК"
    if (!empty($result['data'][$id])) foreach ($result['data'][$id] as $k => $v) $result['data'][$id][$k]['detailed'] = 'N'; // или можно заменить на свою ссылку: 'https://myshop.ru/delivery.html?id=%id%' (%id% будет заменен id офиса) - если в запрос добавить '&frame=Y', тогда страница будет открываться в окошке (без новой вкладки)
}
перенос офисов СДЭК в тариф "Самовывоз 1"
if (empty($result['cache'])) {
    $from = 5; // код "СДЭК"
    $to = 's1'; // код "Самовывоз 1"
    if (!empty($result['data'][$from])) {
        $result['data'][$to] = $result['data'][$from];
        unset($result['data'][$from]);
        if (!empty($result['limit'])) foreach ($result['limit'] as $k => $v) if ($v['company_id'] == $from) $result['limit'][$k]['company_id'] = $to;
    }
}
удаление пункта выдачи тарифа 'Самовывоз 1' (код 's1')
if (isset($result['data']['s1'])) unset($result['data']['s1']);
генерация собственного пункта выдачи для тарифа 'Самовывоз 1' (код 's1')
/*
Требования при генерации полностью нового пункта выдачи (которого нет в системе eDost):
1. Присвоить уникальный id (например, 1000000, 1000001, 1000002, и т.д.)
2. Указать в параметрах один из вариантов:
    'detailed' => 'https://myshop.ru/delivery.html?id=%id%', // прописать собственную ссылку на детальную информацию (если в запрос добавить '&frame=Y', тогда страница будет открываться в окошке)
    или
    'detailed' => 'N', // отключить ссылку на детальную информацию
3. При использовании собственной ссылки с детальной информацией, ее также необходимо генерировать в функции "AfterGetOrderOffice"
*/
if (empty($result['cache'])) $result['data']['s1'] = array(
    '12345A12345' => array( // ключ и id должны совпадать
        'id' => '12345A12345', // id с буквой "A" – это оригинальный идентификатор пункта выдачи созданного в личном кабинете eDost, и по этому идентификатору можно открыть его страницу с детальной информацией на сайте edost.ru (там адрес, описание, карта и т.д.)
        'code' => '',
        'name' => 'ТЦ Калач',
        'address' => 'Москва, ул. Академика Янгеля, д. 6, корп. 1',
        'address2' => 'оф. 5',
        'tel' => '+7-123-123-45-67',
        'schedule' => 'с 10 до 20, без выходных',
        'gps' => '37.592311,55.596037',
        'type' => 3,
        'metro' => '',
//        'detailed' => 'https://myshop.ru/delivery.html?id=%id%', // прописать собственную ссылку на детальную информацию
//        'detailed' => 'N', // отключить ссылку на детальную информацию
//        'options' => 4, // опции пункта выдачи (2 - недоступна оплата наличными, 4 - возможна оплата картой, 6 - недоступна оплата наличными и возможна оплата картой)
    ),
);
генерация пункта выдачи для тарифа "СДЭК"
if (empty($result['cache'])) $result['data']['5'][1000000] = array(
        'id' => '1000000',
        'code' => '', // если код не указан, тогда при сохранении выбранного в заказе пункта выдачи в адресе в качесте кода будет записана буква 'S' (для тарифов Самовывоз) или 'T' (для всех остальных тарифов)
        'name' => 'ТЦ Калач',
        'address' => 'Москва, ул. Академика Янгеля, д. 6, корп. 1',
        'address2' => 'оф. 5',
        'tel' => '+7-123-123-45-67',
        'schedule' => 'с 10 до 20, без выходных',
        'gps' => '37.592311,55.596037',
        'type' => 3,
        'metro' => '',
//        'detailed' => 'https://myshop.ru/delivery.html?id=%id%', // прописать собственную ссылку на детальную информацию
        'detailed' => 'N', // отключить ссылку на детальную информацию
);
}
8. AfterGetOrderOffice
Вызывается после загрузки данных по пункту выдачи сохраненному в заказе.
Используется при выводе данных в админке и в личном кабинете покупателя (требуется интеграция).

public static function AfterGetOrderOffice($order, &$office) {
/*
$order - параметры заказа
$office - пункт выдачи
*/
отключение у всех пунктов выдачи ссылки "подробнее..."
$office['detailed'] = 'N';
замена у всех пунктов выдачи стандартной ссылки "подробнее..." на свою
$office['detailed'] = 'https://myshop.ru/delivery.html?id=%id%'; // %id% будет автоматически заменен на ID пункта выдачи
замена стандартного блока с данными пункта выдачи своим значением
$office['address_formatted'] = '<div style="font-size: 16px; color: #800;">заказ доставят в '.$office['head'].' (код: '.$office['code'].')</div>';
}
9. BeforeOrderUpdate
Вызывается перед изменением заказа функциями контроля и оформления доставки.

public static function BeforeOrderUpdate($order, $data, &$param) {
/*
$order - заказ
$data - данные по отгрузке
$param - параметры

$param['function'] - название события
'print_no_register' - установка статуса заказа при печате без оформления
'paid' - зачисление платежа и изменение статуса заказа
'register' - сохранение идентификатора отправления и изменение статуса заказа после оформления доставки
'control' - изменение статуса заказа после вручения или прибытия в пункт выдачи
'register_cancel' - удаление в отгрузке идентификатора отправления после отмены оформления

$param['status'] - новый статус заказа
$param['shipment_status'] - новый статус отгрузки
$param['tracking_code'] - идентификатор отправления
$param['payment_id'] - id оплаты
$param['paid'] - true - зачислить оплату для $param['payment_id']
*/
отменить изменение статуса заказа
if (isset($param['status'])) unset($param['status']);
}
10. BeforeSetItem
Вызывается перед обработкой товаров заказа (при расчете доставки и при оформлении доставки).

public static function BeforeSetItem(&$items) {
/*
$items - массив с товарами
*/
установить всем товарам фиксированный вес (в граммах) и габариты (в миллиметрах)
foreach ($items as $k => $item) {
$items[$k]['WEIGHT'] = 1000;
$items[$k]['DIMENSIONS'] = ['WIDTH' => 100, 'HEIGHT' => 200, 'LENGTH' => 300];
}
}
11. BeforeOrderBox
Вызывается перед упаковкой заказа (упаковка из раздела "оформление доставки").
Если заказ уже был упакован ранее (вручную или автоматически) и вес/габариты заказа не изменились, тогда данное событие не вызывается.


public static function BeforeOrderBox(&$data, $function, $order, $param) {
/*
$data - параметры заказа с учетом упаковки (по этим параметрам будет рассчитываться доставка в магазине и эти параметры будут переданы в службу доставки)

$function - название события ('calculate' - расчет доставки, 'register' - раздел "оформление доставки")

$order - параметры заказа без упаковки (если в $data ничего не задано, тогда расчет/оформление будет производиться по $order)

$param - параметр упаковки из настроек
'no' - не использовать
'1' - использовать для всех заказов
's' - использовать только для заказов с габаритами
's2' - использовать только для заказов, у которых все товары с габаритами

Для функции 'calculate' $param загружается из настроек модуля eDost, для функции 'register' из раздела "оформление доставки".
*/
список существующих коробок/пакетов, которые можно использовать для упаковки
$box = edost_class::GetRegisterBox();
echo '<br><b>BeforeOrderBox - box:</b> <pre style="font-size: 12px">'.print_r($box, true).'</pre>'; отменить упаковку
$data = false;
установить свои вес и габариты упакованного заказа (ручной ввод)
$data = [
'box_id' => -1,
'weight' => 2000, // вес в граммах
'size' => [100, 200, 300], // габариты в миллиметрах
];
установить коробку/пакет по id
$data = [
'box_id' => 1, // id коробки/пакета (0 - упаковка не задана/отменена)
'box' => $box[1], // данные выбранной коробки/пакета (должны быть предварительно загружены - смотрите выше)
'weight' => 2000, // вес упакованного заказа в граммах
'size' => [100, 200, 300], // габариты упакованного заказа в миллиметрах
];
}
Модуль расчета доставки в карточке товара
1. Подключение
в файле с константами модуля:
bitrix/modules/edost.catalogdelivery/classes/general/edost_const.php

установить:
define('CATALOGDELIVERY_EDOST_FUNCTION', 'Y');
файл с функциями событий:

bitrix/modules/edost.catalogdelivery/classes/general/edost_function.php
примеры:
2. BeforeCalculate
Вызывается перед расчетом доставки.

public static function BeforeCalculate($mode, &$param) {
/*
$mode - режим вызова ('' - инициализация модуля)
$param - настройки модуля
*/


// продолжить выполнение расчета
return false;

// сбросить расчет
return array();

// сбросить расчет и вывести указанные данные
return array('inside' => массив с данными для встроенного блока, 'format' => массив с данными для полного расчета, 'detailed' => вывести ссылку 'подробнее...');
замена стандартного выбора местоположений на стороннее
например, через модуль с выбором города в шапке сайта

// id местоположения, куда будет рассчитываться доставка
if ($mode != '') {
    $param['location']['id'] = 101;
    $param['location']['zip'] = '101000';
}

// js код, который будет вызываться, когда посетитель кликнет по выбору/изменению города
// вместо данного кода, в собственном js скрипте можно создать функцию edost_ExternalLocation() - если модуль обнаружит данную функцию, тогда автоматически ее вызовет при выборе города
if ($mode == '') $param['external_location'] = "alert('get new city')";

// в стороннем модуле выбора местоположений после изменения города необходимо вызвать js функцию для пересчета доставки в карточке товара: if (window.edost) edost.catalogdelivery.calculate();
установить собственный ключ кэширования
необходимо использовать, например, при расчете из разных городов в одном магазине)

$param['cache_key'] = 'city1';
установить ID товара, который будет браться за основу в ручном калькуляторе
можно использовать, когда требуется учет ограничений по разделам каталога

$param['product_id2'] = 100;
отменить расчет и вывести только во встроенном блоке собственный тариф
для ID указанных местоположений

if ($mode != '' && !empty($param['location']['id']) && in_array($param['location']['id'], array(100, 120))) {
    $result = array();

    $result['inside']['data']['general']['tariff'] = array(
        0 => array(
            'id' => 'door',
            'company' => 'Курьер до МКАД',
            'price_formatted' => '200 руб.',
//            'free' => 'Бесплатно!', // будет выделено зеленым цветом
            'day' => '4 дня',
            'ico' => '/bitrix/images/delivery_edost_img/small/door.gif',
        ),
    );
    $result['inside']['show_ico'] = true;
    $result['inside']['minimize'] = true;
    $result['detailed'] = false; // отключить ссылку 'подробнее...', которая открывает окно с полным расчетом

    return $result;
}
расчет по корзине
например, при интеграции модуля в страницу корзины с JS вызовом:
edost_RunScript('preview', '', 'товары в корзине');

if ($mode != '' && isset($param['product_id']) && $param['product_id'] == 0) $param['add_cart'] = 'Y';
}
3. BeforeCalculateRequest
Вызывается после обработки параметров и перед вызовом функции расчета доставки.

public static function BeforeCalculateRequest(&$order, &$param) {
/*
$order - параметры заказа
$param - параметры модуля
*/


// продолжить выполнение расчета
return false;

// сбросить расчет
return array();

// сбросить расчет и вывести указанные данные
return array('inside' => массив с данными для встроенного блока, 'format' => массив с данными для полного расчета, 'detailed' => вывести ссылку 'подробнее...');
добавить к весу каждой единицы товара по 50 грамм на упаковку
if (!empty($order['ITEMS'])) foreach ($order['ITEMS'] as $k => $v) $order['ITEMS'][$k]['WEIGHT'] += 50;
}
4. AfterCalculate
Вызывается после расчета доставки.

public static function AfterCalculate($order, $param, &$result) {
/*
$order - параметры заказа
$param - параметры модуля
$result - результат расчета
*/
изменение названия группы "Другие способы доставки" и установка ее в начало списка
if (!empty($result['format']['data']['general']['tariff'])) {
    $result['format']['data']['general']['head'] = 'Собственная доставка магазина';
    if (count($result['format']['data']) > 1) $result['format']['data'] = array_merge(array('general' => ''), $result['format']['data']);
}
изменение названия тарифа для группы "до двери" (в блоке со встроенным расчетом)
if (!empty($result['inside']['data']['general']['tariff'])) foreach ($result['inside']['data']['general']['tariff'] as $k => $v)
    if ($v['id'] === 'door') $result['inside']['data']['general']['tariff'][$k]['company'] = 'Курьером';
}
info@edost.ru

© ООО "Айсден", 2006-2023. Все права защищены.