Merge pull request #27150 from overleaf/ls-flexible-licensing-for-stripe-manually-billed-users

Support Stripe manually billed users in flexible licensing

GitOrigin-RevId: b3211577a313f3a241320bfe3910cf648ee49319
This commit is contained in:
Liangjun Song
2025-07-24 11:11:09 +01:00
committed by Copybot
parent 6daf877c90
commit ec591c4f7b
4 changed files with 26 additions and 35 deletions

View File

@@ -303,7 +303,6 @@ async function submitForm(req, res) {
if (paymentProviderSubscription.isCollectionMethodManual) {
await SubscriptionGroupHandler.promises.updateSubscriptionPaymentTerms(
userId,
paymentProviderSubscription,
poNumber
)

View File

@@ -7,7 +7,6 @@ const SubscriptionController = require('./SubscriptionController')
const SubscriptionHelper = require('./SubscriptionHelper')
const { Subscription } = require('../../models/Subscription')
const { User } = require('../../models/User')
const RecurlyClient = require('./RecurlyClient')
const PlansLocator = require('./PlansLocator')
const TeamInvitesHandler = require('./TeamInvitesHandler')
const GroupPlansData = require('./GroupPlansData')
@@ -284,13 +283,18 @@ async function createAddSeatsSubscriptionChange(userId, adding, poNumber) {
const { changeRequest, paymentProviderSubscription } =
await _addSeatsSubscriptionChange(userId, adding)
let subscriptionDetailUpdateRequest
if (paymentProviderSubscription.isCollectionMethodManual) {
await updateSubscriptionPaymentTerms(paymentProviderSubscription, poNumber)
subscriptionDetailUpdateRequest = await updateSubscriptionPaymentTerms(
paymentProviderSubscription,
poNumber
)
}
await Modules.promises.hooks.fire(
'applySubscriptionChangeRequestAndSync',
changeRequest,
userId
userId,
subscriptionDetailUpdateRequest?.termsAndConditions
)
return { adding }
@@ -300,22 +304,12 @@ async function updateSubscriptionPaymentTerms(
paymentProviderSubscription,
poNumber
) {
if (paymentProviderSubscription.service?.includes('stripe')) {
// TODO: Implement Stripe payment terms update
throw new OError(
'Updating payment terms is not supported for Stripe subscriptions',
{
subscriptionId: paymentProviderSubscription.id,
}
)
}
const [termsAndConditions] = await Modules.promises.hooks.fire(
'generateTermsAndConditions',
{ currency: paymentProviderSubscription.currency, poNumber }
)
const updateRequest = poNumber
const subscriptionDetailUpdateRequest = poNumber
? paymentProviderSubscription.getRequestForPoNumberAndTermsAndConditionsUpdate(
poNumber,
termsAndConditions
@@ -323,8 +317,11 @@ async function updateSubscriptionPaymentTerms(
: paymentProviderSubscription.getRequestForTermsAndConditionsUpdate(
termsAndConditions
)
await RecurlyClient.promises.updateSubscriptionDetails(updateRequest)
await Modules.promises.hooks.fire(
'updateSubscriptionDetails',
subscriptionDetailUpdateRequest
)
return subscriptionDetailUpdateRequest
}
async function getGroupPlanUpgradePreview(ownerId) {

View File

@@ -498,9 +498,9 @@ describe('SubscriptionGroupHandler', function () {
this.adding,
'123'
)
this.RecurlyClient.promises.updateSubscriptionDetails
this.Modules.promises.hooks.fire
.calledWith(
'updateSubscriptionDetails',
sinon.match
.has('poNumber')
.and(sinon.match.has('termsAndConditions'))
@@ -532,21 +532,12 @@ describe('SubscriptionGroupHandler', function () {
'T&Cs'
)
.should.equal(true)
this.RecurlyClient.promises.updateSubscriptionDetails
.calledWith(this.poNumberAndTermsAndConditionsUpdate)
.should.equal(true)
})
it('should fail for stripe', async function () {
this.recurlySubscription.service = 'stripe'
await expect(
this.Handler.promises.updateSubscriptionPaymentTerms(
this.recurlySubscription,
this.poNumberAndTermsAndConditionsUpdate.poNumber
this.Modules.promises.hooks.fire
.calledWith(
'updateSubscriptionDetails',
this.poNumberAndTermsAndConditionsUpdate
)
).to.be.rejectedWith(
'Updating payment terms is not supported for Stripe subscriptions'
)
.should.equal(true)
})
})
@@ -558,8 +549,11 @@ describe('SubscriptionGroupHandler', function () {
this.recurlySubscription.getRequestForTermsAndConditionsUpdate
.calledWithMatch('T&Cs')
.should.equal(true)
this.RecurlyClient.promises.updateSubscriptionDetails
.calledWith(this.termsAndConditionsUpdate)
this.Modules.promises.hooks.fire
.calledWith(
'updateSubscriptionDetails',
this.termsAndConditionsUpdate
)
.should.equal(true)
})
})

View File

@@ -23,6 +23,7 @@ export type CustomerSubscriptionUpdatedWebhookEvent = {
]
}
status?: Stripe.Subscription.Status
metadata?: Record<string, string>
}
}
}