ADM-009: Tablas Fiscales (IVA + IIBB) — append-only versioned ref data #22
@@ -0,0 +1,43 @@
|
|||||||
|
using SIGCM2.Application.Common;
|
||||||
|
using SIGCM2.Domain.Fiscal;
|
||||||
|
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||||
|
|
||||||
|
namespace SIGCM2.Application.Abstractions.Persistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persistence contract for IngresosBrutos. Implemented by Dapper repo in Infrastructure.
|
||||||
|
/// </summary>
|
||||||
|
public interface IIngresosBrutosRepository
|
||||||
|
{
|
||||||
|
/// <summary>Inserts a new IngresosBrutos record and returns the generated identity Id.</summary>
|
||||||
|
Task<int> InsertAsync(IibbEntity entity, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Returns the IngresosBrutos with the given Id, or null if not found.</summary>
|
||||||
|
Task<IibbEntity?> GetByIdAsync(int id, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates cosmetic fields only (Descripcion, Activo).
|
||||||
|
/// Never touches Alicuota, Provincia, or vigencia dates.
|
||||||
|
/// </summary>
|
||||||
|
Task<bool> UpdateCosmeticoAsync(int id, string descripcion, bool activo, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the vigencia of the predecessor: UPDATE SET VigenciaHasta = @vigenciaHasta
|
||||||
|
/// WHERE Id = @id AND VigenciaHasta IS NULL (optimistic guard for race conditions).
|
||||||
|
/// Returns true if one row was affected, false if the row was already closed (race detected).
|
||||||
|
/// </summary>
|
||||||
|
Task<bool> UpdateCierreVigenciaAsync(int id, DateOnly vigenciaHasta, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Sets Activo to the given value. Returns true if one row was affected.</summary>
|
||||||
|
Task<bool> SetActivoAsync(int id, bool activo, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Returns a paged list applying optional Activo and Provincia filters.</summary>
|
||||||
|
Task<PagedResult<IibbEntity>> ListAsync(IngresosBrutosQuery query, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the full version chain for the record identified by <paramref name="id"/>,
|
||||||
|
/// ordered from root (no PredecesorId) to the requested Id (inclusive).
|
||||||
|
/// Implemented via a recursive CTE in the concrete repository.
|
||||||
|
/// </summary>
|
||||||
|
Task<IReadOnlyList<IibbEntity>> GetHistorialAsync(int id, CancellationToken ct = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using SIGCM2.Application.Common;
|
||||||
|
using SIGCM2.Domain.Entities;
|
||||||
|
|
||||||
|
namespace SIGCM2.Application.Abstractions.Persistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persistence contract for TipoDeIva. Implemented by Dapper repo in Infrastructure.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITipoDeIvaRepository
|
||||||
|
{
|
||||||
|
/// <summary>Inserts a new TipoDeIva and returns the generated identity Id.</summary>
|
||||||
|
Task<int> InsertAsync(TipoDeIva entity, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Returns the TipoDeIva with the given Id, or null if not found.</summary>
|
||||||
|
Task<TipoDeIva?> GetByIdAsync(int id, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates cosmetic fields only (Codigo, Descripcion, AplicaIVA, Activo).
|
||||||
|
/// Never touches Porcentaje or vigencia dates.
|
||||||
|
/// </summary>
|
||||||
|
Task<bool> UpdateCosmeticoAsync(int id, string codigo, string descripcion, bool aplicaIVA, bool activo, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the vigencia of the predecessor: UPDATE SET VigenciaHasta = @vigenciaHasta
|
||||||
|
/// WHERE Id = @id AND VigenciaHasta IS NULL (optimistic guard for race conditions).
|
||||||
|
/// Returns true if one row was affected, false if the row was already closed (race detected).
|
||||||
|
/// </summary>
|
||||||
|
Task<bool> UpdateCierreVigenciaAsync(int id, DateOnly vigenciaHasta, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Sets Activo to the given value. Returns true if one row was affected.</summary>
|
||||||
|
Task<bool> SetActivoAsync(int id, bool activo, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>Returns a paged list applying optional Activo and Codigo filters.</summary>
|
||||||
|
Task<PagedResult<TipoDeIva>> ListAsync(TiposDeIvaQuery query, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the full version chain for the record identified by <paramref name="id"/>,
|
||||||
|
/// ordered from root (no PredecesorId) to the requested Id (inclusive).
|
||||||
|
/// Implemented via a recursive CTE in the concrete repository.
|
||||||
|
/// </summary>
|
||||||
|
Task<IReadOnlyList<TipoDeIva>> GetHistorialAsync(int id, CancellationToken ct = default);
|
||||||
|
}
|
||||||
11
src/api/SIGCM2.Application/Common/IngresosBrutosQuery.cs
Normal file
11
src/api/SIGCM2.Application/Common/IngresosBrutosQuery.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using SIGCM2.Domain.Fiscal;
|
||||||
|
|
||||||
|
namespace SIGCM2.Application.Common;
|
||||||
|
|
||||||
|
/// <summary>Query parameters for listing ingresos brutos with optional filters and paging.</summary>
|
||||||
|
public sealed record IngresosBrutosQuery(
|
||||||
|
int Page,
|
||||||
|
int PageSize,
|
||||||
|
bool? Activo,
|
||||||
|
ProvinciaArgentina? Provincia
|
||||||
|
);
|
||||||
9
src/api/SIGCM2.Application/Common/TiposDeIvaQuery.cs
Normal file
9
src/api/SIGCM2.Application/Common/TiposDeIvaQuery.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace SIGCM2.Application.Common;
|
||||||
|
|
||||||
|
/// <summary>Query parameters for listing tipos de IVA with optional filters and paging.</summary>
|
||||||
|
public sealed record TiposDeIvaQuery(
|
||||||
|
int Page,
|
||||||
|
int PageSize,
|
||||||
|
bool? Activo,
|
||||||
|
string? Codigo
|
||||||
|
);
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace SIGCM2.Domain.Exceptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thrown when a requested IngresosBrutos record does not exist in the system.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class IngresosBrutosNotFoundException : DomainException
|
||||||
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
|
||||||
|
public IngresosBrutosNotFoundException(int id)
|
||||||
|
: base($"El registro de Ingresos Brutos con id '{id}' no existe.")
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace SIGCM2.Domain.Exceptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thrown when a requested TipoDeIva does not exist in the system.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TipoDeIvaNotFoundException : DomainException
|
||||||
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
|
||||||
|
public TipoDeIvaNotFoundException(int id)
|
||||||
|
: base($"El tipo de IVA con id '{id}' no existe.")
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user