diff --git a/worker-multi-estado.js b/worker-multi-estado.js index b20532c..bb8d64f 100644 --- a/worker-multi-estado.js +++ b/worker-multi-estado.js @@ -1,4 +1,4 @@ -// worker-multi-estado.js (V6 - LOG COMPLETO DE DATOS) +// worker-multi-estado.js (V7 - CON RELLENO DE FECHA CONTACTO) 'use strict'; const { chromium } = require('playwright'); @@ -21,6 +21,7 @@ function toServerTimestamp() { return admin.firestore.FieldValue.serverTimestamp function timeToMultiValue(timeStr) { if (!timeStr) return ""; const [h, m] = timeStr.split(':').map(Number); + // Para el desplegable principal (segundos desde medianoche) return String((h * 3600) + (m * 60)); } @@ -109,7 +110,7 @@ async function processChangeState(page, db, jobData) { await forceUpdate(await commentBox.elementHandle()); } - // 5. FECHA + // 5. FECHA (Siguiente Acción) if (dateStr) { const dateInput = page.locator('input[type="date"]').first(); await dateInput.fill(dateStr); @@ -117,7 +118,7 @@ async function processChangeState(page, db, jobData) { await page.click('body'); } - // 6. HORA + // 6. HORA (Siguiente Acción) if (timeStr) { const secondsValue = timeToMultiValue(timeStr); const timeSelectHandle = await page.$(`xpath=//select[.//option[@value="${secondsValue}"]]`); @@ -134,6 +135,41 @@ 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...'); + + // Rellenar Fecha + if (dateStr) { + const contactDateInput = contactBlock.locator('input[type="date"]'); + await contactDateInput.fill(dateStr); + await forceUpdate(await contactDateInput.elementHandle()); + } + + // Rellenar Hora (Este campo es especial, tiene 2 desplegables: Hora y Minutos por separado) + if (timeStr) { + const [hRaw, mRaw] = timeStr.split(':'); + // La web usa "8", "9" para horas de un dígito, no "08" + const hVal = String(Number(hRaw)); + 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(() => {}); + await forceUpdate(await selects.nth(0).elementHandle()); + } + if (await selects.count() >= 2) { + await selects.nth(1).selectOption(mVal).catch(() => {}); + await forceUpdate(await selects.nth(1).elementHandle()); + } + } + } + // ----------------------------------------------------- + await page.waitForTimeout(2000); // 7. GUARDAR @@ -153,7 +189,7 @@ async function processChangeState(page, db, jobData) { console.log('💾 Click en Guardar...'); await btn.click(); - // 8. GESTIÓN DE ALERTAS + // 8. GESTIÓN DE ALERTAS (POPUP "SÍ") await page.waitForTimeout(3000); const confirmBtn = page.locator('button.form-container-button-submit-toast').filter({ hasText: 'Sí' }); @@ -195,7 +231,7 @@ async function processChangeState(page, db, jobData) { }; } -// --- WORKER LOOP (ACTUALIZADO PARA GUARDAR INFO) --- +// --- WORKER LOOP --- async function claimJobById(db, jobId) { const ref = db.collection(CONFIG.QUEUE_COLLECTION).doc(jobId); return await db.runTransaction(async (tx) => { @@ -206,29 +242,22 @@ async function claimJobById(db, jobId) { }); } -// ✅ MODIFICADO: Ahora recibe el objeto 'job' completo para guardar sus datos async function markJobDone(db, job, result) { const jobId = job.id; - // 1. Actualizamos el estado en la cola await db.collection(CONFIG.QUEUE_COLLECTION).doc(jobId).set({ status: 'DONE', result }, { merge: true }); - - // 2. Guardamos el LOG COMPLETO con los datos de entrada await db.collection(CONFIG.RESULT_COLLECTION).add({ jobId, ok: true, - // Datos del servicio enviados: serviceNumber: job.serviceNumber || '', reason: job.reasonValue || '', comment: job.comment || '', date: job.dateStr || '', time: job.timeStr || '', - // Resultado del robot: - ...result, // Incluye screenshot y message + ...result, createdAt: toServerTimestamp() }); } -// ✅ MODIFICADO: También guardamos los datos si falla, para saber qué provocó el error async function markJobFailed(db, job, err) { const jobId = job.id; await db.collection(CONFIG.QUEUE_COLLECTION).doc(jobId).set({ @@ -239,13 +268,11 @@ async function markJobFailed(db, job, err) { await db.collection(CONFIG.RESULT_COLLECTION).add({ jobId, ok: false, - // Datos del servicio: serviceNumber: job.serviceNumber || '', reason: job.reasonValue || '', comment: job.comment || '', date: job.dateStr || '', time: job.timeStr || '', - // Error: error: err.message, createdAt: toServerTimestamp() }); @@ -262,13 +289,11 @@ async function processJob(db, job) { dateStr: job.dateStr, timeStr: job.timeStr }); - // Pasamos el objeto 'job' entero await markJobDone(db, job, res); console.log(`✅ Job ${job.id} Completado.`); }); } catch (err) { console.error(`❌ Job ${job.id} Falló:`, err.message); - // Pasamos el objeto 'job' entero await markJobFailed(db, job, err); } } @@ -281,7 +306,7 @@ function startWorker(db) { 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 (V6 - LOG COMPLETO) LISTO.'); + console.log('🚀 Worker Multiasistencia (V7 - CON FECHA CONTACTO) LISTO.'); } const db = initFirebase();