feat: kimlik doğrulama, ödeme, kredi ve AI rapor sihirbazı ekle
- better-auth ile giriş/oturum yönetimi (src/lib/auth, giris sayfası) - iyzico ödeme entegrasyonu ve paket satın alma akışı - kredi sistemi ve uygulama veritabanı şeması (drizzle) - AI destekli rapor üretimi ve tercih sihirbazı - rapor yazdırma sayfası ve site header/kullanıcı menüsü Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
147
src/lib/appdb/schema.ts
Normal file
147
src/lib/appdb/schema.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import {
|
||||
sqliteTable,
|
||||
text,
|
||||
integer,
|
||||
uniqueIndex,
|
||||
index,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
|
||||
// ---- better-auth çekirdek tabloları (+ kredi alanları) ----
|
||||
|
||||
export const user = sqliteTable("user", {
|
||||
id: text("id").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
email: text("email").notNull().unique(),
|
||||
emailVerified: integer("email_verified", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
image: text("image"),
|
||||
creditBalance: integer("credit_balance").notNull().default(0),
|
||||
hasPaket: integer("has_paket", { mode: "boolean" }).notNull().default(false),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull(),
|
||||
});
|
||||
|
||||
export const session = sqliteTable("session", {
|
||||
id: text("id").primaryKey(),
|
||||
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||
token: text("token").notNull().unique(),
|
||||
ipAddress: text("ip_address"),
|
||||
userAgent: text("user_agent"),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull(),
|
||||
});
|
||||
|
||||
export const account = sqliteTable("account", {
|
||||
id: text("id").primaryKey(),
|
||||
accountId: text("account_id").notNull(),
|
||||
providerId: text("provider_id").notNull(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
accessToken: text("access_token"),
|
||||
refreshToken: text("refresh_token"),
|
||||
idToken: text("id_token"),
|
||||
accessTokenExpiresAt: integer("access_token_expires_at", {
|
||||
mode: "timestamp",
|
||||
}),
|
||||
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
|
||||
mode: "timestamp",
|
||||
}),
|
||||
scope: text("scope"),
|
||||
password: text("password"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull(),
|
||||
});
|
||||
|
||||
export const verification = sqliteTable("verification", {
|
||||
id: text("id").primaryKey(),
|
||||
identifier: text("identifier").notNull(),
|
||||
value: text("value").notNull(),
|
||||
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }),
|
||||
});
|
||||
|
||||
// ---- Ürün tabloları ----
|
||||
|
||||
export const orders = sqliteTable(
|
||||
"orders",
|
||||
{
|
||||
// cuid — iyzico conversationId olarak da kullanılır
|
||||
id: text("id").primaryKey(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id),
|
||||
product: text("product", { enum: ["paket", "topup"] }).notNull(),
|
||||
amountKurus: integer("amount_kurus").notNull(),
|
||||
credits: integer("credits").notNull(),
|
||||
status: text("status", { enum: ["pending", "paid", "failed"] })
|
||||
.notNull()
|
||||
.default("pending"),
|
||||
iyzicoToken: text("iyzico_token"),
|
||||
iyzicoPaymentId: text("iyzico_payment_id"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
paidAt: integer("paid_at", { mode: "timestamp" }),
|
||||
},
|
||||
(t) => [index("orders_user").on(t.userId)],
|
||||
);
|
||||
|
||||
export const creditLedger = sqliteTable(
|
||||
"credit_ledger",
|
||||
{
|
||||
id: text("id").primaryKey(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id),
|
||||
delta: integer("delta").notNull(),
|
||||
reason: text("reason", {
|
||||
enum: [
|
||||
"trial_grant",
|
||||
"purchase",
|
||||
"topup",
|
||||
"chat_message",
|
||||
"refund",
|
||||
"report_generate",
|
||||
"report_revision",
|
||||
],
|
||||
}).notNull(),
|
||||
refId: text("ref_id"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
},
|
||||
(t) => [
|
||||
uniqueIndex("ledger_reason_ref").on(t.reason, t.refId),
|
||||
index("ledger_user").on(t.userId),
|
||||
],
|
||||
);
|
||||
|
||||
export const chatMessages = sqliteTable(
|
||||
"chat_messages",
|
||||
{
|
||||
id: text("id").primaryKey(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id),
|
||||
role: text("role", { enum: ["user", "assistant"] }).notNull(),
|
||||
content: text("content").notNull(),
|
||||
clientMessageId: text("client_message_id").unique(),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
},
|
||||
(t) => [index("chat_user_created").on(t.userId, t.createdAt)],
|
||||
);
|
||||
|
||||
export const reports = sqliteTable("reports", {
|
||||
id: text("id").primaryKey(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.unique()
|
||||
.references(() => user.id),
|
||||
params: text("params", { mode: "json" }).notNull(),
|
||||
result: text("result", { mode: "json" }),
|
||||
revisionCount: integer("revision_count").notNull().default(0),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull(),
|
||||
});
|
||||
Reference in New Issue
Block a user