Drupal Commerce: учим rules работать с полем Price у заказа


47

По умолчанию в drupal commerce через правила Вы можете работать с полем цена у сущности commerce_product. А вот если Вам необходимо достучаться до поля цена у заказа, то тут будут проблемы. Как вариант, можно все операции делать программно. Вот, небольшой пример, как это делать программно - Программно добавить скидку к заказу. Покажу, как научить правила работать с ценой у заказа.

Необходимо добавить свои новые действия... Не будем придумывать велосипед и за основу возьмем уже готовые действия для сущности commerce_product.

function ИМЯМОДУЛЯ_rules_action_info() {
  $actions = array();

  // Prepare an array of arithmetical actions for altering prices.
  $action_types = array(
    'frz_tweaks_commerce_order_price_multiply' => array(
      'label' => t('Multiply the order price by some amount'),
      'amount description' => t('Specify the numeric amount by which to multiply the price.'),
    ),
    'frz_tweaks_commerce_order_price_amount' => array(
      'label' => t('Set the order price to a specific amount'),
      'amount description' => t('Specify the numeric amount to set the price to.'),
    ),
  );

  // Define the action using a common set of parameters.
  foreach ($action_types as $key => $value) {
    $actions[$key] = array(
      'label' => $value['label'],
      'parameter' => array(
        'commerce_order' => array(
          'type' => 'commerce_order',
          'label' => t('Order'),
        ),
        'amount' => array(
          'type' => 'decimal',
          'label' => t('Amount'),
          'description' => $value['amount description'],
        ),
        'component_name' => array(
          'type' => 'text',
          'label' => t('Price component type'),
          'description' => t('Price components track changes to prices made during the price calculation process, and they are carried over from the unit price to the total price of a line item. When an order total is calculated, it combines all the components of every line item on the order. When the unit price is altered by this action, the selected type of price component will be added to its data array and reflected in the order total display when it is formatted with components showing. Defaults to base price, which displays as the order Subtotal.'),
          'options list' => 'commerce_price_component_titles',
          'default value' => 'base_price',
        ),
        'round_mode' => array(
          'type' => 'integer',
          'label' => t('Price rounding mode'),
          'description' => t('Round the resulting price amount after performing this operation.'),
          'options list' => 'commerce_round_mode_options_list',
          'default value' => COMMERCE_ROUND_HALF_UP,
        ),
      ),
      'group' => t('Commerce Order'),
    );
  }
  return $actions;
}

И теперь, собственно, сами действия:

/*
 * Это действие умножает цену на какое-то ваше значение
 *
 */
function frz_tweaks_commerce_order_price_multiply($commerce_order, $amount, $component_name, $round_mode) {
  if (is_numeric($amount)) {
    $wrapper = entity_metadata_wrapper('commerce_order', $commerce_order);
    $unit_price = $wrapper->commerce_order_total->value();

    // Calculate the updated amount and create a price array representing the
    // difference between it and the current amount.

    $current_amount = $unit_price['amount'];
    $updated_amount = commerce_round($round_mode, $current_amount * $amount);

    $difference = array(
      'amount' => $updated_amount - $current_amount,
      'currency_code' => $unit_price['currency_code'],
      'data' => array(),
    );

    // Set the amount of the unit price and add the difference as a component.
    $wrapper->commerce_order_total->amount = $updated_amount;

    $wrapper->commerce_order_total->data = commerce_price_component_add(
      $wrapper->commerce_order_total->value(),
      $component_name,
      $difference,
      TRUE
    );
  }
}

/*
 * А это действие устанавливает цену в какое-то ваше значение.
 * Т.е. в правилах вы сможете сначала вычислить новое значение для своей цены по Вашим формулам,
 * а затем записать его в поле
 */
function frz_tweaks_commerce_order_price_amount($commerce_order, $amount, $component_name, $round_mode) {
  if (is_numeric($amount)) {
    $wrapper = entity_metadata_wrapper('commerce_order', $commerce_order);
    $unit_price = $wrapper->commerce_order_total->value();

    // Calculate the updated amount and create a price array representing the
    // difference between it and the current amount.
    $current_amount = $unit_price['amount'];
    $updated_amount = commerce_round($round_mode, $amount);

    $difference = array(
      'amount' => $updated_amount - $current_amount,
      'currency_code' => $unit_price['currency_code'],
      'data' => array(),
    );

    // Set the amount of the unit price and add the difference as a component.
    $wrapper->commerce_order_total->amount = $updated_amount;

    $wrapper->commerce_order_total->data = commerce_price_component_add(
      $wrapper->commerce_order_total->value(),
      $component_name,
      $difference,
      TRUE
    );
  }
}

Применение на практике: Вариант с предоплатой заказа 50% 

Добавить комментарий
Может быть интересно

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

2
Иногда при разработке сайта появляется необходимость создавать отдельный шаблон для определенной ноды. По умолчанию такой возможности нет, зато можно это прикрутить самостоятельно. Как это сделать? Это можно узнать в данной статье.

В общем, проблема старая и известная. Правда не на всех рейсурсах заметная. При использовании модуля Metatag, на форму редактирования сущностей добавляется вкладка для индивидуального изменения метатегов. И на ней используется браузер токенов.

1
Те, кто использует модуль Double field могли заметить, что в текстовой области отсутствует редактор. Бывают случаи, когда для удобства наполнения он просто необходим.
1
Допустим, есть словарь с терминами (недавно с ними работал, поэтому с них и начну). У терминов есть дополнительные поля. Мы хотим получить список терминов, у которых значение поля имеет определенное значение.
1