feat: 扩展领域模型与配置

This commit is contained in:
贺爱泽
2025-12-01 13:26:05 +08:00
parent a08804658b
commit 5ddad07658
148 changed files with 8519 additions and 2 deletions

View File

@@ -0,0 +1,949 @@
// <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.App.Persistence;
#nullable disable
namespace TakeoutSaaS.Infrastructure.App.Migrations
{
[DbContext(typeof(TakeoutAppDbContext))]
[Migration("20251201044927_InitialApp")]
partial class InitialApp
{
/// <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.Deliveries.Entities.DeliveryOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CourierName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CourierPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeliveredAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal?>("DeliveryFee")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("DispatchedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FailureReason")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<DateTime?>("PickedUpAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Provider")
.HasColumnType("integer");
b.Property<string>("ProviderOrderId")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderId")
.IsUnique();
b.ToTable("delivery_orders", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("BrandAlias")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("BrandName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("BusinessLicenseNumber")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("City")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactEmail")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("District")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("LegalPerson")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime?>("OnboardedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Province")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ReviewRemarks")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("merchants", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CancelReason")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Channel")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<string>("CustomerName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CustomerPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("DeliveryType")
.HasColumnType("integer");
b.Property<decimal>("DiscountAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("FinishedAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("ItemsAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("OrderNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<decimal>("PaidAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("PaidAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("PayableAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<int>("PaymentStatus")
.HasColumnType("integer");
b.Property<string>("QueueNumber")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<string>("Remark")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<Guid?>("ReservationId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("TableNo")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId", "Status");
b.ToTable("orders", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AttributesJson")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<decimal>("DiscountAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<int>("Quantity")
.HasColumnType("integer");
b.Property<string>("SkuName")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<decimal>("SubTotal")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("Unit")
.HasMaxLength(16)
.HasColumnType("character varying(16)");
b.Property<decimal>("UnitPrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("OrderId");
b.HasIndex("TenantId", "OrderId");
b.ToTable("order_items", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("ChannelTransactionId")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("Method")
.HasColumnType("integer");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<DateTime?>("PaidAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Payload")
.HasColumnType("text");
b.Property<string>("Remark")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("TradeNo")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderId");
b.ToTable("payment_records", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.Property<string>("CoverImage")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<bool>("EnableDelivery")
.HasColumnType("boolean");
b.Property<bool>("EnableDineIn")
.HasColumnType("boolean");
b.Property<bool>("EnablePickup")
.HasColumnType("boolean");
b.Property<string>("GalleryImages")
.HasMaxLength(1024)
.HasColumnType("character varying(1024)");
b.Property<bool>("IsFeatured")
.HasColumnType("boolean");
b.Property<int?>("MaxQuantityPerOrder")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<decimal?>("OriginalPrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<decimal>("Price")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("SpuCode")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<int?>("StockQuantity")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("Subtitle")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("Unit")
.HasMaxLength(16)
.HasColumnType("character varying(16)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "SpuCode")
.IsUnique();
b.HasIndex("TenantId", "StoreId");
b.ToTable("products", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId");
b.ToTable("product_categories", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime?>("CalledAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int?>("EstimatedWaitMinutes")
.HasColumnType("integer");
b.Property<DateTime?>("ExpiredAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("PartySize")
.HasColumnType("integer");
b.Property<string>("Remark")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("TicketNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId");
b.HasIndex("TenantId", "StoreId", "TicketNumber")
.IsUnique();
b.ToTable("queue_tickets", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("CheckInCode")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("CheckedInAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<string>("CustomerName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CustomerPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("PeopleCount")
.HasColumnType("integer");
b.Property<string>("Remark")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("ReservationNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("ReservationTime")
.HasColumnType("timestamp with time zone");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("TablePreference")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "ReservationNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId");
b.ToTable("reservations", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Announcement")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("BusinessHours")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("City")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<decimal>("DeliveryRadiusKm")
.HasPrecision(6, 2)
.HasColumnType("numeric(6,2)");
b.Property<string>("District")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<double?>("Latitude")
.HasColumnType("double precision");
b.Property<double?>("Longitude")
.HasColumnType("double precision");
b.Property<string>("ManagerName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid>("MerchantId")
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("Phone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<string>("Province")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<bool>("QueueEnabled")
.HasColumnType("boolean");
b.Property<bool>("ReservationEnabled")
.HasColumnType("boolean");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<bool>("SupportsDelivery")
.HasColumnType("boolean");
b.Property<bool>("SupportsDineIn")
.HasColumnType("boolean");
b.Property<bool>("SupportsPickup")
.HasColumnType("boolean");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("MerchantId");
b.HasIndex("TenantId", "Code")
.IsUnique();
b.HasIndex("TenantId", "MerchantId");
b.ToTable("stores", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactEmail")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("ContactName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("EffectiveFrom")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("EffectiveTo")
.HasColumnType("timestamp with time zone");
b.Property<string>("Industry")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("LogoUrl")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("Remarks")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("ShortName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("tenants", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
{
b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
{
b.HasOne("TakeoutSaaS.Domain.Merchants.Entities.Merchant", "Merchant")
.WithMany()
.HasForeignKey("MerchantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Merchant");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,497 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TakeoutSaaS.Infrastructure.App.Migrations
{
/// <inheritdoc />
public partial class InitialApp : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "delivery_orders",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
Provider = table.Column<int>(type: "integer", nullable: false),
ProviderOrderId = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Status = table.Column<int>(type: "integer", nullable: false),
DeliveryFee = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true),
CourierName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
CourierPhone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
DispatchedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
PickedUpAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeliveredAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
FailureReason = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_delivery_orders", x => x.Id);
});
migrationBuilder.CreateTable(
name: "merchants",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
BrandName = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
BrandAlias = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
LegalPerson = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
BusinessLicenseNumber = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
ContactPhone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
ContactEmail = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
Province = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
City = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
District = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Status = table.Column<int>(type: "integer", nullable: false),
ReviewRemarks = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
OnboardedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_merchants", x => x.Id);
});
migrationBuilder.CreateTable(
name: "orders",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OrderNo = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
Channel = table.Column<int>(type: "integer", nullable: false),
DeliveryType = table.Column<int>(type: "integer", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
PaymentStatus = table.Column<int>(type: "integer", nullable: false),
CustomerName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
CustomerPhone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
TableNo = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
QueueNumber = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
ReservationId = table.Column<Guid>(type: "uuid", nullable: true),
ItemsAmount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
DiscountAmount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
PayableAmount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
PaidAmount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
PaidAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
FinishedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CancelledAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CancelReason = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Remark = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_orders", x => x.Id);
});
migrationBuilder.CreateTable(
name: "payment_records",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
Method = table.Column<int>(type: "integer", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
TradeNo = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
ChannelTransactionId = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
PaidAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
Remark = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Payload = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_payment_records", x => x.Id);
});
migrationBuilder.CreateTable(
name: "product_categories",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
Description = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
SortOrder = table.Column<int>(type: "integer", nullable: false),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_product_categories", x => x.Id);
});
migrationBuilder.CreateTable(
name: "products",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
CategoryId = table.Column<Guid>(type: "uuid", nullable: false),
SpuCode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
Name = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
Subtitle = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Unit = table.Column<string>(type: "character varying(16)", maxLength: 16, nullable: true),
Price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
OriginalPrice = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true),
StockQuantity = table.Column<int>(type: "integer", nullable: true),
MaxQuantityPerOrder = table.Column<int>(type: "integer", nullable: true),
Status = table.Column<int>(type: "integer", nullable: false),
CoverImage = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
GalleryImages = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
Description = table.Column<string>(type: "text", nullable: true),
EnableDineIn = table.Column<bool>(type: "boolean", nullable: false),
EnablePickup = table.Column<bool>(type: "boolean", nullable: false),
EnableDelivery = table.Column<bool>(type: "boolean", nullable: false),
IsFeatured = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_products", x => x.Id);
});
migrationBuilder.CreateTable(
name: "queue_tickets",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
TicketNumber = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
PartySize = table.Column<int>(type: "integer", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
EstimatedWaitMinutes = table.Column<int>(type: "integer", nullable: true),
CalledAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
ExpiredAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CancelledAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
Remark = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_queue_tickets", x => x.Id);
});
migrationBuilder.CreateTable(
name: "reservations",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
ReservationNo = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
CustomerName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
CustomerPhone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
PeopleCount = table.Column<int>(type: "integer", nullable: false),
ReservationTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
TablePreference = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Remark = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
CheckInCode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
CheckedInAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CancelledAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_reservations", x => x.Id);
});
migrationBuilder.CreateTable(
name: "tenants",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
Name = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
ShortName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
ContactName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
ContactPhone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
ContactEmail = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
Industry = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
LogoUrl = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
EffectiveFrom = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
EffectiveTo = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
Status = table.Column<int>(type: "integer", nullable: false),
Remarks = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_tenants", x => x.Id);
});
migrationBuilder.CreateTable(
name: "stores",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
MerchantId = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
Name = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
Phone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
ManagerName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Status = table.Column<int>(type: "integer", nullable: false),
Province = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
City = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
District = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Longitude = table.Column<double>(type: "double precision", nullable: true),
Latitude = table.Column<double>(type: "double precision", nullable: true),
BusinessHours = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
SupportsDineIn = table.Column<bool>(type: "boolean", nullable: false),
SupportsPickup = table.Column<bool>(type: "boolean", nullable: false),
SupportsDelivery = table.Column<bool>(type: "boolean", nullable: false),
DeliveryRadiusKm = table.Column<decimal>(type: "numeric(6,2)", precision: 6, scale: 2, nullable: false),
QueueEnabled = table.Column<bool>(type: "boolean", nullable: false),
ReservationEnabled = table.Column<bool>(type: "boolean", nullable: false),
Announcement = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_stores", x => x.Id);
table.ForeignKey(
name: "FK_stores_merchants_MerchantId",
column: x => x.MerchantId,
principalTable: "merchants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "order_items",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
ProductName = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
SkuName = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
Unit = table.Column<string>(type: "character varying(16)", maxLength: 16, nullable: true),
Quantity = table.Column<int>(type: "integer", nullable: false),
UnitPrice = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
DiscountAmount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
SubTotal = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
AttributesJson = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_order_items", x => x.Id);
table.ForeignKey(
name: "FK_order_items_orders_OrderId",
column: x => x.OrderId,
principalTable: "orders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_delivery_orders_TenantId_OrderId",
table: "delivery_orders",
columns: new[] { "TenantId", "OrderId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_merchants_TenantId",
table: "merchants",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_order_items_OrderId",
table: "order_items",
column: "OrderId");
migrationBuilder.CreateIndex(
name: "IX_order_items_TenantId_OrderId",
table: "order_items",
columns: new[] { "TenantId", "OrderId" });
migrationBuilder.CreateIndex(
name: "IX_orders_TenantId_OrderNo",
table: "orders",
columns: new[] { "TenantId", "OrderNo" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_orders_TenantId_StoreId_Status",
table: "orders",
columns: new[] { "TenantId", "StoreId", "Status" });
migrationBuilder.CreateIndex(
name: "IX_payment_records_TenantId_OrderId",
table: "payment_records",
columns: new[] { "TenantId", "OrderId" });
migrationBuilder.CreateIndex(
name: "IX_product_categories_TenantId_StoreId",
table: "product_categories",
columns: new[] { "TenantId", "StoreId" });
migrationBuilder.CreateIndex(
name: "IX_products_TenantId_SpuCode",
table: "products",
columns: new[] { "TenantId", "SpuCode" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_products_TenantId_StoreId",
table: "products",
columns: new[] { "TenantId", "StoreId" });
migrationBuilder.CreateIndex(
name: "IX_queue_tickets_TenantId_StoreId",
table: "queue_tickets",
columns: new[] { "TenantId", "StoreId" });
migrationBuilder.CreateIndex(
name: "IX_queue_tickets_TenantId_StoreId_TicketNumber",
table: "queue_tickets",
columns: new[] { "TenantId", "StoreId", "TicketNumber" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_reservations_TenantId_ReservationNo",
table: "reservations",
columns: new[] { "TenantId", "ReservationNo" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_reservations_TenantId_StoreId",
table: "reservations",
columns: new[] { "TenantId", "StoreId" });
migrationBuilder.CreateIndex(
name: "IX_stores_MerchantId",
table: "stores",
column: "MerchantId");
migrationBuilder.CreateIndex(
name: "IX_stores_TenantId_Code",
table: "stores",
columns: new[] { "TenantId", "Code" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_stores_TenantId_MerchantId",
table: "stores",
columns: new[] { "TenantId", "MerchantId" });
migrationBuilder.CreateIndex(
name: "IX_tenants_Code",
table: "tenants",
column: "Code",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "delivery_orders");
migrationBuilder.DropTable(
name: "order_items");
migrationBuilder.DropTable(
name: "payment_records");
migrationBuilder.DropTable(
name: "product_categories");
migrationBuilder.DropTable(
name: "products");
migrationBuilder.DropTable(
name: "queue_tickets");
migrationBuilder.DropTable(
name: "reservations");
migrationBuilder.DropTable(
name: "stores");
migrationBuilder.DropTable(
name: "tenants");
migrationBuilder.DropTable(
name: "orders");
migrationBuilder.DropTable(
name: "merchants");
}
}
}

View File

@@ -0,0 +1,946 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TakeoutSaaS.Infrastructure.App.Persistence;
#nullable disable
namespace TakeoutSaaS.Infrastructure.App.Migrations
{
[DbContext(typeof(TakeoutAppDbContext))]
partial class TakeoutAppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CourierName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CourierPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeliveredAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal?>("DeliveryFee")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("DispatchedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FailureReason")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<DateTime?>("PickedUpAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Provider")
.HasColumnType("integer");
b.Property<string>("ProviderOrderId")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderId")
.IsUnique();
b.ToTable("delivery_orders", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("BrandAlias")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("BrandName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("BusinessLicenseNumber")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("City")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactEmail")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("District")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("LegalPerson")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime?>("OnboardedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Province")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ReviewRemarks")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("merchants", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CancelReason")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Channel")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<string>("CustomerName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CustomerPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("DeliveryType")
.HasColumnType("integer");
b.Property<decimal>("DiscountAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("FinishedAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("ItemsAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("OrderNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<decimal>("PaidAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("PaidAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("PayableAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<int>("PaymentStatus")
.HasColumnType("integer");
b.Property<string>("QueueNumber")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<string>("Remark")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<Guid?>("ReservationId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("TableNo")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId", "Status");
b.ToTable("orders", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AttributesJson")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<decimal>("DiscountAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<int>("Quantity")
.HasColumnType("integer");
b.Property<string>("SkuName")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<decimal>("SubTotal")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("Unit")
.HasMaxLength(16)
.HasColumnType("character varying(16)");
b.Property<decimal>("UnitPrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("OrderId");
b.HasIndex("TenantId", "OrderId");
b.ToTable("order_items", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("ChannelTransactionId")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("Method")
.HasColumnType("integer");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<DateTime?>("PaidAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Payload")
.HasColumnType("text");
b.Property<string>("Remark")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("TradeNo")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "OrderId");
b.ToTable("payment_records", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.Property<string>("CoverImage")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<bool>("EnableDelivery")
.HasColumnType("boolean");
b.Property<bool>("EnableDineIn")
.HasColumnType("boolean");
b.Property<bool>("EnablePickup")
.HasColumnType("boolean");
b.Property<string>("GalleryImages")
.HasMaxLength(1024)
.HasColumnType("character varying(1024)");
b.Property<bool>("IsFeatured")
.HasColumnType("boolean");
b.Property<int?>("MaxQuantityPerOrder")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<decimal?>("OriginalPrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<decimal>("Price")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<string>("SpuCode")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<int?>("StockQuantity")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("Subtitle")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("Unit")
.HasMaxLength(16)
.HasColumnType("character varying(16)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "SpuCode")
.IsUnique();
b.HasIndex("TenantId", "StoreId");
b.ToTable("products", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId");
b.ToTable("product_categories", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime?>("CalledAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int?>("EstimatedWaitMinutes")
.HasColumnType("integer");
b.Property<DateTime?>("ExpiredAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("PartySize")
.HasColumnType("integer");
b.Property<string>("Remark")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("TicketNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId");
b.HasIndex("TenantId", "StoreId", "TicketNumber")
.IsUnique();
b.ToTable("queue_tickets", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("CheckInCode")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("CheckedInAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<string>("CustomerName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("CustomerPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<int>("PeopleCount")
.HasColumnType("integer");
b.Property<string>("Remark")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("ReservationNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("ReservationTime")
.HasColumnType("timestamp with time zone");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<string>("TablePreference")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId", "ReservationNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId");
b.ToTable("reservations", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Announcement")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("BusinessHours")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("City")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<decimal>("DeliveryRadiusKm")
.HasPrecision(6, 2)
.HasColumnType("numeric(6,2)");
b.Property<string>("District")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<double?>("Latitude")
.HasColumnType("double precision");
b.Property<double?>("Longitude")
.HasColumnType("double precision");
b.Property<string>("ManagerName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid>("MerchantId")
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("Phone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<string>("Province")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<bool>("QueueEnabled")
.HasColumnType("boolean");
b.Property<bool>("ReservationEnabled")
.HasColumnType("boolean");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<bool>("SupportsDelivery")
.HasColumnType("boolean");
b.Property<bool>("SupportsDineIn")
.HasColumnType("boolean");
b.Property<bool>("SupportsPickup")
.HasColumnType("boolean");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("MerchantId");
b.HasIndex("TenantId", "Code")
.IsUnique();
b.HasIndex("TenantId", "MerchantId");
b.ToTable("stores", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactEmail")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("ContactName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("ContactPhone")
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("EffectiveFrom")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("EffectiveTo")
.HasColumnType("timestamp with time zone");
b.Property<string>("Industry")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("LogoUrl")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("Remarks")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("ShortName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("tenants", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
{
b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
{
b.HasOne("TakeoutSaaS.Domain.Merchants.Entities.Merchant", "Merchant")
.WithMany()
.HasForeignKey("MerchantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Merchant");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,221 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Merchants.Entities;
using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Payments.Entities;
using TakeoutSaaS.Domain.Products.Entities;
using TakeoutSaaS.Domain.Queues.Entities;
using TakeoutSaaS.Domain.Reservations.Entities;
using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Infrastructure.Common.Persistence;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Infrastructure.App.Persistence;
/// <summary>
/// 业务主库 DbContext。
/// </summary>
public sealed class TakeoutAppDbContext(
DbContextOptions<TakeoutAppDbContext> options,
ITenantProvider tenantProvider,
ICurrentUserAccessor? currentUserAccessor = null)
: TenantAwareDbContext(options, tenantProvider, currentUserAccessor)
{
public DbSet<Tenant> Tenants => Set<Tenant>();
public DbSet<Merchant> Merchants => Set<Merchant>();
public DbSet<Store> Stores => Set<Store>();
public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
public DbSet<Product> Products => Set<Product>();
public DbSet<Order> Orders => Set<Order>();
public DbSet<OrderItem> OrderItems => Set<OrderItem>();
public DbSet<PaymentRecord> PaymentRecords => Set<PaymentRecord>();
public DbSet<Reservation> Reservations => Set<Reservation>();
public DbSet<QueueTicket> QueueTickets => Set<QueueTicket>();
public DbSet<DeliveryOrder> DeliveryOrders => Set<DeliveryOrder>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
ConfigureTenant(modelBuilder.Entity<Tenant>());
ConfigureMerchant(modelBuilder.Entity<Merchant>());
ConfigureStore(modelBuilder.Entity<Store>());
ConfigureProductCategory(modelBuilder.Entity<ProductCategory>());
ConfigureProduct(modelBuilder.Entity<Product>());
ConfigureOrder(modelBuilder.Entity<Order>());
ConfigureOrderItem(modelBuilder.Entity<OrderItem>());
ConfigurePaymentRecord(modelBuilder.Entity<PaymentRecord>());
ConfigureReservation(modelBuilder.Entity<Reservation>());
ConfigureQueueTicket(modelBuilder.Entity<QueueTicket>());
ConfigureDelivery(modelBuilder.Entity<DeliveryOrder>());
ApplyTenantQueryFilters(modelBuilder);
}
private static void ConfigureTenant(EntityTypeBuilder<Tenant> builder)
{
builder.ToTable("tenants");
builder.HasKey(x => x.Id);
builder.Property(x => x.Code).HasMaxLength(64).IsRequired();
builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
builder.Property(x => x.ShortName).HasMaxLength(64);
builder.Property(x => x.ContactName).HasMaxLength(64);
builder.Property(x => x.ContactPhone).HasMaxLength(32);
builder.Property(x => x.ContactEmail).HasMaxLength(128);
builder.Property(x => x.Industry).HasMaxLength(64);
builder.Property(x => x.LogoUrl).HasMaxLength(256);
builder.Property(x => x.Remarks).HasMaxLength(512);
builder.HasIndex(x => x.Code).IsUnique();
}
private static void ConfigureMerchant(EntityTypeBuilder<Merchant> builder)
{
builder.ToTable("merchants");
builder.HasKey(x => x.Id);
builder.Property(x => x.BrandName).HasMaxLength(128).IsRequired();
builder.Property(x => x.BrandAlias).HasMaxLength(64);
builder.Property(x => x.LegalPerson).HasMaxLength(64);
builder.Property(x => x.BusinessLicenseNumber).HasMaxLength(64);
builder.Property(x => x.ContactPhone).HasMaxLength(32).IsRequired();
builder.Property(x => x.ContactEmail).HasMaxLength(128);
builder.Property(x => x.Province).HasMaxLength(64);
builder.Property(x => x.City).HasMaxLength(64);
builder.Property(x => x.District).HasMaxLength(64);
builder.Property(x => x.Address).HasMaxLength(256);
builder.Property(x => x.ReviewRemarks).HasMaxLength(512);
builder.HasIndex(x => x.TenantId);
}
private static void ConfigureStore(EntityTypeBuilder<Store> builder)
{
builder.ToTable("stores");
builder.HasKey(x => x.Id);
builder.Property(x => x.Code).HasMaxLength(32).IsRequired();
builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
builder.Property(x => x.Phone).HasMaxLength(32);
builder.Property(x => x.ManagerName).HasMaxLength(64);
builder.Property(x => x.Province).HasMaxLength(64);
builder.Property(x => x.City).HasMaxLength(64);
builder.Property(x => x.District).HasMaxLength(64);
builder.Property(x => x.Address).HasMaxLength(256);
builder.Property(x => x.BusinessHours).HasMaxLength(256);
builder.Property(x => x.Announcement).HasMaxLength(512);
builder.Property(x => x.DeliveryRadiusKm).HasPrecision(6, 2);
builder.HasIndex(x => new { x.TenantId, x.MerchantId });
builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
}
private static void ConfigureProductCategory(EntityTypeBuilder<ProductCategory> builder)
{
builder.ToTable("product_categories");
builder.HasKey(x => x.Id);
builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
builder.Property(x => x.Description).HasMaxLength(256);
builder.HasIndex(x => new { x.TenantId, x.StoreId });
}
private static void ConfigureProduct(EntityTypeBuilder<Product> builder)
{
builder.ToTable("products");
builder.HasKey(x => x.Id);
builder.Property(x => x.SpuCode).HasMaxLength(32).IsRequired();
builder.Property(x => x.Name).HasMaxLength(128).IsRequired();
builder.Property(x => x.Subtitle).HasMaxLength(256);
builder.Property(x => x.Unit).HasMaxLength(16);
builder.Property(x => x.Price).HasPrecision(18, 2);
builder.Property(x => x.OriginalPrice).HasPrecision(18, 2);
builder.Property(x => x.CoverImage).HasMaxLength(256);
builder.Property(x => x.GalleryImages).HasMaxLength(1024);
builder.Property(x => x.Description).HasColumnType("text");
builder.HasIndex(x => new { x.TenantId, x.StoreId });
builder.HasIndex(x => new { x.TenantId, x.SpuCode }).IsUnique();
}
private static void ConfigureOrder(EntityTypeBuilder<Order> builder)
{
builder.ToTable("orders");
builder.HasKey(x => x.Id);
builder.Property(x => x.OrderNo).HasMaxLength(32).IsRequired();
builder.Property(x => x.CustomerName).HasMaxLength(64);
builder.Property(x => x.CustomerPhone).HasMaxLength(32);
builder.Property(x => x.TableNo).HasMaxLength(32);
builder.Property(x => x.QueueNumber).HasMaxLength(32);
builder.Property(x => x.CancelReason).HasMaxLength(256);
builder.Property(x => x.Remark).HasMaxLength(512);
builder.Property(x => x.ItemsAmount).HasPrecision(18, 2);
builder.Property(x => x.DiscountAmount).HasPrecision(18, 2);
builder.Property(x => x.PayableAmount).HasPrecision(18, 2);
builder.Property(x => x.PaidAmount).HasPrecision(18, 2);
builder.HasIndex(x => new { x.TenantId, x.OrderNo }).IsUnique();
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Status });
}
private static void ConfigureOrderItem(EntityTypeBuilder<OrderItem> builder)
{
builder.ToTable("order_items");
builder.HasKey(x => x.Id);
builder.Property(x => x.ProductName).HasMaxLength(128).IsRequired();
builder.Property(x => x.SkuName).HasMaxLength(128);
builder.Property(x => x.Unit).HasMaxLength(16);
builder.Property(x => x.UnitPrice).HasPrecision(18, 2);
builder.Property(x => x.DiscountAmount).HasPrecision(18, 2);
builder.Property(x => x.SubTotal).HasPrecision(18, 2);
builder.Property(x => x.AttributesJson).HasColumnType("text");
builder.HasIndex(x => new { x.TenantId, x.OrderId });
builder.HasOne<Order>()
.WithMany()
.HasForeignKey(x => x.OrderId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigurePaymentRecord(EntityTypeBuilder<PaymentRecord> builder)
{
builder.ToTable("payment_records");
builder.HasKey(x => x.Id);
builder.Property(x => x.Amount).HasPrecision(18, 2);
builder.Property(x => x.TradeNo).HasMaxLength(64);
builder.Property(x => x.ChannelTransactionId).HasMaxLength(64);
builder.Property(x => x.Remark).HasMaxLength(256);
builder.Property(x => x.Payload).HasColumnType("text");
builder.HasIndex(x => new { x.TenantId, x.OrderId });
}
private static void ConfigureReservation(EntityTypeBuilder<Reservation> builder)
{
builder.ToTable("reservations");
builder.HasKey(x => x.Id);
builder.Property(x => x.ReservationNo).HasMaxLength(32).IsRequired();
builder.Property(x => x.CustomerName).HasMaxLength(64).IsRequired();
builder.Property(x => x.CustomerPhone).HasMaxLength(32).IsRequired();
builder.Property(x => x.TablePreference).HasMaxLength(64);
builder.Property(x => x.Remark).HasMaxLength(512);
builder.Property(x => x.CheckInCode).HasMaxLength(32);
builder.HasIndex(x => new { x.TenantId, x.StoreId });
builder.HasIndex(x => new { x.TenantId, x.ReservationNo }).IsUnique();
}
private static void ConfigureQueueTicket(EntityTypeBuilder<QueueTicket> builder)
{
builder.ToTable("queue_tickets");
builder.HasKey(x => x.Id);
builder.Property(x => x.TicketNumber).HasMaxLength(32).IsRequired();
builder.Property(x => x.Remark).HasMaxLength(256);
builder.HasIndex(x => new { x.TenantId, x.StoreId });
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.TicketNumber }).IsUnique();
}
private static void ConfigureDelivery(EntityTypeBuilder<DeliveryOrder> builder)
{
builder.ToTable("delivery_orders");
builder.HasKey(x => x.Id);
builder.Property(x => x.ProviderOrderId).HasMaxLength(64);
builder.Property(x => x.DeliveryFee).HasPrecision(18, 2);
builder.Property(x => x.CourierName).HasMaxLength(64);
builder.Property(x => x.CourierPhone).HasMaxLength(32);
builder.Property(x => x.FailureReason).HasMaxLength(256);
builder.HasIndex(x => new { x.TenantId, x.OrderId }).IsUnique();
}
}

View File

@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Infrastructure.App.Persistence;
/// <summary>
/// 设计时工厂,供 EF CLI 使用。
/// </summary>
internal sealed class TakeoutAppDesignTimeDbContextFactory
: DesignTimeDbContextFactoryBase<TakeoutAppDbContext>
{
public TakeoutAppDesignTimeDbContextFactory()
: base("TAKEOUTSAAS_APP_CONNECTION", "takeout_saas_app")
{
}
protected override TakeoutAppDbContext CreateContext(
DbContextOptions<TakeoutAppDbContext> options,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor)
=> new(options, tenantProvider, currentUserAccessor);
}

View File

@@ -0,0 +1,68 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using TakeoutSaaS.Infrastructure.Common.Persistence;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
/// <summary>
/// EF Core 设计时 DbContext 工厂基类,提供统一的连接串与依赖替身。
/// </summary>
internal abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDbContextFactory<TContext>
where TContext : TenantAwareDbContext
{
private readonly string _connectionStringEnvVar;
private readonly string _defaultDatabase;
protected DesignTimeDbContextFactoryBase(string connectionStringEnvVar, string defaultDatabase)
{
_connectionStringEnvVar = connectionStringEnvVar;
_defaultDatabase = defaultDatabase;
}
public TContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<TContext>();
optionsBuilder.UseNpgsql(
ResolveConnectionString(),
npgsql =>
{
npgsql.CommandTimeout(30);
npgsql.EnableRetryOnFailure();
});
return CreateContext(
optionsBuilder.Options,
new DesignTimeTenantProvider(),
new DesignTimeCurrentUserAccessor());
}
protected abstract TContext CreateContext(
DbContextOptions<TContext> options,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor);
private string ResolveConnectionString()
{
var env = Environment.GetEnvironmentVariable(_connectionStringEnvVar);
if (!string.IsNullOrWhiteSpace(env))
{
return env;
}
return $"Host=localhost;Port=5432;Database={_defaultDatabase};Username=postgres;Password=postgres";
}
private sealed class DesignTimeTenantProvider : ITenantProvider
{
public Guid GetCurrentTenantId() => Guid.Empty;
}
private sealed class DesignTimeCurrentUserAccessor : ICurrentUserAccessor
{
public Guid UserId => Guid.Empty;
public bool IsAuthenticated => false;
}
}

View File

@@ -0,0 +1,172 @@
// <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("20251201042346_InitialDictionary")]
partial class InitialDictionary
{
/// <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");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<bool>("IsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<int>("Scope")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "Code")
.IsUnique();
b.ToTable("dictionary_groups", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<Guid>("GroupId")
.HasColumnType("uuid");
b.Property<bool>("IsDefault")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("SortOrder")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(100);
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("GroupId", "Key")
.IsUnique();
b.ToTable("dictionary_items", (string)null);
});
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
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TakeoutSaaS.Infrastructure.Dictionary.Migrations
{
/// <inheritdoc />
public partial class InitialDictionary : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "dictionary_groups",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
Name = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
Scope = table.Column<int>(type: "integer", nullable: false),
Description = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_dictionary_groups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "dictionary_items",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
GroupId = table.Column<Guid>(type: "uuid", nullable: false),
Key = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
Value = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
IsDefault = table.Column<bool>(type: "boolean", nullable: false),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true),
SortOrder = table.Column<int>(type: "integer", nullable: false, defaultValue: 100),
Description = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_dictionary_items", x => x.Id);
table.ForeignKey(
name: "FK_dictionary_items_dictionary_groups_GroupId",
column: x => x.GroupId,
principalTable: "dictionary_groups",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_dictionary_groups_TenantId",
table: "dictionary_groups",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_dictionary_groups_TenantId_Code",
table: "dictionary_groups",
columns: new[] { "TenantId", "Code" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_dictionary_items_GroupId_Key",
table: "dictionary_items",
columns: new[] { "GroupId", "Key" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_dictionary_items_TenantId",
table: "dictionary_items",
column: "TenantId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "dictionary_items");
migrationBuilder.DropTable(
name: "dictionary_groups");
}
}
}

View File

@@ -0,0 +1,169 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
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))]
partial class DictionaryDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(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");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<bool>("IsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<int>("Scope")
.HasColumnType("integer");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "Code")
.IsUnique();
b.ToTable("dictionary_groups", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Dictionary.Entities.DictionaryItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<Guid>("GroupId")
.HasColumnType("uuid");
b.Property<bool>("IsDefault")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("SortOrder")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(100);
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("GroupId", "Key")
.IsUnique();
b.ToTable("dictionary_items", (string)null);
});
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
}
}
}

View File

@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Infrastructure.Dictionary.Persistence;
/// <summary>
/// 设计时 DictionaryDbContext 工厂。
/// </summary>
internal sealed class DictionaryDesignTimeDbContextFactory
: DesignTimeDbContextFactoryBase<DictionaryDbContext>
{
public DictionaryDesignTimeDbContextFactory()
: base("TAKEOUTSAAS_APP_CONNECTION", "takeout_saas_app")
{
}
protected override DictionaryDbContext CreateContext(
DbContextOptions<DictionaryDbContext> options,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor)
=> new(options, tenantProvider, currentUserAccessor);
}

View File

@@ -0,0 +1,152 @@
// <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("20251201042324_InitialIdentity")]
partial class InitialIdentity
{
/// <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");
b.Property<string>("Account")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("Avatar")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid?>("MerchantId")
.HasColumnType("uuid");
b.Property<string>("PasswordHash")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Permissions")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Roles")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "Account")
.IsUnique();
b.ToTable("identity_users", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Nickname")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("OpenId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("UnionId")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "OpenId")
.IsUnique();
b.ToTable("mini_users", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TakeoutSaaS.Infrastructure.Identity.Migrations
{
/// <inheritdoc />
public partial class InitialIdentity : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "identity_users",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Account = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
DisplayName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
PasswordHash = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
MerchantId = table.Column<Guid>(type: "uuid", nullable: true),
Roles = table.Column<string>(type: "text", nullable: false),
Permissions = table.Column<string>(type: "text", nullable: false),
Avatar = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_identity_users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "mini_users",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OpenId = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
UnionId = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
Nickname = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
Avatar = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DeletedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
CreatedBy = table.Column<Guid>(type: "uuid", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uuid", nullable: true),
DeletedBy = table.Column<Guid>(type: "uuid", nullable: true),
TenantId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_mini_users", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_identity_users_TenantId",
table: "identity_users",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_identity_users_TenantId_Account",
table: "identity_users",
columns: new[] { "TenantId", "Account" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_mini_users_TenantId",
table: "mini_users",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_mini_users_TenantId_OpenId",
table: "mini_users",
columns: new[] { "TenantId", "OpenId" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "identity_users");
migrationBuilder.DropTable(
name: "mini_users");
}
}
}

View File

@@ -0,0 +1,149 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
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))]
partial class IdentityDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(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");
b.Property<string>("Account")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("Avatar")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<Guid?>("MerchantId")
.HasColumnType("uuid");
b.Property<string>("PasswordHash")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Permissions")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Roles")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "Account")
.IsUnique();
b.ToTable("identity_users", (string)null);
});
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uuid");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DeletedBy")
.HasColumnType("uuid");
b.Property<string>("Nickname")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("OpenId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<Guid>("TenantId")
.HasColumnType("uuid");
b.Property<string>("UnionId")
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("TenantId");
b.HasIndex("TenantId", "OpenId")
.IsUnique();
b.ToTable("mini_users", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Infrastructure.Common.Persistence.DesignTime;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Infrastructure.Identity.Persistence;
/// <summary>
/// 设计时 IdentityDbContext 工厂,供 EF Core CLI 生成迁移使用。
/// </summary>
internal sealed class IdentityDesignTimeDbContextFactory
: DesignTimeDbContextFactoryBase<IdentityDbContext>
{
public IdentityDesignTimeDbContextFactory()
: base("TAKEOUTSAAS_IDENTITY_CONNECTION", "takeout_saas_identity")
{
}
protected override IdentityDbContext CreateContext(
DbContextOptions<IdentityDbContext> options,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor)
=> new(options, tenantProvider, currentUserAccessor);
}

View File

@@ -8,6 +8,10 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />