feat: mejoras SAT, auth, web y migración
SAT: - Cron diario 6-10 AM con grupos de tenants (~20% por hora). - Retries fijos de daily sync a 9 AM y 4 PM CDMX. - Filtrado de contribuyentes con FIEL vigente en cron. - Timeout de 5 min en cliente HTTP del SAT. - Manejo defensivo de 404, EmptyResult (5004) y solicitudes agotadas. - Fechas formateadas en zona horaria America/Mexico_City. - Patch a @nodecfdi/sat-ws-descarga-masiva para evitar getResponse crash. - Sweep de jobs stale con thresholds ajustados. Auth/Web: - Primer pago de suscripción define periodo activo en webhook. - Rate limit de login: 25 intentos / 15 min. - Recuperación de contraseña: 24h de validez. - Soporte viewingTenantId en contribuyentes. - Timeout y estado de carga al crear organización en Facturapi. - Filtros por cliente y cartera en Mis Asignados. - Orden alfabético en selector de contribuyente. DB: - Migración 057: unique index de declaraciones incluye impuestos.
This commit is contained in:
@@ -161,6 +161,7 @@ export default function CsdConfigPage() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [creatingOrg, setCreatingOrg] = useState(false);
|
||||
const [cerFile, setCerFile] = useState<string>('');
|
||||
const [keyFile, setKeyFile] = useState<string>('');
|
||||
const [password, setPassword] = useState('');
|
||||
@@ -178,16 +179,28 @@ export default function CsdConfigPage() {
|
||||
};
|
||||
|
||||
const handleCreateOrg = async () => {
|
||||
if (creatingOrg) return;
|
||||
setCreatingOrg(true);
|
||||
setMessage(null);
|
||||
try {
|
||||
const cfg = { timeout: 60000 };
|
||||
if (selectedContribuyenteId) {
|
||||
await apiClient.post(`/contribuyentes/${selectedContribuyenteId}/facturapi/org`);
|
||||
await apiClient.post(`/contribuyentes/${selectedContribuyenteId}/facturapi/org`, undefined, cfg);
|
||||
} else {
|
||||
await apiClient.post('/facturacion/org');
|
||||
await apiClient.post('/facturacion/org', undefined, cfg);
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['facturapi-org-contrib'] });
|
||||
setMessage({ type: 'success', text: 'Organización creada en Facturapi' });
|
||||
} catch (err: any) {
|
||||
setMessage({ type: 'error', text: err.response?.data?.message || 'Error al crear organización' });
|
||||
const isTimeout = err?.code === 'ECONNABORTED';
|
||||
setMessage({
|
||||
type: 'error',
|
||||
text: isTimeout
|
||||
? 'La creación está tardando más de lo esperado. Refresca la página en unos segundos; si no aparece, intenta de nuevo.'
|
||||
: (err.response?.data?.message || 'Error al crear organización'),
|
||||
});
|
||||
} finally {
|
||||
setCreatingOrg(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -268,7 +281,9 @@ export default function CsdConfigPage() {
|
||||
<p className="text-sm text-muted-foreground">
|
||||
No hay organización configurada para este tenant.
|
||||
</p>
|
||||
<Button onClick={handleCreateOrg}>Crear Organización</Button>
|
||||
<Button onClick={handleCreateOrg} disabled={creatingOrg}>
|
||||
{creatingOrg ? 'Creando… (puede tardar unos segundos)' : 'Crear Organización'}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2 text-sm">
|
||||
|
||||
Reference in New Issue
Block a user