mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-25 02:00:10 +02:00
Merge pull request #23314 from overleaf/ls-update-group-plan-upgrade-mapping
Update group plan upgrade mapping GitOrigin-RevId: aca3d986477dbcf0561635dfd771413a2ba1ef15
This commit is contained in:
@@ -227,29 +227,16 @@ class RecurlySubscription {
|
||||
* Upgrade group plan with the plan code provided
|
||||
*
|
||||
* @param {string} newPlanCode
|
||||
* @param {number} membersLimit
|
||||
* @return {RecurlySubscriptionChangeRequest}
|
||||
*/
|
||||
getRequestForGroupPlanUpgrade(newPlanCode, membersLimit) {
|
||||
getRequestForGroupPlanUpgrade(newPlanCode) {
|
||||
// Ensure all the existing add-ons are added to the new plan
|
||||
// Except for the additional license, which will be added below
|
||||
const addOns = this.addOns
|
||||
.filter(addOn => addOn.code !== 'additional-license')
|
||||
.map(
|
||||
addOn =>
|
||||
new RecurlySubscriptionAddOnUpdate({
|
||||
code: addOn.code,
|
||||
quantity: addOn.quantity,
|
||||
})
|
||||
)
|
||||
|
||||
// Get the number of licenses from the membersLimit field in the Subscription model
|
||||
// This is necessary because legacy group plans do not fully use add-ons to represent seats
|
||||
addOns.push(
|
||||
new RecurlySubscriptionAddOnUpdate({
|
||||
code: 'additional-license',
|
||||
quantity: membersLimit,
|
||||
})
|
||||
const addOns = this.addOns.map(
|
||||
addOn =>
|
||||
new RecurlySubscriptionAddOnUpdate({
|
||||
code: addOn.code,
|
||||
quantity: addOn.quantity,
|
||||
})
|
||||
)
|
||||
|
||||
return new RecurlySubscriptionChangeRequest({
|
||||
|
||||
@@ -683,6 +683,31 @@ async function getLatamCountryBannerDetails(req, res) {
|
||||
return latamCountryBannerDetails
|
||||
}
|
||||
|
||||
/**
|
||||
* There are two sets of group plans: legacy plans and consolidated plans,
|
||||
* and their naming conventions differ.
|
||||
* This helper method computes the name of legacy group plans to ensure
|
||||
* consistency with the naming of consolidated group plans.
|
||||
*
|
||||
* @param {string} planName
|
||||
* @param {string} planCode
|
||||
* @return {string}
|
||||
*/
|
||||
|
||||
function getPlanNameForDisplay(planName, planCode) {
|
||||
const match = planCode.match(
|
||||
/^group_(collaborator|professional)_\d+_(enterprise|educational)$/
|
||||
)
|
||||
|
||||
if (!match) return planName
|
||||
|
||||
const [, type, category] = match
|
||||
const prefix = type === 'collaborator' ? 'Standard' : 'Professional'
|
||||
const suffix = category === 'educational' ? ' Educational' : ''
|
||||
|
||||
return `Overleaf ${prefix} Group${suffix}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a subscription change preview for display purposes
|
||||
*
|
||||
@@ -711,7 +736,10 @@ function makeChangePreview(
|
||||
nextInvoice: {
|
||||
date: subscription.periodEnd.toISOString(),
|
||||
plan: {
|
||||
name: subscriptionChange.nextPlanName,
|
||||
name: getPlanNameForDisplay(
|
||||
subscriptionChange.nextPlanName,
|
||||
subscriptionChange.nextPlanCode
|
||||
),
|
||||
amount: subscriptionChange.nextPlanPrice,
|
||||
},
|
||||
addOns: subscriptionChange.nextAddOns.map(addOn => ({
|
||||
@@ -755,4 +783,5 @@ module.exports = {
|
||||
makeChangePreview,
|
||||
getRecommendedCurrency,
|
||||
getLatamCountryBannerDetails,
|
||||
getPlanNameForDisplay,
|
||||
}
|
||||
|
||||
@@ -186,9 +186,7 @@ async function _getUpgradeTargetPlanCodeMaybeThrow(subscription) {
|
||||
throw new Error('Not eligible for group plan upgrade')
|
||||
}
|
||||
|
||||
return subscription.planCode.includes('educational')
|
||||
? 'group_professional_educational'
|
||||
: 'group_professional'
|
||||
return subscription.planCode.replace('collaborator', 'professional')
|
||||
}
|
||||
|
||||
async function _getGroupPlanUpgradeChangeRequest(ownerId) {
|
||||
@@ -196,26 +194,11 @@ async function _getGroupPlanUpgradeChangeRequest(ownerId) {
|
||||
await SubscriptionLocator.promises.getUsersSubscription(ownerId)
|
||||
|
||||
const newPlanCode = await _getUpgradeTargetPlanCodeMaybeThrow(olSubscription)
|
||||
|
||||
const recurlySubscription = await RecurlyClient.promises.getSubscription(
|
||||
olSubscription.recurlySubscription_id
|
||||
)
|
||||
return recurlySubscription.getRequestForGroupPlanUpgrade(
|
||||
newPlanCode,
|
||||
olSubscription.membersLimit
|
||||
)
|
||||
}
|
||||
|
||||
function _getPlanNameForDisplay(subscription) {
|
||||
if (/^group_collaborator_\d+_enterprise$/.test(subscription.planCode)) {
|
||||
return 'Overleaf Standard Group'
|
||||
}
|
||||
|
||||
if (/^group_collaborator_\d+_educational$/.test(subscription.planCode)) {
|
||||
return 'Overleaf Standard Group Educational'
|
||||
}
|
||||
|
||||
return subscription.planName
|
||||
return recurlySubscription.getRequestForGroupPlanUpgrade(newPlanCode)
|
||||
}
|
||||
|
||||
async function getGroupPlanUpgradePreview(ownerId) {
|
||||
@@ -227,7 +210,10 @@ async function getGroupPlanUpgradePreview(ownerId) {
|
||||
{
|
||||
type: 'group-plan-upgrade',
|
||||
prevPlan: {
|
||||
name: _getPlanNameForDisplay(subscriptionChange.subscription),
|
||||
name: SubscriptionController.getPlanNameForDisplay(
|
||||
subscriptionChange.subscription.planName,
|
||||
subscriptionChange.subscription.planCode
|
||||
),
|
||||
},
|
||||
},
|
||||
subscriptionChange,
|
||||
|
||||
@@ -10,14 +10,22 @@ export const LICENSE_ADD_ON = 'additional-license'
|
||||
function UpgradeSubscriptionPlanDetails() {
|
||||
const { t } = useTranslation()
|
||||
const preview = getMeta('ol-subscriptionChangePreview')
|
||||
const totalLicenses = getMeta('ol-totalLicenses')
|
||||
|
||||
const licenseUnitPrice = useMemo(
|
||||
() =>
|
||||
preview.nextInvoice.addOns.filter(
|
||||
addOn => addOn.code === LICENSE_ADD_ON
|
||||
)[0].unitAmount,
|
||||
[preview]
|
||||
)
|
||||
const licenseUnitPrice = useMemo(() => {
|
||||
const additionalLicenseAddOn = preview.nextInvoice.addOns.filter(
|
||||
addOn => addOn.code === LICENSE_ADD_ON
|
||||
)
|
||||
// Legacy plans might not have additional-license add-on.
|
||||
// Hence we need to compute unit price
|
||||
return additionalLicenseAddOn.length > 0
|
||||
? additionalLicenseAddOn[0].unitAmount
|
||||
: preview.nextInvoice.plan.amount / totalLicenses
|
||||
}, [
|
||||
preview.nextInvoice.addOns,
|
||||
preview.nextInvoice.plan.amount,
|
||||
totalLicenses,
|
||||
])
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
||||
@@ -280,19 +280,13 @@ describe('RecurlyEntities', function () {
|
||||
|
||||
describe('getRequestForGroupPlanUpgrade()', function () {
|
||||
it('returns a correct change request', function () {
|
||||
const changeRequest = this.subscription.getRequestForGroupPlanUpgrade(
|
||||
'test_plan_code',
|
||||
10
|
||||
)
|
||||
const changeRequest =
|
||||
this.subscription.getRequestForGroupPlanUpgrade('test_plan_code')
|
||||
const addOns = [
|
||||
new RecurlySubscriptionAddOnUpdate({
|
||||
code: 'add-on-code',
|
||||
quantity: 1,
|
||||
}),
|
||||
new RecurlySubscriptionAddOnUpdate({
|
||||
code: 'additional-license',
|
||||
quantity: 10,
|
||||
}),
|
||||
]
|
||||
expect(changeRequest).to.deep.equal(
|
||||
new RecurlySubscriptionChangeRequest({
|
||||
|
||||
@@ -71,6 +71,7 @@ describe('SubscriptionGroupHandler', function () {
|
||||
|
||||
this.SubscriptionController = {
|
||||
makeChangePreview: sinon.stub().resolves(this.changePreview),
|
||||
getPlanNameForDisplay: sinon.stub().resolves(),
|
||||
}
|
||||
|
||||
this.SubscriptionUpdater = {
|
||||
@@ -512,6 +513,9 @@ describe('SubscriptionGroupHandler', function () {
|
||||
.stub()
|
||||
.resolves({ groupPlan: true, planCode: 'group_collaborator' })
|
||||
await this.Handler.promises.upgradeGroupPlan(this.user_id)
|
||||
this.recurlySubscription.getRequestForGroupPlanUpgrade
|
||||
.calledWith('group_professional')
|
||||
.should.equal(true)
|
||||
this.RecurlyClient.promises.applySubscriptionChangeRequest
|
||||
.calledWith(this.changeRequest)
|
||||
.should.equal(true)
|
||||
@@ -528,6 +532,9 @@ describe('SubscriptionGroupHandler', function () {
|
||||
planCode: 'group_collaborator_10_educational',
|
||||
})
|
||||
await this.Handler.promises.upgradeGroupPlan(this.user_id)
|
||||
this.recurlySubscription.getRequestForGroupPlanUpgrade
|
||||
.calledWith('group_professional_10_educational')
|
||||
.should.equal(true)
|
||||
this.RecurlyClient.promises.applySubscriptionChangeRequest
|
||||
.calledWith(this.changeRequest)
|
||||
.should.equal(true)
|
||||
|
||||
Reference in New Issue
Block a user