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
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
using SIGCM2.Domain.Entities;
|
||||
|
||||
namespace SIGCM2.Application.Abstractions.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// PRD-003 — Write + query access to dbo.ProductPrices.
|
||||
/// Implemented by ProductPriceRepository (Dapper) in Infrastructure.
|
||||
/// </summary>
|
||||
public interface IProductPriceRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes dbo.usp_AddProductPrice inside the ambient TransactionScope.
|
||||
/// Returns (newId, closedId?). Throws:
|
||||
/// - ProductPriceForwardOnlyException on SQL THROW 50409 or unique index violation (2601/2627).
|
||||
/// - ProductNotFoundException on SQL THROW 50404.
|
||||
/// </summary>
|
||||
Task<(long NewId, long? ClosedId)> AddAsync(
|
||||
int productId,
|
||||
decimal price,
|
||||
DateOnly priceValidFrom,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all price rows for the product, ordered descending by PriceValidFrom (active first).
|
||||
/// Returns empty list when the product has no price history.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<ProductPrice>> GetByProductIdAsync(
|
||||
int productId,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ProductPrice row whose window [PriceValidFrom, PriceValidTo] covers the given
|
||||
/// civil date, or null if no row matches (no history, or date is before any recorded price).
|
||||
/// Used by ProductPricingService.GetPriceAtAsync.
|
||||
/// </summary>
|
||||
Task<ProductPrice?> GetActiveAsync(
|
||||
int productId,
|
||||
DateOnly date,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
Reference in New Issue
Block a user