|
|
@@ -1,11 +1,14 @@
|
|
|
-// TODO: This file may be deleted when Stripe is fully implemented to all users, so, consider deleting it
|
|
|
+// @ts-check
|
|
|
+
|
|
|
const Settings = require('@overleaf/settings')
|
|
|
const logger = require('@overleaf/logger')
|
|
|
|
|
|
/**
|
|
|
* @typedef {import('../../../../types/subscription/plan').RecurlyPlanCode} RecurlyPlanCode
|
|
|
- * @typedef {import('../../../../types/subscription/plan').RecurlyAddOnCode} RecurlyAddOnCode
|
|
|
* @typedef {import('../../../../types/subscription/plan').StripeLookupKey} StripeLookupKey
|
|
|
+ * @typedef {import('../../../../types/subscription/plan').StripeBaseLookupKey} StripeBaseLookupKey
|
|
|
+ * @typedef {import('../../../../types/subscription/plan').Plan} Plan
|
|
|
+ * @typedef {import('../../../../types/subscription/currency').StripeCurrencyCode} StripeCurrencyCode
|
|
|
* @typedef {import('stripe').Stripe.Price.Recurring.Interval} BillingCycleInterval
|
|
|
*/
|
|
|
|
|
|
@@ -26,18 +29,21 @@ function ensurePlansAreSetupCorrectly() {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-const recurlyPlanCodeToStripeLookupKey = {
|
|
|
- collaborator: 'collaborator_may2025',
|
|
|
- 'collaborator-annual': 'collaborator_annual_may2025',
|
|
|
- collaborator_free_trial_7_days: 'collaborator_may2025',
|
|
|
+/**
|
|
|
+ * @type {Record<RecurlyPlanCode, StripeBaseLookupKey>}
|
|
|
+ */
|
|
|
+const recurlyCodeToStripeBaseLookupKey = {
|
|
|
+ collaborator: 'standard_monthly',
|
|
|
+ 'collaborator-annual': 'standard_annual',
|
|
|
+ collaborator_free_trial_7_days: 'standard_monthly',
|
|
|
|
|
|
- professional: 'professional_may2025',
|
|
|
- 'professional-annual': 'professional_annual_may2025',
|
|
|
- professional_free_trial_7_days: 'professional_may2025',
|
|
|
+ professional: 'professional_monthly',
|
|
|
+ 'professional-annual': 'professional_annual',
|
|
|
+ professional_free_trial_7_days: 'professional_monthly',
|
|
|
|
|
|
- student: 'student_may2025',
|
|
|
- 'student-annual': 'student_annual_may2025',
|
|
|
- student_free_trial_7_days: 'student_may2025',
|
|
|
+ student: 'student_monthly',
|
|
|
+ 'student-annual': 'student_annual',
|
|
|
+ student_free_trial_7_days: 'student_monthly',
|
|
|
|
|
|
// TODO: change all group plans' lookup_keys to match the UK account after they have been added
|
|
|
group_collaborator: 'group_standard_enterprise',
|
|
|
@@ -45,41 +51,46 @@ const recurlyPlanCodeToStripeLookupKey = {
|
|
|
group_professional: 'group_professional_enterprise',
|
|
|
group_professional_educational: 'group_professional_educational',
|
|
|
|
|
|
- assistant: 'assistant_may2025',
|
|
|
- 'assistant-annual': 'assistant_annual_may2025',
|
|
|
+ assistant: 'assistant_monthly',
|
|
|
+ 'assistant-annual': 'assistant_annual',
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- *
|
|
|
- * @param {RecurlyPlanCode} recurlyPlanCode
|
|
|
- * @returns {StripeLookupKey}
|
|
|
- */
|
|
|
-function mapRecurlyPlanCodeToStripeLookupKey(recurlyPlanCode) {
|
|
|
- return recurlyPlanCodeToStripeLookupKey[recurlyPlanCode]
|
|
|
-}
|
|
|
+const LATEST_STRIPE_LOOKUP_KEY_VERSION = 'jun2025'
|
|
|
|
|
|
/**
|
|
|
+ * Build the Stripe lookup key, will be in this format:
|
|
|
+ * `${productCode}_${billingInterval}_${latestVersion}_${currency}`
|
|
|
+ * (for example: 'assistant_annual_jun2025_clp')
|
|
|
*
|
|
|
- * @param {RecurlyAddOnCode} recurlyAddOnCode
|
|
|
- * @param {BillingCycleInterval} billingCycleInterval
|
|
|
+ * @param {RecurlyPlanCode} recurlyCode
|
|
|
+ * @param {StripeCurrencyCode} currency
|
|
|
+ * @param {BillingCycleInterval} [billingCycleInterval] -- needed for handling 'assistant' add-on
|
|
|
* @returns {StripeLookupKey|null}
|
|
|
*/
|
|
|
-function mapRecurlyAddOnCodeToStripeLookupKey(
|
|
|
- recurlyAddOnCode,
|
|
|
- billingCycleInterval
|
|
|
-) {
|
|
|
+function buildStripeLookupKey(recurlyCode, currency, billingCycleInterval) {
|
|
|
+ let stripeBaseLookupKey = recurlyCodeToStripeBaseLookupKey[recurlyCode]
|
|
|
+
|
|
|
// Recurly always uses 'assistant' as the code regardless of the subscription duration
|
|
|
- if (recurlyAddOnCode === 'assistant') {
|
|
|
+ if (recurlyCode === 'assistant' && billingCycleInterval) {
|
|
|
if (billingCycleInterval === 'month') {
|
|
|
- return 'assistant_may2025'
|
|
|
+ stripeBaseLookupKey = 'assistant_monthly'
|
|
|
}
|
|
|
if (billingCycleInterval === 'year') {
|
|
|
- return 'assistant_annual_may2025'
|
|
|
+ stripeBaseLookupKey = 'assistant_annual'
|
|
|
}
|
|
|
}
|
|
|
- return null
|
|
|
+
|
|
|
+ if (stripeBaseLookupKey == null) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ return `${stripeBaseLookupKey}_${LATEST_STRIPE_LOOKUP_KEY_VERSION}_${currency}`
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @typedef {{ planType: 'individual' | 'group' | 'student' | null, period: 'annual' | 'monthly' }} PlanTypeAndPeriod
|
|
|
+ * @type {Record<RecurlyPlanCode, PlanTypeAndPeriod>}
|
|
|
+ */
|
|
|
const recurlyPlanCodeToPlanTypeAndPeriod = {
|
|
|
collaborator: { planType: 'individual', period: 'monthly' },
|
|
|
'collaborator-annual': { planType: 'individual', period: 'annual' },
|
|
|
@@ -106,14 +117,17 @@ const recurlyPlanCodeToPlanTypeAndPeriod = {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
* @param {RecurlyPlanCode} recurlyPlanCode
|
|
|
- * @returns {{ planType: 'individual' | 'group' | 'student' | null, period: 'annual' | 'monthly'}}
|
|
|
+ * @returns {PlanTypeAndPeriod}
|
|
|
*/
|
|
|
function getPlanTypeAndPeriodFromRecurlyPlanCode(recurlyPlanCode) {
|
|
|
return recurlyPlanCodeToPlanTypeAndPeriod[recurlyPlanCode]
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @param {string|null} [planCode]
|
|
|
+ * @returns {Plan|null}
|
|
|
+ */
|
|
|
function findLocalPlanInSettings(planCode) {
|
|
|
for (const plan of Settings.plans) {
|
|
|
if (plan.planCode === planCode) {
|
|
|
@@ -126,7 +140,6 @@ function findLocalPlanInSettings(planCode) {
|
|
|
module.exports = {
|
|
|
ensurePlansAreSetupCorrectly,
|
|
|
findLocalPlanInSettings,
|
|
|
- mapRecurlyPlanCodeToStripeLookupKey,
|
|
|
- mapRecurlyAddOnCodeToStripeLookupKey,
|
|
|
+ buildStripeLookupKey,
|
|
|
getPlanTypeAndPeriodFromRecurlyPlanCode,
|
|
|
}
|