← Back to all articles

Errores de validación Peppol BIS 3.0 más comunes y cómo corregirlos

SealDoc Team · · 7 min read

Los fallos de validación de Peppol BIS 3.0 caen en un conjunto predecible de categorías. Los mensajes de error hacen referencia a códigos de reglas de negocio (BR-xx) y números de términos de negocio (BT-xx) del estándar EN16931, que requiere leer la especificación para interpretarlos. Este artículo mapea los fallos más comunes a sus causas y proporciona correcciones concretas.

Todos los ejemplos usan sintaxis UBL 2.1. Para equivalentes en CII, consulta UBL vs CII.

BR-01 a BR-06: campos de cabecera obligatorios ausentes

Estas reglas exigen la presencia de campos obligatorios de nivel superior. Fallan cuando un elemento está ausente o vacío.

ReglaCampoBTCorrección
BR-01Identificador de especificaciónBT-24Añadir CustomizationID con el URI exacto de Peppol BIS 3.0
BR-02Número de facturaBT-1Añadir elemento ID no vacío
BR-03Fecha de emisión de la facturaBT-2Añadir IssueDate en formato YYYY-MM-DD
BR-04Código de moneda de la facturaBT-5Añadir DocumentCurrencyCode con código ISO 4217
BR-05Nombre del vendedorBT-27Añadir AccountingSupplierParty/Party/PartyName/Name
BR-06Nombre del compradorBT-44Añadir AccountingCustomerParty/Party/PartyName/Name

Específico de BR-01: la causa más común es usar el URI base de EN16931 en lugar del URI de Peppol BIS 3.0. Se parecen pero son diferentes:

Incorrecto (base EN16931):

<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>

Correcto (Peppol BIS 3.0):

<cbc:CustomizationID>
  urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
</cbc:CustomizationID>

El validador comprueba la cadena exacta. Consulta la introducción a Peppol BIS 3.0 para el contexto de por qué esto importa.

BR-CO-10: la suma de los importes de línea no coincide con el total

[BR-CO-10]-Sum of Invoice line net amount (BT-106) = 
sum of Invoice line net amount (BT-131).

Esta regla exige que LegalMonetaryTotal/LineExtensionAmount (BT-106) sea igual a la suma de todos los valores InvoiceLine/LineExtensionAmount (BT-131).

El fallo es casi siempre un error de redondeo. Si se redondea cada importe de línea de forma independiente antes de sumar, la suma de los valores redondeados puede diferir de la suma redondeada de los valores brutos.

Incorrecto (redondeo por línea, luego suma):

// Line 1: 3 × 33.333... = 100.00 (rounded)
// Line 2: 3 × 33.333... = 100.00 (rounded)
// Sum of rounded: 200.00
// But raw sum: 3 × 33.333... + 3 × 33.333... = 200.00 exactly in this case

El fallo es más visible con tasas como el 7% de IVA sobre cantidades variables donde el redondeo se acumula en muchas líneas.

Enfoque correcto: sumar los valores brutos sin redondear de todas las líneas, luego redondear el agregado una vez:

var lineNetTotal = invoiceLines.Sum(l => l.Quantity * l.UnitPrice);  // raw
var lineNetTotalRounded = Math.Round(lineNetTotal, 2, MidpointRounding.AwayFromZero);

BR-CO-15: fallo aritmético en el importe del IVA de la factura

[BR-CO-15]-Invoice total VAT amount (BT-110) = 
sum of VAT category tax amount (BT-117).

El importe total del IVA en TaxTotal/TaxAmount debe ser igual a la suma de los valores TaxTotal/TaxSubtotal/TaxAmount de todas las categorías fiscales.

Para una factura de tipo único esto parece trivial, pero los fallos ocurren cuando:

  • Hay varios tipos de IVA y el redondeo se aplica por categoría en lugar de al agregado
  • Hay una categoría de tipo cero o exenta y su TaxAmount es 0.00 en lugar de estar ausente
  • El TaxAmount en el nivel TaxTotal se calcula de forma independiente de los importes TaxSubtotal

Corrección: calcular primero todos los valores TaxSubtotal/TaxAmount, sumarlos y usar esa suma como valor de TaxTotal/TaxAmount. No calcular TaxTotal/TaxAmount por separado.

BR-CO-16: importe pendiente de pago

[BR-CO-16]-Amount due for payment (BT-115) = 
Invoice total with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114).

Si BT-113 (importe pagado) y BT-114 (importe de redondeo) no están presentes, esto se simplifica a BT-115 = BT-112. El fallo ocurre cuando PayableAmount y TaxInclusiveAmount difieren en más de la tolerancia de redondeo permitida.

Causa común: calcular PayableAmount a partir de importes de línea redondeados y TaxInclusiveAmount a partir de un cálculo de total separado que produce un resultado ligeramente diferente.

