Модуль Commerce EMS

22 марта 2013 - 1:51

Написал модуль Commerce EMS для Drupal Commerce - добавляет метод доставки EMS Russian Post.

Оформление заказа
Оформление заказа

Описание:

  • Расчет доставки только по России
  • Модуль использует для расчета api EMS: http://emspost.ru/corp_clients/dogovor_docements/api.php
    - ems.get.locations - для вывода всех возможных точек доставки (сначала идут города далее регионы), и точек отправления (настраивается на странице администрирования)
    - ems.get.max.weight - для определения максимального веса пакета, больше этого значения заказать за один раз заказать нельзя. Вес по умолчанию задается на странице администрирования.
    - ems.calculate - для расчета стоимости и времени доставки
  • Поддерживает 2 типа доставки: Обычная доставка и с объявленной ценностью (в этом случае к стоимости доставки прибавляется 1% стоимости заказываемого товара)

Использование:

Страница администрирования модуля
Страница администрирования модуля

На Страница администрирования модуля можно задать город откуда будут доставляться посылки (по умолчанию Москва); вес отправления по умолчанию (0.5 кг).

Хуки:

  • Для подсчета веса определен hook_commerce_ems_calculate_product_weight_alter(&$unit_weight, $order, $line_item), пример:
    function mymodule_commerce_ems_calculate_product_weight_alter(&$unit_weight, $order, $line_item) {
      $product = entity_metadata_wrapper('commerce_line_item', $line_item)->commerce_product;
      if ($product->type->value() == 'product') {
        $unit_weight = $product->[your_product_field_weight_name]->value();
      }
    }
  • hook_commerce_ems_service_details_form_validate($details_form, $details_values) - валидация значений формы

Шаблоны:

commerce-ems-service-details-note.tpl.php шаблон вывода стоимости и времени доставки:

<?php
/**
 * @file
 * Template file ems service details note.
 *
 * Available variables:
 * - $formatted_price - formatted price on delivery
 * - $period - delivery period
 */

?>
<div class="commerce-ems-service-details-note">
  <?php print t('EMS shipping price: @formatted_price', array('@formatted_price' => $formatted_price)); ?>, <?php print t('shipping period: @period', array('@period' => format_plural($period, '1 day', '@count days'))); ?>
</div>

 

Поля:

Модуль создает поле (extra field) для заказа, которое содержит значение метода доставки,
в случае ems еще и детали:

Поле заказа

Токены:

Так же доступны 2 токена:
[commerce-order:order-shipping-method] - метод доставки, если ems, то с деталями
[commerce-order:order-shipping-method-amount] - стоимость доставки

Вопросы, предложения, замечания можно писать в комментариях, либо мне на почту.

Да, чуть не забыл:
Скачать модуль можно здесь
Пример работы посмотреть здесь

Сказать спасибо:

Яндекс.Деньги: 41001626521447
WMZ: Z362159253433
WMR: R134790704550

Прикрепленные файлы: 

Комментарии

Аватар пользователя Garik

Не могли бы вы объяснить как вы через AJAX обновляете стоимость доставки? Дело в том, что я пишу свой модуль, взяв за основу commerce_shipping_example. Хочу в commerce_shipping_example_service_details_form добавить поле с селектом и в него добавить AJAX. Типо если выбран вариант 1, то выводит то-то.. Обычно в других ф-ях с формой я отслеживаю изменеия по $form_state, но в ф-ии commerce_shipping_example_service_details_form эта переменная не фигурирует и я не могу понять как менять значения формы по AJAX.

Аватар пользователя admin

Добрый день, Вы можете в своем #ajax callback использовать ajax framework, что дает достаточную гибкость, пример:

//функция commerce_shipping_example_service_details_form
function commerce_shipping_example_service_details_form($pane_form, $pane_values, $checkout_pane, $order, $shipping_service) {
........
  $ajax = array(
    'callback' => 'commerce_service_details_ajax_reload',
    'event' => 'change',
    'progress' => array('type' => 'throbber', 'message' => t('Change form...')),
  );
//#ajax select
  $form['ajax_select'] = array(
    '#type' => 'radios',
    '#title' => t('Select type'),
    '#options' => array(
      '0' => t('Type 1'),
      '1' => t('Type 2'),
    ),
    '#default_value' => 0,
    '#ajax' => $ajax
  );
........
}
function commerce_service_details_ajax_reload(&$form, &$form_state) {
  ...
  //Change form
........
 $form_state['rebuild'] = TRUE;
  $commands = array();
  $commands[] = ajax_command_replace('.commerce-checkout-cart-checkout-form', drupal_render($form));
  return array('#type' => 'ajax', '#commands' => $commands);
}

Либо вы можете использовать обычный wrapper в аякс селекте:

function commerce_shipping_example_service_details_form($pane_form, $pane_values, $checkout_pane, $order, $shipping_service) {
........
  $ajax = array(
    'callback' => 'commerce_service_details_ajax_reload',
    'event' => 'change',
    'wrapper' => 'my-form-id'
    'progress' => array('type' => 'throbber', 'message' => t('Change form...')),
  );
//#ajax select
  $form['ajax_select'] = array(
    '#type' => 'radios',
    '#title' => t('Select type'),
    '#options' => array(
      '0' => t('Type 1'),
      '1' => t('Type 2'),
    ),
    '#default_value' => 0,
    '#ajax' => $ajax
  );
........
}

