diff --git a/src/page/pagos.js b/src/page/pagos.js index 50fca98..4662502 100644 --- a/src/page/pagos.js +++ b/src/page/pagos.js @@ -25,6 +25,13 @@ PAGES.pagos = { } } + // Check for scanned persona from QR scanner + var scannedPersona = sessionStorage.getItem('pagos_scanned_persona'); + if (scannedPersona) { + prefilledData.persona = scannedPersona; + sessionStorage.removeItem('pagos_scanned_persona'); + } + var field_tipo = safeuuid(); var field_monto = safeuuid(); var field_persona = safeuuid(); @@ -392,6 +399,14 @@ PAGES.pagos = { PAGES.pagos.datafono(JSON.parse(atob(tid2[2]))) return } + if (tid == "scan_qr") { + PAGES.pagos.__scanQR() + return + } + if (tid == "edit_transaction") { + PAGES.pagos.__editTransaction(tid2[2]) + return + } var nameh1 = safeuuid(); var field_ticket = safeuuid(); @@ -408,6 +423,9 @@ PAGES.pagos = { var div_origen = safeuuid(); var btn_volver = safeuuid(); var btn_volver2 = safeuuid(); + var btn_edit = safeuuid(); + var btn_delete = safeuuid(); + var btn_revert = safeuuid(); container.innerHTML = `

Transacción

