first commit
This commit is contained in:
174
RS_system/Controllers/AccountController.cs
Normal file
174
RS_system/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Rs_system.Models.ViewModels;
|
||||
using Rs_system.Services;
|
||||
using Rs_system.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
public class AccountController : Controller
|
||||
{
|
||||
private readonly IAuthService _authService;
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public AccountController(IAuthService authService, ILogger<AccountController> logger, ApplicationDbContext context)
|
||||
{
|
||||
_authService = authService;
|
||||
_logger = logger;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: /Account/Login
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult Login(string? returnUrl = null)
|
||||
{
|
||||
if (User.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Account/Login
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Login(LoginViewModel model, string? returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var usuario = await _authService.ValidateUserAsync(model.NombreUsuario, model.Contrasena);
|
||||
|
||||
if (usuario == null)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Usuario o contraseña incorrectos");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Get user roles
|
||||
var roles = await _authService.GetUserRolesAsync(usuario.Id);
|
||||
|
||||
// Create claims
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.NameIdentifier, usuario.Id.ToString()),
|
||||
new(ClaimTypes.Name, usuario.NombreUsuario),
|
||||
new(ClaimTypes.Email, usuario.Email),
|
||||
new("FullName", usuario.Persona?.NombreCompleto ?? usuario.NombreUsuario)
|
||||
};
|
||||
|
||||
// Add role claims
|
||||
foreach (var role in roles)
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||
}
|
||||
|
||||
// Add permissions as claims
|
||||
var permissions = await _context.RolesUsuario
|
||||
.Where(ru => ru.UsuarioId == usuario.Id) // Changed user.Id to usuario.Id
|
||||
.Join(_context.RolesPermisos, ru => ru.RolId, rp => rp.RolId, (ru, rp) => rp)
|
||||
.Join(_context.Permisos, rp => rp.PermisoId, p => p.Id, (rp, p) => p)
|
||||
.Select(p => p.Codigo)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var permission in permissions)
|
||||
{
|
||||
claims.Add(new Claim("Permission", permission));
|
||||
}
|
||||
|
||||
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
var authProperties = new AuthenticationProperties
|
||||
{
|
||||
IsPersistent = model.RecordarMe,
|
||||
ExpiresUtc = model.RecordarMe
|
||||
? DateTimeOffset.UtcNow.AddDays(30)
|
||||
: DateTimeOffset.UtcNow.AddHours(8)
|
||||
};
|
||||
|
||||
await HttpContext.SignInAsync(
|
||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
new ClaimsPrincipal(claimsIdentity),
|
||||
authProperties);
|
||||
|
||||
// Update last login
|
||||
await _authService.UpdateLastLoginAsync(usuario.Id);
|
||||
|
||||
_logger.LogInformation("User {Username} logged in", usuario.NombreUsuario);
|
||||
|
||||
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
// GET: /Account/Register
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult Register()
|
||||
{
|
||||
if (User.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Account/Register
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Register(RegisterViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var (success, message, _) = await _authService.RegisterUserAsync(model);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, message);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
TempData["SuccessMessage"] = "¡Registro exitoso! Ahora puedes iniciar sesión.";
|
||||
return RedirectToAction(nameof(Login));
|
||||
}
|
||||
|
||||
// POST: /Account/Logout
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
_logger.LogInformation("User logged out");
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
// GET: /Account/AccessDenied
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult AccessDenied()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
264
RS_system/Controllers/AsistenciaCultoController.cs
Normal file
264
RS_system/Controllers/AsistenciaCultoController.cs
Normal file
@@ -0,0 +1,264 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
using Rs_system.Models.ViewModels;
|
||||
using Rs_system.Models.Enums;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class AsistenciaCultoController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public AsistenciaCultoController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: AsistenciaCulto
|
||||
public async Task<IActionResult> Index(AsistenciaCultoFiltroViewModel filtro)
|
||||
{
|
||||
var query = _context.AsistenciasCulto.AsQueryable();
|
||||
|
||||
// Aplicar filtros
|
||||
if (filtro.FechaDesde.HasValue)
|
||||
{
|
||||
query = query.Where(a => a.FechaHoraInicio >= filtro.FechaDesde.Value.Date);
|
||||
}
|
||||
|
||||
if (filtro.FechaHasta.HasValue)
|
||||
{
|
||||
var fechaHasta = filtro.FechaHasta.Value.Date.AddDays(1).AddSeconds(-1);
|
||||
query = query.Where(a => a.FechaHoraInicio <= fechaHasta);
|
||||
}
|
||||
|
||||
if (filtro.TipoCulto.HasValue)
|
||||
{
|
||||
query = query.Where(a => a.TipoCulto == filtro.TipoCulto.Value);
|
||||
}
|
||||
|
||||
if (filtro.TipoConteo.HasValue)
|
||||
{
|
||||
query = query.Where(a => a.TipoConteo == filtro.TipoConteo.Value);
|
||||
}
|
||||
|
||||
// Ordenar por fecha descendente (más reciente primero)
|
||||
query = query.OrderByDescending(a => a.FechaHoraInicio);
|
||||
|
||||
var resultados = await query.ToListAsync();
|
||||
|
||||
filtro.Resultados = resultados;
|
||||
|
||||
// Pasar tipos de culto y conteo para dropdowns
|
||||
ViewBag.TiposCulto = Enum.GetValues(typeof(TipoCulto)).Cast<TipoCulto>().ToList();
|
||||
ViewBag.TiposConteo = Enum.GetValues(typeof(TipoConteo)).Cast<TipoConteo>().ToList();
|
||||
|
||||
return View(filtro);
|
||||
}
|
||||
|
||||
// GET: AsistenciaCulto/Details/5
|
||||
public async Task<IActionResult> Details(long? id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var asistenciaCulto = await _context.AsistenciasCulto
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
|
||||
if (asistenciaCulto == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(asistenciaCulto);
|
||||
}
|
||||
|
||||
// GET: AsistenciaCulto/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
var model = new AsistenciaCultoViewModel
|
||||
{
|
||||
FechaHoraInicio = DateTime.Now
|
||||
};
|
||||
|
||||
ViewBag.TiposCulto = Enum.GetValues(typeof(TipoCulto)).Cast<TipoCulto>().ToList();
|
||||
ViewBag.TiposConteo = Enum.GetValues(typeof(TipoConteo)).Cast<TipoConteo>().ToList();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// POST: AsistenciaCulto/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create(AsistenciaCultoViewModel model)
|
||||
{
|
||||
ViewBag.TiposCulto = Enum.GetValues(typeof(TipoCulto)).Cast<TipoCulto>().ToList();
|
||||
ViewBag.TiposConteo = Enum.GetValues(typeof(TipoConteo)).Cast<TipoConteo>().ToList();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var asistenciaCulto = new AsistenciaCulto
|
||||
{
|
||||
FechaHoraInicio = model.FechaHoraInicio,
|
||||
TipoCulto = model.TipoCulto,
|
||||
TipoConteo = model.TipoConteo,
|
||||
HermanasMisioneras = model.HermanasMisioneras,
|
||||
HermanosFraternidad = model.HermanosFraternidad,
|
||||
EmbajadoresCristo = model.EmbajadoresCristo,
|
||||
Ninos = model.Ninos,
|
||||
Visitas = model.Visitas,
|
||||
Amigos = model.Amigos,
|
||||
AdultosGeneral = model.AdultosGeneral,
|
||||
TotalManual = model.TotalManual,
|
||||
Observaciones = model.Observaciones,
|
||||
CreadoPor = User.Identity?.Name,
|
||||
CreadoEn = DateTime.UtcNow,
|
||||
ActualizadoEn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_context.Add(asistenciaCulto);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: AsistenciaCulto/Edit/5
|
||||
public async Task<IActionResult> Edit(long? id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var asistenciaCulto = await _context.AsistenciasCulto.FindAsync(id);
|
||||
if (asistenciaCulto == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var model = new AsistenciaCultoViewModel
|
||||
{
|
||||
Id = asistenciaCulto.Id,
|
||||
FechaHoraInicio = asistenciaCulto.FechaHoraInicio,
|
||||
TipoCulto = asistenciaCulto.TipoCulto,
|
||||
TipoConteo = asistenciaCulto.TipoConteo,
|
||||
HermanasMisioneras = asistenciaCulto.HermanasMisioneras,
|
||||
HermanosFraternidad = asistenciaCulto.HermanosFraternidad,
|
||||
EmbajadoresCristo = asistenciaCulto.EmbajadoresCristo,
|
||||
Ninos = asistenciaCulto.Ninos,
|
||||
Visitas = asistenciaCulto.Visitas,
|
||||
Amigos = asistenciaCulto.Amigos,
|
||||
AdultosGeneral = asistenciaCulto.AdultosGeneral,
|
||||
TotalManual = asistenciaCulto.TotalManual,
|
||||
Observaciones = asistenciaCulto.Observaciones
|
||||
};
|
||||
|
||||
ViewBag.TiposCulto = Enum.GetValues(typeof(TipoCulto)).Cast<TipoCulto>().ToList();
|
||||
ViewBag.TiposConteo = Enum.GetValues(typeof(TipoConteo)).Cast<TipoConteo>().ToList();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// POST: AsistenciaCulto/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(long id, AsistenciaCultoViewModel model)
|
||||
{
|
||||
if (id != model.Id)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
ViewBag.TiposCulto = Enum.GetValues(typeof(TipoCulto)).Cast<TipoCulto>().ToList();
|
||||
ViewBag.TiposConteo = Enum.GetValues(typeof(TipoConteo)).Cast<TipoConteo>().ToList();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var asistenciaCulto = await _context.AsistenciasCulto.FindAsync(id);
|
||||
if (asistenciaCulto == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
asistenciaCulto.FechaHoraInicio = model.FechaHoraInicio;
|
||||
asistenciaCulto.TipoCulto = model.TipoCulto;
|
||||
asistenciaCulto.TipoConteo = model.TipoConteo;
|
||||
asistenciaCulto.HermanasMisioneras = model.HermanasMisioneras;
|
||||
asistenciaCulto.HermanosFraternidad = model.HermanosFraternidad;
|
||||
asistenciaCulto.EmbajadoresCristo = model.EmbajadoresCristo;
|
||||
asistenciaCulto.Ninos = model.Ninos;
|
||||
asistenciaCulto.Visitas = model.Visitas;
|
||||
asistenciaCulto.Amigos = model.Amigos;
|
||||
asistenciaCulto.AdultosGeneral = model.AdultosGeneral;
|
||||
asistenciaCulto.TotalManual = model.TotalManual;
|
||||
asistenciaCulto.Observaciones = model.Observaciones;
|
||||
asistenciaCulto.ActualizadoEn = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
_context.Update(asistenciaCulto);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!AsistenciaCultoExists(asistenciaCulto.Id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: AsistenciaCulto/Delete/5
|
||||
public async Task<IActionResult> Delete(long? id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var asistenciaCulto = await _context.AsistenciasCulto
|
||||
.FirstOrDefaultAsync(m => m.Id == id);
|
||||
|
||||
if (asistenciaCulto == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(asistenciaCulto);
|
||||
}
|
||||
|
||||
// POST: AsistenciaCulto/Delete/5
|
||||
[HttpPost, ActionName("Delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteConfirmed(long id)
|
||||
{
|
||||
var asistenciaCulto = await _context.AsistenciasCulto.FindAsync(id);
|
||||
if (asistenciaCulto != null)
|
||||
{
|
||||
_context.AsistenciasCulto.Remove(asistenciaCulto);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool AsistenciaCultoExists(long id)
|
||||
{
|
||||
return _context.AsistenciasCulto.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
88
RS_system/Controllers/ConfiguracionController.cs
Normal file
88
RS_system/Controllers/ConfiguracionController.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class ConfiguracionController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public ConfiguracionController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Configuracion
|
||||
public async Task<IActionResult> Index(string? categoria)
|
||||
{
|
||||
var query = _context.Configuraciones.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrEmpty(categoria))
|
||||
{
|
||||
query = query.Where(c => c.Categoria == categoria);
|
||||
}
|
||||
|
||||
var configuraciones = await query
|
||||
.OrderBy(c => c.Categoria)
|
||||
.ThenBy(c => c.Grupo)
|
||||
.ThenBy(c => c.Orden)
|
||||
.ToListAsync();
|
||||
|
||||
ViewBag.Categorias = await _context.Configuraciones
|
||||
.Select(c => c.Categoria)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
ViewBag.SelectedCategoria = categoria;
|
||||
|
||||
return View(configuraciones);
|
||||
}
|
||||
|
||||
// GET: Configuracion/Edit/5
|
||||
public async Task<IActionResult> Edit(int? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var config = await _context.Configuraciones.FindAsync(id);
|
||||
if (config == null || !config.EsEditable) return NotFound();
|
||||
|
||||
return View(config);
|
||||
}
|
||||
|
||||
// POST: Configuracion/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(int id, [Bind("Id,Valor")] ConfiguracionSistema model)
|
||||
{
|
||||
if (id != model.Id) return NotFound();
|
||||
|
||||
var config = await _context.Configuraciones.FindAsync(id);
|
||||
if (config == null || !config.EsEditable) return NotFound();
|
||||
|
||||
try
|
||||
{
|
||||
config.Valor = model.Valor;
|
||||
config.ActualizadoEn = DateTime.UtcNow;
|
||||
|
||||
_context.Update(config);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction(nameof(Index), new { categoria = config.Categoria });
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!ConfiguracionExists(model.Id)) return NotFound();
|
||||
else throw;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ConfiguracionExists(int id)
|
||||
{
|
||||
return _context.Configuraciones.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
37
RS_system/Controllers/HomeController.cs
Normal file
37
RS_system/Controllers/HomeController.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Diagnostics;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Rs_system.Models;
|
||||
using Rs_system.Models.ViewModels;
|
||||
using Rs_system.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
|
||||
|
||||
public HomeController(ILogger<HomeController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
}
|
||||
127
RS_system/Controllers/ModuloController.cs
Normal file
127
RS_system/Controllers/ModuloController.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class ModuloController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public ModuloController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Modulo
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var modulos = await _context.Modulos
|
||||
.Include(m => m.Parent)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulos);
|
||||
}
|
||||
|
||||
// GET: Modulo/Create
|
||||
public async Task<IActionResult> Create()
|
||||
{
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: Modulo/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create([Bind("Nombre,Icono,Orden,Activo,ParentId")] Modulo modulo)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
modulo.CreadoEn = DateTime.UtcNow;
|
||||
_context.Add(modulo);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulo);
|
||||
}
|
||||
|
||||
// GET: Modulo/Edit/5
|
||||
public async Task<IActionResult> Edit(int? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var modulo = await _context.Modulos.FindAsync(id);
|
||||
if (modulo == null) return NotFound();
|
||||
|
||||
// Exclude current module and its children from parent options
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo && m.Id != id)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulo);
|
||||
}
|
||||
|
||||
// POST: Modulo/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(int id, [Bind("Id,Nombre,Icono,Orden,Activo,ParentId")] Modulo modulo)
|
||||
{
|
||||
if (id != modulo.Id) return NotFound();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Update(modulo);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!ModuloExists(modulo.Id)) return NotFound();
|
||||
else throw;
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo && m.Id != id)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulo);
|
||||
}
|
||||
|
||||
// POST: Modulo/Delete/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
var modulo = await _context.Modulos.FindAsync(id);
|
||||
if (modulo != null)
|
||||
{
|
||||
var isUsed = await _context.Permisos.AnyAsync(p => p.ModuloId == id);
|
||||
if (isUsed)
|
||||
{
|
||||
TempData["ErrorMessage"] = "No se puede eliminar porque tiene permisos asociados.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
_context.Modulos.Remove(modulo);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool ModuloExists(int id)
|
||||
{
|
||||
return _context.Modulos.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
303
RS_system/Controllers/OfrendaController.cs
Normal file
303
RS_system/Controllers/OfrendaController.cs
Normal file
@@ -0,0 +1,303 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
using Rs_system.Models.ViewModels;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class OfrendaController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public OfrendaController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Ofrenda
|
||||
public async Task<IActionResult> Index(int? mes, int? anio)
|
||||
{
|
||||
var currentDate = DateTime.Today;
|
||||
mes ??= currentDate.Month;
|
||||
anio ??= currentDate.Year;
|
||||
|
||||
var registros = await _context.RegistrosCulto
|
||||
.Include(r => r.Ofrendas.Where(o => !o.Eliminado))
|
||||
.ThenInclude(o => o.Descuentos.Where(d => !d.Eliminado))
|
||||
.Where(r => !r.Eliminado && r.Fecha.Month == mes && r.Fecha.Year == anio)
|
||||
.OrderByDescending(r => r.Fecha)
|
||||
.ToListAsync();
|
||||
|
||||
ViewBag.MesActual = mes;
|
||||
ViewBag.AnioActual = anio;
|
||||
ViewBag.Meses = GetMesesSelectList();
|
||||
ViewBag.Anios = GetAniosSelectList();
|
||||
|
||||
return View(registros);
|
||||
}
|
||||
|
||||
// GET: Ofrenda/Details/5
|
||||
public async Task<IActionResult> Details(long? id)
|
||||
{
|
||||
if (id == null)
|
||||
return NotFound();
|
||||
|
||||
var registro = await _context.RegistrosCulto
|
||||
.Include(r => r.Ofrendas.Where(o => !o.Eliminado))
|
||||
.ThenInclude(o => o.Descuentos.Where(d => !d.Eliminado))
|
||||
.FirstOrDefaultAsync(r => r.Id == id && !r.Eliminado);
|
||||
|
||||
if (registro == null)
|
||||
return NotFound();
|
||||
|
||||
return View(registro);
|
||||
}
|
||||
|
||||
// GET: Ofrenda/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
var viewModel = new RegistroCultoViewModel
|
||||
{
|
||||
Fecha = DateOnly.FromDateTime(DateTime.Today)
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// POST: Ofrenda/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create(RegistroCultoViewModel viewModel)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var strategy = _context.Database.CreateExecutionStrategy();
|
||||
|
||||
try
|
||||
{
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||
|
||||
var registro = new RegistroCulto
|
||||
{
|
||||
Fecha = viewModel.Fecha,
|
||||
Observaciones = viewModel.Observaciones,
|
||||
CreadoPor = User.Identity?.Name ?? "Sistema",
|
||||
CreadoEn = DateTime.UtcNow,
|
||||
ActualizadoEn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_context.RegistrosCulto.Add(registro);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Add offerings
|
||||
foreach (var ofrendaVm in viewModel.Ofrendas)
|
||||
{
|
||||
var ofrenda = new Ofrenda
|
||||
{
|
||||
RegistroCultoId = registro.Id,
|
||||
Monto = ofrendaVm.Monto,
|
||||
Concepto = ofrendaVm.Concepto
|
||||
};
|
||||
_context.Ofrendas.Add(ofrenda);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Add deductions
|
||||
foreach (var descuentoVm in ofrendaVm.Descuentos)
|
||||
{
|
||||
var descuento = new DescuentoOfrenda
|
||||
{
|
||||
OfrendaId = ofrenda.Id,
|
||||
Monto = descuentoVm.Monto,
|
||||
Concepto = descuentoVm.Concepto
|
||||
};
|
||||
_context.DescuentosOfrenda.Add(descuento);
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
});
|
||||
|
||||
TempData["SuccessMessage"] = "Registro de ofrendas creado exitosamente.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
ModelState.AddModelError("", "Error al guardar el registro. Intente nuevamente.");
|
||||
}
|
||||
}
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// GET: Ofrenda/Edit/5
|
||||
public async Task<IActionResult> Edit(long? id)
|
||||
{
|
||||
if (id == null)
|
||||
return NotFound();
|
||||
|
||||
var registro = await _context.RegistrosCulto
|
||||
.Include(r => r.Ofrendas.Where(o => !o.Eliminado))
|
||||
.ThenInclude(o => o.Descuentos.Where(d => !d.Eliminado))
|
||||
.FirstOrDefaultAsync(r => r.Id == id && !r.Eliminado);
|
||||
|
||||
if (registro == null)
|
||||
return NotFound();
|
||||
|
||||
var viewModel = new RegistroCultoViewModel
|
||||
{
|
||||
Id = registro.Id,
|
||||
Fecha = registro.Fecha,
|
||||
Observaciones = registro.Observaciones,
|
||||
Ofrendas = registro.Ofrendas.Select(o => new OfrendaItemViewModel
|
||||
{
|
||||
Id = o.Id,
|
||||
Monto = o.Monto,
|
||||
Concepto = o.Concepto,
|
||||
Descuentos = o.Descuentos.Select(d => new DescuentoItemViewModel
|
||||
{
|
||||
Id = d.Id,
|
||||
Monto = d.Monto,
|
||||
Concepto = d.Concepto
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// POST: Ofrenda/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(long id, RegistroCultoViewModel viewModel)
|
||||
{
|
||||
if (id != viewModel.Id)
|
||||
return NotFound();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var strategy = _context.Database.CreateExecutionStrategy();
|
||||
|
||||
try
|
||||
{
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||
|
||||
var registro = await _context.RegistrosCulto
|
||||
.Include(r => r.Ofrendas)
|
||||
.ThenInclude(o => o.Descuentos)
|
||||
.FirstOrDefaultAsync(r => r.Id == id && !r.Eliminado);
|
||||
|
||||
if (registro == null)
|
||||
throw new InvalidOperationException("Registro no encontrado");
|
||||
|
||||
registro.Fecha = viewModel.Fecha;
|
||||
registro.Observaciones = viewModel.Observaciones;
|
||||
registro.ActualizadoEn = DateTime.UtcNow;
|
||||
|
||||
// Mark existing offerings as deleted
|
||||
foreach (var ofrenda in registro.Ofrendas)
|
||||
{
|
||||
ofrenda.Eliminado = true;
|
||||
foreach (var descuento in ofrenda.Descuentos)
|
||||
descuento.Eliminado = true;
|
||||
}
|
||||
|
||||
// Add new offerings
|
||||
foreach (var ofrendaVm in viewModel.Ofrendas)
|
||||
{
|
||||
var ofrenda = new Ofrenda
|
||||
{
|
||||
RegistroCultoId = registro.Id,
|
||||
Monto = ofrendaVm.Monto,
|
||||
Concepto = ofrendaVm.Concepto
|
||||
};
|
||||
_context.Ofrendas.Add(ofrenda);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
foreach (var descuentoVm in ofrendaVm.Descuentos)
|
||||
{
|
||||
var descuento = new DescuentoOfrenda
|
||||
{
|
||||
OfrendaId = ofrenda.Id,
|
||||
Monto = descuentoVm.Monto,
|
||||
Concepto = descuentoVm.Concepto
|
||||
};
|
||||
_context.DescuentosOfrenda.Add(descuento);
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
});
|
||||
|
||||
TempData["SuccessMessage"] = "Registro de ofrendas actualizado exitosamente.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
ModelState.AddModelError("", "Error al actualizar el registro. Intente nuevamente.");
|
||||
}
|
||||
}
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
// POST: Ofrenda/Delete/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Delete(long id)
|
||||
{
|
||||
var registro = await _context.RegistrosCulto.FindAsync(id);
|
||||
if (registro == null)
|
||||
return NotFound();
|
||||
|
||||
registro.Eliminado = true;
|
||||
registro.ActualizadoEn = DateTime.UtcNow;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
TempData["SuccessMessage"] = "Registro eliminado exitosamente.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem> GetMesesSelectList()
|
||||
{
|
||||
var meses = new[]
|
||||
{
|
||||
new { Value = 1, Text = "Enero" },
|
||||
new { Value = 2, Text = "Febrero" },
|
||||
new { Value = 3, Text = "Marzo" },
|
||||
new { Value = 4, Text = "Abril" },
|
||||
new { Value = 5, Text = "Mayo" },
|
||||
new { Value = 6, Text = "Junio" },
|
||||
new { Value = 7, Text = "Julio" },
|
||||
new { Value = 8, Text = "Agosto" },
|
||||
new { Value = 9, Text = "Septiembre" },
|
||||
new { Value = 10, Text = "Octubre" },
|
||||
new { Value = 11, Text = "Noviembre" },
|
||||
new { Value = 12, Text = "Diciembre" }
|
||||
};
|
||||
|
||||
return meses.Select(m => new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem
|
||||
{
|
||||
Value = m.Value.ToString(),
|
||||
Text = m.Text
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem> GetAniosSelectList()
|
||||
{
|
||||
var currentYear = DateTime.Today.Year;
|
||||
return Enumerable.Range(currentYear - 5, 10)
|
||||
.Select(y => new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem
|
||||
{
|
||||
Value = y.ToString(),
|
||||
Text = y.ToString()
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
122
RS_system/Controllers/PermisoController.cs
Normal file
122
RS_system/Controllers/PermisoController.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class PermisoController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public PermisoController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Permiso
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var permisos = await _context.Permisos
|
||||
.Include(p => p.Modulo)
|
||||
.OrderBy(p => p.Modulo!.Orden)
|
||||
.ThenBy(p => p.Orden)
|
||||
.ToListAsync();
|
||||
return View(permisos);
|
||||
}
|
||||
|
||||
// GET: Permiso/Create
|
||||
public async Task<IActionResult> Create()
|
||||
{
|
||||
ViewBag.Modulos = await _context.Modulos.OrderBy(m => m.Orden).ToListAsync();
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: Permiso/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create([Bind("ModuloId,Codigo,Nombre,Descripcion,Url,Icono,Orden,EsMenu")] Permiso permiso)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
if (await _context.Permisos.AnyAsync(p => p.Codigo == permiso.Codigo))
|
||||
{
|
||||
ModelState.AddModelError("Codigo", "El código ya existe.");
|
||||
ViewBag.Modulos = await _context.Modulos.OrderBy(m => m.Orden).ToListAsync();
|
||||
return View(permiso);
|
||||
}
|
||||
|
||||
permiso.CreadoEn = DateTime.UtcNow;
|
||||
_context.Add(permiso);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.Modulos = await _context.Modulos.OrderBy(m => m.Orden).ToListAsync();
|
||||
return View(permiso);
|
||||
}
|
||||
|
||||
// GET: Permiso/Edit/5
|
||||
public async Task<IActionResult> Edit(int? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var permiso = await _context.Permisos.FindAsync(id);
|
||||
if (permiso == null) return NotFound();
|
||||
|
||||
ViewBag.Modulos = await _context.Modulos.OrderBy(m => m.Orden).ToListAsync();
|
||||
return View(permiso);
|
||||
}
|
||||
|
||||
// POST: Permiso/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(int id, [Bind("Id,ModuloId,Codigo,Nombre,Descripcion,Url,Icono,Orden,EsMenu")] Permiso permiso)
|
||||
{
|
||||
if (id != permiso.Id) return NotFound();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Update(permiso);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!PermisoExists(permiso.Id)) return NotFound();
|
||||
else throw;
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.Modulos = await _context.Modulos.OrderBy(m => m.Orden).ToListAsync();
|
||||
return View(permiso);
|
||||
}
|
||||
|
||||
// POST: Permiso/Delete/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
var permiso = await _context.Permisos.FindAsync(id);
|
||||
if (permiso != null)
|
||||
{
|
||||
var isUsed = await _context.RolesPermisos.AnyAsync(rp => rp.PermisoId == id);
|
||||
if (isUsed)
|
||||
{
|
||||
TempData["ErrorMessage"] = "No se puede eliminar porque está asignado a roles.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
_context.Permisos.Remove(permiso);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool PermisoExists(int id)
|
||||
{
|
||||
return _context.Permisos.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
22
RS_system/Controllers/ReportesController.cs
Normal file
22
RS_system/Controllers/ReportesController.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Rs_system.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Rs_system.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ReportesController : Controller
|
||||
{
|
||||
private readonly IReporteService _reporteService;
|
||||
|
||||
public ReportesController(IReporteService reporteService)
|
||||
{
|
||||
_reporteService = reporteService;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
199
RS_system/Controllers/RolController.cs
Normal file
199
RS_system/Controllers/RolController.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class RolController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public RolController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Rol
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
return View(await _context.RolesSistema
|
||||
.Include(r => r.RolesPermisos)
|
||||
.OrderBy(r => r.Nombre)
|
||||
.ToListAsync());
|
||||
}
|
||||
|
||||
// GET: Rol/Create
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: Rol/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create([Bind("Codigo,Nombre,Descripcion")] RolSistema rol)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
if (await _context.RolesSistema.AnyAsync(r => r.Codigo == rol.Codigo))
|
||||
{
|
||||
ModelState.AddModelError("Codigo", "El código de rol ya existe.");
|
||||
return View(rol);
|
||||
}
|
||||
|
||||
rol.CreadoEn = DateTime.UtcNow;
|
||||
_context.Add(rol);
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(rol);
|
||||
}
|
||||
|
||||
// GET: Rol/Edit/5
|
||||
public async Task<IActionResult> Edit(int? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var rol = await _context.RolesSistema.FindAsync(id);
|
||||
if (rol == null) return NotFound();
|
||||
return View(rol);
|
||||
}
|
||||
|
||||
// POST: Rol/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(int id, [Bind("Id,Codigo,Nombre,Descripcion")] RolSistema rol)
|
||||
{
|
||||
if (id != rol.Id) return NotFound();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Update(rol);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!RolExists(rol.Id)) return NotFound();
|
||||
else throw;
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View(rol);
|
||||
}
|
||||
|
||||
// GET: Rol/Permissions/5
|
||||
public async Task<IActionResult> Permissions(int? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var rol = await _context.RolesSistema
|
||||
.Include(r => r.RolesPermisos)
|
||||
.ThenInclude(rp => rp.Permiso)
|
||||
.FirstOrDefaultAsync(r => r.Id == id);
|
||||
|
||||
if (rol == null) return NotFound();
|
||||
|
||||
// Fetch all permissions from DB
|
||||
var permissions = await _context.Permisos
|
||||
.OrderBy(p => p.Modulo)
|
||||
.ThenBy(p => p.Orden)
|
||||
.ToListAsync();
|
||||
|
||||
ViewBag.Rol = rol;
|
||||
ViewBag.AssignedControllerCodes = rol.RolesPermisos.Select(rp => rp.Permiso.Codigo).ToList();
|
||||
|
||||
return View(permissions);
|
||||
}
|
||||
|
||||
// POST: Rol/UpdatePermissions
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
|
||||
public async Task<IActionResult> UpdatePermissions(int rolId, string[] selectedControllers)
|
||||
{
|
||||
var strategy = _context.Database.CreateExecutionStrategy();
|
||||
|
||||
try
|
||||
{
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||
|
||||
var rol = await _context.RolesSistema
|
||||
.Include(r => r.RolesPermisos)
|
||||
.FirstOrDefaultAsync(r => r.Id == rolId);
|
||||
|
||||
if (rol == null) throw new InvalidOperationException("Rol no encontrado");
|
||||
|
||||
// Remove existing permissions
|
||||
_context.RolesPermisos.RemoveRange(rol.RolesPermisos);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Add new permissions
|
||||
if (selectedControllers != null)
|
||||
{
|
||||
foreach (var controllerCode in selectedControllers)
|
||||
{
|
||||
var permiso = await _context.Permisos.FirstOrDefaultAsync(p => p.Codigo == controllerCode);
|
||||
if (permiso != null)
|
||||
{
|
||||
_context.RolesPermisos.Add(new RolPermiso
|
||||
{
|
||||
RolId = rolId,
|
||||
PermisoId = permiso.Id,
|
||||
AsignadoEn = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
});
|
||||
|
||||
TempData["SuccessMessage"] = "Permisos actualizados correctamente.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TempData["ErrorMessage"] = "Ocurrió un error al actualizar los permisos: " + ex.Message;
|
||||
}
|
||||
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
// POST: Rol/Delete/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
var rol = await _context.RolesSistema.FindAsync(id);
|
||||
if (rol != null)
|
||||
{
|
||||
// Check if it's being used by users
|
||||
var isUsed = await _context.RolesUsuario.AnyAsync(ru => ru.RolId == id);
|
||||
if (isUsed)
|
||||
{
|
||||
TempData["ErrorMessage"] = "No se puede eliminar el rol porque está asignado a uno o más usuarios.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
// Remove permissions first
|
||||
var permissions = await _context.RolesPermisos.Where(rp => rp.RolId == id).ToListAsync();
|
||||
_context.RolesPermisos.RemoveRange(permissions);
|
||||
|
||||
_context.RolesSistema.Remove(rol);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool RolExists(int id)
|
||||
{
|
||||
return _context.RolesSistema.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
235
RS_system/Controllers/UsuarioController.cs
Normal file
235
RS_system/Controllers/UsuarioController.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Rs_system.Data;
|
||||
using Rs_system.Models;
|
||||
using Rs_system.Models.ViewModels;
|
||||
using BCrypt.Net;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Rs_system.Controllers;
|
||||
|
||||
[Authorize]
|
||||
public class UsuarioController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public UsuarioController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// GET: Usuario
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var usuarios = await _context.Usuarios
|
||||
.Include(u => u.Persona)
|
||||
.Include(u => u.RolesUsuario)
|
||||
.ThenInclude(ru => ru.Rol)
|
||||
.ToListAsync();
|
||||
return View(usuarios);
|
||||
}
|
||||
|
||||
// GET: Usuario/Create
|
||||
public async Task<IActionResult> Create()
|
||||
{
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(new UsuarioViewModel());
|
||||
}
|
||||
|
||||
// POST: Usuario/Create
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Create(UsuarioViewModel model)
|
||||
{
|
||||
if (string.IsNullOrEmpty(model.Contrasena))
|
||||
{
|
||||
ModelState.AddModelError("Contrasena", "La contraseña es requerida para nuevos usuarios");
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
if (await _context.Usuarios.AnyAsync(u => u.NombreUsuario == model.NombreUsuario))
|
||||
{
|
||||
ModelState.AddModelError("NombreUsuario", "El nombre de usuario ya está en uso");
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if (await _context.Usuarios.AnyAsync(u => u.Email == model.Email))
|
||||
{
|
||||
ModelState.AddModelError("Email", "El correo electrónico ya está en uso");
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||
try
|
||||
{
|
||||
var persona = new Persona
|
||||
{
|
||||
Nombres = model.Nombres,
|
||||
Apellidos = model.Apellidos,
|
||||
Email = model.Email,
|
||||
Telefono = model.Telefono,
|
||||
Activo = true
|
||||
};
|
||||
|
||||
_context.Personas.Add(persona);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var usuario = new Usuario
|
||||
{
|
||||
PersonaId = persona.Id,
|
||||
NombreUsuario = model.NombreUsuario,
|
||||
Email = model.Email,
|
||||
HashContrasena = BCrypt.Net.BCrypt.HashPassword(model.Contrasena),
|
||||
Activo = true,
|
||||
CreadoEn = DateTime.UtcNow,
|
||||
ActualizadoEn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_context.Usuarios.Add(usuario);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Assign Roles
|
||||
if (model.SelectedRoles != null)
|
||||
{
|
||||
foreach (var roleId in model.SelectedRoles)
|
||||
{
|
||||
_context.RolesUsuario.Add(new RolUsuario
|
||||
{
|
||||
UsuarioId = usuario.Id,
|
||||
RolId = roleId,
|
||||
AsignadoEn = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
ModelState.AddModelError("", "Ocurrió un error al crear el usuario.");
|
||||
}
|
||||
}
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: Usuario/Edit/5
|
||||
public async Task<IActionResult> Edit(long? id)
|
||||
{
|
||||
if (id == null) return NotFound();
|
||||
|
||||
var usuario = await _context.Usuarios
|
||||
.Include(u => u.Persona)
|
||||
.Include(u => u.RolesUsuario)
|
||||
.FirstOrDefaultAsync(u => u.Id == id);
|
||||
|
||||
if (usuario == null) return NotFound();
|
||||
|
||||
var model = new UsuarioViewModel
|
||||
{
|
||||
Id = usuario.Id,
|
||||
Nombres = usuario.Persona.Nombres,
|
||||
Apellidos = usuario.Persona.Apellidos,
|
||||
NombreUsuario = usuario.NombreUsuario,
|
||||
Email = usuario.Email,
|
||||
Telefono = usuario.Persona.Telefono,
|
||||
Activo = usuario.Activo,
|
||||
SelectedRoles = usuario.RolesUsuario.Select(ru => ru.RolId).ToList()
|
||||
};
|
||||
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// POST: Usuario/Edit/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Edit(long id, UsuarioViewModel model)
|
||||
{
|
||||
if (id != model.Id) return NotFound();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var usuario = await _context.Usuarios
|
||||
.Include(u => u.Persona)
|
||||
.Include(u => u.RolesUsuario)
|
||||
.FirstOrDefaultAsync(u => u.Id == id);
|
||||
|
||||
if (usuario == null) return NotFound();
|
||||
|
||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||
try
|
||||
{
|
||||
// Update Persona
|
||||
usuario.Persona.Nombres = model.Nombres;
|
||||
usuario.Persona.Apellidos = model.Apellidos;
|
||||
usuario.Persona.Telefono = model.Telefono;
|
||||
usuario.Persona.ActualizadoEn = DateTime.UtcNow;
|
||||
|
||||
// Update Usuario
|
||||
usuario.NombreUsuario = model.NombreUsuario;
|
||||
usuario.Email = model.Email;
|
||||
usuario.Activo = model.Activo;
|
||||
usuario.ActualizadoEn = DateTime.UtcNow;
|
||||
|
||||
if (!string.IsNullOrEmpty(model.Contrasena))
|
||||
{
|
||||
usuario.HashContrasena = BCrypt.Net.BCrypt.HashPassword(model.Contrasena);
|
||||
}
|
||||
|
||||
// Update Roles
|
||||
_context.RolesUsuario.RemoveRange(usuario.RolesUsuario);
|
||||
if (model.SelectedRoles != null)
|
||||
{
|
||||
foreach (var roleId in model.SelectedRoles)
|
||||
{
|
||||
_context.RolesUsuario.Add(new RolUsuario
|
||||
{
|
||||
UsuarioId = usuario.Id,
|
||||
RolId = roleId,
|
||||
AsignadoEn = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
ModelState.AddModelError("", "Ocurrió un error al actualizar el usuario.");
|
||||
}
|
||||
}
|
||||
ViewBag.Roles = await _context.RolesSistema.ToListAsync();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// POST: Usuario/Desactivar/5
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Desactivar(long id)
|
||||
{
|
||||
var usuario = await _context.Usuarios.FindAsync(id);
|
||||
if (usuario != null)
|
||||
{
|
||||
usuario.Activo = false;
|
||||
usuario.ActualizadoEn = DateTime.UtcNow;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private bool UsuarioExists(long id)
|
||||
{
|
||||
return _context.Usuarios.Any(e => e.Id == id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user