1390 lines
63 KiB
C#
1390 lines
63 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
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.Engagement.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.Tenants.Entities;
|
|
using TakeoutSaaS.Infrastructure.Common.Persistence;
|
|
using TakeoutSaaS.Shared.Abstractions.Ids;
|
|
using TakeoutSaaS.Shared.Abstractions.Security;
|
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
|
|
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<TenantBillingStatement> TenantBillingStatements => Set<TenantBillingStatement>();
|
|
/// <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<TenantAuditLog> TenantAuditLogs => Set<TenantAuditLog>();
|
|
/// <summary>
|
|
/// 租户审核领取记录。
|
|
/// </summary>
|
|
public DbSet<TenantReviewClaim> TenantReviewClaims => Set<TenantReviewClaim>();
|
|
/// <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<MerchantAuditLog> MerchantAuditLogs => Set<MerchantAuditLog>();
|
|
/// <summary>
|
|
/// 商户分类。
|
|
/// </summary>
|
|
public DbSet<MerchantCategory> MerchantCategories => Set<MerchantCategory>();
|
|
/// <summary>
|
|
/// 门店实体。
|
|
/// </summary>
|
|
public DbSet<Store> Stores => Set<Store>();
|
|
/// <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<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<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>
|
|
/// SKU 实体。
|
|
/// </summary>
|
|
public DbSet<ProductSku> ProductSkus => Set<ProductSku>();
|
|
/// <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<MemberProfile> MemberProfiles => Set<MemberProfile>();
|
|
/// <summary>
|
|
/// 会员等级。
|
|
/// </summary>
|
|
public DbSet<MemberTier> MemberTiers => Set<MemberTier>();
|
|
/// <summary>
|
|
/// 积分流水。
|
|
/// </summary>
|
|
public DbSet<MemberPointLedger> MemberPointLedgers => Set<MemberPointLedger>();
|
|
/// <summary>
|
|
/// 成长值日志。
|
|
/// </summary>
|
|
public DbSet<MemberGrowthLog> MemberGrowthLogs => Set<MemberGrowthLog>();
|
|
/// <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>());
|
|
ConfigureTenantBilling(modelBuilder.Entity<TenantBillingStatement>());
|
|
ConfigureTenantNotification(modelBuilder.Entity<TenantNotification>());
|
|
ConfigureTenantAnnouncement(modelBuilder.Entity<TenantAnnouncement>());
|
|
ConfigureTenantAnnouncementRead(modelBuilder.Entity<TenantAnnouncementRead>());
|
|
ConfigureTenantVerificationProfile(modelBuilder.Entity<TenantVerificationProfile>());
|
|
ConfigureTenantAuditLog(modelBuilder.Entity<TenantAuditLog>());
|
|
ConfigureTenantReviewClaim(modelBuilder.Entity<TenantReviewClaim>());
|
|
ConfigureMerchantDocument(modelBuilder.Entity<MerchantDocument>());
|
|
ConfigureMerchantContract(modelBuilder.Entity<MerchantContract>());
|
|
ConfigureMerchantStaff(modelBuilder.Entity<MerchantStaff>());
|
|
ConfigureMerchantAuditLog(modelBuilder.Entity<MerchantAuditLog>());
|
|
ConfigureMerchantCategory(modelBuilder.Entity<MerchantCategory>());
|
|
ConfigureStoreBusinessHour(modelBuilder.Entity<StoreBusinessHour>());
|
|
ConfigureStoreHoliday(modelBuilder.Entity<StoreHoliday>());
|
|
ConfigureStoreDeliveryZone(modelBuilder.Entity<StoreDeliveryZone>());
|
|
ConfigureStoreTableArea(modelBuilder.Entity<StoreTableArea>());
|
|
ConfigureStoreTable(modelBuilder.Entity<StoreTable>());
|
|
ConfigureStoreEmployeeShift(modelBuilder.Entity<StoreEmployeeShift>());
|
|
ConfigureStorePickupSetting(modelBuilder.Entity<StorePickupSetting>());
|
|
ConfigureStorePickupSlot(modelBuilder.Entity<StorePickupSlot>());
|
|
ConfigureProductCategory(modelBuilder.Entity<ProductCategory>());
|
|
ConfigureProduct(modelBuilder.Entity<Product>());
|
|
ConfigureProductAttributeGroup(modelBuilder.Entity<ProductAttributeGroup>());
|
|
ConfigureProductAttributeOption(modelBuilder.Entity<ProductAttributeOption>());
|
|
ConfigureProductSku(modelBuilder.Entity<ProductSku>());
|
|
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>());
|
|
ConfigureMemberProfile(modelBuilder.Entity<MemberProfile>());
|
|
ConfigureMemberTier(modelBuilder.Entity<MemberTier>());
|
|
ConfigureMemberPointLedger(modelBuilder.Entity<MemberPointLedger>());
|
|
ConfigureMemberGrowthLog(modelBuilder.Entity<MemberGrowthLog>());
|
|
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>());
|
|
|
|
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.Remarks).HasMaxLength(512);
|
|
builder.HasIndex(x => x.Code).IsUnique();
|
|
builder.HasIndex(x => x.ContactPhone).IsUnique();
|
|
}
|
|
|
|
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 ConfigureTenantAuditLog(EntityTypeBuilder<TenantAuditLog> builder)
|
|
{
|
|
builder.ToTable("tenant_audit_logs");
|
|
builder.HasKey(x => x.Id);
|
|
builder.Property(x => x.TenantId).IsRequired();
|
|
builder.Property(x => x.Title).HasMaxLength(128).IsRequired();
|
|
builder.Property(x => x.Description).HasMaxLength(1024);
|
|
builder.Property(x => x.OperatorName).HasMaxLength(64);
|
|
builder.HasIndex(x => x.TenantId);
|
|
}
|
|
|
|
private static void ConfigureTenantReviewClaim(EntityTypeBuilder<TenantReviewClaim> builder)
|
|
{
|
|
builder.ToTable("tenant_review_claims");
|
|
builder.HasKey(x => x.Id);
|
|
builder.Property(x => x.TenantId).IsRequired();
|
|
builder.Property(x => x.ClaimedBy).IsRequired();
|
|
builder.Property(x => x.ClaimedByName).HasMaxLength(64).IsRequired();
|
|
builder.Property(x => x.ClaimedAt).IsRequired();
|
|
builder.Property(x => x.ReleasedAt);
|
|
builder.HasIndex(x => x.TenantId);
|
|
builder.HasIndex(x => x.ClaimedBy);
|
|
builder.HasIndex(x => x.TenantId).IsUnique().HasFilter("\"ReleasedAt\" IS NULL AND \"DeletedAt\" IS NULL");
|
|
}
|
|
|
|
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.HasIndex(x => x.TenantId);
|
|
}
|
|
|
|
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.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.HasIndex(x => new { x.TenantId, x.MerchantId });
|
|
builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
|
|
}
|
|
|
|
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.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.CoverImage).HasMaxLength(256);
|
|
builder.Property(x => x.GalleryImages).HasMaxLength(1024);
|
|
builder.Property(x => x.Description).HasColumnType("text");
|
|
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.SortOrder).HasDefaultValue(0).HasComment("展示排序,数值越小越靠前。");
|
|
builder.HasIndex(x => new { x.IsActive, 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 ConfigureTenantBilling(EntityTypeBuilder<TenantBillingStatement> builder)
|
|
{
|
|
builder.ToTable("tenant_billing_statements");
|
|
builder.HasKey(x => x.Id);
|
|
builder.Property(x => x.StatementNo).HasMaxLength(64).IsRequired();
|
|
builder.Property(x => x.AmountDue).HasPrecision(18, 2);
|
|
builder.Property(x => x.AmountPaid).HasPrecision(18, 2);
|
|
builder.Property(x => x.Status).HasConversion<int>();
|
|
builder.Property(x => x.LineItemsJson).HasColumnType("text");
|
|
builder.HasIndex(x => new { x.TenantId, x.StatementNo }).IsUnique();
|
|
}
|
|
|
|
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 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.Priority).IsRequired();
|
|
builder.Property(x => x.IsActive).IsRequired();
|
|
ConfigureAuditableEntity(builder);
|
|
ConfigureSoftDeleteEntity(builder);
|
|
builder.HasIndex(x => new { x.TenantId, x.AnnouncementType, x.IsActive });
|
|
builder.HasIndex(x => new { x.TenantId, x.EffectiveFrom, x.EffectiveTo });
|
|
}
|
|
|
|
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 ConfigureMerchantAuditLog(EntityTypeBuilder<MerchantAuditLog> builder)
|
|
{
|
|
builder.ToTable("merchant_audit_logs");
|
|
builder.HasKey(x => x.Id);
|
|
builder.Property(x => x.MerchantId).IsRequired();
|
|
builder.Property(x => x.Title).HasMaxLength(128).IsRequired();
|
|
builder.Property(x => x.Description).HasMaxLength(1024);
|
|
builder.Property(x => x.OperatorName).HasMaxLength(64);
|
|
builder.HasIndex(x => new { x.TenantId, x.MerchantId });
|
|
}
|
|
|
|
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.Reason).HasMaxLength(256);
|
|
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Date }).IsUnique();
|
|
}
|
|
|
|
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.HasIndex(x => new { x.TenantId, x.StoreId, x.ZoneName });
|
|
}
|
|
|
|
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.RowVersion).IsRowVersion();
|
|
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).IsRowVersion();
|
|
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Name });
|
|
}
|
|
|
|
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 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.HasIndex(x => new { x.TenantId, x.SkuCode }).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).IsRowVersion();
|
|
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).IsRowVersion();
|
|
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).IsRowVersion();
|
|
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.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 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.Status).HasConversion<int>();
|
|
builder.HasIndex(x => new { x.TenantId, x.Mobile }).IsUnique();
|
|
}
|
|
|
|
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.BenefitsJson).HasColumnType("text");
|
|
builder.HasIndex(x => new { x.TenantId, x.Name }).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 ConfigureMemberGrowthLog(EntityTypeBuilder<MemberGrowthLog> builder)
|
|
{
|
|
builder.ToTable("member_growth_logs");
|
|
builder.HasKey(x => x.Id);
|
|
builder.Property(x => x.MemberId).IsRequired();
|
|
builder.Property(x => x.Notes).HasMaxLength(256);
|
|
builder.HasIndex(x => new { x.TenantId, x.MemberId, x.OccurredAt });
|
|
}
|
|
|
|
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 });
|
|
}
|
|
}
|