/ Плагины / Акция 20% на каждый 3 и 30% на каждый 4 товар

Акция 20% на каждый 3 и 30% на каждый 4 товар

30.01.2021

739

Поступила нестандартная задача, реализовать акцию 20% на каждый 3 и 30% на каждый 4 товар. Сложность заключалась в том что скидки 20% и 30% должны были действовать на товары начиная с самого дешевого, т.е. первая скидка (20% за 3 товар) на самый дешевый, далее (30% за 4 товар) на второй товар с конца и т.д. Причем в расчете товаров для акции нужно было учитывать каждую единицу позиций (и количество каждой позиции и количество наименований) в пределах определенной категории.

Основной расчет акции (первая версия)

add_action( 'woocommerce_cart_calculate_fees','wc_custom_surcharge', 10, 1 );
function wc_custom_surcharge( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
		
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
		
		// Условие категории
		
		$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
		
		if ( $_product->get_type() == 'simple' ) {
			
			$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
			
		} elseif ( $_product->get_type() == 'variation' ) {
			
			$variation = wc_get_product($_product->get_ID());
			$varproduct = wc_get_product( $variation->get_parent_id() );
			$terms = get_the_terms( $varproduct->get_ID(), 'product_cat' );
			
		}
		
		if ($terms[0]->slug == 'compact-disc') { // если категория
		
			$prices[] = array(
				'cust_id' => $_product->get_ID(), 
				'cust_price' => $_product->get_price(),
				'cust_quantity' => $cart_item['quantity']
			);
			
			$action_quantity[] = $cart_item['quantity'];
		
		}
		
	}

	//asort($prices); // сортировка массива с сохранением ключей
	//sort($prices); // сортировка массива без сохранения ключей	
	
	// сортировка 2-х мерного массива по ключу
	usort($prices, function($a, $b) {
		return $a['cust_price'] <=> $b['cust_price'];
	});

	$fee_descript = '';
	$fee = 0;

	if (array_sum($action_quantity) == 3 ) {
		
		$fee = $prices[0]['cust_price'] * 0.2;
		$fee_descript = 'Скидка 20% на третий товар';
		
	} elseif (array_sum($action_quantity) >= 4) { 
	
		if (count($prices) == 1) {
			
			$fee = ($prices[0]['cust_price'] * 0.2) + ($prices[0]['cust_price'] * 0.3);
			$fee_descript = 'Скидка 20% на третий и 30% на четвертый товары';
			
		} else {
			
			if ($prices[0]['cust_quantity'] == 1) {
				
				$fee = ($prices[0]['cust_price'] * 0.2) + ($prices[1]['cust_price'] * 0.3);
				$fee_descript = 'Скидка 20% на третий и 30% на четвертый товары';
				
			} else {
				
				$fee = ($prices[0]['cust_price'] * 0.2) + ($prices[0]['cust_price'] * 0.3);
				$fee_descript = 'Скидка 20% на третий и 30% на четвертый товары';
				
			}
			
		}
		
	}

	$cart->add_fee( __($fee_descript, 'woocommerce'), -$fee, true );
}
Различные варианты сортировки:

asort($prices); // сортировка массива с сохранением ключей
sort($prices); // сортировка массива без сохранения ключей	

usort($prices, function($a, $b) { //сортировка 2-х мерного массива по ключу
	return $a['cust_price'] <=> $b['cust_price'];
});

Вывод уведомление о сумме скидки в корзине (первая версия)

В некоторых шаблонах данный вывод не нужен, т.к. в первой функции есть вывод общей суммы скидки, но выводится он в шаблоне Оформление.

add_action( 'woocommerce_before_cart_totals','print_message_wc_custom_surcharge', 7, 1 );

