Онлайн-руководство разработчика NetCat
Новогодние скидки до 25%!
Подробнее
Модуль «Поиск по сайту» 12.2.1Начало работы с модулем 12.2.2Язык запросов 12.2.3Способы хранения индекса 12.2.4Интерфейс модуля в панели управления сайтом 12.2.5Области индексирования 12.2.6Области HTML-страниц 12.2.7Области поиска на сайте 12.2.8Индексирование по расписанию, запуск индексирования в фоновом режиме 12.2.9Правила индексирования 12.2.10Постановка задачи переиндексирования в очередь 12.2.11Интеграция модуля в макеты дизайна сайта 12.2.12Простая форма поиска 12.2.13Расширенная форма поиска 12.2.14Вывод результатов поиска 12.2.15Стилизация списка подсказок 12.2.16Расширенные настройки 12.2.17Разработка расширений модуля 12.2.18Обзор архитектуры модуля 12.2.19Обработчики документов различных типов 12.2.20Текстовые фильтры 12.2.21Анализаторы текста 12.2.22Корректировщики запросов 12.2.23Подключение других поисковых систем 12.2.24Решение проблем с поиском 12.2.25Решение проблем с индексированием 12.2.26Справочник API

Классы расчёта доставки

Если возникает необходимость расчёта стоимости доставки для способов, которые не поддерживаются системой «из коробки», вы можете создать собственный класса для расчёта стоимости и сроков доставки.

Описание классов актуально для версии 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, содержащая способы и/или варианты доставки.

Действия, необходимые для подключения нового способа расчёта доставки

  1. Создать класс (далее для примера он будет называться my_delivery_service), расширяющий класс nc_netshop_delivery_service.
    Для расчёта стоимости достаточно реализовать метод calculate_delivery() (см. ниже).
  2. Обеспечить доступность этого класса по необходимости: например, написать функцию-загрузчик по требованию для 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';
        }
    });
            
  3. В списке ShopDeliveryService («Службы доставки») добавить элемент:
    название — «Мой способ доставки»
    значение — "my_delivery_service" (имя класса для расчёта доставки)
  4. В настройках модуля «Интернет-магазин» добавить новый способ доставки, выбрать способ автоматического расчёта доставки − «Мой способ доставки».

Свойства класса доставки

Все стандартные свойства являются защищёнными (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) — получение вариантов доставки

Если служба доставки предлагает различные варианты доставки (с разными типами, стоимостью или сроками), то в классе расчёта доставки:

  1. Должно быть установлено свойство $can_provide_multiple_variants = true
  2. Метод calculate_delivery() должен возвращать null:
    public function calculate_delivery() {
        return null;
    }
  3. Метод 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');
Описание проекта