gastos recreado, confirmaciones bonitas, fix modal nueva conrtaseña etc

This commit is contained in:
2026-03-21 01:07:06 -03:00
parent ed918bb857
commit 45e4f58747
6 changed files with 104 additions and 37 deletions

View File

@@ -36,7 +36,8 @@ services:
# TODO general:
- separar productos para tiendas
- limpiar requirements.txt
- hacer que trabajador acompañante solo muestre trabajadores en el mismo modulo
- hacer placeholders funcionales (si dice 0 que el sistema lea 0 no null)
# TODO peppermint:
## formulario
- cantidad de boletas por metodo de pago

View File

@@ -1,12 +1,8 @@
{% extends "macros/base.html" %}
{% import "macros/modals.html" as modals %}
{% block title %}Estructura Operativa{% endblock %}
{% block head %}
<!-- HEAD -->
{% endblock %}
{% block content %}
<h2 class="mb-4">Estructura Operativa</h2>
@@ -45,9 +41,22 @@
<tr>
<td class="align-middle">{{ zona[1] }}</td>
<td class="text-end">
<form action="{{ url_for('delete_structure', type='zona', id=zona[0]) }}" method="POST" class="d-inline">
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar esta Zona?');">Eliminar</button>
</form>
{# Botón que dispara el modal de confirmación #}
<button type="button" class="btn btn-sm btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#deleteZona{{ zona[0] }}">
Eliminar
</button>
{# Llamada a la macro para generar el modal de esta zona específica #}
{{ modals.confirm_modal(
'deleteZona' ~ zona[0],
'Eliminar Zona',
'¿Estás seguro de eliminar la zona "' ~ zona[1] ~ '"? Esto podría afectar a los módulos asociados.',
url_for('delete_structure', type='zona', id=zona[0]),
'btn-danger',
'Eliminar'
) }}
</td>
</tr>
{% else %}
@@ -82,7 +91,7 @@
<input type="text" class="form-control" name="modulo_name" placeholder="Nombre del Módulo" required>
</div>
<div class="col-md-2">
<button class="btn btn-primary w-100" type="submit">+</button>
<button class="btn btn-primary w-100" type="submit">Agregar</button>
</div>
</div>
</form>
@@ -101,9 +110,22 @@
<td class="align-middle">{{ modulo[1] }}</td>
<td class="align-middle"><span class="badge bg-info text-dark">{{ modulo[2] }}</span></td>
<td class="text-end">
<form action="{{ url_for('delete_structure', type='modulo', id=modulo[0]) }}" method="POST" class="d-inline">
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar este Módulo?');">Eliminar</button>
</form>
{# Botón que dispara el modal de confirmación #}
<button type="button" class="btn btn-sm btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#deleteModulo{{ modulo[0] }}">
Eliminar
</button>
{# Llamada a la macro para el módulo #}
{{ modals.confirm_modal(
'deleteModulo' ~ modulo[0],
'Eliminar Módulo',
'¿Deseas eliminar el módulo "' ~ modulo[1] ~ '"?',
url_for('delete_structure', type='modulo', id=modulo[0]),
'btn-danger',
'Eliminar'
) }}
</td>
</tr>
{% else %}

View File

@@ -106,31 +106,62 @@
</table>
</div>
</div>
{{ confirm_modal(
id='confirmResetPass',
title='Restablecer Contraseña',
message='¿Estás seguro de generar una nueva contraseña? La anterior dejará de funcionar inmediatamente.',
action_url='#',
btn_class='btn-warning',
btn_text='Generar Nueva Clave'
) }}
{% endblock %}
{% block scripts %}
<script>
const editWorkerModal = document.getElementById('editWorkerModal');
const confirmResetModal = document.getElementById('confirmResetPass');
if (editWorkerModal) {
editWorkerModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
// IMPORTANTE: Definir las rutas correctamente
const editForm = editWorkerModal.querySelector('#editWorkerForm');
const resetForm = editWorkerModal.querySelector('#resetPasswordForm');
editForm.action = "/admin/workers/edit/" + id;
resetForm.action = "/admin/workers/reset_password/" + id;
// Si el modal se abre desde el botón "Editar" de la tabla
if (button && button.hasAttribute('data-id')) {
const id = button.getAttribute('data-id');
const name = button.getAttribute('data-name');
const editForm = editWorkerModal.querySelector('#editWorkerForm');
const resetForm = confirmResetModal.querySelector('form');
editForm.action = "/admin/workers/edit/" + id;
resetForm.action = "/admin/workers/reset_password/" + id;
// Rellenar campos
editWorkerModal.querySelector('#edit_worker_rut').value = button.getAttribute('data-rut');
editWorkerModal.querySelector('#edit_worker_name').value = button.getAttribute('data-name');
editWorkerModal.querySelector('#edit_worker_phone').value = button.getAttribute('data-phone');
editWorkerModal.querySelector('#edit_worker_modulo').value = button.getAttribute('data-modulo');
confirmResetModal.querySelector('.modal-body').textContent = `¿Estás seguro de generar una nueva contraseña para ${name}? La anterior dejará de funcionar.`;
editWorkerModal.querySelector('#edit_worker_rut').value = button.getAttribute('data-rut');
editWorkerModal.querySelector('#edit_worker_name').value = name;
editWorkerModal.querySelector('#edit_worker_phone').value = button.getAttribute('data-phone');
editWorkerModal.querySelector('#edit_worker_modulo').value = button.getAttribute('data-modulo');
}
});
}
// Lógica para reabrir el modal de edición al cancelar el de confirmación
if (confirmResetModal) {
// Buscamos el botón de cancelar dentro del modal de confirmación
const btnCancelar = confirmResetModal.querySelector('.btn-secondary');
const btnCerrarX = confirmResetModal.querySelector('.btn-close');
const reabrirEdicion = () => {
const modalEdicion = new bootstrap.Modal(editWorkerModal);
modalEdicion.show();
};
btnCancelar.addEventListener('click', reabrirEdicion);
btnCerrarX.addEventListener('click', reabrirEdicion);
}
document.getElementById('rutInput').addEventListener('input', function(e) {
let value = this.value.replace(/[^0-9kK]/g, '').toUpperCase();
if (value.length > 1) {

View File

@@ -99,11 +99,12 @@
<hr>
<div class="d-grid">
<form id="resetPasswordForm" method="POST" action="" onsubmit="return confirm('¿Generar nueva contraseña?');">
<button type="submit" class="btn btn-outline-warning btn-sm w-100">
<i class="bi bi-key me-1"></i> Restablecer Contraseña
</button>
</form>
<button type="button" class="btn btn-outline-warning btn-sm w-100"
data-bs-toggle="modal"
data-bs-target="#confirmResetPass"
data-bs-dismiss="modal"> {# Esto cierra el de edición al abrir el de confirmación #}
<i class="bi bi-key me-1"></i> Restablecer Contraseña
</button>
<small class="text-muted text-center mt-1">Generará una nueva clave aleatoria.</small>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="container">
<a class="navbar-brand d-flex align-items-center fw-bold text-primary-emphasis" href="{{ url_for('index') }}">
<i class="bi bi-receipt-cutoff me-2 fs-4 text-info"></i>
<span>SekiPOS</span>
<span>MikuTBD</span>
</a>
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">

View File

@@ -138,15 +138,22 @@
</div>
<div class="row g-3 mb-4 p-3 bg-body-secondary rounded shadow-sm">
<div class="col-md-6">
<div class="col-md-4">
<label class="form-label text-info fw-bold">Total Digital (Tarjeta + MP)</label>
<div class="input-group">
<span class="input-group-text bg-info text-white border-info">$</span>
<input type="text" class="form-control bg-dark-subtle fw-bold" placeholder="0" id="total_digital" readonly>
</div>
</div>
<div class="col-md-6">
<label class="form-label text-success fw-bold">Total Ventas (Todos los medios)</label>
<div class="col-md-4">
<label class="form-label text-danger fw-bold">Gastos del Módulo</label>
<div class="input-group">
<span class="input-group-text bg-danger text-white border-danger">-$</span>
<input type="text" class="form-control money-input sale-input" name="gastos" id="gastos" placeholder="0">
</div>
</div>
<div class="col-md-4">
<label class="form-label text-success fw-bold">Total Ventas (Neto)</label>
<div class="input-group">
<span class="input-group-text bg-success text-white border-success">$</span>
<input type="text" class="form-control bg-dark-subtle fw-bold" placeholder="0" id="total_general" readonly>
@@ -251,16 +258,21 @@ document.addEventListener('DOMContentLoaded', function() {
function calcularTotales() {
// Limpiamos los puntos para sumar números puros
const getVal = (id) => parseInt(document.getElementById(id).value.replace(/\D/g, '')) || 0;
const getVal = (id) => {
const el = document.getElementById(id);
return el ? parseInt(el.value.replace(/\D/g, '')) || 0 : 0;
};
const tarjeta = getVal('venta_tarjeta');
const mp = getVal('venta_mp');
const efectivo = getVal('venta_efectivo');
const gastos = getVal('gastos'); // Nuevo campo capturado
const totalDigital = tarjeta + mp;
const totalGeneral = totalDigital + efectivo;
// El total general ahora resta los gastos para mostrar el neto real
const totalGeneral = (totalDigital + efectivo) - gastos;
// Formateamos de vuelta a moneda chilena para mostrar
// Formateamos de vuelta a moneda chilena
displayDigital.value = totalDigital.toLocaleString('es-CL');
displayGeneral.value = totalGeneral.toLocaleString('es-CL');
}