function print_message_wc_custom_surcharge() {
	
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
		
		$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );		
		
		if ( $_product->get_type() == 'simple' ) {
			
			$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
			
		} elseif ( $_product->get_type() == 'variation' ) {
			
			$variation = wc_get_product($_product->get_ID());
			$varproduct = wc_get_product( $variation->get_parent_id() );
			$terms = get_the_terms( $varproduct->get_ID(), 'product_cat' );
			
		}
		
		if ($terms[0]->slug == 'compact-disc') { // если категория
			
			$prices[] = array(
				'cust_id' => $_product->get_ID(), 
				'cust_price' => $_product->get_price(),
				'cust_quantity' => $cart_item['quantity']
			);
			
			$action_quantity[] = $cart_item['quantity'];
		
		}
		
	}

	//asort($prices); // сортировка массива с сохранением ключей
	//sort($prices); // сортировка массива без сохранения ключей	
	
	// сортировка 2-х мерного массива по ключу
	usort($prices, function($a, $b) {
		return $a['cust_price'] <=> $b['cust_price'];
	});
	
	$symbol = get_woocommerce_currency_symbol('RUB');
	
	echo '<div class="discount-message">';

	if (array_sum($action_quantity) == 3 ) {
		
		$skidka = $prices[0]['cust_price'] * 0.2;
		echo '<p>скидка 20% на третий товар: <strong>'.round($skidka, 2).' '.$symbol.'</strong></p>';
		
	} elseif (array_sum($action_quantity) >= 4) { 

		if (count($prices) == 1) {
			
			$skidka = $prices[0]['cust_price'] * 0.2;
			$skidka_2 = $prices[0]['cust_price'] * 0.3;
			echo '<p>скидка 20% на третий товар: <strong>'.round($skidka, 2).' '.$symbol.'</strong></p>';
			echo '<p>скидка 30% на четвертый товар: <strong>'.round($skidka_2, 2).' '.$symbol.'</strong></p>';
			
		} else {
			
			if ($prices[0]['cust_quantity'] == 1) {
				
				$skidka = $prices[0]['cust_price'] * 0.2;
				$skidka_2 = $prices[1]['cust_price'] * 0.3;
				echo '<p>скидка 20% на третий товар: <strong>'.round($skidka, 2).' '.$symbol.'</strong></p>';
				echo '<p>скидка 30% на четвертый товар: <strong>'.round($skidka_2, 2).' '.$symbol.'</strong></p>';
				
			} else {
				
				$skidka = $prices[0]['cust_price'] * 0.2;
				$skidka_2 = $prices[0]['cust_price'] * 0.3;
				echo '<p>скидка 20% на третий товар: <strong>'.round($skidka, 2).' '.$symbol.'</strong></p>';
				echo '<p>скидка 30% на четвертый товар: <strong>'.round($skidka_2, 2).' '.$symbol.'</strong></p>';
				
			}
			
		}
		
	}
	
	echo '</div>';

}

После этого задача была дополнена тем, что нужно было отобразить скидки в каждой строке товара к которому она применяется в виде старой и новой цены. Из-за этого пришлось частично изменить алгоритм.

Также, и что более важно, первая версия функции работала только с 3-м и 4-м товарами, а не с каждым 3 и каждым 4 товаром.

Основной расчет акции (вторая версия)

add_action( 'woocommerce_cart_calculate_fees','wc_custom_surcharge', 10, 1 );
function wc_custom_surcharge( $cart ) {
	
	if ( is_admin() && ! defined( 'DOING_AJAX' ) )
	return;
	
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
		
		$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
		
		if ( $_product->get_type() == 'simple' ) {
			
			$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
			
		} elseif ( $_product->get_type() == 'variation' ) {
			
			$variation = wc_get_product($_product->get_ID());
			$varproduct = wc_get_product( $variation->get_parent_id() );
			$terms = get_the_terms( $varproduct->get_ID(), 'product_cat' );
			
		}
		
		if ($terms[0]->slug == 'compact-disc') { // если категория
		
			// создаем столько цен сколько единиц товара
			$prices[] = array_fill(0, $cart_item['quantity'], $_product->get_price());
		
		}
		
	}	
	
	// объединяем в один массив цен
	$all_prices = array();
	foreach ($prices as $child) {
		$all_prices = array_merge($all_prices, $child);
	}	
	
	sort($all_prices);
	
	$action_20_count = floor(count($all_prices) / 3 );
	$action_30_count = floor(count($all_prices) / 4 );
	$actions_count = $action_20_count + $action_30_count;
	
	// Убием каждую 7 скидку т.к. они дублируются на одном товаре (12, 24, 36 и т.д.)
	if ($actions_count % 7 == 0) {
		$actions_count = $actions_count - ($actions_count / 7);
	}
	
	if ( count($all_prices) >= 3 ) {
		
		$fee_descript = 'Скидка 20% за каждый третий и 30% за каждый четвертый товары';
		$fee = 0;

		$i = 0;	
		
		foreach ($all_prices as $cus_price) {
			
			$i++;
			
			if ($i <= $actions_count) { // соответствует количеству примененных скидок
			
				if ($i % 2 != 0) { // нечетные
				
					$all_actions_price[] = $cus_price * 0.2;
					
				} else {
					
					$all_actions_price[] = $cus_price * 0.3;
					
				}
			
			}
			
		}
		
		$fee = round(array_sum($all_actions_price), 2);
		
		$cart->add_fee( __($fee_descript, 'woocommerce'), -$fee, true );

	}
	
}

