-
Notifications
You must be signed in to change notification settings - Fork 2k
Show Expired status for monetize subscriptions past their end date #107864
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
Conversation
Jetpack Cloud live (direct link)
Automattic for Agencies live (direct link)
|
|
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser: App Entrypoints (~63 bytes added 📈 [gzipped]) DetailsCommon code that is always downloaded and parsed every time the app is loaded, no matter which route is used. Sections (~273 bytes added 📈 [gzipped]) DetailsSections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to. Async-loaded Components (~65 bytes added 📈 [gzipped]) DetailsReact components that are loaded lazily, when a certain part of UI is displayed for the first time. Legend What is parsed and gzip size?Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory. Generated by performance advisor bot at iscalypsofastyet.com. |
43a5bfd to
745f3c4
Compare
|
This PR modifies the release build for the following Calypso Apps: For info about this notification, see here: PCYsg-OT6-p2
To test WordPress.com changes, run |
sirbrillig
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely better than what was there before but I think we can be more accurate about the definition of "today" without a large amount of additional work.
client/dashboard/me/billing-monetize-subscriptions/monetize-item.tsx
Outdated
Show resolved
Hide resolved
97a8620 to
10205aa
Compare
sirbrillig
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
| } | ||
|
|
||
| // Check if end_date is in the past (convert to ISO 8601 and append Z to parse as UTC) | ||
| const endDate = new Date( subscription.end_date.replace( ' ', 'T' ) + 'Z' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a useful technique! It may be worth putting it into a helper function somewhere. It looks like regular purchases end up serialized in ISO8601 already (eg: expiry_date: '2026-11-13T00:00:00+00:00') so this might only be important for Monetize purchases. Though if we made a helper it should probably include a little more protection to make sure there's no time zone already (I think maybe just check for a +?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I've added a parseDateAsUTC() helper in datetime.ts. It only"fixes" datetime strings that don't already have timezone info. Anything with Z or +00:00 passes through unchanged to new Date().
- 2026-01-06 12:00:00 → 2026-01-06T12:00:00Z
- 2026-01-06 12:00:00.123456 → 2026-01-06T12:00:00.123456Z
- 2026-01-06T12:00:00 → 2026-01-06T12:00:00Z
- 2026-01-06T12:00:00Z → pass through
- 2026-01-06T12:00:00+00:00 → pass through
10205aa to
35c573f
Compare
35c573f to
8ae710d
Compare
…107864) * Show Expired status for monetize subscriptions past their end date * Show 'Expired X ago' with error styling for expired monetize subscriptions * Fix 'Expired today' to use calendar day comparison instead of 24-hour window * Fix timezone parsing for monetize subscription dates * Add parseDateAsUTC helper to convert MYSQL to ISO8601
Resolves #MON-63
Proposed changes
Add expiry date check to MonetizeSubscriptionTerms component in the Hosting Dashboard
Add expiry date check to MembershipTerms component in legacy Calypso
Use calendar day comparison (
isToday()/moment().isSame(day)) instead of 24-hour window for "Expired today" detectionReturn "Expired today" or "Expired X ago" status with error styling when end_date is in the past, matching existing WPCOM purchase behavior
Fix incorrect translator comment that referenced non-existent %(siteUrl)s placeholder
Why are these changes being made?
When a monetize/membership subscription expires, the UI incorrectly displays "Renews at $X on [past date]" instead of showing "Expired". This is confusing for users who see a renewal date that has already passed. We should basically display this like we display other expired subscriptions in Calypso and the Hosting Dashboard.
The fix adds a simple date comparison before rendering the renewal/expiry text. If the end_date is in the past, we now show "Expired today" or "Expired X ago" with error styling, matching how other expired subscriptions are displayed.
Technical context
Monetize/membership subscriptions use a different data model than WPCOM purchases (plans, domains):
For WPCOM purchases, the backend calculates and returns an expiryStatus field that the frontend uses directly. For monetize subscriptions, items with status='active' are returned regardless of whether end_date has passed - the frontend was not checking for this condition.
This fix adds a frontend date comparison to handle the case where status='active' but end_date is in the past. A backend change to calculate an expiryStatus equivalent could be considered for future consistency, but this frontend fix is sufficient for correct display.
Testing instructions
Manual Testing
Prerequisites
Find a Site with Existing Expired Subscription and/or Manipulate data on sandbox:
change the following to hard coded values:
Navigate to Hosting Dashboard billing: http://calypso.localhost:3000/me/purchases
Load /me/billing/monetize-subscriptions and validate the same
Before Fix
After Fix
Test Cases to Verify
Pre-merge Checklist