Drupal → Программно добавить скидку к заказу

18.12.2015

Ранее показывал как добавлять скидки к заказу из админки. Сейчас покажу как это же можно сделать программно.

Пример добавления скидки в $10 для заказов с числом товаров больше 5:

/**
 * Implements hook_commerce_order_presave().
 */
function MODULENAME_commerce_order_presave($order) {
  $order_wrap = entity_metadata_wrapper('commerce_order', $order);
  $line_items_quantity = commerce_line_items_quantity($order_wrap->commerce_line_items, commerce_product_line_item_types());

  if ($line_items_quantity > 5) {
    $discount = array(
      'amount' => 1000, // cents
      'currency_code' => 'USD',
    );

    $order_total = $order_wrap->commerce_order_total->value();

    // Convert discount currency
    if ($discount['currency_code'] != $order_total['currency_code']) {
      $discount['amount'] = commerce_currency_convert($discount['amount'], $discount['currency_code'], $order_total['currency_code']);
      $discount['currency_code'] = $order_total['currency_code'];
    }

    $order_wrap->commerce_order_total->amount = $order_total['amount'] - $discount['amount'];
    $order_wrap->commerce_order_total->data = commerce_price_component_add($order_total, 'discount', $discount, TRUE);
  }
}
Написанное актуально для
Commerce 1
Похожие записи

Комментарии

Гость
16.05.2016, 14:06

как сделать что бы скидка срабатывала только определенных товаров?

Ольга
11.08.2016, 18:45

xandeadx, может вы подскажите, как реализовать подобное вне хука commerce_order_presave()? Дело в том, что этот хук срабатывает ДО того как пользователь заполнит форму на странице checkout, а мне надо чтобы срабатывало ПОСЛЕ, по нажатию кнопки submit. Навешиваю на кнопку свой обработчик, пишу аналогичный код, но не работает.

function commerce_my_checkout_mysubmit(&$form, &$form_state) {
  $order = commerce_order_load($form_state['order']->order_id);
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $line_items_quantity = commerce_line_items_quantity($order_wrapper->commerce_line_items, commerce_product_line_item_types());
 
  if ($line_items_quantity > 5) {
    $discount_decimal = 500;
    $discount_currency_code = 'RUB';
 
    $order_total = $order_wrapper->commerce_order_total->value();
    $discount_amount = commerce_currency_decimal_to_amount($discount_decimal, $discount_currency_code);
    $discount_amount = commerce_currency_convert($discount_amount, $discount_currency_code, $order_total['currency_code']);
 
    $order_wrapper->commerce_order_total->amount = $order_total['amount'] - $discount_amount;
    $order_wrapper->commerce_order_total->data = commerce_price_component_add($order_total, 'discount', array(
      'amount' => $discount_amount,
      'currency_code' => $order_total['currency_code'],
      'data' => array(),
    ), TRUE);
  }
}

просто выполните в нужный момент commerce_cart_order_refresh($order), функция запустит hook_commerce_order_presave.

xandeadx, добрый день, делаю функционал динамического увеличения стоимости заказа на определённую сумму, которую получаю от стороннего API. сумму передаю в _presave() доп.переменной.

кажется, я не совсем понял ваш последний комментарий о commerce_cart_order_refresh($order)

делаю как-то так:

function ajaxcartrefresh_menu(){
	$items = array();
		$items['ajax/change-cart/%/%'] = array(
			'page callback' => 'ajaxcartrefresh_updater',
			'page arguments' => array(2,3),
			'type' => MENU_CALLBACK,
			'access arguments' => array('access content'),  
		);
	return $items;
}

function ajaxcartrefresh_updater($order,$summ){
	commerce_cart_order_refresh($order); //dafuq!
}

