feat(api): pagination on GET product prices (closes #47)
- GET /api/v1/products/{id}/prices now returns PagedResult<ProductPriceDto>
with OFFSET/FETCH + COUNT via Dapper (two queries on same connection)
- Query params: ?page (default 1) and ?pageSize (default 20, max 100)
- Clamping: Math.Max(1, page) + Math.Clamp(pageSize, 1, 100) in handler
- Auth upgraded from [Authorize] to [RequirePermission("catalogo:productos:gestionar")]
- IProductPriceRepository.GetByProductIdAsync signature updated to paginated form
- AddProductPriceCommandHandler adapted to read back via page=1, pageSize=2
- TDD cycle: RED (tests updated to PagedResult shape) -> GREEN (implementation) -> REFACTOR
- Tests: 1418 total (1106 Application + 312 Api), 0 failures
closes #47
This commit is contained in:
@@ -4,6 +4,7 @@ using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.Common;
|
||||
using SIGCM2.Application.Products.Prices;
|
||||
using SIGCM2.Application.Products.Prices.AddPrice;
|
||||
using SIGCM2.Domain.Entities;
|
||||
@@ -50,11 +51,10 @@ public class AddProductPriceCommandHandlerTests
|
||||
_pricesRepo.AddAsync(1, Arg.Any<decimal>(), Arg.Any<DateOnly>(), Arg.Any<CancellationToken>())
|
||||
.Returns((10L, (long?)null));
|
||||
|
||||
_pricesRepo.GetByProductIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<ProductPrice>
|
||||
{
|
||||
MakePrice(10, 1, 150m, Today)
|
||||
}.AsReadOnly() as IReadOnlyList<ProductPrice>);
|
||||
_pricesRepo.GetByProductIdAsync(1, Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new PagedResult<ProductPrice>(
|
||||
new List<ProductPrice> { MakePrice(10, 1, 150m, Today) },
|
||||
1, 2, 1));
|
||||
|
||||
_handler = new AddProductPriceCommandHandler(_pricesRepo, _productsRepo, _audit, _time);
|
||||
}
|
||||
@@ -110,12 +110,14 @@ public class AddProductPriceCommandHandlerTests
|
||||
_pricesRepo.AddAsync(1, Arg.Any<decimal>(), Arg.Any<DateOnly>(), Arg.Any<CancellationToken>())
|
||||
.Returns((20L, (long?)5L)); // newId=20, closedId=5
|
||||
|
||||
_pricesRepo.GetByProductIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<ProductPrice>
|
||||
{
|
||||
MakePrice(20, 1, 200m, Tomorrow),
|
||||
MakePrice(5, 1, 150m, Today, pvt: Tomorrow.AddDays(-1))
|
||||
}.AsReadOnly() as IReadOnlyList<ProductPrice>);
|
||||
_pricesRepo.GetByProductIdAsync(1, Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new PagedResult<ProductPrice>(
|
||||
new List<ProductPrice>
|
||||
{
|
||||
MakePrice(20, 1, 200m, Tomorrow),
|
||||
MakePrice(5, 1, 150m, Today, pvt: Tomorrow.AddDays(-1))
|
||||
},
|
||||
1, 2, 2));
|
||||
|
||||
var result = await _handler.Handle(ValidCmd() with { Price = 200m, PriceValidFrom = Tomorrow });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user