Corrección: calcular un total bruto canónico, usarlo tanto para TaxInclusiveAmount como para PayableAmount.

BR-S-08 y BR-S-09: coherencia del tipo y el importe del IVA

[BR-S-08]-For each different value of VAT category rate (BT-119) where the 
VAT category code (BT-118) is "S", the VAT category taxable amount (BT-116) 
in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts 
(BT-131) where the VAT category code of the Invoice line (BT-151) is "S" 
and the VAT rate for the Invoice line (BT-152) equals the VAT category rate.

Esta regla agrupa todas las líneas por tipo de IVA y verifica que el importe imponible en cada TaxSubtotal coincida con la suma de las líneas con ese tipo. Falla cuando:

  • Una línea tiene un tipo de IVA que no tiene un TaxSubtotal correspondiente
  • Existe un TaxSubtotal para un tipo pero ninguna línea usa ese tipo
  • Las diferencias de redondeo se acumulan entre los cálculos a nivel de línea y a nivel de subtotal

Corrección: construir los elementos TaxSubtotal dinámicamente a partir de las líneas, agrupando por (código de categoría de IVA, tipo de IVA), en lugar de construirlos de forma independiente.

BR-E-01 / BR-AE-01: facturas con inversión del sujeto pasivo y exentas de impuestos

[BR-E-01]-An Invoice that contains an Invoice line (BG-25), a Document level 
allowance (BG-20) or a Document level charge (BG-21) where the VAT category 
code (BT-151) is "E" shall contain exactly one VAT breakdown...

Las facturas con IVA exento (E), inversión del sujeto pasivo (AE) o tipo cero (Z) requieren estructuras TaxCategory específicas que difieren de las facturas de tipo estándar (S).

Errores comunes:

  • Usar el valor S para todas las líneas independientemente del tratamiento real del IVA
  • Omitir los elementos TaxExemptionReasonCode o TaxExemptionReason requeridos para las categorías exentas
  • Falta AccountingSupplierParty/Party/PartyTaxScheme cuando la factura usa inversión del sujeto pasivo

Para la inversión del sujeto pasivo (AE), el identificador de IVA del esquema fiscal del comprador debe estar presente, y el identificador de IVA del vendedor también debe estar presente.

Reglas de extensión específicas de Peppol: Alemania

Los perfiles Peppol alemanes añaden reglas sobre la base de EN16931. Fallos comunes:

BR-DE-TMP-32: la fecha de entrega (BT-72) es obligatoria para las facturas B2G alemanas. Añadir Delivery/ActualDeliveryDate en formato YYYY-MM-DD.

BR-DE-18: debe estar presente el identificador de IVA del vendedor (BT-31) o un número de registro fiscal (BT-32). La ausencia de ambos causa el rechazo. Si el vendedor está exento de IVA, proporcionar BT-32 con el número de registro fiscal en su lugar.

BR-DE-16: la referencia del comprador (BT-10, Leitweg-ID) es obligatoria para las facturas B2G alemanas. Se valida el formato del Leitweg-ID: debe coincidir con el patrón \d{2,12}-\d{4,12}-\d{2}.

Depuración eficiente

La salida de errores Schematron incluye una ubicación XPath:

<svrl:failed-assert location="/Invoice[1]/cac:LegalMonetaryTotal[1]">
  <svrl:text>[BR-CO-10]-Sum of Invoice line net amounts...</svrl:text>
</svrl:failed-assert>

Usar la ubicación XPath para navegar directamente al elemento que falla. Para las reglas aritméticas, añadir salida de depuración que registre los valores brutos antes del redondeo para rastrear el origen de la discrepancia.

Los archivos XSLT precompilados de las versiones de GitHub de Peppol BIS son los artefactos de validación de referencia. Ejecutarlos con Saxon HE como se describe en generación de facturas Peppol BIS 3.0 en C#. Ejecutar contra la versión más reciente es importante: los conjuntos de reglas se actualizan con cada versión de Peppol BIS, y una regla que pasa contra un XSLT antiguo puede fallar contra el actual.

SealDoc y los errores de validación

SealDoc ejecuta la validación Schematron de EN16931 y Peppol BIS 3.0 en cada factura antes de su entrega. Cuando la validación falla, la API devuelve una respuesta de error estructurada que mapea cada fallo a su código BR, el BT violado y la ubicación XPath en el documento enviado.

Para las organizaciones que depuran un proceso de generación de facturas existente, el validador público de SealDoc acepta archivos de factura UBL y CII, ejecuta el XSLT actual de Peppol BIS 3.0 y devuelve la lista completa de fallos con descripciones en lenguaje claro. Los conjuntos de reglas se mantienen actualizados con las versiones de Peppol BIS, de modo que el validador siempre refleja las reglas que aplicará un Punto de Acceso receptor.


← Back to all articles