Merge pull request #26519 from overleaf/ls-group-plan-upgrade-in-stripe
Support group plan upgrade in Stripe GitOrigin-RevId: 44ae35c6221bf96a0b91526178d6ab1aff80f2a3
This commit is contained in:
@@ -296,39 +296,12 @@ async function updateSubscriptionPaymentTerms(
|
||||
await RecurlyClient.promises.updateSubscriptionDetails(updateRequest)
|
||||
}
|
||||
|
||||
async function _getUpgradeTargetPlanCodeMaybeThrow(subscription) {
|
||||
if (
|
||||
subscription.planCode.includes('professional') ||
|
||||
!subscription.groupPlan
|
||||
) {
|
||||
throw new Error('Not eligible for group plan upgrade')
|
||||
}
|
||||
|
||||
return subscription.planCode.replace('collaborator', 'professional')
|
||||
}
|
||||
|
||||
async function _getGroupPlanUpgradeChangeRequest(ownerId) {
|
||||
const olSubscription =
|
||||
await SubscriptionLocator.promises.getUsersSubscription(ownerId)
|
||||
|
||||
await ensureSubscriptionIsActive(olSubscription)
|
||||
|
||||
const newPlanCode = await _getUpgradeTargetPlanCodeMaybeThrow(olSubscription)
|
||||
const recurlySubscription = await RecurlyClient.promises.getSubscription(
|
||||
olSubscription.recurlySubscription_id
|
||||
)
|
||||
|
||||
await ensureSubscriptionCollectionMethodIsNotManual(recurlySubscription)
|
||||
await ensureSubscriptionHasNoPendingChanges(recurlySubscription)
|
||||
|
||||
return recurlySubscription.getRequestForGroupPlanUpgrade(newPlanCode)
|
||||
}
|
||||
|
||||
async function getGroupPlanUpgradePreview(ownerId) {
|
||||
const changeRequest = await _getGroupPlanUpgradeChangeRequest(ownerId)
|
||||
const subscriptionChange =
|
||||
await RecurlyClient.promises.previewSubscriptionChange(changeRequest)
|
||||
const paymentMethod = await RecurlyClient.promises.getPaymentMethod(ownerId)
|
||||
const preview = await Modules.promises.hooks.fire(
|
||||
'previewGroupPlanUpgrade',
|
||||
ownerId
|
||||
)
|
||||
const { subscriptionChange, paymentMethod } = preview[0]
|
||||
return SubscriptionController.makeChangePreview(
|
||||
{
|
||||
type: 'group-plan-upgrade',
|
||||
@@ -345,12 +318,7 @@ async function getGroupPlanUpgradePreview(ownerId) {
|
||||
}
|
||||
|
||||
async function upgradeGroupPlan(ownerId) {
|
||||
const changeRequest = await _getGroupPlanUpgradeChangeRequest(ownerId)
|
||||
await RecurlyClient.promises.applySubscriptionChangeRequest(changeRequest)
|
||||
await SubscriptionHandler.promises.syncSubscription(
|
||||
{ uuid: changeRequest.subscription.id },
|
||||
ownerId
|
||||
)
|
||||
await Modules.promises.hooks.fire('upgradeGroupPlan', ownerId)
|
||||
}
|
||||
|
||||
async function updateGroupMembersBulk(
|
||||
|
||||
@@ -199,6 +199,30 @@ module.exports = {
|
||||
price_in_cents: 3000,
|
||||
features: features.professional,
|
||||
},
|
||||
{
|
||||
planCode: 'group_professional',
|
||||
name: 'Professional - Group Account - Enterprise',
|
||||
hideFromUsers: true,
|
||||
price_in_cents: 0,
|
||||
annual: true,
|
||||
features: features.professional,
|
||||
groupPlan: true,
|
||||
membersLimit: 0,
|
||||
membersLimitAddOn: 'additional-license',
|
||||
canUseFlexibleLicensing: true,
|
||||
},
|
||||
{
|
||||
planCode: 'group_collaborator',
|
||||
name: 'Collaborator - Group Account - Enterprise',
|
||||
hideFromUsers: true,
|
||||
price_in_cents: 0,
|
||||
annual: true,
|
||||
features: features.collaborator,
|
||||
groupPlan: true,
|
||||
membersLimit: 0,
|
||||
membersLimitAddOn: 'additional-license',
|
||||
canUseFlexibleLicensing: true,
|
||||
},
|
||||
],
|
||||
|
||||
bonus_features: {
|
||||
|
||||
@@ -779,100 +779,14 @@ describe('SubscriptionGroupHandler', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('upgradeGroupPlan', function () {
|
||||
it('should upgrade the subscription for flexible licensing group plans', async function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription = sinon
|
||||
.stub()
|
||||
.resolves({
|
||||
groupPlan: true,
|
||||
recurlyStatus: {
|
||||
state: 'active',
|
||||
},
|
||||
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)
|
||||
this.SubscriptionHandler.promises.syncSubscription
|
||||
.calledWith({ uuid: this.changeRequest.subscription.id }, this.user_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should upgrade the subscription for legacy group plans', async function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription = sinon
|
||||
.stub()
|
||||
.resolves({
|
||||
groupPlan: true,
|
||||
recurlyStatus: {
|
||||
state: 'active',
|
||||
},
|
||||
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)
|
||||
this.SubscriptionHandler.promises.syncSubscription
|
||||
.calledWith({ uuid: this.changeRequest.subscription.id }, this.user_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should fail the upgrade if is professional already', async function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription = sinon
|
||||
.stub()
|
||||
.resolves({
|
||||
groupPlan: true,
|
||||
recurlyStatus: {
|
||||
state: 'active',
|
||||
},
|
||||
planCode: 'group_professional',
|
||||
})
|
||||
await expect(
|
||||
this.Handler.promises.upgradeGroupPlan(this.user_id)
|
||||
).to.be.rejectedWith('Not eligible for group plan upgrade')
|
||||
})
|
||||
|
||||
it('should fail the upgrade if not group plan', async function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription = sinon
|
||||
.stub()
|
||||
.resolves({
|
||||
groupPlan: false,
|
||||
recurlyStatus: {
|
||||
state: 'active',
|
||||
},
|
||||
planCode: 'test_plan_code',
|
||||
})
|
||||
await expect(
|
||||
this.Handler.promises.upgradeGroupPlan(this.user_id)
|
||||
).to.be.rejectedWith('Not eligible for group plan upgrade')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getGroupPlanUpgradePreview', function () {
|
||||
it('should generate preview for subscription upgrade', async function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription = sinon
|
||||
.stub()
|
||||
.resolves({
|
||||
groupPlan: true,
|
||||
recurlyStatus: {
|
||||
state: 'active',
|
||||
},
|
||||
planCode: 'group_collaborator',
|
||||
})
|
||||
this.Modules.promises.hooks.fire.resolves([
|
||||
{ subscriptionChange: this.previewSubscriptionChange },
|
||||
])
|
||||
const result = await this.Handler.promises.getGroupPlanUpgradePreview(
|
||||
this.user_id
|
||||
)
|
||||
this.RecurlyClient.promises.previewSubscriptionChange
|
||||
.calledWith(this.changeRequest)
|
||||
.should.equal(true)
|
||||
|
||||
result.should.equal(this.changePreview)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user