Subscriptions core package for WooCommerce

Overview

WooCommerce Subscriptions Core

This package adds core subscriptions functionality to your WooCommerce store.

Dependencies

Usage

The /Automattic/woocommerce-subscriptions-core/ repository is treated as a development repository and includes development assets, like unit tests and configuration files.

This package can be loaded as standalone plugin for development purposes, however it's intended to be loaded as follows:

composer.json

"repositories": [
    {
        "type": "git",
        "url": "https://github.com/Automattic/woocommerce-subscriptions-core.git"
    }
],
"require": {
    "woocommerce/subscriptions-core": "1.0.0",
},

my-main-plugin-file.php

require_once PATH_TO_WOOCOMMERCE_SUBSCRIPTIONS_CORE . 'includes/class-wc-subscriptions-core-plugin.php';
new WC_Subscriptions_Core_Plugin();

Development

After cloning the repo, install dependencies and build:

npm install && composer install
npm run build

Features Provided in Core

  • Simple & Variable Subscriptions Product Types
    • Virtual and Downloadable
    • Limited Subscriptions
    • All standard product features: trials period, sign-up fees, synced, one-time shipping
  • Manage Subscriptions (Update the status of subscriptions)
  • All subscription global helper functions (eg. wcs_get_subscriptions_for_order())
  • Subscription Coupons (Sign-up fee and Recurring coupons)
  • Subscriptions REST API endpoints
  • Checkout Blocks + Subscriptions support
  • Support for the WooCommerce Payments gateway
  • Privacy/GDPR exporters for Subscriptions
