Feat: Cambios Varios 2
This commit is contained in:
171
src/SIGCM.API/Controllers/CashSessionsController.cs
Normal file
171
src/SIGCM.API/Controllers/CashSessionsController.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
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] decimal openingBalance)
|
||||
{
|
||||
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, 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: ${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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user