В данном случае функция работает на каждый 3 и 4 товары. Также внесена корректировка на каждое 7 срабатывание скидки, т.к. в этот момент происходит дублирование из-за того что каждый 12 товар является и третьи и четвертым (12 шт, 24 шт, 36 и т.д.).

Вывод уведомление о сумме скидки в корзине (вторая версия)

// Вывести информацию о скидке в корзине перед Итого
add_action( 'woocommerce_before_cart_totals','print_message_wc_custom_surcharge', 7, 1 );

function print_message_wc_custom_surcharge() {
	
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
		
		$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
		
		if ( $_product->get_type() == 'simple' ) {
			
			$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
			
		} elseif ( $_product->get_type() == 'variation' ) {
			
			$variation = wc_get_product($_product->get_ID());
			$varproduct = wc_get_product( $variation->get_parent_id() );
			$terms = get_the_terms( $varproduct->get_ID(), 'product_cat' );
			
		}
		
		if ($terms[0]->slug == 'compact-disc') { // если категория
		
			// создаем столько цен сколько единиц товара
			$prices[] = array_fill(0, $cart_item['quantity'], $_product->get_price());
		
		}
		
	}	
	
	// объединяем в один массив цен
	$all_prices = array();
	foreach ($prices as $child) {
		$all_prices = array_merge($all_prices, $child);
	}	
	
	sort($all_prices);
	
	$action_20_count = floor(count($all_prices) / 3 );
	$action_30_count = floor(count($all_prices) / 4 );
	$actions_count = $action_20_count + $action_30_count;
	
	// Убием каждую 7 скидку т.к. они дублируются на одном товаре (12, 24, 36 и т.д.)
	if ($actions_count % 7 == 0) {
		$actions_count = $actions_count - ($actions_count / 7);
	}	
	
	$symbol = get_woocommerce_currency_symbol('RUB');
	
	if ( count($all_prices) >= 3 ) {
		
		echo '<div class="discount-message">';

		$i = 0;	
		
		foreach ($all_prices as $cus_price) {
			
			$i++;
			
			if ($i <= $actions_count) { // соответствует количеству примененных скидок
			
				if ($i % 2 != 0) { // нечетные
				
					$all_actions_price[] = $cus_price * 0.2;
					
				} else {
					
					$all_actions_price[] = $cus_price * 0.3;
					
				}
			
			}
			
		}
		
		$skidka = round(array_sum($all_actions_price), 2);
		
		echo '<p>Скидка 20% за каждый третий и 30% за каждый четвертый товары: <strong><bdi>'.$skidka.' '.$symbol.'</bdi></strong></p>';
	
		echo '</div>';

	}

}
Заполнение массива значениями:

$prices[] = array_fill(0, $cart_item['quantity'], $_product->get_price());

Изменение итоговой суммы по позициям участвующих в акции

add_filter( 'woocommerce_cart_item_subtotal', 'bbloomer_if_coupon_slash_item_subtotal', 99, 3 );
 
