gastos recreado, confirmaciones bonitas, fix modal nueva conrtaseña etc
This commit is contained in:
@@ -36,7 +36,8 @@ services:
|
|||||||
# TODO general:
|
# TODO general:
|
||||||
- separar productos para tiendas
|
- separar productos para tiendas
|
||||||
- limpiar requirements.txt
|
- 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:
|
# TODO peppermint:
|
||||||
## formulario
|
## formulario
|
||||||
- cantidad de boletas por metodo de pago
|
- cantidad de boletas por metodo de pago
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
{% extends "macros/base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
{% import "macros/modals.html" as modals %}
|
||||||
|
|
||||||
{% block title %}Estructura Operativa{% endblock %}
|
{% block title %}Estructura Operativa{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<!-- HEAD -->
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="mb-4">Estructura Operativa</h2>
|
<h2 class="mb-4">Estructura Operativa</h2>
|
||||||
|
|
||||||
@@ -45,9 +41,22 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="align-middle">{{ zona[1] }}</td>
|
<td class="align-middle">{{ zona[1] }}</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<form action="{{ url_for('delete_structure', type='zona', id=zona[0]) }}" method="POST" class="d-inline">
|
{# Botón que dispara el modal de confirmación #}
|
||||||
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar esta Zona?');">Eliminar</button>
|
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||||
</form>
|
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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -82,7 +91,7 @@
|
|||||||
<input type="text" class="form-control" name="modulo_name" placeholder="Nombre del Módulo" required>
|
<input type="text" class="form-control" name="modulo_name" placeholder="Nombre del Módulo" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -101,9 +110,22 @@
|
|||||||
<td class="align-middle">{{ modulo[1] }}</td>
|
<td class="align-middle">{{ modulo[1] }}</td>
|
||||||
<td class="align-middle"><span class="badge bg-info text-dark">{{ modulo[2] }}</span></td>
|
<td class="align-middle"><span class="badge bg-info text-dark">{{ modulo[2] }}</span></td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<form action="{{ url_for('delete_structure', type='modulo', id=modulo[0]) }}" method="POST" class="d-inline">
|
{# Botón que dispara el modal de confirmación #}
|
||||||
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar este Módulo?');">Eliminar</button>
|
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||||
</form>
|
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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -106,31 +106,62 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</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 %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const editWorkerModal = document.getElementById('editWorkerModal');
|
const editWorkerModal = document.getElementById('editWorkerModal');
|
||||||
|
const confirmResetModal = document.getElementById('confirmResetPass');
|
||||||
|
|
||||||
if (editWorkerModal) {
|
if (editWorkerModal) {
|
||||||
editWorkerModal.addEventListener('show.bs.modal', function (event) {
|
editWorkerModal.addEventListener('show.bs.modal', function (event) {
|
||||||
const button = event.relatedTarget;
|
const button = event.relatedTarget;
|
||||||
const id = button.getAttribute('data-id');
|
|
||||||
|
|
||||||
// IMPORTANTE: Definir las rutas correctamente
|
// Si el modal se abre desde el botón "Editar" de la tabla
|
||||||
const editForm = editWorkerModal.querySelector('#editWorkerForm');
|
if (button && button.hasAttribute('data-id')) {
|
||||||
const resetForm = editWorkerModal.querySelector('#resetPasswordForm');
|
const id = button.getAttribute('data-id');
|
||||||
|
const name = button.getAttribute('data-name');
|
||||||
editForm.action = "/admin/workers/edit/" + id;
|
|
||||||
resetForm.action = "/admin/workers/reset_password/" + id;
|
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
|
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 = button.getAttribute('data-name');
|
editWorkerModal.querySelector('#edit_worker_rut').value = button.getAttribute('data-rut');
|
||||||
editWorkerModal.querySelector('#edit_worker_phone').value = button.getAttribute('data-phone');
|
editWorkerModal.querySelector('#edit_worker_name').value = name;
|
||||||
editWorkerModal.querySelector('#edit_worker_modulo').value = button.getAttribute('data-modulo');
|
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) {
|
document.getElementById('rutInput').addEventListener('input', function(e) {
|
||||||
let value = this.value.replace(/[^0-9kK]/g, '').toUpperCase();
|
let value = this.value.replace(/[^0-9kK]/g, '').toUpperCase();
|
||||||
if (value.length > 1) {
|
if (value.length > 1) {
|
||||||
|
|||||||
@@ -99,11 +99,12 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="d-grid">
|
<div class="d-grid">
|
||||||
<form id="resetPasswordForm" method="POST" action="" onsubmit="return confirm('¿Generar nueva contraseña?');">
|
<button type="button" class="btn btn-outline-warning btn-sm w-100"
|
||||||
<button type="submit" class="btn btn-outline-warning btn-sm w-100">
|
data-bs-toggle="modal"
|
||||||
<i class="bi bi-key me-1"></i> Restablecer Contraseña
|
data-bs-target="#confirmResetPass"
|
||||||
</button>
|
data-bs-dismiss="modal"> {# Esto cierra el de edición al abrir el de confirmación #}
|
||||||
</form>
|
<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>
|
<small class="text-muted text-center mt-1">Generará una nueva clave aleatoria.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand d-flex align-items-center fw-bold text-primary-emphasis" href="{{ url_for('index') }}">
|
<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>
|
<i class="bi bi-receipt-cutoff me-2 fs-4 text-info"></i>
|
||||||
<span>SekiPOS</span>
|
<span>MikuTBD</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
|||||||
@@ -138,15 +138,22 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-3 mb-4 p-3 bg-body-secondary rounded shadow-sm">
|
<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>
|
<label class="form-label text-info fw-bold">Total Digital (Tarjeta + MP)</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text bg-info text-white border-info">$</span>
|
<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>
|
<input type="text" class="form-control bg-dark-subtle fw-bold" placeholder="0" id="total_digital" readonly>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-4">
|
||||||
<label class="form-label text-success fw-bold">Total Ventas (Todos los medios)</label>
|
<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">
|
<div class="input-group">
|
||||||
<span class="input-group-text bg-success text-white border-success">$</span>
|
<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>
|
<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() {
|
function calcularTotales() {
|
||||||
// Limpiamos los puntos para sumar números puros
|
// 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 tarjeta = getVal('venta_tarjeta');
|
||||||
const mp = getVal('venta_mp');
|
const mp = getVal('venta_mp');
|
||||||
const efectivo = getVal('venta_efectivo');
|
const efectivo = getVal('venta_efectivo');
|
||||||
|
const gastos = getVal('gastos'); // Nuevo campo capturado
|
||||||
|
|
||||||
const totalDigital = tarjeta + mp;
|
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');
|
displayDigital.value = totalDigital.toLocaleString('es-CL');
|
||||||
displayGeneral.value = totalGeneral.toLocaleString('es-CL');
|
displayGeneral.value = totalGeneral.toLocaleString('es-CL');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user