Просмотр исходного кода

Merge pull request #26519 from overleaf/ls-group-plan-upgrade-in-stripe

Support group plan upgrade in Stripe

GitOrigin-RevId: 44ae35c6221bf96a0b91526178d6ab1aff80f2a3
Liangjun Song 1 год назад
Родитель
Сommit
c7ae851d39

+ 6 - 38
services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js

@@ -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(

+ 24 - 0
services/web/test/acceptance/config/settings.test.defaults.js

@@ -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: {

+ 3 - 89
services/web/test/unit/src/Subscription/SubscriptionGroupHandlerTests.js

@@ -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)
     })
   })