Drupal commerce — скидка для пользователей, быстрый вариант.

Понадобилось добавить скидку для пользователей магазина на основе Drupal Commerce, а так как нужно это довольно часто то я сделал все и экспортировал как фичу в отдельный модуль. А еще добавил пару печенек. Вот так выглядит установка скидки пользователю:

Drupal commerce_user_field_discount установка скидки

Установка скидки на странице управления пользователями

Сначала решил сделать как можно проще, по-этому к профилю пользователя добавил поле список со дробными числами (List float), назвал его field_discount и указал лейблы: 5%, 10%, 15% и 20%, значения для этих лейблов поставил как коэффициент на который буду умножать стоимость, т.е. 0.95, 0.90, 0.85 и 0.80. Дальше на странице управления ценами admin/commerce/config/product-pricing добавил правило по которому стоимость продукта умножается на значение поля. Правило повесил на событие Calculating the sell price of a product, добавил два условия: первое — Entity has field, указал Entity как site:current-user и выбрал поле field_discount, и второе условие — Data value is empty со значением site:current-user:field-discount и поставил галочку Negate. Таким образом будет выполнятся проверка установлено ли у пользователя поле скидки и есть ли в нем значение (последнее ну так, на всякий случай). Дальше добавил действие Multiply the unit price by some amount со значениями Line item = commerce_line_item, Amount = site:current-user:field-discount и Price component type = Discount, а Price rounding mode уже по желанию заказчика, я оставил как есть — округление в большую сторону. Все, правила будут работать, скидки считаться, но чтобы сменить скидку для пользователя нужно заходить в редактирование каждого пользователя и изменять скидку, это не удобно, а еще поле со скидкой пока что сможет изменить любой пользователя !!!, так что я сначала в отдельном модуле добавил право на редактирование поля, дальше это право можно указать отдельным ролям, и ограничил редактирование поля (модуль назвал commerce_user_field_discount, в конце статьи будет ссылка на архив):

/**
 * Implements hook_permission().
 */
function commerce_user_field_discount_permission() {
  $return = array();

  $return['commerce_user_field_discount_administer'] = array(
    'title' => t('Set user discount'),
    'description' => t('Set user discount field'),
  );

  return $return;
}

/**
 * Implements hook_field_access().
 */
function commerce_user_field_discount_field_access($op, $field, $entity_type, $entity, $account) {
  if ($field['field_name'] == 'field_discount') {
    return user_access('commerce_user_field_discount_administer');
  }
  return TRUE;
}

Теперь то все будет работать правильно, и только пользователь с правом указанным в админке сможет редактировать поле скидки.
Но все равно немного не удобно пока устанавливать скидку пользователям, да и чтобы посмотреть тоже нужно каждый раз заходить в редактирование, решил и это исправить, пару хуков и все отлично:

/**
 * Implements hook_user_operations().
 */
function commerce_user_field_discount_user_operations($form = array(), $form_state = array()) {
  $operations = array();
  if (user_access('commerce_user_field_discount_administer')) {
    $field = field_info_field('field_discount');
    $allowed_values = list_allowed_values($field);

    $discounts = array();
    foreach ($allowed_values as $key => $value) {
      $discounts['set_discount-' . $key] = $value;
    }

    if (count($discounts)) {
      $discount_operations = array(
        t('Set discount to the selected users') => array(
          'label' => $discounts,
        ),
      );

      $discount_operations += array(
        t('Remove discount from the selected users') => array(
          'label' => t("Remove discount"),
          'callback' => '_commerce_user_field_discount_multiple_set_discount',
        ),
      );

      $operations += $discount_operations;
    }
  }

  // If the form has been posted, we need to insert the proper data for
  // role editing if necessary.
  if (!empty($form_state['submitted'])) {
    $operation_discount = explode('-', $form_state['values']['operation']);
    $operation = $operation_discount[0];
    if ($operation == 'set_discount') {
      $discount = $operation_discount[1];
      if (user_access('commerce_user_field_discount_administer')) {
        $operations[$form_state['values']['operation']] = array(
          'callback' => '_commerce_user_field_discount_multiple_set_discount',
          'callback arguments' => array($discount),
        );
      }
      else {
        watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
        return;
      }
    }
  }
  return $operations;
}

/**
 * Callback function for admin mass adding/deleting a user role.
 */
function _commerce_user_field_discount_multiple_set_discount($accounts, $discount = NULL) {
  $accounts = user_load_multiple($accounts);
  foreach ($accounts as $account) {
    if ($account !== FALSE) {
      $account_wrapper = entity_metadata_wrapper('user', $account);
      if ($account_wrapper->field_discount !== $discount) {
        $account_wrapper->field_discount->set($discount);
        $account_wrapper->save();
      }
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_user_field_discount_form_user_admin_account_alter(&$form, &$form_state, $form_id) {
  $field = field_info_field('field_discount');
  $allowed_values = list_allowed_values($field);

  $uids = array_keys($form['accounts']['#options']);
  $accounts = user_load_multiple($uids);

  foreach ($accounts as $account) {
    if ($account !== FALSE) {
      $account_wrapper = entity_metadata_wrapper('user', $account);
      $discount = $account_wrapper->field_discount->value();
      $form['accounts']['#options'][$account->uid]['discount'] = isset($allowed_values[$discount]) ? $allowed_values[$discount] : '';
    }
  }

  $header = array();
  foreach ($form['accounts']['#header'] as $key => $value) {
    $header[$key] = $value;
    if ($key == 'roles') {
      $header['discount'] = array('data' => t('Discount'));
    }
  }
  $form['accounts']['#header'] = $header;
}

Теперь все легко и удобно, и выглядит так как на анимации в начале статьи.
Ссылочка на архив drupal_commerce_user_field_discount.tar.gz. Для установки модуля нужен модуль features, так как поля и правила я экспортировал именно им, потому что так быстрее.

Об ошибках или говнокоде сообщайте прямо в комментарии. Если уж совсем ничего не понятно, делай по руководству http://www.drupalcommerce.org/user-guide/discounts-and-coupons. А если совсем лень в чем-то разбираться то просто установи модуль и импортируй фичи.

Drupal commerce — скидка для пользователей, быстрый вариант.: 6 комментариев

  1. Евгений

    Отлично работает, как раз то что нужно! Спасибо!
    Есть один вопрос, разницу в цене видно только в корзине, подскажи, что дописать, что б и на сайте цена отображалась для каждого пользывателя уже со скидкой?

    1. zviryatko Автор записи

      Привет. Посмотри хуки в commerce_price модуле, там должен быть нужный для изменения вывода цены.

  2. romsla

    Расчитывает и отображает скидку только в корзине и в каталоге.
    При оформлении заказа (www.mysite.com/checkout/nomer_zakaza) скидки нет.
    Что может быть?

    Спасибо.

    1. zviryatko Автор записи

      Может rule какой-то нужно еще изменить, думаю дело в них, посмотри как считается цена при оформлении, может там берет оригинальную цену товара, туда и добавь учет скидки.

      1. romsla

        Нет не рул. Не добавлял своих правил, ставил модуль на чистый друпал.
        Версия ядра Друпал 7.36 — не работает
        Версия ядра Друпал 7.38 — работает.

        Обновил версию друпал, ничего дополнительно не делал, все вродь работает.

        Спасибо за модуль. Спасибо за помощь.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *