mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #24848 from overleaf/mf-save-stripe-checkout-data-to-mongo-db
[web] Save stripe checkout data to mongodb GitOrigin-RevId: 537778a041f92f43ccf6455c29a56c7a961ce765
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @import { PaymentProvider } from '../../../../types/subscription/dashboard/subscription'
|
||||||
|
*/
|
||||||
|
|
||||||
const OError = require('@overleaf/o-error')
|
const OError = require('@overleaf/o-error')
|
||||||
const { DuplicateAddOnError, AddOnNotPresentError } = require('./Errors')
|
const { DuplicateAddOnError, AddOnNotPresentError } = require('./Errors')
|
||||||
const PlansLocator = require('./PlansLocator')
|
const PlansLocator = require('./PlansLocator')
|
||||||
@@ -27,8 +31,9 @@ class PaymentProviderSubscription {
|
|||||||
* @param {Date} props.periodEnd
|
* @param {Date} props.periodEnd
|
||||||
* @param {string} props.collectionMethod
|
* @param {string} props.collectionMethod
|
||||||
* @param {PaymentProviderSubscriptionChange} [props.pendingChange]
|
* @param {PaymentProviderSubscriptionChange} [props.pendingChange]
|
||||||
* @param {string} [props.service]
|
* @param {PaymentProvider['service']} [props.service]
|
||||||
* @param {string} [props.state]
|
* @param {string} [props.state]
|
||||||
|
* @param {Date|null} [props.trialPeriodStart]
|
||||||
* @param {Date|null} [props.trialPeriodEnd]
|
* @param {Date|null} [props.trialPeriodEnd]
|
||||||
* @param {Date|null} [props.pausePeriodStart]
|
* @param {Date|null} [props.pausePeriodStart]
|
||||||
* @param {number|null} [props.remainingPauseCycles]
|
* @param {number|null} [props.remainingPauseCycles]
|
||||||
@@ -51,6 +56,7 @@ class PaymentProviderSubscription {
|
|||||||
this.pendingChange = props.pendingChange ?? null
|
this.pendingChange = props.pendingChange ?? null
|
||||||
this.service = props.service ?? 'recurly'
|
this.service = props.service ?? 'recurly'
|
||||||
this.state = props.state ?? 'active'
|
this.state = props.state ?? 'active'
|
||||||
|
this.trialPeriodStart = props.trialPeriodStart ?? null
|
||||||
this.trialPeriodEnd = props.trialPeriodEnd ?? null
|
this.trialPeriodEnd = props.trialPeriodEnd ?? null
|
||||||
this.pausePeriodStart = props.pausePeriodStart ?? null
|
this.pausePeriodStart = props.pausePeriodStart ?? null
|
||||||
this.remainingPauseCycles = props.remainingPauseCycles ?? null
|
this.remainingPauseCycles = props.remainingPauseCycles ?? null
|
||||||
|
|||||||
@@ -411,6 +411,7 @@ function subscriptionFromApi(apiSubscription) {
|
|||||||
collectionMethod: apiSubscription.collectionMethod,
|
collectionMethod: apiSubscription.collectionMethod,
|
||||||
service: 'recurly',
|
service: 'recurly',
|
||||||
state: apiSubscription.state ?? 'active',
|
state: apiSubscription.state ?? 'active',
|
||||||
|
trialPeriodStart: apiSubscription.trialStartedAt,
|
||||||
trialPeriodEnd: apiSubscription.trialEndsAt,
|
trialPeriodEnd: apiSubscription.trialEndsAt,
|
||||||
pausePeriodStart: apiSubscription.pausedAt,
|
pausePeriodStart: apiSubscription.pausedAt,
|
||||||
remainingPauseCycles: apiSubscription.remainingPauseCycles,
|
remainingPauseCycles: apiSubscription.remainingPauseCycles,
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ const UserAuditLogHandler = require('../User/UserAuditLogHandler')
|
|||||||
const AccountMappingHelper = require('../Analytics/AccountMappingHelper')
|
const AccountMappingHelper = require('../Analytics/AccountMappingHelper')
|
||||||
const { SSOConfig } = require('../../models/SSOConfig')
|
const { SSOConfig } = require('../../models/SSOConfig')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../../../../types/subscription/dashboard/subscription').Subscription} Subscription
|
||||||
|
* @typedef {import('../../../../types/subscription/dashboard/subscription').PaymentProvider} PaymentProvider
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the admin of the given subscription.
|
* Change the admin of the given subscription.
|
||||||
*
|
*
|
||||||
@@ -51,7 +56,7 @@ async function syncSubscription(
|
|||||||
let subscription =
|
let subscription =
|
||||||
await SubscriptionLocator.promises.getUsersSubscription(adminUserId)
|
await SubscriptionLocator.promises.getUsersSubscription(adminUserId)
|
||||||
if (subscription == null) {
|
if (subscription == null) {
|
||||||
subscription = await _createNewSubscription(adminUserId)
|
subscription = await createNewSubscription(adminUserId)
|
||||||
}
|
}
|
||||||
await updateSubscriptionFromRecurly(
|
await updateSubscriptionFromRecurly(
|
||||||
recurlySubscription,
|
recurlySubscription,
|
||||||
@@ -226,7 +231,13 @@ async function createDeletedSubscription(subscription, deleterData) {
|
|||||||
await DeletedSubscription.findOneAndUpdate(filter, data, options).exec()
|
await DeletedSubscription.findOneAndUpdate(filter, data, options).exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _createNewSubscription(adminUserId) {
|
/**
|
||||||
|
* Creates a new subscription for the given admin user.
|
||||||
|
*
|
||||||
|
* @param {string} adminUserId
|
||||||
|
* @returns {Promise<Subscription>}
|
||||||
|
*/
|
||||||
|
async function createNewSubscription(adminUserId) {
|
||||||
const subscription = new Subscription({
|
const subscription = new Subscription({
|
||||||
admin_id: adminUserId,
|
admin_id: adminUserId,
|
||||||
manager_ids: [adminUserId],
|
manager_ids: [adminUserId],
|
||||||
@@ -242,7 +253,7 @@ async function _deleteAndReplaceSubscriptionFromRecurly(
|
|||||||
) {
|
) {
|
||||||
const adminUserId = subscription.admin_id
|
const adminUserId = subscription.admin_id
|
||||||
await deleteSubscription(subscription, requesterData)
|
await deleteSubscription(subscription, requesterData)
|
||||||
const newSubscription = await _createNewSubscription(adminUserId)
|
const newSubscription = await createNewSubscription(adminUserId)
|
||||||
await updateSubscriptionFromRecurly(
|
await updateSubscriptionFromRecurly(
|
||||||
recurlySubscription,
|
recurlySubscription,
|
||||||
newSubscription,
|
newSubscription,
|
||||||
@@ -428,6 +439,7 @@ async function _sendSubscriptionEventForAllMembers(subscriptionId, event) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
updateAdmin: callbackify(updateAdmin),
|
updateAdmin: callbackify(updateAdmin),
|
||||||
syncSubscription: callbackify(syncSubscription),
|
syncSubscription: callbackify(syncSubscription),
|
||||||
|
createNewSubscription: callbackify(createNewSubscription),
|
||||||
deleteSubscription: callbackify(deleteSubscription),
|
deleteSubscription: callbackify(deleteSubscription),
|
||||||
createDeletedSubscription: callbackify(createDeletedSubscription),
|
createDeletedSubscription: callbackify(createDeletedSubscription),
|
||||||
addUserToGroup: callbackify(addUserToGroup),
|
addUserToGroup: callbackify(addUserToGroup),
|
||||||
@@ -440,6 +452,7 @@ module.exports = {
|
|||||||
promises: {
|
promises: {
|
||||||
updateAdmin,
|
updateAdmin,
|
||||||
syncSubscription,
|
syncSubscription,
|
||||||
|
createNewSubscription,
|
||||||
addUserToGroup,
|
addUserToGroup,
|
||||||
refreshUsersFeatures,
|
refreshUsersFeatures,
|
||||||
removeUserFromGroup,
|
removeUserFromGroup,
|
||||||
|
|||||||
@@ -64,6 +64,15 @@ const SubscriptionSchema = new Schema(
|
|||||||
subscriptionId: {
|
subscriptionId: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
state: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
trialStartedAt: {
|
||||||
|
type: Date,
|
||||||
|
},
|
||||||
|
trialEndsAt: {
|
||||||
|
type: Date,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
collectionMethod: {
|
collectionMethod: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ describe('SubscriptionHandler', function () {
|
|||||||
promises: {
|
promises: {
|
||||||
updateSubscriptionFromRecurly: sinon.stub().resolves(),
|
updateSubscriptionFromRecurly: sinon.stub().resolves(),
|
||||||
syncSubscription: sinon.stub().resolves(),
|
syncSubscription: sinon.stub().resolves(),
|
||||||
|
syncStripeSubscription: sinon.stub().resolves(),
|
||||||
startFreeTrial: sinon.stub().resolves(),
|
startFreeTrial: sinon.stub().resolves(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { SubscriptionState } from '../../subscription/dashboard/subscription'
|
||||||
|
|
||||||
type SubscriptionBase = {
|
type SubscriptionBase = {
|
||||||
featuresPageURL: string
|
featuresPageURL: string
|
||||||
}
|
}
|
||||||
@@ -9,7 +11,7 @@ export type FreePlanSubscription = {
|
|||||||
type FreeSubscription = FreePlanSubscription
|
type FreeSubscription = FreePlanSubscription
|
||||||
|
|
||||||
type RecurlyStatus = {
|
type RecurlyStatus = {
|
||||||
state: 'active' | 'canceled' | 'expired' | 'paused'
|
state: SubscriptionState
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaidSubscriptionBase = {
|
type PaidSubscriptionBase = {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '../plan'
|
} from '../plan'
|
||||||
import { User } from '../../user'
|
import { User } from '../../user'
|
||||||
|
|
||||||
type SubscriptionState = 'active' | 'canceled' | 'expired' | 'paused'
|
export type SubscriptionState = 'active' | 'canceled' | 'expired' | 'paused'
|
||||||
|
|
||||||
// when puchasing a new add-on in recurly, we only need to provide the code
|
// when puchasing a new add-on in recurly, we only need to provide the code
|
||||||
export type PurchasingAddOnCode = {
|
export type PurchasingAddOnCode = {
|
||||||
@@ -99,3 +99,13 @@ export type MemberGroupSubscription = Omit<GroupSubscription, 'admin_id'> & {
|
|||||||
planLevelName: string
|
planLevelName: string
|
||||||
admin_id: User
|
admin_id: User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaymentProviderService = 'stripe' | 'recurly'
|
||||||
|
|
||||||
|
export type PaymentProvider = {
|
||||||
|
service: PaymentProviderService
|
||||||
|
subscriptionId: string
|
||||||
|
state: SubscriptionState
|
||||||
|
trialStartedAt?: Nullable<Date>
|
||||||
|
trialEndsAt?: Nullable<Date>
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user