# Débito automático: editar la tarjeta adherida

## Objetivo
Que un cliente adherido al débito automático pueda cambiar los datos de su tarjeta desde "Suscripción" (`/user/facturacion`) sin darse de baja.

## Problema
- Reportado por el cliente Martijena Pablo (idUser 7283, person 60674) por WhatsApp de soporte: cambia los números de la tarjeta y no se guardan.
- Con la adhesión activa, los campos de la tarjeta se pueden editar, pero el único botón es "CANCELAR ADHESIÓN" (`resources/views/auth/facturacion/index.vue:279-284`).
- No existe ningún endpoint para actualizar: `UserFacturacionController` solo tiene `adhesion()` (insert) y `cancelar_adhesion()` (soft delete); `TaxesAdminTarjetasController` solo lista.
- El usuario también reporta que el atajo "Cancelar + Adherirme" no le guardó. Según el código debería guardar, porque `tusers_tarjetas` vive en la conexión `seguridad` y la transacción se abre en la conexión por defecto (`finance`), así que el insert no se deshace. Falta confirmarlo con datos de producción.
- Los errores no se muestran: `cancelar_adhesion()` en la vista no tiene `catch`, el `catch` de `adhesion()` muestra `error.response.data.errores`, que viene vacío en un 500, y el backend solo atrapa `PDOException` (un fallo del mail da 500).

## Alcance autorizado
- Endpoint nuevo para actualizar la tarjeta del usuario logueado (solo `tarjeta_taxes_id`, `tarjeta_num` y `tarjeta_titular`), con mail de "Cambio de tarjeta".
- Botón "GUARDAR CAMBIOS" en la vista cuando ya hay adhesión, con las mismas validaciones del alta.
- Mostrar el error real en alta, baja y actualización.
- Fuera de alcance: cambiar el contenido del mail de adhesión existente y el guardado de la tarjeta en texto plano. Quedan como observación.

## Restricciones
- Sin commits ni push: el dueño commitea directo a `master`. Además, el working tree tiene cambios de Masters IA de otra sesión.
- No compilar assets (`npm run`) sin pedido explícito.
- Sin escrituras en bases de datos.

## Tareas
- [x] T1 — Backend: `actualizar_tarjeta()` en `UserFacturacionController`, más la ruta `POST /user/facturacion/actualizar_tarjeta`. Ruta: delegada (writer, 2+ archivos no triviales).
- [x] T2 — Frontend: botón "GUARDAR CAMBIOS" y método `actualizar_tarjeta()` en `index.vue`, más `catch` con el mensaje real en alta y baja. Ruta: delegada (mismo writer).
- [x] T3 — Confirmar en producción (solo lectura y con autorización) qué pasó con la tarjeta del usuario 7283. Resuelto en parte: la base confirma que nunca se canceló; los logs no son accesibles con `devreadonly`.

## Criterios de aceptación
- Un usuario adherido cambia tarjeta, número o titular, toca "GUARDAR CAMBIOS" y al recargar ve los datos nuevos.
- Solo se puede actualizar la tarjeta propia: el backend usa `Auth::user()` y nunca un id que mande el cliente.
- Si falla el envío del mail, los datos quedan guardados y el usuario ve un aviso, no un error mudo.
- Las validaciones son las mismas del alta: tarjeta requerida, número de 16 dígitos y titular requerido.

## Checks
- `php -l` sobre el controlador y las rutas.
- `php artisan route:list --path=user/facturacion` para confirmar la ruta nueva.
- Excepción al test-first: no hay un test determinístico corrible. El controlador depende de auth, de dos conexiones MySQL y del envío de mail; `tests/Feature` no tiene cobertura de esto y correrlo pegaría a bases reales.

## Progreso y evidencia
- Mirror de Engram: pendiente (mem_save falla con "host session already ended").
- T1+T2 (writer delegado, sin commit): `php -l app/Http/Controllers/Auth/UserFacturacionController.php` → sin errores; `php -l routes/webs/user.php` → sin errores; `php artisan route:list --path=user/facturacion` → falla por entorno (el constructor de `PspSucursalController` consulta la conexión `psp` y MySQL responde "Access denied, this account is locked"); verificación alternativa con `php artisan tinker` recorriendo `Route::getRoutes()` → aparece `POST user/facturacion/actualizar_tarjeta → UserFacturacionController@actualizar_tarjeta`. Vista no compilada (sin `npm run`, según restricción).

- Control del parent: `php -l app/Http/Controllers/Auth/UserFacturacionController.php` → sin errores; lectura del diff de `actualizar_tarjeta()` → busca solo por `Auth::user()->idUser`, actualiza solo los 3 campos de `$request->only` y el mail va en su propio try/catch.
- Diff: controlador +83, `index.vue` +75 / -6, `routes/webs/user.php` +1.

- T3 (agente de conexión, `devreadonly@137.184.158.50`, solo SELECT):
  - **Tarjeta del cliente:** `tusers_tarjetas` del usuario 7283 tiene una sola fila (id 123, terminación 4730), activa, con `updated_at` y `deleted_at` en NULL. Nunca se canceló ni se insertó otra.
  - **Colas:** ningún `jobs` ni `failed_jobs` relacionado desde el 10/10.
  - **Logins del cliente:** 14/10 15:23 y 15:44; 16/10 09:49.
  - **El atajo funciona:** los usuarios 1095 y 4716 cancelaron y se volvieron a adherir sin problema el 13/10.
  - **Logs:** los de Laravel y nginx no se pueden leer con `devreadonly` (son `forge:adm` 0640).
  - **Conclusión:** el cliente nunca llegó a ejecutar la cancelación, así que nunca vio "ADHERIRME". Puede haber editado los campos sin botón de guardar, no haber confirmado la baja, o la baja falló en silencio (sin `.catch`, ya corregido).
- Hallazgo lateral: el mail de `adhesion()` lleva el número completo de la tarjeta, y como `EmailGenerico` es ShouldQueue, ese número queda en `jobs.payload` y `failed_jobs.payload`.

## Próximo paso
Probar en local la pantalla `/user/facturacion` con un usuario adherido (necesita `npm run` para compilar la vista, a pedido del dueño). T3 queda pendiente de autorización para consultar producción en solo lectura.
