// 杜康好客 · 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 REDEEM_PENDING_PHOTO } enum RedeemPendingStatus { PENDING COMPLETED REJECTED } /// Redeem channel: SCAN or PHONE enum RedeemChannel { SCAN PHONE } enum ResourceMediaType { IMAGE VIDEO FILE } enum ResourceStatus { ACTIVE DELETED } enum EventType { STORE_AUDIT ORDER_STATUS BENEFIT_LEDGER HQ_OPERATION PROMO_TOUCH TICKET_COLLAB } enum ActorType { USER STORE PARTNER HQ SYSTEM } enum TicketType { REFUND RESHIPMENT ALERT DAMAGE_RETURN RETURN_REFUND PACKAGE_DISPUTE } enum SupportTicketType { BUG SUGGESTION OTHER } enum SupportTicketStatus { PENDING_REVIEW REJECTED DEVELOPING TESTING PASSED PUBLISHED } enum SupportTicketPriority { LOW NORMAL HIGH URGENT } enum DevPlanTaskType { BUG REQUIREMENT OPTIMIZATION } enum DevPlanTaskStatus { TODO DEVELOPED RELEASED } enum DevPlanVersionStatus { PENDING IN_PROGRESS TESTING RELEASED } enum InvoiceTitleType { PERSONAL ENTERPRISE } enum InvoiceKind { NORMAL SPECIAL } enum InvoiceStatus { PENDING ISSUED REJECTED } enum AromaType { QINGXIANG JIANGXIANG NONGXIANG } enum ProductStatus { DRAFT ON_SALE OFF_SALE } enum DetailTemplateStatus { ACTIVE DISABLED } enum PromoCodeStatus { ACTIVE DISABLED } enum PromoCodeScene { ONLINE_LINK OFFLINE_PICKUP PARTNER_CHANNEL EVENT OTHER } enum PromoMetricEventType { SCAN ATTRIBUTION REGISTER ORDER } enum CityStatus { PENDING ACTIVE PAUSED } enum CityPartnerScopeType { CITY_WIDE DISTRICT } enum CityPartnerStatus { ACTIVE PAUSED } enum WarehouseManagerType { HQ PARTNER } enum WarehouseStatus { ACTIVE PAUSED } enum FulfillmentProviderType { API MANUAL } enum FulfillmentProviderStatus { ACTIVE DISABLED } enum WarehouseFulfillmentMode { API_AUTO MANUAL } enum PartnerStaffRole { PARTNER INTERNAL PROMOTER } enum StoreStaffRole { MANAGER CASHIER } enum AccountStatus { ACTIVE DISABLED } enum HqAdminRole { SUPER_ADMIN OPS FINANCE CUSTOMER_SERVICE } enum PartnerBillStatus { PENDING_REVIEW AWAITING_CONFIRM UNPAID PAID REJECTED } // 酒厂/门店对账单打款状态 enum FinancePayStatus { UNPAID PAID } // 物流承运商结算方式:前期充值,后期挂账月结 enum LogisticsSettlementMethod { PREPAID MONTHLY_CREDIT } enum LogisticsPrepaidLedgerType { RECHARGE DEDUCT ADJUST } enum StoreStatus { OPEN PAUSED CLOSED } enum StoreAuditStatus { PENDING APPROVED REJECTED } enum StorePackageChangeStatus { PENDING APPROVED REJECTED } enum StorePackageSubmitterType { PARTNER SHOP } enum StoreInfoChangeStatus { PENDING APPROVED REJECTED } enum StoreInfoChangeSubmitterType { PARTNER SHOP HQ_DIRECT_ADMIN } enum UserSourceType { ORGANIC PROMO_CODE SHARE_LINK FRIEND_REFERRAL OFFLINE_EVENT PARTNER_PROXY OTHER } enum OrderType { NORMAL RESHIPMENT PROXY } 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 ON_SITE_PICKUP } enum FreightPayType { FREE COD } enum DeliveryProvider { XFX LOGISTICS MANUAL } enum BenefitCouponStatus { ACTIVE USED_UP VOID } enum StorePayoutStatus { PENDING PAID } enum StoreWithdrawStatus { PENDING_REVIEW REJECTED PAID } enum ThirdPartyProvider { WECHAT_PAY WECHAT_REFUND WECHAT_AUTH WECHAT_MAP ALIYUN_OSS XFX SMS LOGISTICS } enum ThirdPartyLogStatus { PENDING SUCCESS FAILED } enum BenefitLedgerType { GRANT REDEEM REFUND_VOID ADJUST } // ─── COMMON ─────────────────────────────────────────── model SystemVersion { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt gitTag String? @map("git_tag") @db.VarChar(128) commitId String @map("commit_id") @db.VarChar(64) commitMessage String @map("commit_message") @db.VarChar(512) branch String? @db.VarChar(64) deployedBy String? @map("deployed_by") @db.VarChar(32) deployedAt DateTime @default(now()) @map("deployed_at") @db.DateTime(3) @@index([deployedAt]) @@map("system_version") } model SystemConfig { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt configKey String @unique @map("config_key") @db.VarChar(128) value String @db.Text createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) @@map("system_config") } /// 企业微信智能机器人(HQ 可创建多实例,长连接) model WecomBot { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt name String @db.VarChar(64) role String @db.VarChar(32) botId String @unique @map("bot_id") @db.VarChar(128) secret String @db.VarChar(256) avatarUrl String? @map("avatar_url") @db.VarChar(512) welcome String? @db.VarChar(1024) /// JSON 字符串数组,模块化权限 permissions String @db.Text /// 可执行 support_ticket.review 的企微 userid 白名单 reviewSuperAdminWecomUserIds String? @map("review_super_admin_wecom_user_ids") @db.Text aiEnabled Boolean @default(false) @map("ai_enabled") llmConfigId BigInt? @map("llm_config_id") @db.UnsignedBigInt knowledgeBaseId BigInt? @map("knowledge_base_id") @db.UnsignedBigInt enabled Boolean @default(true) sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) llmConfig LlmApiConfig? @relation(fields: [llmConfigId], references: [id], onDelete: SetNull) knowledgeBase KnowledgeBase? @relation(fields: [knowledgeBaseId], references: [id], onDelete: SetNull) wecomBotLogs LogWecomBot[] @@index([enabled, sortOrder]) @@index([llmConfigId]) @@index([knowledgeBaseId]) @@map("wecom_bot") } /// 企微机器人操作审计 model LogWecomBot { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt botId BigInt? @map("bot_id") @db.UnsignedBigInt botKey String? @map("bot_key") @db.VarChar(64) wecomUserId String @map("wecom_user_id") @db.VarChar(64) action String @db.VarChar(64) permission String? @db.VarChar(64) inputSummary String? @map("input_summary") @db.VarChar(512) success Boolean @default(true) errorMessage String? @map("error_message") @db.VarChar(512) latencyMs Int? @map("latency_ms") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) bot WecomBot? @relation(fields: [botId], references: [id], onDelete: SetNull) @@index([botId, createdAt]) @@index([wecomUserId, createdAt]) @@index([action, createdAt]) @@map("log_wecom_bot") } /// 企微群机器人 Webhook 消息推送(v3.4.11) model WecomMessagePush { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt name String @db.VarChar(64) avatarUrl String? @map("avatar_url") @db.VarChar(512) webhookUrl String @map("webhook_url") @db.VarChar(512) enabled Boolean @default(true) mentionWecomUserId String? @map("mention_wecom_user_id") @db.VarChar(64) /// JSON 字符串数组,推送条件 key pushConditions String @map("push_conditions") @db.Text sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) @@index([enabled, sortOrder]) @@map("wecom_message_push") } /// 企微业务通知文案模板(v3.5.3 · 按事件全站一份,HQ 可编辑) model WecomPushTemplate { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt eventKey String @unique @map("event_key") @db.VarChar(64) title String @db.VarChar(128) body String @db.Text handleLabel String @default("去处理") @map("handle_label") @db.VarChar(32) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) @@map("wecom_push_template") } /// HQ 语言模型 API 配置(非超管仅可见/可开关自己创建的) model LlmApiConfig { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt name String @db.VarChar(64) provider String @db.VarChar(32) baseUrl String @map("base_url") @db.VarChar(512) apiKey String @map("api_key") @db.VarChar(512) modelName String @map("model_name") @db.VarChar(128) temperature Decimal? @db.Decimal(3, 2) maxTokens Int? @map("max_tokens") systemPrompt String? @map("system_prompt") @db.Text enabled Boolean @default(true) createdByHqAccountId BigInt @map("created_by_hq_account_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) wecomBots WecomBot[] @@index([createdByHqAccountId, enabled]) @@map("llm_api_config") } /// HQ 知识库 model KnowledgeBase { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt name String @db.VarChar(128) description String? @db.VarChar(512) enabled Boolean @default(true) createdByHqAccountId BigInt @map("created_by_hq_account_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) documents KnowledgeDocument[] wecomBots WecomBot[] @@index([createdByHqAccountId, enabled]) @@map("knowledge_base") } model KnowledgeDocument { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt knowledgeBaseId BigInt @map("knowledge_base_id") @db.UnsignedBigInt title String @db.VarChar(256) fileName String? @map("file_name") @db.VarChar(256) fileUrl String? @map("file_url") @db.VarChar(1024) mimeType String? @map("mime_type") @db.VarChar(128) sizeBytes Int? @map("size_bytes") contentText String? @map("content_text") @db.LongText status String @default("READY") @db.VarChar(16) errorMessage String? @map("error_message") @db.VarChar(512) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) knowledgeBase KnowledgeBase @relation(fields: [knowledgeBaseId], references: [id], onDelete: Cascade) @@index([knowledgeBaseId]) @@map("knowledge_document") } model MockSmsCode { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt phone String @db.VarChar(20) scene String @db.VarChar(64) code String @db.VarChar(8) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([createdAt]) @@map("mock_sms_code") } 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") redeemPendingPhotos RedeemPendingRecord[] @relation("RedeemPendingPhoto") @@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") } /// HQ 内部技术支持工单(BUG / 建议 / 其他) model CommonSupportTicket { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt ticketNo String @unique @map("ticket_no") @db.VarChar(32) ticketType SupportTicketType @map("ticket_type") status SupportTicketStatus @default(PENDING_REVIEW) priority SupportTicketPriority @default(NORMAL) @map("priority") title String @db.VarChar(128) content String? @db.Text rejectReason String? @map("reject_reason") @db.VarChar(512) creatorId BigInt @map("creator_id") @db.UnsignedBigInt creatorName String @map("creator_name") @db.VarChar(64) reviewerId BigInt? @map("reviewer_id") @db.UnsignedBigInt reviewerName String? @map("reviewer_name") @db.VarChar(64) reviewedAt DateTime? @map("reviewed_at") @db.DateTime(3) remark String? @db.VarChar(512) attachmentUrls Json? @map("attachment_urls") releasedVersionNo String? @map("released_version_no") @db.VarChar(32) publishedAt DateTime? @map("published_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) completedAt DateTime? @map("completed_at") @db.DateTime(3) @@index([status, createdAt]) @@index([ticketType, status]) @@index([creatorId]) @@index([releasedVersionNo]) @@map("common_support_ticket") devPlanTasks DevPlanTask[] } /// 开发计划 · 任务 model DevPlanTask { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt taskNo String @unique @map("task_no") @db.VarChar(32) content String @db.Text type DevPlanTaskType status DevPlanTaskStatus @default(TODO) creatorHqAccountId BigInt @map("creator_hq_account_id") @db.UnsignedBigInt supportTicketId BigInt? @map("support_ticket_id") @db.UnsignedBigInt lastDispatchedAt DateTime? @map("last_dispatched_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) completedAt DateTime? @map("completed_at") @db.DateTime(3) supportTicket CommonSupportTicket? @relation(fields: [supportTicketId], references: [id], onDelete: SetNull) versionLinks DevPlanVersionTask[] @@index([status, createdAt]) @@index([supportTicketId]) @@map("dev_plan_task") } /// 开发计划 · 版本 model DevPlanVersion { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt versionNo String @unique @map("version_no") @db.VarChar(32) content String? @db.Text status DevPlanVersionStatus @default(PENDING) /// @deprecated 不再使用,保留兼容旧数据 assigneeHqAccountId BigInt? @map("assignee_hq_account_id") @db.UnsignedBigInt devStartedAt DateTime? @map("dev_started_at") @db.DateTime(3) devCompletedAt DateTime? @map("dev_completed_at") @db.DateTime(3) releasedAt DateTime? @map("released_at") @db.DateTime(3) durationMinutes Int? @map("duration_minutes") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) taskLinks DevPlanVersionTask[] @@index([status, createdAt]) @@map("dev_plan_version") } /// 开发计划 · 版本-任务多对多 model DevPlanVersionTask { versionId BigInt @map("version_id") @db.UnsignedBigInt taskId BigInt @map("task_id") @db.UnsignedBigInt sortOrder Int @default(0) @map("sort_order") version DevPlanVersion @relation(fields: [versionId], references: [id], onDelete: Cascade) task DevPlanTask @relation(fields: [taskId], references: [id], onDelete: Cascade) @@id([versionId, taskId]) @@index([taskId]) @@map("dev_plan_version_task") } /// 开发计划 · 全局设置(单例 id=1) model DevPlanSettings { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt reviewAssistantLlmConfigId BigInt? @map("review_assistant_llm_config_id") @db.UnsignedBigInt reviewAssistantKnowledgeBaseId BigInt? @map("review_assistant_knowledge_base_id") @db.UnsignedBigInt reviewAssistantPrompt String? @map("review_assistant_prompt") @db.Text updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) @@map("dev_plan_settings") } /// 开发计划 · 任务派发审计 model DevPlanTaskDispatch { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt taskIdsJson String @map("task_ids_json") @db.Text supplement String? @db.Text operatorHqAccountId BigInt @map("operator_hq_account_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([createdAt]) @@map("dev_plan_task_dispatch") } 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") allowOnSitePickup Boolean @default(false) @map("allow_on_site_pickup") /// 允许配送到址(同城线上购买) allowOnlinePurchase Boolean @default(true) @map("allow_online_purchase") /// 允许跨城配送(依附线上购买) allowCrossCityDelivery Boolean @default(true) @map("allow_cross_city_delivery") /// Online test: only listed phones can see/buy when enabled visibilityWhitelistEnabled Boolean @default(false) @map("visibility_whitelist_enabled") 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[] visibilityPhones CommonProductVisibilityPhone[] @@index([status, aromaType]) @@map("common_product_item") } /// Product visibility whitelist phones (match by bound phone) model CommonProductVisibilityPhone { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt productId BigInt @map("product_id") @db.UnsignedBigInt phone String @db.VarChar(20) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) product CommonProductItem @relation(fields: [productId], references: [id], onDelete: Cascade) @@unique([productId, phone]) @@index([phone]) @@map("common_product_visibility_phone") } /// 全局测试白名单手机号(测试账号 + 限测商品/门店可见) model CommonTestWhitelistPhone { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt phone String @unique @db.VarChar(20) note String? @db.VarChar(256) createdByHqId BigInt? @map("created_by_hq_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) createdBy HqAccount? @relation("TestWhitelistCreatedBy", fields: [createdByHqId], references: [id], onDelete: SetNull) @@index([createdAt]) @@map("common_test_whitelist_phone") } model CommonProductDetailTemplate { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt code String @unique @db.VarChar(32) name String @db.VarChar(64) description String? @db.VarChar(256) aromaType AromaType? @map("aroma_type") storyTitle String? @map("story_title") @db.VarChar(128) storyText String? @map("story_text") @db.Text features Json? detailImageUrls Json? @map("detail_image_urls") suggestedDetailImageCount Int @default(1) @map("suggested_detail_image_count") sortOrder Int @default(0) @map("sort_order") status DetailTemplateStatus @default(ACTIVE) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) @@index([status, sortOrder]) @@map("common_product_detail_template") } model CommonStoreCategory { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt code String @unique @db.VarChar(32) name String @db.VarChar(64) sort Int @default(0) parentId BigInt? @map("parent_id") @db.UnsignedBigInt status String @default("ACTIVE") @db.VarChar(16) parent CommonStoreCategory? @relation("StoreCategoryTree", fields: [parentId], references: [id], onDelete: Restrict) children CommonStoreCategory[] @relation("StoreCategoryTree") stores Store[] @@index([parentId, sort]) @@index([status]) @@map("common_store_category") } model CommonPromoCode { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt code String @unique @db.VarChar(32) name String @db.VarChar(128) scene PromoCodeScene @default(ONLINE_LINK) qrcodeId String @unique @map("qrcode_id") @db.VarChar(64) status PromoCodeStatus @default(ACTIVE) ownerUserId BigInt? @map("owner_user_id") @db.UnsignedBigInt remark String? @db.VarChar(256) 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) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) ownerUser User? @relation("PromoOwnerUser", fields: [ownerUserId], references: [id], onDelete: SetNull) qrcodeResource CommonResource? @relation("PromoQrcode", fields: [qrcodeResourceId], references: [id], onDelete: SetNull) attributions UserPromoAttribution[] orders Order[] metricEvents LogPromoEvent[] @@index([ownerUserId]) @@index([scene, status]) @@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) localMinQty Int @default(2) @map("local_min_qty") crossMinQty Int @default(6) @map("cross_min_qty") maxPartnerCommissionRate Decimal @default(0.05) @map("max_partner_commission_rate") @db.Decimal(5, 4) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) warehouses CityWarehouse[] partnerAccounts PartnerAccount[] @relation("PartnerAccountCity") stores Store[] orders Order[] @@map("common_city") } model FulfillmentProvider { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt code String @unique @db.VarChar(32) name String @db.VarChar(128) type FulfillmentProviderType status FulfillmentProviderStatus @default(ACTIVE) configJson String? @map("config_json") @db.Text capabilitiesJson String? @map("capabilities_json") @db.Text bankAccountName String? @map("bank_account_name") @db.VarChar(64) bankName String? @map("bank_name") @db.VarChar(64) bankBranch String? @map("bank_branch") @db.VarChar(128) bankAccountNo String? @map("bank_account_no") @db.VarChar(64) settlementMethod LogisticsSettlementMethod @default(PREPAID) @map("settlement_method") pricingRulesJson String? @map("pricing_rules_json") @db.Text prepaidBalance Decimal @default(0) @map("prepaid_balance") @db.Decimal(12, 2) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) warehouses CityWarehouse[] deliveries OrderDelivery[] logisticsBills LogisticsBill[] prepaidLedgers LogisticsPrepaidLedger[] @@map("common_fulfillment_provider") } // 物流对账月账单(按承运商汇总) model LogisticsBill { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt billNo String @unique @map("bill_no") @db.VarChar(32) fulfillmentProviderId BigInt @map("fulfillment_provider_id") @db.UnsignedBigInt periodStart DateTime @map("period_start") @db.DateTime(3) periodEnd DateTime @map("period_end") @db.DateTime(3) orderCount Int @default(0) @map("order_count") bottleCount Int @default(0) @map("bottle_count") logisticsAmount Decimal @map("logistics_amount") @db.Decimal(12, 2) settlementMethod LogisticsSettlementMethod @map("settlement_method") pricingSnapshotJson String? @map("pricing_snapshot_json") @db.Text status FinancePayStatus @default(UNPAID) paidAt DateTime? @map("paid_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) fulfillmentProvider FulfillmentProvider @relation(fields: [fulfillmentProviderId], references: [id], onDelete: Restrict) items LogisticsBillItem[] prepaidLedgers LogisticsPrepaidLedger[] @@unique([fulfillmentProviderId, periodStart]) @@index([status, periodStart]) @@map("logistics_bill") } model LogisticsBillItem { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt logisticsBillId BigInt @map("logistics_bill_id") @db.UnsignedBigInt orderId BigInt @map("order_id") @db.UnsignedBigInt orderNo String @map("order_no") @db.VarChar(32) quantity Int logisticsAmount Decimal @map("logistics_amount") @db.Decimal(10, 2) shippedAt DateTime @map("shipped_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) logisticsBill LogisticsBill @relation(fields: [logisticsBillId], references: [id], onDelete: Cascade) @@unique([logisticsBillId, orderId]) @@index([logisticsBillId]) @@map("logistics_bill_item") } model LogisticsPrepaidLedger { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt fulfillmentProviderId BigInt @map("fulfillment_provider_id") @db.UnsignedBigInt type LogisticsPrepaidLedgerType amount Decimal @db.Decimal(12, 2) balanceAfter Decimal @map("balance_after") @db.Decimal(12, 2) logisticsBillId BigInt? @map("logistics_bill_id") @db.UnsignedBigInt remark String? @db.VarChar(256) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) fulfillmentProvider FulfillmentProvider @relation(fields: [fulfillmentProviderId], references: [id], onDelete: Restrict) logisticsBill LogisticsBill? @relation(fields: [logisticsBillId], references: [id], onDelete: SetNull) @@index([fulfillmentProviderId, createdAt]) @@map("logistics_prepaid_ledger") } model CityWarehouse { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt cityId BigInt @map("city_id") @db.UnsignedBigInt name String @db.VarChar(128) address String @db.VarChar(256) contactName String @map("contact_name") @db.VarChar(64) contactPhone String @map("contact_phone") @db.VarChar(20) managerType WarehouseManagerType @map("manager_type") partnerAccountId BigInt? @map("partner_account_id") @db.UnsignedBigInt status WarehouseStatus @default(ACTIVE) fulfillmentMode WarehouseFulfillmentMode @default(MANUAL) @map("fulfillment_mode") fulfillmentProviderId BigInt? @map("fulfillment_provider_id") @db.UnsignedBigInt manualCarrierLabel String? @map("manual_carrier_label") @db.VarChar(64) manualQueryUrlTemplate String? @map("manual_query_url_template") @db.VarChar(512) lng Decimal? @db.Decimal(10, 7) lat Decimal? @db.Decimal(10, 7) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) city CommonCity @relation(fields: [cityId], references: [id], onDelete: Cascade) partnerAccount PartnerAccount? @relation("WarehouseManager", fields: [partnerAccountId], references: [id], onDelete: SetNull) managedBy PartnerAccount? @relation("ManagedWarehouse") fulfillmentProvider FulfillmentProvider? @relation(fields: [fulfillmentProviderId], references: [id], onDelete: SetNull) fulfilledOrders Order[] @relation("OrderFulfillmentWarehouse") @@index([cityId]) @@index([partnerAccountId]) @@index([fulfillmentProviderId]) @@map("common_city_warehouse") } // ─── PARTNER ────────────────────────────────────────── model PartnerAccount { id BigInt @id @default(autoincrement()) @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) wxNickname String? @map("wx_nickname") @db.VarChar(64) wxAvatarUrl String? @map("wx_avatar_url") @db.VarChar(512) isPrimary Int @default(0) @map("is_primary") @db.TinyInt parentAccountId BigInt? @map("parent_account_id") @db.UnsignedBigInt staffRole PartnerStaffRole? @map("staff_role") permissions Json? status AccountStatus @default(ACTIVE) lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3) cityId BigInt? @map("city_id") @db.UnsignedBigInt scopeType CityPartnerScopeType? @map("scope_type") districtCodes Json? @map("district_codes") orderCommissionRate Decimal? @default(0) @map("order_commission_rate") @db.Decimal(5, 4) redeemCommissionRate Decimal? @default(0.03) @map("redeem_commission_rate") @db.Decimal(5, 4) bindingStatus CityPartnerStatus? @default(ACTIVE) @map("binding_status") 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) weeklyStoreTarget Int? @default(20) @map("weekly_store_target") managedWarehouseId BigInt? @unique @map("managed_warehouse_id") @db.UnsignedBigInt /// 测试合伙人账号 isTest Boolean @default(false) @map("is_test") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) city CommonCity? @relation("PartnerAccountCity", fields: [cityId], references: [id], onDelete: Restrict) managedWarehouse CityWarehouse? @relation("ManagedWarehouse", fields: [managedWarehouseId], references: [id], onDelete: SetNull) managedWarehouses CityWarehouse[] @relation("WarehouseManager") parent PartnerAccount? @relation("PartnerAccountHierarchy", fields: [parentAccountId], references: [id], onDelete: SetNull) children PartnerAccount[] @relation("PartnerAccountHierarchy") stores Store[] bills PartnerBill[] @@index([cityId, scopeType]) @@index([cityId, isPrimary]) @@index([parentAccountId]) @@index([wxOpenId]) @@index([contactPhone]) @@index([isTest]) @@map("partner_account") } model PartnerBill { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt billNo String @unique @map("bill_no") @db.VarChar(32) partnerAccountId BigInt @map("partner_account_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(PENDING_REVIEW) confirmedAt DateTime? @map("confirmed_at") @db.DateTime(3) sentAt DateTime? @map("sent_at") @db.DateTime(3) paidAt DateTime? @map("paid_at") @db.DateTime(3) rejectReason String? @map("reject_reason") @db.VarChar(500) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) partnerAccount PartnerAccount @relation(fields: [partnerAccountId], references: [id], onDelete: Restrict) @@index([partnerAccountId, status]) @@unique([partnerAccountId, periodStart]) @@map("partner_bill") } // ─── HQ ─────────────────────────────────────────────── model HqAccount { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt phone String @unique @db.VarChar(20) loginName String? @unique @map("login_name") @db.VarChar(64) passwordHash String? @map("password_hash") @db.VarChar(255) 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) permissions HqAccountPermission[] testWhitelistPhones CommonTestWhitelistPhone[] @relation("TestWhitelistCreatedBy") @@map("hq_account") } model HqRolePermission { adminRole HqAdminRole @map("admin_role") permissionKey String @map("permission_key") @db.VarChar(64) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@id([adminRole, permissionKey]) @@map("hq_role_permission") } model HqAccountPermission { hqAccountId BigInt @map("hq_account_id") @db.UnsignedBigInt permissionKey String @map("permission_key") @db.VarChar(64) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) hqAccount HqAccount @relation(fields: [hqAccountId], references: [id], onDelete: Cascade) @@id([hqAccountId, permissionKey]) @@map("hq_account_permission") } // ─── 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 /// 测试账号:命中全局测试白名单手机号 isTest Boolean @default(false) @map("is_test") 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? ownedPromoCodes CommonPromoCode[] @relation("PromoOwnerUser") orders Order[] invoices UserInvoice[] invoiceTitles UserInvoiceTitle[] benefitCoupons BenefitCoupon[] redeemRecords RedeemRecord[] redeemPendingRecords RedeemPendingRecord[] @@index([sourceType, sourceRefId]) @@index([referrerUserId]) @@index([mergedIntoUserId]) @@index([wxOpenId]) @@index([isTest]) @@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 partnerAccountId BigInt @map("partner_account_id") @db.UnsignedBigInt categoryId BigInt? @map("category_id") @db.UnsignedBigInt name String @db.VarChar(128) /// 门店主账号登录手机号(老板);与 StoreAccount.phone 对齐 phone String @db.VarChar(20) /// 对外联系电话(店长等);C 端拨号展示用;空则回退 phone contactPhone String? @map("contact_phone") @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 // 好客权益券使用规则(C 端门店详情展示) benefitUsageRule String? @map("benefit_usage_rule") @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) auditStatus StoreAuditStatus @default(APPROVED) @map("audit_status") rejectReason String? @map("reject_reason") @db.VarChar(512) auditedAt DateTime? @map("audited_at") @db.DateTime(3) openTime String? @map("open_time") @db.VarChar(8) closeTime String? @map("close_time") @db.VarChar(8) openTime2 String? @map("open_time_2") @db.VarChar(8) closeTime2 String? @map("close_time_2") @db.VarChar(8) settlementRate Decimal @default(0.60) @map("settlement_rate") @db.Decimal(5, 4) /// Online test: only listed phones can see store on C-end when enabled visibilityWhitelistEnabled Boolean @default(false) @map("visibility_whitelist_enabled") /// FIN-001:允许未出账手动提现的白名单门店 withdrawWhitelistEnabled Boolean @default(false) @map("withdraw_whitelist_enabled") /// 测试门店:不计结算 / HQ 可手动标记 isTest Boolean @default(false) @map("is_test") /// C 端 / 列表排序:数值越小越靠前 sortOrder Int @default(0) @map("sort_order") 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) partnerAccount PartnerAccount @relation(fields: [partnerAccountId], references: [id], onDelete: Restrict) category CommonStoreCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull) coverResource CommonResource? @relation("StoreCover", fields: [coverResourceId], references: [id], onDelete: SetNull) bindings StoreAccountStore[] redeemRecords RedeemRecord[] redeemPendingRecords RedeemPendingRecord[] ratings StoreRating[] payouts StorePayout[] storeBills StoreBill[] withdrawRequests StoreWithdrawRequest[] visibilityPhones StoreVisibilityPhone[] packages StorePackage[] packageChangeRequests StorePackageChangeRequest[] infoChangeRequests StoreInfoChangeRequest[] @@index([cityId, status]) @@index([partnerAccountId]) @@index([auditStatus, createdAt]) @@index([isTest]) @@index([sortOrder]) @@map("store_store") } /// Store visibility whitelist phones (match by bound user phone) model StoreVisibilityPhone { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt phone String @db.VarChar(20) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) store Store @relation(fields: [storeId], references: [id], onDelete: Cascade) @@unique([storeId, phone]) @@index([phone]) @@map("store_visibility_phone") } model StorePackage { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt name String @db.VarChar(128) price Decimal @db.Decimal(10, 2) dishes String @db.Text usableTime String? @map("usable_time") @db.VarChar(256) otherNotes String? @map("other_notes") @db.VarChar(512) imageUrl String? @map("image_url") @db.VarChar(512) /// 套餐多图 URL 列表(JSON string[]),最多 20 张;imageUrl 同步为首图 imageUrls Json? @map("image_urls") sortOrder Int @default(0) @map("sort_order") 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([storeId, sortOrder]) @@map("store_package") } model StorePackageChangeRequest { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt status StorePackageChangeStatus @default(PENDING) packagesJson Json @map("packages_json") submitterType StorePackageSubmitterType @map("submitter_type") submitterId BigInt @map("submitter_id") @db.UnsignedBigInt rejectReason String? @map("reject_reason") @db.VarChar(512) reviewedAt DateTime? @map("reviewed_at") @db.DateTime(3) reviewerId BigInt? @map("reviewer_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) store Store @relation(fields: [storeId], references: [id], onDelete: Cascade) @@index([storeId, status]) @@index([status, createdAt]) @@map("store_package_change_request") } /// 用户发票抬头(C 端"我的 → 发票管理") model UserInvoiceTitle { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt userId BigInt @map("user_id") @db.UnsignedBigInt titleType InvoiceTitleType @map("title_type") // PERSONAL | ENTERPRISE titleName String @map("title_name") @db.VarChar(128) taxNo String? @map("tax_no") @db.VarChar(32) email String? @db.VarChar(128) phone String? @db.VarChar(20) addressPhone String? @map("address_phone") @db.VarChar(256) bankAccount String? @map("bank_account") @db.VarChar(256) isDefault Boolean @default(false) @map("is_default") 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, isDefault]) @@map("user_invoice_title") } /// 门店基础信息变更请求(合伙人/门店端提交 → 总部审核) model StoreInfoChangeRequest { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt status StoreInfoChangeStatus @default(PENDING) /// 变更前 Store 全量快照 liveSnapshot Json @map("live_snapshot") /// 提交时希望变更的字段集合(白名单内) proposedSnapshot Json @map("proposed_snapshot") /// 变更的字段名数组 changedFields Json @map("changed_fields") submitterType StoreInfoChangeSubmitterType @map("submitter_type") submitterId BigInt @map("submitter_id") @db.UnsignedBigInt rejectReason String? @map("reject_reason") @db.VarChar(512) reviewedAt DateTime? @map("reviewed_at") @db.DateTime(3) reviewerId BigInt? @map("reviewer_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) store Store @relation(fields: [storeId], references: [id], onDelete: Cascade) @@index([storeId, status]) @@index([status, createdAt]) @@map("store_info_change_request") } model StoreAccount { id BigInt @id @default(autoincrement()) @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(1) @map("is_primary") @db.TinyInt parentAccountId BigInt? @map("parent_account_id") @db.UnsignedBigInt staffRole StoreStaffRole? @map("staff_role") permissions Json? 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) status AccountStatus @default(ACTIVE) lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3) /// 测试门店账号(商户) isTest Boolean @default(false) @map("is_test") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3) parentAccount StoreAccount? @relation("StoreAccountHierarchy", fields: [parentAccountId], references: [id], onDelete: Restrict) childAccounts StoreAccount[] @relation("StoreAccountHierarchy") bindings StoreAccountStore[] redeemPendingRecords RedeemPendingRecord[] withdrawRequests StoreWithdrawRequest[] @@index([parentAccountId]) @@index([isTest]) @@map("store_account") } model StoreAccountStore { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeAccountId BigInt @map("store_account_id") @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) storeAccount StoreAccount @relation(fields: [storeAccountId], references: [id], onDelete: Cascade) store Store @relation(fields: [storeId], references: [id], onDelete: Cascade) @@unique([storeAccountId, storeId]) @@index([storeId]) @@map("store_account_store") } // ─── 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) partnerAccountIdAtPay BigInt? @map("partner_account_id_at_pay") @db.UnsignedBigInt orderCommissionRateAtPay Decimal? @map("order_commission_rate_at_pay") @db.Decimal(5, 4) /// 代下单操作人(与佣金归属 partnerAccountIdAtPay 分离) proxyPartnerAccountId BigInt? @map("proxy_partner_account_id") @db.UnsignedBigInt proxyPartnerName String? @map("proxy_partner_name") @db.VarChar(64) proxyPartnerPhone String? @map("proxy_partner_phone") @db.VarChar(20) fulfillmentWarehouseId BigInt? @map("fulfillment_warehouse_id") @db.UnsignedBigInt /// 大单等场景拦截自动推承运商,待总部确认后推单或自配送 fulfillmentHold Boolean @default(false) @map("fulfillment_hold") fulfillmentHoldReason String? @map("fulfillment_hold_reason") @db.VarChar(64) remark String? @db.VarChar(512) /// 测试订单快照(下单时取自 User.isTest) isTest Boolean @default(false) @map("is_test") 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) fulfillmentWarehouse CityWarehouse? @relation("OrderFulfillmentWarehouse", fields: [fulfillmentWarehouseId], references: [id], onDelete: SetNull) 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? invoices UserInvoice[] @@index([userId, status]) @@index([cityId, createdAt]) @@index([productId]) @@index([barcode69]) @@index([payExternalNo]) @@index([ipCity]) @@index([gpsCity]) @@index([fulfillmentWarehouseId]) @@index([proxyPartnerAccountId]) @@index([isTest]) @@index([status, payExpireAt]) @@map("user_order") } model UserInvoice { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt invoiceNo String @unique @map("invoice_no") @db.VarChar(32) orderId BigInt @map("order_id") @db.UnsignedBigInt userId BigInt @map("user_id") @db.UnsignedBigInt titleType InvoiceTitleType @map("title_type") invoiceKind InvoiceKind @map("invoice_kind") titleName String @map("title_name") @db.VarChar(128) taxNo String? @map("tax_no") @db.VarChar(32) addressPhone String? @map("address_phone") @db.VarChar(256) bankAccount String? @map("bank_account") @db.VarChar(256) email String @db.VarChar(128) phone String @db.VarChar(20) status InvoiceStatus @default(PENDING) fileUrl String? @map("file_url") @db.VarChar(512) resourceId BigInt? @map("resource_id") @db.UnsignedBigInt issuedAt DateTime? @map("issued_at") @db.DateTime(3) operatorId BigInt? @map("operator_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) user User @relation(fields: [userId], references: [id], onDelete: Restrict) @@index([userId, status]) @@index([orderId]) @@index([status, createdAt]) @@map("user_invoice") } model OrderDelivery { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt orderId BigInt @unique @map("order_id") @db.UnsignedBigInt provider DeliveryProvider fulfillmentProviderId BigInt? @map("fulfillment_provider_id") @db.UnsignedBigInt providerOrderNo String? @map("provider_order_no") @db.VarChar(64) trackingNo String? @map("tracking_no") @db.VarChar(64) logisticsCompany String? @map("logistics_company") @db.VarChar(64) manualQueryUrl String? @map("manual_query_url") @db.VarChar(512) 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) fulfillmentProvider FulfillmentProvider? @relation(fields: [fulfillmentProviderId], references: [id], onDelete: SetNull) signPhotoResource CommonResource? @relation("DeliverySignPhoto", fields: [signPhotoResourceId], references: [id], onDelete: SetNull) @@index([fulfillmentProviderId]) @@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[] redeemAllocations RedeemRecordAllocation[] @@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) /// SCAN=qrcode, PHONE=phone channel RedeemChannel @default(SCAN) /// 测试核销快照(User.isTest || Store.isTest) isTest Boolean @default(false) @map("is_test") 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? pending RedeemPendingRecord? allocations RedeemRecordAllocation[] @@index([storeId, createdAt]) @@index([storeId, channel, createdAt]) @@index([isTest]) @@map("user_redeem_record") } // 核销单跨券 FIFO 分摊明细(含次券可追溯) model RedeemRecordAllocation { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt redeemRecordId BigInt @map("redeem_record_id") @db.UnsignedBigInt couponId BigInt @map("coupon_id") @db.UnsignedBigInt amount Decimal @db.Decimal(10, 2) sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) redeemRecord RedeemRecord @relation(fields: [redeemRecordId], references: [id], onDelete: Cascade) coupon BenefitCoupon @relation(fields: [couponId], references: [id], onDelete: Restrict) @@unique([redeemRecordId, couponId]) @@index([couponId]) @@index([redeemRecordId]) @@map("user_redeem_record_allocation") } model RedeemPendingRecord { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt pendingNo String @unique @map("pending_no") @db.VarChar(32) redeemToken String @map("redeem_token") @db.VarChar(64) storeId BigInt @map("store_id") @db.UnsignedBigInt storeAccountId BigInt @map("store_account_id") @db.UnsignedBigInt userId BigInt @map("user_id") @db.UnsignedBigInt amount Decimal @db.Decimal(10, 2) redeemType String @default("DIRECT") @map("redeem_type") @db.VarChar(16) allocationsJson Json @map("allocations_json") photoResourceId BigInt @map("photo_resource_id") @db.UnsignedBigInt failCount Int @default(5) @map("fail_count") status RedeemPendingStatus @default(PENDING) redeemRecordId BigInt? @unique @map("redeem_record_id") @db.UnsignedBigInt processedAt DateTime? @map("processed_at") @db.DateTime(3) processedByHqId BigInt? @map("processed_by_hq_id") @db.UnsignedBigInt rejectReason String? @map("reject_reason") @db.VarChar(256) remark String? @db.VarChar(256) 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: Restrict) storeAccount StoreAccount @relation(fields: [storeAccountId], references: [id], onDelete: Restrict) user User @relation(fields: [userId], references: [id], onDelete: Restrict) photoResource CommonResource @relation("RedeemPendingPhoto", fields: [photoResourceId], references: [id], onDelete: Restrict) redeemRecord RedeemRecord? @relation(fields: [redeemRecordId], references: [id], onDelete: SetNull) @@index([storeId, status, createdAt]) @@index([redeemToken]) @@index([status, createdAt]) @@map("user_redeem_pending") } 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 StoreBill { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt billNo String @unique @map("bill_no") @db.VarChar(32) storeId BigInt @map("store_id") @db.UnsignedBigInt billDate DateTime @map("bill_date") @db.DateTime(3) redeemCount Int @default(0) @map("redeem_count") redeemAmount Decimal @map("redeem_amount") @db.Decimal(10, 2) settlementRate Decimal @map("settlement_rate") @db.Decimal(5, 4) payoutAmount Decimal @map("payout_amount") @db.Decimal(10, 2) status FinancePayStatus @default(UNPAID) paidAt DateTime? @map("paid_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) store Store @relation(fields: [storeId], references: [id], onDelete: Restrict) payouts StorePayout[] @@unique([storeId, billDate]) @@index([status, billDate]) @@map("store_bill") } 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 storeBillId BigInt? @map("store_bill_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) storeBill StoreBill? @relation(fields: [storeBillId], references: [id], onDelete: SetNull) withdrawItem StoreWithdrawPayoutItem? @@index([storeId, status]) @@index([storeBillId]) @@map("store_payout") } model StoreWithdrawRequest { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt withdrawNo String @unique @map("withdraw_no") @db.VarChar(32) storeId BigInt @map("store_id") @db.UnsignedBigInt storeAccountId BigInt @map("store_account_id") @db.UnsignedBigInt amount Decimal @db.Decimal(10, 2) payoutCount Int @default(0) @map("payout_count") status StoreWithdrawStatus @default(PENDING_REVIEW) rejectReason String? @map("reject_reason") @db.VarChar(512) appliedAt DateTime @default(now()) @map("applied_at") @db.DateTime(3) reviewedAt DateTime? @map("reviewed_at") @db.DateTime(3) reviewedByHqId BigInt? @map("reviewed_by_hq_id") @db.UnsignedBigInt paidAt DateTime? @map("paid_at") @db.DateTime(3) paymentRef String? @map("payment_ref") @db.VarChar(128) 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: Restrict) storeAccount StoreAccount @relation(fields: [storeAccountId], references: [id], onDelete: Restrict) items StoreWithdrawPayoutItem[] @@index([storeId, status]) @@index([status, appliedAt]) @@map("store_withdraw_request") } model StoreWithdrawPayoutItem { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt withdrawRequestId BigInt @map("withdraw_request_id") @db.UnsignedBigInt storePayoutId BigInt @unique @map("store_payout_id") @db.UnsignedBigInt createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) withdrawRequest StoreWithdrawRequest @relation(fields: [withdrawRequestId], references: [id], onDelete: Cascade) storePayout StorePayout @relation(fields: [storePayoutId], references: [id], onDelete: Restrict) @@index([withdrawRequestId]) @@map("store_withdraw_payout_item") } model WineryBill { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt billNo String @unique @map("bill_no") @db.VarChar(32) billDate DateTime @map("bill_date") @db.DateTime(3) orderCount Int @default(0) @map("order_count") orderAmount Decimal @map("order_amount") @db.Decimal(10, 2) wineryRate Decimal @map("winery_rate") @db.Decimal(5, 4) wineryAmount Decimal @map("winery_amount") @db.Decimal(10, 2) status FinancePayStatus @default(UNPAID) paidAt DateTime? @map("paid_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) items WineryBillItem[] @@unique([billDate]) @@index([status, billDate]) @@map("winery_bill") } model WineryBillItem { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt wineryBillId BigInt @map("winery_bill_id") @db.UnsignedBigInt orderId BigInt @unique @map("order_id") @db.UnsignedBigInt orderNo String @map("order_no") @db.VarChar(32) deliveryType String @map("delivery_type") @db.VarChar(16) payAmount Decimal @map("pay_amount") @db.Decimal(10, 2) wineryAmount Decimal @map("winery_amount") @db.Decimal(10, 2) paidAt DateTime @map("paid_at") @db.DateTime(3) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) wineryBill WineryBill @relation(fields: [wineryBillId], references: [id], onDelete: Cascade) @@index([wineryBillId]) @@map("winery_bill_item") } // ─── 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 LogPromoEvent { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt promoCodeId BigInt @map("promo_code_id") @db.UnsignedBigInt eventType PromoMetricEventType @map("event_type") userId BigInt? @map("user_id") @db.UnsignedBigInt orderId BigInt? @map("order_id") @db.UnsignedBigInt sessionId String? @map("session_id") @db.VarChar(64) clientIp String? @map("client_ip") @db.VarChar(45) ipProvince String? @map("ip_province") @db.VarChar(32) ipCity String? @map("ip_city") @db.VarChar(32) createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) promoCode CommonPromoCode @relation(fields: [promoCodeId], references: [id], onDelete: Cascade) @@index([promoCodeId, eventType, createdAt]) @@index([createdAt]) @@map("log_promo_event") } 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") } model LogStoreAnalytics { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt storeAccountId BigInt? @map("store_account_id") @db.UnsignedBigInt storeId BigInt @map("store_id") @db.UnsignedBigInt eventName String @map("event_name") @db.VarChar(64) clientApp ClientApp? @map("client_app") refType String? @map("ref_type") @db.VarChar(32) refId BigInt? @map("ref_id") @db.UnsignedBigInt extraJson Json? @map("extra_json") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([storeId, createdAt]) @@index([storeAccountId, createdAt]) @@index([eventName, createdAt]) @@map("log_store_analytics") } model LogPartnerAnalytics { id BigInt @id @default(autoincrement()) @db.UnsignedBigInt partnerAccountId BigInt @map("partner_account_id") @db.UnsignedBigInt eventName String @map("event_name") @db.VarChar(64) clientApp ClientApp? @map("client_app") refType String? @map("ref_type") @db.VarChar(32) refId BigInt? @map("ref_id") @db.UnsignedBigInt extraJson Json? @map("extra_json") createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3) @@index([partnerAccountId, createdAt]) @@index([eventName, createdAt]) @@map("log_partner_analytics") }