function ajaxcartrefresh_commerce_order_presave($order,$summ) {
	$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
	$line_items_quantity = commerce_line_items_quantity($order_wrapper->commerce_line_items, commerce_product_line_item_types());
	
	$discount_decimal = $summ;
	$discount_currency_code = 'RUB';
	
	$order_total = $order_wrapper->commerce_order_total->value();
	$discount_amount = commerce_currency_decimal_to_amount($discount_decimal, $discount_currency_code);
	$discount_amount = commerce_currency_convert($discount_amount, $discount_currency_code, $order_total['currency_code']);
	
	$order_wrapper->commerce_order_total->amount = $order_total['amount'] + $discount_amount;
	$order_wrapper->commerce_order_total->data = commerce_price_component_add($order_total, 'fee', array(
	  'amount' => $discount_amount,
	  'currency_code' => $order_total['currency_code'],
	  'data' => array(),
	),

Боль : когда перехожу по адресу, например mysite.com/ajax/change-cart/11/250, итоговая стоимость заказа не меняется
Вопрос : когда запускать card_order_refresh и как через него передать переменную $summ в _presave?

Сапсибо

сделайте $summ глобальной переменной

Да, спасибо!

Остался только вопрос по commerce_cart_order_refresh — вызывает ли она _commerce_order_presave сама по себе или нужны дополнительные манипуляции?
В документации прямого вызова не нашёл.

Привет!
надо изменить стоимость каждой позиции. делаю так

  $line_wrapper->commerce_unit_price->amount = $price_in_kop;
  $line_wrapper->commerce_unit_price->data = commerce_price_component_add(
    $price_in_kop,
    'base_price',
    array(
      'amount' => $price_in_kop,
      'currency_code' => 'RUB',
      'data' => array(),
    ),
    TRUE
  );

В $line все норм, но не считается сумма заказа http://i.imgur.com/qTLNxcN.png

Её нельзя автоматом подсчитывать?

Это не совсем скида или наценка. Цена зависит от разных мест (даже от значения элементов самой страницы), Т.е. нет какого-то одного правила.
Вообще я делаю форму заказа в один клик и в form_submit делаю вручную заказ. В нем делаю товар. В общем надо будет $order_wrapper->commerce_order_total установить самому?

Только почему так не помогает?

  $order_wrapper->commerce_order_total->amount = $price_in_kop;
  $order_wrapper->commerce_order_total->data = commerce_price_component_add(
    $price_in_kop,
    'base_price',
    array(
      'amount' => $price_in_kop,
      'currency_code' => 'RUB',
      'data' => array(),
    ),
    TRUE
  );

В общем изначально не правильно понимал суть компонентов ))

в итоге получилось так:

  $line_item = commerce_product_line_item_new($product, $quantity, $order->order_id);

  $line_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
  // Устонавливаем цену товара
  $origin_price = $line_wrapper->commerce_unit_price->value()[amount];
  // Высчитываем разницу, чтобы сделать наценку к текущей цене.
  // (чтобы считались верно сумма заказа и т.п.)
  $fee = $price_in_kop - $origin_price;

  $base_price = array(
    'amount' => $fee,
    'currency_code' => 'RUB',
    'data' => array(),
  );
  
  $line_wrapper->commerce_unit_price->amount = $price_in_kop;
  $line_wrapper->commerce_unit_price->data = commerce_price_component_add(
    $line_wrapper->commerce_unit_price->value(),
    'base_price',
    $base_price,
    TRUE
  );
  
  $line_wrapper->field_paint_size->set($paint_size);
  $line_wrapper->field_paint_frame->set($paint_frame);
  $line_wrapper->save();

  commerce_line_item_save($line_item);

Стояла задача сделать динамический расчет стоимости доставки на странице
checkout в зависимости от того какая страна била вибрана пользователем в поле
сгенерированим модулем addressfield
Сделал так:
http://pastebin.com/CYxDNxfQ

Бил би рад если етот комертарий отнести в отдельний пост, может кому то пригодиться
Извиняюсь за такой русский, лень переключать

Гость
31.05.2017, 15:10

Интересно получается, добавляешь наценку на все товары через commerce_cart_line_item_refresh и commerce_product_calculate_sell_price_line_item_alter. Потом добавляешь скидку в commerce_order_presave. Все адеватно отображается и добавляется. А когда после payment , возвращается на сайт, сохраняет ордер со старыми ценами и без дисконта. Самое интересное что если убрать payment, то есть после review сразу complete , то сохраняет заказ адекватно. Не подскажете где искать проблему?Уже целый день ищу...

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