Sfoglia il codice sorgente

[web] mv PaymentService to modules

GitOrigin-RevId: 73d739f53d96ff9e9d51a535907dbdc878aa6624
Kristina Hjertberg 1 anno fa
parent
commit
f8f2585164

+ 0 - 81
services/web/app/src/Features/Subscription/PaymentService.js

@@ -1,81 +0,0 @@
-// @ts-check
-
-const RecurlyClient = require('./RecurlyClient.js')
-const logger = require('@overleaf/logger')
-const { callbackify } = require('util')
-
-/**
- * @import { PaymentProviderSubscription, PaymentProviderAccount, PaymentProviderCoupon } from "./PaymentProviderEntities.js"
- * @import { ObjectId } from 'mongodb'
- */
-
-/**
- * this represents a subset of the Mongo Subscription record
- *
- * @typedef {object} MongoSubscription
- * @property {ObjectId} admin_id
- * @property {string} [recurlySubscription_id]
- */
-
-/**
- * @typedef {object} PaymentRecord
- * @property {PaymentProviderSubscription} subscription
- * @property {PaymentProviderAccount | null} account
- * @property {PaymentProviderCoupon[]} coupons
- */
-
-/**
- * Get payment information from our Mongo record
- *
- * @param {MongoSubscription} subscription
- * @return {Promise<PaymentRecord | null>}
- */
-async function getPaymentFromRecord(subscription) {
-  if (subscription == null) {
-    logger.debug('no subscription provided')
-    return null
-  }
-  const userId = (subscription.admin_id._id || subscription.admin_id).toString()
-  const recurlySubscriptionId = subscription.recurlySubscription_id
-
-  // TODO: handle non-recurly payment records
-  if (recurlySubscriptionId == null || recurlySubscriptionId === '') {
-    logger.debug(
-      { userId },
-      "no recurly subscription id found for user's subscription"
-    )
-    return null
-  }
-
-  const subscriptionResponse = await RecurlyClient.promises.getSubscription(
-    recurlySubscriptionId
-  )
-  if (!subscriptionResponse) {
-    logger.debug(
-      { recurlySubscriptionId },
-      'no recurly subscription found for subscription id'
-    )
-    return null
-  }
-
-  const accountResponse =
-    await RecurlyClient.promises.getAccountForUserId(userId)
-  const accountCoupons =
-    await RecurlyClient.promises.getActiveCouponsForUserId(userId)
-
-  // TODO: include account and coupons in subscription class instead of separately here
-  // if Recurly is removed (Recurly needs 2 extra requests to get account & coupon data)
-  return {
-    subscription: subscriptionResponse,
-    account: accountResponse,
-    coupons: accountCoupons,
-  }
-}
-
-module.exports = {
-  getPaymentFromRecord: callbackify(getPaymentFromRecord),
-
-  promises: {
-    getPaymentFromRecord,
-  },
-}

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

@@ -23,8 +23,8 @@ const {
   V1ConnectionError,
   V1ConnectionError,
 } = require('../Errors/Errors')
 } = require('../Errors/Errors')
 const FeaturesHelper = require('./FeaturesHelper')
 const FeaturesHelper = require('./FeaturesHelper')
-const PaymentService = require('./PaymentService')
 const { formatCurrency } = require('../../util/currency')
 const { formatCurrency } = require('../../util/currency')
