// 杜康好客 · V3.1 数据模型(由 init_v3.sql 生成) // 激活方式:确认后替换 schema.prisma,执行 prisma migrate / db push + seed-v31 // 旧版备份:schema.legacy-v21.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } // ─── 枚举(与 init_v3.sql COMMENT 对齐)──────────────── enum ClientApp { USER_MINI USER_H5 PARTNER_MINI PARTNER_H5 HQ_MINI HQ_WEB SHOP_H5 } enum ResourceOwnerType { PRODUCT STORE PARTNER USER ORDER PROMO HQ } enum ResourceBizType { COVER ENV CONTRACT CAROUSEL DETAIL AVATAR QRCODE SIGN_PHOTO VIDEO } enum ResourceMediaType { IMAGE VIDEO FILE } enum ResourceStatus { ACTIVE DELETED } enum EventType { STORE_AUDIT ORDER_STATUS BENEFIT_LEDGER HQ_OPERATION PROMO_TOUCH } enum ActorType { USER STORE PARTNER HQ SYSTEM } enum TicketType { REFUND RESHIPMENT ALERT } enum AromaType { QINGXIANG JIANGXIANG NONGXIANG } enum ProductStatus { DRAFT ON_SALE OFF_SALE } enum PromoCodeStatus { ACTIVE DISABLED } enum CityStatus { PENDING ACTIVE PAUSED } enum PartnerStaffRole { PARTNER INTERNAL PROMOTER } enum AccountStatus { ACTIVE DISABLED } enum HqAdminRole { SUPER_ADMIN OPS FINANCE CUSTOMER_SERVICE } enum PartnerBillStatus { DRAFT CONFIRMED PAID } enum StoreStatus { OPEN PAUSED CLOSED } enum UserSourceType { ORGANIC PROMO_CODE SHARE_LINK FRIEND_REFERRAL OFFLINE_EVENT OTHER } enum OrderType { NORMAL RESHIPMENT } enum OrderStatus { PENDING_PAY PENDING_SHIP OUT_WAREHOUSE SHIPPING PENDING_RECEIVE COMPLETED CANCELLED REFUNDING REFUNDED } enum PayStatus { UNPAID PAYING PAID REFUNDING REFUNDED } enum DeliveryType { LOCAL CROSS_CITY } enum FreightPayType { FREE COD } enum DeliveryProvider { XFX LOGISTICS MANUAL } enum BenefitCouponStatus { ACTIVE USED_UP VOID } enum StorePayoutStatus { PENDING PAID } enum ThirdPartyProvider { WECHAT_PAY WECHAT_REFUND WECHAT_AUTH WECHAT_MAP XFX SMS LOGISTICS } enum ThirdPartyLogStatus { PENDING SUCCESS FAILED } enum BenefitLedgerType { GRANT REDEEM REFUND_VOID ADJUST } // ─── COMMON ─────────────────────────────────────────── model CommonWxAppConfig { 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("common_wx_app_config") } model CommonResource { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt ownerType ResourceOwnerType @map("owner_type") ownerId BigInt @map("owner_id") @db.UnsignedBigInt bizType ResourceBizType @map("biz_type") mediaType ResourceMediaType @default(IMAGE) @map("media_type") ossBucket String @map("oss_bucket") @db.VarChar(64) ossKey String @map("oss_key") @db.VarChar(256) url String @db.VarChar(512) fileName String? @map("file_name") @db.VarChar(128) fileSize BigInt? @map("file_size") @db.UnsignedBigInt mimeType String? @map("mime_type") @db.VarChar(64) sortOrder Int @default(0) @map("sort_order") status ResourceStatus @default(ACTIVE) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) productCovers CommonProductItem[] @relation("ProductCover") promoQrcodes CommonPromoCode[] @relation("PromoQrcode") userAvatars User[] @relation("UserAvatar") storeCovers Store[] @relation("StoreCover") orderImages Order[] @relation("OrderProductImage") deliveryPhotos OrderDelivery[] @relation("DeliverySignPhoto") @@index([ownerType, ownerId, bizType]) @@index([status]) @@map("common_resource") } model CommonEvent { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt eventType EventType @map("event_type") refType String @map("ref_type") @db.VarChar(32) refId BigInt @map("ref_id") @db.UnsignedBigInt actorType ActorType? @map("actor_type") actorId BigInt? @map("actor_id") @db.UnsignedBigInt status String? @db.VarChar(32) param1 String? @db.VarChar(128) param1Desc String? @map("param1_desc") @db.VarChar(64) param2 String? @db.VarChar(128) param2Desc String? @map("param2_desc") @db.VarChar(64) param3 String? @db.VarChar(128) param3Desc String? @map("param3_desc") @db.VarChar(64) amount1 Decimal? @db.Decimal(10, 2) amount2 Decimal? @db.Decimal(10, 2) remark String? @db.VarChar(512) extraJson Json? @map("extra_json") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([refType, refId, eventType]) @@index([eventType, createdAt]) @@index([actorType, actorId]) @@map("common_event") } model CommonTicket { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt ticketNo String @unique @map("ticket_no") @db.VarChar(32) ticketType TicketType @map("ticket_type") status String @default("PENDING") @db.VarChar(32) refType String @map("ref_type") @db.VarChar(32) refId BigInt @map("ref_id") @db.UnsignedBigInt operatorType ActorType? @map("operator_type") operatorId BigInt? @map("operator_id") @db.UnsignedBigInt param1 String? @db.VarChar(128) param1Desc String? @map("param1_desc") @db.VarChar(64) param2 String? @db.VarChar(128) param2Desc String? @map("param2_desc") @db.VarChar(64) param3 String? @db.VarChar(128) param3Desc String? @map("param3_desc") @db.VarChar(64) remark String? @db.VarChar(512) extraJson Json? @map("extra_json") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) completedAt DateTime? @map("completed_at") @db.DateTime(3) @@index([refType, refId]) @@index([ticketType, status]) @@map("common_ticket") } model CommonProductItem { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt skuCode String @unique @map("sku_code") @db.VarChar(32) barcode69 String @unique @map("barcode_69") @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") coverResourceId BigInt? @map("cover_resource_id") @db.UnsignedBigInt detailContent Json? @map("detail_content") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) coverResource CommonResource? @relation("ProductCover", fields: [coverResourceId], references: [id], onDelete: SetNull) orders Order[] @@index([status, aromaType]) @@map("common_product_item") } model CommonStoreCategory { 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("common_store_category") } model CommonPromoCode { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt code String @unique @db.VarChar(32) name String @db.VarChar(128) status PromoCodeStatus @default(ACTIVE) qrcodeResourceId BigInt? @map("qrcode_resource_id") @db.UnsignedBigInt scanCount Int @default(0) @map("scan_count") orderCount Int @default(0) @map("order_count") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) qrcodeResource CommonResource? @relation("PromoQrcode", fields: [qrcodeResourceId], references: [id], onDelete: SetNull) attributions UserPromoAttribution[] orders Order[] @@map("common_promo_code") } model CommonCity { 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 CommonCityCommissionRule? stores Store[] orders Order[] @@index([partnerId]) @@map("common_city") } model CommonCityCommissionRule { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt cityId BigInt @unique @map("city_id") @db.UnsignedBigInt orderCommissionRate Decimal @default(0) @map("order_commission_rate") @db.Decimal(5, 4) redeemCommissionRate Decimal @default(0) @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 CommonCity @relation(fields: [cityId], references: [id], onDelete: Cascade) @@map("common_city_commission_rule") } // ─── PARTNER ────────────────────────────────────────── 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) contractNo String? @map("contract_no") @db.VarChar(64) contractSignedAt DateTime? @map("contract_signed_at") @db.DateTime(3) contractExpireAt DateTime? @map("contract_expire_at") @db.DateTime(3) 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 CommonCity[] accounts PartnerAccount[] stores Store[] bills PartnerBill[] @@index([contactPhone]) @@map("partner_partner") } 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_account") } 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 @default(0) @map("order_commission") @db.Decimal(10, 2) redeemCommission Decimal @default(0) @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) @@index([partnerId, status]) @@map("partner_bill") } // ─── HQ ─────────────────────────────────────────────── 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) @@map("hq_account") } // ─── USER ───────────────────────────────────────────── model User { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt userNo String @unique @map("user_no") @db.VarChar(20) deviceKey String? @unique @map("device_key") @db.VarChar(36) phone String? @unique @db.VarChar(20) phoneVerifiedAt DateTime? @map("phone_verified_at") @db.DateTime(3) mergedIntoUserId BigInt? @map("merged_into_user_id") @db.UnsignedBigInt wxOpenId String? @map("wx_open_id") @db.VarChar(64) wxUnionId String? @map("wx_union_id") @db.VarChar(64) nickname String? @db.VarChar(64) avatarResourceId BigInt? @map("avatar_resource_id") @db.UnsignedBigInt status Int @default(1) @db.TinyInt sourceType UserSourceType @default(ORGANIC) @map("source_type") sourceRefId BigInt? @map("source_ref_id") @db.UnsignedBigInt sourceLabel String? @map("source_label") @db.VarChar(128) referrerUserId BigInt? @map("referrer_user_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) mergedInto User? @relation("UserMerge", fields: [mergedIntoUserId], references: [id], onDelete: SetNull) mergedFrom User[] @relation("UserMerge") referrer User? @relation("UserReferrer", fields: [referrerUserId], references: [id], onDelete: SetNull) referrers User[] @relation("UserReferrer") avatar CommonResource? @relation("UserAvatar", fields: [avatarResourceId], references: [id], onDelete: SetNull) addresses UserAddress[] cityPreference UserCityPreference? promoTouch UserPromoAttribution? orders Order[] benefitCoupons BenefitCoupon[] redeemRecords RedeemRecord[] @@index([sourceType, sourceRefId]) @@index([referrerUserId]) @@index([mergedIntoUserId]) @@index([wxOpenId]) @@map("user_user") } 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_address") } 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_preference") } 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 CommonPromoCode @relation(fields: [promoCodeId], references: [id], onDelete: Restrict) @@index([promoCodeId]) @@map("user_promo_attribution") } // ─── STORE ──────────────────────────────────────────── 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_name") @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 coverResourceId BigInt? @map("cover_resource_id") @db.UnsignedBigInt 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 CommonCity @relation(fields: [cityId], references: [id], onDelete: Restrict) partner Partner @relation(fields: [partnerId], references: [id], onDelete: Restrict) category CommonStoreCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull) coverResource CommonResource? @relation("StoreCover", fields: [coverResourceId], references: [id], onDelete: SetNull) account StoreAccount? redeemRecords RedeemRecord[] ratings StoreRating[] payouts StorePayout[] @@index([cityId, status]) @@index([partnerId]) @@map("store_store") } 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) @@map("store_account") } // ─── ORDER ──────────────────────────────────────────── 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) payStatus PayStatus @default(UNPAID) @map("pay_status") 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) productId BigInt @map("product_id") @db.UnsignedBigInt barcode69 String @map("barcode_69") @db.VarChar(32) productName String @map("product_name") @db.VarChar(128) productSpec String @map("product_spec") @db.VarChar(128) imageResourceId BigInt? @map("image_resource_id") @db.UnsignedBigInt quantity Int listUnitPrice Decimal @map("list_unit_price") @db.Decimal(10, 2) listAmount Decimal @map("list_amount") @db.Decimal(10, 2) discountAmount Decimal @default(0) @map("discount_amount") @db.Decimal(10, 2) productAmount Decimal @map("product_amount") @db.Decimal(10, 2) freightAmount Decimal @default(0) @map("freight_amount") @db.Decimal(10, 2) freightPayType FreightPayType? @map("freight_pay_type") payAmount Decimal @map("pay_amount") @db.Decimal(10, 2) benefitAmount Decimal @default(0) @map("benefit_amount") @db.Decimal(10, 2) 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) clientIp String? @map("client_ip") @db.VarChar(45) ipProvince String? @map("ip_province") @db.VarChar(32) ipCity String? @map("ip_city") @db.VarChar(32) ipDistrict String? @map("ip_district") @db.VarChar(32) gpsProvince String? @map("gps_province") @db.VarChar(32) gpsCity String? @map("gps_city") @db.VarChar(32) gpsDistrict String? @map("gps_district") @db.VarChar(32) gpsLatitude Decimal? @map("gps_latitude") @db.Decimal(10, 7) gpsLongitude Decimal? @map("gps_longitude") @db.Decimal(10, 7) gpsAddress String? @map("gps_address") @db.VarChar(256) payExternalNo String? @map("pay_external_no") @db.VarChar(64) 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 CommonCity @relation(fields: [cityId], references: [id], onDelete: Restrict) originOrder Order? @relation("OrderReshipment", fields: [originOrderId], references: [id], onDelete: SetNull) reshipments Order[] @relation("OrderReshipment") promoCode CommonPromoCode? @relation(fields: [promoCodeId], references: [id], onDelete: SetNull) product CommonProductItem @relation(fields: [productId], references: [id], onDelete: Restrict) imageResource CommonResource? @relation("OrderProductImage", fields: [imageResourceId], references: [id], onDelete: SetNull) delivery OrderDelivery? benefitCoupon BenefitCoupon? @@index([userId, status]) @@index([cityId, createdAt]) @@index([productId]) @@index([barcode69]) @@index([payExternalNo]) @@index([ipCity]) @@index([gpsCity]) @@map("user_order") } model OrderDelivery { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt orderId BigInt @unique @map("order_id") @db.UnsignedBigInt provider DeliveryProvider 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) signPhotoResourceId BigInt? @map("sign_photo_resource_id") @db.UnsignedBigInt updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) order Order @relation(fields: [orderId], references: [id], onDelete: Cascade) signPhotoResource CommonResource? @relation("DeliverySignPhoto", fields: [signPhotoResourceId], references: [id], onDelete: SetNull) @@map("user_order_delivery") } // ─── BENEFIT & REDEEM ───────────────────────────────── 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 @unique @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) redeemRecords RedeemRecord[] @@index([userId, status]) @@map("user_benefit_coupon") } 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) 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) rating StoreRating? payout StorePayout? @@index([storeId, createdAt]) @@map("user_redeem_record") } 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("user_store_rating") } 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]) @@map("store_payout") } // ─── LOG ────────────────────────────────────────────── model LogThirdParty { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt provider ThirdPartyProvider scene String @db.VarChar(64) refType String? @map("ref_type") @db.VarChar(32) refId BigInt? @map("ref_id") @db.UnsignedBigInt requestUrl String? @map("request_url") @db.VarChar(512) requestBody Json? @map("request_body") responseBody Json? @map("response_body") externalNo String? @map("external_no") @db.VarChar(128) amount Decimal? @db.Decimal(10, 2) status ThirdPartyLogStatus @default(PENDING) errorMessage String? @map("error_message") @db.VarChar(512) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([refType, refId]) @@index([provider, scene, createdAt]) @@index([externalNo]) @@map("log_third_party") } model LogUserAnalytics { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt userId BigInt? @map("user_id") @db.UnsignedBigInt sessionId String? @map("session_id") @db.VarChar(64) eventName String @map("event_name") @db.VarChar(64) clientApp ClientApp? @map("client_app") pagePath String? @map("page_path") @db.VarChar(128) refType String? @map("ref_type") @db.VarChar(32) refId BigInt? @map("ref_id") @db.UnsignedBigInt keyword String? @db.VarChar(128) sourceType String? @map("source_type") @db.VarChar(32) sourceRefId BigInt? @map("source_ref_id") @db.UnsignedBigInt extraJson Json? @map("extra_json") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([userId, createdAt]) @@index([eventName, createdAt]) @@index([sessionId]) @@index([refType, refId]) @@map("log_user_analytics") }