/** * Sets which coupons should be applied for this calculation. * * This function is hooked to "woocommerce_before_calculate_totals" so that WC will calculate a subscription * product's total based on the total of it's price per period and sign up fee (if any). * * @since 1.3.5 */ public static function remove_coupons($cart) { $calculation_type = WC_Subscriptions_Cart::get_calculation_type(); // Only hook when totals are being calculated completely (on cart & checkout pages) if ('none' == $calculation_type || !WC_Subscriptions_Cart::cart_contains_subscription() || !is_checkout() && !is_cart() && !defined('WOOCOMMERCE_CHECKOUT') && !defined('WOOCOMMERCE_CART')) { return; } $applied_coupons = $cart->get_applied_coupons(); // If we're calculating a sign-up fee or recurring fee only amount, remove irrelevant coupons if (!empty($applied_coupons)) { // Keep track of which coupons, if any, need to be reapplied immediately $coupons_to_reapply = array(); foreach ($applied_coupons as $coupon_code) { $coupon = new WC_Coupon($coupon_code); if (in_array($coupon->type, array('recurring_fee', 'recurring_percent'))) { // always apply coupons to their specific calculation case if ('recurring_total' == $calculation_type) { $coupons_to_reapply[] = $coupon_code; } elseif ('none' == $calculation_type && !WC_Subscriptions_Cart::all_cart_items_have_free_trial()) { // sometimes apply recurring coupons to initial total $coupons_to_reapply[] = $coupon_code; } else { self::$removed_coupons[] = $coupon_code; } } elseif ('none' == $calculation_type && !in_array($coupon->type, array('recurring_fee', 'recurring_percent'))) { // apply all coupons to the first payment $coupons_to_reapply[] = $coupon_code; } else { self::$removed_coupons[] = $coupon_code; } } // Now remove all coupons (WC only provides a function to remove all coupons) $cart->remove_coupons(); // And re-apply those which relate to this calculation $cart->applied_coupons = $coupons_to_reapply; if (isset($cart->coupons)) { // WC 2.3+ $cart->coupons = $cart->get_coupons(); } } }
/** * Apply sign up fee or recurring fee discount * * @since 1.2 */ public static function apply_subscription_discount($original_price, $cart_item, $cart) { _deprecated_function(__METHOD__, '2.0.10', 'Have moved to filtering on "woocommerce_coupon_get_discount_amount" to return discount amount. See: ' . __CLASS__ . '::get_discount_amount()'); $product_id = $cart_item['data']->is_type(array('subscription_variation')) ? $cart_item['data']->variation_id : $cart_item['data']->id; if (!WC_Subscriptions_Product::is_subscription($product_id)) { return $original_price; } $price = $calculation_price = $original_price; $calculation_type = WC_Subscriptions_Cart::get_calculation_type(); if (!empty($cart->applied_coupons)) { foreach ($cart->applied_coupons as $code) { $coupon = new WC_Coupon($code); // Pre 2.5 is_valid_for_product() does not use wc_get_product_coupon_types() if (WC_Subscriptions::is_woocommerce_pre('2.5')) { $is_valid_for_product = true; } else { $is_valid_for_product = $coupon->is_valid_for_product(wc_get_product($product_id), $cart_item); } if ($coupon->apply_before_tax() && $coupon->is_valid() && $is_valid_for_product) { $apply_recurring_coupon = $apply_recurring_percent_coupon = $apply_initial_coupon = $apply_initial_percent_coupon = false; // Apply recurring fee discounts to recurring total calculations if ('recurring_total' == $calculation_type) { $apply_recurring_coupon = 'recurring_fee' == $coupon->type ? true : false; $apply_recurring_percent_coupon = 'recurring_percent' == $coupon->type ? true : false; } if ('none' == $calculation_type) { // If all items have a free trial we don't need to apply recurring coupons to the initial total if (!WC_Subscriptions_Cart::all_cart_items_have_free_trial()) { if ('recurring_fee' == $coupon->type) { $apply_initial_coupon = true; } if ('recurring_percent' == $coupon->type) { $apply_initial_percent_coupon = true; } } // Apply sign-up discounts to initial total if (!empty($cart_item['data']->subscription_sign_up_fee)) { if ('sign_up_fee' == $coupon->type) { $apply_initial_coupon = true; } if ('sign_up_fee_percent' == $coupon->type) { $apply_initial_percent_coupon = true; } $calculation_price = $cart_item['data']->subscription_sign_up_fee; } } if ($apply_recurring_coupon || $apply_initial_coupon) { $discount_amount = $calculation_price < $coupon->amount ? $calculation_price : $coupon->amount; // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items) if ($apply_initial_coupon && 'recurring_fee' == $coupon->type && !empty($cart_item['data']->subscription_trial_length)) { $discount_amount = 0; } $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity']; $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']); $price = $price - $discount_amount; } elseif ($apply_recurring_percent_coupon) { $discount_amount = round($calculation_price / 100 * $coupon->amount, WC()->cart->dp); $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity']; $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']); $price = $price - $discount_amount; } elseif ($apply_initial_percent_coupon) { // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items) if ('recurring_percent' == $coupon->type && empty($cart_item['data']->subscription_trial_length)) { $amount_to_discount = $cart_item['data']->subscription_price; } else { $amount_to_discount = 0; } // Sign up fee coupons only apply to sign up fees if ('sign_up_fee_percent' == $coupon->type) { $amount_to_discount = $cart_item['data']->subscription_sign_up_fee; } $discount_amount = round($amount_to_discount / 100 * $coupon->amount, WC()->cart->dp); $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity']; $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']); $price = $price - $discount_amount; } } } if ($price < 0) { $price = 0; } } return $price; }