11import { db } from '@sim/db'
2- import { member , subscription , user , userStats } from '@sim/db/schema'
2+ import { member , subscription , user } from '@sim/db/schema'
33import { createLogger } from '@sim/logger'
44import { and , eq , inArray , sql } from 'drizzle-orm'
55import { getEffectiveBillingStatus , isOrganizationBillingBlocked } from '@/lib/billing/core/access'
66import { getHighestPrioritySubscription } from '@/lib/billing/core/plan'
7- import { getUserUsageLimit } from '@/lib/billing/core/usage'
87import {
98 getPlanTierCredits ,
10- isOrgPlan ,
119 isPro as isPlanPro ,
1210 isTeam as isPlanTeam ,
1311} from '@/lib/billing/plan-helpers'
@@ -16,12 +14,9 @@ import {
1614 checkProPlan ,
1715 checkTeamPlan ,
1816 ENTITLED_SUBSCRIPTION_STATUSES ,
19- getFreeTierLimit ,
20- getPerUserMinimumLimit ,
2117 hasUsableSubscriptionAccess ,
2218 USABLE_SUBSCRIPTION_STATUSES ,
2319} from '@/lib/billing/subscriptions/utils'
24- import type { UserSubscriptionState } from '@/lib/billing/types'
2520import {
2621 isAccessControlEnabled ,
2722 isBillingEnabled ,
@@ -485,145 +480,6 @@ export async function hasLiveSyncAccess(userId: string): Promise<boolean> {
485480 }
486481}
487482
488- /**
489- * Check if user has exceeded their cost limit based on current period usage
490- */
491- export async function hasExceededCostLimit ( userId : string ) : Promise < boolean > {
492- try {
493- if ( ! isBillingEnabled ) {
494- return false
495- }
496-
497- const subscription = await getHighestPrioritySubscription ( userId )
498-
499- let limit = getFreeTierLimit ( ) // Default free tier limit
500-
501- if ( subscription ) {
502- // Team/Enterprise: Use organization limit
503- if ( isOrgPlan ( subscription . plan ) ) {
504- limit = await getUserUsageLimit ( userId )
505- logger . info ( 'Using organization limit' , {
506- userId,
507- plan : subscription . plan ,
508- limit,
509- } )
510- } else {
511- // Pro/Free: Use individual limit
512- limit = getPerUserMinimumLimit ( subscription )
513- logger . info ( 'Using subscription-based limit' , {
514- userId,
515- plan : subscription . plan ,
516- limit,
517- } )
518- }
519- } else {
520- logger . info ( 'Using free tier limit' , { userId, limit } )
521- }
522-
523- // Get user stats to check current period usage
524- const statsRecords = await db . select ( ) . from ( userStats ) . where ( eq ( userStats . userId , userId ) )
525-
526- if ( statsRecords . length === 0 ) {
527- return false
528- }
529-
530- // Use current period cost instead of total cost for accurate billing period tracking
531- const currentCost = Number . parseFloat (
532- statsRecords [ 0 ] . currentPeriodCost ?. toString ( ) || statsRecords [ 0 ] . totalCost . toString ( )
533- )
534-
535- logger . info ( 'Checking cost limit' , { userId, currentCost, limit } )
536-
537- return currentCost >= limit
538- } catch ( error ) {
539- logger . error ( 'Error checking cost limit' , { error, userId } )
540- return false // Be conservative in case of error
541- }
542- }
543-
544- /**
545- * Check if sharing features are enabled for user
546- */
547- // Removed unused feature flag helpers: isSharingEnabled, isMultiplayerEnabled, isWorkspaceCollaborationEnabled
548-
549- /**
550- * Get comprehensive subscription state for a user
551- * Single function to get all subscription information
552- */
553- export async function getUserSubscriptionState ( userId : string ) : Promise < UserSubscriptionState > {
554- try {
555- // Get subscription and user stats in parallel to minimize DB calls
556- const [ subscription , statsRecords ] = await Promise . all ( [
557- getHighestPrioritySubscription ( userId ) ,
558- db . select ( ) . from ( userStats ) . where ( eq ( userStats . userId , userId ) ) . limit ( 1 ) ,
559- ] )
560-
561- // Determine plan types based on subscription (avoid redundant DB calls)
562- const isPro =
563- ! isBillingEnabled ||
564- ! ! (
565- subscription &&
566- ( checkProPlan ( subscription ) ||
567- checkTeamPlan ( subscription ) ||
568- checkEnterprisePlan ( subscription ) )
569- )
570- const isTeam =
571- ! isBillingEnabled ||
572- ! ! ( subscription && ( checkTeamPlan ( subscription ) || checkEnterprisePlan ( subscription ) ) )
573- const isEnterprise = ! isBillingEnabled || ! ! ( subscription && checkEnterprisePlan ( subscription ) )
574- const isFree = ! isPro && ! isTeam && ! isEnterprise
575-
576- // Determine plan name
577- let planName = 'free'
578- if ( isEnterprise ) planName = 'enterprise'
579- else if ( isTeam ) planName = 'team'
580- else if ( isPro ) planName = 'pro'
581-
582- // Check cost limit using already-fetched user stats
583- let hasExceededLimit = false
584- if ( isBillingEnabled && statsRecords . length > 0 ) {
585- let limit = getFreeTierLimit ( ) // Default free tier limit
586- if ( subscription ) {
587- // Team/Enterprise: Use organization limit
588- if ( isOrgPlan ( subscription . plan ) ) {
589- limit = await getUserUsageLimit ( userId )
590- } else {
591- // Pro/Free: Use individual limit
592- limit = getPerUserMinimumLimit ( subscription )
593- }
594- }
595-
596- const currentCost = Number . parseFloat (
597- statsRecords [ 0 ] . currentPeriodCost ?. toString ( ) || statsRecords [ 0 ] . totalCost . toString ( )
598- )
599- hasExceededLimit = currentCost >= limit
600- }
601-
602- return {
603- isPro,
604- isTeam,
605- isEnterprise,
606- isFree,
607- highestPrioritySubscription : subscription ,
608- hasExceededLimit,
609- planName,
610- }
611- } catch ( error ) {
612- logger . error ( 'Error getting user subscription state' , { error, userId } )
613-
614- // Return safe defaults in case of error
615- return {
616- isPro : false ,
617- isTeam : false ,
618- isEnterprise : false ,
619- isFree : true ,
620- highestPrioritySubscription : null ,
621- hasExceededLimit : false ,
622- planName : 'free' ,
623- }
624- }
625- }
626-
627483/**
628484 * Send welcome email for Pro and Team plan subscriptions
629485 */
0 commit comments