From 1acb68f41cbb83803e6bb8ddbdb45061c50fa454 Mon Sep 17 00:00:00 2001 From: Liangjun Song <146005915+adai26@users.noreply.github.com> Date: Thu, 14 Aug 2025 11:32:02 +0100 Subject: [PATCH] Merge pull request #27800 from overleaf/ls-support-create-stripe-customer-from-admin-panel Support creating Stripe customer from admin panel GitOrigin-RevId: 3e23008e1f4690e6f3737b5689e20958bf468f82 --- .../Subscription/PaymentProviderEntities.js | 2 +- .../app/src/Features/Subscription/RecurlyClient.js | 2 +- services/web/frontend/js/utils/meta.ts | 2 ++ .../unit/src/Subscription/RecurlyClientTests.js | 7 +++---- services/web/types/admin-capabilities.ts | 1 + .../types/subscription/dashboard/subscription.ts | 14 +++++++++----- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/services/web/app/src/Features/Subscription/PaymentProviderEntities.js b/services/web/app/src/Features/Subscription/PaymentProviderEntities.js index 42206f6db1..f13fcc1ec3 100644 --- a/services/web/app/src/Features/Subscription/PaymentProviderEntities.js +++ b/services/web/app/src/Features/Subscription/PaymentProviderEntities.js @@ -603,7 +603,7 @@ class PaymentProviderAccount { * @param {object} props * @param {string} props.code * @param {string} props.email - * @param {boolean} props.hasPastDueInvoice + * @param {boolean} [props.hasPastDueInvoice] */ constructor(props) { this.code = props.code diff --git a/services/web/app/src/Features/Subscription/RecurlyClient.js b/services/web/app/src/Features/Subscription/RecurlyClient.js index 2031f50392..d4e02bc702 100644 --- a/services/web/app/src/Features/Subscription/RecurlyClient.js +++ b/services/web/app/src/Features/Subscription/RecurlyClient.js @@ -90,7 +90,7 @@ async function createAccountForUserId(userId) { } const account = await client.createAccount(accountCreate) logger.debug({ userId, account }, 'created recurly account') - return account + return accountFromApi(account) } /** diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts index 670909d2dd..f94cdf2710 100644 --- a/services/web/frontend/js/utils/meta.ts +++ b/services/web/frontend/js/utils/meta.ts @@ -30,6 +30,7 @@ import { GroupPolicy, ManagedGroupSubscription, MemberGroupSubscription, + StripePaymentProviderService, } from '../../../types/subscription/dashboard/subscription' import { SplitTestInfo } from '../../../types/split-test' import { ValidationStatus } from '../../../types/group-management/validation' @@ -254,6 +255,7 @@ export interface Meta { 'ol-stripeSubscriptionData': { customerId: string subscriptionState: string | null + paymentProviderService: StripePaymentProviderService | null } 'ol-subscription': any // TODO: mixed types, split into two fields 'ol-subscriptionChangePreview': SubscriptionChangePreview diff --git a/services/web/test/unit/src/Subscription/RecurlyClientTests.js b/services/web/test/unit/src/Subscription/RecurlyClientTests.js index b2717fa05f..2838cff167 100644 --- a/services/web/test/unit/src/Subscription/RecurlyClientTests.js +++ b/services/web/test/unit/src/Subscription/RecurlyClientTests.js @@ -193,11 +193,10 @@ describe('RecurlyClient', function () { describe('createAccountForUserId', function () { it('should return the Account as created by recurly', async function () { this.client.createAccount = sinon.stub().resolves(this.recurlyAccount) - await expect( - this.RecurlyClient.promises.createAccountForUserId(this.user._id) + const result = await this.RecurlyClient.promises.createAccountForUserId( + this.user._id ) - .to.eventually.be.an.instanceOf(recurly.Account) - .that.has.property('code', this.user._id) + expect(result).to.has.property('code', this.user._id) }) it('should throw any API errors', async function () { diff --git a/services/web/types/admin-capabilities.ts b/services/web/types/admin-capabilities.ts index 929a68ff6b..f6755e4251 100644 --- a/services/web/types/admin-capabilities.ts +++ b/services/web/types/admin-capabilities.ts @@ -17,6 +17,7 @@ export type AdminCapability = | 'view-script-log' | 'view-split-test' | 'view-user-additional-info' + | 'create-stripe-account' export type AdminRole = | 'engagement' diff --git a/services/web/types/subscription/dashboard/subscription.ts b/services/web/types/subscription/dashboard/subscription.ts index 694e5b948c..10965bd520 100644 --- a/services/web/types/subscription/dashboard/subscription.ts +++ b/services/web/types/subscription/dashboard/subscription.ts @@ -107,11 +107,15 @@ export type MemberGroupSubscription = Omit & { admin_id: User } -type PaymentProviderService = 'stripe-us' | 'stripe-uk' | 'recurly' -export type StripePaymentProviderService = Exclude< - PaymentProviderService, - 'recurly' -> +const STRIPE_PAYMENT_PROVIDER_SERVICES = ['stripe-uk', 'stripe-us'] as const +const PAYMENT_PROVIDER_SERVICES = [ + ...STRIPE_PAYMENT_PROVIDER_SERVICES, + 'recurly', +] as const + +export type PaymentProviderService = (typeof PAYMENT_PROVIDER_SERVICES)[number] +export type StripePaymentProviderService = + (typeof STRIPE_PAYMENT_PROVIDER_SERVICES)[number] export type PaymentProvider = { service: PaymentProviderService