Если возникает необходимость расчёта стоимости доставки для способов, которые не поддерживаются системой «из коробки», вы можете создать собственный класса для расчёта стоимости и сроков доставки.
Описание классов актуально для версии 5.8.0 и старше; часть свойств и методов может отсутствовать в предыдущих версиях.
Способ доставки настраивается в панели управления модуля «Интернет-магазин». Ему соответствует класс nc_netshop_delivery_method
.
Служба доставки — внешний сервис, предоставляющий информацию о стоимости и сроках доставки (API компании, осуществляющей доставку).
Способ расчёта доставки (класс расчёта доставки) — PHP-класс, который отвечает за расчёт сроков и стоимости доставки. Выбирается в способе доставки в поле «Способ автоматического расчёта стоимости доставки». Классы расчёта доставки должны быть наследниками класса nc_netshop_delivery_service
.
Тип доставки указывает как производится доставка (курьером по адресу, до пункта выдачи, в почтовое отделение). В классах задаётся с использованием констант nc_netshop_delivery::DELIVERY_TYPE_*
.
Варианты доставки позволяют выдавать информацию о нескольких доступных вариантах доставки, настроив в настройках модуля только один способ доставки. Данная возможность полезна, например, при интеграции с агрегаторами доставки, которые позволяют выбрать множество различных служб доставки с различной стоимостью и сроками.
Класс вариантов доставки — nc_netshop_delivery_method_variant
— можно использовать везде, где используется nc_netshop_delivery_method
(например, при выводе информации о доступных для заказа способах доставки), так как он является его наследником.
Варианты доставки создаются классом расчёта доставки, который должен установить стоимость и сроки доставки. Вариант доставки не может иметь класс расчёта доставки и условия.
Коллекция способов доставки — коллекция nc_netshop_delivery_method_collection
, содержащая способы и/или варианты доставки.
my_delivery_service
), расширяющий класс nc_netshop_delivery_service
.calculate_delivery()
(см. ниже).spl_autoload_register()
, или в модуле default в function.inc.php
подгружать этот класс.
Допустим, класс my_delivery_service
находится в файле netcat/modules/default/my_delivery_service.class.php
, тогда автозагрузчик этого класса в netcat/modules/default/function.inc.php
будет выглядеть следующим образом:
// Загрузка класса my_delivery_service при необходимости spl_autoload_register(function($class_name) { if ($class_name === 'my_delivery_service') { include_once nc_module_folder('default') . 'my_delivery_service.class.php'; } });
ShopDeliveryService
(«Службы доставки») добавить элемент:Все стандартные свойства являются защищёнными (protected).
string $name
— название службы доставки (произвольный текст).string $delivery_type
— тип доставки, задаётся одной из констант класса nc_netshop_delivery
:
nc_netshop_delivery::DELIVERY_TYPE_COURIER
— курьерская доставкаnc_netshop_delivery::DELIVERY_TYPE_POST
— доставка почтойnc_netshop_delivery::DELIVERY_TYPE_PICKUP
— доставка до пункта выдачиnc_netshop_delivery::DELIVERY_TYPE_MULTIPLE
— возможны несколько типов доставки (определён метод get_variants()
, возвращающий варианты доставки различных типов)array $mapped_fields
— список полей, которым нужны соответствия (для получения полей заказа в методе calculate_delivery()
или get_variants()
). Ключом массива является имя поля, доступное внутри класса в массиве $this->data
, а значением — текстовое описание поля, например:
protected $mapped_fields = array( // в настройках способа доставки нужно будет выбрать источник значения // для поля «город доставки» ($this->data['to_city']): 'to_city' => 'Город доставки', );
boolean $can_provide_multiple_variants
— если true
, значит служба доставки может предложить более одного варианта доставки (определён метод get_variants()
).В простейшем случае для работа класса расчёта доставки достаточно реализовать только метод calculate_delivery()
, остальные методы можно оставить без изменений.
calculate_delivery()
— расчёт стоимости и сроков доставкиДанные о заказе будут доступны в свойстве $this->data
. По умолчанию в этом массиве доступны элементы:
'items'
— состав заказа, экземпляр объекта nc_netshop_item_collection'valuation'
— стоимость товаров в заказе'weight'
— сумма по полю Weight для всех товаров в заказе. Если сумма по полю Weight равна 0, вес будет равен 100 (грамм), так как внешние службы расчёта стоимости доставки не позволяют рассчитывать вес отправления с нулевым весом. Вес в поле Weight должен быть указан в граммах.'size1'
, 'size2'
, 'size3'
— габариты общей упаковки товаров в заказе в сантиметрах. Значения вычисляются суммированием значений свойств товаров PackageSize1
PackageSize2
и PackageSize3
с подбором оптимального размера общей упаковки. Для каждого товара без указания габаритов упаковки будут взяты габариты, указанные в настройках модуля («Размер упаковки товара по умолчанию»). Размеры у товаров и в настройках модуля должны быть заданы в сантиметрах.$mapped_fields
.Метод calculate_delivery()
должен вернуть массив со свойствами:
'price' => стоимость доставки, 'currency' => валюта стоимости доставки, 'min_days' => минимальное количество дней на доставку, 'max_days' => максимальное количество дней на доставку
В случае возникновения ошибки при расчёте и невозможности выдачи правильной оценки доставки нужно вернуть null
и установить два свойства у экземпляра класса:
$this->last_error = 'Описание ошибки'; $this->last_error_code = код_ошибки; // например, 1
/** * Заготовка для класса расчёта доставки */ class my_delivery_service extends nc_netshop_delivery_service { /** @var array Свойства, которые сопоставляются с полями заказов */ protected $mapped_fields = array( 'to_city' => 'Город доставки', ); /** * Метод расчёта стоимости доставки */ public function calculate_delivery() { // В нашем примере доставка стоит 500 руб. плюс 10 руб. за каждый неполный // килограмм веса посылки плюс 0,1% от стоимости товаров $weight_in_kilograms = ceil($this->data['weight'] / 1000); $delivery_cost = 500 + 10 * $weight_in_kilograms + $this->data['valuation'] * 0.001; // итоговая стоимость к оплате будет округлена // в соответствии с настройками модуля // В нашем примере доставка в Москву и Санкт-Петербург заказ доставляется // за 1 день, а доставка в другие города занимает от 3 до 5 дней if ($this->data['city'] == 'Москва' || $this->data['city'] == 'Санкт-Петербург') { $min_days = 1; $max_days = 1; } else { $min_days = 3; $max_days = 5; } return array( 'price' => $delivery_cost, 'currency' => 'RUR', 'min_days' => $min_days, 'max_days' => $max_days ); } }
get_variants(nc_netshop_delivery_method $method)
— получение вариантов доставкиЕсли служба доставки предлагает различные варианты доставки (с разными типами, стоимостью или сроками), то в классе расчёта доставки:
$can_provide_multiple_variants = true
calculate_delivery()
должен возвращать null
:
public function calculate_delivery() { return null; }
get_variants()
должен возвращать коллекцию nc_netshop_delivery_method_collection
(даже если окажется, что нет доступных вариантов доставки), содержащую объекты nc_netshop_delivery_method_variant
.Метод в качестве аргумента принимает объект nc_netshop_delivery_method
со свойствами способа доставки, заданными в модуле.
Метод всегда должен возвращать коллекцию nc_netshop_delivery_method_collection
.
При подборе доступных способов доставки для заказа (метод matching()
коллекции способов доставки, отбирающий способы доставки по условиям, заданным в настройках модуля) способы доставки с классом расчёта доставки, у которых $can_provide_multiple_variants = true
, заменяются на варианты, возвращаемые методом get_variants()
этого класса.
При замене способа доставки на варианты к вариантам будут применены настройки способа доставки (прибавлена стоимость доставки, установлены дни и время отправки). К идентификатору, указанному у варианта доставки, будет дописан идентификатор способа доставки (чтобы не было конфликта идентификаторов вариантов разных способов доставки).
<?php class my_delivery_service extends nc_netshop_delivery_service { /** @var string тип доставки */ protected $delivery_type = nc_netshop_delivery::DELIVERY_TYPE_MULTIPLE; /** @var bool служба может предложить более одного варианта доставки */ protected $can_provide_multiple_variants = true; /** * Расчёт производится в методе get_variants(). * @return array|null */ public function calculate_delivery() { return null; } /** * @param nc_netshop_delivery_method $method * @return nc_netshop_delivery_method_collection */ public function get_variants(nc_netshop_delivery_method $method) { $delivery_variants = new nc_netshop_delivery_method_collection(); // Доставка курьером $courier_delivery = $this->get_courier_delivery_variant(); $delivery_variants->add($courier_delivery); // Доставка в пункт выдачи $pickup_delivery = $this->get_pickup_delivery_variant(); $delivery_variants->add($pickup_delivery); return $delivery_variants; } /** * Пример метода, возвращающего вариант с информацией о курьерской доставке * @return nc_netshop_delivery_method_variant */ protected function get_courier_delivery_variant() { $courier_delivery = new nc_netshop_delivery_method_variant(array( 'id' => 1, // это может быть внешний идентификатор от службы доставки // (при выводе вариантов к id варианта будет дописан id способа доставки) // id должен быть уникальным в пределах способа доставки 'name' => 'Экспресс-доставка курьером', 'description' => 'Доставка в пределах города в день заказа. Вы можете проверить товар при курьере.', 'delivery_type' => nc_netshop_delivery::DELIVERY_TYPE_COURIER, 'extra_charge_absolute' => 300, // стоимость в рублях 'extra_charge_relative' => 0, // стоимость в процентах от суммы заказа 'minimum_delivery_days' => 0, // 0 — возможна доставка в тот же день 'maximum_delivery_days' => 0, // максимальное число дней на доставку )); return $courier_delivery; } /** * Пример метода, возвращающего вариант доставки в пункт выдачи * @return nc_netshop_delivery_method_variant */ protected function get_pickup_delivery_variant() { // Вариант доставки до пункта выдачи (50 руб., доставка на следующий день) $pickup_delivery = new nc_netshop_delivery_method_variant(array( 'id' => 2, 'name' => 'Доставка в пункты выдачи', 'description' => '', 'delivery_type' => nc_netshop_delivery::DELIVERY_TYPE_PICKUP, 'extra_charge_absolute' => 50, 'extra_charge_relative' => 0, 'minimum_delivery_days' => 1, 'maximum_delivery_days' => 1, )); // Список внешних (не заданных в Netcat, а полученных от службы доставки) // пунктов выдачи в выбранном городе: $delivery_points = new nc_netshop_delivery_point_external_collection(); // Пример объекта с информацией о пункте выдачи заказов $delivery_point = new nc_netshop_delivery_point_external(array( 'id' => 'PVZ-1', // в качестве префикса автоматически будет // добавлен ID варианта доставки 'name' => 'ГУМ', 'description' => 'Первый этаж, 1 линия у фонтана', 'phones' => '+7 495 123-45-67', 'location_name' => 'Москва', 'address' => 'Красная площадь, дом 3', 'latitude' => '55.7547', 'longitude' => '37.6216', 'payment_on_delivery_cash' => true, 'payment_on_delivery_card' => false, // тип пункта выдачи может быть: // nc_netshop_delivery_point::TYPE_PICKUP — обычный ПВЗ // nc_netshop_delivery_point::TYPE_POSTAMAT — постамат 'type' => nc_netshop_delivery_point::TYPE_PICKUP // по умолчанию )); // Расписание работы $delivery_point_schedule = new nc_netshop_delivery_schedule(); // с понедельника по пятницу с 10 до 22 $delivery_point_schedule->add(new nc_netshop_delivery_interval(array( 'day1' => true, 'day2' => true, 'day3' => true, 'day4' => true, 'day5' => true, 'time_from' => '10:00', 'time_to' => '22:00', ))); // в субботу с 10 до 20 с перерывом с 14 до 14:30 $delivery_point_schedule->add(new nc_netshop_delivery_interval(array( 'day6' => true, 'time_from' => '10:00', 'time_to' => '14:00', ))); $delivery_point_schedule->add(new nc_netshop_delivery_interval(array( 'day6' => true, 'time_from' => '14:30', 'time_to' => '20:00', ))); // Устанавливаем расписание у пункта выдачи $delivery_point->set_schedule($delivery_point_schedule); $delivery_points->add($delivery_point); // Устанавливаем пункты выдачи у варианта доставки $pickup_delivery->set_delivery_points($delivery_points); return $pickup_delivery; } }
get_settings_fields()
— дополнительные параметры для настройки классаМетод get_settings_fields()
может использоваться для указания дополнительных полей для настройки способа расчёта доставки, которые будут выводиться на странице редактирования способа доставки.
Метод должен вернуть массив с описанием полей. Структура массива с описанием полей такая же, как для пользовательских настроек макетов и шаблонов компонентов.
Пример:
public function get_settings_fields() { return array( 'param1' => array( 'type' => 'string', 'caption' => 'Параметр 1 (строка)', ), 'param2' => array( 'type' => 'textarea', 'caption' => 'Параметр 2 (текстовый блок)', 'codemirror' => false, ), 'param3' => array( 'type' => 'select', 'subtype' => 'static', 'caption' => 'Параметр 3 (выпадающий список)', 'options' => array( 'value1' => 'значение 1', 'value2' => 'значение 2', ) ), ); }
Параметры для службы доставки, заданные в настройках способа доставки, можно получить методом get_setting()
:
$this->get_setting('param1');