@@ -784,11 +784,11 @@ const PricingVersion20240913 = {
784784 } ) ;
785785
786786 const { error : updateError } = await dbExecute (
787- `UPDATE organization
788- SET subscription_status = 'active',
789- stripe_subscription_id = $1,
790- stripe_subscription_item_id = $2,
791- tier = 'pro-20250202',
787+ `UPDATE organization
788+ SET subscription_status = 'active',
789+ stripe_subscription_id = $1,
790+ stripe_subscription_item_id = $2,
791+ tier = 'pro-20250202',
792792 stripe_metadata = $3
793793 WHERE id = $4` ,
794794 [ subscriptionId , subscriptionItemId , { addons : addons } , orgId || "" ] ,
@@ -820,6 +820,155 @@ const PricingVersion20240913 = {
820820 handleDelete : PricingVersionOld . handleDelete ,
821821} ;
822822
823+ // New pricing version (2025-12-10): $79/mo flat + $6/GB byte-based billing
824+ // Prompts now included, no per-seat, no per-request
825+ const ProVersion20251210 = {
826+ async handleCreate ( event : Stripe . Event ) {
827+ const subscription = event . data . object as Stripe . Subscription ;
828+ const subscriptionId = subscription . id ;
829+ const subscriptionItemId = subscription ?. items . data [ 0 ] . id ;
830+ const orgId = subscription . metadata ?. orgId ;
831+
832+ // New pricing: all features included in base plan
833+ const addons : Addons = {
834+ alerts : true ,
835+ prompts : true ,
836+ experiments : true ,
837+ evals : true ,
838+ } ;
839+
840+ const { error : updateError } = await dbExecute (
841+ `UPDATE organization
842+ SET subscription_status = 'active',
843+ stripe_subscription_id = $1,
844+ stripe_subscription_item_id = $2,
845+ tier = 'pro-20251210',
846+ stripe_metadata = $3
847+ WHERE id = $4` ,
848+ [ subscriptionId , subscriptionItemId , { addons : addons } , orgId || "" ] ,
849+ ) ;
850+
851+ if ( updateError ) {
852+ logger . error ( { error : updateError } , "Failed to update organization" ) ;
853+ }
854+
855+ // Invite members after org is updated
856+ await inviteOnboardingMembers ( orgId ) ;
857+
858+ // Send PostHog event
859+ await sendSubscriptionEvent ( "subscription_created" , subscription , {
860+ includeOrgData : true ,
861+ addons : JSON . stringify ( addons ) ,
862+ } ) ;
863+ } ,
864+
865+ handleUpdate : async ( _event : Stripe . Event ) => {
866+ const subscription = _event . data . object as Stripe . Subscription ;
867+ await sendSubscriptionCanceledEvent ( subscription ) ;
868+ } ,
869+ handleCheckoutSessionCompleted : async ( _event : Stripe . Event ) => {
870+ return ;
871+ } ,
872+ handleDelete : PricingVersionOld . handleDelete ,
873+ } ;
874+
875+ // New Team pricing version (2025-12-10): $799/mo flat + $6/GB byte-based billing
876+ const TeamVersion20251210 = {
877+ async handleCreate ( event : Stripe . Event ) {
878+ const subscription = event . data . object as Stripe . Subscription ;
879+ const subscriptionId = subscription . id ;
880+ const subscriptionItemId = subscription ?. items . data [ 0 ] . id ;
881+ const orgId = subscription . metadata ?. orgId ;
882+
883+ // Get the existing subscription from the organization
884+ type OrgSubscriptionData = {
885+ stripe_subscription_id : string | null ;
886+ name : string | null ;
887+ owner : string | null ;
888+ } ;
889+
890+ const { data : orgDataArray , error : orgDataError } =
891+ await dbExecute < OrgSubscriptionData > (
892+ `SELECT stripe_subscription_id, name, owner FROM organization WHERE id = $1 LIMIT 1` ,
893+ [ orgId || "" ] ,
894+ ) ;
895+
896+ if ( orgDataError ) {
897+ logger . error (
898+ { error : orgDataError } ,
899+ "Failed to fetch organization data" ,
900+ ) ;
901+ }
902+
903+ const orgData =
904+ orgDataArray && orgDataArray . length > 0 ? orgDataArray [ 0 ] : null ;
905+
906+ // Cancel old subscription if it exists AND it's different from the new one
907+ if (
908+ orgData &&
909+ orgData . stripe_subscription_id &&
910+ typeof orgData . stripe_subscription_id === "string" &&
911+ orgData . stripe_subscription_id !== subscriptionId // Don't cancel the subscription we just created!
912+ ) {
913+ try {
914+ logger . info ( "Cancelling old subscription" ) ;
915+ await stripe . subscriptions . cancel ( orgData . stripe_subscription_id , {
916+ invoice_now : true ,
917+ prorate : true ,
918+ } ) ;
919+ } catch ( _e ) {
920+ logger . error ( { error : _e } , "Error canceling old subscription" ) ;
921+ }
922+ }
923+
924+ // New pricing: all features included in base plan
925+ const addons : Addons = {
926+ alerts : true ,
927+ prompts : true ,
928+ experiments : true ,
929+ evals : true ,
930+ } ;
931+
932+ // Update to new subscription
933+ const { error : updateError } = await dbExecute (
934+ `UPDATE organization
935+ SET subscription_status = 'active',
936+ stripe_subscription_id = $1,
937+ stripe_subscription_item_id = $2,
938+ tier = 'team-20251210',
939+ stripe_metadata = $3
940+ WHERE id = $4` ,
941+ [ subscriptionId , subscriptionItemId , { addons } , orgId || "" ] ,
942+ ) ;
943+
944+ if ( updateError ) {
945+ logger . error ( { error : updateError } , "Failed to update organization" ) ;
946+ }
947+
948+ // Invite members after org is updated
949+ await inviteOnboardingMembers ( orgId ) ;
950+
951+ // Create Slack channel and invite team members
952+ if ( orgData ?. name ) {
953+ await createSlackChannelAndInviteMembers ( orgId , orgData . name ) ;
954+ }
955+
956+ // Send PostHog event
957+ await sendSubscriptionEvent ( "subscription_created" , subscription , {
958+ includeOrgData : true ,
959+ } ) ;
960+ } ,
961+
962+ handleUpdate : async ( _event : Stripe . Event ) => {
963+ const subscription = _event . data . object as Stripe . Subscription ;
964+ await sendSubscriptionCanceledEvent ( subscription ) ;
965+ } ,
966+ handleCheckoutSessionCompleted : async ( _event : Stripe . Event ) => {
967+ return ;
968+ } ,
969+ handleDelete : PricingVersionOld . handleDelete ,
970+ } ;
971+
823972const InvoiceHandlers = {
824973 async handleInvoiceCreated ( event : Stripe . Event ) {
825974 const invoice = event . data . object as Stripe . Invoice ;
@@ -999,13 +1148,20 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
9991148 | Stripe . Subscription
10001149 | Stripe . Checkout . Session ;
10011150
1002- const pricingFunctions =
1003- stripeObject . metadata ?. [ "tier" ] === "pro-20240913" ||
1004- stripeObject . metadata ?. [ "tier" ] === "pro-20250202"
1005- ? PricingVersion20240913
1006- : stripeObject . metadata ?. [ "tier" ] === "team-20250130"
1007- ? TeamVersion20250130
1008- : PricingVersionOld ;
1151+ const tier = stripeObject . metadata ?. [ "tier" ] ;
1152+ let pricingFunctions ;
1153+
1154+ if ( tier === "pro-20251210" ) {
1155+ pricingFunctions = ProVersion20251210 ;
1156+ } else if ( tier === "team-20251210" ) {
1157+ pricingFunctions = TeamVersion20251210 ;
1158+ } else if ( tier === "pro-20240913" || tier === "pro-20250202" ) {
1159+ pricingFunctions = PricingVersion20240913 ;
1160+ } else if ( tier === "team-20250130" ) {
1161+ pricingFunctions = TeamVersion20250130 ;
1162+ } else {
1163+ pricingFunctions = PricingVersionOld ;
1164+ }
10091165
10101166 if ( event . type === "test_helpers.test_clock.advancing" ) {
10111167 return res . status ( 200 ) . end ( ) ;
0 commit comments