Merge pull request #23462 from overleaf/ls-update-pricing-logic-for-small-educational-plans

Update pricing logic for small educational plans

GitOrigin-RevId: 0051f238ce50b2067b7dc75d08f55dc1c7ac3502
This commit is contained in:
Liangjun Song
2025-02-07 11:42:02 +00:00
committed by Copybot
parent 64e8d2b8b3
commit eb5417fad5
2 changed files with 83 additions and 2 deletions

View File

@@ -143,8 +143,12 @@ async function _addSeatsSubscriptionChange(userId, adding) {
.additional_license_legacy_price_in_cents
if (
planPriceInCents / 100 > recurlySubscription.planPrice &&
legacyUnitPriceInCents > 0
_shouldUseLegacyPricing(
recurlySubscription.planPrice,
planPriceInCents / 100,
usage,
size
)
) {
unitPrice = legacyUnitPriceInCents / 100
}
@@ -163,6 +167,23 @@ async function _addSeatsSubscriptionChange(userId, adding) {
}
}
function _shouldUseLegacyPricing(
actualPlanPrice,
currentPlanPrice,
usage,
size
) {
// For small educational groups (5 or fewer members)
// 2025 pricing is cheaper than legacy pricing
if (size <= 5 && usage === 'educational') {
return currentPlanPrice < actualPlanPrice
}
// For all other scenarios
// 2025 pricing is more expensive than legacy pricing
return currentPlanPrice > actualPlanPrice
}
async function previewAddSeatsSubscriptionChange(userId, adding) {
const { changeRequest, currentAddonQuantity } =
await _addSeatsSubscriptionChange(userId, adding)

View File

@@ -143,6 +143,16 @@ describe('SubscriptionGroupHandler', function () {
},
},
},
educational: {
collaborator: {
USD: {
5: {
price_in_cents: 10000,
additional_license_legacy_price_in_cents: 5000,
},
},
},
},
}
this.Handler = SandboxedModule.require(modulePath, {
@@ -509,6 +519,56 @@ describe('SubscriptionGroupHandler', function () {
)
.should.equal(true)
})
it('should return the subscription change preview with legacy add-on price for small educational group', async function () {
this.PlansLocator.findLocalPlanInSettings = sinon.stub().returns({
...this.localPlanInSettings,
planCode: 'group_collaborator_5_educational',
canUseFlexibleLicensing: true,
})
this.recurlySubscription.planPrice =
this.GroupPlansData.enterprise.collaborator.USD[5].price_in_cents /
100 +
1
preview =
await this.Handler.promises.previewAddSeatsSubscriptionChange(
this.adminUser_id,
this.adding
)
this.recurlySubscription.getRequestForAddOnPurchase
.calledWithExactly(
this.RecurlyEntities.MEMBERS_LIMIT_ADD_ON_CODE,
this.adding,
this.GroupPlansData.enterprise.collaborator.USD[5]
.additional_license_legacy_price_in_cents / 100
)
.should.equal(true)
})
it('should return the subscription change preview with non-legacy add-on price for small educational group', async function () {
this.PlansLocator.findLocalPlanInSettings = sinon.stub().returns({
...this.localPlanInSettings,
planCode: 'group_collaborator_5_educational',
canUseFlexibleLicensing: true,
})
this.recurlySubscription.planPrice =
this.GroupPlansData.enterprise.collaborator.USD[5].price_in_cents /
100
preview =
await this.Handler.promises.previewAddSeatsSubscriptionChange(
this.adminUser_id,
this.adding
)
this.recurlySubscription.getRequestForAddOnPurchase
.calledWithExactly(
this.RecurlyEntities.MEMBERS_LIMIT_ADD_ON_CODE,
this.adding,
undefined
)
.should.equal(true)
})
})
})
})