148 lines
5.4 KiB
C#
148 lines
5.4 KiB
C#
using foundation_system.Data;
|
|
using foundation_system.Models;
|
|
using foundation_system.Models.ViewModels;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace foundation_system.Controllers
|
|
{
|
|
[Authorize]
|
|
public class CajaChicaController : Controller
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
|
|
public CajaChicaController(ApplicationDbContext context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
// GET: CajaChica
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
var cajas = await _context.CajasChicas
|
|
.Include(c => c.Responsable)
|
|
.ThenInclude(u => u.Persona)
|
|
.ToListAsync();
|
|
return View(cajas);
|
|
}
|
|
|
|
// GET: CajaChica/Details/5
|
|
public async Task<IActionResult> Details(int? id)
|
|
{
|
|
if (id == null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
var cajaChica = await _context.CajasChicas
|
|
.Include(c => c.Responsable)
|
|
.ThenInclude(u => u.Persona)
|
|
.Include(c => c.Movimientos.OrderByDescending(m => m.FechaMovimiento).ThenByDescending(m => m.Id))
|
|
.ThenInclude(m => m.CategoriaGasto)
|
|
.Include(c => c.Movimientos)
|
|
.ThenInclude(m => m.UsuarioRegistro)
|
|
.ThenInclude(u => u.Persona)
|
|
.FirstOrDefaultAsync(m => m.Id == id);
|
|
|
|
if (cajaChica == null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
return View(cajaChica);
|
|
}
|
|
|
|
// GET: CajaChica/Create
|
|
public IActionResult Create()
|
|
{
|
|
ViewData["ResponsableUsuarioId"] = new SelectList(_context.Usuarios.Include(u => u.Persona).Select(u => new {
|
|
Id = u.Id,
|
|
NombreCompleto = u.Persona.Nombres + " " + u.Persona.Apellidos
|
|
}), "Id", "NombreCompleto");
|
|
return View(new CajaChicaViewModel());
|
|
}
|
|
|
|
// POST: CajaChica/Create
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> Create(CajaChicaViewModel model)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
// Verify user doesn't already have an open box
|
|
var existingBox = await _context.CajasChicas
|
|
.AnyAsync(c => c.ResponsableUsuarioId == model.ResponsableUsuarioId && c.Estado == "ABIERTA");
|
|
|
|
if (existingBox)
|
|
{
|
|
ModelState.AddModelError("ResponsableUsuarioId", "El usuario ya tiene una caja chica abierta.");
|
|
}
|
|
else
|
|
{
|
|
var cajaChica = new CajaChica
|
|
{
|
|
Nombre = model.Nombre,
|
|
ResponsableUsuarioId = model.ResponsableUsuarioId,
|
|
MontoAsignado = model.MontoAsignado,
|
|
SaldoActual = model.MontoAsignado, // Starts full
|
|
FechaApertura = model.FechaApertura,
|
|
Estado = "ABIERTA",
|
|
CreadoEn = DateTime.UtcNow,
|
|
ActualizadoEn = DateTime.UtcNow
|
|
};
|
|
|
|
_context.Add(cajaChica);
|
|
await _context.SaveChangesAsync();
|
|
|
|
// Create initial movement
|
|
var movimiento = new CajaChicaMovimiento
|
|
{
|
|
CajaChicaId = cajaChica.Id,
|
|
TipoMovimiento = "APERTURA",
|
|
FechaMovimiento = model.FechaApertura,
|
|
Monto = model.MontoAsignado,
|
|
Descripcion = "Apertura de Fondo Fijo",
|
|
UsuarioRegistroId = long.Parse(User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "1"), // Fallback to 1 if not found
|
|
CreadoEn = DateTime.UtcNow
|
|
};
|
|
|
|
_context.Add(movimiento);
|
|
await _context.SaveChangesAsync();
|
|
|
|
return RedirectToAction(nameof(Index));
|
|
}
|
|
}
|
|
|
|
ViewData["ResponsableUsuarioId"] = new SelectList(_context.Usuarios.Include(u => u.Persona).Select(u => new {
|
|
Id = u.Id,
|
|
NombreCompleto = u.Persona.Nombres + " " + u.Persona.Apellidos
|
|
}), "Id", "NombreCompleto", model.ResponsableUsuarioId);
|
|
return View(model);
|
|
}
|
|
|
|
// POST: CajaChica/Close/5
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> Close(int id)
|
|
{
|
|
var caja = await _context.CajasChicas.FindAsync(id);
|
|
if (caja == null) return NotFound();
|
|
|
|
if (caja.SaldoActual != caja.MontoAsignado)
|
|
{
|
|
// In a real scenario, you'd require reimbursement first or an adjustment
|
|
// For now, we'll just allow closing but maybe warn (or simple logic)
|
|
}
|
|
|
|
caja.Estado = "CERRADA";
|
|
caja.FechaCierre = DateOnly.FromDateTime(DateTime.Today);
|
|
caja.ActualizadoEn = DateTime.UtcNow;
|
|
|
|
await _context.SaveChangesAsync();
|
|
return RedirectToAction(nameof(Index));
|
|
}
|
|
}
|
|
}
|