feat: 订单商品查询支持tenantId可选过滤
This commit is contained in:
@@ -45,6 +45,7 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
|||||||
[PermissionAuthorize("order:read")]
|
[PermissionAuthorize("order:read")]
|
||||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<OrderDto>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(ApiResponse<PagedResult<OrderDto>>), StatusCodes.Status200OK)]
|
||||||
public async Task<ApiResponse<PagedResult<OrderDto>>> List(
|
public async Task<ApiResponse<PagedResult<OrderDto>>> List(
|
||||||
|
[FromQuery] long? tenantId,
|
||||||
[FromQuery] long? storeId,
|
[FromQuery] long? storeId,
|
||||||
[FromQuery] OrderStatus? status,
|
[FromQuery] OrderStatus? status,
|
||||||
[FromQuery] PaymentStatus? paymentStatus,
|
[FromQuery] PaymentStatus? paymentStatus,
|
||||||
@@ -58,6 +59,7 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
|||||||
// 1. 组装查询参数并执行查询
|
// 1. 组装查询参数并执行查询
|
||||||
var result = await mediator.Send(new SearchOrdersQuery
|
var result = await mediator.Send(new SearchOrdersQuery
|
||||||
{
|
{
|
||||||
|
TenantId = tenantId,
|
||||||
StoreId = storeId,
|
StoreId = storeId,
|
||||||
Status = status,
|
Status = status,
|
||||||
PaymentStatus = paymentStatus,
|
PaymentStatus = paymentStatus,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
|||||||
[PermissionAuthorize("product:read")]
|
[PermissionAuthorize("product:read")]
|
||||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<ProductDto>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(ApiResponse<PagedResult<ProductDto>>), StatusCodes.Status200OK)]
|
||||||
public async Task<ApiResponse<PagedResult<ProductDto>>> List(
|
public async Task<ApiResponse<PagedResult<ProductDto>>> List(
|
||||||
|
[FromQuery] long? tenantId,
|
||||||
[FromQuery] long? storeId,
|
[FromQuery] long? storeId,
|
||||||
[FromQuery] long? categoryId,
|
[FromQuery] long? categoryId,
|
||||||
[FromQuery] ProductStatus? status,
|
[FromQuery] ProductStatus? status,
|
||||||
@@ -56,6 +57,7 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
|||||||
// 1. 组装查询参数并执行查询
|
// 1. 组装查询参数并执行查询
|
||||||
var result = await mediator.Send(new SearchProductsQuery
|
var result = await mediator.Send(new SearchProductsQuery
|
||||||
{
|
{
|
||||||
|
TenantId = tenantId,
|
||||||
StoreId = storeId,
|
StoreId = storeId,
|
||||||
CategoryId = categoryId,
|
CategoryId = categoryId,
|
||||||
Status = status,
|
Status = status,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using TakeoutSaaS.Application.App.Orders.Dto;
|
|||||||
using TakeoutSaaS.Application.App.Orders.Queries;
|
using TakeoutSaaS.Application.App.Orders.Queries;
|
||||||
using TakeoutSaaS.Domain.Orders.Entities;
|
using TakeoutSaaS.Domain.Orders.Entities;
|
||||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||||
|
|
||||||
@@ -11,29 +10,26 @@ namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
|||||||
/// 订单详情查询处理器。
|
/// 订单详情查询处理器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GetOrderByIdQueryHandler(
|
public sealed class GetOrderByIdQueryHandler(
|
||||||
IOrderRepository orderRepository,
|
IOrderRepository orderRepository)
|
||||||
ITenantProvider tenantProvider)
|
|
||||||
: IRequestHandler<GetOrderByIdQuery, OrderDto?>
|
: IRequestHandler<GetOrderByIdQuery, OrderDto?>
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<OrderDto?> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
|
public async Task<OrderDto?> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取当前租户
|
// 1. 查询订单主体(跨租户)
|
||||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
var order = await orderRepository.FindByIdAsync(request.OrderId, cancellationToken);
|
||||||
|
|
||||||
// 2. 查询订单主体
|
|
||||||
var order = await orderRepository.FindByIdAsync(request.OrderId, tenantId, cancellationToken);
|
|
||||||
if (order == null)
|
if (order == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 查询关联明细
|
// 2. (空行后) 查询关联明细(按订单租户)
|
||||||
|
var tenantId = order.TenantId;
|
||||||
var items = await orderRepository.GetItemsAsync(order.Id, tenantId, cancellationToken);
|
var items = await orderRepository.GetItemsAsync(order.Id, tenantId, cancellationToken);
|
||||||
var histories = await orderRepository.GetStatusHistoryAsync(order.Id, tenantId, cancellationToken);
|
var histories = await orderRepository.GetStatusHistoryAsync(order.Id, tenantId, cancellationToken);
|
||||||
var refunds = await orderRepository.GetRefundsAsync(order.Id, tenantId, cancellationToken);
|
var refunds = await orderRepository.GetRefundsAsync(order.Id, tenantId, cancellationToken);
|
||||||
|
|
||||||
// 4. 映射并返回
|
// 3. (空行后) 映射并返回
|
||||||
return MapToDto(order, items, histories, refunds);
|
return MapToDto(order, items, histories, refunds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using TakeoutSaaS.Application.App.Orders.Dto;
|
|||||||
using TakeoutSaaS.Application.App.Orders.Queries;
|
using TakeoutSaaS.Application.App.Orders.Queries;
|
||||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||||
|
|
||||||
@@ -11,24 +10,22 @@ namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
|||||||
/// 订单列表查询处理器。
|
/// 订单列表查询处理器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SearchOrdersQueryHandler(
|
public sealed class SearchOrdersQueryHandler(
|
||||||
IOrderRepository orderRepository,
|
IOrderRepository orderRepository)
|
||||||
ITenantProvider tenantProvider)
|
|
||||||
: IRequestHandler<SearchOrdersQuery, PagedResult<OrderDto>>
|
: IRequestHandler<SearchOrdersQuery, PagedResult<OrderDto>>
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<PagedResult<OrderDto>> Handle(SearchOrdersQuery request, CancellationToken cancellationToken)
|
public async Task<PagedResult<OrderDto>> Handle(SearchOrdersQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取当前租户并查询订单
|
// 1. 查询订单(可选租户过滤)
|
||||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
var orders = await orderRepository.SearchAsync(request.TenantId, request.Status, request.PaymentStatus, cancellationToken);
|
||||||
var orders = await orderRepository.SearchAsync(tenantId, request.Status, request.PaymentStatus, cancellationToken);
|
|
||||||
|
|
||||||
// 2. 可选过滤:门店
|
// 2. (空行后) 可选过滤:门店
|
||||||
if (request.StoreId.HasValue)
|
if (request.StoreId.HasValue)
|
||||||
{
|
{
|
||||||
orders = orders.Where(x => x.StoreId == request.StoreId.Value).ToList();
|
orders = orders.Where(x => x.StoreId == request.StoreId.Value).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 可选过滤:订单号模糊
|
// 3. (空行后) 可选过滤:订单号模糊
|
||||||
if (!string.IsNullOrWhiteSpace(request.OrderNo))
|
if (!string.IsNullOrWhiteSpace(request.OrderNo))
|
||||||
{
|
{
|
||||||
var orderNo = request.OrderNo.Trim();
|
var orderNo = request.OrderNo.Trim();
|
||||||
@@ -37,14 +34,14 @@ public sealed class SearchOrdersQueryHandler(
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 排序与分页
|
// 4. (空行后) 排序与分页
|
||||||
var sorted = ApplySorting(orders, request.SortBy, request.SortDescending);
|
var sorted = ApplySorting(orders, request.SortBy, request.SortDescending);
|
||||||
var paged = sorted
|
var paged = sorted
|
||||||
.Skip((request.Page - 1) * request.PageSize)
|
.Skip((request.Page - 1) * request.PageSize)
|
||||||
.Take(request.PageSize)
|
.Take(request.PageSize)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 5. 映射 DTO
|
// 5. (空行后) 映射 DTO
|
||||||
var items = paged.Select(order => new OrderDto
|
var items = paged.Select(order => new OrderDto
|
||||||
{
|
{
|
||||||
Id = order.Id,
|
Id = order.Id,
|
||||||
@@ -72,7 +69,7 @@ public sealed class SearchOrdersQueryHandler(
|
|||||||
CreatedAt = order.CreatedAt
|
CreatedAt = order.CreatedAt
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// 6. 返回分页结果
|
// 6. (空行后) 返回分页结果
|
||||||
return new PagedResult<OrderDto>(items, request.Page, request.PageSize, orders.Count);
|
return new PagedResult<OrderDto>(items, request.Page, request.PageSize, orders.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ namespace TakeoutSaaS.Application.App.Orders.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SearchOrdersQuery : IRequest<PagedResult<OrderDto>>
|
public sealed class SearchOrdersQuery : IRequest<PagedResult<OrderDto>>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(可选,空表示跨租户查询)。
|
||||||
|
/// </summary>
|
||||||
|
public long? TenantId { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 门店 ID(可选)。
|
/// 门店 ID(可选)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using TakeoutSaaS.Application.App.Products.Dto;
|
using TakeoutSaaS.Application.App.Products.Dto;
|
||||||
using TakeoutSaaS.Application.App.Products.Queries;
|
using TakeoutSaaS.Application.App.Products.Queries;
|
||||||
using TakeoutSaaS.Domain.Products.Entities;
|
|
||||||
using TakeoutSaaS.Domain.Products.Repositories;
|
using TakeoutSaaS.Domain.Products.Repositories;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
||||||
|
|
||||||
@@ -11,18 +9,15 @@ namespace TakeoutSaaS.Application.App.Products.Handlers;
|
|||||||
/// 商品详情查询处理器。
|
/// 商品详情查询处理器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GetProductByIdQueryHandler(
|
public sealed class GetProductByIdQueryHandler(
|
||||||
IProductRepository productRepository,
|
IProductRepository productRepository)
|
||||||
ITenantProvider tenantProvider)
|
|
||||||
: IRequestHandler<GetProductByIdQuery, ProductDto?>
|
: IRequestHandler<GetProductByIdQuery, ProductDto?>
|
||||||
{
|
{
|
||||||
private readonly IProductRepository _productRepository = productRepository;
|
|
||||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ProductDto?> Handle(GetProductByIdQuery request, CancellationToken cancellationToken)
|
public async Task<ProductDto?> Handle(GetProductByIdQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
// 1. 查询商品(跨租户)
|
||||||
var product = await _productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken);
|
var product = await productRepository.FindByIdAsync(request.ProductId, cancellationToken);
|
||||||
|
// 2. (空行后) 映射并返回
|
||||||
return product == null ? null : ProductMapping.ToDto(product);
|
return product == null ? null : ProductMapping.ToDto(product);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using MediatR;
|
|||||||
using TakeoutSaaS.Application.App.Products.Dto;
|
using TakeoutSaaS.Application.App.Products.Dto;
|
||||||
using TakeoutSaaS.Application.App.Products.Queries;
|
using TakeoutSaaS.Application.App.Products.Queries;
|
||||||
using TakeoutSaaS.Domain.Products.Repositories;
|
using TakeoutSaaS.Domain.Products.Repositories;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
||||||
|
|
||||||
@@ -10,22 +9,21 @@ namespace TakeoutSaaS.Application.App.Products.Handlers;
|
|||||||
/// 商品全量详情查询处理器。
|
/// 商品全量详情查询处理器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GetProductDetailQueryHandler(
|
public sealed class GetProductDetailQueryHandler(
|
||||||
IProductRepository productRepository,
|
IProductRepository productRepository)
|
||||||
ITenantProvider tenantProvider)
|
|
||||||
: IRequestHandler<GetProductDetailQuery, ProductDetailDto?>
|
: IRequestHandler<GetProductDetailQuery, ProductDetailDto?>
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ProductDetailDto?> Handle(GetProductDetailQuery request, CancellationToken cancellationToken)
|
public async Task<ProductDetailDto?> Handle(GetProductDetailQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 读取 SPU
|
// 1. 读取 SPU(跨租户)
|
||||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
var product = await productRepository.FindByIdAsync(request.ProductId, cancellationToken);
|
||||||
var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken);
|
|
||||||
if (product is null)
|
if (product is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询子项
|
// 2. (空行后) 读取租户并查询子项
|
||||||
|
var tenantId = product.TenantId;
|
||||||
var skusTask = productRepository.GetSkusAsync(product.Id, tenantId, cancellationToken);
|
var skusTask = productRepository.GetSkusAsync(product.Id, tenantId, cancellationToken);
|
||||||
var attrGroupsTask = productRepository.GetAttributeGroupsAsync(product.Id, tenantId, cancellationToken);
|
var attrGroupsTask = productRepository.GetAttributeGroupsAsync(product.Id, tenantId, cancellationToken);
|
||||||
var attrOptionsTask = productRepository.GetAttributeOptionsAsync(product.Id, tenantId, cancellationToken);
|
var attrOptionsTask = productRepository.GetAttributeOptionsAsync(product.Id, tenantId, cancellationToken);
|
||||||
@@ -36,7 +34,7 @@ public sealed class GetProductDetailQueryHandler(
|
|||||||
|
|
||||||
await Task.WhenAll(skusTask, attrGroupsTask, attrOptionsTask, addonGroupsTask, addonOptionsTask, mediaTask, pricingTask);
|
await Task.WhenAll(skusTask, attrGroupsTask, attrOptionsTask, addonGroupsTask, addonOptionsTask, mediaTask, pricingTask);
|
||||||
|
|
||||||
// 3. 组装 DTO
|
// 3. (空行后) 组装 DTO
|
||||||
var skus = await skusTask;
|
var skus = await skusTask;
|
||||||
var attrGroups = await attrGroupsTask;
|
var attrGroups = await attrGroupsTask;
|
||||||
var attrOptions = (await attrOptionsTask).ToLookup(x => x.AttributeGroupId);
|
var attrOptions = (await attrOptionsTask).ToLookup(x => x.AttributeGroupId);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using TakeoutSaaS.Application.App.Products.Dto;
|
|||||||
using TakeoutSaaS.Application.App.Products.Queries;
|
using TakeoutSaaS.Application.App.Products.Queries;
|
||||||
using TakeoutSaaS.Domain.Products.Repositories;
|
using TakeoutSaaS.Domain.Products.Repositories;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
namespace TakeoutSaaS.Application.App.Products.Handlers;
|
||||||
|
|
||||||
@@ -11,25 +10,28 @@ namespace TakeoutSaaS.Application.App.Products.Handlers;
|
|||||||
/// 商品列表查询处理器。
|
/// 商品列表查询处理器。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SearchProductsQueryHandler(
|
public sealed class SearchProductsQueryHandler(
|
||||||
IProductRepository productRepository,
|
IProductRepository productRepository)
|
||||||
ITenantProvider tenantProvider)
|
|
||||||
: IRequestHandler<SearchProductsQuery, PagedResult<ProductDto>>
|
: IRequestHandler<SearchProductsQuery, PagedResult<ProductDto>>
|
||||||
{
|
{
|
||||||
private readonly IProductRepository _productRepository = productRepository;
|
|
||||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<PagedResult<ProductDto>> Handle(SearchProductsQuery request, CancellationToken cancellationToken)
|
public async Task<PagedResult<ProductDto>> Handle(SearchProductsQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
// 1. 查询商品列表(可选租户过滤)
|
||||||
var products = await _productRepository.SearchAsync(tenantId, request.StoreId, request.CategoryId, request.Status, cancellationToken);
|
var products = await productRepository.SearchAsync(
|
||||||
|
request.TenantId,
|
||||||
|
request.StoreId,
|
||||||
|
request.CategoryId,
|
||||||
|
request.Status,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
// 2. (空行后) 排序与分页
|
||||||
var sorted = ApplySorting(products, request.SortBy, request.SortDescending);
|
var sorted = ApplySorting(products, request.SortBy, request.SortDescending);
|
||||||
var paged = sorted
|
var paged = sorted
|
||||||
.Skip((request.Page - 1) * request.PageSize)
|
.Skip((request.Page - 1) * request.PageSize)
|
||||||
.Take(request.PageSize)
|
.Take(request.PageSize)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
// 3. (空行后) 映射 DTO 并返回分页结果
|
||||||
var items = paged.Select(MapToDto).ToList();
|
var items = paged.Select(MapToDto).ToList();
|
||||||
return new PagedResult<ProductDto>(items, request.Page, request.PageSize, products.Count);
|
return new PagedResult<ProductDto>(items, request.Page, request.PageSize, products.Count);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ namespace TakeoutSaaS.Application.App.Products.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SearchProductsQuery : IRequest<PagedResult<ProductDto>>
|
public sealed class SearchProductsQuery : IRequest<PagedResult<ProductDto>>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(可选,空表示跨租户查询)。
|
||||||
|
/// </summary>
|
||||||
|
public long? TenantId { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 门店 ID(可选)。
|
/// 门店 ID(可选)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ public interface IOrderRepository
|
|||||||
/// <returns>订单实体或 null。</returns>
|
/// <returns>订单实体或 null。</returns>
|
||||||
Task<Order?> FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
|
Task<Order?> FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 依据标识获取订单(跨租户)。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="orderId">订单 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>订单实体或 null。</returns>
|
||||||
|
Task<Order?> FindByIdAsync(long orderId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 依据订单号获取订单。
|
/// 依据订单号获取订单。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -37,6 +45,16 @@ public interface IOrderRepository
|
|||||||
/// <returns>订单集合。</returns>
|
/// <returns>订单集合。</returns>
|
||||||
Task<IReadOnlyList<Order>> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default);
|
Task<IReadOnlyList<Order>> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按状态筛选订单列表(可选租户过滤)。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID(可选,空表示跨租户查询)。</param>
|
||||||
|
/// <param name="status">订单状态。</param>
|
||||||
|
/// <param name="paymentStatus">支付状态。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>订单集合。</returns>
|
||||||
|
Task<IReadOnlyList<Order>> SearchAsync(long? tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取订单明细行。
|
/// 获取订单明细行。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,11 +13,21 @@ public interface IProductRepository
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Task<Product?> FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
|
Task<Product?> FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 依据标识获取商品(跨租户)。
|
||||||
|
/// </summary>
|
||||||
|
Task<Product?> FindByIdAsync(long productId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按分类与状态筛选商品列表。
|
/// 按分类与状态筛选商品列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null);
|
Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按分类与状态筛选商品列表(可选租户过滤)。
|
||||||
|
/// </summary>
|
||||||
|
Task<IReadOnlyList<Product>> SearchAsync(long? tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取租户下的商品分类。
|
/// 获取租户下的商品分类。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ public sealed class EfOrderRepository(TakeoutAdminDbContext context) : IOrderRep
|
|||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Order?> FindByIdAsync(long orderId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
// 1. 按主键查询(跨租户)
|
||||||
|
return context.Orders
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(x => x.Id == orderId)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Order?> FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default)
|
public Task<Order?> FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -57,6 +67,35 @@ public sealed class EfOrderRepository(TakeoutAdminDbContext context) : IOrderRep
|
|||||||
return orders;
|
return orders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<IReadOnlyList<Order>> SearchAsync(long? tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
// 1. 构建查询(可选租户过滤)
|
||||||
|
var query = context.Orders.AsNoTracking();
|
||||||
|
if (tenantId.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.TenantId == tenantId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 可选过滤:订单状态
|
||||||
|
if (status.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.Status == status.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 可选过滤:支付状态
|
||||||
|
if (paymentStatus.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.PaymentStatus == paymentStatus.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. (空行后) 排序并返回
|
||||||
|
var orders = await query
|
||||||
|
.OrderByDescending(x => x.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<OrderItem>> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
public async Task<IReadOnlyList<OrderItem>> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,16 @@ public sealed class EfProductRepository(TakeoutAdminDbContext context) : IProduc
|
|||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Product?> FindByIdAsync(long productId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
// 1. 按主键查询(跨租户)
|
||||||
|
return context.Products
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(x => x.Id == productId)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null)
|
public async Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null)
|
||||||
{
|
{
|
||||||
@@ -59,6 +69,47 @@ public sealed class EfProductRepository(TakeoutAdminDbContext context) : IProduc
|
|||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<IReadOnlyList<Product>> SearchAsync(long? tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null)
|
||||||
|
{
|
||||||
|
// 1. 构建查询(可选租户过滤)
|
||||||
|
var query = context.Products.AsNoTracking();
|
||||||
|
if (tenantId.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.TenantId == tenantId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 可选过滤:门店
|
||||||
|
if (storeId.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.StoreId == storeId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 可选过滤:分类
|
||||||
|
if (categoryId.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.CategoryId == categoryId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. (空行后) 可选过滤:状态
|
||||||
|
if (status.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.Status == status.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. (空行后) 可选过滤:更新时间下限
|
||||||
|
if (updatedAfter.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(x => (x.UpdatedAt ?? x.CreatedAt) >= updatedAfter.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. (空行后) 排序并返回
|
||||||
|
var products = await query
|
||||||
|
.OrderBy(x => x.Name)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<ProductCategory>> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default)
|
public async Task<IReadOnlyList<ProductCategory>> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user