From 37e4b840d971b8b7f623bd64b3702fbfcff825e9 Mon Sep 17 00:00:00 2001 From: enlineawork Date: Mon, 7 Sep 2026 15:25:40 -0300 Subject: [PATCH] F3.1 WEB: mostrar entregas documentales al Inspector --- web-v2/src/pages/DocumentDeliveryPage.tsx | 150 ++++++++++++++++++++-- 1 file changed, 139 insertions(+), 11 deletions(-) diff --git a/web-v2/src/pages/DocumentDeliveryPage.tsx b/web-v2/src/pages/DocumentDeliveryPage.tsx index 7eb2683..baeaa3c 100644 --- a/web-v2/src/pages/DocumentDeliveryPage.tsx +++ b/web-v2/src/pages/DocumentDeliveryPage.tsx @@ -1,16 +1,144 @@ import { FormEvent, useEffect, useState } from 'react'; +import { useAuth } from '../auth/AuthContext'; import { Alert, LoadingBlock, errorMessage } from '../components/Feedback'; import { Icon } from '../components/Icon'; -import { getDocumentDeliverySettings, listDocumentDeliveries, retryDocumentDelivery, retryPendingDocumentDeliveries, updateDocumentDeliverySettings } from '../lib/api'; +import { + getDocumentDeliverySettings, + listDocumentDeliveries, + retryDocumentDelivery, + retryPendingDocumentDeliveries, + updateDocumentDeliverySettings, +} from '../lib/api'; import type { DocumentDeliveryItem, DocumentDeliverySettings } from '../lib/api'; -import { useAuth } from '../auth/AuthContext'; -const statusLabel:Record={PENDING:'Pendiente',WAITING_RECIPIENT:'Falta destinatario',WAITING_TRANSPORT:'SMTP sin configurar',WAITING_ARTIFACT:'Documento pendiente',SENT:'Enviado',FAILED:'Error'}; -export function DocumentDeliveryPage(){ const {hasPermission}=useAuth(); const canManage=hasPermission('document_delivery.manage'); const [settings,setSettings]=useState(null); const [items,setItems]=useState([]); const [officeEmail,setOfficeEmail]=useState(''); const [directorEmail,setDirectorEmail]=useState(''); const [loading,setLoading]=useState(true); const [saving,setSaving]=useState(false); const [error,setError]=useState(''); const [success,setSuccess]=useState(''); - const load=async()=>{const [s,o]=await Promise.all([getDocumentDeliverySettings(),listDocumentDeliveries()]);setSettings(s);setOfficeEmail(s.officeEmail??'');setDirectorEmail(s.directorEmail??'');setItems(o.data);}; useEffect(()=>{load().catch(e=>setError(errorMessage(e))).finally(()=>setLoading(false));},[]); - const save=async(e:FormEvent)=>{e.preventDefault();setSaving(true);setError('');setSuccess('');try{const s=await updateDocumentDeliverySettings({officeEmail:officeEmail||null,directorEmail:directorEmail||null});setSettings(s);setSuccess('Destinatarios institucionales actualizados');}catch(err){setError(errorMessage(err));}finally{setSaving(false);}}; - const retryAll=async()=>{setSaving(true);setError('');setSuccess('');try{const r=await retryPendingDocumentDeliveries();await load();setSuccess(`Se procesaron ${r.processed} entrega/s pendientes.`);}catch(err){setError(errorMessage(err));}finally{setSaving(false);}}; - if(loading)return ; return
DOCUMENTOS

Entrega documental

Configurá los destinatarios institucionales y controlá el envío automático de Actas e Informes.

{canManage&&}
{error&&{error}}{success&&{success}} -

Destinatarios institucionales

El email de cada empresa se configura dentro de su ficha de Inventario. Las credenciales SMTP permanecen fuera de la base de datos.

{settings?.smtpConfigured?'Servidor de correo configurado':'Servidor de correo pendiente'}{settings?.mailFrom?` · Remitente ${settings.mailFrom}`:' · Falta configurar SMTP_HOST y MAIL_FROM en el servidor.'}

{canManage&&
}
-
TRAZABILIDAD

Últimas entregas

{items.length}
{items.length===0?
Todavía no existen entregas documentales.
:
{items.map(item=>)}
DocumentoDestinoEstadoIntentos
{item.documentKind==='ACT_PDF'?item.actCode:item.reportCode}{item.documentKind==='ACT_PDF'?'Acta PDF':'Informe Word'}{item.recipientAssetName??(item.recipientKind==='COMPANY'?'Empresa sin identificar':item.recipientKind==='OFFICE'?'Oficina':'Director')}{item.recipientEmail??'Sin email configurado'}{statusLabel[item.status]}{item.lastError&&{item.lastError}}{item.attempts}{canManage&&item.status!=='SENT'&&}
}
-
; } +const statusLabel: Record = { + PENDING: 'Pendiente', + WAITING_RECIPIENT: 'Falta destinatario', + WAITING_TRANSPORT: 'SMTP sin configurar', + WAITING_ARTIFACT: 'Documento pendiente', + SENT: 'Enviado', + FAILED: 'Error', +}; + +type DeliveryWithInspector = DocumentDeliveryItem & { + recipientUserId?: string | null; + recipientUserName?: string | null; +}; + +function recipientLabel(item: DeliveryWithInspector): string { + if (item.recipientAssetName) return item.recipientAssetName; + if (item.recipientUserName) return item.recipientUserName; + const kind = String(item.recipientKind); + if (kind === 'COMPANY') return 'Empresa sin identificar'; + if (kind === 'OFFICE') return 'Oficina'; + if (kind === 'INSPECTOR') return 'Inspector responsable'; + return 'Director'; +} + +export function DocumentDeliveryPage() { + const { hasPermission } = useAuth(); + const canManage = hasPermission('document_delivery.manage'); + const [settings, setSettings] = useState(null); + const [items, setItems] = useState([]); + const [officeEmail, setOfficeEmail] = useState(''); + const [directorEmail, setDirectorEmail] = useState(''); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(''); + + const load = async () => { + const [currentSettings, outbox] = await Promise.all([ + getDocumentDeliverySettings(), + listDocumentDeliveries(), + ]); + setSettings(currentSettings); + setOfficeEmail(currentSettings.officeEmail ?? ''); + setDirectorEmail(currentSettings.directorEmail ?? ''); + setItems(outbox.data); + }; + + useEffect(() => { + load().catch((requestError) => setError(errorMessage(requestError))).finally(() => setLoading(false)); + }, []); + + const save = async (event: FormEvent) => { + event.preventDefault(); + setSaving(true); + setError(''); + setSuccess(''); + try { + const currentSettings = await updateDocumentDeliverySettings({ + officeEmail: officeEmail || null, + directorEmail: directorEmail || null, + }); + setSettings(currentSettings); + setSuccess('Destinatarios institucionales actualizados'); + } catch (requestError) { + setError(errorMessage(requestError)); + } finally { + setSaving(false); + } + }; + + const retryAll = async () => { + setSaving(true); + setError(''); + setSuccess(''); + try { + const result = await retryPendingDocumentDeliveries(); + await load(); + setSuccess(`Se procesaron ${result.processed} entrega/s pendientes.`); + } catch (requestError) { + setError(errorMessage(requestError)); + } finally { + setSaving(false); + } + }; + + if (loading) return ; + + return
+
+
+ DOCUMENTOS +

Entrega documental

+

Configurá los destinatarios institucionales y controlá el envío automático de Actas e Informes.

+
+ {canManage && } +
+ {error && {error}} + {success && {success}} + +
+
+
+

Destinatarios institucionales

+

El email de cada empresa se configura dentro de su ficha de Inventario. El Inspector responsable usa automáticamente el email declarado en su Usuario. Las credenciales SMTP permanecen fuera de la base de datos.

+
+
+ + +
+

{settings?.smtpConfigured ? 'Servidor de correo configurado' : 'Servidor de correo pendiente'}{settings?.mailFrom ? ` · Remitente ${settings.mailFrom}` : ' · Falta configurar SMTP_HOST y MAIL_FROM en el servidor.'}

+ {canManage &&
} +
+
+ +
+
TRAZABILIDAD

Últimas entregas

{items.length}
+ {items.length === 0 + ?
Todavía no existen entregas documentales.
+ :
{items.map((baseItem) => { + const item = baseItem as DeliveryWithInspector; + return + + + + + + ; + })}
DocumentoDestinoEstadoIntentos
{item.documentKind === 'ACT_PDF' ? item.actCode : item.reportCode}{item.documentKind === 'ACT_PDF' ? 'Acta PDF' : 'Informe Word'}{recipientLabel(item)}{item.recipientEmail ?? 'Sin email configurado'}{statusLabel[item.status]}{item.lastError && {item.lastError}}{item.attempts}{canManage && item.status !== 'SENT' && }
} +
+
; +}