Акция 3 товар бесплатно

Привет! Подскажите есть ли какой-то готовый функционал чтобы сделать акцию третий товар в подарок.

Получается так что если человек добавил 3 товара или более в корзину то самый дешевый товар из этого идет бесплатно.

Возможно есть готовые модули для этого?

Есть готовый модуль у simtechdev

Если вы про “Special Offer:Buy X Get Y” то это не совсем тот функционал что нужен)

Удалось найти решение?
Сами вот ищем (

И нам актуально

А почему бы совместно не заказать написание этого модуля? или здесь такое не практикуется)

Боюсь, на текущем функционале промо акций такого не реализовать, логика текущих промо акций скорее всего не позволит подобной реализации. Так что это будет совершенно другой, отдельной реализацией промо, в результате чего встанет ещё одна, также возможно неразрешимая задача, увязать новую реализацию промо со старой.
Однако если кому то это удастся, я буду в ряду первых, кто будет за подобное решение.

1 лайк

Делал такой функционал *не красивым * способом - прямым редактированием функции fn_promotion_apply_cart_rule. Если интересно, то постараюсь вспомнить и описать подробнее

Да, думаю было бы интересно )
у нас в проекте есть уже попиленые функции , так что это не смущает )

Теоретически можно, но вопрос лицензии модуля от автора.
У нас даже есть запрос стоимости, но клиент не готов пока для такого функционала такую стоимость оплатить (
Выкрутились при помощи веса товара в корзине (при условии, что у остальных товаров вес 0).

Обращаю внимание. Делалось на скорость. Не проверялось на все возможные сочетания промо-акций. Это решение надо выносить в модуль и дорабатывать.
Сам смысл довольно простой. По сути нужно просто создать новый вид бонуса, который можно включать в настройках промо-акции. Будем делать каждый n-й товар бесплатным.

  1. Создаём в схеме app/schemas/promotions/schema.php новый вид бонуса. Ищем в файле описание любого типа бонуса, например, $schema['bonuses']['discount_on_categories']. Вставляем после него свой новый бонус $schema['bonuses']['free_every_n_product'] = array( 'function' => array('fn_promotion_apply_cart_rule', '#this', '@cart', '@auth', '@cart_products'), 'discount_bonuses' => array('number'), 'zones' => array('cart'), 'filter' => 'floatval' );

  2. За применение бонуса отвечает ф-ия fn_promotion_apply_cart_rule. Находим её в файле app/functions/fn.promotions.php .Находим в ней условия применения бонусов и вставляем новое по своему созданному бонусу. Например, вставляем после if ($bonus['bonus'] == 'order_discount') { ...} свой код ` elseif ($bonus[‘bonus’] == ‘free_every_n_product’) {
    $free_products = (int)(count($cart_products) / $bonus[‘discount_value’]);

    $counter = 0;
    $bonus_free = $bonus;

    $bonus_free[‘discount_bonus’] = ‘by_percentage’;
    $bonus_free[‘discount_value’] = 100;
    $cart_products = fn_my_changes_array_sort($cart_products,‘price’, SORT_ASC); //!important fn_my_changes_array_sort is in my-changes module

     foreach ($cart_products as $k => $v) {
         if ( ++$counter > $free_products ) break;
            
             if (!isset($cart_products[$k]['promotions'])) {
                 $cart_products[$k]['promotions'] = array();
             }
    
             if (isset($cart['products'][$k]['extra']['promotions'][$bonus['promotion_id']])) {
                 $cart_products[$k]['promotions'][$bonus['promotion_id']] = $cart['products'][$k]['extra']['promotions'][$bonus['promotion_id']];
             }
             
             if (!isset($cart_products[$k]['promotions'][$bonus['promotion_id']])
                 && fn_promotion_apply_discount($bonus['promotion_id'], $bonus_free, $cart_products[$k], true, $cart, $cart_products)
             ) {
                 $cart['use_discount'] = true;
             }        
     }
    

    }. Что тут происходит. По сути нам нужно на каждый n-й товар сделать скидку 100%). Само собой, сортируем сначала товары по стоимости, чтобы сделать скидку на товары с самой низкой стоимостью в корзине. Для сортировки сделал свою ф-ию fn_my_changes_array_sort, к-я сортирует массивы любой степени вложенности по нужному полю. (Возможно в движке есть готовая, её не нашёл). Ф-ию вынес в модуль my_changes. Её добавляем в файл app/addons/my_changes/func.php Код :function fn_my_changes_array_sort($array, $on, $order=SORT_ASC)
    {
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
    foreach ($array as $k => $v) {
    if (is_array($v)) {
    foreach ($v as $k2 => $v2) {
    if ($k2 == $on) {
    $sortable_array[$k] = $v2;
    }
    }
    } else {
    $sortable_array[$k] = $v;
    }
    }

     switch ($order) {
         case SORT_ASC:
             asort($sortable_array);
         break;
         case SORT_DESC:
             arsort($sortable_array);
         break;
     }
    
     foreach ($sortable_array as $k => $v) {
         $new_array[$k] = $array[$k];
     }
    

    }

    return $new_array;
    }`
    3.Не забываем зарегистрировать в админке языковую переменную promotion_bonus_free_every_n_product = Каждый n-ый товар бесплатно. Чистим кэш.

  3. Код сюда вставляется кривовато, следите за скобками и запятыми)

