feat: migrate snowflake ids and refresh migrations
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TakeoutSaaS.Domain.Deliveries.Repositories;
|
||||
using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Domain.Payments.Repositories;
|
||||
using TakeoutSaaS.Domain.Products.Repositories;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Options;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
using TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.Common.Extensions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// 业务主库基础设施注册扩展。
|
||||
/// </summary>
|
||||
public static class AppServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册业务主库 DbContext 与仓储。
|
||||
/// </summary>
|
||||
/// <param name="services">服务集合。</param>
|
||||
/// <param name="configuration">配置源。</param>
|
||||
/// <returns>服务集合。</returns>
|
||||
public static IServiceCollection AddAppInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddDatabaseInfrastructure(configuration);
|
||||
services.AddPostgresDbContext<TakeoutAppDbContext>(DatabaseConstants.AppDataSource);
|
||||
|
||||
services.AddScoped<IMerchantRepository, EfMerchantRepository>();
|
||||
services.AddScoped<IStoreRepository, EfStoreRepository>();
|
||||
services.AddScoped<IProductRepository, EfProductRepository>();
|
||||
services.AddScoped<IOrderRepository, EfOrderRepository>();
|
||||
services.AddScoped<IPaymentRepository, EfPaymentRepository>();
|
||||
services.AddScoped<IDeliveryRepository, EfDeliveryRepository>();
|
||||
|
||||
services.AddOptions<AppSeedOptions>()
|
||||
.Bind(configuration.GetSection(AppSeedOptions.SectionName))
|
||||
.ValidateDataAnnotations();
|
||||
|
||||
services.AddHostedService<AppDataSeeder>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -1,949 +0,0 @@
|
||||
// <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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,497 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Options;
|
||||
|
||||
/// <summary>
|
||||
/// 业务数据种子配置。
|
||||
/// </summary>
|
||||
public sealed class AppSeedOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置节名称。
|
||||
/// </summary>
|
||||
public const string SectionName = "App:Seed";
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用业务数据种子。
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认租户配置。
|
||||
/// </summary>
|
||||
public TenantSeedOptions? DefaultTenant { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 基础字典分组。
|
||||
/// </summary>
|
||||
public List<DictionarySeedGroupOptions> DictionaryGroups { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using TakeoutSaaS.Domain.Dictionary.Enums;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Options;
|
||||
|
||||
/// <summary>
|
||||
/// 字典分组种子配置。
|
||||
/// </summary>
|
||||
public sealed class DictionarySeedGroupOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属租户,不填则使用默认租户或系统租户。
|
||||
/// </summary>
|
||||
public long? TenantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分组编码。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分组名称。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(128)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分组作用域。
|
||||
/// </summary>
|
||||
public DictionaryScope Scope { get; set; } = DictionaryScope.Business;
|
||||
|
||||
/// <summary>
|
||||
/// 描述信息。
|
||||
/// </summary>
|
||||
[MaxLength(512)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用。
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 字典项集合。
|
||||
/// </summary>
|
||||
public List<DictionarySeedItemOptions> Items { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Options;
|
||||
|
||||
/// <summary>
|
||||
/// 字典项种子配置。
|
||||
/// </summary>
|
||||
public sealed class DictionarySeedItemOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典项键。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 字典项值。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(256)]
|
||||
public string Value { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 描述。
|
||||
/// </summary>
|
||||
[MaxLength(512)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序。
|
||||
/// </summary>
|
||||
public int SortOrder { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用。
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Options;
|
||||
|
||||
/// <summary>
|
||||
/// 默认租户种子配置。
|
||||
/// </summary>
|
||||
public sealed class TenantSeedOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义租户标识,不填则自动生成。
|
||||
/// </summary>
|
||||
public long TenantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户编码。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 租户名称。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(128)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 租户简称。
|
||||
/// </summary>
|
||||
[MaxLength(128)]
|
||||
public string? ShortName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 联系人姓名。
|
||||
/// </summary>
|
||||
[MaxLength(64)]
|
||||
public string? ContactName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 联系电话。
|
||||
/// </summary>
|
||||
[MaxLength(32)]
|
||||
public string? ContactPhone { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TakeoutSaaS.Domain.Dictionary.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Infrastructure.App.Options;
|
||||
using TakeoutSaaS.Infrastructure.Dictionary.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// 业务数据种子,确保默认租户与基础字典可重复执行。
|
||||
/// </summary>
|
||||
public sealed class AppDataSeeder : IHostedService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<AppDataSeeder> _logger;
|
||||
private readonly AppSeedOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化种子服务。
|
||||
/// </summary>
|
||||
public AppDataSeeder(
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<AppDataSeeder> logger,
|
||||
IOptions<AppSeedOptions> options)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_options.Enabled)
|
||||
{
|
||||
_logger.LogInformation("AppSeed 未启用,跳过业务数据初始化");
|
||||
return;
|
||||
}
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var appDbContext = scope.ServiceProvider.GetRequiredService<TakeoutAppDbContext>();
|
||||
var dictionaryDbContext = scope.ServiceProvider.GetRequiredService<DictionaryDbContext>();
|
||||
|
||||
var defaultTenantId = await EnsureDefaultTenantAsync(appDbContext, cancellationToken);
|
||||
await EnsureDictionarySeedsAsync(dictionaryDbContext, defaultTenantId, cancellationToken);
|
||||
|
||||
_logger.LogInformation("AppSeed 完成业务数据初始化");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// 确保默认租户存在。
|
||||
/// </summary>
|
||||
private async Task<long?> EnsureDefaultTenantAsync(TakeoutAppDbContext dbContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantOptions = _options.DefaultTenant;
|
||||
if (tenantOptions == null || string.IsNullOrWhiteSpace(tenantOptions.Code) || string.IsNullOrWhiteSpace(tenantOptions.Name))
|
||||
{
|
||||
_logger.LogInformation("AppSeed 未配置默认租户,跳过租户种子");
|
||||
return null;
|
||||
}
|
||||
|
||||
var code = tenantOptions.Code.Trim();
|
||||
var existingTenant = await dbContext.Tenants
|
||||
.IgnoreQueryFilters()
|
||||
.FirstOrDefaultAsync(x => x.Code == code, cancellationToken);
|
||||
|
||||
if (existingTenant == null)
|
||||
{
|
||||
var tenant = new Tenant
|
||||
{
|
||||
Id = tenantOptions.TenantId,
|
||||
Code = code,
|
||||
Name = tenantOptions.Name.Trim(),
|
||||
ShortName = tenantOptions.ShortName?.Trim(),
|
||||
ContactName = tenantOptions.ContactName?.Trim(),
|
||||
ContactPhone = tenantOptions.ContactPhone?.Trim(),
|
||||
Status = TenantStatus.Active
|
||||
};
|
||||
|
||||
await dbContext.Tenants.AddAsync(tenant, cancellationToken);
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("AppSeed 已创建默认租户 {TenantCode}", code);
|
||||
return tenant.Id;
|
||||
}
|
||||
|
||||
var updated = false;
|
||||
|
||||
if (!string.Equals(existingTenant.Name, tenantOptions.Name, StringComparison.Ordinal))
|
||||
{
|
||||
existingTenant.Name = tenantOptions.Name.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(existingTenant.ShortName, tenantOptions.ShortName, StringComparison.Ordinal))
|
||||
{
|
||||
existingTenant.ShortName = tenantOptions.ShortName?.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(existingTenant.ContactName, tenantOptions.ContactName, StringComparison.Ordinal))
|
||||
{
|
||||
existingTenant.ContactName = tenantOptions.ContactName?.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(existingTenant.ContactPhone, tenantOptions.ContactPhone, StringComparison.Ordinal))
|
||||
{
|
||||
existingTenant.ContactPhone = tenantOptions.ContactPhone?.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (existingTenant.Status != TenantStatus.Active)
|
||||
{
|
||||
existingTenant.Status = TenantStatus.Active;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
dbContext.Tenants.Update(existingTenant);
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("AppSeed 已更新默认租户 {TenantCode}", code);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("AppSeed 默认租户 {TenantCode} 已存在且无需更新", code);
|
||||
}
|
||||
|
||||
return existingTenant.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保基础字典存在。
|
||||
/// </summary>
|
||||
private async Task EnsureDictionarySeedsAsync(DictionaryDbContext dbContext, long? defaultTenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_options.DictionaryGroups == null || _options.DictionaryGroups.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("AppSeed 未配置基础字典,跳过字典种子");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var groupOptions in _options.DictionaryGroups)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(groupOptions.Code) || string.IsNullOrWhiteSpace(groupOptions.Name))
|
||||
{
|
||||
_logger.LogWarning("AppSeed 跳过字典分组,Code 或 Name 为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
var tenantId = groupOptions.TenantId ?? defaultTenantId ?? 0;
|
||||
var code = groupOptions.Code.Trim();
|
||||
|
||||
var group = await dbContext.DictionaryGroups
|
||||
.IgnoreQueryFilters()
|
||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Code == code, cancellationToken);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
group = new DictionaryGroup
|
||||
{
|
||||
Id = 0,
|
||||
TenantId = tenantId,
|
||||
Code = code,
|
||||
Name = groupOptions.Name.Trim(),
|
||||
Scope = groupOptions.Scope,
|
||||
Description = groupOptions.Description?.Trim(),
|
||||
IsEnabled = groupOptions.IsEnabled
|
||||
};
|
||||
|
||||
await dbContext.DictionaryGroups.AddAsync(group, cancellationToken);
|
||||
_logger.LogInformation("AppSeed 创建字典分组 {GroupCode} (Tenant: {TenantId})", code, tenantId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var groupUpdated = false;
|
||||
|
||||
if (!string.Equals(group.Name, groupOptions.Name, StringComparison.Ordinal))
|
||||
{
|
||||
group.Name = groupOptions.Name.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(group.Description, groupOptions.Description, StringComparison.Ordinal))
|
||||
{
|
||||
group.Description = groupOptions.Description?.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.Scope != groupOptions.Scope)
|
||||
{
|
||||
group.Scope = groupOptions.Scope;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.IsEnabled != groupOptions.IsEnabled)
|
||||
{
|
||||
group.IsEnabled = groupOptions.IsEnabled;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (groupUpdated)
|
||||
{
|
||||
dbContext.DictionaryGroups.Update(group);
|
||||
}
|
||||
}
|
||||
|
||||
await UpsertDictionaryItemsAsync(dbContext, group, groupOptions.Items, tenantId, cancellationToken);
|
||||
}
|
||||
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并字典项。
|
||||
/// </summary>
|
||||
private static async Task UpsertDictionaryItemsAsync(
|
||||
DictionaryDbContext dbContext,
|
||||
DictionaryGroup group,
|
||||
IEnumerable<DictionarySeedItemOptions> seedItems,
|
||||
long tenantId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var materializedItems = seedItems
|
||||
.Where(item => !string.IsNullOrWhiteSpace(item.Key) && !string.IsNullOrWhiteSpace(item.Value))
|
||||
.ToList();
|
||||
|
||||
if (materializedItems.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var existingItems = await dbContext.DictionaryItems
|
||||
.IgnoreQueryFilters()
|
||||
.Where(x => x.GroupId == group.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var seed in materializedItems)
|
||||
{
|
||||
var key = seed.Key.Trim();
|
||||
var existing = existingItems.FirstOrDefault(x => x.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
var newItem = new DictionaryItem
|
||||
{
|
||||
Id = 0,
|
||||
TenantId = tenantId,
|
||||
GroupId = group.Id,
|
||||
Key = key,
|
||||
Value = seed.Value.Trim(),
|
||||
Description = seed.Description?.Trim(),
|
||||
SortOrder = seed.SortOrder,
|
||||
IsEnabled = seed.IsEnabled
|
||||
};
|
||||
|
||||
await dbContext.DictionaryItems.AddAsync(newItem, cancellationToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
var updated = false;
|
||||
|
||||
if (!string.Equals(existing.Value, seed.Value, StringComparison.Ordinal))
|
||||
{
|
||||
existing.Value = seed.Value.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(existing.Description, seed.Description, StringComparison.Ordinal))
|
||||
{
|
||||
existing.Description = seed.Description?.Trim();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (existing.SortOrder != seed.SortOrder)
|
||||
{
|
||||
existing.SortOrder = seed.SortOrder;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (existing.IsEnabled != seed.IsEnabled)
|
||||
{
|
||||
existing.IsEnabled = seed.IsEnabled;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
dbContext.DictionaryItems.Update(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ using TakeoutSaaS.Domain.Reservations.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Entities;
|
||||
using TakeoutSaaS.Infrastructure.Common.Persistence;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
@@ -31,8 +32,9 @@ namespace TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
public sealed class TakeoutAppDbContext(
|
||||
DbContextOptions<TakeoutAppDbContext> options,
|
||||
ITenantProvider tenantProvider,
|
||||
ICurrentUserAccessor? currentUserAccessor = null)
|
||||
: TenantAwareDbContext(options, tenantProvider, currentUserAccessor)
|
||||
ICurrentUserAccessor? currentUserAccessor = null,
|
||||
IIdGenerator? idGenerator = null)
|
||||
: TenantAwareDbContext(options, tenantProvider, currentUserAccessor, idGenerator)
|
||||
{
|
||||
public DbSet<Tenant> Tenants => Set<Tenant>();
|
||||
public DbSet<TenantPackage> TenantPackages => Set<TenantPackage>();
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Deliveries.Entities;
|
||||
using TakeoutSaaS.Domain.Deliveries.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 配送聚合的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfDeliveryRepository : IDeliveryRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfDeliveryRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<DeliveryOrder?> FindByIdAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.DeliveryOrders
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == deliveryOrderId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<DeliveryOrder?> FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.DeliveryOrders
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderId == orderId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DeliveryEvent>> GetEventsAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var events = await _context.DeliveryEvents
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.DeliveryOrderId == deliveryOrderId)
|
||||
.OrderBy(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.DeliveryOrders.AddAsync(deliveryOrder, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddEventAsync(DeliveryEvent deliveryEvent, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.DeliveryEvents.AddAsync(deliveryEvent, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Merchants.Entities;
|
||||
using TakeoutSaaS.Domain.Merchants.Enums;
|
||||
using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 商户聚合的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfMerchantRepository : IMerchantRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfMerchantRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Merchant?> FindByIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Merchants
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == merchantId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = _context.Merchants
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId);
|
||||
|
||||
if (status.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.Status == status.Value);
|
||||
}
|
||||
|
||||
return await query
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<MerchantStaff>> GetStaffAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var staffs = await _context.MerchantStaff
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
||||
.OrderBy(x => x.Name)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return staffs;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<MerchantContract>> GetContractsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var contracts = await _context.MerchantContracts
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return contracts;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<MerchantDocument>> GetDocumentsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var documents = await _context.MerchantDocuments
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
||||
.OrderBy(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return documents;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddMerchantAsync(Merchant merchant, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Merchants.AddAsync(merchant, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddStaffAsync(MerchantStaff staff, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.MerchantStaff.AddAsync(staff, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddContractAsync(MerchantContract contract, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.MerchantContracts.AddAsync(contract, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddDocumentAsync(MerchantDocument document, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.MerchantDocuments.AddAsync(document, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Enums;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Domain.Payments.Enums;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 订单聚合的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfOrderRepository : IOrderRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfOrderRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Order?> FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Orders
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == orderId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Order?> FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Orders
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderNo == orderNo)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<Order>> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = _context.Orders
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId);
|
||||
|
||||
if (status.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.Status == status.Value);
|
||||
}
|
||||
|
||||
if (paymentStatus.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.PaymentStatus == paymentStatus.Value);
|
||||
}
|
||||
|
||||
var orders = await query
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<OrderItem>> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var items = await _context.OrderItems
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderId == orderId)
|
||||
.OrderBy(x => x.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<OrderStatusHistory>> GetStatusHistoryAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var histories = await _context.OrderStatusHistories
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderId == orderId)
|
||||
.OrderBy(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return histories;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<RefundRequest>> GetRefundsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var refunds = await _context.RefundRequests
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderId == orderId)
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return refunds;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddOrderAsync(Order order, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Orders.AddAsync(order, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddItemsAsync(IEnumerable<OrderItem> items, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.OrderItems.AddRangeAsync(items, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.OrderStatusHistories.AddAsync(history, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddRefundAsync(RefundRequest refund, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.RefundRequests.AddAsync(refund, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Payments.Entities;
|
||||
using TakeoutSaaS.Domain.Payments.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 支付记录的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfPaymentRepository : IPaymentRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfPaymentRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PaymentRecord?> FindByIdAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.PaymentRecords
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == paymentId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PaymentRecord?> FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.PaymentRecords
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.OrderId == orderId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<PaymentRefundRecord>> GetRefundsAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var refunds = await _context.PaymentRefundRecords
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.PaymentRecordId == paymentId)
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return refunds;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddPaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.PaymentRecords.AddAsync(payment, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddRefundAsync(PaymentRefundRecord refund, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.PaymentRefundRecords.AddAsync(refund, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Products.Entities;
|
||||
using TakeoutSaaS.Domain.Products.Enums;
|
||||
using TakeoutSaaS.Domain.Products.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 商品聚合的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfProductRepository : IProductRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfProductRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Product?> FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Products
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == productId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = _context.Products
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId);
|
||||
|
||||
if (categoryId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.CategoryId == categoryId.Value);
|
||||
}
|
||||
|
||||
if (status.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.Status == status.Value);
|
||||
}
|
||||
|
||||
var products = await query
|
||||
.OrderBy(x => x.Name)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return products;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductCategory>> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var categories = await _context.ProductCategories
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductSku>> GetSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var skus = await _context.ProductSkus
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return skus;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductAddonGroup>> GetAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var groups = await _context.ProductAddonGroups
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductAddonOption>> GetAddonOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var groupIds = await _context.ProductAddonGroups
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (groupIds.Count == 0)
|
||||
{
|
||||
return Array.Empty<ProductAddonOption>();
|
||||
}
|
||||
|
||||
var options = await _context.ProductAddonOptions
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && groupIds.Contains(x.AddonGroupId))
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductAttributeGroup>> GetAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var groups = await _context.ProductAttributeGroups
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductAttributeOption>> GetAttributeOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var groupIds = await _context.ProductAttributeGroups
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (groupIds.Count == 0)
|
||||
{
|
||||
return Array.Empty<ProductAttributeOption>();
|
||||
}
|
||||
|
||||
var options = await _context.ProductAttributeOptions
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && groupIds.Contains(x.AttributeGroupId))
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductMediaAsset>> GetMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var assets = await _context.ProductMediaAssets
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<ProductPricingRule>> GetPricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var rules = await _context.ProductPricingRules
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.ProductId == productId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.ProductCategories.AddAsync(category, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddProductAsync(Product product, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Products.AddAsync(product, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddSkusAsync(IEnumerable<ProductSku> skus, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.ProductSkus.AddRangeAsync(skus, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddAddonGroupsAsync(IEnumerable<ProductAddonGroup> groups, IEnumerable<ProductAddonOption> options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var addGroupsTask = _context.ProductAddonGroups.AddRangeAsync(groups, cancellationToken);
|
||||
var addOptionsTask = _context.ProductAddonOptions.AddRangeAsync(options, cancellationToken);
|
||||
return Task.WhenAll(addGroupsTask, addOptionsTask);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddAttributeGroupsAsync(IEnumerable<ProductAttributeGroup> groups, IEnumerable<ProductAttributeOption> options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var addGroupsTask = _context.ProductAttributeGroups.AddRangeAsync(groups, cancellationToken);
|
||||
var addOptionsTask = _context.ProductAttributeOptions.AddRangeAsync(options, cancellationToken);
|
||||
return Task.WhenAll(addGroupsTask, addOptionsTask);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddMediaAssetsAsync(IEnumerable<ProductMediaAsset> assets, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.ProductMediaAssets.AddRangeAsync(assets, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddPricingRulesAsync(IEnumerable<ProductPricingRule> rules, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.ProductPricingRules.AddRangeAsync(rules, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Enums;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 门店聚合的 EF Core 仓储实现。
|
||||
/// </summary>
|
||||
public sealed class EfStoreRepository : IStoreRepository
|
||||
{
|
||||
private readonly TakeoutAppDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仓储。
|
||||
/// </summary>
|
||||
public EfStoreRepository(TakeoutAppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Store?> FindByIdAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Stores
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.Id == storeId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<Store>> SearchAsync(long tenantId, StoreStatus? status, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = _context.Stores
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId);
|
||||
|
||||
if (status.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.Status == status.Value);
|
||||
}
|
||||
|
||||
var stores = await query
|
||||
.OrderBy(x => x.Name)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return stores;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreBusinessHour>> GetBusinessHoursAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var hours = await _context.StoreBusinessHours
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.DayOfWeek)
|
||||
.ThenBy(x => x.StartTime)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return hours;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreDeliveryZone>> GetDeliveryZonesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var zones = await _context.StoreDeliveryZones
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return zones;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreHoliday>> GetHolidaysAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var holidays = await _context.StoreHolidays
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.Date)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return holidays;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreTableArea>> GetTableAreasAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var areas = await _context.StoreTableAreas
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return areas;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreTable>> GetTablesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var tables = await _context.StoreTables
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.TableCode)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreEmployeeShift>> GetShiftsAsync(long storeId, long tenantId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var shifts = await _context.StoreEmployeeShifts
|
||||
.AsNoTracking()
|
||||
.Where(x => x.TenantId == tenantId && x.StoreId == storeId)
|
||||
.OrderBy(x => x.ShiftDate)
|
||||
.ThenBy(x => x.StartTime)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return shifts;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddStoreAsync(Store store, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.Stores.AddAsync(store, cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddBusinessHoursAsync(IEnumerable<StoreBusinessHour> hours, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreBusinessHours.AddRangeAsync(hours, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddDeliveryZonesAsync(IEnumerable<StoreDeliveryZone> zones, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreDeliveryZones.AddRangeAsync(zones, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddHolidaysAsync(IEnumerable<StoreHoliday> holidays, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreHolidays.AddRangeAsync(holidays, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddTableAreasAsync(IEnumerable<StoreTableArea> areas, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreTableAreas.AddRangeAsync(areas, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddTablesAsync(IEnumerable<StoreTable> tables, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreTables.AddRangeAsync(tables, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task AddShiftsAsync(IEnumerable<StoreEmployeeShift> shifts, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.StoreEmployeeShifts.AddRangeAsync(shifts, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user