Jack Robson
Jack Robson

Reputation: 2302

Change WooCommerce Subscription Product Start Date Before Adding to Cart

One of my WooCommerce websites that uses WooCommerce Subscriptions plugin has a problem.

The problem is one product is only shipped every 2 weeks on a certain date.

The next shipping date is November 9th.

I need to figure out how to add this as the default start date for the product.

I tried using the features described in the WC_Subscriptions_Synchroniser class of the WooCommerce Subscriptions plugin.

I enabled the Synchronise Renewals feature.

enter image description here

And also changed the Synchronise Renewals date to Friday of each week as November 9th is a Friday.

enter image description here

However, this makes the First renewal date be November 2nd which is the upcoming Friday.

enter image description here

I'm trying to figure out how to delay the start date to November 9th instead of the November 2nd it is displaying now.

Any advice appreciated.

Upvotes: 2

Views: 4489

Answers (1)

Guibod
Guibod

Reputation: 440

Same issue here. I managed to prepare a future start date, but there is a hard coded limitation to this.

Check out this piece of code in wcs_function.php

// validate the start_date field
if ( ! is_string( $args['start_date'] ) || false === wcs_is_datetime_mysql_format( $args['start_date'] ) ) {
    return new WP_Error( 'woocommerce_subscription_invalid_start_date_format', _x( 'Invalid date. The date must be a string and of the format: "Y-m-d H:i:s".', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
} else if ( wcs_date_to_time( $args['start_date'] ) > current_time( 'timestamp', true ) ) {
    return new WP_Error( 'woocommerce_subscription_invalid_start_date', _x( 'Subscription start date must be before current day.', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
}

It is not possible to create a subscription in the future. This is maybe related to Subscription plugin limitation, or a very narrow approach to the subscription problem.

Meaning that even juggling with cart item properties through woocommerce_add_cart_item_data, wcs_recurring_cart_start_date, woocommerce_get_item_data as I did you'll be eventually hitting a wall. You'll either need to alter Woocommerce Subscription hard limits or be very creative.

Now, i'll show you my 3 action/filters involved, that's rather simple. I've simplified the stuff because it involved date validation and formatting that you may not need.

You'll need a my_delay_post_attr POST field in your product page.

First save into the cart item some custom field you added on the product page.

add_filter('woocommerce_add_cart_item_data', 'my_woocommerce_add_cart_item_data', 10, 1);
/**
 * Read a Y-m-d H:i:s formatted (mysql) date from POST data
 * then store it in the cart item.
 * @param $cart_item_data array
 */
function my_woocommerce_add_cart_item_data($cart_item_data)
{
    if (@$_POST['my_delay_post_attr']) {
        $cart_item_data['my_delay_post_attr'] = $_POST['my_delay_post_attr'];
    }

    return $cart_item_data;
}

Now, let's alter start date upon CART -> ORDER step:

add_filter('wcs_recurring_cart_start_date', 'my_wcs_recurring_cart_start_date', 10, 2);
/**
 * @param string $date
 * @param \WC_Cart $recurring_cart
 *
 * @return mixed
 */
function my_wcs_recurring_cart_start_date($date, $recurring_cart) {
    $cartContents = $recurring_cart->cart_contents;

    if (!$cartContents) {
        return $date;
    }

    if (!count($cartContents)) {
        return $date;
    }

    $key = array_keys($cartContents)[0];

    // I'd suggest you not to trust this, and apply some verification here
    return @$cartContents[$key]['my_delay_post_attr];
}

And finally display this information in cart page:

add_filter( 'woocommerce_get_item_data', 'my_woocommerce_get_item_data', 10, 2 );

public static function my_woocommerce_get_item_data( $item_data, $cart_item ) {
    if (!@$cart_item['my_delay_post_attr']) {
        return $item_data;
    }

    $item_data[] = array(
        'key'     => 'Start of the subscription',
        'value'   => $cart_item['my_delay_post_attr'],
        'display' => '',
    );

    return $item_data;
}

EDIT: I've reached Prosspress support and this is what they answered me about this hard limit on future subscriptions:

I understand you're trying to manually create a subscription and are asking about the limitation around the start date needing to be in the future. This limitation is there to support the gateways, as some are very specific and rigid around the timing of subscriptions. You may be safe to create a workaround for that check, but we can't make any promises - the check is there for a reason. If you are insistent on removing it, please run thorough testing on a development environment first to ensure there are no issues with your gateway.

EDIT2:

I can confirm that PAYPAL won't work with this trick. As for Prosspress response:

We are unsure how Stripe and Mercanet would handle this change. (We do know for sure that PayPal Standard, for example, would not handle this well.)

If you decide to move forward with this, we recommend testing very thoroughly. However, I wonder if there is a more simple option to accomplish what you are trying to achieve? Do you need the actual creation date to be in the future, or do you just need the first payment to be in the future?

If the latter, rather than trying to change date_created, you might consider using a free trial or creating a false free trial. This is the functionality used for subscription synchronization. Also, we recently separated out date_created and start_date in the database. While this functionality isn't fully developed yet, it might give you another point to work with as you move forward with your customization.

Upvotes: 6

Related Questions