Errores de validación Peppol BIS 3.0 más comunes y cómo corregirlos
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.
| Regla | Campo | BT | Corrección |
|---|---|---|---|
| BR-01 | Identificador de especificación | BT-24 | Añadir CustomizationID con el URI exacto de Peppol BIS 3.0 |
| BR-02 | Número de factura | BT-1 | Añadir elemento ID no vacío |
| BR-03 | Fecha de emisión de la factura | BT-2 | Añadir IssueDate en formato YYYY-MM-DD |
| BR-04 | Código de moneda de la factura | BT-5 | Añadir DocumentCurrencyCode con código ISO 4217 |
| BR-05 | Nombre del vendedor | BT-27 | Añadir AccountingSupplierParty/Party/PartyName/Name |
| BR-06 | Nombre del comprador | BT-44 | Añ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
TaxAmountes0.00en lugar de estar ausente - El
TaxAmounten el nivelTaxTotalse calcula de forma independiente de los importesTaxSubtotal
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
TaxSubtotalcorrespondiente - Existe un
TaxSubtotalpara 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
Spara todas las líneas independientemente del tratamiento real del IVA - Omitir los elementos
TaxExemptionReasonCodeoTaxExemptionReasonrequeridos para las categorías exentas - Falta
AccountingSupplierParty/Party/PartyTaxSchemecuando 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.