feat(application): Rubros commands/queries + RubroTreeBuilder + audit (CAT-001)

This commit is contained in:
2026-04-18 19:25:35 -03:00
parent dcb2e5ada6
commit d9fc9a2867
26 changed files with 1330 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
using SIGCM2.Domain.Entities;
namespace SIGCM2.Application.Abstractions.Persistence;
public interface IRubroRepository
{
Task<int> AddAsync(Rubro rubro, CancellationToken ct = default);
Task<Rubro?> GetByIdAsync(int id, CancellationToken ct = default);
Task<IReadOnlyList<Rubro>> GetAllAsync(bool incluirInactivos, CancellationToken ct = default);
/// <summary>
/// Returns all descendants of rootId via recursive CTE (used only by MoveRubro for cycle detection).
/// </summary>
Task<IReadOnlyList<Rubro>> GetDescendantsAsync(int rootId, CancellationToken ct = default);
Task UpdateAsync(Rubro rubro, CancellationToken ct = default);
/// <summary>
/// Returns the count of active children for the given parentId.
/// Used by soft-delete to guard against deleting non-leaf rubros.
/// </summary>
Task<int> CountActiveChildrenAsync(int id, CancellationToken ct = default);
/// <summary>
/// Returns MAX(Orden)+1 among siblings of the given parentId (0 if no siblings).
/// Used for append-on-create ordering.
/// </summary>
Task<int> GetMaxOrdenAsync(int? parentId, CancellationToken ct = default);
/// <summary>
/// Returns true if an active Rubro with the same Nombre (CI) exists under the same parentId,
/// optionally excluding the Rubro with the given id (for rename operations).
/// </summary>
Task<bool> ExistsByNombreUnderParentAsync(int? parentId, string nombre, int? excludeId, CancellationToken ct = default);
/// <summary>
/// Returns the depth of the given parentId (0 if parentId is null = root level).
/// Uses a recursive CTE going upward through ancestors.
/// </summary>
Task<int> GetDepthAsync(int? parentId, CancellationToken ct = default);
}