Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(esp-sync): get inactive subscriptions with failed or pending orders #3658

Merged
merged 7 commits into from
Jan 9, 2025

Conversation

dkoo
Copy link
Contributor

@dkoo dkoo commented Jan 8, 2025

All Submissions:

Changes proposed in this Pull Request:

Fixes an issue where Newspack\Reader_Activation\Sync\WooCommerce::get_most_recent_cancelled_or_expired_subscription( $user_id ) fails to get subscriptions whose most recent order has a failed or pending status. This is because $subscription->get_date( 'last_order_date_completed' ) will only return a value if the subscription's most recent order has a completed status.

How to test the changes in this Pull Request:

  1. As a new reader, purchase a subscription.
  2. As an admin, edit the subscription and use the "Order actions" menu to create a pending renewal order for the subscription (this will put the subscription into "on hold" status"):
Screenshot 2025-01-07 at 4 36 32 PM
  1. On release, using wp shell, run \Newspack\Reader_Activation\Sync\WooCommerce::get_contact_from_customer( $user_id ); to get the contact data for the order. Observe that the contact data does not contain any info about the on-hold subscription:
> \Newspack\Reader_Activation\Sync\WooCommerce::get_contact_from_customer( 127 );

= [
    "email" => "[email protected]",
    "metadata" => [
      "account" => 127,
      "registration_date" => "2025-01-07 22:40:54",
      "total_paid" => "",
      "membership_status" => "",
      "payment_page" => "",
      "payment_page_utm" => "",
      "sub_start_date" => "",
      "sub_end_date" => "",
      "cancellation_reason" => "",
      "billing_cycle" => "",
      "recurring_payment" => "",
      "last_payment_date" => "",
      "last_payment_amount" => "",
      "product_name" => "",
      "next_payment_date" => "",
    ],
    "name" => "Test Contact",
  ]
  1. Check out this branch, start a new wp shell session, and confirm that \Newspack\Reader_Activation\Sync\WooCommerce::get_contact_from_customer( $user_id ); now contains info about the on-hold subscription:
> \Newspack\Reader_Activation\Sync\WooCommerce::get_contact_from_customer( 127 );
= [
    "email" => "[email protected]",
    "metadata" => [
      "payment_page" => "https://localhost/support/?utm_campaign=Newspack%202025&utm_content=testing",
      "payment_page_utm_campaign" => "Newspack 2025",
      "payment_page_utm_content" => "testing",
      "membership_status" => "on-hold",
      "sub_start_date" => "2025-01-07 22:40:55",
      "sub_end_date" => "",
      "billing_cycle" => "month",
      "recurring_payment" => "25.00",
      "last_payment_amount" => "25.00",
      "last_payment_date" => "2025-01-08 16:47:45",
      "next_payment_date" => "2025-02-07 22:40:55",
      "product_name" => "All Access - Monthly",
      "payment_page_utm_source" => "",
      "payment_page_utm_medium" => "",
      "payment_page_utm_term" => "",
      "cancellation_reason" => "",
      "total_paid" => "75.00",
      "account" => 127,
      "registration_date" => "2025-01-07 22:40:54",
    ],
    "name" => "Test Contact",
  ]

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@dkoo dkoo added the [Status] Needs Review The issue or pull request needs to be reviewed label Jan 8, 2025
@dkoo dkoo self-assigned this Jan 8, 2025
@dkoo dkoo requested a review from a team as a code owner January 8, 2025 16:49
Copy link
Contributor

@leogermani leogermani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works.

I have pushed one commit. I noticed that if a subscription is set to on-hold, the Membership status would not get the "Ex-" prefix.

I have a small performance feedback:

While looping through the related orders, if we find one completed order, that would be enough. In the current implementation we'll always loop through all the orders, and call wc_get_order to all of them even if it's not necessary. It would be better to exit the loop when we find the first completed order.

And a nitpick. You don't need array_keys there, as get_related_orders also return the IDs in the values. example:

array(1) {
  [4788]=>
  int(4788)
}

@dkoo
Copy link
Contributor Author

dkoo commented Jan 8, 2025

@leogermani 82f889a does a little refactoring to address your feedback—thanks!

// Only subscriptions that had a completed order are considered.
if ( ! empty( $subscription->get_date( 'last_order_date_completed' ) ) ) {
// Only subscriptions that have at least one completed order are considered.
$related_orders = $subscription->get_related_orders( 'all' );
Copy link
Contributor

@leogermani leogermani Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the change to add the all param is making woocommerce-subscriptions call wc_get_order for every order. So the gain in performance we had here was nulled by the fact that we are calling wc_get_order for all orders anyways. (see https://github.com/woocommerce/-unused-woocommerce-subscriptions/blob/bff84d85400f964c4ddfc048381db9bf7be400d7/includes/class-wc-subscription.php#L1836 )

We can just get the ids as before, and only fetch the order details as needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But now that we need to check the status of each order, we'd need to call wc_get_order() ourselves anyway if we don't use the all argument. Unless there's a way to get an order's status by order ID without fetching the whole object that I don't know about?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I found a better way to do it. 882a2e6 uses WC_Subscription::get_payment_count() to check the number of completed orders for the subscription instead of fetching and iterating through all orders.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b921675 should be safest

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leogermani let me know if you have any other improvements to suggest!

@dkoo dkoo requested a review from leogermani January 9, 2025 16:34
@github-actions github-actions bot added [Status] Approved The pull request has been reviewed and is ready to merge and removed [Status] Needs Review The issue or pull request needs to be reviewed labels Jan 9, 2025
@dkoo dkoo merged commit cca29d3 into release Jan 9, 2025
11 checks passed
@dkoo dkoo deleted the hotfix/get-reader-inactive-subscriptions branch January 9, 2025 21:41
matticbot pushed a commit that referenced this pull request Jan 9, 2025
## [5.10.6](v5.10.5...v5.10.6) (2025-01-09)

### Bug Fixes

* **esp-sync:** get inactive subscriptions with failed or pending orders ([#3658](#3658)) ([cca29d3](cca29d3))
@matticbot
Copy link
Contributor

🎉 This PR is included in version 5.10.6 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released [Status] Approved The pull request has been reviewed and is ready to merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants