[web] Update survey filters (#32189)

Updates the filters to support different subscription cohorts: group plans, professional plans, etc.

GitOrigin-RevId: cc9ef4a2460942baa449fe7e6b8c14a88ae2f92f
This commit is contained in:
Miguel Serrano
2026-03-18 09:06:25 +00:00
committed by Copybot
parent bfcd62883a
commit 34fc7e2c7a
3 changed files with 73 additions and 15 deletions
@@ -71,17 +71,19 @@ const SubscriptionLocator = {
return subscription?.admin_id return subscription?.admin_id
}, },
async hasGroupSubscription(userOrId) { async getAllAssociatedSubscriptions(userOrId, projection = {}) {
if (!Features.hasFeature('saas')) return false if (!Features.hasFeature('saas')) return []
const userId = SubscriptionLocator._getUserId(userOrId) const userId = SubscriptionLocator._getUserId(userOrId)
return await Subscription.exists({ return await Subscription.find(
groupPlan: true, {
$or: [ $or: [
{ member_ids: userId }, { admin_id: userId },
{ manager_ids: userId }, { manager_ids: userId },
{ admin_id: userId }, { member_ids: userId },
], ],
}).exec() },
projection
).exec()
}, },
async getSubscription(subscriptionId) { async getSubscription(subscriptionId) {
@@ -3,6 +3,7 @@ import crypto from 'node:crypto'
import SurveyCache from './SurveyCache.mjs' import SurveyCache from './SurveyCache.mjs'
import SubscriptionLocator from '../Subscription/SubscriptionLocator.mjs' import SubscriptionLocator from '../Subscription/SubscriptionLocator.mjs'
import PlansHelper from '../Subscription/PlansHelper.mjs'
import { callbackify } from '@overleaf/promise-utils' import { callbackify } from '@overleaf/promise-utils'
import UserGetter from '../User/UserGetter.mjs' import UserGetter from '../User/UserGetter.mjs'
@@ -19,10 +20,31 @@ import UserGetter from '../User/UserGetter.mjs'
async function getSurvey(userId) { async function getSurvey(userId) {
const survey = await SurveyCache.get(true) const survey = await SurveyCache.get(true)
if (survey) { if (survey) {
if (survey.options?.hasGroupSubscription) { const hasFilters =
const hasGroupSubscription = survey.options.hasFreeSubscription ||
await SubscriptionLocator.promises.hasGroupSubscription(userId) survey.options.hasIndividualStandardSubscription ||
if (!hasGroupSubscription) { survey.options.hasIndividualProfessionalSubscription ||
survey.options.hasGroupStandardSubscription ||
survey.options.hasGroupProfessionalSubscription
if (hasFilters) {
const subscriptions =
await SubscriptionLocator.promises.getAllAssociatedSubscriptions(
userId,
{
groupPlan: 1,
planCode: 1,
}
)
const isFreeSubscription = Boolean(!subscriptions?.length)
if (isFreeSubscription) {
if (!survey.options?.hasFreeSubscription) {
return
}
} else if (
!subscriptions.some(sub => _canDisplaySurvey(sub, survey.options))
) {
return return
} }
} }
@@ -64,6 +86,24 @@ async function getSurvey(userId) {
} }
} }
function _canDisplaySurvey(subscription, options = {}) {
const {
hasIndividualStandardSubscription,
hasIndividualProfessionalSubscription,
hasGroupStandardSubscription,
hasGroupProfessionalSubscription,
} = options
const isGroupPlan = subscription.groupPlan
const isProfessional = PlansHelper.isProfessionalPlan(subscription.planCode)
return (
(hasIndividualStandardSubscription && !isGroupPlan && !isProfessional) ||
(hasIndividualProfessionalSubscription && !isGroupPlan && isProfessional) ||
(hasGroupStandardSubscription && isGroupPlan && !isProfessional) ||
(hasGroupProfessionalSubscription && isGroupPlan && isProfessional)
)
}
function _userRolloutPercentile(userId, surveyName) { function _userRolloutPercentile(userId, surveyName) {
const hash = crypto const hash = crypto
.createHash('md5') .createHash('md5')
+17 -1
View File
@@ -36,7 +36,23 @@ export const SurveySchema = new Schema(
required: true, required: true,
}, },
options: { options: {
hasGroupSubscription: { hasFreeSubscription: {
type: Boolean,
default: false,
},
hasIndividualStandardSubscription: {
type: Boolean,
default: false,
},
hasIndividualProfessionalSubscription: {
type: Boolean,
default: false,
},
hasGroupStandardSubscription: {
type: Boolean,
default: false,
},
hasGroupProfessionalSubscription: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },