mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #26014 from overleaf/kh-remaining-references-to-recurly-fields
[web] update remaining references to `recurlyStatus` and `recurlySubscription_id` GitOrigin-RevId: f5e905eba598cfcd146803c6ccc36a2304021544
This commit is contained in:
@@ -14,6 +14,7 @@ const ProjectHelper = require('./ProjectHelper')
|
||||
const metrics = require('@overleaf/metrics')
|
||||
const { User } = require('../../models/User')
|
||||
const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
|
||||
const { isPaidSubscription } = require('../Subscription/SubscriptionHelper')
|
||||
const LimitationsManager = require('../Subscription/LimitationsManager')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const AuthorizationManager = require('../Authorization/AuthorizationManager')
|
||||
@@ -655,12 +656,11 @@ const _ProjectController = {
|
||||
}
|
||||
}
|
||||
|
||||
const hasNonRecurlySubscription =
|
||||
subscription && !subscription.recurlySubscription_id
|
||||
const hasPaidSubscription = isPaidSubscription(subscription)
|
||||
const hasManuallyCollectedSubscription =
|
||||
subscription?.collectionMethod === 'manual'
|
||||
const canPurchaseAddons = !(
|
||||
hasNonRecurlySubscription || hasManuallyCollectedSubscription
|
||||
hasPaidSubscription || hasManuallyCollectedSubscription
|
||||
)
|
||||
const assistantDisabled = user.aiErrorAssistant?.enabled === false // the assistant has been manually disabled by the user
|
||||
const canUseErrorAssistant =
|
||||
@@ -792,7 +792,7 @@ const _ProjectController = {
|
||||
referal_id: user.referal_id,
|
||||
signUpDate: user.signUpDate,
|
||||
allowedFreeTrial,
|
||||
hasRecurlySubscription: subscription?.recurlySubscription_id != null,
|
||||
hasPaidSubscription,
|
||||
featureSwitches: user.featureSwitches,
|
||||
features: fullFeatureSet,
|
||||
featureUsage,
|
||||
|
||||
@@ -26,6 +26,7 @@ import GeoIpLookup from '../../infrastructure/GeoIpLookup.js'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import SplitTestSessionHandler from '../SplitTests/SplitTestSessionHandler.js'
|
||||
import TutorialHandler from '../Tutorial/TutorialHandler.js'
|
||||
import SubscriptionHelper from '../Subscription/SubscriptionHelper.js'
|
||||
|
||||
/**
|
||||
* @import { GetProjectsRequest, GetProjectsResponse, AllUsersProjects, MongoProject } from "./types"
|
||||
@@ -388,13 +389,13 @@ async function projectListPage(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
let hasIndividualRecurlySubscription = false
|
||||
let hasIndividualPaidSubscription = false
|
||||
|
||||
try {
|
||||
hasIndividualRecurlySubscription =
|
||||
usersIndividualSubscription?.groupPlan === false &&
|
||||
usersIndividualSubscription?.recurlyStatus?.state !== 'canceled' &&
|
||||
usersIndividualSubscription?.recurlySubscription_id !== ''
|
||||
hasIndividualPaidSubscription =
|
||||
SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
usersIndividualSubscription
|
||||
)
|
||||
} catch (error) {
|
||||
logger.error({ err: error }, 'Failed to get individual subscription')
|
||||
}
|
||||
@@ -437,7 +438,7 @@ async function projectListPage(req, res, next) {
|
||||
groupId: subscription._id,
|
||||
groupName: subscription.teamName,
|
||||
})),
|
||||
hasIndividualRecurlySubscription,
|
||||
hasIndividualPaidSubscription,
|
||||
userRestrictions: Array.from(req.userRestrictions || []),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ const { callbackify } = require('util')
|
||||
const { callbackifyMultiResult } = require('@overleaf/promise-utils')
|
||||
const PlansLocator = require('./PlansLocator')
|
||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||
const SubscriptionHelper = require('./SubscriptionHelper')
|
||||
const UserFeaturesUpdater = require('./UserFeaturesUpdater')
|
||||
const FeaturesHelper = require('./FeaturesHelper')
|
||||
const Settings = require('@overleaf/settings')
|
||||
@@ -117,7 +118,10 @@ async function computeFeatures(userId) {
|
||||
async function _getIndividualFeatures(userId) {
|
||||
const subscription =
|
||||
await SubscriptionLocator.promises.getUsersSubscription(userId)
|
||||
if (subscription == null || subscription?.recurlyStatus?.state === 'paused') {
|
||||
if (
|
||||
subscription == null ||
|
||||
SubscriptionHelper.getPaidSubscriptionState(subscription) === 'paused'
|
||||
) {
|
||||
return {}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const SessionManager = require('../Authentication/SessionManager')
|
||||
const SubscriptionHandler = require('./SubscriptionHandler')
|
||||
const SubscriptionHelper = require('./SubscriptionHelper')
|
||||
const SubscriptionViewModelBuilder = require('./SubscriptionViewModelBuilder')
|
||||
const LimitationsManager = require('./LimitationsManager')
|
||||
const RecurlyWrapper = require('./RecurlyWrapper')
|
||||
@@ -262,7 +263,8 @@ async function pauseSubscription(req, res, next) {
|
||||
{
|
||||
pause_length: pauseCycles,
|
||||
plan_code: subscription?.planCode,
|
||||
subscriptionId: subscription?.recurlySubscription_id,
|
||||
subscriptionId:
|
||||
SubscriptionHelper.getPaymentProviderSubscriptionId(subscription),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ const OError = require('@overleaf/o-error')
|
||||
const SubscriptionUpdater = require('./SubscriptionUpdater')
|
||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||
const SubscriptionController = require('./SubscriptionController')
|
||||
const SubscriptionHelper = require('./SubscriptionHelper')
|
||||
const { Subscription } = require('../../models/Subscription')
|
||||
const { User } = require('../../models/User')
|
||||
const RecurlyClient = require('./RecurlyClient')
|
||||
@@ -77,7 +78,7 @@ async function ensureFlexibleLicensingEnabled(plan) {
|
||||
}
|
||||
|
||||
async function ensureSubscriptionIsActive(subscription) {
|
||||
if (subscription?.recurlyStatus?.state !== 'active') {
|
||||
if (SubscriptionHelper.getPaidSubscriptionState(subscription) !== 'active') {
|
||||
throw new InactiveError('The subscription is not active', {
|
||||
subscriptionId: subscription._id.toString(),
|
||||
})
|
||||
|
||||
@@ -4,6 +4,7 @@ const RecurlyWrapper = require('./RecurlyWrapper')
|
||||
const RecurlyClient = require('./RecurlyClient')
|
||||
const { User } = require('../../models/User')
|
||||
const logger = require('@overleaf/logger')
|
||||
const SubscriptionHelper = require('./SubscriptionHelper')
|
||||
const SubscriptionUpdater = require('./SubscriptionUpdater')
|
||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||
const LimitationsManager = require('./LimitationsManager')
|
||||
@@ -101,8 +102,7 @@ async function updateSubscription(user, planCode) {
|
||||
if (
|
||||
!hasSubscription ||
|
||||
subscription == null ||
|
||||
(subscription.recurlySubscription_id == null &&
|
||||
subscription.paymentProvider?.subscriptionId == null)
|
||||
SubscriptionHelper.getPaymentProviderSubscriptionId(subscription) == null
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -299,7 +299,10 @@ async function pauseSubscription(user, pauseCycles) {
|
||||
// only allow pausing on monthly plans not in a trial
|
||||
const { subscription } =
|
||||
await LimitationsManager.promises.userHasSubscription(user)
|
||||
if (!subscription || !subscription.recurlyStatus) {
|
||||
if (
|
||||
!subscription ||
|
||||
!SubscriptionHelper.getPaidSubscriptionState(subscription)
|
||||
) {
|
||||
throw new Error('No active subscription to pause')
|
||||
}
|
||||
|
||||
@@ -310,10 +313,9 @@ async function pauseSubscription(user, pauseCycles) {
|
||||
) {
|
||||
throw new Error('Can only pause monthly individual plans')
|
||||
}
|
||||
if (
|
||||
subscription.recurlyStatus.trialEndsAt &&
|
||||
subscription.recurlyStatus.trialEndsAt > new Date()
|
||||
) {
|
||||
const trialEndsAt =
|
||||
SubscriptionHelper.getSubscriptionTrialEndsAt(subscription)
|
||||
if (trialEndsAt && trialEndsAt > new Date()) {
|
||||
throw new Error('Cannot pause a subscription in a trial')
|
||||
}
|
||||
if (subscription.addOns?.length) {
|
||||
@@ -329,7 +331,10 @@ async function pauseSubscription(user, pauseCycles) {
|
||||
async function resumeSubscription(user) {
|
||||
const { subscription } =
|
||||
await LimitationsManager.promises.userHasSubscription(user)
|
||||
if (!subscription || !subscription.recurlyStatus) {
|
||||
if (
|
||||
!subscription ||
|
||||
!SubscriptionHelper.getPaidSubscriptionState(subscription)
|
||||
) {
|
||||
throw new Error('No active subscription to resume')
|
||||
}
|
||||
await RecurlyClient.promises.resumeSubscriptionByUuid(
|
||||
|
||||
@@ -86,7 +86,66 @@ function generateInitialLocalizedGroupPrice(recommendedCurrency, locale) {
|
||||
}
|
||||
}
|
||||
|
||||
function isPaidSubscription(subscription) {
|
||||
const hasRecurlySubscription =
|
||||
subscription?.recurlySubscription_id &&
|
||||
subscription?.recurlySubscription_id !== ''
|
||||
const hasStripeSubscription =
|
||||
subscription?.paymentProvider?.subscriptionId &&
|
||||
subscription?.paymentProvider?.subscriptionId !== ''
|
||||
return !!(subscription && (hasRecurlySubscription || hasStripeSubscription))
|
||||
}
|
||||
|
||||
function isIndividualActivePaidSubscription(subscription) {
|
||||
return (
|
||||
isPaidSubscription(subscription) &&
|
||||
subscription?.groupPlan === false &&
|
||||
subscription?.recurlyStatus?.state !== 'canceled' &&
|
||||
subscription?.paymentProvider?.state !== 'canceled'
|
||||
)
|
||||
}
|
||||
|
||||
function getPaymentProviderSubscriptionId(subscription) {
|
||||
if (subscription?.recurlySubscription_id) {
|
||||
return subscription.recurlySubscription_id
|
||||
}
|
||||
if (subscription?.paymentProvider?.subscriptionId) {
|
||||
return subscription.paymentProvider.subscriptionId
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function getPaidSubscriptionState(subscription) {
|
||||
if (subscription?.recurlyStatus?.state) {
|
||||
return subscription.recurlyStatus.state
|
||||
}
|
||||
if (subscription?.paymentProvider?.state) {
|
||||
return subscription.paymentProvider.state
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function getSubscriptionTrialStartedAt(subscription) {
|
||||
if (subscription?.recurlyStatus) {
|
||||
return subscription.recurlyStatus?.trialStartedAt
|
||||
}
|
||||
return subscription?.paymentProvider?.trialStartedAt
|
||||
}
|
||||
|
||||
function getSubscriptionTrialEndsAt(subscription) {
|
||||
if (subscription?.recurlyStatus) {
|
||||
return subscription.recurlyStatus?.trialEndsAt
|
||||
}
|
||||
return subscription?.paymentProvider?.trialEndsAt
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldPlanChangeAtTermEnd,
|
||||
generateInitialLocalizedGroupPrice,
|
||||
isPaidSubscription,
|
||||
isIndividualActivePaidSubscription,
|
||||
getPaymentProviderSubscriptionId,
|
||||
getPaidSubscriptionState,
|
||||
getSubscriptionTrialStartedAt,
|
||||
getSubscriptionTrialEndsAt,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// ts-check
|
||||
const Settings = require('@overleaf/settings')
|
||||
const RecurlyWrapper = require('./RecurlyWrapper')
|
||||
const PlansLocator = require('./PlansLocator')
|
||||
const {
|
||||
isStandaloneAiAddOnPlanCode,
|
||||
@@ -8,7 +7,6 @@ const {
|
||||
} = require('./PaymentProviderEntities')
|
||||
const SubscriptionFormatters = require('./SubscriptionFormatters')
|
||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||
const SubscriptionUpdater = require('./SubscriptionUpdater')
|
||||
const InstitutionsGetter = require('../Institutions/InstitutionsGetter')
|
||||
const InstitutionsManager = require('../Institutions/InstitutionsManager')
|
||||
const PublishersGetter = require('../Publishers/PublishersGetter')
|
||||
@@ -227,6 +225,7 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') {
|
||||
// don't return subscription payment information
|
||||
delete personalSubscription.paymentProvider
|
||||
delete personalSubscription.recurly
|
||||
delete personalSubscription.recurlySubscription_id
|
||||
|
||||
const tax = paymentRecord.subscription.taxAmount || 0
|
||||
// Some plans allow adding more seats than the base plan provides.
|
||||
@@ -374,15 +373,6 @@ async function buildUsersSubscriptionViewModel(user, locale = 'en') {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{_id: string}} user
|
||||
* @returns {Promise<Subscription>}
|
||||
*/
|
||||
async function getBestSubscription(user) {
|
||||
const { bestSubscription } = await getUsersSubscriptionDetails(user)
|
||||
return bestSubscription
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{_id: string}} user
|
||||
* @returns {Promise<{bestSubscription:Subscription,individualSubscription:DBSubscription|null,memberGroupSubscriptions:DBSubscription[]}>}
|
||||
@@ -400,15 +390,18 @@ async function getUsersSubscriptionDetails(user) {
|
||||
if (
|
||||
individualSubscription &&
|
||||
!individualSubscription.customAccount &&
|
||||
individualSubscription.recurlySubscription_id &&
|
||||
!individualSubscription.recurlyStatus?.state
|
||||
SubscriptionHelper.getPaymentProviderSubscriptionId(
|
||||
individualSubscription
|
||||
) &&
|
||||
!SubscriptionHelper.getPaidSubscriptionState(individualSubscription)
|
||||
) {
|
||||
const recurlySubscription = await RecurlyWrapper.promises.getSubscription(
|
||||
individualSubscription.recurlySubscription_id,
|
||||
{ includeAccount: true }
|
||||
const paymentResults = await Modules.promises.hooks.fire(
|
||||
'getPaymentFromRecordPromise',
|
||||
individualSubscription
|
||||
)
|
||||
await SubscriptionUpdater.promises.updateSubscriptionFromRecurly(
|
||||
recurlySubscription,
|
||||
await Modules.promises.hooks.fire(
|
||||
'syncSubscription',
|
||||
paymentResults[0]?.subscription,
|
||||
individualSubscription
|
||||
)
|
||||
individualSubscription =
|
||||
@@ -540,7 +533,8 @@ function _isPlanEqualOrBetter(planA, planB) {
|
||||
|
||||
function _getRemainingTrialDays(subscription) {
|
||||
const now = new Date()
|
||||
const trialEndDate = subscription.recurlyStatus?.trialEndsAt
|
||||
const trialEndDate =
|
||||
SubscriptionHelper.getSubscriptionTrialEndsAt(subscription)
|
||||
return trialEndDate && trialEndDate > now
|
||||
? Math.ceil(
|
||||
(trialEndDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000)
|
||||
@@ -605,10 +599,8 @@ module.exports = {
|
||||
buildUsersSubscriptionViewModel: callbackify(buildUsersSubscriptionViewModel),
|
||||
buildPlansList,
|
||||
buildPlansListForSubscriptionDash,
|
||||
getBestSubscription: callbackify(getBestSubscription),
|
||||
promises: {
|
||||
buildUsersSubscriptionViewModel,
|
||||
getBestSubscription,
|
||||
getUsersSubscriptionDetails,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import OError from '@overleaf/o-error'
|
||||
import TeamInvitesHandler from './TeamInvitesHandler.js'
|
||||
import SessionManager from '../Authentication/SessionManager.js'
|
||||
import SubscriptionLocator from './SubscriptionLocator.js'
|
||||
import SubscriptionHelper from './SubscriptionHelper.js'
|
||||
import ErrorController from '../Errors/ErrorController.js'
|
||||
import EmailHelper from '../Helpers/EmailHelper.js'
|
||||
import UserGetter from '../User/UserGetter.js'
|
||||
@@ -87,12 +88,10 @@ async function viewInvite(req, res, next) {
|
||||
const personalSubscription =
|
||||
await SubscriptionLocator.promises.getUsersSubscription(userId)
|
||||
|
||||
const hasIndividualRecurlySubscription =
|
||||
personalSubscription &&
|
||||
personalSubscription.groupPlan === false &&
|
||||
personalSubscription.recurlyStatus?.state !== 'canceled' &&
|
||||
personalSubscription.recurlySubscription_id &&
|
||||
personalSubscription.recurlySubscription_id !== ''
|
||||
const hasIndividualPaidSubscription =
|
||||
SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
personalSubscription
|
||||
)
|
||||
|
||||
if (subscription?.managedUsersEnabled) {
|
||||
if (!subscription.populated('groupPolicy')) {
|
||||
@@ -155,7 +154,7 @@ async function viewInvite(req, res, next) {
|
||||
return res.render('subscriptions/team/invite', {
|
||||
inviterName: invite.inviterName,
|
||||
inviteToken: invite.token,
|
||||
hasIndividualRecurlySubscription,
|
||||
hasIndividualPaidSubscription,
|
||||
expired: req.query.expired,
|
||||
userRestrictions: Array.from(req.userRestrictions || []),
|
||||
currentManagedUserAdminEmail,
|
||||
|
||||
@@ -34,7 +34,7 @@ block append meta
|
||||
meta(name="ol-recommendedCurrency" data-type="string" content=recommendedCurrency)
|
||||
meta(name="ol-showLATAMBanner" data-type="boolean" content=showLATAMBanner)
|
||||
meta(name="ol-groupSubscriptionsPendingEnrollment" data-type="json" content=groupSubscriptionsPendingEnrollment)
|
||||
meta(name="ol-hasIndividualRecurlySubscription" data-type="boolean" content=hasIndividualRecurlySubscription)
|
||||
meta(name="ol-hasIndividualPaidSubscription" data-type="boolean" content=hasIndividualPaidSubscription)
|
||||
meta(name="ol-groupSsoSetupSuccess" data-type="boolean" content=groupSsoSetupSuccess)
|
||||
meta(name="ol-showUSGovBanner" data-type="boolean" content=showUSGovBanner)
|
||||
meta(name="ol-usGovBannerVariant" data-type="string" content=usGovBannerVariant)
|
||||
|
||||
@@ -4,7 +4,7 @@ block entrypointVar
|
||||
- entrypoint = 'pages/user/subscription/invite'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-hasIndividualRecurlySubscription" data-type="boolean" content=hasIndividualRecurlySubscription)
|
||||
meta(name="ol-hasIndividualPaidSubscription" data-type="boolean" content=hasIndividualPaidSubscription)
|
||||
meta(name="ol-inviterName" data-type="string" content=inviterName)
|
||||
meta(name="ol-inviteToken" data-type="string" content=inviteToken)
|
||||
meta(name="ol-currentManagedUserAdminEmail" data-type="string" content=currentManagedUserAdminEmail)
|
||||
|
||||
@@ -4,6 +4,7 @@ import GroupPlan from './group-plan'
|
||||
import CommonsPlan from './commons-plan'
|
||||
import PausedPlan from './paused-plan'
|
||||
import getMeta from '../../../../utils/meta'
|
||||
import { getUserSubscriptionState } from '../../util/user'
|
||||
|
||||
function CurrentPlanWidget() {
|
||||
const usersBestSubscription = getMeta('ol-usersBestSubscription')
|
||||
@@ -19,7 +20,7 @@ function CurrentPlanWidget() {
|
||||
const isCommonsPlan = type === 'commons'
|
||||
const isPaused =
|
||||
isIndividualPlan &&
|
||||
usersBestSubscription.subscription?.recurlyStatus?.state === 'paused'
|
||||
getUserSubscriptionState(usersBestSubscription) === 'paused'
|
||||
|
||||
const featuresPageURL = '/learn/how-to/Overleaf_premium_features'
|
||||
const subscriptionPageUrl = '/user/subscription'
|
||||
|
||||
@@ -57,19 +57,19 @@ export function useGroupInvitationNotification(
|
||||
const location = useLocation()
|
||||
const { handleDismiss } = useAsyncDismiss()
|
||||
|
||||
const hasIndividualRecurlySubscription = getMeta(
|
||||
'ol-hasIndividualRecurlySubscription'
|
||||
const hasIndividualPaidSubscription = getMeta(
|
||||
'ol-hasIndividualPaidSubscription'
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (hasIndividualRecurlySubscription) {
|
||||
if (hasIndividualPaidSubscription) {
|
||||
setGroupInvitationStatus(
|
||||
GroupInvitationStatus.CancelIndividualSubscription
|
||||
)
|
||||
} else {
|
||||
setGroupInvitationStatus(GroupInvitationStatus.AskToJoin)
|
||||
}
|
||||
}, [hasIndividualRecurlySubscription])
|
||||
}, [hasIndividualPaidSubscription])
|
||||
|
||||
const acceptGroupInvite = useCallback(() => {
|
||||
if (managedUsersEnabled) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { UserRef } from '../../../../../types/project/dashboard/api'
|
||||
import { Subscription } from '../../../../../types/project/dashboard/subscription'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
export function getUserName(user: UserRef) {
|
||||
@@ -20,3 +21,16 @@ export function getUserName(user: UserRef) {
|
||||
|
||||
return 'None'
|
||||
}
|
||||
|
||||
export function getUserSubscriptionState(subscription: Subscription) {
|
||||
if ('subscription' in subscription) {
|
||||
if (subscription.subscription.recurlyStatus) {
|
||||
return subscription.subscription.recurlyStatus.state
|
||||
}
|
||||
if (subscription.subscription.paymentProvider) {
|
||||
return subscription.subscription.paymentProvider.state
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -19,20 +19,20 @@ export type InviteViewTypes =
|
||||
| undefined
|
||||
|
||||
function GroupInviteViews() {
|
||||
const hasIndividualRecurlySubscription = getMeta(
|
||||
'ol-hasIndividualRecurlySubscription'
|
||||
const hasIndividualPaidSubscription = getMeta(
|
||||
'ol-hasIndividualPaidSubscription'
|
||||
)
|
||||
const cannotJoinSubscription = getMeta('ol-cannot-join-subscription')
|
||||
|
||||
useEffect(() => {
|
||||
if (cannotJoinSubscription) {
|
||||
setView('managed-user-cannot-join')
|
||||
} else if (hasIndividualRecurlySubscription) {
|
||||
} else if (hasIndividualPaidSubscription) {
|
||||
setView('cancel-personal-subscription')
|
||||
} else {
|
||||
setView('invite')
|
||||
}
|
||||
}, [cannotJoinSubscription, hasIndividualRecurlySubscription])
|
||||
}, [cannotJoinSubscription, hasIndividualPaidSubscription])
|
||||
const [view, setView] = useState<InviteViewTypes>(undefined)
|
||||
|
||||
if (!view) {
|
||||
|
||||
@@ -127,7 +127,7 @@ export interface Meta {
|
||||
'ol-groupsAndEnterpriseBannerVariant': GroupsAndEnterpriseBannerVariant
|
||||
'ol-hasAiAssistViaWritefull': boolean
|
||||
'ol-hasGroupSSOFeature': boolean
|
||||
'ol-hasIndividualRecurlySubscription': boolean
|
||||
'ol-hasIndividualPaidSubscription': boolean
|
||||
'ol-hasManagedUsersFeature': boolean
|
||||
'ol-hasPassword': boolean
|
||||
'ol-hasSubscription': boolean
|
||||
|
||||
@@ -186,7 +186,7 @@ export const NotificationGroupInvitationCancelSubscription = (args: any) => {
|
||||
},
|
||||
})
|
||||
|
||||
window.metaAttributesCache.set('ol-hasIndividualRecurlySubscription', true)
|
||||
window.metaAttributesCache.set('ol-hasIndividualPaidSubscription', true)
|
||||
|
||||
return (
|
||||
<ProjectListProvider>
|
||||
|
||||
@@ -62,10 +62,7 @@ describe('<GroupInvitationNotification />', function () {
|
||||
|
||||
describe('user with existing personal subscription', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-hasIndividualRecurlySubscription',
|
||||
true
|
||||
)
|
||||
window.metaAttributesCache.set('ol-hasIndividualPaidSubscription', true)
|
||||
})
|
||||
|
||||
it('is able to join group successfully without cancelling personal subscription', function () {
|
||||
|
||||
@@ -441,7 +441,7 @@ describe('<UserNotifications />', function () {
|
||||
),
|
||||
])
|
||||
window.metaAttributesCache.set(
|
||||
'ol-hasIndividualRecurlySubscription',
|
||||
'ol-hasIndividualPaidSubscription',
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
@@ -18,10 +18,7 @@ describe('group invite', function () {
|
||||
|
||||
describe('when user has personal subscription', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-hasIndividualRecurlySubscription',
|
||||
true
|
||||
)
|
||||
window.metaAttributesCache.set('ol-hasIndividualPaidSubscription', true)
|
||||
})
|
||||
|
||||
it('renders cancel personal subscription view', async function () {
|
||||
@@ -55,10 +52,7 @@ describe('group invite', function () {
|
||||
|
||||
describe('when user does not have a personal subscription', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-hasIndividualRecurlySubscription',
|
||||
false
|
||||
)
|
||||
window.metaAttributesCache.set('ol-hasIndividualPaidSubscription', false)
|
||||
window.metaAttributesCache.set('ol-inviteToken', 'token123')
|
||||
})
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ export const annualActiveSubscription: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -68,7 +67,6 @@ export const annualActiveSubscriptionEuro: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -111,7 +109,6 @@ export const annualActiveSubscriptionPro: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'professional',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'professional',
|
||||
name: 'Professional',
|
||||
@@ -153,7 +150,6 @@ export const pastDueExpiredSubscription: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -196,7 +192,6 @@ export const canceledSubscription: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -239,7 +234,6 @@ export const pendingSubscriptionChange: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -290,7 +284,6 @@ export const groupActiveSubscription: GroupSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'group_collaborator_10_enterprise',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'group_collaborator_10_enterprise',
|
||||
name: 'Overleaf Standard (Collaborator) - Group Account (10 licenses) - Enterprise',
|
||||
@@ -338,7 +331,6 @@ export const groupActiveSubscriptionWithPendingLicenseChange: GroupSubscription
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'group_collaborator_10_enterprise',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'group_collaborator_10_enterprise',
|
||||
name: 'Overleaf Standard (Collaborator) - Group Account (10 licenses) - Enterprise',
|
||||
@@ -396,7 +388,6 @@ export const trialSubscription: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'paid-personal_free_trial_7_days',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'paid-personal_free_trial_7_days',
|
||||
name: 'Personal',
|
||||
@@ -439,7 +430,6 @@ export const customSubscription: CustomSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator-annual',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator-annual',
|
||||
name: 'Standard (Collaborator) Annual',
|
||||
@@ -460,7 +450,6 @@ export const trialCollaboratorSubscription: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator_free_trial_7_days',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator_free_trial_7_days',
|
||||
name: 'Standard (Collaborator)',
|
||||
@@ -503,7 +492,6 @@ export const monthlyActiveCollaborator: PaidSubscription = {
|
||||
admin_id: 'abc123',
|
||||
teamInvites: [],
|
||||
planCode: 'collaborator',
|
||||
recurlySubscription_id: 'ghi789',
|
||||
plan: {
|
||||
planCode: 'collaborator',
|
||||
name: 'Standard (Collaborator)',
|
||||
|
||||
@@ -201,9 +201,6 @@ describe('ProjectController', function () {
|
||||
getCurrentAffiliations: sinon.stub().resolves([]),
|
||||
},
|
||||
}
|
||||
this.SubscriptionViewModelBuilder = {
|
||||
getBestSubscription: sinon.stub().yields(null, { type: 'free' }),
|
||||
}
|
||||
this.SurveyHandler = {
|
||||
getSurvey: sinon.stub().yields(null, {}),
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ const MockResponse = require('../helpers/MockResponse')
|
||||
const modulePath =
|
||||
'../../../../app/src/Features/Subscription/SubscriptionController'
|
||||
const SubscriptionErrors = require('../../../../app/src/Features/Subscription/Errors')
|
||||
const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
|
||||
|
||||
const mockSubscriptions = {
|
||||
'subscription-123-active': {
|
||||
@@ -77,7 +78,6 @@ describe('SubscriptionController', function () {
|
||||
buildPlansList: sinon.stub(),
|
||||
promises: {
|
||||
buildUsersSubscriptionViewModel: sinon.stub().resolves({}),
|
||||
getBestSubscription: sinon.stub().resolves({}),
|
||||
},
|
||||
buildPlansListForSubscriptionDash: sinon
|
||||
.stub()
|
||||
@@ -146,7 +146,7 @@ describe('SubscriptionController', function () {
|
||||
'../SplitTests/SplitTestHandler': this.SplitTestV2Hander,
|
||||
'../Authentication/SessionManager': this.SessionManager,
|
||||
'./SubscriptionHandler': this.SubscriptionHandler,
|
||||
'./SubscriptionHelper': this.SubscriptionHelper,
|
||||
'./SubscriptionHelper': SubscriptionHelper,
|
||||
'./SubscriptionViewModelBuilder': this.SubscriptionViewModelBuilder,
|
||||
'./LimitationsManager': this.LimitationsManager,
|
||||
'../../infrastructure/GeoIpLookup': this.GeoIpLookup,
|
||||
|
||||
@@ -5,6 +5,7 @@ const { expect } = chai
|
||||
const {
|
||||
PaymentProviderSubscription,
|
||||
} = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
|
||||
const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
|
||||
|
||||
const MODULE_PATH =
|
||||
'../../../../app/src/Features/Subscription/SubscriptionHandler'
|
||||
@@ -149,6 +150,7 @@ describe('SubscriptionHandler', function () {
|
||||
'../../models/User': {
|
||||
User: this.User,
|
||||
},
|
||||
'./SubscriptionHelper': SubscriptionHelper,
|
||||
'./SubscriptionUpdater': this.SubscriptionUpdater,
|
||||
'./SubscriptionLocator': this.SubscriptionLocator,
|
||||
'./LimitationsManager': this.LimitationsManager,
|
||||
|
||||
@@ -267,4 +267,206 @@ describe('SubscriptionHelper', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('isPaidSubscription', function () {
|
||||
it('should return true for a subscription with a recurly subscription id', function () {
|
||||
const result = this.SubscriptionHelper.isPaidSubscription({
|
||||
recurlySubscription_id: 'some-id',
|
||||
})
|
||||
expect(result).to.be.true
|
||||
})
|
||||
|
||||
it('should return true for a subscription with a stripe subscription id', function () {
|
||||
const result = this.SubscriptionHelper.isPaidSubscription({
|
||||
paymentProvider: { subscriptionId: 'some-id' },
|
||||
})
|
||||
expect(result).to.be.true
|
||||
})
|
||||
|
||||
it('should return false for a free subscription', function () {
|
||||
const result = this.SubscriptionHelper.isPaidSubscription({})
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a missing subscription', function () {
|
||||
const result = this.SubscriptionHelper.isPaidSubscription()
|
||||
expect(result).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
describe('isIndividualActivePaidSubscription', function () {
|
||||
it('should return true for an active recurly subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
recurlyStatus: { state: 'active' },
|
||||
recurlySubscription_id: 'some-id',
|
||||
}
|
||||
)
|
||||
expect(result).to.be.true
|
||||
})
|
||||
|
||||
it('should return true for an active stripe subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
paymentProvider: { subscriptionId: 'sub_123', state: 'active' },
|
||||
}
|
||||
)
|
||||
expect(result).to.be.true
|
||||
})
|
||||
|
||||
it('should return false for a canceled recurly subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
recurlyStatus: { state: 'canceled' },
|
||||
recurlySubscription_id: 'some-id',
|
||||
}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a canceled stripe subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
paymentProvider: { state: 'canceled', subscriptionId: 'sub_123' },
|
||||
}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a group plan subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: true,
|
||||
recurlyStatus: { state: 'active' },
|
||||
recurlySubscription_id: 'some-id',
|
||||
}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a free subscription', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a subscription with an empty string for recurlySubscription_id', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
recurlySubscription_id: '',
|
||||
recurlyStatus: { state: 'active' },
|
||||
}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a subscription with an empty string for paymentProvider.subscriptionId', function () {
|
||||
const result = this.SubscriptionHelper.isIndividualActivePaidSubscription(
|
||||
{
|
||||
groupPlan: false,
|
||||
paymentProvider: { state: 'active', subscriptionId: '' },
|
||||
}
|
||||
)
|
||||
expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false for a missing subscription', function () {
|
||||
const result = this.SubscriptionHelper.isPaidSubscription()
|
||||
expect(result).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
describe('getPaymentProviderSubscriptionId', function () {
|
||||
it('should return the recurly subscription id if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaymentProviderSubscriptionId({
|
||||
recurlySubscription_id: 'some-id',
|
||||
})
|
||||
expect(result).to.equal('some-id')
|
||||
})
|
||||
|
||||
it('should return the payment provider subscription id if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaymentProviderSubscriptionId({
|
||||
paymentProvider: { subscriptionId: 'sub_123' },
|
||||
})
|
||||
expect(result).to.equal('sub_123')
|
||||
})
|
||||
|
||||
it('should return null if no subscription id exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaymentProviderSubscriptionId(
|
||||
{}
|
||||
)
|
||||
expect(result).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('getPaidSubscriptionState', function () {
|
||||
it('should return the recurly state if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaidSubscriptionState({
|
||||
recurlyStatus: { state: 'active' },
|
||||
})
|
||||
expect(result).to.equal('active')
|
||||
})
|
||||
|
||||
it('should return the payment provider state if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaidSubscriptionState({
|
||||
paymentProvider: { state: 'active' },
|
||||
})
|
||||
expect(result).to.equal('active')
|
||||
})
|
||||
|
||||
it('should return null if no state exists', function () {
|
||||
const result = this.SubscriptionHelper.getPaidSubscriptionState({})
|
||||
expect(result).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSubscriptionTrialStartedAt', function () {
|
||||
it('should return the recurly trial start date if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialStartedAt({
|
||||
recurlySubscription_id: 'some-id',
|
||||
recurlyStatus: { trialStartedAt: new Date('2023-01-01') },
|
||||
})
|
||||
expect(result).to.deep.equal(new Date('2023-01-01'))
|
||||
})
|
||||
|
||||
it('should return the payment provider trial start date if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialStartedAt({
|
||||
paymentProvider: { trialStartedAt: new Date('2023-01-01') },
|
||||
})
|
||||
expect(result).to.deep.equal(new Date('2023-01-01'))
|
||||
})
|
||||
|
||||
it('should return undefined if no trial start date exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialStartedAt({})
|
||||
expect(result).to.be.undefined
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSubscriptionTrialEndsAt', function () {
|
||||
it('should return the recurly trial end date if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialEndsAt({
|
||||
recurlySubscription_id: 'some-id',
|
||||
recurlyStatus: { trialEndsAt: new Date('2023-01-01') },
|
||||
})
|
||||
expect(result).to.deep.equal(new Date('2023-01-01'))
|
||||
})
|
||||
|
||||
it('should return the payment provider trial end date if it exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialEndsAt({
|
||||
paymentProvider: { trialEndsAt: new Date('2023-01-01') },
|
||||
})
|
||||
expect(result).to.deep.equal(new Date('2023-01-01'))
|
||||
})
|
||||
|
||||
it('should return undefined if no trial end date exists', function () {
|
||||
const result = this.SubscriptionHelper.getSubscriptionTrialEndsAt({})
|
||||
expect(result).to.be.undefined
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ const {
|
||||
PaymentProviderSubscriptionAddOn,
|
||||
PaymentProviderSubscriptionChange,
|
||||
} = require('../../../../app/src/Features/Subscription/PaymentProviderEntities')
|
||||
const SubscriptionHelper = require('../../../../app/src/Features/Subscription/SubscriptionHelper')
|
||||
|
||||
const modulePath =
|
||||
'../../../../app/src/Features/Subscription/SubscriptionViewModelBuilder'
|
||||
@@ -159,13 +160,14 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
'./SubscriptionUpdater': this.SubscriptionUpdater,
|
||||
'./PlansLocator': this.PlansLocator,
|
||||
'../../infrastructure/Modules': (this.Modules = {
|
||||
promises: { hooks: { fire: sinon.stub().resolves([]) } },
|
||||
hooks: {
|
||||
fire: sinon.stub().yields(null, []),
|
||||
},
|
||||
}),
|
||||
'./V1SubscriptionManager': {},
|
||||
'../Publishers/PublishersGetter': this.PublishersGetter,
|
||||
'./SubscriptionHelper': {},
|
||||
'./SubscriptionHelper': SubscriptionHelper,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -180,10 +182,10 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.returns(this.commonsPlan)
|
||||
})
|
||||
|
||||
describe('getBestSubscription', function () {
|
||||
describe('getUsersSubscriptionDetails', function () {
|
||||
it('should return a free plan when user has no subscription or affiliation', async function () {
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
assert.deepEqual(usersBestSubscription, { type: 'free' })
|
||||
@@ -195,8 +197,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.withArgs(this.user)
|
||||
.resolves(this.individualCustomSubscription)
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -213,8 +215,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.withArgs(this.user)
|
||||
.resolves(this.individualSubscription)
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -234,8 +236,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.withArgs(this.user)
|
||||
.resolves(this.individualSubscription)
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -255,8 +257,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.withArgs(this.user)
|
||||
.resolves(this.individualSubscription)
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -268,8 +270,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should update subscription if recurly data is missing', async function () {
|
||||
this.individualSubscriptionWithoutRecurly = {
|
||||
it('should update subscription if recurly payment state is missing', async function () {
|
||||
this.individualSubscriptionWithoutPaymentState = {
|
||||
planCode: this.planCode,
|
||||
plan: this.plan,
|
||||
recurlySubscription_id: this.recurlySubscription_id,
|
||||
@@ -280,37 +282,104 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
this.SubscriptionLocator.promises.getUsersSubscription
|
||||
.withArgs(this.user)
|
||||
.onCall(0)
|
||||
.resolves(this.individualSubscriptionWithoutRecurly)
|
||||
.resolves(this.individualSubscriptionWithoutPaymentState)
|
||||
.withArgs(this.user)
|
||||
.onCall(1)
|
||||
.resolves(this.individualSubscription)
|
||||
this.RecurlyWrapper.promises.getSubscription
|
||||
.withArgs(this.individualSubscription.recurlySubscription_id, {
|
||||
includeAccount: true,
|
||||
})
|
||||
.resolves(this.paymentRecord)
|
||||
const payment = {
|
||||
subscription: this.paymentRecord,
|
||||
account: new PaymentProviderAccount({}),
|
||||
coupons: [],
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
this.Modules.promises.hooks.fire
|
||||
.withArgs(
|
||||
'getPaymentFromRecordPromise',
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
)
|
||||
.resolves([payment])
|
||||
this.Modules.promises.hooks.fire
|
||||
.withArgs(
|
||||
'syncSubscription',
|
||||
payment,
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
)
|
||||
.resolves([])
|
||||
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
sinon.assert.calledWith(
|
||||
this.RecurlyWrapper.promises.getSubscription,
|
||||
this.individualSubscriptionWithoutRecurly.recurlySubscription_id,
|
||||
{ includeAccount: true }
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.SubscriptionUpdater.promises.updateSubscriptionFromRecurly,
|
||||
this.paymentRecord,
|
||||
this.individualSubscriptionWithoutRecurly
|
||||
)
|
||||
assert.deepEqual(usersBestSubscription, {
|
||||
type: 'individual',
|
||||
subscription: this.individualSubscription,
|
||||
plan: this.plan,
|
||||
remainingTrialDays: -1,
|
||||
})
|
||||
assert.isTrue(
|
||||
this.Modules.promises.hooks.fire.withArgs(
|
||||
'getPaymentFromRecordPromise',
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
).calledOnce
|
||||
)
|
||||
})
|
||||
|
||||
it('should update subscription if stripe payment state is missing', async function () {
|
||||
this.individualSubscriptionWithoutPaymentState = {
|
||||
planCode: this.planCode,
|
||||
plan: this.plan,
|
||||
paymentProvider: {
|
||||
subscriptionId: this.recurlySubscription_id,
|
||||
},
|
||||
}
|
||||
this.paymentRecord = {
|
||||
state: 'active',
|
||||
}
|
||||
this.SubscriptionLocator.promises.getUsersSubscription
|
||||
.withArgs(this.user)
|
||||
.onCall(0)
|
||||
.resolves(this.individualSubscriptionWithoutPaymentState)
|
||||
.withArgs(this.user)
|
||||
.onCall(1)
|
||||
.resolves(this.individualSubscription)
|
||||
const payment = {
|
||||
subscription: this.paymentRecord,
|
||||
account: new PaymentProviderAccount({}),
|
||||
coupons: [],
|
||||
}
|
||||
|
||||
this.Modules.promises.hooks.fire
|
||||
.withArgs(
|
||||
'getPaymentFromRecordPromise',
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
)
|
||||
.resolves([payment])
|
||||
this.Modules.promises.hooks.fire
|
||||
.withArgs(
|
||||
'syncSubscription',
|
||||
payment,
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
)
|
||||
.resolves([])
|
||||
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
assert.deepEqual(usersBestSubscription, {
|
||||
type: 'individual',
|
||||
subscription: this.individualSubscription,
|
||||
plan: this.plan,
|
||||
remainingTrialDays: -1,
|
||||
})
|
||||
assert.isTrue(
|
||||
this.Modules.promises.hooks.fire.withArgs(
|
||||
'getPaymentFromRecordPromise',
|
||||
this.individualSubscriptionWithoutPaymentState
|
||||
).calledOnce
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -318,8 +387,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
this.SubscriptionLocator.promises.getMemberSubscriptions
|
||||
.withArgs(this.user)
|
||||
.resolves([this.groupSubscription])
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
assert.deepEqual(usersBestSubscription, {
|
||||
@@ -336,8 +405,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.resolves([
|
||||
Object.assign({}, this.groupSubscription, { teamName: 'test team' }),
|
||||
])
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
assert.deepEqual(usersBestSubscription, {
|
||||
@@ -353,8 +422,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
.withArgs(this.user._id)
|
||||
.resolves([this.commonsSubscription])
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -385,8 +454,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
compileTimeout: 60,
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -410,8 +479,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
compileTimeout: 60,
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -440,8 +509,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
compileTimeout: 240,
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -469,8 +538,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
compileTimeout: 240,
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -499,8 +568,8 @@ describe('SubscriptionViewModelBuilder', function () {
|
||||
compileTimeout: 240,
|
||||
}
|
||||
|
||||
const usersBestSubscription =
|
||||
await this.SubscriptionViewModelBuilder.promises.getBestSubscription(
|
||||
const { bestSubscription: usersBestSubscription } =
|
||||
await this.SubscriptionViewModelBuilder.promises.getUsersSubscriptionDetails(
|
||||
this.user
|
||||
)
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ describe('TeamInvitesController', function () {
|
||||
},
|
||||
}
|
||||
|
||||
describe('hasIndividualRecurlySubscription', function () {
|
||||
describe('hasIndividualPaidSubscription', function () {
|
||||
it('is true for personal subscription', function (ctx) {
|
||||
return new Promise(resolve => {
|
||||
ctx.SubscriptionLocator.promises.getUsersSubscription.resolves({
|
||||
@@ -184,7 +184,7 @@ describe('TeamInvitesController', function () {
|
||||
})
|
||||
const res = {
|
||||
render: (template, data) => {
|
||||
expect(data.hasIndividualRecurlySubscription).to.be.true
|
||||
expect(data.hasIndividualPaidSubscription).to.be.true
|
||||
resolve()
|
||||
},
|
||||
}
|
||||
@@ -200,7 +200,7 @@ describe('TeamInvitesController', function () {
|
||||
})
|
||||
const res = {
|
||||
render: (template, data) => {
|
||||
expect(data.hasIndividualRecurlySubscription).to.be.false
|
||||
expect(data.hasIndividualPaidSubscription).to.be.false
|
||||
resolve()
|
||||
},
|
||||
}
|
||||
@@ -219,7 +219,7 @@ describe('TeamInvitesController', function () {
|
||||
})
|
||||
const res = {
|
||||
render: (template, data) => {
|
||||
expect(data.hasIndividualRecurlySubscription).to.be.false
|
||||
expect(data.hasIndividualPaidSubscription).to.be.false
|
||||
resolve()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { SubscriptionState } from '../../subscription/dashboard/subscription'
|
||||
import {
|
||||
SubscriptionState,
|
||||
PaymentProvider,
|
||||
} from '../../subscription/dashboard/subscription'
|
||||
|
||||
type SubscriptionBase = {
|
||||
featuresPageURL: string
|
||||
@@ -22,6 +25,7 @@ type PaidSubscriptionBase = {
|
||||
teamName?: string
|
||||
name: string
|
||||
recurlyStatus?: RecurlyStatus
|
||||
paymentProvider?: PaymentProvider
|
||||
}
|
||||
} & SubscriptionBase
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ export type Subscription = {
|
||||
membersLimit: number
|
||||
teamInvites: object[]
|
||||
planCode: string
|
||||
recurlySubscription_id: string
|
||||
plan: Plan
|
||||
pendingPlan?: PendingPaymentProviderPlan
|
||||
addOns?: AddOn[]
|
||||
|
||||
@@ -39,7 +39,7 @@ export type User = {
|
||||
isAdmin?: boolean
|
||||
email: string
|
||||
allowedFreeTrial?: boolean
|
||||
hasRecurlySubscription?: boolean
|
||||
hasPaidSubscription?: boolean
|
||||
first_name?: string
|
||||
last_name?: string
|
||||
alphaProgram?: boolean
|
||||
|
||||
Reference in New Issue
Block a user