From dfea9dacab1ebd9ffc63f817df6fb3687c4d1978 Mon Sep 17 00:00:00 2001
From: Liangjun Song <146005915+adai26@users.noreply.github.com>
Date: Thu, 5 Dec 2024 13:40:00 +0100
Subject: [PATCH] Merge pull request #22146 from
overleaf/ls-consider-flexible-licensing-on-payment-page
support new group plans in checkout flow
GitOrigin-RevId: ec6aff363e0eeb5d82067cea44479b5045258490
---
.../Features/Subscription/RecurlyWrapper.js | 12 +++++++
services/web/frontend/js/utils/meta.ts | 1 +
.../src/Subscription/RecurlyWrapperTests.js | 34 +++++++++++++++++++
.../web/types/recurly/pricing/subscription.ts | 7 +++-
4 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/services/web/app/src/Features/Subscription/RecurlyWrapper.js b/services/web/app/src/Features/Subscription/RecurlyWrapper.js
index 9660a8c5dd..5830b69bb2 100644
--- a/services/web/app/src/Features/Subscription/RecurlyWrapper.js
+++ b/services/web/app/src/Features/Subscription/RecurlyWrapper.js
@@ -286,6 +286,14 @@ const promises = {
{ userId: user._id },
'starting process of creating paypal subscription'
)
+ if (subscriptionDetails.subscription_add_ons) {
+ // TODO: support flexible licensing in paypal flow
+ const err = new Error('Add-on purchase not supported')
+ OError.tag(err, 'error in paypal subscription creation process', {
+ user_id: user._id,
+ })
+ throw err
+ }
// We use waterfall through each of these actions in sequence
// passing a `cache` object along the way. The cache is initialized
// with required data, and `async.apply` to pass the cache to the first function
@@ -343,6 +351,10 @@ const promises = {
data.account.billing_info.three_d_secure_action_result_token_id =
recurlyTokenIds.threeDSecureActionResult
}
+ if (subscriptionDetails.subscription_add_ons) {
+ data.subscription_add_ons = subscriptionDetails.subscription_add_ons
+ }
+
const customFields =
getCustomFieldsFromSubscriptionDetails(subscriptionDetails)
if (customFields) {
diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts
index 941cfd32c6..b1b8fc948d 100644
--- a/services/web/frontend/js/utils/meta.ts
+++ b/services/web/frontend/js/utils/meta.ts
@@ -130,6 +130,7 @@ export interface Meta {
'ol-languages': SpellCheckLanguage[]
'ol-learnedWords': string[]
'ol-legacyEditorThemes': string[]
+ 'ol-licenseQuantity': number | undefined
'ol-linkSharingEnforcement': boolean
'ol-linkSharingWarning': boolean
'ol-loadingText': string
diff --git a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js
index be55517aed..b2144b039b 100644
--- a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js
+++ b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js
@@ -579,6 +579,9 @@ describe('RecurlyWrapper', function () {
state: 'some_state',
zip: 'some_zip',
},
+ subscription_add_ons: [
+ { subscription_add_on: { add_on_code: 'test_add_on', quantity: 2 } },
+ ],
ITMCampaign: 'itm-campaign-value',
ITMContent: 'itm-content-value',
ITMReferrer: 'itm-referrer-value',
@@ -633,6 +636,12 @@ describe('RecurlyWrapper', function () {
a-3d-token-id
+
+
+ test_add_on
+ 2
+
+
itm_campaign
@@ -884,6 +893,31 @@ describe('RecurlyWrapper', function () {
this.createSubscription.callCount.should.equal(0)
})
})
+
+ it('throw error if purchase with addon', async function () {
+ this.subscriptionDetails = {
+ currencyCode: 'EUR',
+ plan_code: 'some_plan_code',
+ coupon_code: '',
+ isPaypal: true,
+ address: {
+ address1: 'addr_one',
+ address2: 'addr_two',
+ country: 'some_country',
+ state: 'some_state',
+ zip: 'some_zip',
+ },
+ subscription_add_ons: [
+ { subscription_add_on: { add_on_code: 'test_add_on', quantity: 2 } },
+ ],
+ }
+ await expect(this.call()).to.be.rejected
+ this.checkAccountExists.callCount.should.equal(0)
+ this.createAccount.callCount.should.equal(0)
+ this.createBillingInfo.callCount.should.equal(0)
+ this.setAddressAndCompanyBillingInfo.callCount.should.equal(0)
+ this.createSubscription.callCount.should.equal(0)
+ })
})
describe('paypal actions', function () {
diff --git a/services/web/types/recurly/pricing/subscription.ts b/services/web/types/recurly/pricing/subscription.ts
index e018daf085..744d08c3ea 100644
--- a/services/web/types/recurly/pricing/subscription.ts
+++ b/services/web/types/recurly/pricing/subscription.ts
@@ -48,13 +48,18 @@ interface Coupon {
redemption_resource: string
}
+interface AddOn {
+ code: string
+ quantity: number
+}
+
// Extending the default interface as it lacks the `items` prop
export interface SubscriptionPricingInstanceCustom
extends SubscriptionPricingInstance,
SubscriptionPricingState {
id: string
items: {
- addons: unknown[]
+ addons: AddOn[]
address?: Address
coupon?: Coupon
currency: string