9f1a312bb9
chore(infra): configure coverlet for backend C# coverage
...
Add coverlet.runsettings with Cobertura format, exclusions for migrations,
DI wiring, Program.cs and auto-props. Document coverage commands in README.
coverlet.collector 6.0.4 was already present via Directory.Packages.props.
Coverage baseline (Application.Tests + Api.Tests combined):
- Application.Tests: line 80.9%, branch 65.3%
- Api.Tests: line 64.9%, branch 57.8%
Closes #48
2026-04-19 19:21:45 -03:00
dd0e5e4fe8
Merge pull request 'feat: PRD-003 ProductPrices históricos (ValidFrom/ValidTo)' ( #45 ) from feature/PRD-003 into main
2026-04-19 22:07:21 +00:00
7cabb677f3
test(integration): concurrency + SYSTEM_VERSIONING + e2e extra (PRD-003)
2026-04-19 18:43:11 -03:00
6a9818b0ae
feat(frontend): productPrices feature — history + dialog (PRD-003)
...
- API layer: getProductPrices + addProductPrice (axiosClient)
- Hooks: useProductPrices (useQuery, staleTime 30s, enabled productId>0)
useAddProductPrice (useMutation, invalidates ['products', id, 'prices'])
- Components: ProductPriceHistory (shadcn Table + Badge Vigente, formatCivilDate, formatCurrency)
AddProductPriceDialog (shadcn Dialog + Form, Zod schema con priceValidFrom>=todayArgentina())
- Integration: ProductsPage gets "Ver precios" per row opening prices dialog
- lib/numberFormat.ts: formatCurrency() con Intl.NumberFormat ARS
- types.ts extended: ProductPrice, AddProductPriceRequest, AddProductPriceResponse
- Tests (Vitest + RTL): 19 tests — RED→GREEN confirmed
- ProductPriceHistory: loading/error/empty/data/Badge Vigente/dialog/permissions
- AddProductPriceDialog: validation (fecha pasada, precio=0, precio negativo),
happy path payload + close, server 409 inline error, vi.useFakeTimers ART
- hooks: useProductPrices caching + disabled when productId=0,
useAddProductPrice invalidateQueries + error 409
- 453 total tests, 0 rojos
2026-04-19 18:36:17 -03:00
f6f24bc4be
feat(api): ProductPricesController + DI + ExceptionFilter integration (PRD-003)
...
- GET /api/v1/products/{id}/prices [Authorize] → 200 IReadOnlyList<ProductPriceDto>
- POST /api/v1/admin/products/{id}/prices [RequirePermission catalogo:productos:gestionar] → 201 AddProductPriceResponse + Location header
- ExceptionFilter: 3 new cases (ProductPriceForwardOnlyException→409, ProductPriceInvalidException→400, ProductSinPrecioActivoException→404)
- Fix AddProductPriceCommandHandler: move GetByProductIdAsync outside TransactionScope using block to avoid InvalidOperationException (scope already complete)
- 16 e2e tests in ProductPricesControllerTests: 401/403, 200 history ordered DESC, 404 not found, 201 first/second price, 400 validation, 409 forward-only, audit event, DateOnly yyyy-MM-dd roundtrip
- 305 Api.Tests + 1088 Application.Tests = 1393 total, 0 red
2026-04-19 18:26:24 -03:00
2d2e90fa3c
feat(infrastructure): ProductPriceRepository Dapper + SP invocation (PRD-003)
2026-04-19 18:15:30 -03:00
4b0567d252
feat(application): commands/queries + IProductPricingService (PRD-003)
...
- IProductPriceRepository (AddAsync/GetByProductIdAsync/GetActiveAsync)
- ProductPriceDto, AddProductPriceCommand/Response, GetProductPricesQuery
- AddProductPriceCommandValidator (FluentValidation + TimeProvider, fecha >= hoy_AR)
- AddProductPriceCommandHandler (TransactionScope AsyncFlow, audit fail-closed)
- GetProductPricesQueryHandler (verifica producto existe, lista vacía válida)
- IProductPricingService + ProductPricingService (GetPriceAtAsync → decimal?)
- DI wiring en DependencyInjection.cs
- 29 tests NSubstitute + FakeTimeProvider, 1081 Application.Tests GREEN
2026-04-19 18:08:16 -03:00
54b0265994
feat(domain): ProductPrice entity + exceptions (PRD-003)
2026-04-19 17:59:43 -03:00
59f30cddfb
feat(bd): V019 crea dbo.ProductPrices + SP + índices (PRD-003)
2026-04-19 17:53:58 -03:00
e735afb5b4
Merge pull request 'feat(domain): RubroConProductosActivosException + guard en DeactivateRubro ( closes #41 )' ( #44 ) from fix/issue-41-rubro-deactivation-guard into main
2026-04-19 20:09:38 +00:00
50a5118a78
feat(api): ExceptionFilter + e2e 409 para RubroConProductosActivos ( closes #41 )
...
Mapea RubroConProductosActivosException → HTTP 409 con error code
rubro_con_productos_activos. Test e2e usa DI override (patrón issue #36 )
para stub IProductQueryRepository sin sembrar Products reales en DB.
2026-04-19 17:08:42 -03:00
c974e824e0
feat(infrastructure): ProductQueryRepository.CountActiveByRubroAsync + integration test
...
Implementa SELECT COUNT(1) FROM dbo.Product WHERE RubroId = @RubroId AND IsActive = 1.
Tests de integración verifican: 0 sin productos, count correcto con mix
activos/inactivos/otro rubro, y solo inactivos retorna 0.
2026-04-19 17:08:35 -03:00
900fd5e975
feat(application): DeactivateRubroCommandHandler guard contra Products activos
...
Extiende IProductQueryRepository con CountActiveByRubroAsync, inyecta
el repositorio en el handler e intercala el chequeo después del guard
de hijos activos. Tests de unidad cubren: throw, success con 0 productos,
y estabilidad del orden de guardas (hijos primero).
2026-04-19 17:08:30 -03:00
e9d1e3237d
feat(domain): RubroConProductosActivosException + test ( closes #41 )
...
Co-authored-by: fix/issue-41-rubro-deactivation-guard
2026-04-19 17:08:23 -03:00
e33e9f332e
Merge pull request 'refactor(tests): TestWebAppFactory.CreateClientWithOverrides para DI override scoped ( closes #36 )' ( #43 ) from fix/issue-36-rsa-singleton-override into main
2026-04-19 20:00:47 +00:00
0e363d1cfc
refactor(tests): TestWebAppFactory.CreateClientWithOverrides para DI override por test ( closes #36 )
...
Agrega helper CreateClientWithOverrides en TestWebAppFactory que envuelve
WithWebHostBuilder+ConfigureTestServices para inyectar stubs por test sin
tocar la fábrica compartida. Usa el patrón para agregar 2 tests e2e:
Deactivate_WhenProductQueryReturnsInUse_Returns409WithErrorCode (PRD-001/PRD-002)
y CreateRubro_WhenParentHasAvisos_Returns409WithErrorCode (CAT-002).
Remueve el comentario TODO PRD-002. 287 Api tests verdes.
2026-04-19 16:59:53 -03:00
c5a8cd9edd
Merge pull request 'fix: openEdit fetch ProductTypeDetail antes de abrir dialog ( closes #37 )' ( #42 ) from fix/issue-37-openedit-fetch-detail into main
2026-04-19 19:53:47 +00:00
616f6432d1
fix(frontend): openEdit fetch ProductTypeDetail antes de abrir dialog ( closes #37 )
...
Reemplaza el stub con nulls por queryClient.fetchQuery con getProductTypeById,
deshabilitando el botón durante la carga y mostrando toast.error si falla.
2026-04-19 16:53:00 -03:00
1730b0623e
Merge pull request 'feat: PRD-002 Product CRUD' ( #40 ) from feature/PRD-002 into main
2026-04-19 16:49:58 +00:00
d7fb3105fa
feat(bd): V018 crea dbo.Product + SqlTestFixture consolida V018 + permisos catalogo (PRD-002 W6)
2026-04-19 13:46:11 -03:00
b4f17d6961
refactor: eliminar NullProductQueryRepository dead code + EXISTS en ProductQueryRepository (PRD-002 S1 S2)
2026-04-19 13:37:10 -03:00
a7cfcdb683
test(frontend): ProductsPage pagination + filter tests (PRD-002 W5)
2026-04-19 13:36:48 -03:00
0f5455aba6
test(frontend): ProductFormDialog + DeactivateProductDialog tests (PRD-002 W3 W4)
2026-04-19 13:35:23 -03:00
2b79b6f769
feat(frontend): ProductForm reactivo a flags ProductType (PRD-002 W2)
2026-04-19 13:33:53 -03:00
d262454b28
fix(api): ExceptionFilter 409 para ProductTypeInactivo y RubroInactivo (PRD-002 W1)
2026-04-19 13:31:38 -03:00
08a4738daf
feat(frontend): Products feature — CRUD page, form, dialogs, hooks (PRD-002)
...
Implements full frontend for PRD-002: 5 API fns, 5 hooks (useProducts,
useCreateProduct, useUpdateProduct, useDeactivateProduct), ProductForm,
ProductFormDialog, DeactivateProductDialog, ProductsPage with CanPerform
gating. Router entry at /admin/products and sidebar link added. 19 Vitest
tests GREEN (api, hooks, page).
2026-04-19 13:24:42 -03:00
a41a4ea341
test(api): guard proof — ProductType deactivation returns 409 when active Products exist (PRD-002)
2026-04-19 13:18:21 -03:00
165abc8245
feat(api): ProductsController + ExceptionFilter Product cases, fix permiso count to 27 (PRD-002)
2026-04-19 13:17:31 -03:00
733ca0e2e2
test(infrastructure): ProductRepository integration tests — roundtrip, update, deactivate history, UQ (PRD-002)
2026-04-19 13:11:21 -03:00
8c9a50504d
feat(infrastructure): ProductRepository + ProductQueryRepository, DI swap activates guard (PRD-002)
2026-04-19 13:10:21 -03:00
bb455be745
feat(application): Product handlers + DI registration, fix permiso count to 27 (PRD-002)
2026-04-19 13:07:59 -03:00
8b555e1f8b
feat(application): Product commands, DTOs, IProductRepository, validators (PRD-002)
2026-04-19 13:02:42 -03:00
16197cf242
feat(domain): Product entity + 5 domain exceptions (PRD-002)
2026-04-19 12:59:58 -03:00
0462970ea1
Merge pull request 'feat: PRD-001 ProductType (flags + multimedia)' ( #38 ) from feature/PRD-001 into main
2026-04-19 15:18:53 +00:00
d6ec618ff2
docs(tests): TODO W1 PRD-002 en ProductTypesControllerTests + audit doc ya completo (PRD-001)
...
Agrega comentario TODO antes del bloque DELETE explicando el gap e2e
para 409 IsInUse (bloqueado por RSA singleton, issue #36 , PRD-002).
Auditoría.md ya tenía las entradas producto_tipo.* desde apply anterior.
2026-04-19 12:10:35 -03:00
230405e056
feat(frontend): wire dialogs en ProductTypesPage (PRD-001 W3)
...
Conecta ProductTypeFormDialog (create/edit) y DeactivateProductTypeDialog
en ProductTypesPage: botón "Nuevo Tipo", acción Editar por fila, acción
Desactivar por fila, empty state CTA "Crear primer tipo".
9 tests nuevos de page integration. Total: 390.
2026-04-19 12:10:09 -03:00
9cb1e84ec0
feat(frontend): ProductTypeForm + Dialog + DeactivateDialog con TDD (PRD-001 W3)
...
Implementa los 3 componentes de UI faltantes con enfoque Red→Green:
- ProductTypeForm: zod schema con transforms para multimedia numérica,
lógica condicional (multimedia deshabilitada cuando allowImages=false),
normalización en submit.
- ProductTypeFormDialog: mode create/edit, inline error 409, aria-describedby (NFR8).
- DeactivateProductTypeDialog: AlertDialog confirmar soft-delete, inline error 409 EnUso.
18 tests nuevos (8 form + 6 dialog + 4 deactivate). Total: 381.
2026-04-19 12:08:36 -03:00
3db4dedb91
feat(frontend): feature product-types completa (PRD-001)
...
types, api, hooks, ProductTypesPage, router /admin/product-types,
sidebar Tipos de Producto; 11 vitest tests nuevos — suite total 363 GREEN.
2026-04-19 10:01:12 -03:00
170789886b
feat(api): ProductTypesController + ExceptionFilter 4 casos PRD-001
...
CRUD endpoints con validación FluentValidation inline; 4 nuevas excepciones mapeadas
en ExceptionFilter; conteos de permisos 25→26 actualizados; 12 e2e tests nuevos.
2026-04-19 09:57:11 -03:00
936d1dc353
feat(infrastructure): ProductTypeRepository Dapper + DI wiring (PRD-001)
...
CRUD + paginado con filtros sobre dbo.ProductType; history temporal verificada en tests.
11 integration tests nuevos, suite total 935 GREEN.
2026-04-19 09:49:08 -03:00
5c8f19bf39
feat(application): CRUD handlers + validators + DI de ProductType (PRD-001)
...
Create/Update/Deactivate handlers con TransactionScope + audit; validators FluentValidation;
DI wiring NullProductQueryRepository + 5 handlers; SqlTestFixture V017 + permiso count 25→26.
2026-04-19 09:46:31 -03:00
3c9e852379
feat(application): IProductTypeRepository + IProductQueryRepository stub + queries (PRD-001)
2026-04-19 09:38:51 -03:00
132d17c99f
feat(domain): ProductType entity + domain exceptions (PRD-001)
2026-04-19 09:36:29 -03:00
de70152d3e
feat(bd): V017 crea dbo.ProductType con SYSTEM_VERSIONING + permiso catalogo:tipos:gestionar (PRD-001)
2026-04-19 09:34:23 -03:00
d8d1da8ea4
Merge pull request 'feat: CAT-002 Regla de Oro Rama vs Hoja + validaciones' ( #35 ) from feature/CAT-002 into main
2026-04-19 11:56:32 +00:00
a0a1874ac2
test(frontend): apretar match exacto del title en CategoryTree (CAT-002 W2)
2026-04-19 08:52:34 -03:00
4f25233bab
feat(frontend): tieneAvisos en RubroTreeNode + disable btn subrubro (CAT-002)
2026-04-19 08:35:42 -03:00
bb5dde6e24
feat(api): ExceptionFilter 409 para regla de oro + DTO delta (CAT-002)
2026-04-19 08:31:39 -03:00
f861dfa826
feat(application): RubroTreeBuilder + GetRubroTree con tieneAvisos (CAT-002)
2026-04-19 08:25:13 -03:00
c03aad8c5a
feat(application): guard avisos en MoveRubroCommandHandler (CAT-002)
2026-04-19 08:24:07 -03:00