fix: init billing server for new users

This commit is contained in:
Harshith Mullapudi 2025-10-02 11:25:52 +05:30
parent 489fb5934a
commit 27762262d2
5 changed files with 100 additions and 15 deletions

View File

@ -2,6 +2,7 @@ import type { Prisma, User } from "@core/database";
import type { GoogleProfile } from "@coji/remix-auth-google";
import { prisma } from "~/db.server";
import { env } from "~/env.server";
import { ensureBillingInitialized } from "~/services/billing.server";
export type { User } from "@core/database";
type FindOrCreateMagicLink = {
@ -156,11 +157,6 @@ export async function findOrCreateGoogleUser({
authIdentifier,
email,
authenticationMethod: "GOOGLE",
UserUsage: {
create: {
availableCredits: 200,
},
},
},
});

View File

@ -1,5 +1,6 @@
import { type Workspace } from "@core/database";
import { prisma } from "~/db.server";
import { ensureBillingInitialized } from "~/services/billing.server";
import { sendEmail } from "~/services/email.server";
import { logger } from "~/services/logger.service";
import { SpaceService } from "~/services/space.server";
@ -40,6 +41,8 @@ export async function createWorkspace(
},
});
await ensureBillingInitialized(workspace.id);
await spaceService.createSpace({
name: "Profile",
description: profileRule,

View File

@ -6,11 +6,7 @@
*/
import { prisma } from "~/db.server";
import {
BILLING_CONFIG,
isBillingEnabled,
getPlanConfig,
} from "~/config/billing.server";
import { getPlanConfig } from "~/config/billing.server";
import type { PlanType, Subscription } from "@prisma/client";
export type CreditOperation = "addEpisode" | "search" | "chatMessage";
@ -114,7 +110,7 @@ export async function initializeSubscription(
/**
* Ensure workspace has billing records initialized
*/
async function ensureBillingInitialized(workspaceId: string) {
export async function ensureBillingInitialized(workspaceId: string) {
const workspace = await prisma.workspace.findUnique({
where: { id: workspaceId },
include: {

View File

@ -760,7 +760,7 @@ export async function hasCredits(
}
const userUsage = workspace.user.UserUsage;
const subscription = workspace.Subscription;
// const subscription = workspace.Subscription;
// If has available credits, return true
if (userUsage.availableCredits >= creditCost) {
@ -768,9 +768,9 @@ export async function hasCredits(
}
// If overage is enabled (Pro/Max), return true
if (subscription.enableUsageBilling) {
return true;
}
// if (subscription.enableUsageBilling) {
// return true;
// }
// Free plan with no credits left
return false;

View File

@ -574,8 +574,19 @@ model UserUsage {
updatedAt DateTime @updatedAt
deleted DateTime?
// Current period tracking
availableCredits Int @default(0)
usedCredits Int @default(0)
overageCredits Int @default(0) // Credits used beyond monthly allocation
// Last reset tracking
lastResetAt DateTime @default(now())
nextResetAt DateTime?
// Usage breakdown (optional analytics)
episodeCreditsUsed Int @default(0)
searchCreditsUsed Int @default(0)
chatCreditsUsed Int @default(0)
user User @relation(fields: [userId], references: [id])
userId String @unique
@ -614,6 +625,69 @@ model WebhookDeliveryLog {
createdAt DateTime @default(now())
}
model Subscription {
id String @id @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Stripe integration
stripeCustomerId String? @unique
stripeSubscriptionId String? @unique
stripePriceId String?
stripeCurrentPeriodEnd DateTime?
// Plan details
planType PlanType @default(FREE)
status SubscriptionStatus @default(ACTIVE)
// Monthly credits allocation
monthlyCredits Int @default(0)
// Billing cycle tracking
currentPeriodStart DateTime @default(now())
currentPeriodEnd DateTime
// Usage-based pricing (for PRO plan)
enableUsageBilling Boolean @default(false)
usagePricePerCredit Float? // Price per credit after monthly quota
// Overage tracking
overageCreditsUsed Int @default(0)
overageAmount Float @default(0)
// Relations
workspace Workspace @relation(fields: [workspaceId], references: [id])
workspaceId String @unique
BillingHistory BillingHistory[]
}
model BillingHistory {
id String @id @default(uuid())
createdAt DateTime @default(now())
// Billing period
periodStart DateTime
periodEnd DateTime
// Credits tracking
monthlyCreditsAllocated Int
creditsUsed Int
overageCreditsUsed Int
// Charges
subscriptionAmount Float
usageAmount Float // Overage charges
totalAmount Float
// Stripe integration
stripeInvoiceId String? @unique
stripePaymentStatus String?
// Relations
subscription Subscription @relation(fields: [subscriptionId], references: [id])
subscriptionId String
}
model Workspace {
id String @id @default(uuid())
createdAt DateTime @default(now())
@ -643,6 +717,21 @@ model Workspace {
RecallLog RecallLog[]
Space Space[]
MCPSession MCPSession[]
Subscription Subscription?
}
enum PlanType {
FREE
PRO
MAX
}
enum SubscriptionStatus {
ACTIVE
CANCELED
PAST_DUE
TRIALING
PAUSED
}
enum AuthenticationMethod {
@ -656,6 +745,7 @@ enum IngestionStatus {
COMPLETED
FAILED
CANCELLED
NO_CREDITS
}
enum UserType {