Если возникает необходимость расчёта стоимости доставки для способов, которые не поддерживаются системой «из коробки», вы можете создать собственный класса для расчёта стоимости и сроков доставки.
Описание классов актуально для версии 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 = truecalculate_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');