($c['peticion'] ?? '') === 'ausentismos_up'))[0] ?? null; check('el POST llegó al ERP', $post !== null); check('con el contrato exacto del procesador', [$post['body']['empleado_id'] ?? null, $post['body']['novedad_id'] ?? null, $post['body']['fecha_inicial'] ?? null, $post['body']['fecha_final'] ?? null], ['412', '112', $hoy, $hoy]); check('y la trazabilidad', $post['body']['telefono'] ?? null, '57300AUSEN'); // ════ 3. Ausentismo según el perfil del número ═══════════════════════════════ echo "\nPerfil — trabajador vinculado y supervisor\n"; fakePhone('57300TRABAJADOR', 412, 0); fakePhone('57300JEFE', 412, 1); $ctx = contexto('57300TRABAJADOR'); $r = NormalBot::processInteractive($co, $ctx, 'registrar_ausentismo'); check('el trabajador vinculado no se pregunta: arranca por el motivo', str_contains(textoDe($r), 'motivo del ausentismo')); $ctx = contexto('57300JEFE'); $r = NormalBot::processInteractive($co, $ctx, 'registrar_ausentismo'); check('el supervisor elige aunque tenga tercero', str_contains(textoDe($r), 'nombre o documento')); capturas(); // ════ 4. Ciclos: apertura con selección múltiple ═════════════════════════════ echo "\nCiclos — apertura de varios lotes\n"; $ctx = contexto('57300CICLOS'); $r = NormalBot::processInteractive($co, $ctx, 'registrar_ciclo'); check('pregunta el tipo de ciclo', str_contains(textoDe($r), 'Qué ciclo')); $r = NormalBot::processInteractive($co, $ctx, 'cosecha'); check('después la acción', isset(filasDe($r)['apertura'])); $r = NormalBot::processInteractive($co, $ctx, 'apertura'); $r = NormalBot::processInteractive($co, $ctx, $hoy); $filas = filasDe($r); check('lista de lotes con "Otro lote" y "Listo"', isset($filas['__todos']) && isset($filas['__listo'])); $r = NormalBot::processInteractive($co, $ctx, '1'); check('marcar redibuja con el check', str_contains(filasDe($r)['1'] ?? '', '✅')); $r = NormalBot::processInteractive($co, $ctx, '2'); check('el contador acumula', str_contains(filasDe($r)['__listo'] ?? '', '(2)')); $r = NormalBot::processInteractive($co, $ctx, '__todos'); check('"Otro lote" pasa al catálogo completo, paginado', isset(filasDe($r)['__mas'])); check('sin perder lo marcado', str_contains(filasDe($r)['1'] ?? '', '✅')); $r = NormalBot::processInteractive($co, $ctx, '__mas'); check('y la página 2 alcanza el lote 12', isset(filasDe($r)['12'])); $r = NormalBot::processInteractive($co, $ctx, '__mas'); // vuelve: no hay página 3 $r = NormalBot::processInteractive($co, $ctx, '__mas'); $r = NormalBot::processInteractive($co, $ctx, '__listo'); check('resumen final', isset(filasDe($r)['__cap_confirm'])); capturas(); NormalBot::processInteractive($co, $ctx, '__cap_confirm'); $post = array_values(array_filter(capturas(), fn($c) => str_contains($c['peticion'] ?? '', 'ciclos_')))[0] ?? null; check('la URL resolvió el tipo elegido', $post['peticion'] ?? null, 'ciclos_cosecha_up'); check('lote_ids como arreglo', $post['body']['lote_ids'] ?? null, ['1', '2']); check('con la acción y la fecha', [$post['body']['accion'] ?? null, $post['body']['fecha'] ?? null], ['apertura', $hoy]); // ════ 5. Mantenimiento: requires/resolver + payload completo ═════════════════ echo "\nMantenimiento — el grupo se pide primero\n"; $ctx = contexto('57300MANT'); $r = NormalBot::processInteractive($co, $ctx, 'registrar_mantenimiento'); check('sin grupo elegido desvía al selector', isset(filasDe($r)['5'])); $r = NormalBot::processInteractive($co, $ctx, '5'); check('y vuelve al flujo: pide la fecha', str_contains(textoDe($r), 'De qué fecha')); $r = NormalBot::processInteractive($co, $ctx, $hoy); check('el lote muestra la cantidad faltante', str_contains(filasDe($r)['4'] ?? '', 'falta 12')); $r = NormalBot::processInteractive($co, $ctx, '4'); check('la labor sale del grupo elegido', filasDe($r), ['77' => 'PLATEO MANUAL']); $r = NormalBot::processInteractive($co, $ctx, '77'); $r = NormalBot::processInteractive($co, $ctx, '412'); $r = NormalBot::processInteractive($co, $ctx, '__listo'); $r = NormalBot::process($co, $ctx, '12'); check('resumen', isset(filasDe($r)['__cap_confirm'])); capturas(); NormalBot::processInteractive($co, $ctx, '__cap_confirm'); $post = array_values(array_filter(capturas(), fn($c) => ($c['peticion'] ?? '') === 'labores_up'))[0] ?? null; check('postea todo lo que labores_up exige', [$post['body']['novedad_id'] ?? null, $post['body']['lote_id'] ?? null, $post['body']['empleados'] ?? null, $post['body']['cantidad'] ?? null], ['77', '4', ['412'], '12']); // ════ 6. Labores fase 2 ═══════════════════════════════════════════════════════ echo "\nLabores diarias — cuadrilla completa\n"; $ctx = contexto('57300LABOR'); $id = ConversationContext::getOrCreate(1, '57300LABOR')['id']; ConversationContext::updateMetadata($id, ['finca' => ['finca_id' => '4', 'finca_label' => 'REPOSO']]); $r = NormalBot::processInteractive($co, $ctx, 'registrar_labor'); $r = NormalBot::processInteractive($co, $ctx, $hoy); check('el catálogo viene filtrado por fase', filasDe($r), ['42' => 'TRACTORISTA', '43' => 'HORAS EXTRA']); $r = NormalBot::processInteractive($co, $ctx, '42'); check('los lotes son los de su finca', isset(filasDe($r)['4']) && isset(filasDe($r)['9'])); $r = NormalBot::processInteractive($co, $ctx, '4'); $r = NormalBot::processInteractive($co, $ctx, '412'); $r = NormalBot::processInteractive($co, $ctx, '415'); $r = NormalBot::processInteractive($co, $ctx, '__listo'); $r = NormalBot::process($co, $ctx, '1'); capturas(); NormalBot::processInteractive($co, $ctx, '__cap_confirm'); $post = array_values(array_filter(capturas(), fn($c) => ($c['peticion'] ?? '') === 'labores_up'))[0] ?? null; check('la cuadrilla viaja como arreglo', $post['body']['empleados'] ?? null, ['412', '415']); // ════ 7. NLU: entity resuelve el grupo y ejecuta el informe ═══════════════════ echo "\nNLU — \"informe de mantenimiento de plateo\" en un mensaje\n"; $ctx = contexto('57300NLU'); $id = ConversationContext::getOrCreate(1, '57300NLU')['id']; ConversationContext::updateMetadata($id, ['finca' => ['finca_id' => '4', 'finca_label' => 'REPOSO']]); ConversationContext::updateNode($id, '__greeted'); AiBot::$respuestas = [[ 'action' => 'route', 'key' => 'ciclo_mantenimiento_top', 'entities' => ['grupo' => 'plateo'], ]]; capturas(); $r = NormalBot::process($co, $ctx, 'quiero informe de mantenimiento de plateo'); check('el informe llegó sin menús intermedios', str_contains(textoDe($r), 'informe-de-prueba')); $get = array_values(array_filter(capturas(), fn($c) => str_contains($c['peticion'] ?? '', 'mantenimiento_top')))[0] ?? null; check('la entity resolvió el grupo en la URL', $get['query']['grupo'] ?? null, '5'); check('y la consulta dice quién pregunta', $get['query']['wa'] ?? null, '57300NLU'); // ════ Resultado ═══════════════════════════════════════════════════════════════ echo "\n" . ($GLOBALS['fallas'] ? "{$GLOBALS['fallas']} falla(s)\n" : "Todos los flujos ejecutan de punta a punta\n"); exit($GLOBALS['fallas'] ? 1 : 0);