feat(admin): integrate Next.js admin panel (admin-next/) from feat/nextjs-admin
- Add admin-next/: full Next.js + Prisma + shadcn admin panel (45 API routes, 76 components) - docker-compose: tg_shop_admin service (port 3000, shared db/shop.db, prisma), bot talks to it via ADMIN_CHAT_URL=http://tg_shop_admin:3000/api/chat - tor-proxy now proxies onion admin to tg_shop_admin:3000 (new panel) - chatbotService: ADMIN_CHAT_URL default = http://tg_shop_admin:3000/api/chat (removed localhost:3100 anachronism) - .env admin secrets gitignored (admin-next/.env)
This commit is contained in:
236
admin-next/prisma/schema.prisma
Executable file
236
admin-next/prisma/schema.prisma
Executable file
@@ -0,0 +1,236 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// Telegram Shop Admin Panel — Full Schema
|
||||
// ────────────────────────────────────────────
|
||||
|
||||
model TgUser {
|
||||
id Int @id @default(autoincrement())
|
||||
telegramId String @unique @map("telegram_id")
|
||||
username String?
|
||||
country String?
|
||||
city String?
|
||||
district String?
|
||||
status Int @default(0) // 0=active 2=blocked
|
||||
totalBalance Float @default(0) @map("total_balance")
|
||||
bonusBalance Float @default(0) @map("bonus_balance")
|
||||
language String @default("en")
|
||||
languageSet Int @default(0) @map("language_set")
|
||||
notes String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
wallets CryptoWallet[]
|
||||
transactions Transaction[]
|
||||
purchases Purchase[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model CryptoWallet {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @map("user_id")
|
||||
walletType String @map("wallet_type") // BTC/LTC/ETH/USDT/USDC
|
||||
address String
|
||||
derivationPath String? @map("derivation_path")
|
||||
mnemonic String? // encrypted
|
||||
balance Float @default(0)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
user TgUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, walletType])
|
||||
@@map("crypto_wallets")
|
||||
}
|
||||
|
||||
model Transaction {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @map("user_id")
|
||||
walletType String @map("wallet_type")
|
||||
txHash String? @map("tx_hash")
|
||||
amount Float
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
user TgUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("transactions")
|
||||
}
|
||||
|
||||
model Location {
|
||||
id Int @id @default(autoincrement())
|
||||
country String
|
||||
city String
|
||||
district String @default("")
|
||||
isActive Int @default(1) @map("is_active")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
categories Category[]
|
||||
products Product[]
|
||||
|
||||
@@unique([country, city, district])
|
||||
@@map("locations")
|
||||
}
|
||||
|
||||
model Category {
|
||||
id Int @id @default(autoincrement())
|
||||
locationId Int @map("location_id")
|
||||
name String
|
||||
isActive Int @default(1) @map("is_active")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
location Location @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
||||
subcategories Subcategory[]
|
||||
products Product[]
|
||||
|
||||
@@unique([locationId, name])
|
||||
@@map("categories")
|
||||
}
|
||||
|
||||
model Subcategory {
|
||||
id Int @id @default(autoincrement())
|
||||
categoryId Int @map("category_id")
|
||||
name String
|
||||
isActive Int @default(1) @map("is_active")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
products Product[]
|
||||
|
||||
@@unique([categoryId, name])
|
||||
@@map("subcategories")
|
||||
}
|
||||
|
||||
model Product {
|
||||
id Int @id @default(autoincrement())
|
||||
locationId Int @map("location_id")
|
||||
categoryId Int @map("category_id")
|
||||
subcategoryId Int? @map("subcategory_id")
|
||||
name String
|
||||
description String?
|
||||
privateData String? @map("private_data")
|
||||
price Float
|
||||
quantityInStock Int @default(0) @map("quantity_in_stock")
|
||||
photoUrl String? @map("photo_url")
|
||||
hiddenPhotoUrl String? @map("hidden_photo_url")
|
||||
hiddenCoordinates String? @map("hidden_coordinates")
|
||||
hiddenDescription String? @map("hidden_description")
|
||||
isMono Int @default(0) @map("is_mono")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
location Location @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
subcategory Subcategory? @relation(fields: [subcategoryId], references: [id], onDelete: SetNull)
|
||||
purchases Purchase[]
|
||||
|
||||
@@map("products")
|
||||
}
|
||||
|
||||
model Purchase {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int @map("user_id")
|
||||
productId Int @map("product_id")
|
||||
walletType String? @map("wallet_type")
|
||||
txHash String? @map("tx_hash")
|
||||
quantity Int
|
||||
totalPrice Float @map("total_price")
|
||||
purchaseDate DateTime @default(now()) @map("purchase_date")
|
||||
status String @default("pending") // pending/completed/cancelled
|
||||
|
||||
user TgUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("purchases")
|
||||
}
|
||||
|
||||
model CommissionPayment {
|
||||
id Int @id @default(autoincrement())
|
||||
totalBalanceUsd Float @map("total_balance_usd")
|
||||
commissionRate Float @map("commission_rate")
|
||||
commissionAmountUsd Float @map("commission_amount_usd")
|
||||
paidAmountUsd Float @map("paid_amount_usd")
|
||||
walletCount Int @map("wallet_count")
|
||||
note String?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@map("commission_payments")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id Int @id @default(autoincrement())
|
||||
action String
|
||||
adminId String @map("admin_id")
|
||||
details String? // JSON string
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@map("audit_log")
|
||||
}
|
||||
|
||||
// ─── Chatbot & Leads Module ─────────────────────────────────
|
||||
|
||||
model ChatSession {
|
||||
id Int @id @default(autoincrement())
|
||||
sessionId String @unique @map("session_id")
|
||||
telegramId String? @map("telegram_id")
|
||||
leadId Int? @map("lead_id")
|
||||
messages String // JSON array of {role, content, timestamp}
|
||||
language String @default("en")
|
||||
device String?
|
||||
ip String?
|
||||
country String?
|
||||
customerProfile String? @map("customer_profile") // AI-generated profile JSON
|
||||
isActive Boolean @default(true) @map("is_active")
|
||||
operatorName String? @map("operator_name")
|
||||
autoReplyDisabled Boolean @default(false) @map("auto_reply_disabled")
|
||||
operatorConnectedAt DateTime? @map("operator_connected_at")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @map("updated_at")
|
||||
|
||||
lead Lead? @relation(fields: [leadId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@map("chat_sessions")
|
||||
}
|
||||
|
||||
model Lead {
|
||||
id Int @id @default(autoincrement())
|
||||
telegramId String? @unique @map("telegram_id")
|
||||
name String?
|
||||
phone String?
|
||||
email String?
|
||||
telegram String?
|
||||
status String @default("new") // new/contacted/qualified/lost/spam
|
||||
verification String @default("pending")
|
||||
notes String?
|
||||
customFields String @default("{}") @map("custom_fields")
|
||||
geoAddress String? @map("geo_address")
|
||||
aiLeadScore Float? @map("ai_lead_score")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @map("updated_at")
|
||||
|
||||
chatSessions ChatSession[]
|
||||
|
||||
@@map("leads")
|
||||
}
|
||||
|
||||
model SiteSetting {
|
||||
id Int @id @default(autoincrement())
|
||||
key String @unique
|
||||
value String
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @map("updated_at")
|
||||
|
||||
@@map("site_settings")
|
||||
}
|
||||
|
||||
model UserState {
|
||||
chatId String @id @map("chat_id")
|
||||
stateData String? @map("state_data")
|
||||
updatedAt Int @map("updated_at")
|
||||
|
||||
@@map("user_states")
|
||||
}
|
||||
Reference in New Issue
Block a user