0

I ned to create a custom coupon for use with WooCommerce Subscriptions because for some reason you can either have one on the sign up fee OR you have one on the recurring amount, but I need a coupon to be applied to both, but there is no option.

I have created a custom coupon using the filter woocommerce_coupon_discount_types, but the filter to then implement this coupon in the cart, woocommerce_coupon_get_discount_amount, does not add it to the recurring amounts, only adds it to the sign up fee.

How does one apply a coupon to the recurring fee?

function dhti_coupon_get_discount_amount($discount, $discounting_amount, $cart_item, $single, $coupon)
{
    if ($coupon->discount_type == 'sign_up_and_recurring_percent')
    {
        $discount = $discounting_amount * $coupon->amount / 100;
        return $discount;
    }
    else
    {
        return $discount;
    }
}
add_filter('woocommerce_coupon_get_discount_amount', 'dhti_coupon_get_discount_amount', 10, 5);

enter image description here

  • I think that is not possible to have 2 coupon types on the same coupon regarding Woocommerce subscriptions additional types. What you could do is to auto add a coupon, when a specific coupon type is added to cart (you have some related answers in StackOverFlow regarding auto applied coupons). – LoicTheAztec Apr 18 '19 at 13:55
  • I can see in the file class-wc-subscriptions-coupon.php, in the function remove_coupons() it is removing coupon that are not 'recurring_fee' or 'recurring_percent'. There is filter in here our own types here. – Laurence Cope Apr 18 '19 at 14:28
  • If its not possible them the only other way I can think of is to add a fee to subscriptions only? I could do this if the other coupon is called. – Laurence Cope Apr 18 '19 at 14:31
0

I have managed to find a way, but welcome a better one.

As mentioned in the OP comments, the function remove_coupons() in class WC_Subscriptions_Coupon in file woocommerce-subscriptions/includes/class-wc-subscriptions-coupon.php is removing coupons that are not 'recurring_fee' or 'recurring_percent'. There is no filter added we can tap into to assign our own custom coupon types, so there does not seem to be any chance of getting past this.

So to get around this, we can create our own filter using the same code as the remove_coupons() method, in this case called remove_coupons_custom() and then add this filter in the same way as it is in the original class.

But the original method still runs and will remove our coupon, so we need to then remove the original filter from running by adding remove_action( 'woocommerce_before_calculate_totals', 'WC_Subscriptions_Coupon::remove_coupons', 10 ); in the top of our new function.

I do not like this approach in case the original code is changed to a degree that breaks or stops ours working, but is the only way I can see to do it at the moment, unless the original code is modified to add a filter we can tap into to add our own custom types.

function remove_coupons_custom( $cart )
{
    // Remove original action added by WC_Subscriptions_Coupon class
    remove_action( 'woocommerce_before_calculate_totals', 'WC_Subscriptions_Coupon::remove_coupons', 10 );

    // Create WC_Subscriptions_Coupon instance so we can replace self reference below in original method
    $WC_Subscriptions_Coupon = new WC_Subscriptions_Coupon;

    $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 );
            $coupon_type = wcs_get_coupon_property( $coupon, 'discount_type' );

            if ( in_array( $coupon_type, array( 'recurring_fee', 'recurring_percent', 'sign_up_and_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 {
                    $WC_Subscriptions_Coupon::$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 {
                $WC_Subscriptions_Coupon::$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();
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'remove_coupons_custom', 10 );

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.