Przeglądaj źródła

Move AI related functions from PaymentProviderEntities to AiHelper (#26956)

* Move AI related functions from PaymentProviderEntities to AiHelper

* added @ts-check

GitOrigin-RevId: 8c8eec334b40a7f8f8533f6d5194f428112f68f9
Domagoj Kriskovic 1 rok temu
rodzic
commit
11cb140fe3

+ 1 - 3
services/web/app/src/Features/Project/ProjectController.js

@@ -46,9 +46,7 @@ const TutorialHandler = require('../Tutorial/TutorialHandler')
 const UserUpdater = require('../User/UserUpdater')
 const UserUpdater = require('../User/UserUpdater')
 const Modules = require('../../infrastructure/Modules')
 const Modules = require('../../infrastructure/Modules')
 const UserGetter = require('../User/UserGetter')
 const UserGetter = require('../User/UserGetter')
-const {
-  isStandaloneAiAddOnPlanCode,
-} = require('../Subscription/PaymentProviderEntities')
+const { isStandaloneAiAddOnPlanCode } = require('../Subscription/AiHelper')
 const SubscriptionController = require('../Subscription/SubscriptionController.js')
 const SubscriptionController = require('../Subscription/SubscriptionController.js')
 const { formatCurrency } = require('../../util/currency')
 const { formatCurrency } = require('../../util/currency')
 
 

+ 46 - 0
services/web/app/src/Features/Subscription/AiHelper.js

@@ -0,0 +1,46 @@
+// @ts-check
+// Initially, this functions lived in PaymentProviderEntities.js,
+// but it was moved to this file to prevent circular dependency issue
+
+const AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE = 'assistant'
+const AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE = 'assistant-annual'
+const AI_ADD_ON_CODE = 'assistant'
+
+/**
+ * Returns whether the given plan code is a standalone AI plan
+ *
+ * @param {string} planCode
+ * @return {boolean}
+ */
+function isStandaloneAiAddOnPlanCode(planCode) {
+  return (
+    planCode === AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE ||
+    planCode === AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE
+  )
+}
+
+/**
+ * Returns whether subscription change will have have the ai bundle once the change is processed
+ *
+ * @param {Object} subscriptionChange The subscription change object coming from payment provider
+ * type should be PaymentProviderSubscriptionChange but if imported here, it creates a circular dependency
+ * TODO: fix this when moved to es modules
+ *
+ * @return {boolean}
+ */
+function subscriptionChangeIsAiAssistUpgrade(subscriptionChange) {
+  return Boolean(
+    isStandaloneAiAddOnPlanCode(subscriptionChange.nextPlanCode) ||
+      subscriptionChange.nextAddOns?.some(
+        addOn => addOn.code === AI_ADD_ON_CODE
+      )
+  )
+}
+
+module.exports = {
+  AI_ADD_ON_CODE,
+  AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE,
+  AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE,
+  isStandaloneAiAddOnPlanCode,
+  subscriptionChangeIsAiAssistUpgrade,
+}

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

@@ -15,7 +15,7 @@ const UserGetter = require('../User/UserGetter')
 const AnalyticsManager = require('../Analytics/AnalyticsManager')
 const AnalyticsManager = require('../Analytics/AnalyticsManager')
 const Queues = require('../../infrastructure/Queues')
 const Queues = require('../../infrastructure/Queues')
 const Modules = require('../../infrastructure/Modules')
 const Modules = require('../../infrastructure/Modules')
-const { AI_ADD_ON_CODE } = require('./PaymentProviderEntities')
+const { AI_ADD_ON_CODE } = require('./AiHelper')
 
 
 /**
 /**
  * Enqueue a job for refreshing features for the given user
  * Enqueue a job for refreshing features for the given user

+ 2 - 41
services/web/app/src/Features/Subscription/PaymentProviderEntities.js

@@ -9,13 +9,9 @@
 const OError = require('@overleaf/o-error')
 const OError = require('@overleaf/o-error')
 const { DuplicateAddOnError, AddOnNotPresentError } = require('./Errors')
 const { DuplicateAddOnError, AddOnNotPresentError } = require('./Errors')
 const PlansLocator = require('./PlansLocator')
 const PlansLocator = require('./PlansLocator')
-
-let SubscriptionHelper = null // Work around circular import (loaded at the bottom of the file)
-
+const SubscriptionHelper = require('./SubscriptionHelper')
+const { AI_ADD_ON_CODE, isStandaloneAiAddOnPlanCode } = require('./AiHelper')
 const MEMBERS_LIMIT_ADD_ON_CODE = 'additional-license'
 const MEMBERS_LIMIT_ADD_ON_CODE = 'additional-license'
-const AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE = 'assistant'
-const AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE = 'assistant-annual'
-const AI_ADD_ON_CODE = 'assistant'
 
 
 class PaymentProviderSubscription {
 class PaymentProviderSubscription {
   /**
   /**
@@ -588,18 +584,6 @@ class PaymentProviderAccount {
   }
   }
 }
 }
 
 
-/**
- * Returns whether the given plan code is a standalone AI plan
- *
- * @param {string} planCode
- */
-function isStandaloneAiAddOnPlanCode(planCode) {
-  return (
-    planCode === AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE ||
-    planCode === AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE
-  )
-}
-
 /**
 /**
  * Returns whether the given plan code is a group plan
  * Returns whether the given plan code is a group plan
  *
  *
@@ -609,27 +593,8 @@ function isGroupPlanCode(planCode) {
   return planCode.includes('group')
   return planCode.includes('group')
 }
 }
 
 
-/**
- * Returns whether subscription change will have have the ai bundle once the change is processed
- *
- * @param {PaymentProviderSubscriptionChange} subscriptionChange The subscription change object coming from payment provider
- *
- * @return {boolean}
- */
-function subscriptionChangeIsAiAssistUpgrade(subscriptionChange) {
-  return Boolean(
-    isStandaloneAiAddOnPlanCode(subscriptionChange.nextPlanCode) ||
-      subscriptionChange.nextAddOns?.some(
-        addOn => addOn.code === AI_ADD_ON_CODE
-      )
-  )
-}
-
 module.exports = {
 module.exports = {
-  AI_ADD_ON_CODE,
   MEMBERS_LIMIT_ADD_ON_CODE,
   MEMBERS_LIMIT_ADD_ON_CODE,
-  AI_ASSIST_STANDALONE_MONTHLY_PLAN_CODE,
-  AI_ASSIST_STANDALONE_ANNUAL_PLAN_CODE,
   PaymentProviderSubscription,
   PaymentProviderSubscription,
   PaymentProviderSubscriptionAddOn,
   PaymentProviderSubscriptionAddOn,
   PaymentProviderSubscriptionChange,
   PaymentProviderSubscriptionChange,
@@ -643,9 +608,5 @@ module.exports = {
   PaymentProviderCoupon,
   PaymentProviderCoupon,
   PaymentProviderAccount,
   PaymentProviderAccount,
   isGroupPlanCode,
   isGroupPlanCode,
-  isStandaloneAiAddOnPlanCode,
-  subscriptionChangeIsAiAssistUpgrade,
   PaymentProviderImmediateCharge,
   PaymentProviderImmediateCharge,
 }
 }
-
-SubscriptionHelper = require('./SubscriptionHelper')

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

@@ -1,7 +1,7 @@
 const SplitTestHandler = require('../SplitTests/SplitTestHandler')
 const SplitTestHandler = require('../SplitTests/SplitTestHandler')
 const AnalyticsManager = require('../Analytics/AnalyticsManager')
 const AnalyticsManager = require('../Analytics/AnalyticsManager')
 const SubscriptionEmailHandler = require('./SubscriptionEmailHandler')
 const SubscriptionEmailHandler = require('./SubscriptionEmailHandler')
-const { AI_ADD_ON_CODE } = require('./PaymentProviderEntities')
+const { AI_ADD_ON_CODE } = require('./AiHelper')
 const { ObjectId } = require('mongodb-legacy')
 const { ObjectId } = require('mongodb-legacy')
 
 
 const INVOICE_SUBSCRIPTION_LIMIT = 10
 const INVOICE_SUBSCRIPTION_LIMIT = 10

+ 5 - 6
services/web/app/src/Features/Subscription/SubscriptionController.js

@@ -27,9 +27,11 @@ const Modules = require('../../infrastructure/Modules')
 const async = require('async')
 const async = require('async')
 const HttpErrorHandler = require('../Errors/HttpErrorHandler')
 const HttpErrorHandler = require('../Errors/HttpErrorHandler')
 const RecurlyClient = require('./RecurlyClient')
 const RecurlyClient = require('./RecurlyClient')
-const { AI_ADD_ON_CODE } = require('./PaymentProviderEntities')
+const {
+  AI_ADD_ON_CODE,
+  subscriptionChangeIsAiAssistUpgrade,
+} = require('./AiHelper')
 const PlansLocator = require('./PlansLocator')
 const PlansLocator = require('./PlansLocator')
-const PaymentProviderEntities = require('./PaymentProviderEntities')
 const { User } = require('../../models/User')
 const { User } = require('../../models/User')
 const UserGetter = require('../User/UserGetter')
 const UserGetter = require('../User/UserGetter')
 const PermissionsManager = require('../Authorization/PermissionsManager')
 const PermissionsManager = require('../Authorization/PermissionsManager')
@@ -377,10 +379,7 @@ async function previewAddonPurchase(req, res) {
 
 
     const { isPremium: hasAiAssistViaWritefull } =
     const { isPremium: hasAiAssistViaWritefull } =
       await UserGetter.promises.getWritefullData(userId)
       await UserGetter.promises.getWritefullData(userId)
-    const isAiUpgrade =
-      PaymentProviderEntities.subscriptionChangeIsAiAssistUpgrade(
-        subscriptionChange
-      )
+    const isAiUpgrade = subscriptionChangeIsAiAssistUpgrade(subscriptionChange)
     if (hasAiAssistViaWritefull && isAiUpgrade) {
     if (hasAiAssistViaWritefull && isAiUpgrade) {
       return res.redirect(
       return res.redirect(
         '/user/subscription?redirect-reason=writefull-entitled'
         '/user/subscription?redirect-reason=writefull-entitled'

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

@@ -1,6 +1,6 @@
 const { formatCurrency } = require('../../util/currency')
 const { formatCurrency } = require('../../util/currency')
 const GroupPlansData = require('./GroupPlansData')
 const GroupPlansData = require('./GroupPlansData')
-const { isStandaloneAiAddOnPlanCode } = require('./PaymentProviderEntities')
+const { isStandaloneAiAddOnPlanCode } = require('./AiHelper')
 
 
 /**
 /**
  * If the user changes to a less expensive plan, we shouldn't apply the change immediately.
  * If the user changes to a less expensive plan, we shouldn't apply the change immediately.

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

@@ -6,10 +6,7 @@ const { callbackifyAll } = require('@overleaf/promise-utils')
 const { Subscription } = require('../../models/Subscription')
 const { Subscription } = require('../../models/Subscription')
 const { DeletedSubscription } = require('../../models/DeletedSubscription')
 const { DeletedSubscription } = require('../../models/DeletedSubscription')
 const logger = require('@overleaf/logger')
 const logger = require('@overleaf/logger')
-const {
-  AI_ADD_ON_CODE,
-  isStandaloneAiAddOnPlanCode,
-} = require('./PaymentProviderEntities')
+const { AI_ADD_ON_CODE, isStandaloneAiAddOnPlanCode } = require('./AiHelper')
 require('./GroupPlansData') // make sure dynamic group plans are loaded
 require('./GroupPlansData') // make sure dynamic group plans are loaded
 
 
 const SubscriptionLocator = {
 const SubscriptionLocator = {

+ 2 - 4
services/web/app/src/Features/Subscription/SubscriptionViewModelBuilder.js

@@ -1,10 +1,8 @@
 // ts-check
 // ts-check
 const Settings = require('@overleaf/settings')
 const Settings = require('@overleaf/settings')
 const PlansLocator = require('./PlansLocator')
 const PlansLocator = require('./PlansLocator')
-const {
-  isStandaloneAiAddOnPlanCode,
-  MEMBERS_LIMIT_ADD_ON_CODE,
-} = require('./PaymentProviderEntities')
+const { isStandaloneAiAddOnPlanCode } = require('./AiHelper')
+const { MEMBERS_LIMIT_ADD_ON_CODE } = require('./PaymentProviderEntities')
 const SubscriptionFormatters = require('./SubscriptionFormatters')
 const SubscriptionFormatters = require('./SubscriptionFormatters')
 const SubscriptionLocator = require('./SubscriptionLocator')
 const SubscriptionLocator = require('./SubscriptionLocator')
 const InstitutionsGetter = require('../Institutions/InstitutionsGetter')
 const InstitutionsGetter = require('../Institutions/InstitutionsGetter')

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

@@ -4,7 +4,7 @@ const sinon = require('sinon')
 const { ObjectId } = require('mongodb-legacy')
 const { ObjectId } = require('mongodb-legacy')
 const {
 const {
   AI_ADD_ON_CODE,
   AI_ADD_ON_CODE,
-} = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
+} = require('../../../../app/src/Features/Subscription/AiHelper')
 
 
 const MODULE_PATH = '../../../../app/src/Features/Subscription/FeaturesUpdater'
 const MODULE_PATH = '../../../../app/src/Features/Subscription/FeaturesUpdater'
 
 

+ 3 - 1
services/web/test/unit/src/Subscription/PaymentProviderEntitiesTest.js

@@ -4,13 +4,15 @@ const SandboxedModule = require('sandboxed-module')
 const { expect } = require('chai')
 const { expect } = require('chai')
 const Errors = require('../../../../app/src/Features/Subscription/Errors')
 const Errors = require('../../../../app/src/Features/Subscription/Errors')
 const {
 const {
-  AI_ADD_ON_CODE,
   PaymentProviderSubscriptionChangeRequest,
   PaymentProviderSubscriptionChangeRequest,
   PaymentProviderSubscriptionUpdateRequest,
   PaymentProviderSubscriptionUpdateRequest,
   PaymentProviderSubscriptionChange,
   PaymentProviderSubscriptionChange,
   PaymentProviderSubscription,
   PaymentProviderSubscription,
   PaymentProviderSubscriptionAddOnUpdate,
   PaymentProviderSubscriptionAddOnUpdate,
 } = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
 } = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
+const {
+  AI_ADD_ON_CODE,
+} = require('../../../../app/src/Features/Subscription/AiHelper')
 const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
 const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
 
 
 const MODULE_PATH =
 const MODULE_PATH =

+ 1 - 1
services/web/test/unit/src/Subscription/SubscriptionControllerTests.js

@@ -9,7 +9,7 @@ const SubscriptionErrors = require('../../../../app/src/Features/Subscription/Er
 const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
 const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
 const {
 const {
   AI_ADD_ON_CODE,
   AI_ADD_ON_CODE,
-} = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
+} = require('../../../../app/src/Features/Subscription/AiHelper')
 
 
 const mockSubscriptions = {
 const mockSubscriptions = {
   'subscription-123-active': {
   'subscription-123-active': {