Skip to content

Flujos de trabajo

Esta página reúne los flujos de trabajo principales en formato de diagrama para facilitar la comprensión del ciclo de vida completo de un comprobante fiscal electrónico.


Desde la configuración inicial hasta obtener el PDF listo para entregar al cliente.

flowchart TD
  A([Inicio]) --> B[new UruFacturaClient config\nvalida la config y carga el certificado]
  B --> C[RegistrarCaeAsync\nuna vez por CAE]
  C --> G[Describir el comprobante\nnew Cfe tipo · Detalle · Receptor · Referencias]
  G --> H[EmitirAsync]
  H --> V{¿Válido y hay CAE?}
  V -- No --> X[❌ CfeValidationException o CaeException\nno se consume ningún número]
  V -- Sí --> E[CfeEmitido\nnúmero · XML firmado · totales · QR]
  E --> K[EnviarAsync\nsobre EnvioCFE + SOAP/WS-Security]
  K --> L{Acuse del sobre}
  L -- AS\nrecibido --> L2[ConsultarEnvioAsync acuse]
  L -- BS / BA\nrechazado --> N[❌ Revisar acuse.Mensaje\ny reenviar el mismo CfeEmitido]
  L2 -- AE\naceptado --> M[✅ emitido.AceptadoPorDgi]
  L2 -- BE / CE --> N2[❌ emitido.MensajeDgi]
  M --> O[CfePdf.GenerarA4 / GenerarTermico]
  O --> Q([Fin])

Pipeline interno de EmitirAsync y EnviarAsync

Section titled “Pipeline interno de EmitirAsync y EnviarAsync”
sequenceDiagram
  participant App as Tu aplicación
  participant Client as UruFacturaClient
  participant Store as IUruFacturaStore
  participant DGI as DGI (SOAP)

  App->>Client: EmitirAsync(cfe)
  Note over Client: Valida el contenido y copia sus listas
  Client->>Store: ListarCaesAsync()
  Note over Client: Elige el CAE vigente y el próximo número,<br/>arma el XML, calcula totales y firma
  Client->>Store: RegistrarEmisionAsync(emitido, último número leído)
  Note over Store: Avanza el CAE y guarda el CFE en una transacción.<br/>Si otra emisión usó el número: no guarda nada y se renumera
  Client-->>App: CfeEmitido

  App->>Client: EnviarAsync(emitido)
  Client->>Store: ReservarIdEnvioAsync()
  Client->>DGI: EFACRECEPCIONSOBRE (sobre EnvioCFE, WS-Security)
  DGI-->>Client: ACKSobre (AS/BS, IdReceptor, Token)
  Client->>Store: GuardarCfesAsync (IdReceptor y Token)
  Client-->>App: AcuseSobre

flowchart LR
  A[CFE validado y numerado] --> B[Serializar a XML\nesquema DGI]
  B --> C[Calcular digest\nSHA-256 / SHA-1]
  C --> D[Construir SignedInfo\nC14N · enveloped-signature]
  D --> E[Firmar SignedInfo\ncon la clave privada]
  E --> F[Adjuntar certificado\nKeyInfo X509]
  F --> G[CfeEmitido.Xml\nCodigoSeguridad = DigestValue]
  G --> H[Sobre EnvioCFE\n+ SOAP firmado con WS-Security]

stateDiagram-v2
  [*] --> Registrado : RegistrarCaeAsync
  Registrado --> EnUso : EmitirAsync usa el primer número
  EnUso --> EnUso : EmitirAsync\n(UltimoNroUsado + 1)

  EnUso --> AdvertenciaRango : >= 80% del rango usado
  AdvertenciaRango --> Agotado : UltimoNroUsado = RangoHasta

  EnUso --> AdvertenciaVencimiento : <= 7 días para vencer
  AdvertenciaVencimiento --> Vencido : hoy > FechaVencimiento

  Agotado --> [*] : se usa el siguiente CAE vigente
  Vencido --> [*] : se usa el siguiente CAE vigente

Pasos necesarios para pasar de cero a emitir en producción.

