Reintentar Envíos Fallidos
Exportar contenido
Reenvía masivamente todas las facturas con errores temporales (ERROR o PENDING_RETRY).
- Ve a VeriFactu Dashboard.
- Revisa las facturas con errores en la tabla — columna “VeriFactu”.
- Clic en “Reintentar Fallidas” en la sección Acciones — se abre confirmación.
- Confirma — el sistema reinicia el envío de todas las facturas con error.
- Espera — aparece toast con resultado: “Exitosos: X, Errores: Y”.
- Revisa la tabla actualizada — facturas exitosas cambian a SENT (verde).
Facturas que se reintentan
Sección titulada «Facturas que se reintentan»| Estado actual | Se reintenta | Motivo |
|---|---|---|
| ERROR | Sí | Error temporal recuperable |
| PENDING_RETRY | Sí | Ya en cola, se acelera el reintento |
| FAILED | No | Error permanente (max 5 reintentos agotados) |
| SENT | No | Ya enviada correctamente |
| NULL | No | VeriFactu no activo o borrador |
Como se que lo hice bien
Sección titulada «Como se que lo hice bien»- Toast muestra: “Exitosos: 8, Errores: 2”.
- Las facturas exitosas aparecen con badge SENT (verde).
- Las facturas que siguen con error mantienen badge rojo.
- El contador de “Enviadas” en las tarjetas aumenta.
Errores comunes
Sección titulada «Errores comunes»| Mensaje | Causa | Solución |
|---|---|---|
| ”Sin facturas para reintentar” | No hay facturas con ERROR o PENDING_RETRY | No es necesario reintentar |
| Botón deshabilitado | No hay facturas con errores | Espera a que aparezcan errores |
Detalles tecnicos — Reintentar Envios Fallidos
Sección titulada «Detalles tecnicos — Reintentar Envios Fallidos»Función: handleBulkRetry
Ubicación: VeriFactuDashboard.tsx
Flujo:
- Filtra facturas con
verifactu_status IN ('ERROR', 'PENDING_RETRY') - Para cada factura:
const { data: response, error } = await supabase.functions.invoke('update-invoice-status',{body: {invoice_id: invoice.id,new_status: invoice.status, // Mantiene status actual (sent/paid)},});
- El edge function
update-invoice-statusdetecta quenew_statusno cambia - Vuelve a ejecutar lógica de VeriFactu
- Si éxito:
verifactu_status = 'SENT', incrementasuccessCount - Si error: mantiene
ERROR, incrementaerrorCount - Rate limiting: 500ms entre requests
- Al finalizar, muestra toast y recarga dashboard
Rate limiting:
await new Promise(resolve => setTimeout(resolve, 500));Evita saturar API de VeriFactu con múltiples requests simultáneos.
Edge Function: update-invoice-status (lógica VeriFactu)
Trigger: Cambio de status de factura.
Condiciones para reenviar VeriFactu:
new_status IN ('sent', 'paid')isVeriFactuEnabled(businessId) === true- Factura no está en status SENT ya
Flujo de reintento:
const verifactuService = new VeriFactuService(supabase);const response = await verifactuService.sendInvoice( invoice, business, customer, items);
if (response?.ResultCode === 0) { // Éxito await supabase .from('invoices') .update({ verifactu_status: 'SENT', verifactu_csv: response.Return.CSV, verifactu_qr_code: response.Return.QrCode, verifactu_sent_at: new Date().toISOString(), verifactu_error_code: null, verifactu_error_description: null, }) .eq('id', invoice.id);} else { // Error await supabase .from('invoices') .update({ verifactu_status: 'ERROR', verifactu_error_code: response.Return.ErrorCode, verifactu_error_description: response.Return.ErrorDescription, verifactu_retry_count: (invoice.verifactu_retry_count || 0) + 1, verifactu_last_retry_at: new Date().toISOString(), }) .eq('id', invoice.id);}Cron: verifactu-retry
Trigger: Cada 5 minutos (configurado en Supabase Cron).
Query de facturas pendientes:
SELECT * FROM verifactu_retry_queueWHERE next_retry_at <= NOW() AND retry_count < 5ORDER BY next_retry_atLIMIT 50;Lógica de backoff exponencial:
const delays = [5, 15, 30, 60, 120]; // minutosconst nextRetryMinutes = delays[retry_count] || 120;const next_retry_at = new Date(Date.now() + nextRetryMinutes * 60 * 1000);Marcado como FAILED:
UPDATE invoicesSET verifactu_status = 'FAILED'WHERE id IN ( SELECT invoice_id FROM verifactu_retry_queue WHERE retry_count >= 5);
DELETE FROM verifactu_retry_queueWHERE retry_count >= 5;