2 лайка

Товар 1 = $100 - 1 шт
Товар 2 = $100 - 1 шт
Товар 3 = $80 - 5 шт

Сортируя по цене не получится Товар 3 = $80 - 5 шт = $400 в подарок? ))

Само собой это не универсальное решение. А делалось под конкретную бизнес-логику. Я поэтому сразу и написал, что нужно дорабатывать. Не вижу проблем в вашем случае повесить ещё условие проверять кол-во товаров и делать скидку не на всю группу. На общую схему добавления промо-кода это не влияет))

1 лайк

Для интереса, поправил для такого случая. Всего-то нужно поменять и поправить пару строк. В итоге для fn_promotion_apply_cart_rule `elseif ($bonus[‘bonus’] == ‘free_every_n_product’) {

$free_products = (int)($cart['amount'] / $bonus['discount_value']);

$counter = 1;
$bonus_free = $bonus;

$bonus_free['discount_bonus'] = 'by_percentage';
$bonus_free['discount_value'] = 100;
$cart_products =  fn_my_changes_array_sort($cart_products,'price', SORT_ASC); //!important fn_my_changes_array_sort is in my-changes module 

    foreach ($cart_products as $k => $v) {

        if ( $counter > $free_products ) break;
        $counter +=  $v['amount'];
        if ($v['amount'] >=  $free_products) {
            $bonus_free['discount_value'] = (int)(100 * $free_products / $v['amount']);
        }  else {
                $free_products -= $v['amount'];
                $counter -=  $v['amount'];
            }


            if (!isset($cart_products[$k]['promotions'])) {
                $cart_products[$k]['promotions'] = array();
            }

            if (isset($cart['products'][$k]['extra']['promotions'][$bonus['promotion_id']])) {
                $cart_products[$k]['promotions'][$bonus['promotion_id']] = $cart['products'][$k]['extra']['promotions'][$bonus['promotion_id']];
            }
            
            if (!isset($cart_products[$k]['promotions'][$bonus['promotion_id']])
                && fn_promotion_apply_discount($bonus['promotion_id'], $bonus_free, $cart_products[$k], true, $cart, $cart_products)
            ) {
                $cart['use_discount'] = true;
            } 
    }
}`
4 лайка

Мега-респект! Будем пробовать, внедрять и допиливать!

Было бы круто, если бы кто-то оформил в модуль. Думаю, он был бы востребованным.