mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-18 07:38:27 +00:00
fix: init billing server for new users
This commit is contained in:
parent
489fb5934a
commit
27762262d2
@ -2,6 +2,7 @@ import type { Prisma, User } from "@core/database";
|
|||||||
import type { GoogleProfile } from "@coji/remix-auth-google";
|
import type { GoogleProfile } from "@coji/remix-auth-google";
|
||||||
import { prisma } from "~/db.server";
|
import { prisma } from "~/db.server";
|
||||||
import { env } from "~/env.server";
|
import { env } from "~/env.server";
|
||||||
|
import { ensureBillingInitialized } from "~/services/billing.server";
|
||||||
export type { User } from "@core/database";
|
export type { User } from "@core/database";
|
||||||
|
|
||||||
type FindOrCreateMagicLink = {
|
type FindOrCreateMagicLink = {
|
||||||
@ -156,11 +157,6 @@ export async function findOrCreateGoogleUser({
|
|||||||
authIdentifier,
|
authIdentifier,
|
||||||
email,
|
email,
|
||||||
authenticationMethod: "GOOGLE",
|
authenticationMethod: "GOOGLE",
|
||||||
UserUsage: {
|
|
||||||
create: {
|
|
||||||
availableCredits: 200,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { type Workspace } from "@core/database";
|
import { type Workspace } from "@core/database";
|
||||||
import { prisma } from "~/db.server";
|
import { prisma } from "~/db.server";
|
||||||
|
import { ensureBillingInitialized } from "~/services/billing.server";
|
||||||
import { sendEmail } from "~/services/email.server";
|
import { sendEmail } from "~/services/email.server";
|
||||||
import { logger } from "~/services/logger.service";
|
import { logger } from "~/services/logger.service";
|
||||||
import { SpaceService } from "~/services/space.server";
|
import { SpaceService } from "~/services/space.server";
|
||||||
@ -40,6 +41,8 @@ export async function createWorkspace(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await ensureBillingInitialized(workspace.id);
|
||||||
|
|
||||||
await spaceService.createSpace({
|
await spaceService.createSpace({
|
||||||
name: "Profile",
|
name: "Profile",
|
||||||
description: profileRule,
|
description: profileRule,
|
||||||
|
|||||||
@ -6,11 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { prisma } from "~/db.server";
|
import { prisma } from "~/db.server";
|
||||||
import {
|
import { getPlanConfig } from "~/config/billing.server";
|
||||||
BILLING_CONFIG,
|
|
||||||
isBillingEnabled,
|
|
||||||
getPlanConfig,
|
|
||||||
} from "~/config/billing.server";
|
|
||||||
import type { PlanType, Subscription } from "@prisma/client";
|
import type { PlanType, Subscription } from "@prisma/client";
|
||||||
|
|
||||||
export type CreditOperation = "addEpisode" | "search" | "chatMessage";
|
export type CreditOperation = "addEpisode" | "search" | "chatMessage";
|
||||||
@ -114,7 +110,7 @@ export async function initializeSubscription(
|
|||||||
/**
|
/**
|
||||||
* Ensure workspace has billing records initialized
|
* Ensure workspace has billing records initialized
|
||||||
*/
|
*/
|
||||||
async function ensureBillingInitialized(workspaceId: string) {
|
export async function ensureBillingInitialized(workspaceId: string) {
|
||||||
const workspace = await prisma.workspace.findUnique({
|
const workspace = await prisma.workspace.findUnique({
|
||||||
where: { id: workspaceId },
|
where: { id: workspaceId },
|
||||||
include: {
|
include: {
|
||||||
|
|||||||
@ -760,7 +760,7 @@ export async function hasCredits(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userUsage = workspace.user.UserUsage;
|
const userUsage = workspace.user.UserUsage;
|
||||||
const subscription = workspace.Subscription;
|
// const subscription = workspace.Subscription;
|
||||||
|
|
||||||
// If has available credits, return true
|
// If has available credits, return true
|
||||||
if (userUsage.availableCredits >= creditCost) {
|
if (userUsage.availableCredits >= creditCost) {
|
||||||
@ -768,9 +768,9 @@ export async function hasCredits(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If overage is enabled (Pro/Max), return true
|
// If overage is enabled (Pro/Max), return true
|
||||||
if (subscription.enableUsageBilling) {
|
// if (subscription.enableUsageBilling) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Free plan with no credits left
|
// Free plan with no credits left
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -574,8 +574,19 @@ model UserUsage {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deleted DateTime?
|
deleted DateTime?
|
||||||
|
|
||||||
|
// Current period tracking
|
||||||
availableCredits Int @default(0)
|
availableCredits Int @default(0)
|
||||||
usedCredits 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])
|
user User @relation(fields: [userId], references: [id])
|
||||||
userId String @unique
|
userId String @unique
|
||||||
@ -614,6 +625,69 @@ model WebhookDeliveryLog {
|
|||||||
createdAt DateTime @default(now())
|
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 {
|
model Workspace {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@ -643,6 +717,21 @@ model Workspace {
|
|||||||
RecallLog RecallLog[]
|
RecallLog RecallLog[]
|
||||||
Space Space[]
|
Space Space[]
|
||||||
MCPSession MCPSession[]
|
MCPSession MCPSession[]
|
||||||
|
Subscription Subscription?
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlanType {
|
||||||
|
FREE
|
||||||
|
PRO
|
||||||
|
MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SubscriptionStatus {
|
||||||
|
ACTIVE
|
||||||
|
CANCELED
|
||||||
|
PAST_DUE
|
||||||
|
TRIALING
|
||||||
|
PAUSED
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AuthenticationMethod {
|
enum AuthenticationMethod {
|
||||||
@ -656,6 +745,7 @@ enum IngestionStatus {
|
|||||||
COMPLETED
|
COMPLETED
|
||||||
FAILED
|
FAILED
|
||||||
CANCELLED
|
CANCELLED
|
||||||
|
NO_CREDITS
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserType {
|
enum UserType {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user