diff --git a/worker-multi-estado.js b/worker-multi-estado.js index bb8d64f..71f99c9 100644 --- a/worker-multi-estado.js +++ b/worker-multi-estado.js @@ -1,4 +1,4 @@ -// worker-multi-estado.js (V7 - CON RELLENO DE FECHA CONTACTO) +// worker-multi-estado.js (V7 - CON DEBUG DE SELECTOR Y FECHA CONTACTO) 'use strict'; const { chromium } = require('playwright'); @@ -16,7 +16,10 @@ const CONFIG = { // --- UTILS --- const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); -function toServerTimestamp() { return admin.firestore.FieldValue.serverTimestamp(); } + +function toServerTimestamp() { + return admin.firestore.FieldValue.serverTimestamp(); +} function timeToMultiValue(timeStr) { if (!timeStr) return ""; @@ -28,6 +31,7 @@ function timeToMultiValue(timeStr) { // --- FIREBASE INIT --- function initFirebase() { if (!process.env.FIREBASE_PRIVATE_KEY) throw new Error('Missing FIREBASE_PRIVATE_KEY'); + if (!admin.apps.length) { admin.initializeApp({ credential: admin.credential.cert({ @@ -44,7 +48,11 @@ function initFirebase() { async function loginMulti(page, db) { let user = "", pass = ""; const doc = await db.collection("providerCredentials").doc("multiasistencia").get(); - if (doc.exists) { user = doc.data().user; pass = doc.data().pass; } + + if (doc.exists) { + user = doc.data().user; + pass = doc.data().pass; + } if (!user) throw new Error("Faltan credenciales en providerCredentials/multiasistencia"); @@ -53,7 +61,11 @@ async function loginMulti(page, db) { const userFilled = await page.evaluate((u) => { const el = document.querySelector('input[name="usuario"]') || document.querySelector('input[type="text"]'); - if (el) { el.value = u; el.dispatchEvent(new Event('input', { bubbles: true })); return true; } + if (el) { + el.value = u; + el.dispatchEvent(new Event('input', { bubbles: true })); + return true; + } return false; }, user); @@ -95,12 +107,31 @@ async function processChangeState(page, db, jobData) { await page.waitForSelector('select.answer-select', { timeout: 20000 }); await page.waitForTimeout(1500); - console.log('📝 Rellenando formulario...'); - // 3. MOTIVO + // 3. MOTIVO (CON DIAGNÓSTICO DE ERROR) const reasonSel = page.locator('select.answer-select').first(); - await reasonSel.selectOption(String(reasonValue)); + const targetValue = String(reasonValue); + + // --- BLOQUE DE DIAGNÓSTICO --- + const availableOptions = await reasonSel.evaluate((select) => { + return Array.from(select.options).map(o => ({ + value: o.value, + text: o.innerText.trim() + })); + }); + + console.log(`🔍 Intentando seleccionar motivo ID: "${targetValue}"`); + const optionExists = availableOptions.find(o => o.value === targetValue); + + if (!optionExists) { + const validList = availableOptions.map(o => `[${o.value}: ${o.text}]`).join(', '); + console.error(`❌ ERROR: El motivo "${targetValue}" no existe.`); + throw new Error(`MOTIVO INVÁLIDO: El ID "${targetValue}" no está disponible en este estado. Opciones válidas: ${validList}`); + } + // ----------------------------- + + await reasonSel.selectOption(targetValue); await forceUpdate(await reasonSel.elementHandle()); // 4. COMENTARIO @@ -122,7 +153,7 @@ async function processChangeState(page, db, jobData) { if (timeStr) { const secondsValue = timeToMultiValue(timeStr); const timeSelectHandle = await page.$(`xpath=//select[.//option[@value="${secondsValue}"]]`); - + if (timeSelectHandle) { await timeSelectHandle.selectOption(secondsValue); await forceUpdate(timeSelectHandle); @@ -138,7 +169,7 @@ async function processChangeState(page, db, jobData) { // --- NUEVO BLOQUE: FECHA DE CONTACTO (CONDICIONAL) --- // Buscamos si existe el campo "Fecha en la que contactó con el cliente" const contactBlock = page.locator('encastrables-date-hour-field').filter({ hasText: 'Fecha en la que contactó con el cliente' }); - + if (await contactBlock.count() > 0 && await contactBlock.isVisible()) { console.log('📞 Detectado campo obligatorio "Fecha contacto cliente". Rellenando...'); @@ -157,6 +188,7 @@ async function processChangeState(page, db, jobData) { const mVal = mRaw; // Los minutos sí suelen tener el "00" const selects = contactBlock.locator('select'); + // Asumimos que el primer select es Hora y el segundo Minutos dentro de este bloque if (await selects.count() >= 1) { await selects.nth(0).selectOption(hVal).catch(() => {}); @@ -191,9 +223,8 @@ async function processChangeState(page, db, jobData) { // 8. GESTIÓN DE ALERTAS (POPUP "SÍ") await page.waitForTimeout(3000); - const confirmBtn = page.locator('button.form-container-button-submit-toast').filter({ hasText: 'Sí' }); - + if (await confirmBtn.count() > 0 && await confirmBtn.isVisible()) { console.log('🚨 ALERTA SMS DETECTADA. Pulsando "Sí"...'); await confirmBtn.click(); @@ -245,9 +276,10 @@ async function claimJobById(db, jobId) { async function markJobDone(db, job, result) { const jobId = job.id; await db.collection(CONFIG.QUEUE_COLLECTION).doc(jobId).set({ status: 'DONE', result }, { merge: true }); + await db.collection(CONFIG.RESULT_COLLECTION).add({ jobId, - ok: true, + ok: true, serviceNumber: job.serviceNumber || '', reason: job.reasonValue || '', comment: job.comment || '', @@ -303,10 +335,12 @@ function startWorker(db) { const run = async () => { while(queue.length) { await processJob(db, await claimJobById(db, queue.shift())); } }; + db.collection(CONFIG.QUEUE_COLLECTION).where('status', '==', 'PENDING').onSnapshot(s => { s.docChanges().forEach(c => { if(c.type==='added') { queue.push(c.doc.id); run(); } }); }); - console.log('🚀 Worker Multiasistencia (V7 - CON FECHA CONTACTO) LISTO.'); + + console.log('🚀 Worker Multiasistencia (V7 - CON DEBUG) LISTO.'); } const db = initFirebase();