Модуль 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 выдает ошибку, подскажите пожалуйста, где мне надо что-то поправить?
С уважением, Олег.

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

В общем юзанул ваш модуль, после чего полетело много всего на сайте, полетели модули, отключились, jQuery вырубило, кэш перестал чиститься выводило ошибку 500, полетели куча ошибок, интересно, почему так?
сейчас все устранил, но все же хочется знать, в чем могла быть причина..? сайт работал до установки вашего модуля

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

В общем юзанул ваш модуль, после чего полетело много всего на сайте, полетели модули, отключились, jQuery вырубило, кэш перестал чиститься выводило ошибку 500, полетели куча ошибок, интересно, почему так?
сейчас все устранил, но все же хочется знать, в чем могла быть причина..? сайт работал до установки вашего модуля