flowchart TD
  A([Empresa sin habilitación]) --> B[1. Inscripción\nDGI en línea → Gestión CFE\n→ Inscripción como Emisor Electrónico]
  B --> C{Aprobada?}
  C -- No --> D[Esperar resolución DGI\ngeneralmente días hábiles]
  D --> C
  C -- Sí --> E[2. Obtener certificado digital\nABITAB · Correo Uruguayo · CertiSur\nFormato .p12/.pfx · vinculado al RUT]
  E --> F[3. Solicitar CAE\nDGI en línea → Solicitud de CAE\nPor tipo de CFE y rango]
  F --> G[4. Configurar SDK en Homologación\nAmbiente.Homologacion]
  G --> H[5. Emitir y enviar CFEs de prueba\nEmitirAsync · EnviarAsync]
  H --> I[6. Enviar Reporte Diario de prueba\nEnviarReporteDiarioAsync]
  I --> J[7. Consultar estado de cada CFE\nConsultarEnvioAsync]
  J --> K{Todo OK?}
  K -- No --> L[Corregir errores\nrevisando respuesta.Mensaje]
  L --> H
  K -- Sí --> M[8. Notificar finalización\na DGI vía portal]
  M --> N{DGI aprueba?}
  N -- No --> O[Atender observaciones DGI]
  O --> H
  N -- Sí --> P[9. Cambiar a Producción\nAmbiente.Produccion]
  P --> Q([✅ Habilitado para emitir en producción])

DGI exige enviar un resumen de todos los CFE emitidos cada día.

flowchart TD
  A([Fin de la jornada]) --> B{¿Se emitió\nalgún CFE hoy?}
  B -- No --> C[No es obligatorio\npero recomendable enviar\nreporte vacío]
  B -- Sí --> D[El almacenamiento tiene\nlos CFE emitidos del día]
  D --> F[EnviarReporteDiarioAsync\nfecha]
  F --> E[SDK resume por tipo de CFE\nmontos · cantidades · rangos]
  E --> G[Arma ReporteDiarioCFE y lo firma\nno incluye los XML de los CFE]
  G --> H[POST SOAP EFACRECEPCIONREPORTE]
  H --> I{Respuesta DGI}
  I -- AR\nrecibido --> J[✅ Reporte recibido\nArchivar confirmación]
  I -- BR / BA\nrechazado --> K[❌ Reintentar\nrevisando respuesta.Mensaje]
  K --> F
  J --> L([Fin del día])
  C --> L

Las tres costuras públicas son el cliente, el almacenamiento y el transporte a la DGI. Todo lo demás (XML, firma, sobre, reporte) es interno.

classDiagram
  direction LR

  class IUruFacturaClient {
      <<interface>>
      +RegistrarCaeAsync(cae)
      +EliminarCaeAsync(cae)
      +Validar(cfe) ErrorValidacion
      +EmitirAsync(cfe) CfeEmitido
      +EnviarAsync(cfes) AcuseSobre
      +ConsultarEnvioAsync(acuse) EstadoEnvio
      +ConsultarCfeAsync(cfe) EstadoComprobante
      +EnviarReporteDiarioAsync(fecha) AcuseReporte
  }

  class IUruFacturaStore {
      <<interface>>
      +GuardarCaeAsync(cae)
      +ListarCaesAsync() Cae
      +EliminarCaeAsync(cae) bool
      +RegistrarEmisionAsync(emitido, ultimoLeido) bool
      +ReservarIdEnvioAsync() long
      +GuardarCfesAsync(cfes)
      +BuscarCfesAsync(nroInterno)
      +ListarCfesAsync(fecha)
  }

  class IDgiClient {
      <<interface>>
      +EnviarSobreAsync(xml) AcuseSobre
      +ConsultarEnvioAsync(id, token) EstadoEnvio
      +ConsultarCfeAsync(tipo, serie, nro) EstadoComprobante
      +EnviarReporteAsync(xml) AcuseReporte
  }

  class CfePdf {
      <<static>>
      +GenerarA4(emitido) byte[]
      +GenerarTermico(emitido) byte[]
  }

  IUruFacturaClient <|.. UruFacturaClient
  UruFacturaClient --> IUruFacturaStore
  UruFacturaClient --> IDgiClient
  IUruFacturaStore <|.. InMemoryStore
  IUruFacturaStore <|.. EfUruFacturaStore
  IDgiClient <|.. DgiSoapClient : interno