feat: editar desde el resumen sin rehacer el formulario
Cancelar obligaba a empezar de cero por una fecha mal puesta. El resumen suma un tercer boton —WhatsApp admite tres y usaba dos—: Editar lista los campos ya cargados con su valor, se elige uno, se corrige y se vuelve derecho al resumen. Los campos que alimentan a otros declaran 'invalida' en el seed: cambiar el tipo de ausentismo borra el motivo y lo vuelve a preguntar, acotado al tipo nuevo. Sin eso quedaba un motivo de Incapacidad dentro de un Permiso y el ERP recibia datos incoherentes sin que nadie lo notara. El motor engancha en un solo lugar, capAskNext: mientras queden campos sin valor los pregunta en cadena, y cuando no queda ninguno vuelve al resumen en vez de seguir el orden del formulario. Aplica a los cinco flujos de carga. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
6616b63683
commit
52dbd1e203
@@ -1374,6 +1374,7 @@ class NormalBot
|
||||
'body' => ['text' => $summary],
|
||||
'action' => ['buttons' => [
|
||||
['type' => 'reply', 'reply' => ['id' => '__cap_confirm', 'title' => '✅ Confirmar']],
|
||||
['type' => 'reply', 'reply' => ['id' => '__cap_edit', 'title' => '✏️ Editar']],
|
||||
['type' => 'reply', 'reply' => ['id' => '__cap_cancel', 'title' => '❌ Cancelar']],
|
||||
]],
|
||||
], $company);
|
||||
@@ -1422,6 +1423,32 @@ class NormalBot
|
||||
|
||||
private static function capAskNext(array $cap, string $to, array $company, int $ctxId = 0): ?array
|
||||
{
|
||||
// Editando desde el resumen: se pregunta el primer campo que quedo sin
|
||||
// valor —el que se eligio, mas los que dependian de el— y al completarse
|
||||
// todos se vuelve al resumen en vez de seguir el orden del formulario.
|
||||
if (!empty($cap['__editando'])) {
|
||||
$pendiente = null;
|
||||
foreach ($cap['fields'] as $i => $f) {
|
||||
$k = $f['key'] ?? '';
|
||||
if ($k === '' || isset($cap['collected'][$k])) continue;
|
||||
if (self::capShouldSkip($f, $cap['collected'])) continue;
|
||||
$pendiente = $i;
|
||||
break;
|
||||
}
|
||||
unset($cap['__editando']);
|
||||
if ($pendiente !== null) {
|
||||
$cap['__editando'] = true;
|
||||
$cap['index'] = $pendiente;
|
||||
}
|
||||
$m = $ctxId > 0 ? ConversationContext::getMetadata($ctxId) : [];
|
||||
$m['__cap'] = $cap;
|
||||
if ($ctxId > 0) ConversationContext::updateMetadata($ctxId, $m);
|
||||
|
||||
if ($pendiente === null) {
|
||||
return self::capShowConfirmOrSubmit($cap, $m, ['from' => $to], $company, $ctxId);
|
||||
}
|
||||
}
|
||||
|
||||
// Saltar campos ya pre-llenados (no contiguos)
|
||||
$prefilled = $cap['prefilled'] ?? [];
|
||||
while ((int)$cap['index'] < count($cap['fields'])) {
|
||||
@@ -2163,6 +2190,58 @@ class NormalBot
|
||||
if ($input === '__cap_confirm') {
|
||||
return self::submitCapPost($meta, $context, $company, $ctxId);
|
||||
}
|
||||
// Elegir que corregir sin rehacer todo el formulario
|
||||
if ($input === '__cap_edit') {
|
||||
$cap = $meta['__cap'];
|
||||
$rows = [];
|
||||
foreach ($cap['fields'] as $f) {
|
||||
$k = $f['key'] ?? '';
|
||||
if ($k === '' || !isset($cap['collected'][$k])) continue;
|
||||
$valor = $cap['collected_labels'][$k] ?? $cap['collected'][$k];
|
||||
if (is_array($valor)) $valor = implode(', ', $valor);
|
||||
$rows[] = [
|
||||
'id' => '__cap_ed:' . $k,
|
||||
'title' => mb_substr(self::capFieldLabel($cap['fields'], $k), 0, 24),
|
||||
'description' => mb_substr((string)$valor, 0, 72),
|
||||
];
|
||||
}
|
||||
$rows[] = ['id' => '__cap_ed_volver', 'title' => '↩️ Volver', 'description' => 'Sin cambios'];
|
||||
return self::enqueueInteractive($context['from'], [
|
||||
'type' => 'list',
|
||||
'header' => ['type' => 'text', 'text' => mb_substr($cap['header'], 0, 60)],
|
||||
'body' => ['text' => '¿Qué quieres corregir?'],
|
||||
'footer' => ['text' => ''],
|
||||
'action' => ['button' => 'Ver campos', 'sections' => [[
|
||||
'title' => 'Campos',
|
||||
'rows' => array_slice($rows, 0, self::LISTA_MAX_FILAS),
|
||||
]]],
|
||||
], $company);
|
||||
}
|
||||
if ($input === '__cap_ed_volver') {
|
||||
return self::capShowConfirmOrSubmit($meta['__cap'], $meta, $context, $company, $ctxId);
|
||||
}
|
||||
if (str_starts_with($input, '__cap_ed:')) {
|
||||
$clave = substr($input, strlen('__cap_ed:'));
|
||||
$cap = $meta['__cap'];
|
||||
|
||||
// Un campo alimenta a otros: cambiar el tipo invalida el motivo,
|
||||
// cambiar el lote invalida el producto. Se borran y se vuelven a
|
||||
// preguntar en cadena, si no el ERP recibiria datos incoherentes.
|
||||
$borrar = [$clave];
|
||||
foreach ($cap['fields'] as $f) {
|
||||
if (($f['key'] ?? '') === $clave) {
|
||||
$borrar = array_merge($borrar, (array)($f['invalida'] ?? []));
|
||||
}
|
||||
}
|
||||
foreach ($borrar as $k) {
|
||||
unset($cap['collected'][$k], $cap['collected_labels'][$k]);
|
||||
}
|
||||
|
||||
$cap['__editando'] = true;
|
||||
$meta['__cap'] = $cap;
|
||||
ConversationContext::updateMetadata($ctxId, $meta);
|
||||
return self::capAskNext($cap, $context['from'], $company, $ctxId);
|
||||
}
|
||||
if ($input === '__cap_cancel') {
|
||||
$m = ConversationContext::getMetadata($ctxId);
|
||||
unset($m['__cap']);
|
||||
|
||||
Reference in New Issue
Block a user