Conversation
ca28c5f to
8545da3
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (3)
WalkthroughThe pull request adds an 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ast-grep (0.42.1)ghost/core/test/unit/server/services/members/members-api/repositories/member-repository.test.jsThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ca28c5fd5b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/portal/src/utils/helpers.js`:
- Around line 116-117: The archived-tier check currently calls getProductFromId
which uses getAllProductsForSite and can return false positives due to portal
plan filters; change the logic to directly inspect site.products instead:
replace the call to getProductFromId({site, productId: tierId}) with a direct
search in site.products (e.g., find or some equivalent) to determine if the
tierId exists on the site, so archived detection relies only on site.products
rather than filtered getAllProductsForSite/getProductFromId.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4e14d588-1a95-4dc6-8fa6-ca0c2aa17cc3
📒 Files selected for processing (7)
apps/portal/package.jsonapps/portal/src/components/pages/AccountHomePage/components/continue-gift-subscription-banner.jsapps/portal/src/components/pages/AccountHomePage/components/paid-account-actions.jsapps/portal/src/utils/helpers.jsapps/portal/test/utils/helpers.test.jsghost/core/core/server/services/members/members-api/repositories/member-repository.jsghost/core/test/unit/server/services/members/members-api/repositories/member-repository.test.js
We validate that a tier is active at the time a gift is purchased. After purchase, gifts should remain redeemable even if the tier is later archived, since it has already been paid for already. This change allows gifts to be redeemed on an archived tier.
Additionally, this creates a dead end when a gift subscriber chooses to continue as a paid member. The current UI only allows continuation on the same tier/cadence so remaining gift time can be carried over as trial days. If that tier has since been archived, this results in users trying to continue onto an unavailable tier. With this change, we now render the standard upgrade flow when the gifted tier is no longer available, letting the member pick from current
active tiers. The trade-off is that the remaining gift days can't be preserved in that case; archived tiers are expected to be an edge case in practice.
Portal:
- New `isArchivedTier({member, site})` helper that follows the existing
`isActiveOffer` pattern (a tier id missing from `site.products` means
the tier has been archived).
- The gift "Continue subscription" banner and the gift-specific
Continue button on the account page are gated on the tier still
being available; otherwise the regular Change button takes over and
routes the member through the standard upgrade screen.
Backend:
- `MemberRepository.create` / `update` previously rejected any product
that wasn't `active` with "Cannot use archived Tiers", which also
blocked the gift-redemption path (creating a member on the gifted
tier). The check is now skipped when `status === 'gift'`. Non-gift
paths (comped, paid) keep the archived-tier block.
- In `create()`, the products validation block was moved below the
status defaulting block so the gift carve-out can read the resolved
status.
8545da3 to
36f2432
Compare
closes https://linear.app/ghost/issue/BER-3566
We validate that a tier is active at the time a gift is purchased. After purchase, gifts should remain redeemable even if the tier is later archived, since they have already been paid for already. This change allows gifts to be redeemed on an archived tier.
Additionally, gift members can currently only continue their subscription on the same tier/cadence so remaining gift time can be carried over as trial days. If that tier has since been archived, this results in a checkout error, as we don't allow paid subscriptions on archived tiers. With this change, the UI renders the standard upgrade flow when the gifted tier is no longer available, letting the member pick from current active tiers. The trade-off is that the remaining gift days can't be preserved in that case; archived tiers are expected to be an edge case in practice.
What changed
Portal:
isArchivedTier({member, site})helper that follows the existingisActiveOfferpattern (a tier id missing fromsite.productsmeans the tier has been archived).Backend:
MemberRepository.create/updatepreviously rejected any product that wasn'tactivewith "Cannot use archived Tiers", which also blocked the gift-redemption path (creating a member on the gifted tier). The check is now skipped whenstatus === 'gift'. Non-gift paths (comped, paid) keep the archived-tier block.create(), the products validation block was moved below the status defaulting block so the gift carve-out can read the resolved status.