Saltar al contenido principal
Esta guía te explica la estructura y lógica empleadas para generar el reporte CADOC 4111 en XML.
  Estos reportes se rigen por el estándar COSIF y deben coincidir con la estructura XML definida por el BACEN. Puedes adaptar la lógica a tu propio modelo de datos, pero el formato XML debe ser respetado.

¿Qué es CADOC 4111?

El CADOC 4111 se utiliza para presentar información diaria sobre saldos contables, incluyendo activos, pasivos y cuentas de orden, tal como se define en los ítems I y III del Artículo 2 de la Resolución BCB N.º 208, del 22 de marzo de 2022, y la Instrucción Normativa BCB N.º 524, del 18 de septiembre de 2024. Utilizarás Reporter para generar este reporte en XML, empleando tus propios datos.

Estructura CADOC

Formato base

El reporte CADOC debe ser un archivo XML y debe seguir la estructura definida por el BACEN:
<?xml version="1.0" encoding="UTF-8"?>
<documento codigoDocumento="4111" cnpj="99999999" dataBase="AAAA-MM" tipoRemessa="I">
<contas>
<conta codigoConta="1000000009" saldoDia="99.99" />
<conta codigoConta="1100000002" saldoDia="99.99" />
</contas>
</documento>

Campos Obligatorios

Estos campos son requeridos y deben ser incluidos:

<?xml version="1.0" encoding="UTF-8"?>

Siempre inicia el archivo. Define la versión XML y la codificación para que el sistema sepa cómo leer el contenido.

Etiqueta <documento>

Envuelve toda la estructura CADOC e incluye:
  • codigoDocumento: Identifica el tipo de reporte, el cual es 4111.
  • cnpj: Identifica la institución financiera.   - Utiliza solo los primeros 8 dígitos del CNPJ (solo números, sin puntuación).
  • dataBase: Período de reporte, en el formato "AAAA-MM".   - Ejemplo: "2025-01" significa enero de 2025.
  • tipoRemessa: Define el tipo de presentación:   - "I" (Inclusión): Primera presentación para ese período.   - “S”` (Sustitución): Actualización o corrección de datos previamente aceptados.
  Si tu primera presentación fue rechazada debido a errores, aún necesitas usar `“I”` en tu próximo intento. Solo usa `“S”` para reemplazar datos previamente aprobados.

Etiqueta <contas>

Agrupa todas las entradas de cuentas para el período de reporte.

Etiqueta <conta>

  • codigoConta: Código de cuenta, siguiendo el formato COSIF.
  • saldo: Saldo de la cuenta en formato decimal (dos decimales).

Uso de Reporter

Cada organización puede adaptar la plantilla para que se ajuste a su propio modelo de datos, solo reemplaza los nombres de marcador de posición (como midaz_onboarding.account, midaz_transaction.balance, etc.) para que coincidan con tu estructura. La lógica sigue siendo la misma, solo cambian las rutas y nombres de los campos. Aquí tienes un ejemplo funcional que puedes usar como punto de partida:
<documento codigoDocumento="4111"
           cnpj={{ midaz_onboarding.organization.0.legal_document|slice:':8' }}
           dataBase={% date_time "YYYY/MM" %}
           tipoRemessa="I">
  <contas>
    {%- for account in midaz_onboarding.account %}
      {%- with balance = filter(midaz_transaction.balance, "account_id", account.id)[0] %}
        {%- set saldoDia = balance.available %}
        <conta codigoConta="{{ account.id|slice:':10' }}" saldo="{{ saldoDia|floatformat:2 }}"/>
      {% endwith %}
    {% endfor %}
  </contas>
</documento>

Desglose del código

<documento ...>

<documento codigoDocumento="4111"
          cnpj={{ midaz_onboarding.organization.0.legal_document|slice:':8' }}
          dataBase={% date_time "YYYY/MM" %}
          tipoRemessa="I">
Define el documento de nivel superior y los metadatos requeridos.

codigoDocumento="4111"

Indica al BACEN que estás enviando un informe 4111. Obtiene los primeros 8 dígitos del CNPJ de la organización.
  • midaz_onboarding.organization.0.legal_document: Captura el CNPJ de la primera organización en la lista.
  • slice:':8': Lo recorta a los primeros 8 dígitos.

dataBase={% date_time "YYYY/MM" %}

Establece el período del informe dinámicamente.
  • {% date_time "YYYY/MM" %}: Imprime el año y el mes actuales en el momento de la renderización.

tipoRemessa="I"

Indica si se trata de una presentación por primera vez (I) o una corrección (S).

Información de la Cuenta

    {%- for account in midaz_onboarding.account %}
      {%- with balance = filter(midaz_transaction.balance, "account_id", account.id)[0] %}
        {%- set saldoDia = balance.available %}

{% for account in midaz_onboarding.account %}

Itera sobre todas las cuentas asociadas con la lista midaz_onboarding.account.
  • Por cada iteración, crea un nuevo alcance donde account se refiere a un elemento específico de esa lista.

{% with balance = filter(midaz_transaction.balance, "account_id", account.id)[0] %}

Dentro del bucle:
  • Filtra midaz_transaction.balance por account_id para que coincida con el ID de la cuenta actual.
  • [0]: Obtiene el primer saldo coincidente (asumiendo que solo hay uno por cuenta).
  • Lo almacena como una variable temporal balance.

{%- set saldoDia = balance.available %}

  • Recupera el saldo y lo almacena como saldoDia.

Salida de cada etiqueta <conta />

<conta codigoConta="{{ account.id|slice:':10' }}" saldo="{{ saldoDia|floatformat:2 }}"/>
Crea un elemento <conta> por cada cuenta, con dos atributos:
  • codigoConta="{{ account.id|slice:':10' }}": Usa los primeros 10 caracteres del ID de la cuenta; útil si el ID completo es demasiado largo o si la integración requiere una longitud fija.
  • saldo="{{ saldoDia|floatformat:2 }}": Da formato al saldo con exactamente dos decimales.
Aplica siempre el escalado antes de renderizar valores numéricos para garantizar la precisión. Usa floatformat:2 para forzar dos decimales.

Cierre de la plantilla

  </contas>
</documento>
Concluye la lista de cuentas y la estructura del documento.

Ejemplo renderizado

Así es como podría verse el XML final después de renderizarlo:
<?xml version="1.0" encoding="UTF-8"?>
<documento codigoDocumento="4111" cnpj= 78425230 dataBase=2025/06 tipoRemessa="I" >
	<contas>
		<conta codigoConta="0196d9758" saldoDia= "-2500000.00" />
		<conta codigoConta="0196d9720" saldoDia= "499950.00" />
		<conta codigoConta="0196d9761" saldoDia= "500050.00" />
		<conta codigoConta="0196d9779" saldoDia= "500000.00" />
		<conta codigoConta="0196d9797" saldoDia= "500000.00" />
		<conta codigoConta="0196d9725" saldoDia= "500000.00" />
		</contas>
	</documento>

Personalización de la plantilla

Puede ajustar los nombres de los marcadores de posición (como midaz_onboarding.account) para que coincidan con su propio modelo de datos. Solo asegúrese de conservar la estructura XML; esto garantiza que BACEN acepte su archivo.
Siempre valide el XML generado con el esquema de BACEN antes de enviarlo. La estructura por sí sola no es suficiente; los datos deben reflejar el libro mayor real de su institución.
I