Совместимость с плагином woocommerce-subscriptions - Компьюти
Logo КОМПЬЮТИ

Совместимость с плагином woocommerce-subscriptions

Время чтения: 4 мин. 227 просмотров

Данное решение для тех кто использует плагин подписок для woocommerce https://woocommerce.com/products/woocommerce-subscriptions/

Спасибо пользователю @avsalexandra за предоставленное решение.

Проблема: при активированном плагине woocommerce-subscriptions не работает списание баллов.

Решение: добавить в файл functions.php вашей темы код:

 function avs_bfw_bonus_coupon_raw() {
    $opts = get_option('bonus_option_name');
    return isset($opts['bonus-points-on-cart']) ? (string) $opts['bonus-points-on-cart'] : '';
}
function avs_bfw_bonus_coupon_lc() {
    $raw = avs_bfw_bonus_coupon_raw();
    return $raw !== '' ? wc_strtolower( trim( $raw ) ) : '';
}
 
/** Признаки подписок */
function avs_is_subscription_product( $product ) {
    if ( ! $product ) return false;
    $type = is_callable([$product,'get_type']) ? $product->get_type() : '';
    if ( in_array( $type, ['subscription','subscription_variation','variable-subscription'], true ) ) return true;
    if ( function_exists('wcs_is_subscription') && wcs_is_subscription( $product ) ) return true;
    return false;
}
function avs_cart_contains_subscription() {
    if ( ! function_exists('WC') || ! WC()->cart ) return false;
    foreach ( WC()->cart->get_cart() as $item ) {
        $product = $item['data'] ?? null;
        if ( avs_is_subscription_product( $product ) ) return true;
    }
    return false;
}
function avs_cart_is_subscription_renewal() {
    return function_exists('wcs_cart_contains_renewal') && wcs_cart_contains_renewal();
}
 
/** Снимаем хук плагина, создающий рекурсию */
function avs_detach_bfw_add_fee() {
    if ( class_exists('BfwPoints') ) {
        $cb   = ['BfwPoints','bfwoo_add_fee'];
        $prio = has_action( 'woocommerce_cart_calculate_fees', $cb );
        if ( false !== $prio ) remove_action( 'woocommerce_cart_calculate_fees', $cb, $prio );
    }
}
add_action( 'plugins_loaded', 'avs_detach_bfw_add_fee', 9999 );
add_action( 'init',           'avs_detach_bfw_add_fee', 9999 );
add_action( 'wp',             'avs_detach_bfw_add_fee', 9999 );
 
/** 1) Без подписок ИЛИ renewal: добавляем ЛОУЭРКЕЙС‑код купона РАНО (без пересчётов) */
add_action( 'woocommerce_before_calculate_totals', function( $cart ) {
    if ( is_admin() && ! defined('DOING_AJAX') ) return;
    if ( ! is_object( $cart ) ) return;
 
    // Если это первичная покупка подписки — купон НЕ добавляем (будет fee ниже).
    // Если это renewal — купон добавлять можно.
    if ( avs_cart_contains_subscription() && ! avs_cart_is_subscription_renewal() ) return;
 
    $user_id = get_current_user_id();
    if ( ! $user_id || ! class_exists('BfwPoints') ) return;
 
    $fast_points = (float) BfwPoints::getFastPoints( $user_id );
    if ( $fast_points <= 0 ) return;
 
    $opts     = get_option('bonus_option_name');
    $bonus_lc = avs_bfw_bonus_coupon_lc();
    if ( $bonus_lc === '' ) return;
 
    // Если запрещено совмещать с другими купонами — не добавляем при наличии чужих купонов
    $applied = (array) $cart->get_applied_coupons();
    if ( ! empty( $opts['balls-and-coupon'] ) ) {
        foreach ( $applied as $code ) {
            if ( wc_strtolower( $code ) !== $bonus_lc ) return;
        }
    }
 
    $applied_lc = array_map( 'wc_strtolower', $applied );
    if ( ! in_array( $bonus_lc, $applied_lc, true ) ) {
        $cart->applied_coupons[] = $bonus_lc;
    }
}, 5 );
 
