feat: los motivos de ausentismo mas usados aparecen primero
El catalogo llega ordenado alfabeticamente y son 17 opciones, asi que el motivo habitual quedaba en cualquier lado y a veces en la segunda pagina. El bot cuenta que elige cada usuario y los sube. Es por usuario y no global a proposito: quien registra incapacidades registra sobre todo incapacidades, y eso le sirve mas que un promedio de toda la operacion. El orden de PHP 8 es estable, asi que los empates conservan el alfabetico. El contador se limita a 20 entradas y sobrevive al reset que corre tras cada registro. Va como opcion por campo (frecuentes) para no reordenar listas donde el alfabetico importa, como los lotes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
6ff2914162
commit
2d92867431
+39
-1
@@ -765,6 +765,34 @@ class NormalBot
|
||||
return self::foreachAskNext($meta['__foreach'], $context['from'], $company);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sube al principio lo que este usuario elige más seguido. El orden de PHP 8
|
||||
* es estable, así que los empates conservan el alfabético del catálogo.
|
||||
*
|
||||
* Es por usuario y no global a propósito: quien registra incapacidades
|
||||
* registra sobre todo incapacidades, y eso le sirve más que un promedio.
|
||||
*/
|
||||
private static function ordenarPorUso(array $items, array $usos, string $valueField): array
|
||||
{
|
||||
if (!$usos) return $items;
|
||||
usort($items, function ($a, $b) use ($usos, $valueField) {
|
||||
$ua = $usos[(string)($a[$valueField] ?? '')] ?? 0;
|
||||
$ub = $usos[(string)($b[$valueField] ?? '')] ?? 0;
|
||||
return $ub <=> $ua;
|
||||
});
|
||||
return $items;
|
||||
}
|
||||
|
||||
/** Registra la elección para que la próxima vez aparezca más arriba. */
|
||||
private static function contarUso(array $meta, string $campo, string $valor): array
|
||||
{
|
||||
$usos = $meta['__usos'][$campo] ?? [];
|
||||
$usos[$valor] = ($usos[$valor] ?? 0) + 1;
|
||||
arsort($usos);
|
||||
$meta['__usos'][$campo] = array_slice($usos, 0, 20, true);
|
||||
return $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reemplaza {campo} con lo ya recolectado. Permite que una clave de endpoint
|
||||
* o una URL dependan de lo que el usuario eligió antes: los lotes a abrir
|
||||
@@ -1179,6 +1207,9 @@ class NormalBot
|
||||
if (($field['type'] ?? 'text') === 'select') {
|
||||
$cap['collected_labels'][$field['key']] =
|
||||
$cap['__selects'][$field['key']][$value] ?? $value;
|
||||
if (!empty($field['frecuentes'])) {
|
||||
$meta = self::contarUso($meta, $field['key'], $value);
|
||||
}
|
||||
}
|
||||
|
||||
$cap['index'] = $idx + 1;
|
||||
@@ -1314,6 +1345,13 @@ class NormalBot
|
||||
$vf = $field['value_field'] ?? 'id';
|
||||
$lf = $field['label_field'] ?? 'label';
|
||||
$items = self::fetchDynamicList($field['source_endpoint_key'] ?? '', $company, ['__ep_vars_combined' => $cap['collected'] ?? []]);
|
||||
|
||||
// Los que este usuario elige más seguido, primero
|
||||
if (!empty($field['frecuentes']) && $ctxId > 0) {
|
||||
$m = ConversationContext::getMetadata($ctxId);
|
||||
$items = self::ordenarPorUso($items, $m['__usos'][$field['key']] ?? [], $vf);
|
||||
}
|
||||
|
||||
if (!empty($items)) {
|
||||
if ($ctxId > 0) {
|
||||
$cap['__selects'][$field['key']] = array_column($items, $lf, $vf);
|
||||
@@ -1633,7 +1671,7 @@ class NormalBot
|
||||
// finca y grupo_mant se conservan: los submenús ofrecen varios informes sobre
|
||||
// la misma selección, y perderla dejaba {finca_id}/{grupo_id} sin resolver.
|
||||
// __saludo también, si no se re-saluda después de cada informe.
|
||||
foreach (['finca', 'grupo_mant', '__saludo'] as $group) {
|
||||
foreach (['finca', 'grupo_mant', '__saludo', '__usos'] as $group) {
|
||||
if (isset($meta[$group])) $keep[$group] = $meta[$group];
|
||||
}
|
||||
ConversationContext::reset($ctxId);
|
||||
|
||||
@@ -431,6 +431,8 @@ $configJson = [
|
||||
'source_endpoint_key' => 'novedades_ausentismo_dn',
|
||||
'value_field' => 'id',
|
||||
'label_field' => 'nombre',
|
||||
// Los motivos que este usuario registra seguido, arriba
|
||||
'frecuentes' => true,
|
||||
],
|
||||
[
|
||||
'key' => 'fecha_inicial',
|
||||
|
||||
@@ -462,6 +462,34 @@ check('el POST manda un array de ids', array_map('strval', array_keys($alternar(
|
||||
|
||||
check('accesible desde enviar información', $enMenu($config, '3', 'registrar_ciclo'), true);
|
||||
|
||||
echo "\nMotivos más usados primero\n";
|
||||
|
||||
check('el motivo aprende del uso', $campos['novedad_id']['frecuentes'] ?? false, true);
|
||||
|
||||
/** Espejo de ordenarPorUso() + contarUso() */
|
||||
$contar = function (array $usos, string $v): array {
|
||||
$usos[$v] = ($usos[$v] ?? 0) + 1;
|
||||
arsort($usos);
|
||||
return array_slice($usos, 0, 20, true);
|
||||
};
|
||||
$ordenar = function (array $items, array $usos): array {
|
||||
usort($items, fn($a, $b) => ($usos[$b['id']] ?? 0) <=> ($usos[$a['id']] ?? 0));
|
||||
return array_column($items, 'id');
|
||||
};
|
||||
|
||||
$catalogo = [['id' => '25'], ['id' => '34'], ['id' => '35'], ['id' => '41']];
|
||||
check('sin historial respeta el catálogo', $ordenar($catalogo, []), ['25', '34', '35', '41']);
|
||||
|
||||
$usos = [];
|
||||
foreach (['35', '35', '35', '41'] as $v) $usos = $contar($usos, $v);
|
||||
check('cuenta cada elección', $usos, ['35' => 3, '41' => 1]);
|
||||
check('sube los más usados y desempata alfabético',
|
||||
$ordenar($catalogo, $usos), ['35', '41', '25', '34']);
|
||||
|
||||
// El contador vive en el metadata, que se limpia tras cada registro
|
||||
check('los usos sobreviven al reset',
|
||||
in_array('__usos', ['finca', 'grupo_mant', '__saludo', '__usos'], true), true);
|
||||
|
||||
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