Sfoglia il codice sorgente

Merge pull request #28202 from overleaf/ls-remove-user-features-for-past-due-stripe-subscriptions

Remove paid user features for past due Stripe subscriptions

GitOrigin-RevId: 07a97f90312db7f6e91cbf15201f71cbdeb2e33c
Liangjun Song 11 mesi fa
parent
commit
b678b545f7

+ 5 - 2
services/web/app/src/Features/Subscription/FeaturesUpdater.js

@@ -120,7 +120,8 @@ async function _getIndividualFeatures(userId) {
     await SubscriptionLocator.promises.getUsersSubscription(userId)
   if (
     subscription == null ||
-    SubscriptionHelper.getPaidSubscriptionState(subscription) === 'paused'
+    SubscriptionHelper.getPaidSubscriptionState(subscription) === 'paused' ||
+    subscription.userFeaturesDisabled
   ) {
     return {}
   }
@@ -140,7 +141,9 @@ async function _getIndividualFeatures(userId) {
 async function _getGroupFeatureSets(userId) {
   const subs =
     await SubscriptionLocator.promises.getGroupSubscriptionsMemberOf(userId)
-  return (subs || []).map(_subscriptionToFeatures)
+  return (subs || [])
+    .filter(sub => sub.userFeaturesDisabled !== true)
+    .map(_subscriptionToFeatures)
 }
 
 async function _getFeaturesOverrides(user) {

+ 1 - 1
services/web/app/src/Features/Subscription/SubscriptionLocator.js

@@ -94,7 +94,7 @@ const SubscriptionLocator = {
   async getGroupSubscriptionsMemberOf(userId) {
     return await Subscription.find(
       { member_ids: userId },
-      { _id: 1, planCode: 1 }
+      { _id: 1, planCode: 1, userFeaturesDisabled: 1 }
     )
   },
 

+ 1 - 0
services/web/app/src/models/Subscription.js

@@ -45,6 +45,7 @@ const SubscriptionSchema = new Schema(
       groupSSO: { type: Boolean, default: true },
       domainCapture: { type: Boolean, default: false },
     },
+    userFeaturesDisabled: Boolean,
     addOns: Schema.Types.Mixed,
     overleaf: {
       id: {

+ 43 - 0
services/web/test/unit/src/Subscription/FeaturesUpdaterTests.js

@@ -135,6 +135,49 @@ describe('FeaturesUpdater', function () {
   })
 
   describe('computeFeatures', function () {
+    describe('when userFeaturesDisabled is true for individual plan', function () {
+      beforeEach(function () {
+        this.SubscriptionLocator.promises.getUsersSubscription
+          .withArgs(this.user._id)
+          .resolves({
+            planCode: 'individual-plan',
+            userFeaturesDisabled: true,
+            groupPlan: false,
+            addOns: [this.aiAddOn],
+          })
+      })
+
+      it('removes all individual plan features', async function () {
+        const features = await this.FeaturesUpdater.promises.computeFeatures(
+          this.user._id
+        )
+        expect(features).to.deep.equal({ default: 'features' })
+      })
+    })
+
+    describe('when userFeaturesDisabled is true for group plan', function () {
+      beforeEach(function () {
+        const groupSubscription = {
+          planCode: 'group-plan-1',
+          userFeaturesDisabled: true,
+          groupPlan: true,
+          addOns: [this.aiAddOn],
+        }
+        this.SubscriptionLocator.promises.getUsersSubscription
+          .withArgs(this.user._id)
+          .resolves(groupSubscription)
+        this.SubscriptionLocator.promises.getGroupSubscriptionsMemberOf
+          .withArgs(this.user._id)
+          .resolves([groupSubscription])
+      })
+
+      it('removes all group plan features', async function () {
+        const features = await this.FeaturesUpdater.promises.computeFeatures(
+          this.user._id
+        )
+        expect(features).to.deep.equal({ default: 'features' })
+      })
+    })
     beforeEach(function () {
       this.SubscriptionLocator.promises.getUsersSubscription
         .withArgs(this.user._id)

+ 9 - 0
services/web/types/stripe/webhook-event.ts

@@ -82,6 +82,14 @@ export type InvoiceVoidedWebhookEvent = {
   request: Stripe.Event.Request
 }
 
+export type InvoiceOverdueWebhookEvent = {
+  type: 'invoice.overdue'
+  data: {
+    object: Stripe.Invoice
+  }
+  request: Stripe.Event.Request
+}
+
 export type CustomerSubscriptionWebhookEvent =
   | CustomerSubscriptionUpdatedWebhookEvent
   | CustomerSubscriptionCreatedWebhookEvent
@@ -92,3 +100,4 @@ export type WebhookEvent =
   | InvoicePaidWebhookEvent
   | InvoiceVoidedWebhookEvent
   | PaymentIntentPaymentFailedWebhookEvent
+  | InvoiceOverdueWebhookEvent