fix(audit): corrige errores criticos y mayores, mejora UX/accesibilidad y optimiza rendimiento
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

- Arregla @require_auth, permisos, race conditions, locks de caja/stock
- Elimina N+1 en layaway, flotilla, dashboard y global_invoice
- Asegura folios atomicos para CFDI, ordenes de servicio y polizas
- Protege client_secret de MercadoLibre en backend
- Conecta botones/filtros de config, customers, accounting e invoicing
- Mejora accesibilidad (labels/aria-label) y estados de carga/vacio
- Limpia accounting.js obsoleto y consolida accounting.v9.js
- Actualiza cache busting a v32 y Service Worker a v32
- Documenta todo en docs/AUDIT_Y_MEJORAS_2026-06-15.md

Tests: 35 passed
This commit is contained in:
2026-06-29 23:54:58 +00:00
parent 59a4893e84
commit 2bdeb2973a
61 changed files with 2879 additions and 706 deletions

View File

@@ -304,7 +304,7 @@ const Config = (() => {
async function saveEmployee(data) {
// Check if we're editing (modal has editId) or creating
var modal = document.getElementById('employee-modal');
var modal = document.getElementById('modal-employee');
var editId = modal ? modal.dataset.editId : null;
var url = API + '/employees';
var method = 'POST';
@@ -368,24 +368,25 @@ const Config = (() => {
var emp = (json.data || []).find(function(e) { return e.id === empId; });
if (!emp) { toast('Empleado no encontrado', 'error'); return; }
// Pre-fill the "new employee" modal with existing data for editing
setVal('new-emp-name', emp.name);
setVal('new-emp-email', emp.email || '');
var roleSelect = document.getElementById('new-emp-role');
// Pre-fill the employee modal with existing data for editing
setVal('emp-name', emp.name);
setVal('emp-email', emp.email || '');
setVal('emp-phone', emp.phone || '');
var roleSelect = document.getElementById('emp-role');
if (roleSelect) roleSelect.value = emp.role || 'cashier';
var branchSelect = document.getElementById('new-emp-branch');
var branchSelect = document.getElementById('emp-branch');
if (branchSelect) branchSelect.value = emp.branch_id || '';
setVal('new-emp-discount', emp.max_discount_pct || '');
setVal('new-emp-pin', ''); // Don't pre-fill PIN for security
setVal('emp-discount', emp.max_discount_pct || '');
setVal('emp-pin', ''); // Don't pre-fill PIN for security
// Store the ID so saveEmployee knows it's an update
var modal = document.getElementById('employee-modal');
var modal = document.getElementById('modal-employee');
if (modal) {
modal.dataset.editId = empId;
var title = modal.querySelector('.modal-title, h3');
if (title) title.textContent = 'Editar Empleado';
}
openModal('employee-modal');
openModal('modal-employee');
} catch (e) {
toast('Error: ' + e.message, 'error');
}
@@ -442,6 +443,25 @@ const Config = (() => {
}
}
async function saveAll() {
if (!checkAuth()) return;
var btn = document.getElementById('btn-save-all');
if (btn) { btn.disabled = true; btn.textContent = 'Guardando...'; }
try {
await saveBusiness();
await saveTaxParams();
await saveCurrency();
await saveVehicleCompatSource();
await saveAllowedBrands();
await saveModules();
toast('Configuración guardada', 'ok');
} catch (e) {
toast(e.message, 'error');
} finally {
if (btn) { btn.disabled = false; btn.textContent = 'Guardar Cambios'; }
}
}
// -------------------------------------------------------------------------
// Event bindings
// -------------------------------------------------------------------------
@@ -506,6 +526,12 @@ const Config = (() => {
var btnNewEmp = document.getElementById('btn-new-employee');
if (btnNewEmp) {
btnNewEmp.addEventListener('click', function() {
var modal = document.getElementById('modal-employee');
if (modal) {
delete modal.dataset.editId;
var title = modal.querySelector('.modal-title, h3');
if (title) title.textContent = 'Nuevo Empleado';
}
openModal('modal-employee');
});
}
@@ -529,6 +555,7 @@ const Config = (() => {
btnSaveEmp.disabled = true;
btnSaveEmp.textContent = 'Guardando...';
var isEdit = !!document.getElementById('modal-employee').dataset.editId;
try {
await saveEmployee({
name: name,
@@ -539,7 +566,7 @@ const Config = (() => {
branch_id: branchId ? parseInt(branchId, 10) : null,
max_discount_pct: parseFloat(document.getElementById('emp-discount').value) || 0
});
toast('Empleado creado');
toast(isEdit ? 'Empleado actualizado' : 'Empleado creado');
closeModal('modal-employee');
// Reset form
document.getElementById('emp-name').value = '';
@@ -815,6 +842,10 @@ const Config = (() => {
// Bind UI events
bindEvents();
// Global save button
var btnSaveAll = document.getElementById('btn-save-all');
if (btnSaveAll) btnSaveAll.addEventListener('click', saveAll);
// Vehicle compat source save button
var btnCompat = document.getElementById('btn-save-compat-source');
if (btnCompat) {
@@ -854,14 +885,6 @@ const Config = (() => {
document.addEventListener('DOMContentLoaded', init);
return {
init, setTheme, selectThemeOption, loadAllowedBrands, saveAllowedBrands,
loadBranches, loadEmployees, saveBranch, saveEmployee, editEmployee,
loadBusiness, saveBusiness, saveTaxParams,
loadCurrency, saveCurrency,
loadModules, saveModules,
openModal, closeModal, openBranchModal, editBranch
};
// Register Cmd+K items
if (typeof registerCmdKItem === "function") {
registerCmdKItem({ group: "Principal", label: "POS Ventas", href: "/pos/sale", icon: "🛒" });
@@ -870,4 +893,14 @@ const Config = (() => {
registerCmdKItem({ group: "Principal", label: "Dashboard", href: "/pos/dashboard", icon: "📊" });
}
return {
init, setTheme, selectThemeOption, loadAllowedBrands, saveAllowedBrands,
loadBranches, loadEmployees, saveBranch, saveEmployee, editEmployee,
loadBusiness, saveBusiness, saveTaxParams, saveAll,
loadCurrency, saveCurrency,
loadVehicleCompatSource, saveVehicleCompatSource,
loadModules, saveModules,
openModal, closeModal, openBranchModal, editBranch
};
})();