171 lines
5.7 KiB
C#
171 lines
5.7 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using SIGCM.Application.DTOs;
|
|
using SIGCM.Infrastructure.Repositories;
|
|
using SIGCM.Domain.Entities; // <-- Faltaba para AuditLog
|
|
using System.Security.Claims;
|
|
using SIGCM.Infrastructure.Services; // <-- Recomendado para claridad en User.FindFirst
|
|
|
|
namespace SIGCM.API.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
[Authorize]
|
|
public class CashSessionsController : ControllerBase
|
|
{
|
|
private readonly CashSessionRepository _repo;
|
|
private readonly AuditRepository _auditRepo; // <-- AGREGADO: Declaración del campo
|
|
|
|
// ACTUALIZADO: Inyección de ambos repositorios en el constructor
|
|
public CashSessionsController(CashSessionRepository repo, AuditRepository auditRepo)
|
|
{
|
|
_repo = repo;
|
|
_auditRepo = auditRepo;
|
|
}
|
|
|
|
[HttpGet("status")]
|
|
public async Task<IActionResult> GetStatus()
|
|
{
|
|
var userIdClaim = User.FindFirst("Id")?.Value;
|
|
if (string.IsNullOrEmpty(userIdClaim) || !int.TryParse(userIdClaim, out int userId))
|
|
return Unauthorized();
|
|
|
|
var session = await _repo.GetActiveSessionAsync(userId);
|
|
return Ok(new { isOpen = session != null, session });
|
|
}
|
|
|
|
[HttpPost("open")]
|
|
public async Task<IActionResult> Open([FromBody] CashOpeningDto dto)
|
|
{
|
|
var userIdClaim = User.FindFirst("Id")?.Value;
|
|
if (!int.TryParse(userIdClaim, out int userId)) return Unauthorized();
|
|
|
|
var existing = await _repo.GetActiveSessionAsync(userId);
|
|
if (existing != null) return BadRequest("Ya tienes una caja abierta");
|
|
|
|
var id = await _repo.OpenSessionAsync(userId, dto.OpeningBalance);
|
|
|
|
// Opcional: Auditar la apertura
|
|
await _auditRepo.AddLogAsync(new AuditLog
|
|
{
|
|
UserId = userId,
|
|
Action = "CASH_SESSION_OPENED",
|
|
EntityId = id,
|
|
EntityType = "CashSession",
|
|
Details = $"Caja abierta con fondo: ${dto.OpeningBalance}",
|
|
CreatedAt = DateTime.UtcNow
|
|
});
|
|
|
|
return Ok(new { id });
|
|
}
|
|
|
|
[HttpPost("close")]
|
|
public async Task<IActionResult> Close(CashClosingDto dto)
|
|
{
|
|
var userIdClaim = User.FindFirst("Id")?.Value;
|
|
if (!int.TryParse(userIdClaim, out int userId)) return Unauthorized();
|
|
|
|
var session = await _repo.GetActiveSessionAsync(userId);
|
|
if (session == null) return BadRequest("No hay una sesión activa para cerrar");
|
|
|
|
var system = await _repo.GetSystemTotalsAsync(userId, session.OpeningDate, DateTime.UtcNow);
|
|
|
|
session.DeclaredCash = dto.DeclaredCash;
|
|
session.DeclaredCards = dto.DeclaredDebit + dto.DeclaredCredit;
|
|
session.DeclaredTransfers = dto.DeclaredTransfer;
|
|
|
|
session.SystemExpectedCash = (decimal)(system.Cash ?? 0m);
|
|
session.SystemExpectedCards = (decimal)(system.Cards ?? 0m);
|
|
session.SystemExpectedTransfers = (decimal)(system.Transfers ?? 0m);
|
|
|
|
decimal totalExpected = session.SystemExpectedCash.Value + session.OpeningBalance +
|
|
session.SystemExpectedCards.Value + session.SystemExpectedTransfers.Value;
|
|
|
|
decimal totalDeclared = dto.DeclaredCash + dto.DeclaredDebit + dto.DeclaredCredit + dto.DeclaredTransfer;
|
|
|
|
session.TotalDifference = totalDeclared - totalExpected;
|
|
|
|
await _repo.CloseSessionAsync(session);
|
|
|
|
// Auditar el cierre
|
|
await _auditRepo.AddLogAsync(new AuditLog
|
|
{
|
|
UserId = userId,
|
|
Action = "CASH_SESSION_CLOSED",
|
|
EntityId = session.Id,
|
|
EntityType = "CashSession",
|
|
Details = $"Caja cerrada por el usuario. Diferencia detectada: ${session.TotalDifference}",
|
|
CreatedAt = DateTime.UtcNow
|
|
});
|
|
|
|
return Ok(new
|
|
{
|
|
message = "Caja cerrada. Pendiente de validación por supervisor.",
|
|
difference = session.TotalDifference,
|
|
sessionId = session.Id
|
|
});
|
|
}
|
|
|
|
[HttpGet("summary")]
|
|
public async Task<IActionResult> GetSummary()
|
|
{
|
|
var userIdClaim = User.FindFirst("Id")?.Value;
|
|
if (!int.TryParse(userIdClaim, out int userId)) return Unauthorized();
|
|
|
|
var session = await _repo.GetActiveSessionAsync(userId);
|
|
if (session == null) return BadRequest("No hay sesión activa");
|
|
|
|
var system = await _repo.GetSystemTotalsAsync(userId, session.OpeningDate, DateTime.UtcNow);
|
|
|
|
return Ok(new
|
|
{
|
|
openingBalance = session.OpeningBalance,
|
|
cashSales = (decimal)(system.Cash ?? 0m),
|
|
cardSales = (decimal)(system.Cards ?? 0m),
|
|
transferSales = (decimal)(system.Transfers ?? 0m),
|
|
totalExpected = session.OpeningBalance + (decimal)(system.Cash ?? 0m) + (decimal)(system.Cards ?? 0m) + (decimal)(system.Transfers ?? 0m)
|
|
});
|
|
}
|
|
|
|
[HttpGet("pending")]
|
|
[Authorize(Roles = "Admin")]
|
|
public async Task<IActionResult> GetPending()
|
|
{
|
|
var pending = await _repo.GetPendingValidationAsync();
|
|
return Ok(pending);
|
|
}
|
|
|
|
[HttpPost("{id}/validate")]
|
|
[Authorize(Roles = "Admin")]
|
|
public async Task<IActionResult> Validate(int id, [FromBody] string notes)
|
|
{
|
|
var adminIdClaim = User.FindFirst("Id")?.Value;
|
|
if (!int.TryParse(adminIdClaim, out int adminId)) return Unauthorized();
|
|
|
|
await _repo.ValidateSessionAsync(id, adminId, notes);
|
|
|
|
await _auditRepo.AddLogAsync(new AuditLog
|
|
{
|
|
UserId = adminId,
|
|
Action = "CASH_SESSION_VALIDATED",
|
|
EntityId = id,
|
|
EntityType = "CashSession",
|
|
Details = $"Caja #{id} validada y liquidada. Notas: {notes}",
|
|
CreatedAt = DateTime.UtcNow
|
|
});
|
|
|
|
return Ok(new { message = "Sesión liquidada correctamente" });
|
|
}
|
|
|
|
[HttpGet("{id}/pdf")]
|
|
public async Task<IActionResult> DownloadPdf(int id)
|
|
{
|
|
var session = await _repo.GetSessionDetailAsync(id);
|
|
if (session == null) return NotFound();
|
|
|
|
var pdfBytes = ReportGenerator.GenerateCashSessionPdf(session);
|
|
string fileName = $"Acta_Cierre_{id}_{DateTime.Now:yyyyMMdd}.pdf";
|
|
|
|
return File(pdfBytes, "application/pdf", fileName);
|
|
}
|
|
} |