feat: 补充数据库脚本和配置
This commit is contained in:
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
@@ -134,7 +143,7 @@
|
||||
"PrefetchCount": 20
|
||||
},
|
||||
"Scheduler": {
|
||||
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_hangfire;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_hangfire_db;Username=hangfire_user;Password=HangFire112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"WorkerCount": 5,
|
||||
"DashboardEnabled": false,
|
||||
"DashboardPath": "/hangfire"
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
@@ -134,7 +143,7 @@
|
||||
"PrefetchCount": 20
|
||||
},
|
||||
"Scheduler": {
|
||||
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_hangfire;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_hangfire_db;Username=hangfire_user;Password=HangFire112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"WorkerCount": 5,
|
||||
"DashboardEnabled": false,
|
||||
"DashboardPath": "/hangfire"
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_app;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"IdentityDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_saas_identity;Username=identity_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_identity_db;Username=identity_user;Password=IdentityUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
},
|
||||
"DictionaryDatabase": {
|
||||
"Write": "Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
|
||||
"Reads": [
|
||||
"Host=120.53.222.17;Port=5432;Database=takeout_dictionary_db;Username=dictionary_user;Password=DictionaryUser112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
|
||||
@@ -14,4 +14,9 @@ public static class DatabaseConstants
|
||||
/// 身份认证库(IdentityDatabase)。
|
||||
/// </summary>
|
||||
public const string IdentityDataSource = "IdentityDatabase";
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>⣨DictionaryDatabase<73><65><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public const string DictionaryDataSource = "DictionaryDatabase";
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\TakeoutSaaS.Shared.Abstractions\TakeoutSaaS.Shared.Abstractions.csproj" />
|
||||
|
||||
4330
src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201055852_ExpandDomainSchema.Designer.cs
generated
Normal file
4330
src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201055852_ExpandDomainSchema.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
5641
src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201094254_AddEntityComments.Designer.cs
generated
Normal file
5641
src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201094254_AddEntityComments.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,17 @@
|
||||
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;
|
||||
@@ -25,16 +35,91 @@ public sealed class TakeoutAppDbContext(
|
||||
: TenantAwareDbContext(options, tenantProvider, currentUserAccessor)
|
||||
{
|
||||
public DbSet<Tenant> Tenants => Set<Tenant>();
|
||||
public DbSet<TenantPackage> TenantPackages => Set<TenantPackage>();
|
||||
public DbSet<TenantSubscription> TenantSubscriptions => Set<TenantSubscription>();
|
||||
public DbSet<TenantQuotaUsage> TenantQuotaUsages => Set<TenantQuotaUsage>();
|
||||
public DbSet<TenantBillingStatement> TenantBillingStatements => Set<TenantBillingStatement>();
|
||||
public DbSet<TenantNotification> TenantNotifications => Set<TenantNotification>();
|
||||
|
||||
public DbSet<Merchant> Merchants => Set<Merchant>();
|
||||
public DbSet<MerchantDocument> MerchantDocuments => Set<MerchantDocument>();
|
||||
public DbSet<MerchantContract> MerchantContracts => Set<MerchantContract>();
|
||||
public DbSet<MerchantStaff> MerchantStaff => Set<MerchantStaff>();
|
||||
|
||||
public DbSet<Store> Stores => Set<Store>();
|
||||
public DbSet<StoreBusinessHour> StoreBusinessHours => Set<StoreBusinessHour>();
|
||||
public DbSet<StoreHoliday> StoreHolidays => Set<StoreHoliday>();
|
||||
public DbSet<StoreDeliveryZone> StoreDeliveryZones => Set<StoreDeliveryZone>();
|
||||
public DbSet<StoreTableArea> StoreTableAreas => Set<StoreTableArea>();
|
||||
public DbSet<StoreTable> StoreTables => Set<StoreTable>();
|
||||
public DbSet<StoreEmployeeShift> StoreEmployeeShifts => Set<StoreEmployeeShift>();
|
||||
|
||||
public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
|
||||
public DbSet<Product> Products => Set<Product>();
|
||||
public DbSet<ProductAttributeGroup> ProductAttributeGroups => Set<ProductAttributeGroup>();
|
||||
public DbSet<ProductAttributeOption> ProductAttributeOptions => Set<ProductAttributeOption>();
|
||||
public DbSet<ProductSku> ProductSkus => Set<ProductSku>();
|
||||
public DbSet<ProductAddonGroup> ProductAddonGroups => Set<ProductAddonGroup>();
|
||||
public DbSet<ProductAddonOption> ProductAddonOptions => Set<ProductAddonOption>();
|
||||
public DbSet<ProductPricingRule> ProductPricingRules => Set<ProductPricingRule>();
|
||||
public DbSet<ProductMediaAsset> ProductMediaAssets => Set<ProductMediaAsset>();
|
||||
|
||||
public DbSet<InventoryItem> InventoryItems => Set<InventoryItem>();
|
||||
public DbSet<InventoryAdjustment> InventoryAdjustments => Set<InventoryAdjustment>();
|
||||
public DbSet<InventoryBatch> InventoryBatches => Set<InventoryBatch>();
|
||||
|
||||
public DbSet<ShoppingCart> ShoppingCarts => Set<ShoppingCart>();
|
||||
public DbSet<CartItem> CartItems => Set<CartItem>();
|
||||
public DbSet<CartItemAddon> CartItemAddons => Set<CartItemAddon>();
|
||||
public DbSet<CheckoutSession> CheckoutSessions => Set<CheckoutSession>();
|
||||
|
||||
public DbSet<Order> Orders => Set<Order>();
|
||||
public DbSet<OrderItem> OrderItems => Set<OrderItem>();
|
||||
public DbSet<OrderStatusHistory> OrderStatusHistories => Set<OrderStatusHistory>();
|
||||
public DbSet<RefundRequest> RefundRequests => Set<RefundRequest>();
|
||||
|
||||
public DbSet<PaymentRecord> PaymentRecords => Set<PaymentRecord>();
|
||||
public DbSet<PaymentRefundRecord> PaymentRefundRecords => Set<PaymentRefundRecord>();
|
||||
|
||||
public DbSet<Reservation> Reservations => Set<Reservation>();
|
||||
public DbSet<QueueTicket> QueueTickets => Set<QueueTicket>();
|
||||
|
||||
public DbSet<DeliveryOrder> DeliveryOrders => Set<DeliveryOrder>();
|
||||
public DbSet<DeliveryEvent> DeliveryEvents => Set<DeliveryEvent>();
|
||||
|
||||
public DbSet<GroupOrder> GroupOrders => Set<GroupOrder>();
|
||||
public DbSet<GroupParticipant> GroupParticipants => Set<GroupParticipant>();
|
||||
|
||||
public DbSet<CouponTemplate> CouponTemplates => Set<CouponTemplate>();
|
||||
public DbSet<Coupon> Coupons => Set<Coupon>();
|
||||
public DbSet<PromotionCampaign> PromotionCampaigns => Set<PromotionCampaign>();
|
||||
|
||||
public DbSet<MemberProfile> MemberProfiles => Set<MemberProfile>();
|
||||
public DbSet<MemberTier> MemberTiers => Set<MemberTier>();
|
||||
public DbSet<MemberPointLedger> MemberPointLedgers => Set<MemberPointLedger>();
|
||||
public DbSet<MemberGrowthLog> MemberGrowthLogs => Set<MemberGrowthLog>();
|
||||
|
||||
public DbSet<ChatSession> ChatSessions => Set<ChatSession>();
|
||||
public DbSet<ChatMessage> ChatMessages => Set<ChatMessage>();
|
||||
public DbSet<SupportTicket> SupportTickets => Set<SupportTicket>();
|
||||
public DbSet<TicketComment> TicketComments => Set<TicketComment>();
|
||||
|
||||
public DbSet<AffiliatePartner> AffiliatePartners => Set<AffiliatePartner>();
|
||||
public DbSet<AffiliateOrder> AffiliateOrders => Set<AffiliateOrder>();
|
||||
public DbSet<AffiliatePayout> AffiliatePayouts => Set<AffiliatePayout>();
|
||||
|
||||
public DbSet<CheckInCampaign> CheckInCampaigns => Set<CheckInCampaign>();
|
||||
public DbSet<CheckInRecord> CheckInRecords => Set<CheckInRecord>();
|
||||
public DbSet<CommunityPost> CommunityPosts => Set<CommunityPost>();
|
||||
public DbSet<CommunityComment> CommunityComments => Set<CommunityComment>();
|
||||
public DbSet<CommunityReaction> CommunityReactions => Set<CommunityReaction>();
|
||||
|
||||
public DbSet<MapLocation> MapLocations => Set<MapLocation>();
|
||||
public DbSet<NavigationRequest> NavigationRequests => Set<NavigationRequest>();
|
||||
|
||||
public DbSet<MetricDefinition> MetricDefinitions => Set<MetricDefinition>();
|
||||
public DbSet<MetricSnapshot> MetricSnapshots => Set<MetricSnapshot>();
|
||||
public DbSet<MetricAlertRule> MetricAlertRules => Set<MetricAlertRule>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -43,14 +128,72 @@ public sealed class TakeoutAppDbContext(
|
||||
ConfigureTenant(modelBuilder.Entity<Tenant>());
|
||||
ConfigureMerchant(modelBuilder.Entity<Merchant>());
|
||||
ConfigureStore(modelBuilder.Entity<Store>());
|
||||
ConfigureTenantPackage(modelBuilder.Entity<TenantPackage>());
|
||||
ConfigureTenantSubscription(modelBuilder.Entity<TenantSubscription>());
|
||||
ConfigureTenantQuotaUsage(modelBuilder.Entity<TenantQuotaUsage>());
|
||||
ConfigureTenantBilling(modelBuilder.Entity<TenantBillingStatement>());
|
||||
ConfigureTenantNotification(modelBuilder.Entity<TenantNotification>());
|
||||
ConfigureMerchantDocument(modelBuilder.Entity<MerchantDocument>());
|
||||
ConfigureMerchantContract(modelBuilder.Entity<MerchantContract>());
|
||||
ConfigureMerchantStaff(modelBuilder.Entity<MerchantStaff>());
|
||||
ConfigureStoreBusinessHour(modelBuilder.Entity<StoreBusinessHour>());
|
||||
ConfigureStoreHoliday(modelBuilder.Entity<StoreHoliday>());
|
||||
ConfigureStoreDeliveryZone(modelBuilder.Entity<StoreDeliveryZone>());
|
||||
ConfigureStoreTableArea(modelBuilder.Entity<StoreTableArea>());
|
||||
ConfigureStoreTable(modelBuilder.Entity<StoreTable>());
|
||||
ConfigureStoreEmployeeShift(modelBuilder.Entity<StoreEmployeeShift>());
|
||||
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>());
|
||||
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);
|
||||
}
|
||||
@@ -218,4 +361,632 @@ public sealed class TakeoutAppDbContext(
|
||||
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");
|
||||
}
|
||||
|
||||
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 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 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 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.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.HasIndex(x => new { x.TenantId, x.StoreId, x.ProductSkuId, x.BatchNumber }).IsUnique();
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
@@ -12,7 +13,7 @@ internal sealed class TakeoutAppDesignTimeDbContextFactory
|
||||
: DesignTimeDbContextFactoryBase<TakeoutAppDbContext>
|
||||
{
|
||||
public TakeoutAppDesignTimeDbContextFactory()
|
||||
: base("TAKEOUTSAAS_APP_CONNECTION", "takeout_saas_app")
|
||||
: base(DatabaseConstants.AppDataSource, "TAKEOUTSAAS_APP_CONNECTION")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ public abstract class AppDbContext(DbContextOptions options, ICurrentUserAccesso
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
ApplySoftDeleteQueryFilters(modelBuilder);
|
||||
modelBuilder.ApplyXmlComments();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using TakeoutSaaS.Infrastructure.Common.Persistence;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using TakeoutSaaS.Infrastructure.Common.Options;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core 设计时 DbContext 工厂基类,提供统一的连接串与依赖替身。
|
||||
/// EF Core 设计时 DbContext 工厂基类,统一读取 appsettings 中的数据库配置。
|
||||
/// </summary>
|
||||
internal abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDbContextFactory<TContext>
|
||||
where TContext : TenantAwareDbContext
|
||||
{
|
||||
private readonly string _connectionStringEnvVar;
|
||||
private readonly string _defaultDatabase;
|
||||
private readonly string _dataSourceName;
|
||||
private readonly string? _connectionStringEnvVar;
|
||||
|
||||
protected DesignTimeDbContextFactoryBase(string connectionStringEnvVar, string defaultDatabase)
|
||||
protected DesignTimeDbContextFactoryBase(string dataSourceName, string? connectionStringEnvVar = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataSourceName))
|
||||
{
|
||||
throw new ArgumentException("数据源名称不能为空。", nameof(dataSourceName));
|
||||
}
|
||||
|
||||
_dataSourceName = dataSourceName;
|
||||
_connectionStringEnvVar = connectionStringEnvVar;
|
||||
_defaultDatabase = defaultDatabase;
|
||||
}
|
||||
|
||||
public TContext CreateDbContext(string[] args)
|
||||
@@ -46,15 +54,91 @@ internal abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDb
|
||||
|
||||
private string ResolveConnectionString()
|
||||
{
|
||||
var env = Environment.GetEnvironmentVariable(_connectionStringEnvVar);
|
||||
if (!string.IsNullOrWhiteSpace(env))
|
||||
if (!string.IsNullOrWhiteSpace(_connectionStringEnvVar))
|
||||
{
|
||||
return env;
|
||||
var envValue = Environment.GetEnvironmentVariable(_connectionStringEnvVar);
|
||||
if (!string.IsNullOrWhiteSpace(envValue))
|
||||
{
|
||||
return envValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $"Host=localhost;Port=5432;Database={_defaultDatabase};Username=postgres;Password=postgres";
|
||||
var configuration = BuildConfiguration();
|
||||
var writeConnection = configuration[$"{DatabaseOptions.SectionName}:DataSources:{_dataSourceName}:Write"];
|
||||
if (string.IsNullOrWhiteSpace(writeConnection))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"未在配置中找到数据源 '{_dataSourceName}' 的 Write 连接字符串,请检查 appsettings 或设置 {_connectionStringEnvVar ?? "相应"} 环境变量。");
|
||||
}
|
||||
|
||||
return writeConnection;
|
||||
}
|
||||
|
||||
private static IConfigurationRoot BuildConfiguration()
|
||||
{
|
||||
var basePath = ResolveConfigurationDirectory();
|
||||
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development";
|
||||
|
||||
return new ConfigurationBuilder()
|
||||
.SetBasePath(basePath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: false)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static string ResolveConfigurationDirectory()
|
||||
{
|
||||
var explicitDir = Environment.GetEnvironmentVariable("TAKEOUTSAAS_APPSETTINGS_DIR");
|
||||
if (!string.IsNullOrWhiteSpace(explicitDir) && Directory.Exists(explicitDir))
|
||||
{
|
||||
return explicitDir;
|
||||
}
|
||||
|
||||
var currentDir = Directory.GetCurrentDirectory();
|
||||
var solutionRoot = LocateSolutionRoot(currentDir);
|
||||
|
||||
var candidateDirs = new[]
|
||||
{
|
||||
currentDir,
|
||||
solutionRoot,
|
||||
solutionRoot is null ? null : Path.Combine(solutionRoot, "src", "Api", "TakeoutSaaS.AdminApi"),
|
||||
solutionRoot is null ? null : Path.Combine(solutionRoot, "src", "Api", "TakeoutSaaS.UserApi"),
|
||||
solutionRoot is null ? null : Path.Combine(solutionRoot, "src", "Api", "TakeoutSaaS.MiniApi")
|
||||
}.Where(dir => !string.IsNullOrWhiteSpace(dir));
|
||||
|
||||
foreach (var dir in candidateDirs)
|
||||
{
|
||||
if (dir != null && Directory.Exists(dir) && HasAppSettings(dir))
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
"未找到 appsettings 配置文件,请设置 TAKEOUTSAAS_APPSETTINGS_DIR 环境变量指向包含 appsettings*.json 的目录。");
|
||||
}
|
||||
|
||||
private static string? LocateSolutionRoot(string currentPath)
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(currentPath);
|
||||
while (directoryInfo != null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directoryInfo.FullName, "TakeoutSaaS.sln")))
|
||||
{
|
||||
return directoryInfo.FullName;
|
||||
}
|
||||
|
||||
directoryInfo = directoryInfo.Parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool HasAppSettings(string directory) =>
|
||||
File.Exists(Path.Combine(directory, "appsettings.json")) ||
|
||||
Directory.GetFiles(directory, "appsettings.*.json").Length > 0;
|
||||
|
||||
private sealed class DesignTimeTenantProvider : ITenantProvider
|
||||
{
|
||||
public Guid GetCurrentTenantId() => Guid.Empty;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Common.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Applies XML documentation summaries to EF Core entities/columns as comments.
|
||||
/// </summary>
|
||||
internal static class ModelBuilderCommentExtensions
|
||||
{
|
||||
public static void ApplyXmlComments(this ModelBuilder modelBuilder)
|
||||
{
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
ApplyEntityComment(entityType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyEntityComment(IMutableEntityType entityType)
|
||||
{
|
||||
var clrType = entityType.ClrType;
|
||||
if (clrType == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (XmlDocCommentProvider.TryGetSummary(clrType, out var typeComment))
|
||||
{
|
||||
entityType.SetComment(typeComment);
|
||||
}
|
||||
|
||||
foreach (var property in entityType.GetProperties())
|
||||
{
|
||||
var propertyInfo = property.PropertyInfo;
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (XmlDocCommentProvider.TryGetSummary(propertyInfo, out var propertyComment))
|
||||
{
|
||||
property.SetComment(propertyComment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class XmlDocCommentProvider
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Assembly, IReadOnlyDictionary<string, string>> Cache = new();
|
||||
|
||||
public static bool TryGetSummary(MemberInfo member, out string? summary)
|
||||
{
|
||||
summary = null;
|
||||
var assembly = member switch
|
||||
{
|
||||
Type type => type.Assembly,
|
||||
_ => member.DeclaringType?.Assembly
|
||||
};
|
||||
|
||||
if (assembly == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var map = Cache.GetOrAdd(assembly, LoadComments);
|
||||
if (map.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var key = GetMemberKey(member);
|
||||
if (key == null || !map.TryGetValue(key, out var text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
summary = text;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<string, string> LoadComments(Assembly assembly)
|
||||
{
|
||||
var dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
var xmlPath = Path.ChangeExtension(assembly.Location, ".xml");
|
||||
if (string.IsNullOrWhiteSpace(xmlPath) || !File.Exists(xmlPath))
|
||||
{
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
var document = XDocument.Load(xmlPath);
|
||||
foreach (var member in document.Descendants("member"))
|
||||
{
|
||||
var name = member.Attribute("name")?.Value;
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var summary = member.Element("summary")?.Value;
|
||||
if (string.IsNullOrWhiteSpace(summary))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var normalized = Normalize(summary);
|
||||
if (!string.IsNullOrWhiteSpace(normalized))
|
||||
{
|
||||
dictionary[name] = normalized;
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private static string? GetMemberKey(MemberInfo member) =>
|
||||
member switch
|
||||
{
|
||||
Type type => $"T:{GetFullName(type)}",
|
||||
PropertyInfo property => $"P:{GetFullName(property.DeclaringType!)}.{property.Name}",
|
||||
FieldInfo field => $"F:{GetFullName(field.DeclaringType!)}.{field.Name}",
|
||||
_ => null
|
||||
};
|
||||
|
||||
private static string GetFullName(Type type) =>
|
||||
(type.FullName ?? type.Name).Replace('+', '.');
|
||||
|
||||
private static string Normalize(string text)
|
||||
{
|
||||
var chars = text.Replace('\r', ' ').Replace('\n', ' ').Replace('\t', ' ');
|
||||
return string.Join(' ', chars.Split(' ', StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public static class DictionaryServiceCollectionExtensions
|
||||
public static IServiceCollection AddDictionaryInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddDatabaseInfrastructure(configuration);
|
||||
services.AddPostgresDbContext<DictionaryDbContext>(DatabaseConstants.AppDataSource);
|
||||
services.AddPostgresDbContext<DictionaryDbContext>(DatabaseConstants.DictionaryDataSource);
|
||||
|
||||
services.AddScoped<IDictionaryRepository, EfDictionaryRepository>();
|
||||
services.AddScoped<IDictionaryCache, DistributedDictionaryCache>();
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using TakeoutSaaS.Infrastructure.Dictionary.Persistence;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
|
||||
{
|
||||
[DbContext(typeof(DictionaryDbContext))]
|
||||
[Migration("20251201094456_AddEntityComments")]
|
||||
partial class AddEntityComments
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("分组编码(唯一)。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasComment("描述信息。");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true)
|
||||
.HasComment("是否启用。");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("分组名称。");
|
||||
|
||||
b.Property<int>("Scope")
|
||||
.HasColumnType("integer")
|
||||
.HasComment("分组作用域:系统/业务。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("TenantId", "Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("dictionary_groups", null, t =>
|
||||
{
|
||||
t.HasComment("参数字典分组(系统参数、业务参数)。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasComment("描述信息。");
|
||||
|
||||
b.Property<Guid>("GroupId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("关联分组 ID。");
|
||||
|
||||
b.Property<bool>("IsDefault")
|
||||
.HasColumnType("boolean")
|
||||
.HasComment("是否默认项。");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true)
|
||||
.HasComment("是否启用。");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("字典项键。");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValue(100)
|
||||
.HasComment("排序值,越小越靠前。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("字典项值。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("GroupId", "Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("dictionary_items", null, t =>
|
||||
{
|
||||
t.HasComment("参数字典项。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
|
||||
{
|
||||
b.HasOne("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", "Group")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("GroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Group");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryGroup", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,599 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddEntityComments : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterTable(
|
||||
name: "dictionary_items",
|
||||
comment: "参数字典项。");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "dictionary_groups",
|
||||
comment: "参数字典分组(系统参数、业务参数)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Value",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
comment: "字典项值。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "最后更新人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "最近一次更新时间(UTC),从未更新时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "所属租户 ID。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "SortOrder",
|
||||
table: "dictionary_items",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 100,
|
||||
comment: "排序值,越小越靠前。",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "integer",
|
||||
oldDefaultValue: 100);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Key",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
comment: "字典项键。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsEnabled",
|
||||
table: "dictionary_items",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
comment: "是否启用。",
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean",
|
||||
oldDefaultValue: true);
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsDefault",
|
||||
table: "dictionary_items",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
comment: "是否默认项。",
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GroupId",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "关联分组 ID。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Description",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(512)",
|
||||
maxLength: 512,
|
||||
nullable: true,
|
||||
comment: "描述信息。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(512)",
|
||||
oldMaxLength: 512,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "删除人用户标识(软删除),未删除时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "软删除时间(UTC),未删除时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "创建人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
comment: "创建时间(UTC)。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "实体唯一标识。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "最后更新人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "最近一次更新时间(UTC),从未更新时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "所属租户 ID。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Scope",
|
||||
table: "dictionary_groups",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
comment: "分组作用域:系统/业务。",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "integer");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: false,
|
||||
comment: "分组名称。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128);
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsEnabled",
|
||||
table: "dictionary_groups",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
comment: "是否启用。",
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean",
|
||||
oldDefaultValue: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Description",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(512)",
|
||||
maxLength: 512,
|
||||
nullable: true,
|
||||
comment: "描述信息。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(512)",
|
||||
oldMaxLength: 512,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "删除人用户标识(软删除),未删除时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "软删除时间(UTC),未删除时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "创建人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
comment: "创建时间(UTC)。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Code",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
comment: "分组编码(唯一)。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "实体唯一标识。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterTable(
|
||||
name: "dictionary_items",
|
||||
oldComment: "参数字典项。");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "dictionary_groups",
|
||||
oldComment: "参数字典分组(系统参数、业务参数)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Value",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldComment: "字典项值。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "所属租户 ID。");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "SortOrder",
|
||||
table: "dictionary_items",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 100,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "integer",
|
||||
oldDefaultValue: 100,
|
||||
oldComment: "排序值,越小越靠前。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Key",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldComment: "字典项键。");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsEnabled",
|
||||
table: "dictionary_items",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean",
|
||||
oldDefaultValue: true,
|
||||
oldComment: "是否启用。");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsDefault",
|
||||
table: "dictionary_items",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean",
|
||||
oldComment: "是否默认项。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GroupId",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "关联分组 ID。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Description",
|
||||
table: "dictionary_items",
|
||||
type: "character varying(512)",
|
||||
maxLength: 512,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(512)",
|
||||
oldMaxLength: 512,
|
||||
oldNullable: true,
|
||||
oldComment: "描述信息。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "dictionary_items",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldComment: "创建时间(UTC)。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "dictionary_items",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "实体唯一标识。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "所属租户 ID。");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "Scope",
|
||||
table: "dictionary_groups",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "integer",
|
||||
oldComment: "分组作用域:系统/业务。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128,
|
||||
oldComment: "分组名称。");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "IsEnabled",
|
||||
table: "dictionary_groups",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "boolean",
|
||||
oldDefaultValue: true,
|
||||
oldComment: "是否启用。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Description",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(512)",
|
||||
maxLength: 512,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(512)",
|
||||
oldMaxLength: 512,
|
||||
oldNullable: true,
|
||||
oldComment: "描述信息。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "dictionary_groups",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldComment: "创建时间(UTC)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Code",
|
||||
table: "dictionary_groups",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldComment: "分组编码(唯一)。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "dictionary_groups",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "实体唯一标识。");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,50 +26,63 @@ namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("分组编码(唯一)。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasComment("描述信息。");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true);
|
||||
.HasDefaultValue(true)
|
||||
.HasComment("是否启用。");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("分组名称。");
|
||||
|
||||
b.Property<int>("Scope")
|
||||
.HasColumnType("integer");
|
||||
.HasColumnType("integer")
|
||||
.HasComment("分组作用域:系统/业务。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -78,65 +91,83 @@ namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
|
||||
b.HasIndex("TenantId", "Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("dictionary_groups", (string)null);
|
||||
b.ToTable("dictionary_groups", null, t =>
|
||||
{
|
||||
t.HasComment("参数字典分组(系统参数、业务参数)。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasComment("描述信息。");
|
||||
|
||||
b.Property<Guid>("GroupId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("关联分组 ID。");
|
||||
|
||||
b.Property<bool>("IsDefault")
|
||||
.HasColumnType("boolean");
|
||||
.HasColumnType("boolean")
|
||||
.HasComment("是否默认项。");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true);
|
||||
.HasDefaultValue(true)
|
||||
.HasComment("是否启用。");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("字典项键。");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValue(100);
|
||||
.HasDefaultValue(100)
|
||||
.HasComment("排序值,越小越靠前。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("字典项值。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -145,7 +176,10 @@ namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
|
||||
b.HasIndex("GroupId", "Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("dictionary_items", (string)null);
|
||||
b.ToTable("dictionary_items", null, t =>
|
||||
{
|
||||
t.HasComment("参数字典项。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
@@ -12,7 +13,7 @@ internal sealed class DictionaryDesignTimeDbContextFactory
|
||||
: DesignTimeDbContextFactoryBase<DictionaryDbContext>
|
||||
{
|
||||
public DictionaryDesignTimeDbContextFactory()
|
||||
: base("TAKEOUTSAAS_APP_CONNECTION", "takeout_saas_app")
|
||||
: base(DatabaseConstants.DictionaryDataSource, "TAKEOUTSAAS_DICTIONARY_CONNECTION")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using TakeoutSaaS.Infrastructure.Identity.Persistence;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Identity.Migrations
|
||||
{
|
||||
[DbContext(typeof(IdentityDbContext))]
|
||||
[Migration("20251201094410_AddEntityComments")]
|
||||
partial class AddEntityComments
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Account")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("登录账号。");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("头像地址。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("展示名称。");
|
||||
|
||||
b.Property<Guid?>("MerchantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属商户(平台管理员为空)。");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("密码哈希。");
|
||||
|
||||
b.Property<string>("Permissions")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasComment("权限集合。");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasComment("角色集合。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("TenantId", "Account")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("identity_users", null, t =>
|
||||
{
|
||||
t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("头像地址。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("昵称。");
|
||||
|
||||
b.Property<string>("OpenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("微信 OpenId。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<string>("UnionId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("微信 UnionId,可能为空。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TenantId");
|
||||
|
||||
b.HasIndex("TenantId", "OpenId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("mini_users", null, t =>
|
||||
{
|
||||
t.HasComment("小程序用户实体。");
|
||||
});
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,581 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Identity.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddEntityComments : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterTable(
|
||||
name: "mini_users",
|
||||
comment: "小程序用户实体。");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "identity_users",
|
||||
comment: "管理后台账户实体(平台管理员、租户管理员或商户员工)。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "最后更新人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "最近一次更新时间(UTC),从未更新时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "UnionId",
|
||||
table: "mini_users",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true,
|
||||
comment: "微信 UnionId,可能为空。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "所属租户 ID。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OpenId",
|
||||
table: "mini_users",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: false,
|
||||
comment: "微信 OpenId。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Nickname",
|
||||
table: "mini_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
comment: "昵称。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "删除人用户标识(软删除),未删除时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "软删除时间(UTC),未删除时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "创建人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
comment: "创建时间(UTC)。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Avatar",
|
||||
table: "mini_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: true,
|
||||
comment: "头像地址。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "实体唯一标识。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "最后更新人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "最近一次更新时间(UTC),从未更新时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "所属租户 ID。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Roles",
|
||||
table: "identity_users",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
comment: "角色集合。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Permissions",
|
||||
table: "identity_users",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
comment: "权限集合。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "PasswordHash",
|
||||
table: "identity_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
comment: "密码哈希。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "MerchantId",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "所属商户(平台管理员为空)。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "DisplayName",
|
||||
table: "identity_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
comment: "展示名称。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "删除人用户标识(软删除),未删除时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
comment: "软删除时间(UTC),未删除时为 null。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
comment: "创建人用户标识,匿名或系统操作时为 null。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
comment: "创建时间(UTC)。",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Avatar",
|
||||
table: "identity_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: true,
|
||||
comment: "头像地址。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Account",
|
||||
table: "identity_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
comment: "登录账号。",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
comment: "实体唯一标识。",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterTable(
|
||||
name: "mini_users",
|
||||
oldComment: "小程序用户实体。");
|
||||
|
||||
migrationBuilder.AlterTable(
|
||||
name: "identity_users",
|
||||
oldComment: "管理后台账户实体(平台管理员、租户管理员或商户员工)。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "UnionId",
|
||||
table: "mini_users",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128,
|
||||
oldNullable: true,
|
||||
oldComment: "微信 UnionId,可能为空。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "所属租户 ID。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OpenId",
|
||||
table: "mini_users",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(128)",
|
||||
oldMaxLength: 128,
|
||||
oldComment: "微信 OpenId。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Nickname",
|
||||
table: "mini_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldComment: "昵称。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "mini_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldComment: "创建时间(UTC)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Avatar",
|
||||
table: "mini_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldNullable: true,
|
||||
oldComment: "头像地址。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "mini_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "实体唯一标识。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "UpdatedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdatedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "所属租户 ID。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Roles",
|
||||
table: "identity_users",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldComment: "角色集合。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Permissions",
|
||||
table: "identity_users",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldComment: "权限集合。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "PasswordHash",
|
||||
table: "identity_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldComment: "密码哈希。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "MerchantId",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "所属商户(平台管理员为空)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "DisplayName",
|
||||
table: "identity_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldComment: "展示名称。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "DeletedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DeletedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldNullable: true,
|
||||
oldComment: "软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CreatedBy",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true,
|
||||
oldComment: "创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreatedAt",
|
||||
table: "identity_users",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "timestamp with time zone",
|
||||
oldComment: "创建时间(UTC)。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Avatar",
|
||||
table: "identity_users",
|
||||
type: "character varying(256)",
|
||||
maxLength: 256,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(256)",
|
||||
oldMaxLength: 256,
|
||||
oldNullable: true,
|
||||
oldComment: "头像地址。");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Account",
|
||||
table: "identity_users",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldComment: "登录账号。");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "Id",
|
||||
table: "identity_users",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldComment: "实体唯一标识。");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,58 +26,73 @@ namespace TakeoutSaaS.Infrastructure.Identity.Migrations
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Account")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("登录账号。");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("头像地址。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("展示名称。");
|
||||
|
||||
b.Property<Guid?>("MerchantId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属商户(平台管理员为空)。");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("密码哈希。");
|
||||
|
||||
b.Property<string>("Permissions")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
.HasColumnType("text")
|
||||
.HasComment("权限集合。");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
.HasColumnType("text")
|
||||
.HasComment("角色集合。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -86,53 +101,68 @@ namespace TakeoutSaaS.Infrastructure.Identity.Migrations
|
||||
b.HasIndex("TenantId", "Account")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("identity_users", (string)null);
|
||||
b.ToTable("identity_users", null, t =>
|
||||
{
|
||||
t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("实体唯一标识。");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
.HasColumnType("character varying(256)")
|
||||
.HasComment("头像地址。");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("创建时间(UTC)。");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("软删除时间(UTC),未删除时为 null。");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("删除人用户标识(软删除),未删除时为 null。");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasComment("昵称。");
|
||||
|
||||
b.Property<string>("OpenId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("微信 OpenId。");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("所属租户 ID。");
|
||||
|
||||
b.Property<string>("UnionId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasComment("微信 UnionId,可能为空。");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("最近一次更新时间(UTC),从未更新时为 null。");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid");
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -141,7 +171,10 @@ namespace TakeoutSaaS.Infrastructure.Identity.Migrations
|
||||
b.HasIndex("TenantId", "OpenId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("mini_users", (string)null);
|
||||
b.ToTable("mini_users", null, t =>
|
||||
{
|
||||
t.HasComment("小程序用户实体。");
|
||||
});
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
@@ -12,7 +13,7 @@ internal sealed class IdentityDesignTimeDbContextFactory
|
||||
: DesignTimeDbContextFactoryBase<IdentityDbContext>
|
||||
{
|
||||
public IdentityDesignTimeDbContextFactory()
|
||||
: base("TAKEOUTSAAS_IDENTITY_CONNECTION", "takeout_saas_identity")
|
||||
: base(DatabaseConstants.IdentityDataSource, "TAKEOUTSAAS_IDENTITY_CONNECTION")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user