+const Modules = require('../../infrastructure/Modules')
 
 
 /**
 /**
  * @import { Subscription } from "../../../../types/project/dashboard/subscription"
  * @import { Subscription } from "../../../../types/project/dashboard/subscription"
@@ -82,16 +82,16 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') {
     currentInstitutionsWithLicence,
     currentInstitutionsWithLicence,
     managedInstitutions,
     managedInstitutions,
     managedPublishers,
     managedPublishers,
-    paymentRecord,
+    fetchedPaymentRecord,
     plan,
     plan,
   } = await async.auto({
   } = await async.auto({
     personalSubscription(cb) {
     personalSubscription(cb) {
       SubscriptionLocator.getUsersSubscription(user, cb)
       SubscriptionLocator.getUsersSubscription(user, cb)
     },
     },
-    paymentRecord: [
+    fetchedPaymentRecord: [
       'personalSubscription',
       'personalSubscription',
       ({ personalSubscription }, cb) => {
       ({ personalSubscription }, cb) => {
-        PaymentService.getPaymentFromRecord(personalSubscription, cb)
+        Modules.hooks.fire('getPaymentFromRecord', personalSubscription, cb)
       },
       },
     ],
     ],
     plan: [
     plan: [
@@ -138,6 +138,8 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') {
     },
     },
   })
   })
 
 
+  const paymentRecord = fetchedPaymentRecord && fetchedPaymentRecord[0]
+
   if (memberGroupSubscriptions == null) {
   if (memberGroupSubscriptions == null) {
     memberGroupSubscriptions = []
     memberGroupSubscriptions = []
   } else {
   } else {

+ 0 - 117
services/web/test/unit/src/Subscription/PaymentServiceTests.js

@@ -1,117 +0,0 @@
-const sinon = require('sinon')
-const { expect } = require('chai')
-const SandboxedModule = require('sandboxed-module')
-const {
-  PaymentProviderSubscription,
-  PaymentProviderAccount,
-  PaymentProviderCoupon,
-} = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
-
-const MODULE_PATH = '../../../../app/src/Features/Subscription/PaymentService'
-
-describe('PaymentService', function () {
-  beforeEach(function () {
-    this.user = {
-      _id: '123456',
-    }
-    this.recurlySubscription = new PaymentProviderSubscription({
-      id: 'subscription-id',
-      userId: this.user._id,
-      currency: 'EUR',
-      planCode: 'plan-code',
-      planName: 'plan-name',
-      planPrice: 13,
-      addOns: [],
-      subtotal: 15,
-      taxRate: 0.1,
-      taxAmount: 1.5,
-      total: 14.5,
-      periodStart: new Date(),
-      periodEnd: new Date(),
-      collectionMethod: 'automatic',
-    })
-    this.recurlyAccount = new PaymentProviderAccount({
-      code: this.user._id,
-      email: 'example@example.com',
-      hasPastDueInvoice: true,
-    })
-    this.recurlyCoupons = [
-      new PaymentProviderCoupon({
-        code: 'coupon-code',
-        name: 'coupon name',
-        description: 'coupon description',
-      }),
-    ]
-    this.mongoSubscription = {
-      admin_id: this.user,
-      recurlySubscription_id: this.recurlySubscription.id,
-    }
-    this.RecurlyClient = {
-      promises: {
-        getSubscription: sinon.stub(),
-        getAccountForUserId: sinon.stub(),
-        getActiveCouponsForUserId: sinon.stub(),
-      },
-    }
-    return (this.PaymentService = SandboxedModule.require(MODULE_PATH, {
-      requires: {
-        './RecurlyClient': this.RecurlyClient,
-      },
-    }))
-  })
-
-  describe('getPaymentFromRecord', function () {
-    it('should return null for a missing subscription', async function () {
-      const response =
-        await this.PaymentService.promises.getPaymentFromRecord(null)
-      expect(response).to.equal(null)
-    })
-
-    it('should return null if payment service subscription id is missing', async function () {
-      this.mongoSubscription.recurlySubscription_id = null
-      const response = await this.PaymentService.promises.getPaymentFromRecord(
-        this.mongoSubscription
-      )
-      expect(response).to.equal(null)
-    })
-
-    it('should return the subscription', async function () {
-      this.RecurlyClient.promises.getSubscription.returns(
-        this.recurlySubscription
-      )
-      const response = await this.PaymentService.promises.getPaymentFromRecord(
-        this.mongoSubscription
-      )
-      expect(response.subscription).to.deep.equal(this.recurlySubscription)
-    })
-
-    it('should return account information if found', async function () {
-      this.RecurlyClient.promises.getSubscription.returns(
-        this.recurlySubscription
-      )
-      this.RecurlyClient.promises.getAccountForUserId.returns(
-        this.recurlyAccount
-      )
-      const response = await this.PaymentService.promises.getPaymentFromRecord(
-        this.mongoSubscription
-      )
-      expect(response.account.email).to.equal(this.recurlyAccount.email)
-      expect(response.account.hasPastDueInvoice).to.equal(
-        this.recurlyAccount.hasPastDueInvoice
-      )
-    })
-
-    it('should include coupons if found', async function () {
-      this.RecurlyClient.promises.getSubscription.returns(
-        this.recurlySubscription
-      )
-      this.RecurlyClient.promises.getActiveCouponsForUserId.returns(
-        this.recurlyCoupons
-      )
-      const response = await this.PaymentService.promises.getPaymentFromRecord(
-        this.mongoSubscription
-      )
-      expect(response.coupons).to.deep.equal(this.recurlyCoupons)
-    })
-  })
-})

+ 26 - 17
services/web/test/unit/src/Subscription/SubscriptionViewModelBuilderTests.js

@@ -143,9 +143,6 @@ describe('SubscriptionViewModelBuilder', function () {
     this.PlansLocator = {
     this.PlansLocator = {
       findLocalPlanInSettings: sinon.stub(),
       findLocalPlanInSettings: sinon.stub(),
     }
     }
-    this.PaymentService = {
-      getPaymentFromRecord: sinon.stub().yields(),
-    }
     this.SubscriptionViewModelBuilder = SandboxedModule.require(modulePath, {
     this.SubscriptionViewModelBuilder = SandboxedModule.require(modulePath, {
       requires: {
       requires: {
         '@overleaf/settings': this.Settings,
         '@overleaf/settings': this.Settings,
@@ -155,7 +152,11 @@ describe('SubscriptionViewModelBuilder', function () {
         './RecurlyWrapper': this.RecurlyWrapper,
         './RecurlyWrapper': this.RecurlyWrapper,
         './SubscriptionUpdater': this.SubscriptionUpdater,
         './SubscriptionUpdater': this.SubscriptionUpdater,
         './PlansLocator': this.PlansLocator,
         './PlansLocator': this.PlansLocator,
-        './PaymentService': this.PaymentService,
+        '../../infrastructure/Modules': (this.Modules = {
+          hooks: {
+            fire: sinon.stub().yields(null, []),
+          },
+        }),
         './V1SubscriptionManager': {},
         './V1SubscriptionManager': {},
         '../Publishers/PublishersGetter': this.PublishersGetter,
         '../Publishers/PublishersGetter': this.PublishersGetter,
         './SubscriptionHelper': {},
         './SubscriptionHelper': {},
@@ -512,14 +513,18 @@ describe('SubscriptionViewModelBuilder', function () {
           null,
           null,
           this.individualSubscription
           this.individualSubscription
         )
         )
-        this.PaymentService.getPaymentFromRecord.yields(null, {
-          subscription: this.paymentRecord,
-          account: new PaymentProviderAccount({
-            email: 'example@example.com',
-            hasPastDueInvoice: false,
-          }),
-          coupons: [],
-        })
+        this.Modules.hooks.fire
+          .withArgs('getPaymentFromRecord', this.individualSubscription)
+          .yields(null, [
+            {
+              subscription: this.paymentRecord,
+              account: new PaymentProviderAccount({
+                email: 'example@example.com',
+                hasPastDueInvoice: false,
+              }),
+              coupons: [],
+            },
+          ])
         const result =
         const result =
           await this.SubscriptionViewModelBuilder.promises.buildUsersSubscriptionViewModel(
           await this.SubscriptionViewModelBuilder.promises.buildUsersSubscriptionViewModel(
             this.user
             this.user
@@ -585,11 +590,15 @@ describe('SubscriptionViewModelBuilder', function () {
               }),
               }),
             ],
             ],
           })
           })
-        this.PaymentService.getPaymentFromRecord.yields(null, {
-          subscription: this.paymentRecord,
-          account: {},
-          coupons: [],
-        })
+        this.Modules.hooks.fire
+          .withArgs('getPaymentFromRecord', this.individualSubscription)
+          .yields(null, [
+            {
+              subscription: this.paymentRecord,
+              account: {},
+              coupons: [],
+            },
+          ])
         const result =
         const result =
           await this.SubscriptionViewModelBuilder.promises.buildUsersSubscriptionViewModel(
           await this.SubscriptionViewModelBuilder.promises.buildUsersSubscriptionViewModel(
             this.user
             this.user