fix: 7 de las 17 novedades de ausentismo eran inalcanzables
buildDynamicListResponse cortaba en 10 filas con array_slice y descartaba el resto sin aviso, asi que el catalogo de motivos mostraba 10 de 17 y las otras 7 no habia forma de elegirlas. Ahora pagina: 9 opciones y "Ver mas" con cuantas faltan, hasta agotarlas. El 10 dejo de estar suelto en el codigo y quedo como LISTA_MAX_FILAS, que es el limite de WhatsApp de donde salio el problema. Solo cubre los campos select; dynamic_list lo va a necesitar para los lotes de Ciclos y va con ese trabajo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
f06a400d16
commit
576ea7de40
+29
-1
@@ -3,6 +3,9 @@ declare(strict_types=1);
|
||||
|
||||
class NormalBot
|
||||
{
|
||||
/** Filas máximas de una lista interactiva de WhatsApp. Estaba suelto como 10. */
|
||||
private const LISTA_MAX_FILAS = 10;
|
||||
|
||||
public static function process(array $company, array $context, string $input, bool $suppressFallback = false): ?array
|
||||
{
|
||||
$config = self::getConfig($company);
|
||||
@@ -549,12 +552,28 @@ class NormalBot
|
||||
$sections[] = ['title' => $secTitle, 'rows' => array_slice($rows, 0, 10)];
|
||||
}
|
||||
} else {
|
||||
// Con más opciones que filas disponibles se pagina: el último lugar
|
||||
// queda para "Ver más". Sin esto las sobrantes eran inalcanzables.
|
||||
$pagina = max(0, (int)($flow['__page'] ?? 0));
|
||||
$hayMas = count($items) > self::LISTA_MAX_FILAS;
|
||||
$porPagina = $hayMas ? self::LISTA_MAX_FILAS - 1 : self::LISTA_MAX_FILAS;
|
||||
$visibles = array_slice($items, $pagina * $porPagina, $porPagina);
|
||||
|
||||
$rows = [];
|
||||
foreach (array_slice($items, 0, 10) as $item) {
|
||||
foreach ($visibles as $item) {
|
||||
$id = (string)($item[$valueField] ?? '');
|
||||
if ($id === '') continue;
|
||||
$rows[] = ['id' => $id, 'title' => mb_substr((string)($item[$labelField] ?? $id), 0, 24)];
|
||||
}
|
||||
|
||||
$restantes = count($items) - (($pagina + 1) * $porPagina);
|
||||
if ($hayMas && $restantes > 0) {
|
||||
$rows[] = [
|
||||
'id' => '__mas',
|
||||
'title' => '➕ Ver más',
|
||||
'description' => "Faltan {$restantes}",
|
||||
];
|
||||
}
|
||||
$sections = [['title' => mb_substr($flow['section_title'] ?? 'Opciones', 0, 24), 'rows' => $rows]];
|
||||
}
|
||||
|
||||
@@ -963,6 +982,14 @@ class NormalBot
|
||||
return self::capShowConfirmOrSubmit($cap, $meta, $context, $company, $ctxId);
|
||||
}
|
||||
|
||||
// ── 1b. "Ver más": avanza la página y vuelve a mostrar la misma lista ─
|
||||
if ($value === '__mas') {
|
||||
$cap['__page'][$field['key']] = (int)($cap['__page'][$field['key']] ?? 0) + 1;
|
||||
$meta['__cap'] = $cap;
|
||||
ConversationContext::updateMetadata($ctxId, $meta);
|
||||
return self::capAskNext($cap, $context['from'], $company, $ctxId);
|
||||
}
|
||||
|
||||
// ── 2. User chose "Otra opción" — ask for manual text ────────────────
|
||||
if ($value === '__cap_other') {
|
||||
$cap['__awaiting_other'] = true;
|
||||
@@ -1172,6 +1199,7 @@ class NormalBot
|
||||
'body' => $field['prompt'] ?? ('Selecciona ' . ($field['label'] ?? $field['key'])),
|
||||
'button' => 'Ver opciones',
|
||||
'section_title' => $field['label'] ?? $field['key'],
|
||||
'__page' => (int)($cap['__page'][$field['key']] ?? 0),
|
||||
], $to, $company);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +371,41 @@ check('cancelar sigue cancelando', $rutaFe($esperandoFecha, '__foreach_cance
|
||||
check('con fecha ya elegida no interfiere', $rutaFe($conFecha, 'submenu_ciclos'), 'menus');
|
||||
check('un foreach sin fecha tampoco', $rutaFe(['ask_date' => false], 'submenu_ciclos'), 'menus');
|
||||
|
||||
echo "\nPaginado de listas largas\n";
|
||||
|
||||
/** Espejo del paginado de buildDynamicListResponse() */
|
||||
$paginar = function (array $items, int $pagina, int $max = 10): array {
|
||||
$hayMas = count($items) > $max;
|
||||
$porPagina = $hayMas ? $max - 1 : $max;
|
||||
$filas = array_slice($items, $pagina * $porPagina, $porPagina);
|
||||
$restantes = count($items) - (($pagina + 1) * $porPagina);
|
||||
if ($hayMas && $restantes > 0) $filas[] = '__mas';
|
||||
return $filas;
|
||||
};
|
||||
|
||||
// El caso real: 17 novedades de ausentismo, de las que 7 eran inalcanzables
|
||||
$novedades = array_map(fn($n) => "N{$n}", range(1, 17));
|
||||
|
||||
$vistas = [];
|
||||
$pagina = 0;
|
||||
do {
|
||||
$filas = $paginar($novedades, $pagina);
|
||||
$hayMas = in_array('__mas', $filas, true);
|
||||
foreach ($filas as $f) if ($f !== '__mas') $vistas[] = $f;
|
||||
$pagina++;
|
||||
} while ($hayMas && $pagina < 20);
|
||||
|
||||
check('recorriendo las páginas se llega a todas', count($vistas), 17);
|
||||
check('ninguna se repite', count(array_unique($vistas)), 17);
|
||||
check('ninguna se pierde', array_diff($novedades, $vistas), []);
|
||||
check('termina, no cicla', $pagina <= 3, true);
|
||||
check('la última página no ofrece "ver más"',
|
||||
in_array('__mas', $paginar($novedades, 1), true), false);
|
||||
|
||||
// Con 10 o menos no debe aparecer el botón
|
||||
check('10 opciones entran sin paginar',
|
||||
$paginar(array_slice($novedades, 0, 10), 0), array_slice($novedades, 0, 10));
|
||||
|
||||
echo "\nask_finca\n";
|
||||
$af = $flows['ask_finca'];
|
||||
check('no repregunta si ya hay finca', $af['skip_if_set'] ?? false, true);
|
||||
|
||||
Reference in New Issue
Block a user