function bbloomer_if_coupon_slash_item_subtotal( $subtotal, $cart_item_cus ){
	
	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
		
		$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
		
		if ( $_product->get_type() == 'simple' ) {
			
			$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
			
		} elseif ( $_product->get_type() == 'variation' ) {
			
			$variation = wc_get_product($_product->get_ID());
			$varproduct = wc_get_product( $variation->get_parent_id() );
			$terms = get_the_terms( $varproduct->get_ID(), 'product_cat' );
			
		}
		
		if ($terms[0]->slug == 'compact-disc') { // если категория
		
			// создаем столько цен сколько единиц товаров
			
			for ($i = 1; $i <= $cart_item['quantity']; $i++) {
				$prices[] = array(
					'cust_id' => $_product->get_ID(), 
					'cust_price' => $_product->get_price()
				);
			}
		
		}
		
	}
	
	// сортировка 2-х мерного массива по ключу
	usort($prices, function($a, $b) {
		return $a['cust_price'] <=> $b['cust_price'];
	});

	$action_20_count = floor(count($prices) / 3 );
	$action_30_count = floor(count($prices) / 4 );
	$actions_count = $action_20_count + $action_30_count;
	
	// Убием каждую 7 скидку т.к. они дублируются на одном товаре (12, 24, 36 и т.д.)
	if ($actions_count % 7 == 0) {
		$actions_count = $actions_count - ($actions_count / 7);
	}
	
	if ( count($prices) >= 3 ) {

		$i = 0;	
		
		foreach ($prices as $cust_price) {
			
			$i++;
			
			if ($i <= $actions_count) { // соответствует количеству примененных скидок
			
				if ($i % 2 != 0) { // нечетные
				
					$all_actions_price[] = array (
						'cust_id' => $cust_price['cust_id'], 
						'cust_action' => $cust_price['cust_price'] * 0.2						
					);
					
				} else {
					
					$all_actions_price[] = array (
						'cust_id' => $cust_price['cust_id'], 
						'cust_action' => $cust_price['cust_price'] * 0.3						
					);
					
				}
			
			}
			
		}

	}	
	
	foreach ($all_actions_price as $row) {
		
		if ( !isset( $results[$row['cust_id']] ) ) {
			$results[$row['cust_id']] = $row;
		} else {
			$results[$row['cust_id']]['cust_action'] .= ',' . $row['cust_action'];
		}
		
	}
	
	foreach ($results as $result) {

		//количество применений акции к каждой позиции
		//$action_quantity = substr_count($result['cust_action'], ',') + 1;
		
		// можно собрать красивый массив
		//$product_action[$result['cust_id']] = array_sum( explode( ',', $result['cust_action'] ) );
		
		$line_total_discount = array_sum( explode( ',', $result['cust_action'] ) );
		
		if ( $cart_item_cus['data']->get_ID() == $result['cust_id'] ) {
			
			$line_total = $cart_item_cus['data']->get_price() * $cart_item_cus['quantity'];
			
			$newsubtotal = wc_price( $line_total - $line_total_discount ); 
			$subtotal = sprintf( '<del>%s</del> %s', $subtotal, $newsubtotal ); 
		}
		
	}

	return $subtotal;
}

Данная функция создана на основе решения Rodolfo Melogli об предварительном показе цены со скидкой (купоном) и не влияющем на сумму корзины:

add_filter( 'woocommerce_cart_item_subtotal', 'bbloomer_if_coupon_slash_item_subtotal', 99, 3 );
 
function bbloomer_if_coupon_slash_item_subtotal( $subtotal, $cart_item, $cart_item_key ){
	global $woocommerce;
	 
	// Note: use your own coupon code here
	$coupon_code = 'barmada'; 
	 
	if ( $woocommerce->cart->has_discount( $coupon_code )) {
	 
		// Note: apply your own coupon discount multiplier here
		// In this case, it's a 99% discount, hence I multiply by 0.01
		$newsubtotal = wc_price( $cart_item['data']->get_price() * 0.01 * $cart_item['quantity'] ); 
		 
		$subtotal = sprintf( '<s>%s</s> %s', $subtotal, $newsubtotal ); 
	}
	 
	return $subtotal;
}

Поделиться в соц. сетях:

  • Похожие записи
  • Комментарии
  • Вложения
Watermark для изображений товаров (обзор плагинов)

Watermark для изображений товаров (обзор плагинов)

Рассмотрим различные плагины по добавлению водяного знака (watermark) на изображения товаров. WooCommerce Products Image Watermark (BeRocket) Плагин не понравился. Логотип добавляется только одним способом, с указанием положения. Можно перезагрузить загруженные Читать далее »

Настройка вывода подкатегорий товаров

Настройка вывода подкатегорий товаров

При варианте вывода в категориях товаров, в не зависимости есть ли подкатегории или нет, для более точного подбора товаров можно выводить до товаров подкатегории. При этом сделать это можно довольно Читать далее »

Шорткод вывода товаров по метке

Шорткод вывода товаров по метке

Иногда требуется быстро вывести товары с определенной меткой. Данный шорткод проверял лично — работает. В данной функции предусмотрен вывод товаров по колонкам (wc_get_loop_prop( ‘columns’ )). Шорткод выглядит так: Данный шорткод Читать далее »

/

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

Пока нет комментариев. Будь первым!

Акция 20% на каждый 3 и 30% на каждый 4 товар Акция 20% на каждый 3 и 30% на каждый 4 товар
Фильтр по наличию
Рекомендации для васФильтр по наличиюOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.