feat: paginación en GET /api/v1/products/{id}/prices (closes #47) #51
Reference in New Issue
Block a user
Delete Branch "feature/prd-003-prices-pagination"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implementa paginación OFFSET/FETCH en el endpoint GET
/api/v1/products/{id}/prices. Breaking change limpio: contrato cambia deProductPriceDto[]→PagedResult<ProductPriceDto>con soporte depageypageSize. Defaults server-side:page=1, pageSize=20con clamping defensivo[1..100]en pageSize. Alineado con el único patrón paginado existente del repo (ListProducts).Cambios por Capa
Backend (3 commits)
GetProductPricesQueryagregaPageyPageSize; handler devuelvePagedResult<ProductPriceDto>con clamping defensivoGetByProductIdAsyncpaginada con OFFSET/FETCH + COUNT (dos queries separadas, patrón ProductRepository)int? page, int? pageSize; defaults 1/20; nueva permission[RequirePermission("catalogo:productos:gestionar")](alinea con POST)Frontend (1 commit)
getProductPricesdevuelvePagedResult<ProductPrice>conpage/pageSizeparams;useProductPricesconsumidor con queryKey granular['product-prices', productId, page, pageSize]ProductPriceHistoryrenderizaprices.items+ controles Anterior/Siguiente; estado local paracurrentPage;placeholderData: keepPreviousDatapara UX smoothuseAddProductPriceactualiza invalidateQueries key a['product-prices', productId](partial match invalida todas las páginas)Hardening (1 commit)
ProductPriceDto[]en código productivoTest Results
Backend: 1424 tests (era 1418 pre-prd-003)
Frontend: 472 tests (era 452 pre-prd-003)
Spec Compliance: 12/12 scenarios + 7 boundary tests — todos PASS
Pattern Refs
PagedResult<T>deApplication.Common+ patrón OFFSET/FETCH + COUNT deProductRepository.GetPagedAsyncPagedResult<T>defeatures/products/types.ts+keepPreviousDatadeuseProductshookCloses #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