using GestionIntegral.Api.Dtos.Auditoria; using GestionIntegral.Api.Dtos.Contables; using GestionIntegral.Api.Services.Contables; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; namespace GestionIntegral.Api.Controllers.Contables { [Route("api/cierres-cc")] [ApiController] [Authorize] public class CierresCuentaCorrienteController : ControllerBase { private readonly ICierreCuentaCorrienteService _cierreService; private readonly ILogger _logger; // Permisos asignables a perfiles. La reapertura (CC002) NO se valida acá: es exclusiva de SuperAdmin. private const string PermisoCrear = "CC001"; private const string PermisoVer = "CC003"; public CierresCuentaCorrienteController( ICierreCuentaCorrienteService cierreService, ILogger logger) { _cierreService = cierreService; _logger = logger; } private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc); private bool EsSuperAdmin() => User.IsInRole("SuperAdmin"); private int? GetCurrentUserId() { if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId)) return userId; _logger.LogWarning("No se pudo obtener el UserId del token JWT en CierresCuentaCorrienteController."); return null; } // POST: api/cierres-cc [HttpPost] [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status409Conflict)] public async Task Crear([FromBody] CrearCierreDto dto) { if (!TienePermiso(PermisoCrear)) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var userId = GetCurrentUserId(); if (userId == null) return Unauthorized(); var (cierre, errorCode, errorMessage) = await _cierreService.CrearCierreAsync(dto, userId.Value); if (errorCode != null) { int status = errorCode switch { "CIERRE_FECHA_ANTERIOR_A_ULTIMO" => StatusCodes.Status409Conflict, "CIERRE_ERROR_INTERNO" => StatusCodes.Status500InternalServerError, _ => StatusCodes.Status400BadRequest }; return StatusCode(status, new { codigo = errorCode, mensaje = errorMessage }); } return StatusCode(StatusCodes.Status201Created, cierre); } // POST: api/cierres-cc/{idCierre}/reabrir [HttpPost("{idCierre:int}/reabrir")] [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] public async Task Reabrir(int idCierre, [FromBody] ReabrirCierreDto dto) { if (!EsSuperAdmin()) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var userId = GetCurrentUserId(); if (userId == null) return Unauthorized(); var (cierre, errorCode, errorMessage) = await _cierreService.ReabrirCierreAsync(idCierre, dto, userId.Value, esSuperAdmin: true); if (errorCode != null) { int status = errorCode switch { "CIERRE_NO_ENCONTRADO" => StatusCodes.Status404NotFound, "CIERRE_PERMISO_DENEGADO" => StatusCodes.Status403Forbidden, "CIERRE_HAY_POSTERIORES_VIGENTES" => StatusCodes.Status409Conflict, "CIERRE_YA_ANULADO" => StatusCodes.Status409Conflict, "CIERRE_ERROR_INTERNO" => StatusCodes.Status500InternalServerError, _ => StatusCodes.Status400BadRequest }; return StatusCode(status, new { codigo = errorCode, mensaje = errorMessage }); } return Ok(cierre); } // GET: api/cierres-cc?idDistribuidor=&idEmpresa=&estado=&fechaCorteDesde=&fechaCorteHasta= [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task GetAll( [FromQuery] int? idDistribuidor, [FromQuery] int? idEmpresa, [FromQuery] string? estado, [FromQuery] DateTime? fechaCorteDesde, [FromQuery] DateTime? fechaCorteHasta) { if (!TienePermiso(PermisoVer)) return Forbid(); var cierres = await _cierreService.GetAllAsync(idDistribuidor, idEmpresa, estado, fechaCorteDesde, fechaCorteHasta); return Ok(cierres); } // GET: api/cierres-cc/{idCierre} [HttpGet("{idCierre:int}")] [ProducesResponseType(typeof(CierreCuentaCorrienteDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetById(int idCierre) { if (!TienePermiso(PermisoVer)) return Forbid(); var cierre = await _cierreService.GetByIdAsync(idCierre); if (cierre == null) return NotFound(new { message = $"Cierre #{idCierre} no encontrado." }); return Ok(cierre); } // GET: api/cierres-cc/ultimo?idDistribuidor=&idEmpresa= // Atajo del frontend para autorrellenar "Desde último cierre" en filtros del reporte. // Acepta CC003 (gestión de cierres) o RR001 (acceso al reporte que CONTIENE este atajo): // operadores con solo el permiso del reporte deben poder usar el atajo desde la pantalla del reporte. [HttpGet("ultimo")] [ProducesResponseType(typeof(UltimoCierreDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUltimoVigente( [FromQuery] int idDistribuidor, [FromQuery] int idEmpresa) { if (!TienePermiso(PermisoVer) && !TienePermiso("RR001")) return Forbid(); var ultimo = await _cierreService.GetUltimoVigenteAsync(idDistribuidor, idEmpresa); if (ultimo == null) return NotFound(new { message = "No hay cierres vigentes para el distribuidor en la empresa indicada." }); return Ok(ultimo); } // GET: api/cierres-cc/{idCierre}/historial [HttpGet("{idCierre:int}/historial")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task GetHistorial(int idCierre) { if (!TienePermiso(PermisoVer)) return Forbid(); var historial = await _cierreService.GetHistorialAsync(idCierre); return Ok(historial); } } }