modificaciones en globalizar config
This commit is contained in:
@@ -19,36 +19,96 @@ public class MenuViewComponent : ViewComponent
|
||||
var userIdClaim = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);
|
||||
if (userIdClaim == null || !long.TryParse(userIdClaim.Value, out var userId))
|
||||
{
|
||||
return View(new List<foundation_system.Models.Permiso>());
|
||||
return View(new foundation_system.Models.ViewModels.MenuViewModel());
|
||||
}
|
||||
|
||||
var isRoot = HttpContext.User.IsInRole("ROOT");
|
||||
|
||||
List<foundation_system.Models.Permiso> menuItems;
|
||||
List<int> userPermisoIds;
|
||||
|
||||
if (isRoot)
|
||||
{
|
||||
menuItems = await _context.Permisos
|
||||
.Include(p => p.Modulo)
|
||||
.Where(p => p.EsMenu)
|
||||
.OrderBy(p => p.Modulo!.Orden)
|
||||
.ThenBy(p => p.Orden)
|
||||
.ToListAsync();
|
||||
userPermisoIds = await _context.Permisos.Select(p => p.Id).ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItems = await _context.RolesUsuario
|
||||
userPermisoIds = await _context.RolesUsuario
|
||||
.Where(ru => ru.UsuarioId == userId)
|
||||
.Join(_context.RolesPermisos, ru => ru.RolId, rp => rp.RolId, (ru, rp) => rp)
|
||||
.Join(_context.Permisos, rp => rp.PermisoId, p => p.Id, (rp, p) => p)
|
||||
.Include(p => p.Modulo)
|
||||
.Where(p => p.EsMenu)
|
||||
.OrderBy(p => p.Modulo!.Orden)
|
||||
.ThenBy(p => p.Orden)
|
||||
.Join(_context.RolesPermisos, ru => ru.RolId, rp => rp.RolId, (ru, rp) => rp.PermisoId)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
return View(menuItems);
|
||||
// Fetch all active modules and permissions
|
||||
var allModules = await _context.Modulos
|
||||
.Include(m => m.Permisos)
|
||||
.Where(m => m.Activo)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
|
||||
var menuViewModel = new foundation_system.Models.ViewModels.MenuViewModel();
|
||||
|
||||
// Build the tree starting from root modules (ParentId == null)
|
||||
var rootModules = allModules.Where(m => m.ParentId == null).OrderBy(m => m.Orden);
|
||||
|
||||
foreach (var module in rootModules)
|
||||
{
|
||||
var menuItem = BuildModuleMenuItem(module, allModules, userPermisoIds);
|
||||
if (menuItem != null)
|
||||
{
|
||||
menuViewModel.Items.Add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
return View(menuViewModel);
|
||||
}
|
||||
|
||||
private foundation_system.Models.ViewModels.MenuItem? BuildModuleMenuItem(
|
||||
foundation_system.Models.Modulo module,
|
||||
List<foundation_system.Models.Modulo> allModules,
|
||||
List<int> userPermisoIds)
|
||||
{
|
||||
var item = new foundation_system.Models.ViewModels.MenuItem
|
||||
{
|
||||
Title = module.Nombre,
|
||||
Icon = module.Icono,
|
||||
IsGroup = true,
|
||||
Order = module.Orden
|
||||
};
|
||||
|
||||
// 1. Add Submodules
|
||||
var subModules = allModules.Where(m => m.ParentId == module.Id).OrderBy(m => m.Orden);
|
||||
foreach (var sub in subModules)
|
||||
{
|
||||
var subItem = BuildModuleMenuItem(sub, allModules, userPermisoIds);
|
||||
if (subItem != null)
|
||||
{
|
||||
item.Children.Add(subItem);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Add Direct Permissions (Menu Items)
|
||||
var permissions = module.Permisos
|
||||
.Where(p => p.EsMenu && userPermisoIds.Contains(p.Id))
|
||||
.OrderBy(p => p.Orden);
|
||||
|
||||
foreach (var p in permissions)
|
||||
{
|
||||
item.Children.Add(new foundation_system.Models.ViewModels.MenuItem
|
||||
{
|
||||
Title = p.Nombre,
|
||||
Icon = p.Icono,
|
||||
Url = p.Url,
|
||||
IsGroup = false,
|
||||
Order = p.Orden
|
||||
});
|
||||
}
|
||||
|
||||
// Only return the item if it has children (permissions or submodules with permissions)
|
||||
if (item.Children.Any())
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Diagnostics;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using foundation_system.Data;
|
||||
using foundation_system.Models;
|
||||
using foundation_system.Models.ViewModels;
|
||||
using foundation_system.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace foundation_system.Controllers;
|
||||
@@ -11,24 +12,24 @@ namespace foundation_system.Controllers;
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly IDashboardService _dashboardService;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
|
||||
public HomeController(ILogger<HomeController> logger, IDashboardService dashboardService)
|
||||
{
|
||||
_logger = logger;
|
||||
_context = context;
|
||||
_dashboardService = dashboardService;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var totalNinos = await _context.Ninos.CountAsync(n => n.Activo);
|
||||
var asistenciasHoy = await _context.Asistencias
|
||||
.CountAsync(a => a.Fecha == DateOnly.FromDateTime(DateTime.Now) && a.Estado == "PRESENTE");
|
||||
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier);
|
||||
if (userIdClaim == null || !long.TryParse(userIdClaim.Value, out var userId))
|
||||
{
|
||||
return View(new DashboardViewModel());
|
||||
}
|
||||
|
||||
ViewBag.TotalNinos = totalNinos;
|
||||
ViewBag.AsistenciasHoy = asistenciasHoy;
|
||||
|
||||
return View();
|
||||
var vm = await _dashboardService.GetDashboardDataAsync(userId);
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
|
||||
@@ -19,19 +19,27 @@ public class ModuloController : Controller
|
||||
// GET: Modulo
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
return View(await _context.Modulos.OrderBy(m => m.Orden).ToListAsync());
|
||||
var modulos = await _context.Modulos
|
||||
.Include(m => m.Parent)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulos);
|
||||
}
|
||||
|
||||
// GET: Modulo/Create
|
||||
public IActionResult 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")] Modulo modulo)
|
||||
public async Task<IActionResult> Create([Bind("Nombre,Icono,Orden,Activo,ParentId")] Modulo modulo)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
@@ -40,6 +48,10 @@ public class ModuloController : Controller
|
||||
await _context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulo);
|
||||
}
|
||||
|
||||
@@ -50,13 +62,19 @@ public class ModuloController : Controller
|
||||
|
||||
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")] Modulo modulo)
|
||||
public async Task<IActionResult> Edit(int id, [Bind("Id,Nombre,Icono,Orden,Activo,ParentId")] Modulo modulo)
|
||||
{
|
||||
if (id != modulo.Id) return NotFound();
|
||||
|
||||
@@ -74,6 +92,10 @@ public class ModuloController : Controller
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
ViewBag.ModulosPadre = await _context.Modulos
|
||||
.Where(m => m.Activo && m.Id != id)
|
||||
.OrderBy(m => m.Orden)
|
||||
.ToListAsync();
|
||||
return View(modulo);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using foundation_system.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@@ -1,33 +1,72 @@
|
||||
-- =============================================
|
||||
-- Author: System
|
||||
-- Create date: 2025-12-31
|
||||
-- Description: Adds permissions for new financial reports.
|
||||
-- Description: Adds permissions for new financial reports with hierarchy.
|
||||
-- =============================================
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
v_modulo_id INT;
|
||||
v_reportes_id INT;
|
||||
v_financieros_id INT;
|
||||
BEGIN
|
||||
SELECT id INTO v_modulo_id FROM modulos WHERE nombre = 'Reportes';
|
||||
-- 1. Ensure Root Module 'Reportes' exists
|
||||
SELECT id INTO v_reportes_id FROM modulos WHERE nombre = 'Reportes';
|
||||
|
||||
-- 1. Movimientos
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
SELECT v_modulo_id, 'reportes.movimientos', 'Movimientos de Caja', 'Detalle de ingresos y egresos', '/Reportes/Movimientos', 'bi bi-list-check', 2, true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.movimientos');
|
||||
IF v_reportes_id IS NULL THEN
|
||||
INSERT INTO modulos (nombre, icono, orden, activo)
|
||||
VALUES ('Reportes', 'bi bi-file-earmark-text', 90, true)
|
||||
RETURNING id INTO v_reportes_id;
|
||||
END IF;
|
||||
|
||||
-- 2. Histórico de Saldos
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
SELECT v_modulo_id, 'reportes.saldos', 'Histórico de Saldos', 'Evolución diaria del saldo', '/Reportes/HistoricoSaldos', 'bi bi-graph-up', 3, true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.saldos');
|
||||
-- 2. Create Sub-Module 'Reportes Financieros'
|
||||
SELECT id INTO v_financieros_id FROM modulos WHERE nombre = 'Reportes Financieros' AND parent_id = v_reportes_id;
|
||||
|
||||
-- 3. Gastos por Categoría
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
SELECT v_modulo_id, 'reportes.gastos', 'Gastos por Categoría', 'Análisis de gastos', '/Reportes/GastosCategoria', 'bi bi-pie-chart', 4, true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.gastos');
|
||||
IF v_financieros_id IS NULL THEN
|
||||
INSERT INTO modulos (nombre, icono, orden, activo, parent_id)
|
||||
VALUES ('Reportes Financieros', 'bi bi-cash-coin', 1, true, v_reportes_id)
|
||||
RETURNING id INTO v_financieros_id;
|
||||
END IF;
|
||||
|
||||
-- 4. Reposiciones
|
||||
-- 3. Add Permissions (Menu Items) linked to 'Reportes Financieros'
|
||||
|
||||
-- Arqueo de Caja (Move if exists or insert)
|
||||
IF EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.arqueo') THEN
|
||||
UPDATE permisos SET modulo_id = v_financieros_id WHERE codigo = 'reportes.arqueo';
|
||||
ELSE
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
SELECT v_modulo_id, 'reportes.reposiciones', 'Reposiciones', 'Reporte de reintegros', '/Reportes/Reposiciones', 'bi bi-cash-stack', 5, true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.reposiciones');
|
||||
VALUES (v_financieros_id, 'reportes.arqueo', 'Arqueo de Caja', 'Cierre diario de caja', '/Reportes/ArqueoCaja', 'bi bi-calculator', 1, true);
|
||||
END IF;
|
||||
|
||||
-- Movimientos
|
||||
IF EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.movimientos') THEN
|
||||
UPDATE permisos SET modulo_id = v_financieros_id WHERE codigo = 'reportes.movimientos';
|
||||
ELSE
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
VALUES (v_financieros_id, 'reportes.movimientos', 'Movimientos de Caja', 'Detalle de ingresos y egresos', '/Reportes/Movimientos', 'bi bi-list-check', 2, true);
|
||||
END IF;
|
||||
|
||||
-- Histórico de Saldos
|
||||
IF EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.saldos') THEN
|
||||
UPDATE permisos SET modulo_id = v_financieros_id WHERE codigo = 'reportes.saldos';
|
||||
ELSE
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
VALUES (v_financieros_id, 'reportes.saldos', 'Histórico de Saldos', 'Evolución diaria del saldo', '/Reportes/HistoricoSaldos', 'bi bi-graph-up', 3, true);
|
||||
END IF;
|
||||
|
||||
-- Gastos por Categoría
|
||||
IF EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.gastos') THEN
|
||||
UPDATE permisos SET modulo_id = v_financieros_id WHERE codigo = 'reportes.gastos';
|
||||
ELSE
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
VALUES (v_financieros_id, 'reportes.gastos', 'Gastos por Categoría', 'Análisis de gastos', '/Reportes/GastosCategoria', 'bi bi-pie-chart', 4, true);
|
||||
END IF;
|
||||
|
||||
-- Reposiciones
|
||||
IF EXISTS (SELECT 1 FROM permisos WHERE codigo = 'reportes.reposiciones') THEN
|
||||
UPDATE permisos SET modulo_id = v_financieros_id WHERE codigo = 'reportes.reposiciones';
|
||||
ELSE
|
||||
INSERT INTO permisos (modulo_id, codigo, nombre, descripcion, url, icono, orden, es_menu)
|
||||
VALUES (v_financieros_id, 'reportes.reposiciones', 'Reposiciones', 'Reporte de reintegros', '/Reportes/Reposiciones', 'bi bi-cash-stack', 5, true);
|
||||
END IF;
|
||||
|
||||
END $$;
|
||||
|
||||
@@ -28,6 +28,14 @@ public class Modulo
|
||||
[Column("creado_en")]
|
||||
public DateTime CreadoEn { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// Navigation property
|
||||
[Column("parent_id")]
|
||||
public int? ParentId { get; set; }
|
||||
|
||||
// Navigation properties
|
||||
[ForeignKey("ParentId")]
|
||||
public virtual Modulo? Parent { get; set; }
|
||||
|
||||
public virtual ICollection<Modulo> SubModulos { get; set; } = new List<Modulo>();
|
||||
|
||||
public virtual ICollection<Permiso> Permisos { get; set; } = new List<Permiso>();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
||||
builder.Services.AddScoped<IAuthService, AuthService>();
|
||||
builder.Services.AddScoped<IAntecedentesService, AntecedentesService>();
|
||||
builder.Services.AddScoped<IReporteService, ReporteService>();
|
||||
builder.Services.AddScoped<IDashboardService, DashboardService>();
|
||||
builder.Services.AddScoped<IConfiguracionService, ConfiguracionService>();
|
||||
|
||||
// Configure cookie authentication
|
||||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
@model foundation_system.Models.ViewModels.LoginViewModel
|
||||
@inject foundation_system.Services.IConfiguracionService ConfigService
|
||||
@{
|
||||
ViewData["Title"] = "Iniciar Sesión";
|
||||
Layout = null;
|
||||
var logoUrl = await ConfigService.GetValorOrDefaultAsync("LOGO_FUNDATION", "/img/logo-placeholder.png");
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
@@ -24,13 +26,7 @@
|
||||
<div class="auth-card animate-fade-in">
|
||||
<div class="auth-header">
|
||||
<div class="auth-logo">
|
||||
<div class="logo-icon">
|
||||
<svg viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="50" cy="50" r="45" stroke="currentColor" stroke-width="4"/>
|
||||
<path d="M30 55 L50 35 L70 55" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M40 65 L50 55 L60 65" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<img src="@logoUrl" alt="Logo" class="img-fluid mb-3" style="max-height: 80px; width: auto; object-fit: contain;" />
|
||||
</div>
|
||||
<h1 class="auth-title">MIES</h1>
|
||||
<p class="auth-subtitle">Misión Esperanza</p>
|
||||
|
||||
@@ -1,8 +1,32 @@
|
||||
@{
|
||||
@model foundation_system.Models.ViewModels.DashboardViewModel
|
||||
@inject foundation_system.Services.IConfiguracionService ConfigService
|
||||
@{
|
||||
ViewData["Title"] = "Dashboard";
|
||||
var nameFoundation = await ConfigService.GetValorOrDefaultAsync("NAME_FOUNDATION", "foundation_system");
|
||||
var description = await ConfigService.GetValorOrDefaultAsync("DESCRIPTION_FOUNDATION", "");
|
||||
}
|
||||
|
||||
|
||||
<div class="card-custom mt-4">
|
||||
<h4>Bienvenido al Sistema @nameFoundation</h4>
|
||||
|
||||
<p class="mb-2">
|
||||
Este sistema ha sido diseñado para apoyar la gestión de la fundación,
|
||||
permitiendo administrar de forma segura los expedientes de los niños,
|
||||
el control de asistencia diaria, entre otros.
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<p class="text-muted mb-0">
|
||||
@description;
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
@* Expediente Stats - Only visible if user has permission *@
|
||||
@if (Model.TienePermisoExpediente)
|
||||
{
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-primary">
|
||||
<div class="d-flex align-items-center">
|
||||
@@ -10,12 +34,43 @@
|
||||
<i class="bi bi-people-fill text-primary fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Total Niños</h6>
|
||||
<h3 class="mb-0">@ViewBag.TotalNinos</h3>
|
||||
<h6 class="text-muted small mb-1">Niños Activos</h6>
|
||||
<h3 class="mb-0">@Model.TotalNinosActivos</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-warning">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0 bg-warning bg-opacity-10 p-3 rounded">
|
||||
<i class="bi bi-cake-fill text-warning fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Cumpleañeros del Mes</h6>
|
||||
<h3 class="mb-0">@Model.CumpleanerosMes</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-danger">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0 bg-danger bg-opacity-10 p-3 rounded">
|
||||
<i class="bi bi-exclamation-triangle-fill text-danger fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Mayores de 14 años</h6>
|
||||
<h3 class="mb-0">@Model.NinosMayores14</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@* Attendance Stats - Only visible if user has permission *@
|
||||
@if (Model.TienePermisoAsistencia)
|
||||
{
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-success">
|
||||
<div class="d-flex align-items-center">
|
||||
@@ -23,28 +78,77 @@
|
||||
<i class="bi bi-calendar-check-fill text-success fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Asistencias Hoy</h6>
|
||||
<h3 class="mb-0">@ViewBag.AsistenciasHoy</h3>
|
||||
<h6 class="text-muted small mb-1">Asistencia Hoy</h6>
|
||||
<h3 class="mb-0">@Model.AsistenciasHoy <small class="text-muted fs-6">/ @Model.TotalNinosParaAsistencia</small></h3>
|
||||
<small class="text-success">@Model.PorcentajeAsistenciaHoy%</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@* Petty Cash Stats - Only visible if user has permission *@
|
||||
@if (Model.TienePermisoCajaChica)
|
||||
{
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-info">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0 bg-info bg-opacity-10 p-3 rounded">
|
||||
<i class="bi bi-wallet2 text-info fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Saldo Caja Chica</h6>
|
||||
<h3 class="mb-0">C$ @Model.SaldoCajaChica.ToString("N2")</h3>
|
||||
@if (!string.IsNullOrEmpty(Model.NombreCajaActiva))
|
||||
{
|
||||
<small class="text-muted">@Model.NombreCajaActiva</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom border-start border-4 border-info">
|
||||
<div class="card-custom border-start border-4 border-secondary">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0 bg-info bg-opacity-10 p-3 rounded">
|
||||
<i class="bi bi-folder-fill text-info fs-3"></i>
|
||||
<div class="flex-shrink-0 bg-secondary bg-opacity-10 p-3 rounded">
|
||||
<i class="bi bi-arrow-down-circle-fill text-secondary fs-3"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
<h6 class="text-muted small mb-1">Expedientes Activos</h6>
|
||||
<h3 class="mb-0">@ViewBag.TotalNinos</h3>
|
||||
<h6 class="text-muted small mb-1">Gastos del Mes</h6>
|
||||
<h3 class="mb-0">C$ @Model.GastosMes.ToString("N2")</h3>
|
||||
<small class="text-muted">@Model.MovimientosMes movimientos</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@* Birthday List - Only visible if user has permission and there are birthdays *@
|
||||
@if (Model.TienePermisoExpediente && Model.ListaCumpleaneros.Any())
|
||||
{
|
||||
<div class="card-custom mt-4">
|
||||
<h4>Bienvenido al Sistema MIES</h4>
|
||||
<p class="text-muted">Utilice el menú lateral para gestionar los expedientes de los niños y el control de asistencia diaria.</p>
|
||||
<h5 class="mb-3"><i class="bi bi-cake2 me-2"></i>Cumpleañeros de @DateTime.Now.ToString("MMMM")</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Día</th>
|
||||
<th>Nombre</th>
|
||||
<th>Cumple</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var cumple in Model.ListaCumpleaneros)
|
||||
{
|
||||
<tr>
|
||||
<td><span class="badge bg-warning text-dark">@cumple.DiaCumple</span></td>
|
||||
<td>@cumple.NombreCompleto</td>
|
||||
<td>@cumple.Edad años</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -19,13 +19,24 @@
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label asp-for="Nombre" class="form-label">Nombre del Módulo</label>
|
||||
<input asp-for="Nombre" class="form-control" placeholder="Ej. Administración, Reportes..." />
|
||||
<span asp-validation-for="Nombre" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label asp-for="Orden" class="form-label">Orden de Visualización</label>
|
||||
<label asp-for="ParentId" class="form-label">Módulo Padre (Opcional)</label>
|
||||
<select asp-for="ParentId" class="form-select">
|
||||
<option value="">-- Ninguno (Módulo Raíz) --</option>
|
||||
@foreach (var modulo in (IEnumerable<foundation_system.Models.Modulo>)ViewBag.ModulosPadre)
|
||||
{
|
||||
<option value="@modulo.Id">@modulo.Nombre</option>
|
||||
}
|
||||
</select>
|
||||
<small class="text-muted">Si se selecciona, este será un sub-módulo</small>
|
||||
</div>
|
||||
<div class="col-md-2 mb-3">
|
||||
<label asp-for="Orden" class="form-label">Orden</label>
|
||||
<input asp-for="Orden" class="form-control" type="number" />
|
||||
<span asp-validation-for="Orden" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
@@ -21,13 +21,24 @@
|
||||
<input type="hidden" asp-for="CreadoEn" />
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label asp-for="Nombre" class="form-label">Nombre del Módulo</label>
|
||||
<input asp-for="Nombre" class="form-control" />
|
||||
<span asp-validation-for="Nombre" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label asp-for="Orden" class="form-label">Orden de Visualización</label>
|
||||
<label asp-for="ParentId" class="form-label">Módulo Padre (Opcional)</label>
|
||||
<select asp-for="ParentId" class="form-select">
|
||||
<option value="">-- Ninguno (Módulo Raíz) --</option>
|
||||
@foreach (var modulo in (IEnumerable<foundation_system.Models.Modulo>)ViewBag.ModulosPadre)
|
||||
{
|
||||
<option value="@modulo.Id">@modulo.Nombre</option>
|
||||
}
|
||||
</select>
|
||||
<small class="text-muted">Si se selecciona, este será un sub-módulo</small>
|
||||
</div>
|
||||
<div class="col-md-2 mb-3">
|
||||
<label asp-for="Orden" class="form-label">Orden</label>
|
||||
<input asp-for="Orden" class="form-control" type="number" />
|
||||
<span asp-validation-for="Orden" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
@model IEnumerable<foundation_system.Models.Permiso>
|
||||
@model foundation_system.Models.ViewModels.MenuViewModel
|
||||
|
||||
@{
|
||||
var currentController = ViewContext.RouteData.Values["controller"]?.ToString();
|
||||
var currentAction = ViewContext.RouteData.Values["action"]?.ToString();
|
||||
var currentUrl = $"/{currentController}/{currentAction}";
|
||||
ViewData["CurrentUrl"] = currentUrl;
|
||||
}
|
||||
|
||||
<nav class="nav flex-column">
|
||||
<a class="nav-link-custom @(ViewContext.RouteData.Values["controller"]?.ToString() == "Home" ? "active" : "")" asp-controller="Home" asp-action="Index">
|
||||
<a class="nav-link-custom @(currentController == "Home" ? "active" : "")" asp-controller="Home" asp-action="Index">
|
||||
<i class="bi bi-house-door"></i> Inicio
|
||||
</a>
|
||||
|
||||
@{
|
||||
var groupedMenu = Model.GroupBy(m => m.Modulo);
|
||||
var currentController = ViewContext.RouteData.Values["controller"]?.ToString();
|
||||
}
|
||||
|
||||
@foreach (var group in groupedMenu)
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<div class="nav-section-title mt-3">
|
||||
@if (!string.IsNullOrEmpty(group.Key?.Icono))
|
||||
{
|
||||
<i class="bi @group.Key.Icono me-1"></i>
|
||||
}
|
||||
@(group.Key?.Nombre ?? "Sin Módulo")
|
||||
</div>
|
||||
@foreach (var item in group)
|
||||
{
|
||||
<a class="nav-link-custom @(currentController == item.Codigo ? "active" : "")" href="@item.Url">
|
||||
<i class="bi @item.Icono"></i> @item.Nombre
|
||||
</a>
|
||||
}
|
||||
<partial name="Components/Menu/_MenuItem" model="item" view-data="ViewData" />
|
||||
}
|
||||
</nav>
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
@inject foundation_system.Services.IConfiguracionService ConfigService
|
||||
@{
|
||||
var logoUrl = await ConfigService.GetValorOrDefaultAsync("LOGO_FOUNDATION", "/assets/home.png");
|
||||
var nameShort = await ConfigService.GetValorOrDefaultAsync("NAME_FOUNDATION_SHORT", "foundation_system");
|
||||
var nameFoundation = await ConfigService.GetValorOrDefaultAsync("NAME_FOUNDATION", "foundation_system");
|
||||
var descriptionShort = await ConfigService.GetValorOrDefaultAsync("DESCRIPTION_SHORT", "Fundacion sin fines de lucro");
|
||||
var version = await ConfigService.GetValorOrDefaultAsync("VERSION_SYSTEM", "1.0.0");
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>@ViewData["Title"] - MIES</title>
|
||||
<title>@ViewData["Title"] - @nameShort</title>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="~/css/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="~/css/all.min.css">
|
||||
@@ -20,15 +28,16 @@
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<a class="sidebar-brand" asp-controller="Home" asp-action="Index">
|
||||
<i class="bi bi-house-heart-fill me-2"></i>MIES
|
||||
<a class="sidebar-brand d-flex align-items-center" asp-controller="Home" asp-action="Index">
|
||||
<img src="@logoUrl" alt="Logo" class="me-2" style="height: 32px; width: auto; object-fit: contain;" />
|
||||
<span>@nameShort</span>
|
||||
</a>
|
||||
</div>
|
||||
<nav class="sidebar-nav p-3">
|
||||
@await Component.InvokeAsync("Menu")
|
||||
</nav>
|
||||
<div class="sidebar-footer p-3 border-top border-secondary">
|
||||
<small class="text-muted">v1.0.0 © 2025</small>
|
||||
<small class="text-muted">v @version © 2026</small>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -53,7 +62,7 @@
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted small">Misión Esperanza © 2025 - Fundación para el desarrollo infantil.</span>
|
||||
<span class="text-muted small">@nameFoundation © 2026 - @descriptionShort.</span>
|
||||
<div class="small text-muted">
|
||||
<i class="bi bi-shield-check me-1"></i> Sistema Seguro
|
||||
</div>
|
||||
|
||||
BIN
foundation_system/wwwroot/Assets/home.png
Normal file
BIN
foundation_system/wwwroot/Assets/home.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
foundation_system/wwwroot/Assets/logo.png
Normal file
BIN
foundation_system/wwwroot/Assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 642 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 160 KiB |
Reference in New Issue
Block a user