fix: allow trial for returning customers whose cancelled WCS sub had zero renewals#1061
Conversation
…zero renewals Fixes ~14% of UM+WCS checkouts where _schedule_trial_end=0 and _schedule_next_payment is set to now+billing_period instead of now+trial_period, causing the first charge to fire immediately rather than after the advertised trial. Root cause: has_trial() blocked trial eligibility for any customer with a cancelled WCS subscription whose parent WC order was completed — even when that subscription was cancelled due to a double-checkout or payment-gateway race and the customer never completed a billing cycle. Double-checkout path (seen in kp-trial-cancel-guard.php context): 1. Customer submits checkout form twice in quick succession 2. Two WCS subscriptions are created; UM/WCS cancels the first 3. The cancelled sub has a completed parent order 4. Next checkout: has_trial() finds the cancelled sub → returns false 5. WC product gets _subscription_trial_length=0 6. WCS schedules next_payment=now+billing_period instead of trial_end Fix: for cancelled subs with a completed parent order, also require at least one renewal order before blocking the trial. Zero renewals means the subscription never completed a billing cycle and should not count as prior subscription history. Verified in dev (WordPress + WCS bundled): - Sub: status=cancelled, parent_order=completed, renewal_orders=0 - Before fix: has_trial() = false (trial blocked, _schedule_trial_end=0) - After fix: has_trial() = true (trial allowed, correct scheduling) - Genuine returner with renewals: still correctly blocked
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
🔨 Build Complete - Ready for Testing!📦 Download Build Artifact (Recommended)Download the zip build, upload to WordPress and test:
🌐 Test in WordPress Playground (Very Experimental)Click the link below to instantly test this PR in your browser - no installation needed! Login credentials: |
|
Performance Test Results Performance test results for 0e929b4 are in 🛎️! Note: the numbers in parentheses show the difference to the previous (baseline) test run. Differences below 2% or 0.5 in absolute values are not shown. URL:
|
Summary
_schedule_trial_end=0and_schedule_next_paymentis set tonow+billing_periodinstead ofnow+trial_period, causing the first charge to fire immediately instead of after the advertised trial.Root cause
has_trial()ininc/checkout/class-cart.phpblocked trial eligibility for any customer with a cancelled WCS subscription whose parent WC order was completed — even when that subscription was cancelled due to a double-checkout or payment-gateway race and the customer never completed a billing cycle.Failure chain
completedhas_trial()finds the cancelled sub →return falsemaybe_create_productgets$days_to_start = 0→ no_subscription_trial_lengthon WC product_schedule_trial_end = 0andnext_payment = now+billing_periodThe existing guard (added in 2.4.14) already skips cancelled subs whose parent order was not completed. This PR adds a second gate: also skip if the subscription had zero renewal orders, meaning it never completed a billing cycle.
Change
File:
inc/checkout/class-cart.php—has_trial(), line ~2310Verification
Reproduced and fixed in the dev WordPress environment:
has_trial() = false❌has_trial() = true✅has_trial() = false✅has_trial() = false✅has_trial() = false✅has_trial() = false✅has_trial() = true✅has_trial() = true✅Verified by running the exact subscription/cart logic directly in
wp evalagainst a real cancelled+completed sub with 0 renewals (sub #73 in dev).Impact
kp-trial-cancel-guard.phpmu-plugin on Kursopro guards a related but distinct symptom — can be audited for removal once this and the sync_subscription_status guards (2.2.x) are confirmed stable in production.aidevops.sh v3.13.78 plugin for OpenCode v1.3.17 with claude-sonnet-4-6 spent 1h 58m and 107,964 tokens on this with the user in an interactive session.
Summary by CodeRabbit
Release Notes