Немного измененный и доработанный вариант акции (20% на 3 товар, 30% на 4 товар).
В данном случае немного изменен принцип применения акции. Если в предыдущем примере акция применялась буквально к каждому 3 и к каждому 4 товару, то в данном случае акция применяется к каждой следующей тройке товаров, ко второму и третьему соответственно. Также сделано экранирование, не учитывать акцию если нет товар из нужной категории, ранее выводились ошибки.
Как и ранее первая скидка применяются к самому дешевому товару и все последующие применяются к товарам с ценой по возрастанию.
Доработано: если у товара несколько категорий и только одна из них должна быть акционной (например stock).
Расчет суммы акции
// Акция 2-20, 3-30
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' );
}
foreach ($terms as $term) {
$terms_slug[] = $term->slug;
}
if ( in_array('stock', $terms_slug) ) { // если категория stock
// создаем столько цен сколько единиц товара
$prices[] = array_fill(0, $cart_item['quantity'], $_product->get_price());
}
}
if (isset($prices)) {
// объединяем в один массив цен
$all_prices = array();
foreach ($prices as $child) {
$all_prices = array_merge($all_prices, $child);
}
sort($all_prices); // цены в порядке возрастания
//print_r($all_prices);
// вычислить количество скидок
if ( count($all_prices) >= 2 ) {
$i = 0;
$n = 0; // период
$actions_count = 0;
foreach ($all_prices as $cus_price) {
$i++;
if ( $i == 2 + 3 * ($n) ) { // число соответствует формуле
$actions_count++;
}
if ($i % 3 == 0) { // кратно 3
$actions_count++;
$n++;
}
}
}
//применить скидки к ценам в порядке возрастания
if ( count($all_prices) >= 2 ) {
$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 );
}
}
}
Вывод уведомления и общей суммы акции
// Вывести информацию о скидке в корзине перед Итого
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' );
}
foreach ($terms as $term) {
$terms_slug[] = $term->slug;
}
if ( in_array('stock', $terms_slug) ) { // если категория stock
// создаем столько цен сколько единиц товара
$prices[] = array_fill(0, $cart_item['quantity'], $_product->get_price());
}
}
if (isset($prices)) {
// объединяем в один массив цен
$all_prices = array();
foreach ($prices as $child) {
$all_prices = array_merge($all_prices, $child);
}
sort($all_prices);
$action_20_count = floor(count($all_prices) / 2 );
$action_30_count = floor(count($all_prices) / 3 );
$actions_count = $action_20_count + $action_30_count;
// Убием каждую 6 скидку т.к. они дублируются на одном товаре (6, 12, 18 и т.д.)
if ($actions_count % 6 == 0) {
$actions_count = $actions_count - ($actions_count / 6);
}
$symbol = get_woocommerce_currency_symbol('RUB');
// определить количество скидок
if ( count($all_prices) >= 2 ) {
$i = 0;
$n = 0; // период
$actions_count = 0;
foreach ($all_prices as $cus_price) {
$i++;
if ( $i == 2 + 3 * ($n) ) { // число соответствует формуле
$actions_count++;
}
if ($i % 3 == 0) { // кратно 3
$actions_count++;
$n++;
}
}
}
// применить скидки
if ( count($all_prices) >= 2 ) {
echo '<div class="discount-message">';
$i = 0;
$n = 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>';
}
}
}
Отображение скидки у каждой позиции в корзине
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' );
}
foreach ($terms as $term) {
$terms_slug[] = $term->slug;
}
if ( in_array('stock', $terms_slug) ) { // если категория stock
// создаем столько цен сколько единиц товаров
for ($i = 1; $i <= $cart_item['quantity']; $i++) {
$prices[] = array(
'cust_id' => $_product->get_ID(),
'cust_price' => $_product->get_price()
);
}
}
}
if (isset($prices)) {
// сортировка 2-х мерного массива по ключу
usort($prices, function($a, $b) {
return $a['cust_price'] <=> $b['cust_price'];
});
$action_20_count = floor(count($prices) / 2 );
$action_30_count = floor(count($prices) / 3 );
$actions_count = $action_20_count + $action_30_count;
// Убием каждую 6 скидку т.к. они дублируются на одном товаре (6, 12, 18 и т.д.)
if ($actions_count % 6 == 0) {
$actions_count = $actions_count - ($actions_count / 6);
}
// определить количество скидок
if ( count($prices) >= 2 ) {
$i = 0;
$n = 0; // период
$actions_count = 0;
foreach ($prices as $cust_price) {
$i++;
//echo 2 + 3 * ($n);
if ( $i == 2 + 3 * ($n) ) { // число соответствует формуле + 3 * ($n - 1)
$actions_count++;
}
if ($i % 3 == 0) { // кратно 3
$actions_count++;
$n++;
}
}
}
// применить скидки
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
);
}
}
}
}
}
if (isset($all_actions_price)) {
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'];
}
}
}
if (isset($results)) {
foreach ($results as $result) {
$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;
}
[site-socialshare]