function commerce_service_details_ajax_reload(&$form, &$form_state) {
  //Change form
  return $form;
}

Аватар пользователя Garik

Ага, вот я обычно 2й вариант и использую. Как в этом случае, например, при выборе в селекте "Type 2", вывести текст "You are select the Type 2"?

Я это представляю примерно так:

function commerce_shipping_example_service_details_form($pane_form, $pane_values, $checkout_pane, $order, $shipping_service) {
..........
if ([что-то что получило и хранит выбранный вариант из селекта] == 1) {
$form['contact_information'] = array(
'#markup' => t('You are select the Type 2'),
);
}
.....
}

Вот собственно что же хранит-то введенные данные?

Аватар пользователя admin

$form_state['input']

Аватар пользователя Garik

Так $form_state в commerce_shipping_example_service_details_form не передается же.

Аватар пользователя admin

еще как передается и даже работает)
обратите внимание на аргументы функции ajax колбэка из моего примера, второй параметр $form_state:

function commerce_service_details_ajax_reload(&$form, &$form_state) {
  //Change form
  return $form;
}

сделайте так:

function commerce_service_details_ajax_reload(&$form, &$form_state) {
  //Change form
  return print_r($form_state['input'], 1);
}
Аватар пользователя Гость

да, в ф-ю ajax_reload передается $form_state с выбранными параметрами, а обратно в details_form уже нет.. Я пробовал в ajax_reload менять значения $form в надежде что она вернется и поменяет-таки то что мне надо, но нифига.. Единственное, как мне кажется, что возвращает в ф-ю details_form в вашем модуле это $_session, по которому уже отслеживаются изменеия.

Аватар пользователя Murz

Огромное спасибо за модуль! Планируется ли его выложить в официальный репозиторий на drupal.org?
И реально ли что-то подобное сделать для обычной почты России? По-идее там есть API для рассчета, например сайт russianpostcalc.ru как-то считает сумму.

Аватар пользователя admin

Добрый день, спасибо, модуль пока в песочнице. Следующим этапом, планировал ввести подсчет международных отправлений.
Не думал пока насчет russianpostcalc.ru, для нее есть описание API?

Аватар пользователя Murz

А можно ссылку на песочницу? ;) А то закачал архив, а хотелось бы оперативно обновления проверять и закачивать.

У russianpostcalc.ru нет API, мой сайт пока их просто тупо парсит напрямую html-ответ. Но с ними я думаю можно пообщаться по этому поводу, они же где-то эту информацию берут, значит существует API.

И ещё вопрос - можно ли модулю передать название города через API, а то у меня посетитель его заполняет в другом поле до того как выбирает доставку, получается дважды нужно ему выбирать.

ЗЫ: кстати а как-то можно подписаться на уведомления о новых камментах по email?

Аватар пользователя Гость

да
международного подсчета не хватает
сколько надо на поддержку модуля?

Аватар пользователя admin

Прошу прощения за задержку ссылка на песочницу https://drupal.org/sandbox/dimitr.semenov/2078953

И ещё вопрос - можно ли модулю передать название города через API

это вопрос тонкий) нужно продумать правильную реализацию такого функционала (например если пользователь введет город которого нет, либо напишет с ошибкой и т.д.), тоже думал об этом.

ЗЫ: кстати а как-то можно подписаться на уведомления о новых камментах по email?

добавил

Аватар пользователя oleg

Добрый вечер, подскажите а куда вставлять хук подсчета веса.

Аватар пользователя oleg

Добрый день, подскажите пожалуйста!
Вопрос по модулю, подскажите куда вставлять хук подсчета веса, чтобы рассчитывался вес заказа и соответственно менялась цена доставки по тарифам EMS ?
С помощью модуля Physical Fields - 7.x-1.x-dev, в типе продукты создал поле с меткой - weight, машинное имя - field_weight , Тип поля - Physical weight, Виджет - Weight textfield.
Куда вставлять hook_commerce_ems_calculate_product_weight_alter(&$unit_weight, $order, $line_item)

function mymodule_commerce_ems_calculate_product_weight_alter(&$unit_weight, $order, $line_item) {
$product = entity_metadata_wrapper('commerce_line_item', $line_item)->commerce_product;
if ($product->type->value() == 'product') {
$unit_weight = $product->[field_weight]->value();
}
}

Аватар пользователя oleg

Добрый день подскажите, не могу разобраться
при расчете стоимости доставки пишет ошибку entity metadata wrapper: unknown data property field_weight
Магазин развернут из коробки commerce kickstart
1.В типе материала, машинное имя Shoes, создал поле: Машинное имя - field_weight, тип поля - Десятичное число, Виджет - текстовая строка. По умолчанию поставил число 5
2. создал модуль Mymodul, вставил код хука:
<?php
function mymodule_commerce_ems_calculate_product_weight_alter(&$unit_weight, $order, $line_item) {
$product = entity_metadata_wrapper('commerce_line_item', $line_item)->commerce_product;
if ($product->type->value() == 'shoes') {
$unit_weight = $product->field_weight->value();
}
}

где указал свой тип материала Shoes и прописал название поля для веса field_weight
надеюсь все верно?
и Вот при расчете товара из типа материала Shoes выдает ошибку, подскажите пожалуйста, где мне надо что-то поправить?
С уважением, Олег.