diff --git a/services/NormalBot.php b/services/NormalBot.php index ad8cc86..5506683 100644 --- a/services/NormalBot.php +++ b/services/NormalBot.php @@ -711,6 +711,7 @@ class NormalBot $labelField = $flow['label_field'] ?? 'name'; // Auto-detect multi-section if items carry a 'section' key $sectionField = $flow['section_field'] ?? (isset($items[0]['section']) ? 'section' : null); + $descField = $flow['desc_field'] ?? (isset($items[0]['descripcion']) ? 'descripcion' : null); if ($sectionField !== null) { $grouped = []; @@ -719,7 +720,12 @@ class NormalBot if ($id === '') continue; $title = mb_substr((string)($item[$labelField] ?? $id), 0, 24); $sec = mb_substr((string)($item[$sectionField] ?? 'Opciones'), 0, 24); - $grouped[$sec][] = ['id' => $id, 'title' => $title]; + $fila = ['id' => $id, 'title' => $title]; + // El titulo se corta a 24: la descripcion lleva el nombre entero + if ($descField !== null && !empty($item[$descField])) { + $fila['description'] = mb_substr((string)$item[$descField], 0, 72); + } + $grouped[$sec][] = $fila; } $sections = []; foreach (array_slice($grouped, 0, 10, true) as $secTitle => $rows) { @@ -737,7 +743,11 @@ class NormalBot foreach ($visibles as $item) { $id = (string)($item[$valueField] ?? ''); if ($id === '') continue; - $rows[] = ['id' => $id, 'title' => mb_substr((string)($item[$labelField] ?? $id), 0, 24)]; + $fila = ['id' => $id, 'title' => mb_substr((string)($item[$labelField] ?? $id), 0, 24)]; + if ($descField !== null && !empty($item[$descField])) { + $fila['description'] = mb_substr((string)$item[$descField], 0, 72); + } + $rows[] = $fila; } $restantes = count($items) - (($pagina + 1) * $porPagina); diff --git a/setup/seed_palmas.php b/setup/seed_palmas.php index 4841bde..63e1afe 100644 --- a/setup/seed_palmas.php +++ b/setup/seed_palmas.php @@ -444,12 +444,25 @@ $configJson = [ 'display_field' => 'nombre', 'not_found_text' => '⚠️ No encontré ese trabajador. Escribe el nombre de nuevo:', ], + [ + // Primero el grupo general: 17 motivos en una sola lista + // llegaban con el nombre cortado y costaban de entender + 'key' => 'grupo_novedad', + 'label' => 'Tipo', + 'type' => 'select', + 'prompt' => '¿Qué tipo de ausentismo?', + 'source_endpoint_key' => 'novedades_grupos_dn', + 'value_field' => 'id', + 'label_field' => 'nombre', + 'desc_field' => 'descripcion', + ], [ 'key' => 'novedad_id', 'label' => 'Motivo', 'type' => 'select', - 'prompt' => '¿Cuál es el motivo del ausentismo?', + 'prompt' => '¿Cuál es el motivo?', 'source_endpoint_key' => 'novedades_ausentismo_dn', + 'desc_field' => 'descripcion', 'value_field' => 'id', 'label_field' => 'nombre', ], @@ -902,7 +915,8 @@ $endpoints = [ // ── Carga de datos (POST) — Fase 1: Ausentismo ────────────────────────── // El lookup agrega &filtro= a esta URL; estado=1 restringe a activos. ['key' => 'empleados_buscar_dn', 'dir' => 'download', 'url' => $BASE . '?peticion=empleados&estado=1&items=10'], - ['key' => 'novedades_ausentismo_dn', 'dir' => 'download', 'url' => $BASE . '?peticion=novedades_ausentismo_dn'], + ['key' => 'novedades_grupos_dn', 'dir' => 'download', 'url' => $BASE . '?peticion=novedades_ausentismo_dn&grupos=1'], + ['key' => 'novedades_ausentismo_dn', 'dir' => 'download', 'url' => $BASE . '?peticion=novedades_ausentismo_dn&grupo_novedad={grupo_novedad}'], ['key' => 'ausentismos_up', 'dir' => 'upload', 'url' => $BASE . '?peticion=ausentismos_up'], ['key' => 'pluvio_upload', 'dir' => 'upload', 'url' => $BASE . '?peticion=pluvio_upload'], diff --git a/setup/tests/fixtures_api.php b/setup/tests/fixtures_api.php index 1e9b171..b1243d8 100644 --- a/setup/tests/fixtures_api.php +++ b/setup/tests/fixtures_api.php @@ -55,7 +55,22 @@ $fixtures = [ ['id' => '415', 'nombre' => 'JULIO CESAR RAMIREZ'], ['id' => '418', 'nombre' => 'MARIA GOMEZ RUIZ'], ], - 'novedades_ausentismo_dn' => $novedades17, + 'novedades_ausentismo_dn' => (function () { + // Como el ERP: ?grupos=1 devuelve los grupos, ?grupo_novedad=X los suyos + $porGrupo = [ + 'Incapacidad' => [['id'=>'46','nombre'=>'ENFERMEDAD < 3 DIAS','descripcion'=>'INCAPACIDAD ENFERMEDAD < 3 DIAS'], + ['id'=>'47','nombre'=>'ACCIDENTE DE TRANSITO','descripcion'=>'INCAPACIDAD ACCIDENTE DE TRANSITO']], + 'Permiso' => [['id'=>'50','nombre'=>'CITA MEDICA','descripcion'=>'PERMISO CITA MEDICA']], + 'Vacaciones' => [['id'=>'57','nombre'=>'DISFRUTADAS','descripcion'=>'VACACIONES DISFRUTADAS']], + ]; + if (!empty($_GET['grupos'])) { + $out = []; + foreach ($porGrupo as $g => $i) $out[] = ['id'=>$g,'nombre'=>$g,'descripcion'=>count($i).' opcion(es)']; + return $out; + } + $g = trim((string)($_GET['grupo_novedad'] ?? '')); + return $g !== '' ? ($porGrupo[$g] ?? []) : array_merge(...array_values($porGrupo)); + })(), 'novedades_labor_dn' => !empty($_GET['grupo']) ? [['id' => '77', 'nombre' => 'PLATEO MANUAL']] : [ diff --git a/setup/tests/test_flujos.php b/setup/tests/test_flujos.php index ea80153..f9ee913 100644 --- a/setup/tests/test_flujos.php +++ b/setup/tests/test_flujos.php @@ -47,15 +47,20 @@ check('con los tres del catálogo', count(filasDe($r)), 3); $r = NormalBot::processInteractive($co, $ctx, '412'); $filas = filasDe($r); -check('sigue el motivo, paginado: 9 + "Ver más"', count($filas), 10); -check('la última fila es "Ver más"', isset($filas['__mas'])); +check('sigue el tipo, no los 17 motivos de una', + array_keys($filas), ['Incapacidad', 'Permiso', 'Vacaciones']); -$r = NormalBot::processInteractive($co, $ctx, '__mas'); +$r = NormalBot::processInteractive($co, $ctx, 'Incapacidad'); $filas = filasDe($r); -check('la página 2 trae las 8 restantes', count($filas), 8); -check('y ya sin "Ver más"', !isset($filas['__mas'])); +check('el motivo se acota al tipo elegido', array_map('strval', array_keys($filas)), ['46', '47']); +check('sin el prefijo del grupo, entra en los 24 de WhatsApp', + max(array_map('mb_strlen', $filas)) <= 24); +$p = json_decode($r['payload'], true); +$fila0 = $p['interactive']['action']['sections'][0]['rows'][0]; +check('y el nombre completo va en la descripción', + $fila0['description'] ?? null, 'INCAPACIDAD ENFERMEDAD < 3 DIAS'); -$r = NormalBot::processInteractive($co, $ctx, '112'); +$r = NormalBot::processInteractive($co, $ctx, '46'); check('sigue la fecha inicial', str_contains(textoDe($r), 'Desde qué fecha')); $hoy = date('Y-m-d'); $ayer = date('Y-m-d', strtotime('-1 day')); @@ -78,7 +83,7 @@ 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]); + ['412', '46', $hoy, $hoy]); check('y la trazabilidad', $post['body']['telefono'] ?? null, '57300AUSEN'); // ════ 3. Ausentismo según el perfil del número ═══════════════════════════════ @@ -89,8 +94,8 @@ 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')); +check('el trabajador vinculado no se pregunta: arranca por el tipo', + str_contains(textoDe($r), 'tipo de ausentismo')); $ctx = contexto('57300JEFE'); $r = NormalBot::processInteractive($co, $ctx, 'registrar_ausentismo');