@@ -471,6 +489,19 @@ PAGES.pagos = {

+ +
+ Acciones + + + +
`; document.getElementById(btn_volver).onclick = () => { @@ -511,6 +542,95 @@ PAGES.pagos = { document.getElementById(field_origen).value = data.Origen + (data.OrigenID ? " (" + data.OrigenID + ")" : ""); document.getElementById(div_origen).style.display = 'block'; } + + // Edit button - navigate to edit mode + document.getElementById(btn_edit).onclick = () => { + setUrlHash("pagos,edit_transaction," + key); + }; + + // Delete button + document.getElementById(btn_delete).onclick = () => { + if (!checkRole("pagos:edit")) { + alert("No tienes permisos para eliminar transacciones"); + return; + } + + if (confirm("¿Estás seguro de que quieres ELIMINAR esta transacción?\n\nEsta acción NO se puede deshacer y los cambios en los monederos NO se revertirán automáticamente.\n\nPara revertir los cambios en los monederos, usa el botón 'Revertir Transacción' en su lugar.")) { + betterGunPut(gun.get(TABLE).get("pagos").get(key), null); + toastr.success("Transacción eliminada"); + setTimeout(() => { + setUrlHash("pagos"); + }, 1000); + } + }; + + // Revert button - reverses wallet balance changes and deletes transaction + document.getElementById(btn_revert).onclick = () => { + if (!checkRole("pagos:edit")) { + alert("No tienes permisos para revertir transacciones"); + return; + } + + if (confirm("¿Estás seguro de que quieres REVERTIR esta transacción?\n\nEsto revertirá los cambios en los monederos y eliminará la transacción.")) { + // Reverse the wallet balance changes + var tipo = data.Tipo; + var monto = parseFloat(data.Monto || 0); + var personaId = data.Persona; + + // For Ingreso, subtract from balance (reverse) + // For Gasto, add to balance (reverse) + // For Transferencia, reverse both sides + + if (tipo === "Ingreso") { + revertWalletBalance(personaId, "Gasto", monto, () => { + deleteTransaction(key); + }); + } else if (tipo === "Gasto") { + revertWalletBalance(personaId, "Ingreso", monto, () => { + deleteTransaction(key); + }); + } else if (tipo === "Transferencia") { + var destinoId = data.PersonaDestino; + revertWalletBalance(personaId, "Ingreso", monto, () => { + revertWalletBalance(destinoId, "Gasto", monto, () => { + deleteTransaction(key); + }); + }); + } + } + }; + + function revertWalletBalance(personaId, tipo, monto, callback) { + var persona = SC_Personas[personaId]; + if (!persona) { + toastr.error("Error: Persona no encontrada"); + return; + } + + var currentBalance = parseFloat(persona.Monedero_Balance || 0); + var newBalance = currentBalance; + + if (tipo === "Ingreso") { + newBalance = currentBalance + monto; + } else if (tipo === "Gasto") { + newBalance = currentBalance - monto; + } + + persona.Monedero_Balance = newBalance; + + TS_encrypt(persona, SECRET, (encrypted) => { + betterGunPut(gun.get(TABLE).get("personas").get(personaId), encrypted); + if (callback) callback(); + }); + } + + function deleteTransaction(transactionKey) { + betterGunPut(gun.get(TABLE).get("pagos").get(transactionKey), null); + toastr.success("Transacción revertida y eliminada"); + setTimeout(() => { + setUrlHash("pagos"); + }, 1000); + } } if (typeof data == "string") { @@ -654,16 +774,20 @@ PAGES.pagos = { const monto = parseFloat(data.Monto || 0) || 0; const tipo = data.Tipo; + const metodo = data.Metodo || ""; + + // Only count Tarjeta Monedero transactions in balance totals + const isMonedero = metodo === "Tarjeta"; // Reset entries on every call for this ID - if (tipo === "Ingreso") { + if (isMonedero && tipo === "Ingreso") { totalData.gastos[id] = 0; totalData.ingresos[id] = monto; - } else if (tipo === "Gasto") { + } else if (isMonedero && tipo === "Gasto") { totalData.ingresos[id] = 0; totalData.gastos[id] = monto; } else { - // For Transferencias, count as gasto + ingreso (neutral) + // For non-Monedero transactions or Transferencias, don't count in totals totalData.ingresos[id] = 0; totalData.gastos[id] = 0; } @@ -694,5 +818,331 @@ PAGES.pagos = { setUrlHash("pagos," + safeuuid("")); }; } + }, + + // QR Scanner for selecting wallet/persona + __scanQR: function() { + if (!checkRole("pagos:edit")) { + setUrlHash("pagos"); + return; + } + + var qrscan = safeuuid(); + var btn_cancel = safeuuid(); + + container.innerHTML = ` +
+

+ 📷 Escanear QR de Monedero +

+ +
+

+ Escanea el código QR del monedero de la persona para seleccionarlo automáticamente +

+
+
+ + +
+ `; + + // Initialize QR scanner + var html5QrcodeScanner = new Html5QrcodeScanner( + qrscan, { fps: 10, qrbox: 250 } + ); + + function onScanSuccess(decodedText, decodedResult) { + html5QrcodeScanner.clear(); + + // Parse the QR code result + // Expected format: "personas,{personaId}" or just "{personaId}" + var personaId = decodedText; + + // If it's a full URL hash, extract the persona ID + if (decodedText.includes("personas,")) { + var parts = decodedText.split(","); + if (parts.length > 1) { + personaId = parts[1]; + } + } + + // Verify the persona exists + if (SC_Personas[personaId]) { + toastr.success("✅ Monedero escaneado: " + SC_Personas[personaId].Nombre); + + // Store the selected persona in sessionStorage and return to datafono + sessionStorage.setItem('pagos_scanned_persona', personaId); + + // Navigate back to datafono + setUrlHash("pagos,datafono"); + } else { + toastr.error("❌ Código QR no reconocido como un monedero válido"); + setTimeout(() => { + setUrlHash("pagos,datafono"); + }, 2000); + } + } + + html5QrcodeScanner.render(onScanSuccess); + EventListeners.QRScanner.push(html5QrcodeScanner); + + // Cancel button + document.getElementById(btn_cancel).onclick = () => { + html5QrcodeScanner.clear(); + setUrlHash("pagos,datafono"); + }; + }, + + // Edit existing transaction + __editTransaction: function(transactionId) { + if (!checkRole("pagos:edit")) { + setUrlHash("pagos"); + return; + } + + var field_tipo = safeuuid(); + var field_monto = safeuuid(); + var field_persona = safeuuid(); + var field_persona_destino = safeuuid(); + var field_metodo = safeuuid(); + var field_notas = safeuuid(); + var field_estado = safeuuid(); + var div_persona_destino = safeuuid(); + var btn_save = safeuuid(); + var btn_cancel = safeuuid(); + + var selectedPersona = ""; + var selectedPersonaDestino = ""; + var originalData = null; + + container.innerHTML = ` +
+

+ ✏️ Editar Transacción +

+ +
+
+ Información de Transacción + + + + + + + + + + + + + + +
+
+ +
+ + +
+
+ `; + + // Load transaction data + gun.get(TABLE).get("pagos").get(transactionId).once((data, key) => { + function loadTransactionData(data) { + originalData = data; + + document.getElementById(field_tipo).value = data.Tipo || "Ingreso"; + document.getElementById(field_metodo).value = data.Metodo || "Efectivo"; + document.getElementById(field_monto).value = data.Monto || 0; + document.getElementById(field_estado).value = data.Estado || "Completado"; + document.getElementById(field_notas).value = data.Notas || ""; + + selectedPersona = data.Persona || ""; + selectedPersonaDestino = data.PersonaDestino || ""; + + loadPersonaSelector(); + + if (data.Tipo === "Transferencia") { + document.getElementById(div_persona_destino).style.display = 'block'; + loadPersonaDestinoSelector(); + } + } + + if (typeof data == "string") { + TS_decrypt(data, SECRET, loadTransactionData); + } else { + loadTransactionData(data || {}); + } + }); + + // Tipo change handler + document.getElementById(field_tipo).addEventListener('change', function() { + var tipo = this.value; + var divDestino = document.getElementById(div_persona_destino); + if (tipo === 'Transferencia') { + divDestino.style.display = 'block'; + loadPersonaDestinoSelector(); + } else { + divDestino.style.display = 'none'; + } + }); + + function loadPersonaSelector() { + var container = document.querySelector('#personaSelector'); + container.innerHTML = ''; + document.getElementById(field_persona).value = selectedPersona; + addCategory_Personas( + container, + SC_Personas, + selectedPersona, + (personaId) => { + document.getElementById(field_persona).value = personaId; + selectedPersona = personaId; + }, + "Monedero", + false, + "- No hay personas registradas -" + ); + } + + function loadPersonaDestinoSelector() { + var container = document.querySelector('#personaDestinoSelector'); + container.innerHTML = ''; + document.getElementById(field_persona_destino).value = selectedPersonaDestino; + addCategory_Personas( + container, + SC_Personas, + selectedPersonaDestino, + (personaId) => { + document.getElementById(field_persona_destino).value = personaId; + selectedPersonaDestino = personaId; + }, + "Monedero Destino", + false, + "- No hay personas registradas -" + ); + } + + // Save button + document.getElementById(btn_save).onclick = () => { + var tipo = document.getElementById(field_tipo).value; + var monto = parseFloat(document.getElementById(field_monto).value); + var personaId = document.getElementById(field_persona).value; + var metodo = document.getElementById(field_metodo).value; + var notas = document.getElementById(field_notas).value; + var estado = document.getElementById(field_estado).value; + + if (!personaId) { + alert("Por favor selecciona un monedero"); + return; + } + + if (isNaN(monto) || monto < 0) { + alert("Por favor ingresa un monto válido"); + return; + } + + if (tipo === 'Transferencia') { + var personaDestinoId = document.getElementById(field_persona_destino).value; + if (!personaDestinoId) { + alert("Por favor selecciona el monedero destino"); + return; + } + if (personaId === personaDestinoId) { + alert("No puedes transferir al mismo monedero"); + return; + } + } + + if (!confirm("¿Estás seguro de que quieres guardar los cambios?\n\nNOTA: Los cambios en los monederos NO se ajustarán automáticamente. Si cambiaste el monto, tipo o persona, deberías revertir la transacción original y crear una nueva.")) { + return; + } + + // Update transaction data + var updatedData = { + ...originalData, + Tipo: tipo, + Monto: monto, + Persona: personaId, + Metodo: metodo, + Notas: notas, + Estado: estado + }; + + if (tipo === 'Transferencia') { + updatedData.PersonaDestino = document.getElementById(field_persona_destino).value; + } else { + delete updatedData.PersonaDestino; + } + + TS_encrypt(updatedData, SECRET, (encrypted) => { + document.getElementById("actionStatus").style.display = "block"; + betterGunPut(gun.get(TABLE).get("pagos").get(transactionId), encrypted); + toastr.success("¡Transacción actualizada!"); + setTimeout(() => { + document.getElementById("actionStatus").style.display = "none"; + setUrlHash("pagos," + transactionId); + }, 1500); + }); + }; + + // Cancel button + document.getElementById(btn_cancel).onclick = () => { + if (confirm("¿Seguro que quieres cancelar? Los cambios no se guardarán.")) { + setUrlHash("pagos," + transactionId); + } + }; } };