feat(fnb-engine): add shopId and status filters to kitchen tickets
Add shopId and status query params to GET /api/v1/kitchen/tickets. Joins through Session to resolve shopId since KitchenTicket only has SessionId. Backward-compatible: without shopId falls back to existing pending-by-station behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
// EN: Query to get kitchen tickets by shop with optional status filter.
|
||||
// VI: Query lấy phiếu bếp theo shop với bộ lọc trạng thái tùy chọn.
|
||||
|
||||
using MediatR;
|
||||
|
||||
namespace FnbEngine.API.Application.Queries;
|
||||
|
||||
public record GetTicketsByShopQuery(
|
||||
Guid ShopId,
|
||||
string? Status = null
|
||||
) : IRequest<IEnumerable<KitchenTicketDto>>;
|
||||
@@ -0,0 +1,33 @@
|
||||
// EN: Handler for GetTicketsByShopQuery.
|
||||
// VI: Handler cho GetTicketsByShopQuery.
|
||||
|
||||
using MediatR;
|
||||
using FnbEngine.Domain.AggregatesModel.KitchenAggregate;
|
||||
|
||||
namespace FnbEngine.API.Application.Queries;
|
||||
|
||||
public class GetTicketsByShopQueryHandler : IRequestHandler<GetTicketsByShopQuery, IEnumerable<KitchenTicketDto>>
|
||||
{
|
||||
private readonly IKitchenTicketRepository _repository;
|
||||
|
||||
public GetTicketsByShopQueryHandler(IKitchenTicketRepository repository)
|
||||
{
|
||||
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<KitchenTicketDto>> Handle(GetTicketsByShopQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tickets = await _repository.GetByShopAsync(request.ShopId, request.Status, cancellationToken);
|
||||
|
||||
return tickets.Select(t => new KitchenTicketDto(
|
||||
t.Id,
|
||||
t.SessionId,
|
||||
t.OrderItemId,
|
||||
t.ItemName,
|
||||
t.Station,
|
||||
t.Priority,
|
||||
t.Status,
|
||||
t.CreatedAt
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -22,16 +22,28 @@ public class KitchenController : ControllerBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EN: Get pending kitchen tickets.
|
||||
/// VI: Lấy danh sách phiếu bếp chờ.
|
||||
/// EN: Get kitchen tickets. Filter by shopId+status or by station (pending only).
|
||||
/// VI: Lấy phiếu bếp. Lọc theo shopId+status hoặc theo station (chỉ pending).
|
||||
/// </summary>
|
||||
[HttpGet("tickets")]
|
||||
[ProducesResponseType(typeof(ApiResponse<IEnumerable<KitchenTicketDto>>), 200)]
|
||||
public async Task<ActionResult<ApiResponse<IEnumerable<KitchenTicketDto>>>> GetPendingTickets(
|
||||
public async Task<ActionResult<ApiResponse<IEnumerable<KitchenTicketDto>>>> GetTickets(
|
||||
[FromQuery] Guid? shopId = null,
|
||||
[FromQuery] string? status = null,
|
||||
[FromQuery] string? station = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var result = await _mediator.Send(new GetPendingTicketsQuery(station), ct);
|
||||
IEnumerable<KitchenTicketDto> result;
|
||||
|
||||
if (shopId.HasValue && shopId.Value != Guid.Empty)
|
||||
{
|
||||
result = await _mediator.Send(new GetTicketsByShopQuery(shopId.Value, status), ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await _mediator.Send(new GetPendingTicketsQuery(station), ct);
|
||||
}
|
||||
|
||||
return Ok(new ApiResponse<IEnumerable<KitchenTicketDto>> { Success = true, Data = result });
|
||||
}
|
||||
|
||||
|
||||
@@ -40,4 +40,10 @@ public interface IKitchenTicketRepository : IRepository<KitchenTicket>
|
||||
/// VI: Lấy danh sách phiếu theo session ID.
|
||||
/// </summary>
|
||||
Task<IEnumerable<KitchenTicket>> GetBySessionAsync(Guid sessionId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// EN: Get tickets by shop ID with optional status filter.
|
||||
/// VI: Lấy danh sách phiếu theo shop ID với bộ lọc trạng thái tùy chọn.
|
||||
/// </summary>
|
||||
Task<IEnumerable<KitchenTicket>> GetByShopAsync(Guid shopId, string? status = null, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -61,4 +61,23 @@ public class KitchenTicketRepository : IKitchenTicketRepository
|
||||
.OrderBy(kt => kt.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<KitchenTicket>> GetByShopAsync(Guid shopId, string? status = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var sessionIds = await _context.Sessions
|
||||
.Where(s => s.ShopId == shopId)
|
||||
.Select(s => s.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var query = _context.KitchenTickets
|
||||
.Where(kt => sessionIds.Contains(kt.SessionId));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(status))
|
||||
query = query.Where(kt => kt.Status == status);
|
||||
|
||||
return await query
|
||||
.OrderByDescending(kt => kt.Priority)
|
||||
.ThenBy(kt => kt.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user