/** 1.1) В корзинах с подписками “балльный” купон всегда невалиден — используем fee */
add_filter( 'woocommerce_coupon_is_valid', function( $valid, $coupon ) {
    $bonus_lc = avs_bfw_bonus_coupon_lc();
    if ( ! $bonus_lc || ! ( $coupon instanceof WC_Coupon ) ) return $valid;
    if ( wc_strtolower( $coupon->get_code() ) !== $bonus_lc ) return $valid;
    if ( avs_cart_contains_subscription() && ! avs_cart_is_subscription_renewal() ) return false;
    return $valid;
}, 9999, 2 );
add_filter( 'woocommerce_coupon_is_valid_for_cart', function( $valid, $coupon ) {
    $bonus_lc = avs_bfw_bonus_coupon_lc();
    if ( ! $bonus_lc || ! ( $coupon instanceof WC_Coupon ) ) return $valid;
    if ( wc_strtolower( $coupon->get_code() ) !== $bonus_lc ) return $valid;
    if ( avs_cart_contains_subscription() && ! avs_cart_is_subscription_renewal() ) return false;
    return $valid;
}, 9999, 2 );
 
/** 2) С подписками (первичный заказ): отрицательный fee вместо купона (без remove_coupon) */
add_action( 'woocommerce_cart_calculate_fees', function( $cart ) {
    if ( is_admin() && ! defined('DOING_AJAX') ) return;
    if ( ! is_object( $cart ) ) return;
    if ( ! avs_cart_contains_subscription() || avs_cart_is_subscription_renewal() ) return;
 
    $user_id = get_current_user_id();
    if ( ! $user_id || ! class_exists('BfwPoints') ) return;
 
    $fast_points = (float) BfwPoints::getFastPoints( $user_id );
    if ( $fast_points <= 0 ) return;
 
    $opts     = get_option('bonus_option_name');
    $bonus_lc = avs_bfw_bonus_coupon_lc();
    $bonus_rw = avs_bfw_bonus_coupon_raw();
 
    // Если запрещено с другими купонами — выходим, если есть чужие купоны
    $applied = (array) $cart->get_applied_coupons();
    if ( ! empty( $opts['balls-and-coupon'] ) ) {
        foreach ( $applied as $code ) {
            if ( wc_strtolower( $code ) !== $bonus_lc ) return;
        }
    }
 
    // Тихо убираем наш купон из applied_coupons (без remove_coupon)
    if ( ! empty( $applied ) ) {
        $cart->applied_coupons = array_values( array_filter(
            $applied,
            static function( $code ) use ( $bonus_lc ) {
                return wc_strtolower( $code ) !== $bonus_lc;
            }
        ) );
    }
 
    // Максимально допустимое списание
    $max_allowed = (float) BfwPoints::maxPossiblePointsInOrder();
    $amount      = min( $fast_points, $max_allowed );
    if ( $amount <= 0 ) return;
 
    // Не добавлять fee повторно
    $label_lc = $bonus_lc ?: wc_strtolower( __( 'Bonus points', 'bonus-for-woo' ) );
    foreach ( (array) $cart->get_fees() as $fee ) {
        if ( isset( $fee->name ) && wc_strtolower( $fee->name ) === $label_lc ) return;
    }
 
    $label = $bonus_rw !== '' ? $bonus_rw : __( 'Bonus points', 'bonus-for-woo' );
    $cart->add_fee( $label, - $amount, false );
}, 20 );
 
 
add_filter('bfw_not_use_points_text','my_bfw_not_use_points_text', 10, 1);
function my_bfw_not_use_points_text()
{
    return '';
}

Чтобы не отображалось двойного списания в корзине и в оформлении заказа (Плагин Подписка Woocommerce добавляет строку «Регулярный итог»), то нужно добавить на этих страницах tr.fee.recurring-total{display:none;}

Комментариев 0