This commit is contained in:
2026-06-30 10:33:56 +08:00
commit 6e047dc0a5
607 changed files with 65966 additions and 0 deletions
+990
View File
@@ -0,0 +1,990 @@
// 杜康好客 · V2.1 数据模型
// 约束说明见 doc/数据库设计2-杜康好客.md
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
// ─── 枚举 ─────────────────────────────────────────────
enum ClientApp {
USER_MINI
USER_H5
PARTNER_MINI
PARTNER_H5
HQ_MINI
SHOP_H5
}
enum AccountStatus {
ACTIVE
DISABLED
}
enum HqAdminRole {
SUPER_ADMIN
OPS
FINANCE
CUSTOMER_SERVICE
}
enum PartnerStaffRole {
PARTNER
INTERNAL
PROMOTER
}
enum CityStatus {
PENDING
ACTIVE
PAUSED
}
enum AromaType {
QINGXIANG
JIANGXIANG
NONGXIANG
}
enum ProductStatus {
DRAFT
ON_SALE
OFF_SALE
}
enum StoreStatus {
OPEN
PAUSED
CLOSED
}
enum StoreAuditType {
NEW
UPDATE
}
enum StoreAuditStatus {
PENDING
APPROVED
REJECTED
}
enum DeliveryType {
LOCAL
CROSS_CITY
}
enum OrderType {
NORMAL
RESHIPMENT
}
enum OrderStatus {
PENDING_PAY
PENDING_SHIP
OUT_WAREHOUSE
SHIPPING
PENDING_RECEIVE
COMPLETED
CANCELLED
REFUNDING
REFUNDED
}
enum PaymentStatus {
PENDING
SUCCESS
FAILED
CLOSED
}
enum RefundStatus {
PENDING
APPROVED
REJECTED
PROCESSING
SUCCESS
FAILED
}
enum InterceptStatus {
PENDING
INTERCEPTING
SUCCESS
FAILED
REDELIVERING
COMPLETED
}
enum BenefitCouponStatus {
ACTIVE
USED_UP
VOID
}
enum BenefitLedgerType {
GRANT
REDEEM
REFUND_VOID
ADJUST
}
enum RedeemTokenStatus {
ACTIVE
USED
EXPIRED
CANCELLED
}
enum StorePayoutStatus {
PENDING
PAID
}
enum PartnerBillStatus {
DRAFT
PENDING_CONFIRM
CONFIRMED
PAID
REJECTED
}
enum WithdrawalStatus {
PENDING
APPROVED
REJECTED
PAID
}
enum PromoCodeStatus {
ACTIVE
DISABLED
}
enum AlertType {
ORDER_TIMEOUT
DELIVERY_DELAY
OTHER
}
enum AlertStatus {
OPEN
RESOLVED
}
enum AfterSaleType {
REFUND
RESHIPMENT
}
enum AfterSaleStatus {
PENDING
PROCESSING
COMPLETED
REJECTED
}
// ─── 微信应用配置 ─────────────────────────────────────
model WxAppConfig {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
clientApp ClientApp @unique @map("client_app")
appId String @map("app_id") @db.VarChar(64)
appSecret String @map("app_secret") @db.VarChar(128)
mchId String? @map("mch_id") @db.VarChar(32)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
@@map("wx_app_configs")
}
// ─── C端用户(phone 唯一主键,微信字段辅助)──────────
model User {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userNo String @unique @map("user_no") @db.VarChar(20)
phone String @unique @db.VarChar(20)
wxOpenId String? @map("wx_open_id") @db.VarChar(64)
wxUnionId String? @map("wx_union_id") @db.VarChar(64)
nickname String? @db.VarChar(64)
avatarUrl String? @map("avatar_url") @db.VarChar(512)
status Int @default(1) @db.TinyInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
addresses UserAddress[]
cityPref UserCityPreference?
orders Order[]
benefitCoupons BenefitCoupon[]
benefitLedgers BenefitLedger[]
redeemRecords RedeemRecord[]
promoTouch UserPromoAttribution?
eventLogs EventLog[]
@@index([wxOpenId])
@@index([wxUnionId])
@@map("users")
}
model UserAddress {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userId BigInt @map("user_id") @db.UnsignedBigInt
receiverName String @map("receiver_name") @db.VarChar(32)
phone String @db.VarChar(20)
province String @db.VarChar(32)
city String @db.VarChar(32)
district String @db.VarChar(32)
detail String @db.VarChar(256)
latitude Decimal? @db.Decimal(10, 7)
longitude Decimal? @db.Decimal(10, 7)
isDefault Int @default(0) @map("is_default") @db.TinyInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@map("user_addresses")
}
model UserCityPreference {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userId BigInt @unique @map("user_id") @db.UnsignedBigInt
selectedCityCode String? @map("selected_city_code") @db.VarChar(16)
selectedDistrict String? @map("selected_district") @db.VarChar(32)
locateCityCode String? @map("locate_city_code") @db.VarChar(16)
locateDistrict String? @map("locate_district") @db.VarChar(32)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("user_city_preferences")
}
// ─── B端账号(三表分离)──────────────────────────────
model StoreAccount {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
storeId BigInt @unique @map("store_id") @db.UnsignedBigInt
phone String @unique @db.VarChar(20)
name String @db.VarChar(64)
wxOpenId String? @map("wx_open_id") @db.VarChar(64)
wxUnionId String? @map("wx_union_id") @db.VarChar(64)
status AccountStatus @default(ACTIVE)
lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
@@index([wxOpenId])
@@map("store_accounts")
}
model PartnerAccount {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
phone String @unique @db.VarChar(20)
name String @db.VarChar(64)
wxOpenId String? @map("wx_open_id") @db.VarChar(64)
wxUnionId String? @map("wx_union_id") @db.VarChar(64)
isPrimary Int @default(0) @map("is_primary") @db.TinyInt
parentAccountId BigInt? @map("parent_account_id") @db.UnsignedBigInt
staffRole PartnerStaffRole? @map("staff_role")
status AccountStatus @default(ACTIVE)
lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
parent PartnerAccount? @relation("PartnerAccountHierarchy", fields: [parentAccountId], references: [id], onDelete: SetNull)
children PartnerAccount[] @relation("PartnerAccountHierarchy")
@@index([partnerId])
@@index([parentAccountId])
@@index([wxOpenId])
@@map("partner_accounts")
}
model HqAccount {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
phone String @unique @db.VarChar(20)
name String @db.VarChar(64)
adminRole HqAdminRole @default(OPS) @map("admin_role")
wxOpenId String? @map("wx_open_id") @db.VarChar(64)
wxUnionId String? @map("wx_union_id") @db.VarChar(64)
status AccountStatus @default(ACTIVE)
lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
storeAudits StoreAudit[]
operationLogs OperationLog[]
afterSales AfterSaleTicket[]
refunds Refund[]
@@index([wxOpenId])
@@index([adminRole])
@@map("hq_accounts")
}
// ─── 开城与合伙人 ─────────────────────────────────────
model Partner {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
companyName String @map("company_name") @db.VarChar(128)
address String @db.VarChar(256)
contactPhone String @map("contact_phone") @db.VarChar(20)
bankAccountName String? @map("bank_account_name") @db.VarChar(64)
bankAccountNo String? @map("bank_account_no") @db.VarChar(32)
bankBranch String? @map("bank_branch") @db.VarChar(128)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
cities City[]
accounts PartnerAccount[]
stores Store[]
bills PartnerBill[]
withdrawals PartnerWithdrawal[]
contracts PartnerContract[]
orderCommissions OrderCommission[]
@@index([contactPhone])
@@map("partners")
}
model City {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
code String @unique @db.VarChar(16)
name String @db.VarChar(64)
province String @db.VarChar(32)
status CityStatus @default(PENDING)
partnerId BigInt? @map("partner_id") @db.UnsignedBigInt
localMinQty Int @default(2) @map("local_min_qty")
crossMinQty Int @default(6) @map("cross_min_qty")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
partner Partner? @relation(fields: [partnerId], references: [id], onDelete: SetNull)
commissionRule CityCommissionRule?
stores Store[]
orders Order[]
@@index([partnerId])
@@index([status])
@@map("cities")
}
model CityCommissionRule {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
cityId BigInt @unique @map("city_id") @db.UnsignedBigInt
orderCommissionRate Decimal @map("order_commission_rate") @db.Decimal(5, 4)
redeemCommissionRate Decimal @map("redeem_commission_rate") @db.Decimal(5, 4)
partnerProfitRate Decimal @default(0.35) @map("partner_profit_rate") @db.Decimal(5, 4)
storeSettlementRate Decimal @default(0.60) @map("store_settlement_rate") @db.Decimal(5, 4)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
city City @relation(fields: [cityId], references: [id], onDelete: Cascade)
@@map("city_commission_rules")
}
model PartnerContract {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
contractNo String @map("contract_no") @db.VarChar(64)
fileUrl String @map("file_url") @db.VarChar(512)
signedAt DateTime @map("signed_at") @db.DateTime(3)
expireAt DateTime? @map("expire_at") @db.DateTime(3)
status String @default("ACTIVE") @db.VarChar(16)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
@@index([partnerId])
@@map("partner_contracts")
}
// ─── 商品 ─────────────────────────────────────────────
model Product {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
skuCode String @unique @map("sku_code") @db.VarChar(32)
name String @db.VarChar(128)
subtitle String? @db.VarChar(256)
aromaType AromaType @map("aroma_type")
spec String @db.VarChar(128)
price Decimal @db.Decimal(10, 2)
benefitAmount Decimal? @map("benefit_amount") @db.Decimal(10, 2)
status ProductStatus @default(DRAFT)
sortOrder Int @default(0) @map("sort_order")
mainImageUrl String @map("main_image_url") @db.VarChar(512)
detailContent Json? @map("detail_content")
carouselUrls Json? @map("carousel_urls")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
orderItems OrderItem[]
@@index([status, aromaType])
@@map("products")
}
// ─── 门店 ─────────────────────────────────────────────
model StoreCategory {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
code String @unique @db.VarChar(32)
name String @db.VarChar(64)
sort Int @default(0)
stores Store[]
@@map("store_categories")
}
model Store {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
cityId BigInt @map("city_id") @db.UnsignedBigInt
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
categoryId BigInt? @map("category_id") @db.UnsignedBigInt
name String @db.VarChar(128)
phone String @db.VarChar(20)
province String @db.VarChar(32)
cityName String @map("city") @db.VarChar(32)
district String @db.VarChar(32)
address String @db.VarChar(256)
latitude Decimal? @db.Decimal(10, 7)
longitude Decimal? @db.Decimal(10, 7)
intro String? @db.Text
coverUrl String? @map("cover_url") @db.VarChar(512)
avgPrice Decimal? @map("avg_price") @db.Decimal(10, 2)
rating Decimal? @db.Decimal(3, 2)
tags Json?
status StoreStatus @default(PAUSED)
openTime String? @map("open_time") @db.VarChar(8)
closeTime String? @map("close_time") @db.VarChar(8)
bankAccountName String? @map("bank_account_name") @db.VarChar(64)
bankAccountNo String? @map("bank_account_no") @db.VarChar(32)
bankBranch String? @map("bank_branch") @db.VarChar(128)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
cityRef City @relation(fields: [cityId], references: [id], onDelete: Restrict)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
category StoreCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
account StoreAccount?
media StoreMedia[]
audits StoreAudit[]
redeemRecords RedeemRecord[]
storePayouts StorePayout[]
ratings StoreRating[]
@@index([cityId, status])
@@index([partnerId])
@@map("stores")
}
model StoreMedia {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
storeId BigInt @map("store_id") @db.UnsignedBigInt
mediaType String @map("media_type") @db.VarChar(16)
url String @db.VarChar(512)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
@@index([storeId])
@@map("store_media")
}
model StoreAudit {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
storeId BigInt @map("store_id") @db.UnsignedBigInt
auditType StoreAuditType @map("audit_type")
status StoreAuditStatus @default(PENDING)
submitData Json? @map("submit_data")
rejectReason String? @map("reject_reason") @db.VarChar(512)
reviewerId BigInt? @map("reviewer_id") @db.UnsignedBigInt
submittedAt DateTime @default(now()) @map("submitted_at") @db.DateTime(3)
reviewedAt DateTime? @map("reviewed_at") @db.DateTime(3)
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
reviewer HqAccount? @relation(fields: [reviewerId], references: [id], onDelete: SetNull)
@@index([storeId, status])
@@index([reviewerId])
@@map("store_audits")
}
// ─── 推广码 ───────────────────────────────────────────
model PromoCode {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
code String @unique @db.VarChar(32)
name String @db.VarChar(128)
status PromoCodeStatus @default(ACTIVE)
wxQrcodeUrl String? @map("wx_qrcode_url") @db.VarChar(512)
scanCount Int @default(0) @map("scan_count")
orderCount Int @default(0) @map("order_count")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
orders Order[]
attributions UserPromoAttribution[]
@@map("promo_codes")
}
model UserPromoAttribution {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userId BigInt @unique @map("user_id") @db.UnsignedBigInt
promoCodeId BigInt @map("promo_code_id") @db.UnsignedBigInt
channelName String @map("channel_name") @db.VarChar(128)
firstTouchAt DateTime @map("first_touch_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
promoCode PromoCode @relation(fields: [promoCodeId], references: [id], onDelete: Restrict)
@@index([promoCodeId])
@@map("user_promo_attributions")
}
// ─── 订单与支付 ─────────────────────────────────────
model Order {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderNo String @unique @map("order_no") @db.VarChar(32)
orderType OrderType @default(NORMAL) @map("order_type")
userId BigInt @map("user_id") @db.UnsignedBigInt
cityId BigInt @map("city_id") @db.UnsignedBigInt
status OrderStatus @default(PENDING_PAY)
deliveryType DeliveryType @map("delivery_type")
originOrderId BigInt? @map("origin_order_id") @db.UnsignedBigInt
promoCodeId BigInt? @map("promo_code_id") @db.UnsignedBigInt
channelSource String? @map("channel_source") @db.VarChar(128)
receiverName String @map("receiver_name") @db.VarChar(32)
receiverPhone String @map("receiver_phone") @db.VarChar(20)
receiverAddress String @map("receiver_address") @db.Text
receiverProvince String @map("receiver_province") @db.VarChar(32)
receiverCity String @map("receiver_city") @db.VarChar(32)
receiverDistrict String @map("receiver_district") @db.VarChar(32)
productAmount Decimal @map("product_amount") @db.Decimal(10, 2)
freightAmount Decimal @default(0) @map("freight_amount") @db.Decimal(10, 2)
freightPayType String? @map("freight_pay_type") @db.VarChar(8)
payAmount Decimal @map("pay_amount") @db.Decimal(10, 2)
benefitAmount Decimal @default(0) @map("benefit_amount") @db.Decimal(10, 2)
paidAt DateTime? @map("paid_at") @db.DateTime(3)
shippedAt DateTime? @map("shipped_at") @db.DateTime(3)
completedAt DateTime? @map("completed_at") @db.DateTime(3)
cancelledAt DateTime? @map("cancelled_at") @db.DateTime(3)
payExpireAt DateTime? @map("pay_expire_at") @db.DateTime(3)
remark String? @db.VarChar(512)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
city City @relation(fields: [cityId], references: [id], onDelete: Restrict)
originOrder Order? @relation("ReshipmentOrder", fields: [originOrderId], references: [id], onDelete: SetNull)
reshipments Order[] @relation("ReshipmentOrder")
promoCode PromoCode? @relation(fields: [promoCodeId], references: [id], onDelete: SetNull)
items OrderItem[]
statusLogs OrderStatusLog[]
delivery OrderDelivery?
payment Payment?
refunds Refund[]
benefitCoupons BenefitCoupon[]
intercepts DeliveryIntercept[]
afterSales AfterSaleTicket[]
commissions OrderCommission[]
@@index([userId, status])
@@index([cityId, createdAt])
@@index([receiverPhone])
@@index([originOrderId])
@@map("orders")
}
model OrderItem {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @map("order_id") @db.UnsignedBigInt
productId BigInt @map("product_id") @db.UnsignedBigInt
productName String @map("product_name") @db.VarChar(128)
productSpec String @map("product_spec") @db.VarChar(128)
productImage String @map("product_image") @db.VarChar(512)
unitPrice Decimal @map("unit_price") @db.Decimal(10, 2)
quantity Int
subtotal Decimal @db.Decimal(10, 2)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Restrict)
@@index([orderId])
@@map("order_items")
}
model OrderStatusLog {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @map("order_id") @db.UnsignedBigInt
fromStatus String? @map("from_status") @db.VarChar(32)
toStatus String @map("to_status") @db.VarChar(32)
operator String? @db.VarChar(64)
remark String? @db.VarChar(256)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
@@index([orderId])
@@map("order_status_logs")
}
model OrderDelivery {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @unique @map("order_id") @db.UnsignedBigInt
provider String @db.VarChar(16)
providerOrderNo String? @map("provider_order_no") @db.VarChar(64)
trackingNo String? @map("tracking_no") @db.VarChar(64)
outWarehouseAt DateTime? @map("out_warehouse_at") @db.DateTime(3)
shippingAt DateTime? @map("shipping_at") @db.DateTime(3)
deliveredAt DateTime? @map("delivered_at") @db.DateTime(3)
rawPayload Json? @map("raw_payload")
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
@@map("order_deliveries")
}
model Payment {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @unique @map("order_id") @db.UnsignedBigInt
paymentNo String @unique @map("payment_no") @db.VarChar(32)
amount Decimal @db.Decimal(10, 2)
status PaymentStatus @default(PENDING)
wxTransactionId String? @unique @map("wx_transaction_id") @db.VarChar(64)
wxPrepayId String? @map("wx_prepay_id") @db.VarChar(64)
paidAt DateTime? @map("paid_at") @db.DateTime(3)
notifyPayload Json? @map("notify_payload")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
@@map("payments")
}
model Refund {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @map("order_id") @db.UnsignedBigInt
refundNo String @unique @map("refund_no") @db.VarChar(32)
amount Decimal @db.Decimal(10, 2)
reason String? @db.VarChar(512)
status RefundStatus @default(PENDING)
wxRefundId String? @map("wx_refund_id") @db.VarChar(64)
benefitAdjust Decimal? @map("benefit_adjust") @db.Decimal(10, 2)
operatorId BigInt? @map("operator_id") @db.UnsignedBigInt
approvedAt DateTime? @map("approved_at") @db.DateTime(3)
refundedAt DateTime? @map("refunded_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Restrict)
operator HqAccount? @relation(fields: [operatorId], references: [id], onDelete: SetNull)
@@index([orderId])
@@index([operatorId])
@@map("refunds")
}
model DeliveryIntercept {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt @map("order_id") @db.UnsignedBigInt
status InterceptStatus @default(PENDING)
oldAddress Json @map("old_address")
newAddress Json @map("new_address")
partnerId BigInt? @map("partner_id") @db.UnsignedBigInt
interceptAt DateTime? @map("intercept_at") @db.DateTime(3)
redeliveryOrderId BigInt? @map("redelivery_order_id") @db.UnsignedBigInt
remark String? @db.VarChar(512)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Restrict)
@@index([orderId, status])
@@map("delivery_intercepts")
}
// ─── 好客权益 ─────────────────────────────────────────
model BenefitCoupon {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
couponNo String @unique @map("coupon_no") @db.VarChar(32)
userId BigInt @map("user_id") @db.UnsignedBigInt
orderId BigInt @map("order_id") @db.UnsignedBigInt
totalAmount Decimal @map("total_amount") @db.Decimal(10, 2)
usedAmount Decimal @default(0) @map("used_amount") @db.Decimal(10, 2)
balance Decimal @db.Decimal(10, 2)
status BenefitCouponStatus @default(ACTIVE)
sourceProduct String @map("source_product") @db.VarChar(128)
version Int @default(0)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
order Order @relation(fields: [orderId], references: [id], onDelete: Restrict)
ledgers BenefitLedger[]
redeemRecords RedeemRecord[]
redeemTokens RedeemToken[]
@@index([userId, status])
@@index([orderId])
@@map("benefit_coupons")
}
model BenefitLedger {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userId BigInt @map("user_id") @db.UnsignedBigInt
couponId BigInt @map("coupon_id") @db.UnsignedBigInt
type BenefitLedgerType
amount Decimal @db.Decimal(10, 2)
balanceAfter Decimal @map("balance_after") @db.Decimal(10, 2)
refType String? @map("ref_type") @db.VarChar(32)
refId BigInt? @map("ref_id") @db.UnsignedBigInt
remark String? @db.VarChar(256)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
coupon BenefitCoupon @relation(fields: [couponId], references: [id], onDelete: Restrict)
@@index([userId, createdAt])
@@index([couponId])
@@map("benefit_ledgers")
}
// ─── 核销 ─────────────────────────────────────────────
model RedeemToken {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
token String @unique @db.VarChar(64)
userId BigInt @map("user_id") @db.UnsignedBigInt
couponId BigInt @map("coupon_id") @db.UnsignedBigInt
storeId BigInt? @map("store_id") @db.UnsignedBigInt
amount Decimal @db.Decimal(10, 2)
status RedeemTokenStatus @default(ACTIVE)
expireAt DateTime @map("expire_at") @db.DateTime(3)
usedAt DateTime? @map("used_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
coupon BenefitCoupon @relation(fields: [couponId], references: [id], onDelete: Restrict)
@@index([couponId])
@@map("redeem_tokens")
}
model RedeemRecord {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
redeemNo String @unique @map("redeem_no") @db.VarChar(32)
userId BigInt @map("user_id") @db.UnsignedBigInt
couponId BigInt @map("coupon_id") @db.UnsignedBigInt
storeId BigInt @map("store_id") @db.UnsignedBigInt
amount Decimal @db.Decimal(10, 2)
settleAmount Decimal @map("settle_amount") @db.Decimal(10, 2)
tokenId BigInt? @map("token_id") @db.UnsignedBigInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
coupon BenefitCoupon @relation(fields: [couponId], references: [id], onDelete: Restrict)
store Store @relation(fields: [storeId], references: [id], onDelete: Restrict)
payout StorePayout?
rating StoreRating?
commissions OrderCommission[]
@@index([storeId, createdAt])
@@index([userId])
@@map("redeem_records")
}
model StoreRating {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
redeemRecordId BigInt @unique @map("redeem_record_id") @db.UnsignedBigInt
storeId BigInt @map("store_id") @db.UnsignedBigInt
serviceScore Int @map("service_score") @db.TinyInt
envScore Int @map("env_score") @db.TinyInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
redeemRecord RedeemRecord @relation(fields: [redeemRecordId], references: [id], onDelete: Cascade)
store Store @relation(fields: [storeId], references: [id], onDelete: Restrict)
@@map("store_ratings")
}
// ─── 结算 ─────────────────────────────────────────────
model StorePayout {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
redeemRecordId BigInt @unique @map("redeem_record_id") @db.UnsignedBigInt
storeId BigInt @map("store_id") @db.UnsignedBigInt
redeemAmount Decimal @map("redeem_amount") @db.Decimal(10, 2)
payoutAmount Decimal @map("payout_amount") @db.Decimal(10, 2)
settlementRate Decimal @map("settlement_rate") @db.Decimal(5, 4)
status StorePayoutStatus @default(PENDING)
expectedPayAt DateTime @map("expected_pay_at") @db.DateTime(3)
paidAt DateTime? @map("paid_at") @db.DateTime(3)
batchNo String? @map("batch_no") @db.VarChar(32)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
redeemRecord RedeemRecord @relation(fields: [redeemRecordId], references: [id], onDelete: Restrict)
store Store @relation(fields: [storeId], references: [id], onDelete: Restrict)
@@index([storeId, status])
@@index([expectedPayAt])
@@map("store_payouts")
}
model OrderCommission {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
orderId BigInt? @map("order_id") @db.UnsignedBigInt
redeemId BigInt? @map("redeem_id") @db.UnsignedBigInt
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
commissionType String @map("commission_type") @db.VarChar(16)
baseAmount Decimal @map("base_amount") @db.Decimal(10, 2)
rate Decimal @db.Decimal(5, 4)
amount Decimal @db.Decimal(10, 2)
billId BigInt? @map("bill_id") @db.UnsignedBigInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
order Order? @relation(fields: [orderId], references: [id], onDelete: SetNull)
redeem RedeemRecord? @relation(fields: [redeemId], references: [id], onDelete: SetNull)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
bill PartnerBill? @relation(fields: [billId], references: [id], onDelete: SetNull)
@@index([partnerId])
@@index([billId])
@@map("order_commissions")
}
model PartnerBill {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
billNo String @unique @map("bill_no") @db.VarChar(32)
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
periodStart DateTime @map("period_start") @db.DateTime(3)
periodEnd DateTime @map("period_end") @db.DateTime(3)
orderCommission Decimal @map("order_commission") @db.Decimal(10, 2)
redeemCommission Decimal @map("redeem_commission") @db.Decimal(10, 2)
totalAmount Decimal @map("total_amount") @db.Decimal(10, 2)
status PartnerBillStatus @default(DRAFT)
confirmedAt DateTime? @map("confirmed_at") @db.DateTime(3)
paidAt DateTime? @map("paid_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
commissions OrderCommission[]
@@index([partnerId, status])
@@map("partner_bills")
}
model PartnerWithdrawal {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
partnerId BigInt @map("partner_id") @db.UnsignedBigInt
amount Decimal @db.Decimal(10, 2)
status WithdrawalStatus @default(PENDING)
remark String? @db.VarChar(256)
appliedAt DateTime @default(now()) @map("applied_at") @db.DateTime(3)
processedAt DateTime? @map("processed_at") @db.DateTime(3)
partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict)
@@index([partnerId])
@@map("partner_withdrawals")
}
// ─── 埋点 ─────────────────────────────────────────────
model EventLog {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
userId BigInt? @map("user_id") @db.UnsignedBigInt
eventName String @map("event_name") @db.VarChar(64)
params Json?
clientApp String? @map("client_app") @db.VarChar(32)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([eventName, createdAt])
@@index([userId])
@@map("event_logs")
}
// ─── 运营与售后 ─────────────────────────────────────
model AfterSaleTicket {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
ticketNo String @unique @map("ticket_no") @db.VarChar(32)
type AfterSaleType
status AfterSaleStatus @default(PENDING)
orderId BigInt @map("order_id") @db.UnsignedBigInt
reshipmentOrderId BigInt? @map("reshipment_order_id") @db.UnsignedBigInt
refundId BigInt? @map("refund_id") @db.UnsignedBigInt
reason String? @db.VarChar(512)
operatorId BigInt? @map("operator_id") @db.UnsignedBigInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
completedAt DateTime? @map("completed_at") @db.DateTime(3)
order Order @relation(fields: [orderId], references: [id], onDelete: Restrict)
operator HqAccount? @relation(fields: [operatorId], references: [id], onDelete: SetNull)
@@index([orderId])
@@index([status, type])
@@index([operatorId])
@@map("after_sale_tickets")
}
model Alert {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
alertType AlertType @map("alert_type")
status AlertStatus @default(OPEN)
refType String @map("ref_type") @db.VarChar(32)
refId BigInt @map("ref_id") @db.UnsignedBigInt
title String @db.VarChar(128)
content String @db.Text
resolvedAt DateTime? @map("resolved_at") @db.DateTime(3)
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
@@index([status, alertType])
@@map("alerts")
}
model OperationLog {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
hqAccountId BigInt @map("hq_account_id") @db.UnsignedBigInt
action String @db.VarChar(64)
refType String? @map("ref_type") @db.VarChar(32)
refId BigInt? @map("ref_id") @db.UnsignedBigInt
detail Json?
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
hqAccount HqAccount @relation(fields: [hqAccountId], references: [id], onDelete: Restrict)
@@index([hqAccountId, createdAt])
@@map("operation_logs")
}
model SmsLog {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
phone String @db.VarChar(20)
template String @db.VarChar(64)
content String @db.Text
status String @db.VarChar(16)
refType String? @map("ref_type") @db.VarChar(32)
refId BigInt? @map("ref_id") @db.UnsignedBigInt
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
@@index([phone, createdAt])
@@map("sms_logs")
}