cinu
This commit is contained in:
49
RS_system/Views/Diezmo/Create.cshtml
Normal file
49
RS_system/Views/Diezmo/Create.cshtml
Normal file
@@ -0,0 +1,49 @@
|
||||
@model Rs_system.Models.ViewModels.DiezmoCierreCreateViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Nuevo Cierre de Diezmos";
|
||||
}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h4 class="mb-1"><i class="bi bi-plus-circle me-2"></i>Nuevo Cierre de Diezmos</h4>
|
||||
<p class="text-muted mb-0">Registra un nuevo período de diezmos</p>
|
||||
</div>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-arrow-left me-1"></i> Volver
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card-custom">
|
||||
<form asp-action="Create" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
|
||||
<div asp-validation-summary="ModelOnly" class="alert alert-danger mb-3" style="display:none;"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Fecha" class="form-label"></label>
|
||||
<input asp-for="Fecha" type="date" class="form-control" />
|
||||
<span asp-validation-for="Fecha" class="text-danger small"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label asp-for="Observaciones" class="form-label"></label>
|
||||
<textarea asp-for="Observaciones" class="form-control" rows="3"
|
||||
placeholder="Opcional — notas o descripción del cierre"></textarea>
|
||||
<span asp-validation-for="Observaciones" class="text-danger small"></span>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary-custom">
|
||||
<i class="bi bi-check-lg me-1"></i> Crear Cierre
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
465
RS_system/Views/Diezmo/Detail.cshtml
Normal file
465
RS_system/Views/Diezmo/Detail.cshtml
Normal file
@@ -0,0 +1,465 @@
|
||||
@model Rs_system.Models.ViewModels.DiezmoCierreDetalleViewModel
|
||||
@{
|
||||
ViewData["Title"] = $"Cierre {Model.Fecha:dd/MM/yyyy}";
|
||||
var cerrado = Model.Cerrado;
|
||||
}
|
||||
|
||||
<!-- Cabecera -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-2">
|
||||
<div>
|
||||
<h4 class="mb-1">
|
||||
<i class="bi bi-cash-coin me-2"></i>Cierre de Diezmos — @Model.Fecha.ToString("dd/MM/yyyy")
|
||||
<span class="@Model.EstadoBadge ms-2">@Model.EstadoTexto</span>
|
||||
</h4>
|
||||
@if (!string.IsNullOrEmpty(Model.Observaciones))
|
||||
{
|
||||
<p class="text-muted mb-0">@Model.Observaciones</p>
|
||||
}
|
||||
@if (cerrado && Model.FechaCierre.HasValue)
|
||||
{
|
||||
<small class="text-muted">Cerrado por <strong>@Model.CerradoPor</strong> el @Model.FechaCierre.Value.ToLocalTime().ToString("dd/MM/yyyy HH:mm")</small>
|
||||
}
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<a asp-action="Index" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-left me-1"></i>Volver
|
||||
</a>
|
||||
@if (!cerrado)
|
||||
{
|
||||
<button type="button" class="btn btn-success btn-sm" onclick="confirmClose(@Model.Id)">
|
||||
<i class="bi bi-lock me-1"></i>Cerrar cierre
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-outline-warning btn-sm" onclick="confirmReopen(@Model.Id)">
|
||||
<i class="bi bi-unlock me-1"></i>Reabrir
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (TempData["SuccessMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-check-circle me-1"></i> @TempData["SuccessMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
}
|
||||
@if (TempData["ErrorMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-exclamation-triangle me-1"></i> @TempData["ErrorMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (cerrado)
|
||||
{
|
||||
<div class="alert alert-secondary d-flex align-items-center mb-4">
|
||||
<i class="bi bi-lock-fill me-2 fs-5"></i>
|
||||
<strong>Este cierre está sellado.</strong> No se puede modificar. Para editarlo, un Administrador debe reabrirlo.
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- BLOQUE 1 — Resumen de totales -->
|
||||
<div class="row mb-4 g-3">
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="card-custom text-center py-3">
|
||||
<h6 class="text-muted small mb-1">Recibido</h6>
|
||||
<h5 class="mb-0" id="uiTotalRecibido">$ @Model.TotalRecibido.ToString("N2")</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="card-custom text-center py-3">
|
||||
<h6 class="text-muted small mb-1">Cambio</h6>
|
||||
<h5 class="text-warning mb-0" id="uiTotalCambio">$ @Model.TotalCambio.ToString("N2")</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="card-custom text-center py-3">
|
||||
<h6 class="text-muted small mb-1">Neto</h6>
|
||||
<h5 class="text-primary mb-0" id="uiTotalNeto">$ @Model.TotalNeto.ToString("N2")</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="card-custom text-center py-3">
|
||||
<h6 class="text-muted small mb-1">Salidas</h6>
|
||||
<h5 class="text-danger mb-0" id="uiTotalSalidas">$ @Model.TotalSalidas.ToString("N2")</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<div id="wrapperSaldoFinal" class="card-custom text-center py-3 border border-2 @(Model.SaldoFinal >= 0 ? "border-success" : "border-danger")">
|
||||
<h6 class="text-muted small mb-1">Saldo Final</h6>
|
||||
<h4 id="uiSaldoFinal" class="@(Model.SaldoFinal >= 0 ? "text-success" : "text-danger") mb-0 fw-bold">
|
||||
$ @Model.SaldoFinal.ToString("N2")
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BLOQUE 2 — Diezmos por miembro -->
|
||||
<div class="card-custom mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0"><i class="bi bi-people me-2"></i>Diezmos por Miembro (@Model.Detalles.Count)</h6>
|
||||
@if (!cerrado)
|
||||
{
|
||||
<button type="button" class="btn btn-primary-custom btn-sm" data-bs-toggle="modal" data-bs-target="#modalAddDetalle">
|
||||
<i class="bi bi-plus-lg me-1"></i>Agregar Diezmo
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table-custom">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">#</th>
|
||||
<th>Miembro</th>
|
||||
<th class="text-end">Entregado</th>
|
||||
<th class="text-end">Cambio</th>
|
||||
<th class="text-end">Neto</th>
|
||||
<th>Notas</th>
|
||||
<th class="text-center">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (!Model.Detalles.Any())
|
||||
{
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-muted py-4">
|
||||
<i class="bi bi-inbox fs-2 d-block mb-1"></i>Sin diezmos registrados
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@{ var i = 1; }
|
||||
@foreach (var d in Model.Detalles)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-muted">@i</td>
|
||||
<td><strong>@d.NombreMiembro</strong></td>
|
||||
<td class="text-end">$ @d.MontoEntregado.ToString("N2")</td>
|
||||
<td class="text-end text-warning">$ @d.CambioEntregado.ToString("N2")</td>
|
||||
<td class="text-end text-primary fw-bold">$ @d.MontoNeto.ToString("N2")</td>
|
||||
<td><small class="text-muted">@d.Observaciones</small></td>
|
||||
<td class="text-center">
|
||||
@if (!cerrado)
|
||||
{
|
||||
<form asp-action="DeleteDetalle" method="post" class="d-inline formDelete" data-confirm-msg="¿Eliminar este diezmo?">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="detalleId" value="@d.Id" />
|
||||
<input type="hidden" name="cierreId" value="@Model.Id" />
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger" title="Eliminar">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
i++;
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BLOQUE 3 — Salidas / Entregas -->
|
||||
<div class="card-custom mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0"><i class="bi bi-box-arrow-up me-2"></i>Salidas y Entregas (@Model.Salidas.Count)</h6>
|
||||
@if (!cerrado)
|
||||
{
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" data-bs-toggle="modal" data-bs-target="#modalAddSalida">
|
||||
<i class="bi bi-plus-lg me-1"></i>Registrar Salida
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table-custom">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tipo</th>
|
||||
<th>Beneficiario</th>
|
||||
<th>Concepto</th>
|
||||
<th class="text-end">Monto</th>
|
||||
<th>Recibo</th>
|
||||
<th class="text-center">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (!Model.Salidas.Any())
|
||||
{
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted py-4">
|
||||
<i class="bi bi-inbox fs-2 d-block mb-1"></i>Sin salidas registradas
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (var s in Model.Salidas)
|
||||
{
|
||||
<tr>
|
||||
<td><span class="badge bg-secondary">@s.TipoSalidaNombre</span></td>
|
||||
<td>@(s.BeneficiarioNombre ?? "—")</td>
|
||||
<td>@s.Concepto</td>
|
||||
<td class="text-end text-danger fw-bold">$ @s.Monto.ToString("N2")</td>
|
||||
<td>
|
||||
@if (!string.IsNullOrEmpty(s.NumeroRecibo))
|
||||
{
|
||||
<a asp-action="Recibo" asp-route-salidaId="@s.Id" target="_blank"
|
||||
class="badge bg-success text-decoration-none">
|
||||
<i class="bi bi-receipt me-1"></i>@s.NumeroRecibo
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-action="Recibo" asp-route-salidaId="@s.Id" target="_blank"
|
||||
class="btn btn-sm btn-outline-secondary btn-sm py-0">
|
||||
<i class="bi bi-receipt me-1"></i>Generar
|
||||
</a>
|
||||
}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if (!cerrado)
|
||||
{
|
||||
<form asp-action="DeleteSalida" method="post" class="d-inline formDelete" data-confirm-msg="¿Eliminar esta salida?">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="salidaId" value="@s.Id" />
|
||||
<input type="hidden" name="cierreId" value="@Model.Id" />
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger" title="Eliminar">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MODAL — Agregar Diezmo por Miembro
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
@if (!cerrado)
|
||||
{
|
||||
<div class="modal fade" id="modalAddDetalle" tabindex="-1" aria-labelledby="modalAddDetalleLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalAddDetalleLabel">
|
||||
<i class="bi bi-person-plus me-2"></i>Registrar Diezmo
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form id="formAddDetalle" asp-action="AddDetalle" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="cierreId" value="@Model.Id" />
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Miembro <span class="text-danger">*</span></label>
|
||||
<select name="MiembroId" class="form-select select2-miembros" required style="width: 100%;">
|
||||
<option value="">— Seleccionar o Escribir —</option>
|
||||
@foreach (var m in Model.MiembrosSelect)
|
||||
{
|
||||
<option value="@m.Value">@m.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label">Monto entregado <span class="text-danger">*</span></label>
|
||||
<input name="MontoEntregado" type="number" step="0.01" min="0.01"
|
||||
class="form-control fw-bold text-success" id="montoEntregado" oninput="calcCambio()" required />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label">Diezmo (Neto) <span class="text-danger">*</span></label>
|
||||
<input name="MontoNeto" type="number" step="0.01" min="0.01"
|
||||
class="form-control fw-bold text-primary" id="montoNeto" oninput="calcCambio()" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 bg-light border p-2 rounded text-end">
|
||||
<small class="text-muted mb-0 d-block">Cambio a devolver:</small>
|
||||
<strong id="cambioDisplay" class="text-warning fs-5">$ 0.00</strong>
|
||||
<input type="hidden" name="CambioEntregado" id="cambioEntregado" value="0" />
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<label class="form-label">Observaciones</label>
|
||||
<input name="Observaciones" type="text" class="form-control"
|
||||
placeholder="Opcional" maxlength="300" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary-custom">
|
||||
<i class="bi bi-check-lg me-1"></i>Guardar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MODAL — Registrar Salida
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
<div class="modal fade" id="modalAddSalida" tabindex="-1" aria-labelledby="modalAddSalidaLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalAddSalidaLabel">
|
||||
<i class="bi bi-box-arrow-up me-2"></i>Registrar Salida
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form id="formAddSalida" asp-action="AddSalida" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="cierreId" value="@Model.Id" />
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Tipo de salida <span class="text-danger">*</span></label>
|
||||
<select name="TipoSalidaId" id="tipoSalidaSelect" class="form-select" required>
|
||||
<option value="">— Seleccionar —</option>
|
||||
@foreach (var t in Model.TiposSalidaSelect)
|
||||
{
|
||||
<option value="@t.Value">@t.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Beneficiario</label>
|
||||
<select name="BeneficiarioId" class="form-select">
|
||||
<option value="">— Sin beneficiario —</option>
|
||||
@foreach (var b in Model.BeneficiariosSelect)
|
||||
{
|
||||
<option value="@b.Value">@b.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Monto <span class="text-danger">*</span></label>
|
||||
<input name="Monto" type="number" step="0.01" min="0.01"
|
||||
class="form-control" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Concepto <span class="text-danger">*</span></label>
|
||||
<input name="Concepto" id="s_concepto" type="text" class="form-control"
|
||||
placeholder="Descripción de la salida" maxlength="300" required />
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info py-2 small mb-3 text-center">
|
||||
Total del Diezmo Recibido (Neto): <strong>$ @Model.TotalNeto.ToString("N2")</strong>
|
||||
</div>
|
||||
|
||||
@if (Model.SaldoFinal > 0)
|
||||
{
|
||||
<div class="alert alert-warning py-2 small mb-0">
|
||||
<i class="bi bi-exclamation-triangle me-1"></i>
|
||||
Saldo disponible: <strong>$ @Model.SaldoFinal.ToString("N2")</strong>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="bi bi-check-lg me-1"></i>Registrar Salida
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Formularios ocultos para cierre/reapertura -->
|
||||
<form id="formCerrar" asp-action="Close" method="post" style="display:none;">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="id" value="@Model.Id" />
|
||||
</form>
|
||||
<form id="formReabrir" asp-action="Reopen" method="post" style="display:none;">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="id" value="@Model.Id" />
|
||||
</form>
|
||||
|
||||
<!-- CSS para Select2 (asumimos que está en el layout o lo cargamos por CDN si no está) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" rel="stylesheet" />
|
||||
|
||||
@section Scripts {
|
||||
<!-- JS para Select2 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Inicializar Select2
|
||||
$('.select2-miembros').select2({
|
||||
theme: "bootstrap-5",
|
||||
dropdownParent: $('#modalAddDetalle'),
|
||||
placeholder: "Buscar por nombre, apellido o num...",
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
language: {
|
||||
noResults: function() { return "No se encontraron miembros"; },
|
||||
searching: function() { return "Buscando..."; }
|
||||
}
|
||||
});
|
||||
|
||||
// Lógica para auto-llenar el Concepto de la salida según el Tipo seleccionado
|
||||
$('#tipoSalidaSelect').on('change', function() {
|
||||
var selectedText = $(this).find("option:selected").text();
|
||||
var currentConcepto = $('#s_concepto').val();
|
||||
if (selectedText && selectedText !== '— Seleccionar —') {
|
||||
if (currentConcepto === '' || currentConcepto === '— Seleccionar —' || currentConcepto !== selectedText) {
|
||||
$('#s_concepto').val(selectedText);
|
||||
}
|
||||
} else {
|
||||
$('#s_concepto').val('');
|
||||
}
|
||||
});
|
||||
|
||||
// Lógica de validación Delete
|
||||
$('.formDelete').on('submit', function (e) {
|
||||
var msg = $(this).data('confirm-msg') || '¿Está seguro de eliminar este registro?';
|
||||
if (!confirm(msg)) e.preventDefault();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Calculo interactivo del cambio (Solo Lectura) en el formulario de Diezmo
|
||||
function calcCambio() {
|
||||
let entregado = parseFloat(document.getElementById('montoEntregado').value) || 0;
|
||||
let neto = parseFloat(document.getElementById('montoNeto').value) || 0;
|
||||
let cambio = entregado - neto;
|
||||
|
||||
if (cambio < 0) cambio = 0;
|
||||
|
||||
document.getElementById('cambioDisplay').textContent = '$ ' + cambio.toFixed(2);
|
||||
document.getElementById('cambioEntregado').value = cambio.toFixed(2);
|
||||
}
|
||||
|
||||
function confirmClose(id) {
|
||||
Swal.fire({
|
||||
title: '¿Cerrar este cierre?',
|
||||
text: 'Una vez cerrado, no se podrán agregar ni modificar diezmos ni salidas.',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#198754',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sí, cerrar',
|
||||
cancelButtonText: 'Cancelar'
|
||||
}).then(r => { if (r.isConfirmed) document.getElementById('formCerrar').submit(); });
|
||||
}
|
||||
|
||||
function confirmReopen(id) {
|
||||
Swal.fire({
|
||||
title: '¿Reabrir este cierre?',
|
||||
text: 'Esto permitirá nuevamente editar diezmos y salidas.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#ffc107',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Sí, reabrir',
|
||||
cancelButtonText: 'Cancelar'
|
||||
}).then(r => { if (r.isConfirmed) document.getElementById('formReabrir').submit(); });
|
||||
}
|
||||
</script>
|
||||
}
|
||||
138
RS_system/Views/Diezmo/Index.cshtml
Normal file
138
RS_system/Views/Diezmo/Index.cshtml
Normal file
@@ -0,0 +1,138 @@
|
||||
@model List<Rs_system.Models.ViewModels.DiezmoCierreListViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Registro de Diezmos";
|
||||
}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-2">
|
||||
<div>
|
||||
<h4 class="mb-1"><i class="bi bi-cash-coin me-2"></i>Registro de Diezmos</h4>
|
||||
<p class="text-muted mb-0">Gestión de cierres periódicos de diezmos</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" id="dropdownCatalogos" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-gear me-1"></i> Catálogos
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownCatalogos">
|
||||
<li><a class="dropdown-item" asp-controller="DiezmoCatalogo" asp-action="TiposSalida"><i class="bi bi-tags me-2 text-muted"></i>Tipos de Salida</a></li>
|
||||
<li><a class="dropdown-item" asp-controller="DiezmoCatalogo" asp-action="Beneficiarios"><i class="bi bi-people me-2 text-muted"></i>Beneficiarios</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a asp-action="Create" class="btn btn-primary-custom">
|
||||
<i class="bi bi-plus-lg me-1"></i> Nuevo Cierre
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (TempData["SuccessMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-check-circle me-1"></i> @TempData["SuccessMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
}
|
||||
@if (TempData["ErrorMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-exclamation-triangle me-1"></i> @TempData["ErrorMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Filtro por año -->
|
||||
<div class="card-custom mb-4">
|
||||
<form method="get" class="row g-3 align-items-end">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Año</label>
|
||||
<select name="anio" class="form-select" asp-items="@(ViewBag.Anios as List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>)">
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="bi bi-funnel me-1"></i> Filtrar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script>document.querySelector('select[name="anio"]').value = '@ViewBag.AnioActual';</script>
|
||||
|
||||
<!-- Tarjetas resumen del período -->
|
||||
@{
|
||||
var totalNeto = Model.Sum(c => c.TotalNeto);
|
||||
var totalSalidas = Model.Sum(c => c.TotalSalidas);
|
||||
var saldoTotal = Model.Sum(c => c.SaldoFinal);
|
||||
}
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom text-center">
|
||||
<h6 class="text-muted mb-2">Total Neto del Período</h6>
|
||||
<h3 class="text-primary mb-0">$ @totalNeto.ToString("N2")</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom text-center">
|
||||
<h6 class="text-muted mb-2">Total Salidas</h6>
|
||||
<h3 class="text-warning mb-0">$ @totalSalidas.ToString("N2")</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card-custom text-center">
|
||||
<h6 class="text-muted mb-2">Saldo Acumulado</h6>
|
||||
<h3 class="@(saldoTotal >= 0 ? "text-success" : "text-danger") mb-0">$ @saldoTotal.ToString("N2")</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabla de cierres -->
|
||||
<div class="card-custom">
|
||||
<div class="table-responsive">
|
||||
<table class="table-custom">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Fecha</th>
|
||||
<th class="text-center">Estado</th>
|
||||
<th class="text-end">Total Recibido</th>
|
||||
<th class="text-end">Total Neto</th>
|
||||
<th class="text-end">Salidas</th>
|
||||
<th class="text-end">Saldo Final</th>
|
||||
<th class="text-center">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (!Model.Any())
|
||||
{
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-muted py-5">
|
||||
<i class="bi bi-inbox fs-1 d-block mb-2"></i>
|
||||
No hay cierres registrados para el año seleccionado
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (var cierre in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<strong>@cierre.Fecha.ToString("dd/MM/yyyy")</strong>
|
||||
<br><small class="text-muted">@cierre.Fecha.DayOfWeek</small>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="@cierre.EstadoBadge">@cierre.EstadoTexto</span>
|
||||
</td>
|
||||
<td class="text-end">$ @cierre.TotalRecibido.ToString("N2")</td>
|
||||
<td class="text-end">$ @cierre.TotalNeto.ToString("N2")</td>
|
||||
<td class="text-end text-warning">$ @cierre.TotalSalidas.ToString("N2")</td>
|
||||
<td class="text-end @(cierre.SaldoFinal >= 0 ? "text-success" : "text-danger") fw-bold">
|
||||
$ @cierre.SaldoFinal.ToString("N2")
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a asp-action="Detail" asp-route-id="@cierre.Id"
|
||||
class="btn btn-sm btn-outline-primary" title="Ver detalle">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
99
RS_system/Views/Diezmo/Recibo.cshtml
Normal file
99
RS_system/Views/Diezmo/Recibo.cshtml
Normal file
@@ -0,0 +1,99 @@
|
||||
@model Rs_system.Models.DiezmoSalida
|
||||
@{
|
||||
ViewData["Title"] = $"Recibo {ViewBag.NumeroRecibo}";
|
||||
Layout = null; // layout propio para impresión
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Recibo @ViewBag.NumeroRecibo</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { font-family: 'Segoe UI', Arial, sans-serif; margin: 0; padding: 20px; color: #212529; }
|
||||
.recibo { max-width: 600px; margin: auto; border: 2px solid #343a40; border-radius: 8px; padding: 30px; }
|
||||
.recibo-header { text-align: center; border-bottom: 2px dashed #ced4da; padding-bottom: 16px; margin-bottom: 20px; }
|
||||
.recibo-header h2 { margin: 0 0 4px; font-size: 1.6rem; }
|
||||
.recibo-header p { margin: 0; color: #6c757d; font-size: .9rem; }
|
||||
.recibo-nro { font-size: 1.1rem; font-weight: bold; color: #0d6efd; }
|
||||
.recibo-body table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
|
||||
.recibo-body tr td { padding: 8px 12px; }
|
||||
.recibo-body tr td:first-child { font-weight: 600; color: #6c757d; width: 40%; }
|
||||
.recibo-monto { text-align: center; background: #f8f9fa; border-radius: 6px; padding: 16px; margin-bottom: 20px; }
|
||||
.recibo-monto h3 { margin: 0; font-size: 2rem; color: #198754; }
|
||||
.recibo-footer { border-top: 2px dashed #ced4da; padding-top: 16px; font-size: .8rem; color: #6c757d; display: flex; justify-content: space-between; }
|
||||
.firma { margin-top: 40px; text-align: center; }
|
||||
.firma-linea { border-top: 1px solid #343a40; width: 220px; margin: auto; padding-top: 6px; }
|
||||
@@media print {
|
||||
body { padding: 0; }
|
||||
.no-print { display: none !important; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="no-print mb-3" style="text-align:center">
|
||||
<button onclick="window.print()" style="padding:8px 20px;cursor:pointer">
|
||||
🖨️ Imprimir / Guardar PDF
|
||||
</button>
|
||||
<button onclick="window.close()" style="padding:8px 20px;cursor:pointer;margin-left:8px">
|
||||
✕ Cerrar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="recibo">
|
||||
<!-- Encabezado -->
|
||||
<div class="recibo-header">
|
||||
<h2>Recibo de Diezmos</h2>
|
||||
<p>Iglesia — módulo de Diezmos</p>
|
||||
<div class="recibo-nro mt-2">@ViewBag.NumeroRecibo</div>
|
||||
</div>
|
||||
|
||||
<!-- Datos -->
|
||||
<div class="recibo-body">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Fecha:</td>
|
||||
<td>@Model.Fecha.ToLocalTime().ToString("dd/MM/yyyy HH:mm")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tipo:</td>
|
||||
<td>@(Model.TipoSalida?.Nombre ?? "—")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Beneficiario:</td>
|
||||
<td>@(Model.Beneficiario?.Nombre ?? "No especificado")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Concepto:</td>
|
||||
<td>@Model.Concepto</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cierre:</td>
|
||||
<td>@(Model.DiezmoCierre?.Fecha.ToString("dd/MM/yyyy") ?? "—")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Emitido por:</td>
|
||||
<td>@ViewBag.Emisor</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Monto destacado -->
|
||||
<div class="recibo-monto">
|
||||
<small style="color:#6c757d">MONTO</small>
|
||||
<h3>$ @Model.Monto.ToString("N2")</h3>
|
||||
</div>
|
||||
|
||||
<!-- Firma -->
|
||||
<div class="firma">
|
||||
<div class="firma-linea">Firma del receptor</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pie -->
|
||||
<div class="recibo-footer">
|
||||
<span>Generado: @DateTime.Now.ToString("dd/MM/yyyy HH:mm")</span>
|
||||
<span>@ViewBag.NumeroRecibo</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user