Aaron
Aaron

Reputation: 45

WooCommerce Subscriptions: change renewal dates after checkout

I have 1 subscription with 3 variations. I'm trying to force the first renewal date depending on the variation ID that was purchased.

Variation 1 (876) set to renew every day - I want first re-bill date to be 11/15/2020 12:00AM Variation 2 (877) set to renew every 2 days - I want first re-bill date to be 2/15/2021 12:00AM Variation 3 (878) set to renew every 3 days - I want first re-bill date to be 8/15/2021 12:00AM

I thought the below code worked. After the order is created the next bill date DOES show one of the above dates, but it must not be registering with WooCommerce or something, because the renewals are triggering regardless of the above dates.

For my test, I create an order for Variation 1, the next payment date is showing 11/15/2020, but it's renewing the next day.

Hoping to get some insight from someone smarter than me. Again, the sub's next bill date is showing the above dates, but renewals are still happening early/before the above dates.


function nextpaymentdatechange( $order_id ){
    $order = wc_get_order( $order_id );
$items = $order->get_items(); 
foreach ( $items as $item_id => $item ) {
   $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id();
   if ( $product_id === 876 ) {
        $subid = $order_id + 1;
        $nextdate = get_post_meta( $subid, '_schedule_next_payment', true );
        $new_date = date( 'Y-m-d H:i:s', strtotime( '2020-11-15 07:00:00', strtotime( $nextdate )) );
        update_post_meta( $subid , '_schedule_next_payment', $new_date);
   }
    else{ if ( $product_id === 877 ) {
        $subid = $order_id + 1;
        $nextdate = get_post_meta( $subid, '_schedule_next_payment', true );
        $new_date = date( 'Y-m-d H:i:s', strtotime( '2021-02-15 07:00:00', strtotime( $nextdate )) );
        update_post_meta( $subid , '_schedule_next_payment', $new_date);
    }
         else{
              if ( $product_id === 878 ) {
        $subid = $order_id + 1;
        $nextdate = get_post_meta( $subid, '_schedule_next_payment', true );
        $new_date = date( 'Y-m-d H:i:s', strtotime( '2021-08-03 07:00:00', strtotime( $nextdate )) );
        update_post_meta( $subid , '_schedule_next_payment', $new_date);
    }
         }
        
    }
   }
} ```

Upvotes: 0

Views: 3340

Answers (2)

olybop
olybop

Reputation: 31

if i understand, this :

function nextpaymentdatechange( $order_id ){
// YOUR SETTINGS: Set in this array your desired dates (value(s)) by product Id (key)
$dates_for_product = array(
    588 => array(
        'end' => '2020-12-05 07:00:00',
    ),
);

// The date types for subscriptions
$suscription_date_types = array('start', 'trial_end', 'next_payment', 'last_payment', 'end');

Set automaticaly a end date 05 of december for my product 588 (it's a simple subscription)?

Upvotes: 0

LoicTheAztec
LoicTheAztec

Reputation: 253784

To make that work you need first to get WC_Subscription Objects from the order using:

$subscriptions = wcs_get_subscriptions_for_order( $order_id );

that gives an array of the WC_Subscription Object(s) for the Order, from an order Id.

Now you can use the WC_Subscription method update_dates($dates), that requires to set an array of all dates types from a subscription that are 'start', 'trial_end', 'next_payment', 'last_payment' and 'end'.

To get a specific date from a subscription, we use WC_Subscription method get_date($date_type).

Additionally I use WC_Subscription method can_date_be_updated($date_type), to check if a date type can be updated.

I am not sure about which ones dates require to be updated as they are likely related.

You can try the following that should update the related(s) subscription(s) dates from an order, based on your code (the code doesn't throw errors).

I thin that you need to change 'next_payment', 'last_payment' and 'end' dates.

Using the methods update_dates() and save() at the end of the code, allows to change dates, save all required data to database refreshing cached data.

The function code:

function nextpaymentdatechange( $order_id ){
    // YOUR SETTINGS: Set in this array your desired dates (value(s)) by product Id (key)
    $dates_for_product = array(
        876 => array(
            'next_payment' => '2020-11-15 07:00:00',
            'last_payment' => '2020-11-16 07:00:00',
        ),
        877 => array(
            'next_payment' => '2021-02-15 07:00:00',
            'last_payment' => '2021-02-16 07:00:00',
        ),
        878 => array(
            'next_payment' => '2021-08-03 07:00:00',
            'last_payment' => '2021-08-04 07:00:00',
        ),
    );

    // The date types for subscriptions
    $suscription_date_types = array('start', 'trial_end', 'next_payment', 'last_payment', 'end');

    // Get the subscriptions from the current order Id
    $subscriptions = wcs_get_subscriptions_for_order( $order_id );

    // Loop through subscriptions
    foreach ( $subscriptions as $subscription_id => $subscription ) {
        // Loop through items in this subscription
        foreach ( $subscription->get_items() as $item_id => $item ) {
            $product = $item->get_product();

            // Loop through defined products dates
            foreach( $dates_for_product as $product_id => $new_dates ) {
                // If current subscription product id matches
                if ( $product->get_id() == $product_id ) {
                    $current_product_id = $product_id; // Set current product id
                    break; // Stop the current loop
                }
            }
            if ( isset($current_product_id) ) {
                break; // Stop the current loop
            }
        }

        // Updating subscription dates
        if ( isset($current_product_id) ) {
            $updated_dates = array(); // Initializing

            // Loop through subscription date types
            foreach( $suscription_date_types as $date_type ) {
                $date           = $subscription->get_date($date_type);

                // For 'next_payment' and 'last_payment' dates
                if( isset($new_dates[$date_type]) && $subscription->can_date_be_updated($date_type) ) {
                    $updated_dates[$date_type] = $new_dates[$date_type];
                }
                // For 'end' date
                elseif ( $date_type === 'end' && $subscription->can_date_be_updated($date_type) ) {
                    $updated_dates[$date_type] = $new_dates['last_payment']; // ??? Or may be instead: $date;  … (or simply: 0;)
                }
                // Other dates
                else {
                    $updated_dates[$date_type] = $date;
                }
            }

            // Update subscription date, save to database and refresh cached data
            $subscription->update_dates($updated_dates);
            $subscription->save();
        }
    }
}

Code goes in functions.php file of your active child theme (or active theme). It should works.

Upvotes: 2

Related Questions