Comments
  • Subscriptions search performance fix

    Subscriptions search performance fix

    Description

    The Subscriptions search in wp-admin -> WooCommerce -> Subscriptions is very slow. It takes as much as 30 seconds on our client website.

    We find that this query in WCS_Subscription_Data_Store_CPT::search_subscriptions() is way too slow:

    SELECT DISTINCT p1.post_id
    FROM wp_postmeta p1
    WHERE p1.meta_value LIKE '%phrase%' AND p1.meta_key IN ('_order_key','_billing_address_index','_shipping_address_index','_billing_email')
    

    Looking as the SQL EXPLAIN I can see that on our client website it has to check 4,000,000 fields.When I split that query into 4 individual queries - one for each meta_key, then it's much faster. The above takes 17 to 20 seconds.

    We found the The individual queries only take about 4 seconds when I sum the times for each:

    SELECT SQL_NO_CACHE DISTINCT p1.post_id
    FROM wp_postmeta p1
    WHERE p1.meta_value LIKE '%phrase%' AND p1.meta_key IN ('_order_key');
    
    SELECT SQL_NO_CACHE DISTINCT p1.post_id
    FROM wp_postmeta p1
    WHERE p1.meta_value LIKE '%phrase%' AND p1.meta_key IN ('_billing_address_index');
    
    SELECT SQL_NO_CACHE DISTINCT p1.post_id
    FROM wp_postmeta p1
    WHERE p1.meta_value LIKE '%phrase%' AND p1.meta_key IN ('_shipping_address_index');
    
    SELECT SQL_NO_CACHE DISTINCT p1.post_id
    FROM wp_postmeta p1
    WHERE p1.meta_value LIKE '%phrase%' AND p1.meta_key IN ('_billing_email');
    

    Here's what the Query Monitor plugin reports without the fix:

    • total time of 28 seconds
    • 5 slow queries, the slowest taking 25

    woocommerce-subscriptions-slow seconds

    And here's with the fix:

    • total time of 4.1 seconds
    • 8 slow queries, but all the 4 individual search queries are still much faster than the single query from before

    woocommerce-subscriptions-fast

    How to test this PR

    1. Make sure you have a lot of Subscriptions in your database. In our case it's 30,000.
    2. Go to wp-admin -> WooCommerce -> Subscriptions
    3. Enter some search phrase and click "Search Subscriptions"
    4. If you have about 30,000 subscriptions you will wait for 20 - 30 seconds to get the results

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [yes] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [no] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    pr: needs review 
    opened by foliovision 10
  • Replace `get_posts()` with `wc_get_orders()` in WC_Subscriptions_Order::get_users_subscription_orders()

    Replace `get_posts()` with `wc_get_orders()` in WC_Subscriptions_Order::get_users_subscription_orders()

    Fixes #144 partially.

    Description

    This PR only replaces get_posts() call in get_users_subscription_orders() with wc_get_orders().

    Some key points:

    • I follow this guide to pass the meta_query bit.
    • I change the field name following this map.
    • I use customer_id parameter, instead of passing it in meta_query.

    How to test this PR

    1. Install woocommerce-subscriptions-core as a plugin.
    2. Since I get_users_subscription_orders() isn't called anywhere, I use wp-console to call it.

    Screen Shot 2022-04-28 at 22 52 10

    Actually, I wondered if we can just delete get_users_subscription_orders() but then I think someone out there (another plugin or custom code) might depend on it.

    1. Run WC_Subscriptions_Order::get_users_subscription_orders(); and make sure base branch and PR branch returns the same output.

    2. I also add this code as a mu-plugin, in a file wp-content/mu-plugins/something.php.

    define('SAVEQUERIES', true);
    add_action( 'shutdown', function() {
        global $wpdb;
        foreach($wpdb->queries as $q) {
            file_put_contents('/tmp/debug.log', "-----start\n" . $q[0] . "\n-----end\n");
        }
    } );
    

    To log queries going to the database. I search for subscription_renewal. I format the query and diff the query made using base branch vs PR branch.

    There is some diff but looks OK:

    Screen Shot 2022-04-28 at 23 07 01

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [x] Will this PR affect WooCommerce Subscriptions? no
    • [x] Will this PR affect WooCommerce Payments? no
    opened by shendy-a8c 10
  • [HPOS] Bulk actions missing from Subscriptions listing in wp-admin

    [HPOS] Bulk actions missing from Subscriptions listing in wp-admin

    Fixes #321

    Note This PR is targeting the hpos-admin-ui-support branch due to the changes required for admin screens in HPOS environments awaiting merge

    Description

    Bulk actions are missing from the Subscriptions listing page in wp-admin when HPOS is enabled.

    NB: Bulk actions will not work with this PR, there is an open issue for this https://github.com/woocommerce/woocommerce/issues/35750.

    There was a small refactor to go along with this change. Previously, the function print_bulk_actions_script() appends the Subscription bulk actions to the dropdown list using jquery. This was due to the bulk_actions-edit-shop_subscription previously not allowing the addition of items but only the removal. This restriction was dropped in WP 4.7.0 (2016-12-06.)

    CPT image HPOS image

    How to test this PR

    With HPOS enabled and using HPOS Admin UI support and associated WooCommerce PR

    1. With HPOS enabled, Go to 'Subscriptions' in wp-admin.
    2. Click on the 'Bulk actions' drop down and compare the options when the store is in CPT mode.

    Product impact

    • [x] Added changelog entry (or does not apply) - This will be rolled up into one changelog entry for admin screens working under HPOS.
    • [x] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [x] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [ ] Added deprecated functions, hooks or classes to the spreadsheet
    opened by brucealdridge 8
  • Update JS linting CI

    Update JS linting CI

    Fixes #58

    Description

    Adds JS linting

    How to test this PR

    1. npm run lint:js
    2. should have no errors or warnings

    Product impact

    • [x] Will this PR affect WooCommerce Subscriptions? no
    • [x] Will this PR affect WooCommerce Payments? no
    pr: ready to merge 
    opened by brucealdridge 8
  • Update `update_post_meta()` code where an order ID is passed to use CRUD

    Update `update_post_meta()` code where an order ID is passed to use CRUD

    Fixes #142

    Description

    When order data is moved to custom tables, updating order meta using update_post_meta() will no longer work. This PR updates all cases of update_post_meta() where an Order ID is passed - thankfully there wasn't many cases in our codebase 😅

    How to test this PR

    Testing wcs_set_objects_property() changes

    This function is pretty well covered in unit tests, however to test nothing is broken a simple test would be to process a subscription renewal order and make sure the renewal order has the correct meta data.

    1. With an active subscription, process a renewal order
    2. Confirm the new renewal order has _billing_address_1 metadata set

    Testing save_old_paypal_meta() changes

    This one was a little trickier to test so I just hacked some of the conditions because the only changes we cared about is the order updating post meta:

    1. Edit the save_old_paypal_meta() function to pass if conditions using, true ||
    2. Manually set $subscriptions to be $subscriptions = [ 101823 => wcs_get_subscription( 101823 ) ];
    3. Run the following snippet:
    add_action( 'admin_footer', function() {
    	update_post_meta( 101823, '_paypal_subscription_id', 'S-fake1234' );
    	update_post_meta( 101823, '_payment_method', 'paypal' );
    
    	WCS_PayPal_Standard_Switcher::save_old_paypal_meta( 101824, [] );
    } );
    
    1. Confirm the $order meta is set in the DB

    image

    Product impact

    • [x] Added changelog entry (or does not apply)
    • [x] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    compatibility 
    opened by mattallan 7
  • Restore missing filters on Subscriptions listing.

    Restore missing filters on Subscriptions listing.

    Fixes #323

    Note This PR is targeting the hpos-admin-ui-support branch due to the changes required for admin screens in HPOS environments awaiting merge.

    Description

    The custom filters that we add to the Subscriptions list screen were not showing when HPOS is enabled.

    A new filter has been added in HPOS environments for this purpose woocommerce_order_list_table_extra_tablenav additionally the usage of global $typenow; has been removed with checks against the order type instead.

    Screenshot 2022-11-29 at 1 59 36 PM

    How to test this PR

    1. On a HPOS enabled site, go to the Subscriptions listing screen in wp-admin.
    2. The filters should be visible.

    NB: The filters for product/customers are unreadable due to the width. There is an open issue for this.

    Product impact

    • [x] Added changelog entry (or does not apply)- This will be rolled up into one changelog entry for admin screens working under HPOS.
    • [ ] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [ ] Added deprecated functions, hooks or classes to the spreadsheet
    pr: needs author reply 
    opened by brucealdridge 6
  • HPOS Admin UI support

    HPOS Admin UI support

    Warning This PR is semi-blocked by upstream changes in WC https://github.com/woocommerce/woocommerce/pull/35658 these changes should be okay to merge prior to this but need these changes for testing.

    fixes #293 fixes #223 fixes #298 fixes #322 fixes #321

    Description

    PR bringing a number of fixes to Admin UI based on the changes introduced in https://github.com/woocommerce/woocommerce/pull/35658

    How to test this PR

    HPOS

    ⚠️ Important: Parts of this flow will be broken and errors will be thrown. For HPOS this PR is aimed at laying the groundwork. File any usability issues you come across while testing.

    1. Enable HPOS tables.
    2. Purchase subscriptions.
    3. Go to the WooCommerce > Subscriptions admin screen.
    4. Note that the page loads and subscriptions are listed.
    5. Click on a subscription to edit it.
    6. Note the page loads.

    CPT

    ⚠️ Important: This PR shouldn't break any CPT flows or UIs. This PR needs to be releasable to existing CPT stores.

    1. Enable CPT tables.
    2. Purchase subscriptions.
    3. Go to the WooCommerce > Subscriptions admin screen.
    4. Note that the page loads and subscriptions are listed.
      • Filter by customer
      • Filter by product
      • filter by status
      • use the bulk actions
      • use the individual actions by hovering a subscription (suspend, reactivate etc).
    5. Click on a subscription to edit it.
    6. Note the page loads.
      • Change the billing schedule
      • Change the subscription data (change the customer, parent order, address data etc.)
    7. Save and make sure things save correctly.

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [ ] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [ ] Added deprecated functions, hooks or classes to the spreadsheet
    pr: needs review 
    opened by brucealdridge 6
  • [HPOS] Replace `get_post_type()` with WC_Data_Store::load( 'subscription' )->get_order_type( $id )

    [HPOS] Replace `get_post_type()` with WC_Data_Store::load( 'subscription' )->get_order_type( $id )

    Describe the bug

    To support subscriptions stored in different data stores, we need to replace all cases of get_post_type() with WC_Data_Store::load( 'subscription' )->get_order_type( $id ).

    Doing a search of get_post_type( in subscriptions-core code there's 15 instances of this still being used.

    In #153 we only targetted code which used this function on WC Orders, but as part of tackling this issue we should replace all cases.


    Updating get_post_type( $subscription_id )

    'shop_subscription' == get_post_type( $post_id )
    

    Replace with:

    'shop_subscription' === WC_Data_Store::load( 'subscription' )->get_order_type( $id )
    

    Updating get_post_type( $product_id )

    I could only find one instance where we're using get_post_type() with product ID inside user_can_not_delete_subscription()

    0 === strpos( get_post_type( $args[2] ), 'product' )
    

    The issue withWC_Data_Store::load( 'product' )->get_product_type( $id ) is that it formats product types i.e. 'product_variation' is returned as just 'variation' so there's not a simple one-to-one replacement for this one.

    We can probably just ignore this one case for now.

    type: bug compatibility: HPOS 
    opened by mattallan 6
  • Refactor our Related Orders Data Store classes to support WC CRUD methods

    Refactor our Related Orders Data Store classes to support WC CRUD methods

    Fixes #145

    Description

    This PR updates our WCS_Related_Order_Store_Cached_CPT and WCS_Related_Order_Store_CPT classes to use WC CRUD methods to be able to support both WP Posts and High-Performance Order Storage (HPOS) environments.

    Note - Doesn't include renaming our classes

    This PR doesn't rename our classes to remove the reference to Custom Post Types with the _CPT suffix. Renaming these classes and deprecating the class isn't a critical part to this refactor, so I will create a separate issue to tackle this at a later time.

    Note - Can't test with HPOS

    This PR does not update our WCS_Post_Meta_Cache_Manager class which triggers a lot of the functionality in these related orders store classes, this means you cannot test this PR with HPOS enabled. You must be using WP Posts.

    What are these caches?

    Subscription related orders (renewals, switch and resubscribe orders) record their relationship in order meta. Historically finding these subscription related orders was costly as it required querying the database for orders with specific meta (a meta query and post join). To fix this in WC Subscriptions 2.3 we introduced a persistent caching layer. In subscription meta we now store a single key to keep track of the subscriptions related orders.

    Screen Shot 2022-11-09 at 4 46 27 pm

    Now to get a subscription's list of renewal orders we simply just refer to this single meta key on the subscription rather than multiple values stored on every order.

    These cache classes act as gatekeepers by providing APIs for fetching related orders get_related_order_ids() and they also house all the hooks for keeping the cache up to date. If a renewal order is trashed, this class is responsible for removing that record for the subscription's related order cache.

    There are 2 public facing pages that include some details of these classes:

    What's new?

    There's a fair bit changing in this PR so let's go through it:

    • New Subscriptions data store functions:
      • delete_all_metadata_by_key - Previously we used WP's delete_metadata() to remove every cache meta we had stored. There's no equivalent in the WC HPOS data stores so we created our own.
      • ~get_metadata_by_key - When fetching related order cache meta data we need to make sure it's fetched directly from the database. This function pulls the metadata directly from the new orders table or if using wp posts, it calls get_post_meta()~
    • Replaced instanced of get_post_meta, update_post_meta & delete_post_meta with relevant WC CRUD method.
    • Replaced uses of get_posts() with new wcs_get_orders_with_meta_query()
    • ~New helper function get_subscription_with_cache_meta() to help us get an instance of WC Subscriptions with all of our related order cache meta in memory. This solves a problem I was facing with trying to fetch the cache returning an empty array and trying to update the cache, creating a duplicate postmeta entry.~

    How to test this PR

    Testing this PR should hopefully be pretty straightforward and the main thing we need to test is making sure the subscription's related-order cache is properly updated when its list of related orders changes, and when an order is updated we also need to make sure the relevant related order meta is updated on the orders.

    Flows to test:

    1. After processing a renewal order, the renewal order is visible in the related orders table on the Edit Subscription page
    2. After processing a renewal order, the new renewal order ID is inside the _subscription_renewal_order_ids_cache on the subscription
    3. After processing a renewal order, make sure the renewal order has the _subscription_renewal and proper subscription ID saved in postmeta.
    4. After trashing a renewal order, the renewal order ID is removed from the _subscription_renewal_order_ids_cache array in subscription postmeta
    5. After trashing a renewal order, the renewal order should not show up in the related orders table on the subscription

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [x] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [x] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [x] Added deprecated functions, hooks or classes to the spreadsheet
    pr: needs review 
    opened by mattallan 6
  • Display related orders table when viewing the new

    Display related orders table when viewing the new "Edit Order" page (HPOS enabled stores)

    Fixes #192

    Description

    This PR displays the related orders table meta box on the "Edit Order" and "Edit Subscription" when HPOS is enabled with non-HPOS compatibility.

    In addition:

    • [x] PHPCS formatting has been fixed in related files. (mostly moved to #280)
    • [x] PHPCS errors/warnings have been addressed in related files. (mostly moved to #280)
      • Some low-hanging errors/warnings have been addressed.
    • [x] Added deprecated functions, hooks or classes to the spreadsheet - yes, 3 hooks added

    How to test this PR

    1. Enable the COT feature and turn on COT (see guide here).
    2. Go into WooCommerce > Settings > Advanced > Custom Data Stores.
    3. Make sure "Use the WooCommerce orders tables" is enabled.
    4. Purchase a subscription and note the order ID.
    5. From WP admin dashboard, go to WooCommerce > Orders and view the "Edit Order" page for the order ID noted above.
    6. Notice that the Related Orders table meta box is visible and contains a link to the related Subscription. You should not see the current order within this table. Screenshot 2022-11-08 at 12 57 37
    7. Click on the related Subscription to be taken to the "Edit Subscription" page. You should not see the current subscription within this table. Screenshot 2022-11-08 at 12 57 24
    8. Notice that the Related Orders table meta box is visible and contains a link to the parent order.
    9. Clicking on the parent order will take you to the "Edit Order" page as above.

    Recommended compatibility tests (checked = tested by PR author):

    • [x] WCPay
    • [x] WC Subs
      • [x] with WC Subs activated + HPOS enabled + syncing on, ~the Related Orders table isn't rendered correctly and following PHP Notice occurs~ it uses a newly deprecated hook. Need to update this issue to clarify: https://github.com/woocommerce/woocommerce-subscriptions/issues/4417
    • [x] WC 6.8.0 – toggling between this subs-core branch & trunk results in identical output.
    • [x] WC HPOS enabled + syncing off
    • [x] WC HPOS enabled + syncing on
    • [x] WC HPOS disabled

    Product impact

    • [x] Added changelog entry (or does not apply)
    • [ ] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    compatibility: HPOS 
    opened by Jinksi 6
  • Fatal divide by zero error when quantity is 0 in PHP8

    Fatal divide by zero error when quantity is 0 in PHP8

    Describe the bug

    In #177, a fix was implemented to prevent a divide by zero error if the store is running on PHP8. The following code is used to check for this:

    // In rare cases quantity can be zero. Check first to prevent triggering a fatal error in php8+
                    if ( 0 !== $item_to_renew['qty'] ) {
                        $_product->set_price( $price / $item_to_renew['qty'] );
                    }
    

    However, it looks like $item_to_renew['qty'] is not an integer (presumably it is a string), so this check doesn't have the desired effect. We had a customer report (5461670-zd-woothemes) reporting a fatal error and proposing the following fix:

    // In rare cases quantity can be zero. Check first to prevent triggering a fatal error in php8+
                    if ( 0 !== intval($item_to_renew['qty']) ) {
                        $_product->set_price( $price / intval($item_to_renew['qty']) );
                    }
    

    This should prevent this error happening in all cases.

    To Reproduce

    See #175 (alternatively, the customer who raised this issue suggested it occurs when a new customer logs into their store).

    Expected behavior

    We don't see any fatal errors related to division by zero errors.

    • [x] Does this issue affect WooCommerce Subscriptions? yes: 5461670-zd-woothemes
    • [ ] Does this issue affect WooCommerce Payments? TBC
    type: bug priority: critical 
    opened by dmallory42 6
  • HPOS syncing from the post record doesn't sync subscription dates

    HPOS syncing from the post record doesn't sync subscription dates

    Blocked by https://github.com/Automattic/woocommerce-subscriptions-core/pull/336

    Describe the bug

    When the post record becomes out of sync with the HPOS table record, WC will attempt to sync the subscription using the post record as the authoritative table.

    This doesn't work with some subscription-specific data. eg dates.

    To Reproduce

    1. Enable HPOS and syncing (see screenshot below).
    2. Go into the database and manually alter the next payment date of a subscription.
    3. View the subscription via the admin screen or customer my account page.
    4. The next payment date should update to reflect the change you made manually. On trunk currently, it won't.

    image

    Expected behavior

    The subscription should sync all data from the post record when it gets out of sync.

    Actual behavior

    Next payment dates and possibly other data points don't sync.

    Product impact

    • [ ] Does this issue affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Does this issue affect WooCommerce Payments? yes/no/tbc, add issue ref

    Additional context

    From the brief investigation I've done, this is caused by a bug in OrdersTableDataStore::set_order_prop() which is called from OrdersTableDataStore::migrate_post_record()

    type: bug status: blocked 
    opened by james-allan 0
  • show

    show "overdue" in admin subscriptions list for failed renewals

    Fixes #260

    Work in progress/prototype branch. Feel free to take over :)

    Description

    How to test this PR

    1. Go to …
    2. Click on …

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [ ] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [ ] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [ ] Added deprecated functions, hooks or classes to the spreadsheet
    opened by haszari 0
  • Fix/replace post hooks manager class

    Fix/replace post hooks manager class

    Fixes #221 Fixes #195

    Description

    This PR updates all of the WP Post-related hooks we were using to hook onto the trashing, deleting and untrashing of orders and subscriptions in the WC_Subscriptions_Manager class to now use the CRUD/HPOS equivalent hooks so that this functionality continues to work on stores that are using custom order tables.

    This PR consists of the following changes:

    1. Moved all of the trash, untrash & delete hooks into a new function that is ran on woocommerce_loaded
    2. Added new add_action()'s calls for when HPOS is enabled to hook onto the new WC order hooks
    3. Updated the existing maybe_trash_subscription() & maybe_cancel_subscription() functions to use CRUD methods

    1. Moved actions into a new function on woocommerce_loaded

    In order to load the new hooks we need to run wcs_is_custom_order_tables_usage_enabled() but this function only works after WC has been loaded.

    While testing this PR I was getting errors due to some WC classes/instances not existing yet when trying to check if HPOS is enabled.

    To fix this, I moved these hooks into their own function which is attached to the WC loaded do action.

    2. New Add Actions

    Here are all of the _post hooks changing in this PR and their new HPOS equivalent hooks:

    • wp_trash_post is now woocommerce_before_trash_order
    • untrashed_post is now woocommerce_untrash_order
    • before_delete_post is now woocommerce_before_delete_order
    • trashed_post is now woocommerce_trash_order
    • deleted_post is nowwoocommerce_delete_order`

    To avoid breaking backwards compatibility, I made it so these new action hooks are only used on stores with HPOS enabled.

    3. Updating functions to use CRUD methods

    Most of the changes in these functions are pretty self-explanatory but there are some I wanted to make note of. order_data_store::untrash_order() method only exists in the OrderTablesDataStore class so I made it so we only use this function if it exists, otherwise, fall back to using the wp_untrash_post() function.

    When fixing fix_trash_meta_status() to work in CRUD, I couldn't use update_meta_data() as it was creating duplicate rows in the database, so I had to use the read_meta() and update_meta() approach which writes this data directly to the DB and works in both HPOS and none-HPOS environments.

    How to test this PR

    There are 4 main flows that need to be tested in this PR:

    1. Trashing a parent order, cancels the subscription first, then trashes it
    2. Trashing a parent order correctly sets the _wp_trash_meta_status to wc-cancelled if the subscription previously had an active status.
    3. Untrashing a parent order also untrashes the subscription (Note: untrashed subscriptions go to pending status)
    4. Deleting a parent order deletes the subscription

    My own testing on this PR:

    HPOS off:

    • [x] Trash a parent order
      • [x] Confirm subscription was cancelled first (need to check order notes)
      • [x] Confirm subscription is trashed
      • [x] Confirm _wp_trash_meta_status is set on subscription
    • [x] Untrash parent order
      • [x] Confirm subscription is also untrashed
    • [x] Delete a parent order
      • [x] Confirm subscription has been deleted from DB
    • [x] Confirm woocommerce_subscription_trashed action hook is triggered after trash
    • [x] Confirm woocommerce_subscription_deleted action hook is triggered after delete

    HPOS on, syncing off:

    • [x] Trash a parent order
      • [x] Confirm subscription was cancelled first (need to check order notes)
      • [x] Confirm subscription is trashed
      • [x] Confirm _wp_trash_meta_status is set on subscription
    • [x] Untrash parent order
      • [x] Confirm subscription is also untrashed
    • [x] Delete a parent order
      • [x] Confirm subscription has been deleted from DB
    • [x] Confirm woocommerce_subscription_trashed action hook is triggered after trash
    • [x] Confirm woocommerce_subscription_deleted action hook is triggered after delete

    HPOS on, syncing on:

    • [x] Trash a parent order
      • [x] Confirm subscription was cancelled first (need to check order notes)
      • [x] Confirm subscription is trashed
      • [x] Confirm _wp_trash_meta_status is set on subscription
    • [x] Untrash parent order
      • [x] Confirm subscription is also untrashed
    • [x] Delete a parent order
      • [x] Confirm subscription has been deleted from DB
    • [x] Confirm woocommerce_subscription_trashed action hook is triggered after trash
    • [x] Confirm woocommerce_subscription_deleted action hook is triggered after delete

    WC 6.8 (HPOS off):

    • [x] Trash a parent order
      • [x] Confirm subscription was cancelled first (need to check order notes)
      • [x] Confirm subscription is trashed
      • [x] Confirm _wp_trash_meta_status is set on subscription
    • [x] Untrash parent order
      • [x] Confirm subscription is also untrashed
    • [x] Delete a parent order
      • [x] Confirm subscription has been deleted from DB
    • [x] Confirm woocommerce_subscription_trashed action hook is triggered after trash
    • [x] Confirm woocommerce_subscription_deleted action hook is triggered after delete

    Product impact

    • [x] Added changelog entry (or does not apply)
    • [x] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [x] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    • [x] Added deprecated functions, hooks or classes to the spreadsheet
    pr: needs review compatibility: HPOS 
    opened by mattallan 1
  • (Re-) calculate taxes for new renewal orders

    (Re-) calculate taxes for new renewal orders

    Description

    When (automatically) adding a new renewal, taxes for the corresponding renewal order should be recalculated. Tax rates in WooCommerce may be subject to change, e.g.:

    • VAT rates may be reduced for a certain amount of time
    • VAT rates may change, increase, decrease for certain countries

    Is there any reason why taxes are not being (re-) calculated for renewals based on the current settings? For orders where prices do not include taxes this may lead to higher/lower total prices but nevertheless taxes would at least be precise and not wrong.

    Testing instructions

    1. Create a new subscription
    2. Update a tax rate, e.g. change percentage
    3. Generate a renewal for the old subscription
    4. See how the renewal does not reflect current tax rates.
    opened by dennisnissle 0
  • Adjust subs-core

    Adjust subs-core "plugin" description metadata to make it clear it's not to be used standalone

    https://github.com/Automattic/woocommerce-subscriptions-core/blob/6b8c650c06d92eb1cb2bdb79e3e98aec14920414/woocommerce-subscriptions-core.php#L5

    The plugin description string currently could be more sternly worded to clarify that running subs-core as a plugin is only appropriate for local development. Suggest something like "Development package of core subscriptions functionality. Not recommended for testing or production."

    type: task 
    opened by haszari 0
  • Use try/catch when calling process_payment to avoid fatals.

    Use try/catch when calling process_payment to avoid fatals.

    Fixes #330, please see for details.

    Please also see discussion in p1670014386600359-slack-C029ME0FYRZ for how this affects processing subscription payment method changes with WooCommerce Payments in particular.

    Description

    See #330 for a description.

    How to test this PR

    Use the Change Payment Method instructions:

    https://woocommerce.com/document/subscriptions/customers-view/#section-11

    To simulate a failure, you could either block the network request w/ Developer Tools or use a test card that will decline. Instead of a fatal error because of a failure, you should instead see a notice with the error.

    Product impact

    • [ ] Added changelog entry (or does not apply)
    • [x] Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
    • [x] Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
    opened by tommyshellberg 1
Releases(5.1.0)
  • 5.1.0(Nov 24, 2022)

    * Fix - Set payment tokens when copying data between orders and subscriptions in a CRUD compatible way. Fixes PHP notices during renewal order process.
    * Fix - Infinite loop that can occur with `WCS_Orders_Table_Subscription_Data_Store::read_multiple()` on HPOS-enabled stores.
    * Fix - On HPOS stores, when querying for subscriptions with wcs_get_orders_with_meta_query() with status 'any', ensure that wc_get_orders() queries for subscription statuses.
    * Fix - On HPOS stores, when saving a subscription make sure subscription properties (ie `_requires_manual_renewal`) are saved to the database.
    * Fix - On HPOS stores, when a subscription is loaded from the database, make sure all core subscription properties are read directly from meta.
    * Fix - When viewing My Account > Subscriptions, fix an issue where no subscriptions were listed when HPOS is enabled.
    * Fix - On HPOS stores, ensure payment tokens are copied from the subscription to the renewal order.
    * Fix - Refactor `WCS_Meta_Box_Schedule::save` to support HPOS stores, fixing a PHP warning notice when updating an order via the Edit Order screen.
    * Fix - Return a fresh instance of the renewal order after creating it. Fixes caching issues on HPOS sites where the returned order has no line items.
    * Fix - Processing a manual renewal order with HPOS and data syncing enabled correctly saves the related order cache metadata on the subscription and prevents the post and order meta data getting out of sync.
    * Fix - Use supported CRUD apis to determine if subscriptions are present on store (`wcs_do_subscriptions_exist`)
    * Fix - With HPOS and data syncing enabled, updating the status of a pending manual renewal order to a paid status correctly activates the related subscription.
    * Update - Refactor the `wcs_is_subscription` helper function to support HPOS.
    * Update - Refactor our Related Orders data store classes (WCS_Related_Order_Store_Cached_CPT and WCS_Related_Order_Store_CPT) to use CRUD methods to support subscriptions and orders stored in HPOS.
    * Update - Display related orders table when viewing the new "Edit Order" page (HPOS enabled stores).
    * Fix - On HPOS stores, make sure the links in the related-orders table redirect to the new Edit Order URL.
    * Dev - Removed the deprecated "wcs_subscriptions_for_{$relation_type}_order" dynamic hook used to filter the list of related subscriptions for the given relation type. The following hooks have been removed with no alternative:
            wcs_subscriptions_for_renewal_order
            wcs_subscriptions_for_switch_order
            wcs_subscriptions_for_resubscribe_order
    * Dev - Introduce a WC_Subscription::set_status() function to handle subscriptions set with a draft or auto-draft status. Replaces the need for the overriding WC_Subscription::get_status() which has been deleted.
    * Dev - Manual renewal orders created with HPOS and data syncing enabled are properly linked to the subscription by its `_subscription_renewal` meta and backfilled to posts table.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.5.2(Nov 15, 2022)

    * Fix - When creating a subscription via the checkout, make sure a new instance of the subscription is attached to the `woocommerce_checkout_subscription_created` action hook.
    
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0(Nov 14, 2022)

    * Dev - The library has been bumped to version to 5.0.0 to reduce confusion with the version of WooCommerce Subscriptions.
    * Dev - Usage of \WC_Subscriptions_Core_Plugin::get_plugin_version() is no longer recommended for version detection. \WC_Subscriptions_Core_Plugin::get_library_version() should be used instead.
    * Add - New wcs_get_orders_with_meta_query() helper function to query for orders and subscriptions.
    * Update - Replace instances of `get_posts()` across codebase with new wcs_get_orders_with_meta_query() function.
    * Dev - Code that was tagged with a version and moved from WooCommerce Subscriptions now explicitly mentions this and shows the correct subscriptions-core and WC Subscriptions versions.
    * Dev - Refactor the saving of subscription dates in the subscription datastore to separate fetching changes and saving. Enables backfilling subscription dates when HPOS syncing is enabled.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.5.1(Nov 4, 2022)

    * Dev - Replace the use of the deprecated wcs_renewal_order_meta hook with wc_subscription_renewal_order_data in the WCS_Related_Order_Store_Cached_CPT class.
    * Dev - Fix typo in deprecation notice for the 'wcs_{type}_meta_query' filter. Incorrect replacement hook.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.5.0(Nov 4, 2022)

    * Add - New WCS_Orders_Table_Subscription_Data_Store class to support subscriptions stored in High-Performance Order Storage (HPOS).
    * Add - New WCS_Orders_Table_Data_Store_Controller class to load the proper subscriptions data store when the store has HPOS enabled.
    * Add - New data copier class to copy data to subscriptions and related orders in place of direct database queries in prepraration for HPOS support.
    * Fix - When saving sync meta data on a new subscription, use 'woocommerce_new_subscription' instead of 'save_post'. This is to prevent errors when purchasing a subscription on stores that have HPOS enabled.
    * Update - Improve maybe_add_subscription_meta() and subscription_contains_synced_product() inside our WC_Subscriptions_Synchroniser class to use CRUD methods.
    * Dev - wcs_get_objects_property and wcs_set_objects_property have been marked as deprecated. Getters/Setters should be used on the objects instead.
    * Dev - Deprecated the "wcs_{type}_meta_query" dynamic hook used to alter the database query used to fetch the meta data to copy between subscriptions and renewal orders. There is no direct replacement. Third-parties should use the "wc_subscriptions_{type}_data" or "wc_subscriptions_object_data" hooks instead.
    * Dev - Deprecated the "wcs_{type}_meta" dynamic hook used to filter data copied to subscriptions and renewal orders. Third-parties should use wc_subscriptions_{type}_data instead.
            wcs_subscription_meta      -> wc_subscriptions_subscription_data
            wcs_parent_meta            -> wc_subscriptions_parent_data
            wcs_resubscribe_order_meta -> wc_subscriptions_resubscribe_order_data
            wcs_renewal_order_meta     -> wc_subscriptions_renewal_order_data
    
    Source code(tar.gz)
    Source code(zip)
  • 2.4.1(Nov 2, 2022)

    * Fix - Undefined method WC_Order::set_shipping_address() on stores running pre-7.1 of WooCommerce which prevented subscriptions from being purchased.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.4.0(Oct 28, 2022)

    * Update - The subscription creation function `wcs_create_subscription` has been updated to use WooCommerce CRUD methods in preparation for supporting High Performance Order Storage (HPOS).
    * Update - Improve wcs_copy_order_address() to use modern APIs for setting address fields.
    * Dev - woocommerce_new_subscription_data hook will only work with CPT datastore and so has been deprecated.
    * Dev - i18n usage of strftime has been deprecated for subscription titles. Date is now formatted using woocommerce standard date formatting.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.3.0(Oct 7, 2022)

    * Fix - Move One Time Shipping metabox fields to use the woocommerce_product_options_shipping_product_data hook introduced in WC 6.0.
    * Dev - Define build tool version requirements for consistent development and build environments.
    * Update - Improve handling of bulk action execution.
    
    Source code(tar.gz)
    Source code(zip)
  • 2.2.1(Aug 25, 2022)

  • 2.2.0(Aug 3, 2022)

  • 2.1.0(Jun 6, 2022)

  • 2.0.0(May 23, 2022)

    * Dev - Retrieving users subscriptions order has been updated to use the WooCommerce specific APIs in WC_Subscriptions_Order.
    * Dev - Deprecate the WC_Subscriptions_Order::get_meta() function. Use wcs_get_objects_property( $order, $meta_key, "single", $default ) instead.
    * Dev - Update the wcs_get_objects_property() function to prevent calls to get_post_meta() on objects that support calling the get_meta() function.
    * Dev - Remove the get_post_meta() call from WCS_Post_Meta_Cache_Manager::maybe_update_for_post_change().
    * Dev - Replace code using get_post_type( $order_id ) with WC Data Store get_order_type().
    * Dev - Replace all cases of update_post_meta() where an Order ID is passed to use WC_Order::update_meta_data() instead. 
    
    Source code(tar.gz)
    Source code(zip)
  • 1.9.0(May 11, 2022)

    * Fix: Display subscription billing details in the Cart Block when purchasing products with subscription plans created using the All Products extension. PR#149
    * Dev: Update phpunit to v9 to allow testing against newer php versions. PR#140
    
    Source code(tar.gz)
    Source code(zip)
  • 1.8.0(Apr 5, 2022)

  • 1.7.0(Mar 18, 2022)

    • Fix: Sets up subscriptions integration with the Mini Cart Block and adds new hook to filter compatible blocks. PR#103
    • Fix: When using a WooCommerce Blocks powered checkout, fix an issue that led to limited products being removed from the cart when completing a switch or renewal order. PR#119 wcs#4232
    • Fix: When there is only one Shipping Method available in the recurring shipping package, make sure that this method is treated as selected in the current session and the woocommerce_after_shipping_rate action runs. PR#115
    • Fix: Don't anonymize new subscriptions related to old subscriptions via a resubscribe relationship. PR#121 wcs#4304 wcpay#3889
    • Fix: Content that appears on the My account > Payment methods page should be translatable. PR#125 wcs#4180 wcpay#3974
    Source code(tar.gz)
    Source code(zip)
  • 1.6.4(Feb 10, 2022)

    2022-02-10 - version 1.6.4

    • Fix: When changing the payment method, make sure the subscription total returns $0 when subscriptions-core is loaded after the woocommerce_loaded action hook. PR#111 wcpay#3768
    Source code(tar.gz)
    Source code(zip)
  • 1.6.3(Feb 7, 2022)

    2022-02-07 - version 1.6.3

    • Fix: Replace uses of is_ajax() with wp_doing_ajax(). PR#108 wcpay#3695 wcs#4296
    • Improve handling of session data.
    Source code(tar.gz)
    Source code(zip)
  • 1.6.2(Jan 19, 2022)

  • 1.6.1(Jan 18, 2022)

    2022-01-18 - version 1.6.1

    • Dev: Update the list of "export-ignore" in .gitattributes to include recent developer files. PR#97
    • Dev: Set the composer package type to "wordpress-plugin". PR#96
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0(Jan 17, 2022)

    2022-01-17 - version 1.6.0

    • Fix: When viewing a WCPay Subscription product page, make sure other gateway's express payment buttons aren't shown. PR#87 wcpay#3401
    • Fix: When viewing a WC Product page with a WCPay subscription product in cart, make sure other gateway's express payment buttons are shown. PR#87 wcpay#3401
    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(Jan 14, 2022)

    2022-01-14 - version 1.5.0

    • New: Introduce filter to allow third-parties to specify the minimum recurring amount the payment method can support. Displays a warning to the merchant when creating products below that amount. #PR89 wcpay#3542
    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(Jan 11, 2022)

    2022-01-03 - version 1.4.0

    • Fix: Simple subscription elements on the product edit page not shown/hidden when necessary. PR#80
    • Fix: Prevent fatal errors on the admin subscriptions screen when a subscription fails to load. PR#84 wcpay#3596 wcs#4286
    • Fix: Compatibility issue when loading subscriptions templates. PR#86 wcpay#3606 wcs#4291
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Dec 21, 2021)

    2021-12-21 - version 1.3.0

    • Fix: Remove references to the Subscription extension in the tooltips found on the Payment Methods settings table. PR#55 wcpay#3234
    • Fix: Update the Automatic Recurring Payments column on the Payment Methods table to only show which payment methods are supported by Subscriptions Core. PR#55
    • Tweak: Update deprecation message when calling WC_Subscriptions_Coupon::cart_contains_limited_recurring_coupon() to mention the correct replacement function. PR#53
    • Fix: Prevent deprecation warnings when using WooCommerce Blocks. PR#54
    • Tweak: Update recurring payments copy on payment gateways page.
    • Fix: Incorrect text when filtering subscriptions to no results.
    • Changed: Subscription products must have a recurring amount greater than $0. PR#56 wcpay#3309
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Nov 23, 2021)

    2021-11-23 - version 1.2.0

    • Fix: Update tooltip wording when deleting product variation. PR#46
    • Fix: Don't show an admin error notice when a store downgrades to a previous minor version of Subscriptions. WCS#4271
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Nov 12, 2021)

    2021-11-12 - version 1.1.0

    • Fix: Add consistent margins to the recurring taxes totals row on the Checkout and Cart block. PR#39
    • Fix: Fatal error due to order with no created date in order row template. PR#40
    • Fix: Fatal error on the customer payment page for renewal orders with deleted products. PR#42
    • Fix: Misleading order note on payment method change. PR#41
    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Oct 29, 2021)

  • 1.0.2(Oct 28, 2021)

  • 1.0.1(Oct 25, 2021)

    2021-10-22 - version 1.0.1

    • Fix: Don't show a downgrade notice when activating the WC Subscriptions extension after installing WCS Core. PR#7
    • Fix: Correctly show the available payment methods when paying for a subscription renewal order. PR#9
    • Fix: Don't show the WC Subscriptions extension welcome/installation message after installing WCS Core. PR#11
    • Fix: Remove the "Welcome to Subscriptions" notice that is displayed upon upgrading from previous minor versions. PR#14
    • Fix: Don't display a "Welcome to Subscriptions 2.1" for stores that have upgraded from really old version of Subscriptions. PR#16
    • Fix: Errors during the upgrade process for stores that are upgrading from very old versions of Subscriptions (1.5.0). PR#16
    • Fix: Show subscription billing information (recurring cart totals, sign up fees etc) on the WooCommerce Checkout block. PR#18
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Oct 19, 2021)

Owner
Automattic
We are passionate about making the web a better place.
Automattic
PHP 7+ Payment processing library. It offers everything you need to work with payments: Credit card & offsite purchasing, subscriptions, payouts etc. - provided by Forma-Pro

Supporting Payum Payum is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our

Payum 1.7k Jan 5, 2023
The Marketplace plugin for WordPress and WooCommerce

WC Vendors 2.0 is a major update. This has a brand new settings system that is not backwards compatible with the existing one. This means all extensions and plugins that interact with WC Vendors will need to be updated to support this new system.

WC Vendors 147 Dec 16, 2022
Cardano Mercury Payment Gateway for WooCommerce

Cardano Mercury for WooCommerce Simple, reliable plugin to accept Cardano (Ada) payments for goods and services in WooCommerce. Version: 1.0 Tags: woo

null 25 Aug 3, 2022
Enable Standard PayPal for WooCommerce

Enable Standard PayPal for WooCommerce Contributors: vikcheema Donate link: https://paypal.me/SukhwantCheema Tags: woocommerce, payment gateway, paypa

Vik Cheema 2 Sep 9, 2021
Adds a new report to the WooCommerce analytics section about used payment methods.

Payment Methods Report for WooCommerce This is an extension to WooCommerce Analytics that will display a new report on the usage of configured payment

Martin Rehberger 1 Jan 15, 2022
Plugin for Woocommerce that enables Visanet's Cybersource payment gateway as a payment method in your website checkout

Plugin for Woocommerce that enables Visanet's Cybersource payment gateway as a payment method in your website checkout

tipi(code) 2 Mar 8, 2022
Chargily ePay Gateway (WooCommerce Plugin)

Chargily ePay Gateway Donate link: https://epay.chargily.com/ chargily, payment, paiement, epay, cib, cibweb, edahabia, algerie, poste, satim, gie, mo

Chargily 15 Dec 7, 2022
Cargo Tracking for WooCommerce

With the WooCommerce cargo tracking plugin, you can add as many cargo companies as you want, show cargo tracking links on the front and admin side, and send cargo tracking emails to users.

İlhan Aydınlı 5 Dec 2, 2022
Commerce GrappQL Package for Laravel

Sailwork Commerce Package for Laravel Document Please read document in here: Document Installation You can install the package via composer: composer

Sail Work 6 May 10, 2021
A PHP package to simplify using DPO Payment API in your application.

DPO (Direct Pay Online) PHP Package The best DPO php package, simple Ever This is the package that will help you add DPO Payment API to your PHP Appli

Zepson Technologies 3 Nov 8, 2022
Laravel paypal payment package , help you process credit card payment using paypal api

Important :The use of the PayPal REST /payments APIs to accept credit card payments is restricted by paypal and they recomand to use Braintree Direct

Anouar Absslm 328 Oct 31, 2022
Laravel Shopping Cart Package

LaraCart - Laravel Shopping Cart Package (http://laracart.lukepolo.com) Features Coupons Session Based System Cross Device Support Multiple cart insta

Luke Policinski 516 Dec 10, 2022
GetCandy is a package that brings functionality akin to Shopify and other e-commerce platforms to Laravel.

GetCandy is a set of Laravel packages that bring functionality akin to Shopify and other e-commerce platforms to Laravel. You have complete freedom to

GetCandy 7 Oct 27, 2022
Aimeos is THE professional, full-featured and high performance e-commerce package for Laravel

Aimeos Slim package ⭐ Star us on GitHub — it helps! Aimeos is THE professional, full-featured and high performance e-commerce package for Laravel! You

Aimeos 101 Sep 14, 2022
Stores the customer_user for WooCommerce orders and subscriptions in the post_author column of posts table.

Post Author Optimization for WooCommerce Requires PHP: 7.0 WP requires at least: 5.7 WP tested up to: 5.7 WC requires at least: 5.6.0 WC tested up to:

Devin Price 9 Apr 2, 2022
Donation Platform for WooCommerce unleashes the power of WooCommerce for your online fundraising, crowdfunding & crowdsponsoring

=== Donation Platform for WooCommerce === Contributors: flinnn Tags: donation, donations, crowdfunding, fundraising, woocommerce Requires at least: 5.

Jonas Höbenreich 15 Dec 21, 2022
WooCommerce Empty Cart Button plugin helps you to add Empty Cart button to WooCommerce Pages/Sections using Shortcode only.

WooCommerce Empty Cart Button plugin helps you to add Empty Cart button to WooCommerce Pages/Sections using Shortcode only. How to use? Download the p

Katr 2 Sep 24, 2022
An E-Commerce package for Laravel with Grafite CMS. Take control of your content and how you sell it! Products, subscriptions, shipping, downloading and more!

Grafite Commerce Grafite has archived this project and no longer supports or develops its code. We recommend using only as a source of ideas for your

Grafite Inc 45 Jun 8, 2021
Laravel Soulbscription - This package provides a straightforward interface to handle subscriptions and features consumption.

About This package provides a straightforward interface to handle subscriptions and features consumption. Installation You can

Lucas Vinicius 269 Jan 1, 2023
Laravel Plans is a package for SaaS apps that need management over plans, features, subscriptions, events for plans or limited, countable features.

Laravel Plans Laravel Plans is a package for SaaS apps that need management over plans, features, subscriptions, events for plans or limited, countabl

ángel 2 Oct 2, 2022