feat: add mini ordering catalog and order APIs
All checks were successful
Build and Deploy MiniApi / build-and-deploy (push) Successful in 23s

This commit is contained in:
2026-03-10 10:03:32 +08:00
parent 2a0e2e6d62
commit 227266d183
33 changed files with 2483 additions and 19 deletions

View File

@@ -0,0 +1,92 @@
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Domain.Payments.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 小程序订单聚合根。
/// </summary>
public sealed class Order : MultiTenantEntityBase
{
/// <summary>
/// 订单号。
/// </summary>
public string OrderNo { get; set; } = string.Empty;
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; set; }
/// <summary>
/// 下单渠道。
/// </summary>
public OrderChannel Channel { get; set; } = OrderChannel.MiniProgram;
/// <summary>
/// 履约方式。
/// </summary>
public DeliveryType DeliveryType { get; set; } = DeliveryType.Delivery;
/// <summary>
/// 订单状态。
/// </summary>
public OrderStatus Status { get; set; } = OrderStatus.PendingPayment;
/// <summary>
/// 支付状态。
/// </summary>
public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Unpaid;
/// <summary>
/// 顾客姓名。
/// </summary>
public string? CustomerName { get; set; }
/// <summary>
/// 顾客手机号。
/// </summary>
public string? CustomerPhone { get; set; }
/// <summary>
/// 桌号。
/// </summary>
public string? TableNo { get; set; }
/// <summary>
/// 排队号。
/// </summary>
public string? QueueNumber { get; set; }
/// <summary>
/// 预约 ID。
/// </summary>
public long? ReservationId { get; set; }
/// <summary>
/// 商品原价合计。
/// </summary>
public decimal ItemsAmount { get; set; }
/// <summary>
/// 优惠金额。
/// </summary>
public decimal DiscountAmount { get; set; }
/// <summary>
/// 应付金额。
/// </summary>
public decimal PayableAmount { get; set; }
/// <summary>
/// 实付金额。
/// </summary>
public decimal PaidAmount { get; set; }
/// <summary>
/// 支付时间。
/// </summary>
public DateTime? PaidAt { get; set; }
/// <summary>
/// 完成时间。
/// </summary>
public DateTime? FinishedAt { get; set; }
/// <summary>
/// 取消时间。
/// </summary>
public DateTime? CancelledAt { get; set; }
/// <summary>
/// 取消原因。
/// </summary>
public string? CancelReason { get; set; }
/// <summary>
/// 订单备注。
/// </summary>
public string? Remark { get; set; }
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 订单明细。
/// </summary>
public sealed class OrderItem : MultiTenantEntityBase
{
/// <summary>
/// 订单 ID。
/// </summary>
public long OrderId { get; set; }
/// <summary>
/// 商品 ID。
/// </summary>
public long ProductId { get; set; }
/// <summary>
/// 商品名称。
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// SKU 名称。
/// </summary>
public string? SkuName { get; set; }
/// <summary>
/// 单位。
/// </summary>
public string? Unit { get; set; }
/// <summary>
/// 数量。
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 单价。
/// </summary>
public decimal UnitPrice { get; set; }
/// <summary>
/// 优惠金额。
/// </summary>
public decimal DiscountAmount { get; set; }
/// <summary>
/// 小计。
/// </summary>
public decimal SubTotal { get; set; }
/// <summary>
/// 属性 JSON。
/// </summary>
public string? AttributesJson { get; set; }
}

View File

@@ -0,0 +1,31 @@
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 订单状态流转记录。
/// </summary>
public sealed class OrderStatusHistory : MultiTenantEntityBase
{
/// <summary>
/// 订单 ID。
/// </summary>
public long OrderId { get; set; }
/// <summary>
/// 变更后的状态。
/// </summary>
public OrderStatus Status { get; set; }
/// <summary>
/// 操作人 ID。
/// </summary>
public long? OperatorId { get; set; }
/// <summary>
/// 备注。
/// </summary>
public string? Notes { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,20 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 履约方式。
/// </summary>
public enum DeliveryType
{
/// <summary>
/// 堂食。
/// </summary>
DineIn = 0,
/// <summary>
/// 自提。
/// </summary>
Pickup = 1,
/// <summary>
/// 配送。
/// </summary>
Delivery = 2
}

View File

@@ -0,0 +1,20 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 下单渠道。
/// </summary>
public enum OrderChannel
{
/// <summary>
/// 未知渠道。
/// </summary>
Unknown = 0,
/// <summary>
/// 小程序。
/// </summary>
MiniProgram = 1,
/// <summary>
/// 扫码点餐。
/// </summary>
ScanToOrder = 2
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 订单状态。
/// </summary>
public enum OrderStatus
{
/// <summary>
/// 待付款。
/// </summary>
PendingPayment = 0,
/// <summary>
/// 已付款待制作。
/// </summary>
AwaitingPreparation = 1,
/// <summary>
/// 制作中。
/// </summary>
InProgress = 2,
/// <summary>
/// 待取餐或待送达。
/// </summary>
Ready = 3,
/// <summary>
/// 已完成。
/// </summary>
Completed = 4,
/// <summary>
/// 已取消。
/// </summary>
Cancelled = 5
}

View File

@@ -0,0 +1,30 @@
using TakeoutSaaS.Domain.Orders.Entities;
namespace TakeoutSaaS.Domain.Orders.Repositories;
/// <summary>
/// 订单写仓储。
/// </summary>
public interface IOrderRepository
{
/// <summary>
/// 新增订单。
/// </summary>
Task AddAsync(Order order, CancellationToken cancellationToken = default);
/// <summary>
/// 批量新增订单明细。
/// </summary>
Task AddItemsAsync(IReadOnlyCollection<OrderItem> items, CancellationToken cancellationToken = default);
/// <summary>
/// 新增状态流转记录。
/// </summary>
Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default);
/// <summary>
/// 查询可写订单。
/// </summary>
Task<Order?> FindAsync(long tenantId, long orderId, CancellationToken cancellationToken = default);
/// <summary>
/// 保存变更。
/// </summary>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}