using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MassTransit;
using TakeoutSaaS.Domain.Analytics.Entities;
using TakeoutSaaS.Domain.Coupons.Entities;
using TakeoutSaaS.Domain.CustomerService.Entities;
using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Distribution.Entities;
using TakeoutSaaS.Domain.Common.Enums;
using TakeoutSaaS.Domain.Engagement.Entities;
using TakeoutSaaS.Domain.Finance.Entities;
using TakeoutSaaS.Domain.GroupBuying.Entities;
using TakeoutSaaS.Domain.Inventory.Entities;
using TakeoutSaaS.Domain.Membership.Entities;
using TakeoutSaaS.Domain.Merchants.Entities;
using TakeoutSaaS.Domain.Navigation.Entities;
using TakeoutSaaS.Domain.Ordering.Entities;
using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Payments.Entities;
using TakeoutSaaS.Domain.Products.Entities;
using TakeoutSaaS.Domain.Queues.Entities;
using TakeoutSaaS.Domain.Reservations.Entities;
using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Infrastructure.Common.Persistence;
using TakeoutSaaS.Shared.Abstractions.Ids;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
using TakeoutSaaS.Infrastructure.App.Persistence.Configurations;

namespace TakeoutSaaS.Infrastructure.App.Persistence;

/// <summary>
/// 业务主库 DbContext。
/// </summary>
public sealed class TakeoutAppDbContext(
    DbContextOptions<TakeoutAppDbContext> options,
    ITenantProvider tenantProvider,
    ICurrentUserAccessor? currentUserAccessor = null,
    IIdGenerator? idGenerator = null)
    : TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator)
{
    /// <summary>
    /// 租户聚合根。
    /// </summary>
    public DbSet<Tenant> Tenants => Set<Tenant>();
    /// <summary>
    /// 租户套餐。
    /// </summary>
    public DbSet<TenantPackage> TenantPackages => Set<TenantPackage>();
    /// <summary>
    /// 租户订阅。
    /// </summary>
    public DbSet<TenantSubscription> TenantSubscriptions => Set<TenantSubscription>();
    /// <summary>
    /// 租户订阅历史。
    /// </summary>
    public DbSet<TenantSubscriptionHistory> TenantSubscriptionHistories => Set<TenantSubscriptionHistory>();
    /// <summary>
    /// 租户配额使用记录。
    /// </summary>
    public DbSet<TenantQuotaUsage> TenantQuotaUsages => Set<TenantQuotaUsage>();
    /// <summary>
    /// 租户配额使用历史记录。
    /// </summary>
    public DbSet<TenantQuotaUsageHistory> TenantQuotaUsageHistories => Set<TenantQuotaUsageHistory>();
    /// <summary>
    /// 租户账单。
    /// </summary>
    public DbSet<TenantBillingStatement> TenantBillingStatements => Set<TenantBillingStatement>();
    /// <summary>
    /// 租户支付记录。
    /// </summary>
    public DbSet<TenantPayment> TenantPayments => Set<TenantPayment>();
    /// <summary>
    /// 租户通知。
    /// </summary>
    public DbSet<TenantNotification> TenantNotifications => Set<TenantNotification>();
    /// <summary>
    /// 租户公告。
    /// </summary>
    public DbSet<TenantAnnouncement> TenantAnnouncements => Set<TenantAnnouncement>();
    /// <summary>
    /// 租户公告已读记录。
    /// </summary>
    public DbSet<TenantAnnouncementRead> TenantAnnouncementReads => Set<TenantAnnouncementRead>();
    /// <summary>
    /// 租户认证资料。
    /// </summary>
    public DbSet<TenantVerificationProfile> TenantVerificationProfiles => Set<TenantVerificationProfile>();
    /// <summary>
    /// 租户账单/配额可见角色规则。
    /// </summary>
    public DbSet<TenantVisibilityRoleRule> TenantVisibilityRoleRules => Set<TenantVisibilityRoleRule>();
    /// <summary>
    /// 租户发票设置。
    /// </summary>
    public DbSet<TenantInvoiceSetting> TenantInvoiceSettings => Set<TenantInvoiceSetting>();
    /// <summary>
    /// 租户发票记录。
    /// </summary>
    public DbSet<TenantInvoiceRecord> TenantInvoiceRecords => Set<TenantInvoiceRecord>();
    /// <summary>
    /// 经营报表快照。
    /// </summary>
    public DbSet<FinanceBusinessReportSnapshot> FinanceBusinessReportSnapshots => Set<FinanceBusinessReportSnapshot>();
    /// <summary>
    /// 成本配置。
    /// </summary>
    public DbSet<FinanceCostProfile> FinanceCostProfiles => Set<FinanceCostProfile>();
    /// <summary>
    /// 成本日覆盖。
    /// </summary>
    public DbSet<FinanceCostDailyOverride> FinanceCostDailyOverrides => Set<FinanceCostDailyOverride>();
    /// <summary>
    /// 成本录入汇总。
    /// </summary>
    public DbSet<FinanceCostEntry> FinanceCostEntries => Set<FinanceCostEntry>();
    /// <summary>
    /// 成本录入明细。
    /// </summary>
    public DbSet<FinanceCostEntryItem> FinanceCostEntryItems => Set<FinanceCostEntryItem>();
    /// <summary>
    /// 配额包定义。
    /// </summary>
    public DbSet<QuotaPackage> QuotaPackages => Set<QuotaPackage>();
    /// <summary>
    /// 租户配额包购买记录。
    /// </summary>
    public DbSet<TenantQuotaPackagePurchase> TenantQuotaPackagePurchases => Set<TenantQuotaPackagePurchase>();
    /// <summary>
    /// 商户实体。
    /// </summary>
    public DbSet<Merchant> Merchants => Set<Merchant>();
    /// <summary>
    /// 商户资质文件。
    /// </summary>
    public DbSet<MerchantDocument> MerchantDocuments => Set<MerchantDocument>();
    /// <summary>
    /// 商户合同。
    /// </summary>
    public DbSet<MerchantContract> MerchantContracts => Set<MerchantContract>();
    /// <summary>
    /// 商户员工。
    /// </summary>
    public DbSet<MerchantStaff> MerchantStaff => Set<MerchantStaff>();
    /// <summary>
    /// 商户分类。
    /// </summary>
    public DbSet<MerchantCategory> MerchantCategories => Set<MerchantCategory>();
    /// <summary>
    /// 门店实体。
    /// </summary>
    public DbSet<Store> Stores => Set<Store>();
    /// <summary>
    /// 门店费用配置。
    /// </summary>
    public DbSet<StoreFee> StoreFees => Set<StoreFee>();
    /// <summary>
    /// 门店资质证照。
    /// </summary>
    public DbSet<StoreQualification> StoreQualifications => Set<StoreQualification>();
    /// <summary>
    /// 门店审核记录。
    /// </summary>
    public DbSet<StoreAuditRecord> StoreAuditRecords => Set<StoreAuditRecord>();
    /// <summary>
    /// 门店营业时间。
    /// </summary>
    public DbSet<StoreBusinessHour> StoreBusinessHours => Set<StoreBusinessHour>();
    /// <summary>
    /// 门店节假日。
    /// </summary>
    public DbSet<StoreHoliday> StoreHolidays => Set<StoreHoliday>();
    /// <summary>
    /// 门店配送区域。
    /// </summary>
    public DbSet<StoreDeliveryZone> StoreDeliveryZones => Set<StoreDeliveryZone>();
    /// <summary>
    /// 门店配送设置。
    /// </summary>
    public DbSet<StoreDeliverySetting> StoreDeliverySettings => Set<StoreDeliverySetting>();
    /// <summary>
    /// 门店堂食设置。
    /// </summary>
    public DbSet<StoreDineInSetting> StoreDineInSettings => Set<StoreDineInSetting>();
    /// <summary>
    /// 门店桌台区域。
    /// </summary>
    public DbSet<StoreTableArea> StoreTableAreas => Set<StoreTableArea>();
    /// <summary>
    /// 门店桌台。
    /// </summary>
    public DbSet<StoreTable> StoreTables => Set<StoreTable>();
    /// <summary>
    /// 门店员工班次。
    /// </summary>
    public DbSet<StoreEmployeeShift> StoreEmployeeShifts => Set<StoreEmployeeShift>();
    /// <summary>
    /// 自提配置。
    /// </summary>
    public DbSet<StorePickupSetting> StorePickupSettings => Set<StorePickupSetting>();
    /// <summary>
    /// 自提时间段。
    /// </summary>
    public DbSet<StorePickupSlot> StorePickupSlots => Set<StorePickupSlot>();
    /// <summary>
    /// 门店班次模板。
    /// </summary>
    public DbSet<StoreStaffTemplate> StoreStaffTemplates => Set<StoreStaffTemplate>();
    /// <summary>
    /// 门店每周排班。
    /// </summary>
    public DbSet<StoreStaffWeeklySchedule> StoreStaffWeeklySchedules => Set<StoreStaffWeeklySchedule>();
    /// <summary>
    /// 商品分类。
    /// </summary>
    public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
    /// <summary>
    /// 商品。
    /// </summary>
    public DbSet<Product> Products => Set<Product>();
    /// <summary>
    /// 商品属性组。
    /// </summary>
    public DbSet<ProductAttributeGroup> ProductAttributeGroups => Set<ProductAttributeGroup>();
    /// <summary>
    /// 商品属性项。
    /// </summary>
    public DbSet<ProductAttributeOption> ProductAttributeOptions => Set<ProductAttributeOption>();
    /// <summary>
    /// 门店规格做法模板。
    /// </summary>
    public DbSet<ProductSpecTemplate> ProductSpecTemplates => Set<ProductSpecTemplate>();
    /// <summary>
    /// 门店规格做法模板选项。
    /// </summary>
    public DbSet<ProductSpecTemplateOption> ProductSpecTemplateOptions => Set<ProductSpecTemplateOption>();
    /// <summary>
    /// 门店规格做法模板关联商品。
    /// </summary>
    public DbSet<ProductSpecTemplateProduct> ProductSpecTemplateProducts => Set<ProductSpecTemplateProduct>();
    /// <summary>
    /// 商品标签。
    /// </summary>
    public DbSet<ProductLabel> ProductLabels => Set<ProductLabel>();
    /// <summary>
    /// 标签与商品关联。
    /// </summary>
    public DbSet<ProductLabelProduct> ProductLabelProducts => Set<ProductLabelProduct>();
    /// <summary>
    /// 商品时段规则。
    /// </summary>
    public DbSet<ProductSchedule> ProductSchedules => Set<ProductSchedule>();
    /// <summary>
    /// 时段规则与商品关联。
    /// </summary>
    public DbSet<ProductScheduleProduct> ProductScheduleProducts => Set<ProductScheduleProduct>();
    /// <summary>
    /// SKU 实体。
    /// </summary>
    public DbSet<ProductSku> ProductSkus => Set<ProductSku>();
    /// <summary>
    /// SKU 异步保存任务。
    /// </summary>
    public DbSet<ProductSkuSaveJob> ProductSkuSaveJobs => Set<ProductSkuSaveJob>();
    /// <summary>
    /// 套餐分组。
    /// </summary>
    public DbSet<ProductComboGroup> ProductComboGroups => Set<ProductComboGroup>();
    /// <summary>
    /// 套餐分组商品。
    /// </summary>
    public DbSet<ProductComboGroupItem> ProductComboGroupItems => Set<ProductComboGroupItem>();
    /// <summary>
    /// 加料分组。
    /// </summary>
    public DbSet<ProductAddonGroup> ProductAddonGroups => Set<ProductAddonGroup>();
    /// <summary>
    /// 加料选项。
    /// </summary>
    public DbSet<ProductAddonOption> ProductAddonOptions => Set<ProductAddonOption>();
    /// <summary>
    /// 定价规则。
    /// </summary>
    public DbSet<ProductPricingRule> ProductPricingRules => Set<ProductPricingRule>();
    /// <summary>
    /// 商品媒体资源。
    /// </summary>
    public DbSet<ProductMediaAsset> ProductMediaAssets => Set<ProductMediaAsset>();
    /// <summary>
    /// 库存项目。
    /// </summary>
    public DbSet<InventoryItem> InventoryItems => Set<InventoryItem>();
    /// <summary>
    /// 库存调整记录。
    /// </summary>
    public DbSet<InventoryAdjustment> InventoryAdjustments => Set<InventoryAdjustment>();
    /// <summary>
    /// 库存批次。
    /// </summary>
    public DbSet<InventoryBatch> InventoryBatches => Set<InventoryBatch>();
    /// <summary>
    /// 库存锁定记录。
    /// </summary>
    public DbSet<InventoryLockRecord> InventoryLockRecords => Set<InventoryLockRecord>();
    /// <summary>
    /// 购物车。
    /// </summary>
    public DbSet<ShoppingCart> ShoppingCarts => Set<ShoppingCart>();
    /// <summary>
    /// 购物车明细。
    /// </summary>
    public DbSet<CartItem> CartItems => Set<CartItem>();
    /// <summary>
    /// 购物车加料。
    /// </summary>
    public DbSet<CartItemAddon> CartItemAddons => Set<CartItemAddon>();
    /// <summary>
    /// 结账会话。
    /// </summary>
    public DbSet<CheckoutSession> CheckoutSessions => Set<CheckoutSession>();
    /// <summary>
    /// 订单聚合。
    /// </summary>
    public DbSet<Order> Orders => Set<Order>();
    /// <summary>
    /// 订单明细。
    /// </summary>
    public DbSet<OrderItem> OrderItems => Set<OrderItem>();
    /// <summary>
    /// 订单状态流转。
    /// </summary>
    public DbSet<OrderStatusHistory> OrderStatusHistories => Set<OrderStatusHistory>();
    /// <summary>
    /// 退款申请。
    /// </summary>
    public DbSet<RefundRequest> RefundRequests => Set<RefundRequest>();
    /// <summary>
    /// 支付记录。
    /// </summary>
    public DbSet<PaymentRecord> PaymentRecords => Set<PaymentRecord>();
    /// <summary>
    /// 支付退款记录。
    /// </summary>
    public DbSet<PaymentRefundRecord> PaymentRefundRecords => Set<PaymentRefundRecord>();
    /// <summary>
    /// 预订记录。
    /// </summary>
    public DbSet<Reservation> Reservations => Set<Reservation>();
    /// <summary>
    /// 排号记录。
    /// </summary>
    public DbSet<QueueTicket> QueueTickets => Set<QueueTicket>();
    /// <summary>
    /// 配送订单。
    /// </summary>
    public DbSet<DeliveryOrder> DeliveryOrders => Set<DeliveryOrder>();
    /// <summary>
    /// 配送事件。
    /// </summary>
    public DbSet<DeliveryEvent> DeliveryEvents => Set<DeliveryEvent>();
    /// <summary>
    /// 团购订单。
    /// </summary>
    public DbSet<GroupOrder> GroupOrders => Set<GroupOrder>();
    /// <summary>
    /// 团购参与者。
    /// </summary>
    public DbSet<GroupParticipant> GroupParticipants => Set<GroupParticipant>();
    /// <summary>
    /// 优惠券模板。
    /// </summary>
    public DbSet<CouponTemplate> CouponTemplates => Set<CouponTemplate>();
    /// <summary>
    /// 优惠券实例。
    /// </summary>
    public DbSet<Coupon> Coupons => Set<Coupon>();
    /// <summary>
    /// 营销活动。
    /// </summary>
    public DbSet<PromotionCampaign> PromotionCampaigns => Set<PromotionCampaign>();
    /// <summary>
    /// 新客有礼配置。
    /// </summary>
    public DbSet<NewCustomerGiftSetting> NewCustomerGiftSettings => Set<NewCustomerGiftSetting>();
    /// <summary>
    /// 新客有礼券规则。
    /// </summary>
    public DbSet<NewCustomerCouponRule> NewCustomerCouponRules => Set<NewCustomerCouponRule>();
    /// <summary>
    /// 新客邀请记录。
    /// </summary>
    public DbSet<NewCustomerInviteRecord> NewCustomerInviteRecords => Set<NewCustomerInviteRecord>();
    /// <summary>
    /// 新客成长记录。
    /// </summary>
    public DbSet<NewCustomerGrowthRecord> NewCustomerGrowthRecords => Set<NewCustomerGrowthRecord>();
    /// <summary>
    /// 次卡模板。
    /// </summary>
    public DbSet<PunchCardTemplate> PunchCardTemplates => Set<PunchCardTemplate>();
    /// <summary>
    /// 次卡实例。
    /// </summary>
    public DbSet<PunchCardInstance> PunchCardInstances => Set<PunchCardInstance>();
    /// <summary>
    /// 次卡使用记录。
    /// </summary>
    public DbSet<PunchCardUsageRecord> PunchCardUsageRecords => Set<PunchCardUsageRecord>();
    /// <summary>
    /// 会员档案。
    /// </summary>
    public DbSet<MemberProfile> MemberProfiles => Set<MemberProfile>();
    /// <summary>
    /// 会员等级。
    /// </summary>
    public DbSet<MemberTier> MemberTiers => Set<MemberTier>();
    /// <summary>
    /// 会员标签。
    /// </summary>
    public DbSet<MemberProfileTag> MemberProfileTags => Set<MemberProfileTag>();
    /// <summary>
    /// 会员日设置。
    /// </summary>
    public DbSet<MemberDaySetting> MemberDaySettings => Set<MemberDaySetting>();
    /// <summary>
    /// 积分流水。
    /// </summary>
    public DbSet<MemberPointLedger> MemberPointLedgers => Set<MemberPointLedger>();
    /// <summary>
    /// 积分商城规则。
    /// </summary>
    public DbSet<MemberPointMallRule> MemberPointMallRules => Set<MemberPointMallRule>();
    /// <summary>
    /// 积分商城兑换商品。
    /// </summary>
    public DbSet<MemberPointMallProduct> MemberPointMallProducts => Set<MemberPointMallProduct>();
    /// <summary>
    /// 积分商城兑换记录。
    /// </summary>
    public DbSet<MemberPointMallRecord> MemberPointMallRecords => Set<MemberPointMallRecord>();
    /// <summary>
    /// 会员储值方案。
    /// </summary>
    public DbSet<MemberStoredCardPlan> MemberStoredCardPlans => Set<MemberStoredCardPlan>();
    /// <summary>
    /// 会员储值充值记录。
    /// </summary>
    public DbSet<MemberStoredCardRechargeRecord> MemberStoredCardRechargeRecords => Set<MemberStoredCardRechargeRecord>();
    /// <summary>
    /// 会员消息触达记录。
    /// </summary>
    public DbSet<MemberReachMessage> MemberReachMessages => Set<MemberReachMessage>();
    /// <summary>
    /// 会员消息模板。
    /// </summary>
    public DbSet<MemberMessageTemplate> MemberMessageTemplates => Set<MemberMessageTemplate>();
    /// <summary>
    /// 会员消息触达收件明细。
    /// </summary>
    public DbSet<MemberReachRecipient> MemberReachRecipients => Set<MemberReachRecipient>();
    /// <summary>
    /// 会话记录。
    /// </summary>
    public DbSet<ChatSession> ChatSessions => Set<ChatSession>();
    /// <summary>
    /// 会话消息。
    /// </summary>
    public DbSet<ChatMessage> ChatMessages => Set<ChatMessage>();
    /// <summary>
    /// 工单记录。
    /// </summary>
    public DbSet<SupportTicket> SupportTickets => Set<SupportTicket>();
    /// <summary>
    /// 工单评论。
    /// </summary>
    public DbSet<TicketComment> TicketComments => Set<TicketComment>();
    /// <summary>
    /// 分销合作伙伴。
    /// </summary>
    public DbSet<AffiliatePartner> AffiliatePartners => Set<AffiliatePartner>();
    /// <summary>
    /// 分销订单。
    /// </summary>
    public DbSet<AffiliateOrder> AffiliateOrders => Set<AffiliateOrder>();
    /// <summary>
    /// 分销结算。
    /// </summary>
    public DbSet<AffiliatePayout> AffiliatePayouts => Set<AffiliatePayout>();
    /// <summary>
    /// 打卡活动。
    /// </summary>
    public DbSet<CheckInCampaign> CheckInCampaigns => Set<CheckInCampaign>();
    /// <summary>
    /// 打卡记录。
    /// </summary>
    public DbSet<CheckInRecord> CheckInRecords => Set<CheckInRecord>();
    /// <summary>
    /// 社区帖子。
    /// </summary>
    public DbSet<CommunityPost> CommunityPosts => Set<CommunityPost>();
    /// <summary>
    /// 社区评论。
    /// </summary>
    public DbSet<CommunityComment> CommunityComments => Set<CommunityComment>();
    /// <summary>
    /// 社区互动。
    /// </summary>
    public DbSet<CommunityReaction> CommunityReactions => Set<CommunityReaction>();
    /// <summary>
    /// 地图位置。
    /// </summary>
    public DbSet<MapLocation> MapLocations => Set<MapLocation>();
    /// <summary>
    /// 导航请求。
    /// </summary>
    public DbSet<NavigationRequest> NavigationRequests => Set<NavigationRequest>();
    /// <summary>
    /// 指标定义。
    /// </summary>
    public DbSet<MetricDefinition> MetricDefinitions => Set<MetricDefinition>();
    /// <summary>
    /// 指标快照。
    /// </summary>
    public DbSet<MetricSnapshot> MetricSnapshots => Set<MetricSnapshot>();
    /// <summary>
    /// 告警规则。
    /// </summary>
    public DbSet<MetricAlertRule> MetricAlertRules => Set<MetricAlertRule>();
    /// <summary>
    /// 配置实体映射关系。
    /// </summary>
    /// <param name="modelBuilder">模型构建器。</param>
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 1. 调用基类配置
        base.OnModelCreating(modelBuilder);
        // 2. 配置全部实体映射
        ConfigureTenant(modelBuilder.Entity<Tenant>());
        ConfigureMerchant(modelBuilder.Entity<Merchant>());
        ConfigureStore(modelBuilder.Entity<Store>());
        ConfigureTenantPackage(modelBuilder.Entity<TenantPackage>());
        ConfigureTenantSubscription(modelBuilder.Entity<TenantSubscription>());
        ConfigureTenantSubscriptionHistory(modelBuilder.Entity<TenantSubscriptionHistory>());
        ConfigureTenantQuotaUsage(modelBuilder.Entity<TenantQuotaUsage>());
        ConfigureTenantQuotaUsageHistory(modelBuilder.Entity<TenantQuotaUsageHistory>());
        ConfigureTenantBilling(modelBuilder.Entity<TenantBillingStatement>());
        ConfigureTenantPayment(modelBuilder.Entity<TenantPayment>());
        ConfigureTenantNotification(modelBuilder.Entity<TenantNotification>());
        ConfigureTenantAnnouncement(modelBuilder.Entity<TenantAnnouncement>());
        ConfigureTenantAnnouncementRead(modelBuilder.Entity<TenantAnnouncementRead>());
        ConfigureTenantVerificationProfile(modelBuilder.Entity<TenantVerificationProfile>());
        ConfigureTenantVisibilityRoleRule(modelBuilder.Entity<TenantVisibilityRoleRule>());
        ConfigureTenantInvoiceSetting(modelBuilder.Entity<TenantInvoiceSetting>());
        ConfigureTenantInvoiceRecord(modelBuilder.Entity<TenantInvoiceRecord>());
        ConfigureFinanceBusinessReportSnapshot(modelBuilder.Entity<FinanceBusinessReportSnapshot>());
        ConfigureFinanceCostProfile(modelBuilder.Entity<FinanceCostProfile>());
        ConfigureFinanceCostDailyOverride(modelBuilder.Entity<FinanceCostDailyOverride>());
        ConfigureFinanceCostEntry(modelBuilder.Entity<FinanceCostEntry>());
        ConfigureFinanceCostEntryItem(modelBuilder.Entity<FinanceCostEntryItem>());
        ConfigureQuotaPackage(modelBuilder.Entity<QuotaPackage>());
        ConfigureTenantQuotaPackagePurchase(modelBuilder.Entity<TenantQuotaPackagePurchase>());
        ConfigureMerchantDocument(modelBuilder.Entity<MerchantDocument>());
        ConfigureMerchantContract(modelBuilder.Entity<MerchantContract>());
        ConfigureMerchantStaff(modelBuilder.Entity<MerchantStaff>());
        ConfigureMerchantCategory(modelBuilder.Entity<MerchantCategory>());
        ConfigureStoreFee(modelBuilder.Entity<StoreFee>());
        ConfigureStoreQualification(modelBuilder.Entity<StoreQualification>());
        ConfigureStoreAuditRecord(modelBuilder.Entity<StoreAuditRecord>());
        ConfigureStoreBusinessHour(modelBuilder.Entity<StoreBusinessHour>());
        ConfigureStoreHoliday(modelBuilder.Entity<StoreHoliday>());
        ConfigureStoreDeliveryZone(modelBuilder.Entity<StoreDeliveryZone>());
        ConfigureStoreDeliverySetting(modelBuilder.Entity<StoreDeliverySetting>());
        ConfigureStoreDineInSetting(modelBuilder.Entity<StoreDineInSetting>());
        ConfigureStoreTableArea(modelBuilder.Entity<StoreTableArea>());
        ConfigureStoreTable(modelBuilder.Entity<StoreTable>());
        ConfigureStoreEmployeeShift(modelBuilder.Entity<StoreEmployeeShift>());
        ConfigureStorePickupSetting(modelBuilder.Entity<StorePickupSetting>());
        ConfigureStorePickupSlot(modelBuilder.Entity<StorePickupSlot>());
        ConfigureStoreStaffTemplate(modelBuilder.Entity<StoreStaffTemplate>());
        ConfigureStoreStaffWeeklySchedule(modelBuilder.Entity<StoreStaffWeeklySchedule>());
        ConfigureProductCategory(modelBuilder.Entity<ProductCategory>());
        ConfigureProduct(modelBuilder.Entity<Product>());
        ConfigureProductAttributeGroup(modelBuilder.Entity<ProductAttributeGroup>());
        ConfigureProductAttributeOption(modelBuilder.Entity<ProductAttributeOption>());
        ConfigureProductSpecTemplate(modelBuilder.Entity<ProductSpecTemplate>());
        ConfigureProductSpecTemplateOption(modelBuilder.Entity<ProductSpecTemplateOption>());
        ConfigureProductSpecTemplateProduct(modelBuilder.Entity<ProductSpecTemplateProduct>());
        ConfigureProductLabel(modelBuilder.Entity<ProductLabel>());
        ConfigureProductLabelProduct(modelBuilder.Entity<ProductLabelProduct>());
        ConfigureProductSchedule(modelBuilder.Entity<ProductSchedule>());
        ConfigureProductScheduleProduct(modelBuilder.Entity<ProductScheduleProduct>());
        ConfigureProductSku(modelBuilder.Entity<ProductSku>());
        ConfigureProductSkuSaveJob(modelBuilder.Entity<ProductSkuSaveJob>());
        ConfigureProductComboGroup(modelBuilder.Entity<ProductComboGroup>());
        ConfigureProductComboGroupItem(modelBuilder.Entity<ProductComboGroupItem>());
        ConfigureProductAddonGroup(modelBuilder.Entity<ProductAddonGroup>());
        ConfigureProductAddonOption(modelBuilder.Entity<ProductAddonOption>());
        ConfigureProductPricingRule(modelBuilder.Entity<ProductPricingRule>());
        ConfigureProductMediaAsset(modelBuilder.Entity<ProductMediaAsset>());
        ConfigureInventoryItem(modelBuilder.Entity<InventoryItem>());
        ConfigureInventoryAdjustment(modelBuilder.Entity<InventoryAdjustment>());
        ConfigureInventoryBatch(modelBuilder.Entity<InventoryBatch>());
        ConfigureInventoryLockRecord(modelBuilder.Entity<InventoryLockRecord>());
        ConfigureShoppingCart(modelBuilder.Entity<ShoppingCart>());
        ConfigureCartItem(modelBuilder.Entity<CartItem>());
        ConfigureCartItemAddon(modelBuilder.Entity<CartItemAddon>());
        ConfigureCheckoutSession(modelBuilder.Entity<CheckoutSession>());
        ConfigureOrder(modelBuilder.Entity<Order>());
        ConfigureOrderItem(modelBuilder.Entity<OrderItem>());
        ConfigureOrderStatusHistory(modelBuilder.Entity<OrderStatusHistory>());
        ConfigureRefundRequest(modelBuilder.Entity<RefundRequest>());
        ConfigurePaymentRecord(modelBuilder.Entity<PaymentRecord>());
        ConfigurePaymentRefundRecord(modelBuilder.Entity<PaymentRefundRecord>());
        ConfigureReservation(modelBuilder.Entity<Reservation>());
        ConfigureQueueTicket(modelBuilder.Entity<QueueTicket>());
        ConfigureDelivery(modelBuilder.Entity<DeliveryOrder>());
        ConfigureDeliveryEvent(modelBuilder.Entity<DeliveryEvent>());
        ConfigureGroupOrder(modelBuilder.Entity<GroupOrder>());
        ConfigureGroupParticipant(modelBuilder.Entity<GroupParticipant>());
        ConfigureCouponTemplate(modelBuilder.Entity<CouponTemplate>());
        ConfigureCoupon(modelBuilder.Entity<Coupon>());
        ConfigurePromotionCampaign(modelBuilder.Entity<PromotionCampaign>());
        ConfigureNewCustomerGiftSetting(modelBuilder.Entity<NewCustomerGiftSetting>());
        ConfigureNewCustomerCouponRule(modelBuilder.Entity<NewCustomerCouponRule>());
        ConfigureNewCustomerInviteRecord(modelBuilder.Entity<NewCustomerInviteRecord>());
        ConfigureNewCustomerGrowthRecord(modelBuilder.Entity<NewCustomerGrowthRecord>());
        ConfigurePunchCardTemplate(modelBuilder.Entity<PunchCardTemplate>());
        ConfigurePunchCardInstance(modelBuilder.Entity<PunchCardInstance>());
        ConfigurePunchCardUsageRecord(modelBuilder.Entity<PunchCardUsageRecord>());
        ConfigureMemberProfile(modelBuilder.Entity<MemberProfile>());
        ConfigureMemberTier(modelBuilder.Entity<MemberTier>());
        ConfigureMemberProfileTag(modelBuilder.Entity<MemberProfileTag>());
        ConfigureMemberDaySetting(modelBuilder.Entity<MemberDaySetting>());
        ConfigureMemberPointLedger(modelBuilder.Entity<MemberPointLedger>());
        ConfigureMemberPointMallRule(modelBuilder.Entity<MemberPointMallRule>());
        ConfigureMemberPointMallProduct(modelBuilder.Entity<MemberPointMallProduct>());
        ConfigureMemberPointMallRecord(modelBuilder.Entity<MemberPointMallRecord>());
        ConfigureMemberStoredCardPlan(modelBuilder.Entity<MemberStoredCardPlan>());
        ConfigureMemberStoredCardRechargeRecord(modelBuilder.Entity<MemberStoredCardRechargeRecord>());
        ConfigureMemberReachMessage(modelBuilder.Entity<MemberReachMessage>());
        ConfigureMemberMessageTemplate(modelBuilder.Entity<MemberMessageTemplate>());
        ConfigureMemberReachRecipient(modelBuilder.Entity<MemberReachRecipient>());
        ConfigureChatSession(modelBuilder.Entity<ChatSession>());
        ConfigureChatMessage(modelBuilder.Entity<ChatMessage>());
        ConfigureSupportTicket(modelBuilder.Entity<SupportTicket>());
        ConfigureTicketComment(modelBuilder.Entity<TicketComment>());
        ConfigureAffiliatePartner(modelBuilder.Entity<AffiliatePartner>());
        ConfigureAffiliateOrder(modelBuilder.Entity<AffiliateOrder>());
        ConfigureAffiliatePayout(modelBuilder.Entity<AffiliatePayout>());
        ConfigureCheckInCampaign(modelBuilder.Entity<CheckInCampaign>());
        ConfigureCheckInRecord(modelBuilder.Entity<CheckInRecord>());
        ConfigureCommunityPost(modelBuilder.Entity<CommunityPost>());
        ConfigureCommunityComment(modelBuilder.Entity<CommunityComment>());
        ConfigureCommunityReaction(modelBuilder.Entity<CommunityReaction>());
        ConfigureMapLocation(modelBuilder.Entity<MapLocation>());
        ConfigureNavigationRequest(modelBuilder.Entity<NavigationRequest>());
        ConfigureMetricDefinition(modelBuilder.Entity<MetricDefinition>());
        ConfigureMetricSnapshot(modelBuilder.Entity<MetricSnapshot>());
        ConfigureMetricAlertRule(modelBuilder.Entity<MetricAlertRule>());
        modelBuilder.AddInboxStateEntity();
        modelBuilder.AddOutboxMessageEntity();
        modelBuilder.AddOutboxStateEntity();

        // 3. 应用多租户全局查询过滤器
        ApplyTenantQueryFilters(modelBuilder);
    }

    private static void ConfigureTenant(EntityTypeBuilder<Tenant> builder)
    {
        builder.ToTable("tenants");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Code).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.ShortName).HasMaxLength(64);
        builder.Property(x => x.ContactName).HasMaxLength(64);
        builder.Property(x => x.ContactPhone).HasMaxLength(32);
        builder.Property(x => x.ContactEmail).HasMaxLength(128);
        builder.Property(x => x.Industry).HasMaxLength(64);
        builder.Property(x => x.LogoUrl).HasColumnType("text");
        builder.Property(x => x.GeoStatus).HasConversion<int>().HasDefaultValue(GeoLocationStatus.Pending);
        builder.Property(x => x.GeoFailReason).HasMaxLength(500);
        builder.Property(x => x.GeoRetryCount).HasDefaultValue(0);
        builder.Property(x => x.Remarks).HasMaxLength(512);
        builder.Property(x => x.OperatingMode).HasConversion<int>();
        builder.HasIndex(x => x.Code).IsUnique();
        builder.HasIndex(x => x.ContactPhone).IsUnique();
        builder.HasIndex(x => new { x.GeoStatus, x.GeoNextRetryAt });
        builder.HasIndex(x => new { x.Longitude, x.Latitude })
            .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL");
    }

    private static void ConfigureTenantVerificationProfile(EntityTypeBuilder<TenantVerificationProfile> builder)
    {
        builder.ToTable("tenant_verification_profiles");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(64);
        builder.Property(x => x.BusinessLicenseUrl).HasMaxLength(512);
        builder.Property(x => x.LegalPersonName).HasMaxLength(64);
        builder.Property(x => x.LegalPersonIdNumber).HasMaxLength(32);
        builder.Property(x => x.LegalPersonIdFrontUrl).HasMaxLength(512);
        builder.Property(x => x.LegalPersonIdBackUrl).HasMaxLength(512);
        builder.Property(x => x.BankAccountName).HasMaxLength(128);
        builder.Property(x => x.BankAccountNumber).HasMaxLength(64);
        builder.Property(x => x.BankName).HasMaxLength(128);
        builder.Property(x => x.ReviewRemarks).HasMaxLength(512);
        builder.Property(x => x.ReviewedByName).HasMaxLength(64);
        builder.HasIndex(x => x.TenantId).IsUnique();
    }

    // 租户订阅历史映射
    private static void ConfigureTenantSubscriptionHistory(EntityTypeBuilder<TenantSubscriptionHistory> builder)
    {
        builder.ToTable("tenant_subscription_histories");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.TenantSubscriptionId).IsRequired();
        builder.Property(x => x.Notes).HasMaxLength(512);
        builder.Property(x => x.Currency).HasMaxLength(8);
        builder.HasIndex(x => new { x.TenantId, x.TenantSubscriptionId });
    }

    private static void ConfigureMerchant(EntityTypeBuilder<Merchant> builder)
    {
        builder.ToTable("merchants");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.BrandName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.BrandAlias).HasMaxLength(64);
        builder.Property(x => x.LegalPerson).HasMaxLength(64);
        builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(64);
        builder.Property(x => x.ContactPhone).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ContactEmail).HasMaxLength(128);
        builder.Property(x => x.Province).HasMaxLength(64);
        builder.Property(x => x.City).HasMaxLength(64);
        builder.Property(x => x.District).HasMaxLength(64);
        builder.Property(x => x.Address).HasMaxLength(256);
        builder.Property(x => x.ReviewRemarks).HasMaxLength(512);
        builder.Property(x => x.OperatingMode).HasConversion<int>();
        builder.Property(x => x.GeoStatus).HasConversion<int>().HasDefaultValue(GeoLocationStatus.Pending);
        builder.Property(x => x.GeoFailReason).HasMaxLength(500);
        builder.Property(x => x.GeoRetryCount).HasDefaultValue(0);
        builder.Property(x => x.IsFrozen).HasDefaultValue(false);
        builder.Property(x => x.FrozenReason).HasMaxLength(500);
        builder.Property(x => x.ClaimedByName).HasMaxLength(100);
        builder.Ignore(x => x.RowVersion);
        builder.Property<uint>("xmin")
            .HasColumnName("xmin")
            .HasColumnType("xid")
            .ValueGeneratedOnAddOrUpdate()
            .IsConcurrencyToken();
        builder.HasIndex(x => x.TenantId);
        builder.HasIndex(x => new { x.TenantId, x.Status });
        builder.HasIndex(x => x.ClaimedBy);
        builder.HasIndex(x => new { x.TenantId, x.GeoStatus, x.GeoNextRetryAt });
        builder.HasIndex(x => new { x.Longitude, x.Latitude })
            .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL");
    }

    private static void ConfigureStore(EntityTypeBuilder<Store> builder)
    {
        builder.ToTable("stores");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Code).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Phone).HasMaxLength(32);
        builder.Property(x => x.ManagerName).HasMaxLength(64);
        builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(50);
        builder.Property(x => x.LegalRepresentative).HasMaxLength(100);
        builder.Property(x => x.RegisteredAddress).HasMaxLength(500);
        builder.Property(x => x.BusinessLicenseImageUrl).HasMaxLength(500);
        builder.Property(x => x.SignboardImageUrl).HasMaxLength(500);
        builder.Property(x => x.OwnershipType).HasConversion<int>();
        builder.Property(x => x.AuditStatus).HasConversion<int>();
        builder.Property(x => x.BusinessStatus).HasConversion<int>();
        builder.Property(x => x.ClosureReason).HasConversion<int?>();
        builder.Property(x => x.ClosureReasonText).HasMaxLength(500);
        builder.Property(x => x.RejectionReason).HasMaxLength(500);
        builder.Property(x => x.ForceCloseReason).HasMaxLength(500);
        builder.Property(x => x.Province).HasMaxLength(64);
        builder.Property(x => x.City).HasMaxLength(64);
        builder.Property(x => x.District).HasMaxLength(64);
        builder.Property(x => x.Address).HasMaxLength(256);
        builder.Property(x => x.BusinessHours).HasMaxLength(256);
        builder.Property(x => x.Announcement).HasMaxLength(512);
        builder.Property(x => x.DeliveryRadiusKm).HasPrecision(6, 2);
        builder.Property(x => x.GeoStatus).HasConversion<int>().HasDefaultValue(GeoLocationStatus.Pending);
        builder.Property(x => x.GeoFailReason).HasMaxLength(500);
        builder.Property(x => x.GeoRetryCount).HasDefaultValue(0);
        builder.HasIndex(x => new { x.TenantId, x.MerchantId });
        builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.AuditStatus });
        builder.HasIndex(x => new { x.TenantId, x.BusinessStatus });
        builder.HasIndex(x => new { x.TenantId, x.OwnershipType });
        builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.GeoStatus, x.GeoNextRetryAt });
        builder.HasIndex(x => new { x.Longitude, x.Latitude })
            .HasFilter("\"Longitude\" IS NOT NULL AND \"Latitude\" IS NOT NULL");
        builder.HasIndex(x => new { x.MerchantId, x.BusinessLicenseNumber })
            .IsUnique()
            .HasFilter("\"BusinessLicenseNumber\" IS NOT NULL AND \"Status\" <> 3");
    }

    private static void ConfigureStoreFee(EntityTypeBuilder<StoreFee> builder)
    {
        builder.ToTable("store_fees");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.MinimumOrderAmount).HasPrecision(10, 2);
        builder.Property(x => x.BaseDeliveryFee).HasPrecision(10, 2);
        builder.Property(x => x.PlatformServiceRate).HasPrecision(5, 2);
        builder.Property(x => x.PackagingFeeMode).HasConversion<int>();
        builder.Property(x => x.OrderPackagingFeeMode).HasConversion<int>();
        builder.Property(x => x.FixedPackagingFee).HasPrecision(10, 2);
        builder.Property(x => x.PackagingFeeTiersJson).HasColumnType("text");
        builder.Property(x => x.FreeDeliveryThreshold).HasPrecision(10, 2);
        builder.Property(x => x.CutleryFeeEnabled).HasDefaultValue(false);
        builder.Property(x => x.CutleryFeeAmount).HasPrecision(10, 2);
        builder.Property(x => x.RushFeeEnabled).HasDefaultValue(false);
        builder.Property(x => x.RushFeeAmount).HasPrecision(10, 2);
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
        builder.HasIndex(x => x.TenantId);
    }

    private static void ConfigureStoreQualification(EntityTypeBuilder<StoreQualification> builder)
    {
        builder.ToTable("store_qualifications");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.QualificationType).HasConversion<int>();
        builder.Property(x => x.FileUrl).HasMaxLength(500).IsRequired();
        builder.Property(x => x.DocumentNumber).HasMaxLength(100);
        builder.Property(x => x.IssuedAt).HasColumnType("date");
        builder.Property(x => x.ExpiresAt).HasColumnType("date");
        builder.Property(x => x.SortOrder).HasDefaultValue(100);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
        builder.HasIndex(x => x.ExpiresAt)
            .HasFilter("\"ExpiresAt\" IS NOT NULL");
        builder.Ignore(x => x.IsExpired);
        builder.Ignore(x => x.IsExpiringSoon);
    }

    private static void ConfigureStoreAuditRecord(EntityTypeBuilder<StoreAuditRecord> builder)
    {
        builder.ToTable("store_audit_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Action).HasConversion<int>();
        builder.Property(x => x.PreviousStatus).HasConversion<int?>();
        builder.Property(x => x.NewStatus).HasConversion<int>();
        builder.Property(x => x.OperatorName).HasMaxLength(100).IsRequired();
        builder.Property(x => x.RejectionReason).HasMaxLength(500);
        builder.Property(x => x.Remarks).HasMaxLength(1000);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
        builder.HasIndex(x => x.CreatedAt);
    }

    private static void ConfigureProductCategory(EntityTypeBuilder<ProductCategory> builder)
    {
        builder.ToTable("product_categories");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(256);
        builder.Property(x => x.Icon).HasMaxLength(512);
        builder.Property(x => x.ChannelsJson).HasColumnType("text").HasDefaultValue("[\"wm\"]");
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
    }

    private static void ConfigureProduct(EntityTypeBuilder<Product> builder)
    {
        builder.ToTable("products");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.SpuCode).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Subtitle).HasMaxLength(256);
        builder.Property(x => x.Unit).HasMaxLength(16);
        builder.Property(x => x.Price).HasPrecision(18, 2);
        builder.Property(x => x.OriginalPrice).HasPrecision(18, 2);
        builder.Property(x => x.Kind).HasConversion<int>().HasDefaultValue(Domain.Products.Enums.ProductKind.Single);
        builder.Property(x => x.SalesMonthly).HasDefaultValue(0);
        builder.Property(x => x.TagsJson).HasColumnType("text").HasDefaultValue("[]");
        builder.Property(x => x.SoldoutMode).HasConversion<int?>();
        builder.Property(x => x.SoldoutReason).HasMaxLength(256);
        builder.Property(x => x.SyncToPlatform).HasDefaultValue(true);
        builder.Property(x => x.NotifyManager).HasDefaultValue(false);
        builder.Property(x => x.CoverImage).HasMaxLength(256);
        builder.Property(x => x.GalleryImages).HasMaxLength(1024);
        builder.Property(x => x.Description).HasColumnType("text");
        builder.Property(x => x.SortWeight).HasDefaultValue(0);
        builder.Property(x => x.PackingFee).HasPrecision(18, 2);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
        builder.HasIndex(x => new { x.TenantId, x.SpuCode }).IsUnique();
    }

    private static void ConfigureOrder(EntityTypeBuilder<Order> builder)
    {
        builder.ToTable("orders");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.OrderNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.CustomerName).HasMaxLength(64);
        builder.Property(x => x.CustomerPhone).HasMaxLength(32);
        builder.Property(x => x.TableNo).HasMaxLength(32);
        builder.Property(x => x.QueueNumber).HasMaxLength(32);
        builder.Property(x => x.CancelReason).HasMaxLength(256);
        builder.Property(x => x.Remark).HasMaxLength(512);
        builder.Property(x => x.ItemsAmount).HasPrecision(18, 2);
        builder.Property(x => x.DiscountAmount).HasPrecision(18, 2);
        builder.Property(x => x.PayableAmount).HasPrecision(18, 2);
        builder.Property(x => x.PaidAmount).HasPrecision(18, 2);
        builder.HasIndex(x => new { x.TenantId, x.OrderNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status });
    }

    private static void ConfigureOrderItem(EntityTypeBuilder<OrderItem> builder)
    {
        builder.ToTable("order_items");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.SkuName).HasMaxLength(128);
        builder.Property(x => x.Unit).HasMaxLength(16);
        builder.Property(x => x.UnitPrice).HasPrecision(18, 2);
        builder.Property(x => x.DiscountAmount).HasPrecision(18, 2);
        builder.Property(x => x.SubTotal).HasPrecision(18, 2);
        builder.Property(x => x.AttributesJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.OrderId });
        builder.HasOne<Order>()
            .WithMany()
            .HasForeignKey(x => x.OrderId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigurePaymentRecord(EntityTypeBuilder<PaymentRecord> builder)
    {
        builder.ToTable("payment_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Amount).HasPrecision(18, 2);
        builder.Property(x => x.TradeNo).HasMaxLength(64);
        builder.Property(x => x.ChannelTransactionId).HasMaxLength(64);
        builder.Property(x => x.Remark).HasMaxLength(256);
        builder.Property(x => x.Payload).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.OrderId });
    }

    private static void ConfigureReservation(EntityTypeBuilder<Reservation> builder)
    {
        builder.ToTable("reservations");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ReservationNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.CustomerName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.CustomerPhone).HasMaxLength(32).IsRequired();
        builder.Property(x => x.TablePreference).HasMaxLength(64);
        builder.Property(x => x.Remark).HasMaxLength(512);
        builder.Property(x => x.CheckInCode).HasMaxLength(32);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
        builder.HasIndex(x => new { x.TenantId, x.ReservationNo }).IsUnique();
    }

    private static void ConfigureQueueTicket(EntityTypeBuilder<QueueTicket> builder)
    {
        builder.ToTable("queue_tickets");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TicketNumber).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Remark).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TicketNumber }).IsUnique();
    }

    private static void ConfigureDelivery(EntityTypeBuilder<DeliveryOrder> builder)
    {
        builder.ToTable("delivery_orders");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProviderOrderId).HasMaxLength(64);
        builder.Property(x => x.DeliveryFee).HasPrecision(18, 2);
        builder.Property(x => x.CourierName).HasMaxLength(64);
        builder.Property(x => x.CourierPhone).HasMaxLength(32);
        builder.Property(x => x.FailureReason).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.OrderId }).IsUnique();
    }

    private static void ConfigureTenantPackage(EntityTypeBuilder<TenantPackage> builder)
    {
        builder.ToTable("tenant_packages");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.FeaturePoliciesJson).HasColumnType("text");
        builder.Property(x => x.PublishStatus)
            .HasConversion<int>()
            .HasDefaultValue(TenantPackagePublishStatus.Draft)
            .HasSentinel((TenantPackagePublishStatus)(-1))
            .HasComment("发布状态：0=草稿，1=已发布。");

        // 1. 解决 EF Core 默认值哨兵问题：当我们希望插入 false/0 时，若数据库配置了 default 且 EF 认为该值是“未设置”，会导致 insert 省略列，最终落库为默认值。
        // 2. 发布状态使用 -1 作为哨兵，避免 Draft=0 被误判为“未设置”而触发数据库默认值（发布/草稿切换必须可控）。
        // 3. 将布尔开关哨兵值设置为数据库默认值：true 作为哨兵，false 才会被显式写入，从而保证“可见性/可售开关”在新增时可正确落库。
        builder.Property(x => x.IsPublicVisible)
            .HasDefaultValue(true)
            .HasSentinel(true)
            .HasComment("是否对外可见（展示页/套餐列表可见性）。");
        builder.Property(x => x.IsAllowNewTenantPurchase)
            .HasDefaultValue(true)
            .HasSentinel(true)
            .HasComment("是否允许新租户购买/选择（仅影响新购）。");

        // 4. 展示配置：推荐标识与标签（用于套餐展示页/对比页）
        builder.Property(x => x.IsRecommended)
            .HasDefaultValue(false)
            .HasComment("是否推荐展示（运营推荐标识）。");
        builder.Property(x => x.Tags)
            .HasColumnType("text[]")
            .HasComment("套餐标签（用于展示与对比页）。");
        builder.Property(x => x.SortOrder).HasDefaultValue(0).HasComment("展示排序，数值越小越靠前。");
        builder.HasIndex(x => new { x.IsActive, x.SortOrder });
        builder.HasIndex(x => new { x.PublishStatus, x.IsActive, x.IsPublicVisible, x.IsAllowNewTenantPurchase, x.SortOrder });
    }

    private static void ConfigureTenantSubscription(EntityTypeBuilder<TenantSubscription> builder)
    {
        builder.ToTable("tenant_subscriptions");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantPackageId).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.TenantPackageId });
    }

    private static void ConfigureTenantQuotaUsage(EntityTypeBuilder<TenantQuotaUsage> builder)
    {
        builder.ToTable("tenant_quota_usages");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.QuotaType).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.QuotaType }).IsUnique();
    }

    private static void ConfigureTenantQuotaUsageHistory(EntityTypeBuilder<TenantQuotaUsageHistory> builder)
    {
        builder.ToTable("tenant_quota_usage_histories");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.QuotaType).HasConversion<int>();
        builder.Property(x => x.ChangeType).HasConversion<int>();
        builder.Property(x => x.ChangeReason).HasMaxLength(256);

        builder.HasIndex(x => new { x.TenantId, x.QuotaType, x.RecordedAt });
        builder.HasIndex(x => new { x.TenantId, x.RecordedAt });
    }

    private static void ConfigureTenantBilling(EntityTypeBuilder<TenantBillingStatement> builder)
    {
        new TenantBillingStatementConfiguration().Configure(builder);
    }

    private static void ConfigureTenantPayment(EntityTypeBuilder<TenantPayment> builder)
    {
        new TenantPaymentConfiguration().Configure(builder);
    }

    private static void ConfigureTenantNotification(EntityTypeBuilder<TenantNotification> builder)
    {
        builder.ToTable("tenant_notifications");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Title).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Message).HasMaxLength(1024).IsRequired();
        builder.Property(x => x.Channel).HasConversion<int>();
        builder.Property(x => x.Severity).HasConversion<int>();
        builder.Property(x => x.MetadataJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.Channel, x.SentAt });
    }

    private static void ConfigureTenantVisibilityRoleRule(EntityTypeBuilder<TenantVisibilityRoleRule> builder)
    {
        builder.ToTable("tenant_visibility_role_rules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.QuotaVisibleRoleCodes).HasColumnType("text[]");
        builder.Property(x => x.BillingVisibleRoleCodes).HasColumnType("text[]");
        builder.Property(x => x.UpdatedBy).IsRequired();
        builder.Property(x => x.UpdatedAt).IsRequired();
        builder.HasIndex(x => x.TenantId).IsUnique();
    }

    private static void ConfigureTenantInvoiceSetting(EntityTypeBuilder<TenantInvoiceSetting> builder)
    {
        builder.ToTable("finance_invoice_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.CompanyName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.TaxpayerNumber).HasMaxLength(64).IsRequired();
        builder.Property(x => x.RegisteredAddress).HasMaxLength(256);
        builder.Property(x => x.RegisteredPhone).HasMaxLength(32);
        builder.Property(x => x.BankName).HasMaxLength(128);
        builder.Property(x => x.BankAccount).HasMaxLength(64);
        builder.Property(x => x.EnableElectronicNormalInvoice).IsRequired();
        builder.Property(x => x.EnableElectronicSpecialInvoice).IsRequired();
        builder.Property(x => x.EnableAutoIssue).IsRequired();
        builder.Property(x => x.AutoIssueMaxAmount).HasPrecision(18, 2).IsRequired();

        builder.HasIndex(x => x.TenantId).IsUnique();
    }

    private static void ConfigureTenantInvoiceRecord(EntityTypeBuilder<TenantInvoiceRecord> builder)
    {
        builder.ToTable("finance_invoice_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.InvoiceNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ApplicantName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.CompanyName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.TaxpayerNumber).HasMaxLength(64);
        builder.Property(x => x.InvoiceType).HasConversion<int>().IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.OrderNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ContactEmail).HasMaxLength(128);
        builder.Property(x => x.ContactPhone).HasMaxLength(32);
        builder.Property(x => x.ApplyRemark).HasMaxLength(256);
        builder.Property(x => x.Status).HasConversion<int>().IsRequired();
        builder.Property(x => x.AppliedAt).IsRequired();
        builder.Property(x => x.IssueRemark).HasMaxLength(256);
        builder.Property(x => x.VoidReason).HasMaxLength(256);

        builder.HasIndex(x => new { x.TenantId, x.InvoiceNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.OrderNo });
        builder.HasIndex(x => new { x.TenantId, x.Status, x.AppliedAt });
        builder.HasIndex(x => new { x.TenantId, x.Status, x.IssuedAt });
        builder.HasIndex(x => new { x.TenantId, x.InvoiceType, x.AppliedAt });
    }

    private static void ConfigureFinanceBusinessReportSnapshot(EntityTypeBuilder<FinanceBusinessReportSnapshot> builder)
    {
        builder.ToTable("finance_business_report_snapshots");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.PeriodType).HasConversion<int>().IsRequired();
        builder.Property(x => x.PeriodStartAt).IsRequired();
        builder.Property(x => x.PeriodEndAt).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>().IsRequired();
        builder.Property(x => x.RevenueAmount).HasPrecision(18, 2);
        builder.Property(x => x.OrderCount).IsRequired();
        builder.Property(x => x.AverageOrderValue).HasPrecision(18, 2);
        builder.Property(x => x.RefundRate).HasPrecision(9, 4);
        builder.Property(x => x.CostTotalAmount).HasPrecision(18, 2);
        builder.Property(x => x.NetProfitAmount).HasPrecision(18, 2);
        builder.Property(x => x.ProfitRate).HasPrecision(9, 4);
        builder.Property(x => x.KpiComparisonJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.IncomeBreakdownJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.CostBreakdownJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.LastError).HasMaxLength(1024);
        builder.Property(x => x.HangfireJobId).HasMaxLength(64);
        builder.Property(x => x.RetryCount).HasDefaultValue(0);

        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PeriodType, x.PeriodStartAt }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PeriodType, x.Status, x.PeriodStartAt });
        builder.HasIndex(x => new { x.TenantId, x.Status, x.CreatedAt });
    }

    private static void ConfigureFinanceCostProfile(EntityTypeBuilder<FinanceCostProfile> builder)
    {
        builder.ToTable("finance_cost_profiles");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Category).HasConversion<int>().IsRequired();
        builder.Property(x => x.CalcMode).HasConversion<int>().IsRequired();
        builder.Property(x => x.Ratio).HasPrecision(9, 6).IsRequired();
        builder.Property(x => x.FixedDailyAmount).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.EffectiveFrom).IsRequired();
        builder.Property(x => x.EffectiveTo);
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.Property(x => x.SortOrder).HasDefaultValue(100);

        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Category, x.EffectiveFrom, x.EffectiveTo });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.IsEnabled, x.SortOrder });
    }

    private static void ConfigureFinanceCostDailyOverride(EntityTypeBuilder<FinanceCostDailyOverride> builder)
    {
        builder.ToTable("finance_cost_daily_overrides");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.BusinessDate).IsRequired();
        builder.Property(x => x.Category).HasConversion<int>().IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.Remark).HasMaxLength(256);

        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.BusinessDate, x.Category }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.BusinessDate });
    }
    private static void ConfigureFinanceCostEntry(EntityTypeBuilder<FinanceCostEntry> builder)
    {
        builder.ToTable("finance_cost_entries");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.Dimension).HasConversion<int>().IsRequired();
        builder.Property(x => x.StoreId);
        builder.Property(x => x.CostMonth).IsRequired();
        builder.Property(x => x.Category).HasConversion<int>().IsRequired();
        builder.Property(x => x.TotalAmount).HasPrecision(18, 2);

        builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth, x.Category }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth });
    }

    private static void ConfigureFinanceCostEntryItem(EntityTypeBuilder<FinanceCostEntryItem> builder)
    {
        builder.ToTable("finance_cost_entry_items");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.EntryId).IsRequired();
        builder.Property(x => x.Dimension).HasConversion<int>().IsRequired();
        builder.Property(x => x.StoreId);
        builder.Property(x => x.CostMonth).IsRequired();
        builder.Property(x => x.Category).HasConversion<int>().IsRequired();
        builder.Property(x => x.ItemName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2);
        builder.Property(x => x.Quantity).HasPrecision(18, 2);
        builder.Property(x => x.UnitPrice).HasPrecision(18, 2);
        builder.Property(x => x.SortOrder).HasDefaultValue(100);

        builder.HasOne<FinanceCostEntry>()
            .WithMany()
            .HasForeignKey(x => x.EntryId)
            .OnDelete(DeleteBehavior.Cascade);

        builder.HasIndex(x => x.EntryId);
        builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth, x.Category, x.SortOrder });
    }

    private static void ConfigureTenantAnnouncement(EntityTypeBuilder<TenantAnnouncement> builder)
    {
        builder.ToTable("tenant_announcements");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.Title).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Content).HasColumnType("text").IsRequired();
        builder.Property(x => x.AnnouncementType)
            .HasConversion<int>();
        builder.Property(x => x.PublisherScope)
            .HasConversion<int>();
        builder.Property(x => x.PublisherUserId);
        builder.Property(x => x.Status)
            .HasConversion<int>();
        builder.Property(x => x.PublishedAt);
        builder.Property(x => x.RevokedAt);
        builder.Property(x => x.ScheduledPublishAt);
        builder.Property(x => x.TargetType).HasMaxLength(64).IsRequired();
        builder.Property(x => x.TargetParameters).HasColumnType("text");
        builder.Property(x => x.Priority).IsRequired();
        builder.Property<bool>("IsActive").IsRequired();
        builder.Property(x => x.RowVersion)
            .IsRowVersion()
            .IsConcurrencyToken()
            .HasColumnType("bytea");
        ConfigureAuditableEntity(builder);
        ConfigureSoftDeleteEntity(builder);
        builder.HasIndex("TenantId", "AnnouncementType", "IsActive");
        builder.HasIndex(x => new { x.TenantId, x.EffectiveFrom, x.EffectiveTo });
        builder.HasIndex(x => new { x.TenantId, x.Status, x.EffectiveFrom });
        builder.HasIndex(x => new { x.Status, x.EffectiveFrom })
            .HasFilter("\"TenantId\" = 0");
    }

    private static void ConfigureTenantAnnouncementRead(EntityTypeBuilder<TenantAnnouncementRead> builder)
    {
        builder.ToTable("tenant_announcement_reads");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.AnnouncementId).IsRequired();
        builder.Property(x => x.UserId);
        builder.Property(x => x.ReadAt).IsRequired();
        ConfigureAuditableEntity(builder);
        ConfigureSoftDeleteEntity(builder);
        builder.HasIndex(x => new { x.TenantId, x.AnnouncementId, x.UserId }).IsUnique();
    }

    private static void ConfigureMerchantDocument(EntityTypeBuilder<MerchantDocument> builder)
    {
        builder.ToTable("merchant_documents");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MerchantId).IsRequired();
        builder.Property(x => x.DocumentType).HasConversion<int>();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.FileUrl).HasMaxLength(512).IsRequired();
        builder.Property(x => x.DocumentNumber).HasMaxLength(64);
        builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.DocumentType });
    }

    private static void ConfigureMerchantContract(EntityTypeBuilder<MerchantContract> builder)
    {
        builder.ToTable("merchant_contracts");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MerchantId).IsRequired();
        builder.Property(x => x.ContractNumber).HasMaxLength(64).IsRequired();
        builder.Property(x => x.FileUrl).HasMaxLength(512).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.TerminationReason).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.ContractNumber }).IsUnique();
    }

    private static void ConfigureMerchantStaff(EntityTypeBuilder<MerchantStaff> builder)
    {
        builder.ToTable("merchant_staff");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MerchantId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Phone).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Email).HasMaxLength(128);
        builder.Property(x => x.RoleType).HasConversion<int>();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.PermissionsJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.MerchantId, x.Phone });
    }

    private static void ConfigureMerchantCategory(EntityTypeBuilder<MerchantCategory> builder)
    {
        builder.ToTable("merchant_categories");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.DisplayOrder).HasDefaultValue(0);
        builder.Property(x => x.IsActive).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.Name }).IsUnique();
    }

    private static void ConfigureStoreBusinessHour(EntityTypeBuilder<StoreBusinessHour> builder)
    {
        builder.ToTable("store_business_hours");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.HourType).HasConversion<int>();
        builder.Property(x => x.Notes).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.DayOfWeek });
    }

    private static void ConfigureStoreHoliday(EntityTypeBuilder<StoreHoliday> builder)
    {
        builder.ToTable("store_holidays");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Date).IsRequired();
        builder.Property(x => x.EndDate);
        builder.Property(x => x.IsAllDay).HasDefaultValue(true);
        builder.Property(x => x.StartTime);
        builder.Property(x => x.EndTime);
        builder.Property(x => x.OverrideType).HasDefaultValue(OverrideType.Closed);
        builder.Property(x => x.IsClosed).HasDefaultValue(true);
        builder.Property(x => x.Reason).HasMaxLength(200);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Date });
    }

    private static void ConfigureStoreDeliveryZone(EntityTypeBuilder<StoreDeliveryZone> builder)
    {
        builder.ToTable("store_delivery_zones");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ZoneName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.PolygonGeoJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.MinimumOrderAmount).HasPrecision(18, 2);
        builder.Property(x => x.DeliveryFee).HasPrecision(18, 2);
        builder.Property(x => x.Color).HasMaxLength(32);
        builder.Property(x => x.Priority).HasDefaultValue(100);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ZoneName });
    }

    private static void ConfigureStoreDeliverySetting(EntityTypeBuilder<StoreDeliverySetting> builder)
    {
        builder.ToTable("store_delivery_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Mode).HasConversion<int>();
        builder.Property(x => x.FreeDeliveryThreshold).HasPrecision(10, 2);
        builder.Property(x => x.MaxDeliveryDistance).HasPrecision(10, 2);
        builder.Property(x => x.RadiusTiersJson).HasColumnType("text");
        builder.Property(x => x.RadiusCenterLatitude).HasPrecision(10, 7);
        builder.Property(x => x.RadiusCenterLongitude).HasPrecision(10, 7);
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureStoreDineInSetting(EntityTypeBuilder<StoreDineInSetting> builder)
    {
        builder.ToTable("store_dinein_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Enabled).HasDefaultValue(true);
        builder.Property(x => x.DefaultDiningMinutes).HasDefaultValue(90);
        builder.Property(x => x.OvertimeReminderMinutes).HasDefaultValue(10);
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureStoreTableArea(EntityTypeBuilder<StoreTableArea> builder)
    {
        builder.ToTable("store_table_areas");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }).IsUnique();
    }

    private static void ConfigureStoreTable(EntityTypeBuilder<StoreTable> builder)
    {
        builder.ToTable("store_tables");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.TableCode).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Tags).HasMaxLength(128);
        builder.Property(x => x.QrCodeUrl).HasMaxLength(512);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TableCode }).IsUnique();
    }

    private static void ConfigureStoreEmployeeShift(EntityTypeBuilder<StoreEmployeeShift> builder)
    {
        builder.ToTable("store_employee_shifts");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.StaffId).IsRequired();
        builder.Property(x => x.RoleType).HasConversion<int>();
        builder.Property(x => x.Notes).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ShiftDate, x.StaffId }).IsUnique();
    }

    private static void ConfigureStorePickupSetting(EntityTypeBuilder<StorePickupSetting> builder)
    {
        builder.ToTable("store_pickup_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.DefaultCutoffMinutes).HasDefaultValue(30);
        builder.Property(x => x.Mode).HasConversion<int>();
        builder.Property(x => x.FineRuleJson).HasColumnType("text");
        builder.Property(x => x.RowVersion)
            .IsRequired()
            .IsConcurrencyToken()
            .ValueGeneratedNever();
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureStorePickupSlot(EntityTypeBuilder<StorePickupSlot> builder)
    {
        builder.ToTable("store_pickup_slots");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Weekdays).HasMaxLength(32).IsRequired();
        builder.Property(x => x.CutoffMinutes).HasDefaultValue(30);
        builder.Property(x => x.RowVersion)
            .IsRequired()
            .IsConcurrencyToken()
            .ValueGeneratedNever();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name });
    }

    private static void ConfigureStoreStaffTemplate(EntityTypeBuilder<StoreStaffTemplate> builder)
    {
        builder.ToTable("store_staff_templates");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.MorningStartTime).IsRequired();
        builder.Property(x => x.MorningEndTime).IsRequired();
        builder.Property(x => x.EveningStartTime).IsRequired();
        builder.Property(x => x.EveningEndTime).IsRequired();
        builder.Property(x => x.FullStartTime).IsRequired();
        builder.Property(x => x.FullEndTime).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureStoreStaffWeeklySchedule(EntityTypeBuilder<StoreStaffWeeklySchedule> builder)
    {
        builder.ToTable("store_staff_weekly_schedules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.StaffId).IsRequired();
        builder.Property(x => x.DayOfWeek).IsRequired();
        builder.Property(x => x.ShiftType).HasConversion<int>();
        builder.Property(x => x.StartTime);
        builder.Property(x => x.EndTime);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.StaffId, x.DayOfWeek }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.DayOfWeek });
    }

    private static void ConfigureProductAttributeGroup(EntityTypeBuilder<ProductAttributeGroup> builder)
    {
        builder.ToTable("product_attribute_groups");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.SelectionType).HasConversion<int>();
        builder.Property(x => x.StoreId);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name });
    }

    private static void ConfigureProductAttributeOption(EntityTypeBuilder<ProductAttributeOption> builder)
    {
        builder.ToTable("product_attribute_options");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.AttributeGroupId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.ExtraPrice).HasPrecision(18, 2);
        builder.HasIndex(x => new { x.TenantId, x.AttributeGroupId, x.Name }).IsUnique();
    }

    private static void ConfigureProductSpecTemplate(EntityTypeBuilder<ProductSpecTemplate> builder)
    {
        builder.ToTable("product_spec_templates");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(256).IsRequired();
        builder.Property(x => x.TemplateType).HasConversion<int>();
        builder.Property(x => x.SelectionType).HasConversion<int>();
        builder.Property(x => x.MinSelect).IsRequired();
        builder.Property(x => x.MaxSelect).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.Property(x => x.IsRequired).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TemplateType, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TemplateType, x.IsEnabled });
    }

    private static void ConfigureProductSpecTemplateOption(EntityTypeBuilder<ProductSpecTemplateOption> builder)
    {
        builder.ToTable("product_spec_template_options");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TemplateId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.ExtraPrice).HasPrecision(18, 2);
        builder.Property(x => x.Stock).IsRequired();
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.TemplateId, x.Name }).IsUnique();
    }

    private static void ConfigureProductSpecTemplateProduct(EntityTypeBuilder<ProductSpecTemplateProduct> builder)
    {
        builder.ToTable("product_spec_template_products");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.TemplateId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TemplateId, x.ProductId }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductId });
    }

    private static void ConfigureProductLabel(EntityTypeBuilder<ProductLabel> builder)
    {
        builder.ToTable("product_labels");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Color).HasMaxLength(32).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.IsEnabled, x.SortOrder });
    }

    private static void ConfigureProductLabelProduct(EntityTypeBuilder<ProductLabelProduct> builder)
    {
        builder.ToTable("product_label_products");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.LabelId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.LabelId, x.ProductId }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductId });
    }

    private static void ConfigureProductSchedule(EntityTypeBuilder<ProductSchedule> builder)
    {
        builder.ToTable("product_schedules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.StartTime).IsRequired();
        builder.Property(x => x.EndTime).IsRequired();
        builder.Property(x => x.WeekDaysMask).IsRequired();
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.IsEnabled });
    }

    private static void ConfigureProductScheduleProduct(EntityTypeBuilder<ProductScheduleProduct> builder)
    {
        builder.ToTable("product_schedule_products");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ScheduleId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ScheduleId, x.ProductId }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductId });
    }

    private static void ConfigureProductSku(EntityTypeBuilder<ProductSku> builder)
    {
        builder.ToTable("product_skus");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.SkuCode).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Barcode).HasMaxLength(64);
        builder.Property(x => x.Price).HasPrecision(18, 2);
        builder.Property(x => x.OriginalPrice).HasPrecision(18, 2);
        builder.Property(x => x.Weight).HasPrecision(10, 3);
        builder.Property(x => x.AttributesJson).HasColumnType("text");
        builder.Property(x => x.IsEnabled).HasDefaultValue(true);
        builder.HasIndex(x => new { x.TenantId, x.ProductId });
        builder.HasIndex(x => new { x.TenantId, x.SkuCode }).IsUnique();
    }

    private static void ConfigureProductSkuSaveJob(EntityTypeBuilder<ProductSkuSaveJob> builder)
    {
        builder.ToTable("product_sku_save_jobs");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.Mode).HasMaxLength(16).IsRequired();
        builder.Property(x => x.PayloadJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.ProgressTotal).IsRequired();
        builder.Property(x => x.ProgressProcessed).IsRequired();
        builder.Property(x => x.FailedCount).IsRequired();
        builder.Property(x => x.ErrorMessage).HasMaxLength(2000);
        builder.Property(x => x.HangfireJobId).HasMaxLength(64);
        builder.HasIndex(x => new { x.TenantId, x.ProductId, x.CreatedAt });
        builder.HasIndex(x => new { x.TenantId, x.Status, x.CreatedAt });
    }

    private static void ConfigureProductComboGroup(EntityTypeBuilder<ProductComboGroup> builder)
    {
        builder.ToTable("product_combo_groups");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.MinSelect).IsRequired();
        builder.Property(x => x.MaxSelect).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.ProductId, x.SortOrder });
        builder.HasIndex(x => new { x.TenantId, x.ProductId, x.Name });
    }

    private static void ConfigureProductComboGroupItem(EntityTypeBuilder<ProductComboGroupItem> builder)
    {
        builder.ToTable("product_combo_group_items");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ComboGroupId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.Quantity).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.ComboGroupId, x.SortOrder });
        builder.HasIndex(x => new { x.TenantId, x.ComboGroupId, x.ProductId }).IsUnique();
    }

    private static void ConfigureProductAddonGroup(EntityTypeBuilder<ProductAddonGroup> builder)
    {
        builder.ToTable("product_addon_groups");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.SelectionType).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.ProductId, x.Name });
    }

    private static void ConfigureProductAddonOption(EntityTypeBuilder<ProductAddonOption> builder)
    {
        builder.ToTable("product_addon_options");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.AddonGroupId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.ExtraPrice).HasPrecision(18, 2);
    }

    private static void ConfigureProductPricingRule(EntityTypeBuilder<ProductPricingRule> builder)
    {
        builder.ToTable("product_pricing_rules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.RuleType).HasConversion<int>();
        builder.Property(x => x.ConditionsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.Price).HasPrecision(18, 2);
        builder.Property(x => x.WeekdaysJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.ProductId, x.RuleType });
    }

    private static void ConfigureProductMediaAsset(EntityTypeBuilder<ProductMediaAsset> builder)
    {
        builder.ToTable("product_media_assets");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.MediaType).HasConversion<int>();
        builder.Property(x => x.Url).HasMaxLength(512).IsRequired();
        builder.Property(x => x.Caption).HasMaxLength(256);
    }

    private static void ConfigureInventoryItem(EntityTypeBuilder<InventoryItem> builder)
    {
        builder.ToTable("inventory_items");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ProductSkuId).IsRequired();
        builder.Property(x => x.BatchNumber).HasMaxLength(64);
        builder.Property(x => x.Location).HasMaxLength(64);
        builder.Property(x => x.RowVersion)
            .IsConcurrencyToken();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.BatchNumber });
    }

    private static void ConfigureInventoryAdjustment(EntityTypeBuilder<InventoryAdjustment> builder)
    {
        builder.ToTable("inventory_adjustments");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.InventoryItemId).IsRequired();
        builder.Property(x => x.AdjustmentType).HasConversion<int>();
        builder.Property(x => x.Reason).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.InventoryItemId, x.OccurredAt });
    }

    private static void ConfigureInventoryBatch(EntityTypeBuilder<InventoryBatch> builder)
    {
        builder.ToTable("inventory_batches");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ProductSkuId).IsRequired();
        builder.Property(x => x.BatchNumber).HasMaxLength(64).IsRequired();
        builder.Property(x => x.RowVersion)
            .IsConcurrencyToken();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.BatchNumber }).IsUnique();
    }

    private static void ConfigureInventoryLockRecord(EntityTypeBuilder<InventoryLockRecord> builder)
    {
        builder.ToTable("inventory_lock_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.ProductSkuId).IsRequired();
        builder.Property(x => x.Quantity).IsRequired();
        builder.Property(x => x.IdempotencyKey).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.RowVersion)
            .IsConcurrencyToken();
        builder.HasIndex(x => new { x.TenantId, x.IdempotencyKey }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.Status });
    }

    private static void ConfigureShoppingCart(EntityTypeBuilder<ShoppingCart> builder)
    {
        builder.ToTable("shopping_carts");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.UserId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.TableContext).HasMaxLength(64);
        builder.Property(x => x.DeliveryPreference).HasMaxLength(32);
        builder.HasIndex(x => new { x.TenantId, x.UserId, x.StoreId }).IsUnique();
    }

    private static void ConfigureCartItem(EntityTypeBuilder<CartItem> builder)
    {
        builder.ToTable("cart_items");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ShoppingCartId).IsRequired();
        builder.Property(x => x.ProductId).IsRequired();
        builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.UnitPrice).HasPrecision(18, 2);
        builder.Property(x => x.Remark).HasMaxLength(256);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.AttributesJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.ShoppingCartId });
    }

    private static void ConfigureCartItemAddon(EntityTypeBuilder<CartItemAddon> builder)
    {
        builder.ToTable("cart_item_addons");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.CartItemId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.ExtraPrice).HasPrecision(18, 2);
    }

    private static void ConfigureCheckoutSession(EntityTypeBuilder<CheckoutSession> builder)
    {
        builder.ToTable("checkout_sessions");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.UserId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.SessionToken).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.ValidationResultJson).HasColumnType("text").IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.SessionToken }).IsUnique();
    }

    private static void ConfigureOrderStatusHistory(EntityTypeBuilder<OrderStatusHistory> builder)
    {
        builder.ToTable("order_status_histories");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.OrderId).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.Notes).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.OrderId, x.OccurredAt });
    }

    private static void ConfigureRefundRequest(EntityTypeBuilder<RefundRequest> builder)
    {
        builder.ToTable("refund_requests");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.OrderId).IsRequired();
        builder.Property(x => x.RefundNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2);
        builder.Property(x => x.Reason).HasMaxLength(256).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.ReviewNotes).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.RefundNo }).IsUnique();
    }

    private static void ConfigurePaymentRefundRecord(EntityTypeBuilder<PaymentRefundRecord> builder)
    {
        builder.ToTable("payment_refund_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.PaymentRecordId).IsRequired();
        builder.Property(x => x.OrderId).IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2);
        builder.Property(x => x.ChannelRefundId).HasMaxLength(64);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.Payload).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.PaymentRecordId });
    }

    private static void ConfigureDeliveryEvent(EntityTypeBuilder<DeliveryEvent> builder)
    {
        builder.ToTable("delivery_events");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.DeliveryOrderId).IsRequired();
        builder.Property(x => x.EventType).HasConversion<int>();
        builder.Property(x => x.Message).HasMaxLength(256);
        builder.Property(x => x.Payload).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.DeliveryOrderId, x.EventType });
    }

    private static void ConfigureGroupOrder(EntityTypeBuilder<GroupOrder> builder)
    {
        builder.ToTable("group_orders");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.GroupOrderNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.GroupPrice).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.GroupOrderNo }).IsUnique();
    }

    private static void ConfigureGroupParticipant(EntityTypeBuilder<GroupParticipant> builder)
    {
        builder.ToTable("group_participants");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.GroupOrderId).IsRequired();
        builder.Property(x => x.OrderId).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.GroupOrderId, x.UserId }).IsUnique();
    }

    private static void ConfigureCouponTemplate(EntityTypeBuilder<CouponTemplate> builder)
    {
        builder.ToTable("coupon_templates");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.CouponType).HasConversion<int>();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.TotalQuantity);
        builder.Property(x => x.PerUserLimit);
        builder.Property(x => x.StoreScopeJson).HasColumnType("text");
        builder.Property(x => x.ProductScopeJson).HasColumnType("text");
        builder.Property(x => x.ChannelsJson).HasColumnType("text");
        builder.Property(x => x.Status).HasConversion<int>();
    }

    private static void ConfigureCoupon(EntityTypeBuilder<Coupon> builder)
    {
        builder.ToTable("coupons");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.CouponTemplateId).IsRequired();
        builder.Property(x => x.Code).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
    }

    private static void ConfigurePromotionCampaign(EntityTypeBuilder<PromotionCampaign> builder)
    {
        builder.ToTable("promotion_campaigns");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.PromotionType).HasConversion<int>();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.RulesJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.AudienceDescription).HasMaxLength(512);
        builder.Property(x => x.BannerUrl).HasMaxLength(512);
    }

    private static void ConfigureNewCustomerGiftSetting(EntityTypeBuilder<NewCustomerGiftSetting> builder)
    {
        builder.ToTable("new_customer_gift_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.GiftType).HasConversion<int>();
        builder.Property(x => x.DirectReduceAmount).HasPrecision(18, 2);
        builder.Property(x => x.DirectMinimumSpend).HasPrecision(18, 2);
        builder.Property(x => x.ShareChannelsJson).HasColumnType("text").IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureNewCustomerCouponRule(EntityTypeBuilder<NewCustomerCouponRule> builder)
    {
        builder.ToTable("new_customer_coupon_rules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Scene).HasConversion<int>();
        builder.Property(x => x.CouponType).HasConversion<int>();
        builder.Property(x => x.Value).HasPrecision(18, 2);
        builder.Property(x => x.MinimumSpend).HasPrecision(18, 2);
        builder.Property(x => x.ValidDays).IsRequired();
        builder.Property(x => x.SortOrder).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Scene, x.SortOrder });
    }

    private static void ConfigureNewCustomerInviteRecord(EntityTypeBuilder<NewCustomerInviteRecord> builder)
    {
        builder.ToTable("new_customer_invite_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.InviterName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.InviteeName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.InviteTime).IsRequired();
        builder.Property(x => x.OrderStatus).HasConversion<int>();
        builder.Property(x => x.RewardStatus).HasConversion<int>();
        builder.Property(x => x.SourceChannel).HasMaxLength(32);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.InviteTime });
    }

    private static void ConfigureNewCustomerGrowthRecord(EntityTypeBuilder<NewCustomerGrowthRecord> builder)
    {
        builder.ToTable("new_customer_growth_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.CustomerKey).HasMaxLength(64).IsRequired();
        builder.Property(x => x.CustomerName).HasMaxLength(64);
        builder.Property(x => x.RegisteredAt).IsRequired();
        builder.Property(x => x.SourceChannel).HasMaxLength(32);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.CustomerKey }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RegisteredAt });
    }

    private static void ConfigurePunchCardTemplate(EntityTypeBuilder<PunchCardTemplate> builder)
    {
        builder.ToTable("punch_card_templates");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.CoverImageUrl).HasMaxLength(512);
        builder.Property(x => x.SalePrice).HasPrecision(18, 2);
        builder.Property(x => x.OriginalPrice).HasPrecision(18, 2);
        builder.Property(x => x.TotalTimes).IsRequired();
        builder.Property(x => x.ValidityType).HasConversion<int>();
        builder.Property(x => x.ValidityDays);
        builder.Property(x => x.ValidFrom);
        builder.Property(x => x.ValidTo);
        builder.Property(x => x.ScopeType).HasConversion<int>();
        builder.Property(x => x.ScopeCategoryIdsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.ScopeTagIdsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.ScopeProductIdsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.UsageMode).HasConversion<int>();
        builder.Property(x => x.UsageCapAmount).HasPrecision(18, 2);
        builder.Property(x => x.DailyLimit);
        builder.Property(x => x.PerOrderLimit);
        builder.Property(x => x.PerUserPurchaseLimit);
        builder.Property(x => x.AllowTransfer).IsRequired();
        builder.Property(x => x.ExpireStrategy).HasConversion<int>();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.NotifyChannelsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status });
    }

    private static void ConfigurePunchCardInstance(EntityTypeBuilder<PunchCardInstance> builder)
    {
        builder.ToTable("punch_card_instances");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.PunchCardTemplateId).IsRequired();
        builder.Property(x => x.InstanceNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.MemberName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.MemberPhoneMasked).HasMaxLength(32).IsRequired();
        builder.Property(x => x.PurchasedAt).IsRequired();
        builder.Property(x => x.ExpiresAt);
        builder.Property(x => x.TotalTimes).IsRequired();
        builder.Property(x => x.RemainingTimes).IsRequired();
        builder.Property(x => x.PaidAmount).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.InstanceNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PunchCardTemplateId });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status, x.ExpiresAt });
    }

    private static void ConfigurePunchCardUsageRecord(EntityTypeBuilder<PunchCardUsageRecord> builder)
    {
        builder.ToTable("punch_card_usage_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.PunchCardTemplateId).IsRequired();
        builder.Property(x => x.PunchCardInstanceId).IsRequired();
        builder.Property(x => x.RecordNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.UsedAt).IsRequired();
        builder.Property(x => x.UsedTimes).IsRequired();
        builder.Property(x => x.RemainingTimesAfterUse).IsRequired();
        builder.Property(x => x.StatusAfterUse).HasConversion<int>();
        builder.Property(x => x.ExtraPayAmount).HasPrecision(18, 2);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RecordNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PunchCardTemplateId, x.UsedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PunchCardInstanceId, x.UsedAt });
    }

    private static void ConfigureMemberProfile(EntityTypeBuilder<MemberProfile> builder)
    {
        builder.ToTable("member_profiles");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Mobile).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Nickname).HasMaxLength(64);
        builder.Property(x => x.AvatarUrl).HasMaxLength(256);
        builder.Property(x => x.StoredBalance).HasPrecision(18, 2);
        builder.Property(x => x.StoredRechargeBalance).HasPrecision(18, 2);
        builder.Property(x => x.StoredGiftBalance).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.Mobile }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.MemberTierId });
    }

    private static void ConfigureMemberTier(EntityTypeBuilder<MemberTier> builder)
    {
        builder.ToTable("member_tiers");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.IconKey).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ColorHex).HasMaxLength(16).IsRequired();
        builder.Property(x => x.UpgradeRuleType).HasMaxLength(16).IsRequired();
        builder.Property(x => x.UpgradeAmountThreshold).HasPrecision(18, 2);
        builder.Property(x => x.BenefitsJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.SortOrder });
    }

    private static void ConfigureMemberProfileTag(EntityTypeBuilder<MemberProfileTag> builder)
    {
        builder.ToTable("member_profile_tags");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MemberProfileId).IsRequired();
        builder.Property(x => x.TagName).HasMaxLength(32).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.MemberProfileId, x.TagName }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.MemberProfileId });
    }

    private static void ConfigureMemberDaySetting(EntityTypeBuilder<MemberDaySetting> builder)
    {
        builder.ToTable("member_day_settings");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.IsEnabled).IsRequired();
        builder.Property(x => x.Weekday).IsRequired();
        builder.Property(x => x.ExtraDiscountRate).HasPrecision(5, 2);
        builder.HasIndex(x => x.TenantId).IsUnique();
    }

    private static void ConfigureMemberPointLedger(EntityTypeBuilder<MemberPointLedger> builder)
    {
        builder.ToTable("member_point_ledgers");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MemberId).IsRequired();
        builder.Property(x => x.Reason).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.MemberId, x.OccurredAt });
    }

    private static void ConfigureMemberPointMallRule(EntityTypeBuilder<MemberPointMallRule> builder)
    {
        builder.ToTable("member_point_mall_rules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.IsConsumeRewardEnabled).IsRequired();
        builder.Property(x => x.ConsumeAmountPerStep).IsRequired();
        builder.Property(x => x.ConsumeRewardPointsPerStep).IsRequired();
        builder.Property(x => x.IsReviewRewardEnabled).IsRequired();
        builder.Property(x => x.ReviewRewardPoints).IsRequired();
        builder.Property(x => x.IsRegisterRewardEnabled).IsRequired();
        builder.Property(x => x.RegisterRewardPoints).IsRequired();
        builder.Property(x => x.IsSigninRewardEnabled).IsRequired();
        builder.Property(x => x.SigninRewardPoints).IsRequired();
        builder.Property(x => x.ExpiryMode).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.StoreId }).IsUnique();
    }

    private static void ConfigureMemberPointMallProduct(EntityTypeBuilder<MemberPointMallProduct> builder)
    {
        builder.ToTable("member_point_mall_products");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.ImageUrl).HasMaxLength(512);
        builder.Property(x => x.RedeemType).HasConversion<int>();
        builder.Property(x => x.ProductId);
        builder.Property(x => x.CouponTemplateId);
        builder.Property(x => x.PhysicalName).HasMaxLength(64);
        builder.Property(x => x.PickupMethod).HasConversion<int?>();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.ExchangeType).HasConversion<int>();
        builder.Property(x => x.RequiredPoints).IsRequired();
        builder.Property(x => x.CashAmount).HasPrecision(18, 2);
        builder.Property(x => x.StockTotal).IsRequired();
        builder.Property(x => x.StockAvailable).IsRequired();
        builder.Property(x => x.PerMemberLimit);
        builder.Property(x => x.NotifyChannelsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductId });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.CouponTemplateId });
    }

    private static void ConfigureMemberPointMallRecord(EntityTypeBuilder<MemberPointMallRecord> builder)
    {
        builder.ToTable("member_point_mall_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.RecordNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.PointMallProductId).IsRequired();
        builder.Property(x => x.MemberId).IsRequired();
        builder.Property(x => x.MemberName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.MemberMobileMasked).HasMaxLength(32).IsRequired();
        builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired();
        builder.Property(x => x.RedeemType).HasConversion<int>();
        builder.Property(x => x.ExchangeType).HasConversion<int>();
        builder.Property(x => x.UsedPoints).IsRequired();
        builder.Property(x => x.CashAmount).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.RedeemedAt).IsRequired();
        builder.Property(x => x.IssuedAt);
        builder.Property(x => x.VerifiedAt);
        builder.Property(x => x.VerifyMethod).HasConversion<int?>();
        builder.Property(x => x.VerifyRemark).HasMaxLength(256);
        builder.Property(x => x.VerifiedBy);
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RecordNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PointMallProductId, x.RedeemedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.MemberId, x.RedeemedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status, x.RedeemedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RedeemedAt });
    }

    private static void ConfigureMemberStoredCardPlan(EntityTypeBuilder<MemberStoredCardPlan> builder)
    {
        builder.ToTable("member_stored_card_plans");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.RechargeAmount).HasPrecision(18, 2);
        builder.Property(x => x.GiftAmount).HasPrecision(18, 2);
        builder.Property(x => x.SortOrder).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RechargeAmount, x.GiftAmount }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.SortOrder });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status });
    }

    private static void ConfigureMemberStoredCardRechargeRecord(EntityTypeBuilder<MemberStoredCardRechargeRecord> builder)
    {
        builder.ToTable("member_stored_card_recharge_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.MemberId).IsRequired();
        builder.Property(x => x.PlanId);
        builder.Property(x => x.RecordNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.MemberName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.MemberMobileMasked).HasMaxLength(32).IsRequired();
        builder.Property(x => x.RechargeAmount).HasPrecision(18, 2);
        builder.Property(x => x.GiftAmount).HasPrecision(18, 2);
        builder.Property(x => x.ArrivedAmount).HasPrecision(18, 2);
        builder.Property(x => x.PaymentMethod).HasConversion<int>();
        builder.Property(x => x.Remark).HasMaxLength(256);
        builder.Property(x => x.RechargedAt).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RecordNo }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.MemberId, x.RechargedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PlanId, x.RechargedAt });
        builder.HasIndex(x => new { x.TenantId, x.StoreId, x.RechargedAt });
    }

    private static void ConfigureMemberReachMessage(EntityTypeBuilder<MemberReachMessage> builder)
    {
        builder.ToTable("member_reach_messages");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.StoreId);
        builder.Property(x => x.TemplateId);
        builder.Property(x => x.Title).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Content).HasColumnType("text").IsRequired();
        builder.Property(x => x.ChannelsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.AudienceType).HasConversion<int>();
        builder.Property(x => x.AudienceTagsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.EstimatedReachCount).IsRequired();
        builder.Property(x => x.ScheduleType).HasConversion<int>();
        builder.Property(x => x.ScheduledAt);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.SentAt);
        builder.Property(x => x.SentCount).IsRequired();
        builder.Property(x => x.ReadCount).IsRequired();
        builder.Property(x => x.ConvertedCount).IsRequired();
        builder.Property(x => x.HangfireJobId).HasMaxLength(64);
        builder.Property(x => x.LastError).HasMaxLength(1024);
        builder.HasIndex(x => new { x.TenantId, x.Status, x.ScheduledAt });
        builder.HasIndex(x => new { x.TenantId, x.CreatedAt });
    }

    private static void ConfigureMemberMessageTemplate(EntityTypeBuilder<MemberMessageTemplate> builder)
    {
        builder.ToTable("member_message_templates");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Category).HasConversion<int>();
        builder.Property(x => x.Content).HasColumnType("text").IsRequired();
        builder.Property(x => x.UsageCount).IsRequired();
        builder.Property(x => x.LastUsedAt);
        builder.HasIndex(x => new { x.TenantId, x.Name }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.Category, x.UsageCount });
    }

    private static void ConfigureMemberReachRecipient(EntityTypeBuilder<MemberReachRecipient> builder)
    {
        builder.ToTable("member_reach_recipients");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MessageId).IsRequired();
        builder.Property(x => x.MemberId).IsRequired();
        builder.Property(x => x.Channel).HasConversion<int>();
        builder.Property(x => x.Mobile).HasMaxLength(32);
        builder.Property(x => x.OpenId).HasMaxLength(128);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.SentAt);
        builder.Property(x => x.ReadAt);
        builder.Property(x => x.ConvertedAt);
        builder.Property(x => x.ErrorMessage).HasMaxLength(512);
        builder.HasIndex(x => new { x.TenantId, x.MessageId, x.MemberId, x.Channel }).IsUnique();
        builder.HasIndex(x => new { x.TenantId, x.MessageId, x.Status });
    }

    private static void ConfigureChatSession(EntityTypeBuilder<ChatSession> builder)
    {
        builder.ToTable("chat_sessions");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.SessionCode).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.SessionCode }).IsUnique();
    }

    private static void ConfigureChatMessage(EntityTypeBuilder<ChatMessage> builder)
    {
        builder.ToTable("chat_messages");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.ChatSessionId).IsRequired();
        builder.Property(x => x.SenderType).HasConversion<int>();
        builder.Property(x => x.ContentType).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Content).HasMaxLength(1024).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.ChatSessionId, x.CreatedAt });
    }

    private static void ConfigureSupportTicket(EntityTypeBuilder<SupportTicket> builder)
    {
        builder.ToTable("support_tickets");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TicketNo).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Subject).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Description).HasColumnType("text").IsRequired();
        builder.Property(x => x.Priority).HasConversion<int>();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.TicketNo }).IsUnique();
    }

    private static void ConfigureTicketComment(EntityTypeBuilder<TicketComment> builder)
    {
        builder.ToTable("ticket_comments");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.SupportTicketId).IsRequired();
        builder.Property(x => x.Content).HasMaxLength(1024).IsRequired();
        builder.Property(x => x.AttachmentsJson).HasColumnType("text");
        builder.HasIndex(x => new { x.TenantId, x.SupportTicketId });
    }

    private static void ConfigureAffiliatePartner(EntityTypeBuilder<AffiliatePartner> builder)
    {
        builder.ToTable("affiliate_partners");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.DisplayName).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Phone).HasMaxLength(32);
        builder.Property(x => x.ChannelType).HasConversion<int>();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.Remarks).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.DisplayName });
    }

    private static void ConfigureAffiliateOrder(EntityTypeBuilder<AffiliateOrder> builder)
    {
        builder.ToTable("affiliate_orders");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.AffiliatePartnerId).IsRequired();
        builder.Property(x => x.OrderId).IsRequired();
        builder.Property(x => x.OrderAmount).HasPrecision(18, 2);
        builder.Property(x => x.EstimatedCommission).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.AffiliatePartnerId, x.OrderId }).IsUnique();
    }

    private static void ConfigureAffiliatePayout(EntityTypeBuilder<AffiliatePayout> builder)
    {
        builder.ToTable("affiliate_payouts");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.AffiliatePartnerId).IsRequired();
        builder.Property(x => x.Period).HasMaxLength(32).IsRequired();
        builder.Property(x => x.Amount).HasPrecision(18, 2);
        builder.Property(x => x.Status).HasConversion<int>();
        builder.Property(x => x.Remarks).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.AffiliatePartnerId, x.Period }).IsUnique();
    }

    private static void ConfigureCheckInCampaign(EntityTypeBuilder<CheckInCampaign> builder)
    {
        builder.ToTable("checkin_campaigns");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.RewardsJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.Name });
    }

    private static void ConfigureCheckInRecord(EntityTypeBuilder<CheckInRecord> builder)
    {
        builder.ToTable("checkin_records");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.CheckInCampaignId).IsRequired();
        builder.Property(x => x.UserId).IsRequired();
        builder.Property(x => x.RewardJson).HasColumnType("text").IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.CheckInCampaignId, x.UserId, x.CheckInDate }).IsUnique();
    }

    private static void ConfigureCommunityPost(EntityTypeBuilder<CommunityPost> builder)
    {
        builder.ToTable("community_posts");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.AuthorUserId).IsRequired();
        builder.Property(x => x.Title).HasMaxLength(128);
        builder.Property(x => x.Content).HasColumnType("text").IsRequired();
        builder.Property(x => x.MediaJson).HasColumnType("text");
        builder.Property(x => x.Status).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.AuthorUserId, x.CreatedAt });
    }

    private static void ConfigureCommunityComment(EntityTypeBuilder<CommunityComment> builder)
    {
        builder.ToTable("community_comments");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.PostId).IsRequired();
        builder.Property(x => x.Content).HasMaxLength(512).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.PostId, x.CreatedAt });
    }

    private static void ConfigureCommunityReaction(EntityTypeBuilder<CommunityReaction> builder)
    {
        builder.ToTable("community_reactions");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.PostId).IsRequired();
        builder.Property(x => x.ReactionType).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.PostId, x.UserId }).IsUnique();
    }

    private static void ConfigureMapLocation(EntityTypeBuilder<MapLocation> builder)
    {
        builder.ToTable("map_locations");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Address).HasMaxLength(256).IsRequired();
        builder.Property(x => x.Landmark).HasMaxLength(128);
        builder.HasIndex(x => new { x.TenantId, x.StoreId });
    }

    private static void ConfigureNavigationRequest(EntityTypeBuilder<NavigationRequest> builder)
    {
        builder.ToTable("navigation_requests");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.UserId).IsRequired();
        builder.Property(x => x.StoreId).IsRequired();
        builder.Property(x => x.Channel).HasConversion<int>();
        builder.Property(x => x.TargetApp).HasConversion<int>();
        builder.HasIndex(x => new { x.TenantId, x.UserId, x.StoreId, x.RequestedAt });
    }

    private static void ConfigureMetricDefinition(EntityTypeBuilder<MetricDefinition> builder)
    {
        builder.ToTable("metric_definitions");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Code).HasMaxLength(64).IsRequired();
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.Property(x => x.DimensionsJson).HasColumnType("text");
        builder.Property(x => x.DefaultAggregation).HasMaxLength(32).IsRequired();
        builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
    }

    private static void ConfigureMetricSnapshot(EntityTypeBuilder<MetricSnapshot> builder)
    {
        builder.ToTable("metric_snapshots");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MetricDefinitionId).IsRequired();
        builder.Property(x => x.DimensionKey).HasMaxLength(256).IsRequired();
        builder.Property(x => x.Value).HasPrecision(18, 4);
        builder.HasIndex(x => new { x.TenantId, x.MetricDefinitionId, x.DimensionKey, x.WindowStart, x.WindowEnd }).IsUnique();
    }

    private static void ConfigureMetricAlertRule(EntityTypeBuilder<MetricAlertRule> builder)
    {
        builder.ToTable("metric_alert_rules");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.MetricDefinitionId).IsRequired();
        builder.Property(x => x.ConditionJson).HasColumnType("text").IsRequired();
        builder.Property(x => x.Severity).HasConversion<int>();
        builder.Property(x => x.NotificationChannels).HasMaxLength(256);
        builder.HasIndex(x => new { x.TenantId, x.MetricDefinitionId, x.Severity });
    }

    private static void ConfigureQuotaPackage(EntityTypeBuilder<QuotaPackage> builder)
    {
        builder.ToTable("quota_packages");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
        builder.Property(x => x.QuotaType).HasConversion<int>().IsRequired();
        builder.Property(x => x.QuotaValue).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.Price).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.IsActive).IsRequired();
        builder.Property(x => x.SortOrder).HasDefaultValue(0);
        builder.Property(x => x.Description).HasMaxLength(512);
        builder.HasIndex(x => new { x.QuotaType, x.IsActive, x.SortOrder });
    }

    private static void ConfigureTenantQuotaPackagePurchase(EntityTypeBuilder<TenantQuotaPackagePurchase> builder)
    {
        builder.ToTable("tenant_quota_package_purchases");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.TenantId).IsRequired();
        builder.Property(x => x.QuotaPackageId).IsRequired();
        builder.Property(x => x.QuotaValue).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.Price).HasPrecision(18, 2).IsRequired();
        builder.Property(x => x.PurchasedAt).IsRequired();
        builder.Property(x => x.Notes).HasMaxLength(512);
        builder.HasIndex(x => new { x.TenantId, x.QuotaPackageId, x.PurchasedAt });
    }
}
