Salta al contingut principal
B2Brouter · Odoo 19 · Compliance

B2Brouter i Odoo: Facturae, VeriFactu i a qui li toca ser l'emissor legal

Abans d'integrar B2Brouter amb Odoo cal decidir una cosa que no és tècnica: quin sistema expedeix la factura. L'article 9 del RD 1007/2023 deixa poc marge, i aquesta decisió determina la resta de l'arquitectura.

B2Brouter és una xarxa d'enviament de documents electrònics, no el teu sistema de facturació. Sembla obvi i no ho és: aquesta frase decideix què pots delegar i què es queda a Odoo. Amb VERI*FACTU, el sistema que expedeix la factura té obligacions que no es compleixen enviant un XML a un tercer, i el reglament ho diu amb hora.

Què resol B2Brouter i què no

És una plataforma d'intercanvi de documents electrònics: punt d'accés Peppol, FACe a Espanya, SDI a Itàlia, Chorus Pro a França, KSeF a Polònia, ZATCA i MyInvois fora d'Europa. Per a Espanya hi afegeix VERI*FACTU, SII i TicketBAI. Tècnicament, una API REST amb una capçalera d'autenticació (X-B2B-API-Key), versionat per data (X-B2B-API-Version, avui 2026-06-26) i tot penjant de /accounts/{id}/…; la seva especificació OpenAPI pública declara 56 rutes i 81 operacions.

El que sí que et treu de sobre és el certificat: està donat d'alta com a col·laborador social en la gestió tributària, de manera que per remetre a l'AEAT n'hi ha prou amb la seva clau d'API. El que no et treu de sobre és la numeració de les teves factures, les rectificatives, el calendari fiscal i (la important) la condició d'emissor.

Qui és l'emissor legal

El Reial decret 1007/2023 anomena sistema informático de facturación el conjunt de maquinari i programari utilitzat per expedir factures. No el que les transporta. I l'article 9, sencer, diu això:

«Los sistemas informáticos de facturación que sean utilizados por los obligados tributarios a que se refiere el artículo 3 de este Reglamento, deberán generar automáticamente un registro de facturación de alta de forma simultánea o inmediatamente anterior a la expedición de cada factura.»

Article 9 del Reglament aprovat pel Reial decret 1007/2023 (BOE-A-2023-24840).

Simultània o immediatament anterior. No hi ha «immediatament després», ni «aquella mateixa nit», ni «quan el cron sincronitzi». Si Odoo valida la factura a les 11:04 i un procés nocturn la bolca a les 23:00 perquè un tercer generi el registre, el disseny està malament, encara que l'XML acabi arribant a l'AEAT.

Delegar es pot: l'article 6 permet que les obligacions «podrán cumplirse materialmente por el destinatario de la operación o por un tercero», però afegeix que això «no exime a los obligados tributarios… de la responsabilidad del cumplimiento». Pots delegar la feina; la responsabilitat, no.

La conseqüència pràctica és només una: la factura ha de néixer i numerar-se en un únic lloc, i el registre s'ha de generar en aquest mateix acte. Si Odoo és on es valida la factura, Odoo és l'emissor. La resta és transport.

Què s'ha de quedar a Odoo

  • La numeració i les sèries. Un número assignat en dos sistemes és un incident esperant data.
  • La immutabilitat. L'article 8.2.a) exigeix que qualsevol correcció es faci «mediante al menos un registro de facturación adicional posterior». A Odoo, «restablecer a borrador» sobre una factura registrada deixa de ser una opció.
  • La traçabilitat. Els articles 1 i 8.1 demanen integritat, conservació, traçabilitat i inalterabilitat. Això és un registre d'esdeveniments, no un log que rota cada set dies.
  • La declaració responsable. L'article 13 exigeix que consti «por escrito y de modo visible en el propio sistema informático en cada una de sus versiones», i l'atribueix al productor del sistema. Si qui expedeix és Odoo amb els teus mòduls, parla d'aquest conjunt.

El preu d'equivocar-se no és teòric: l'article 201 bis de la Ley General Tributaria sanciona amb 50.000 € per exercici la mera tinença de sistemes de facturació no certificats quan ho hagin de ser. La disposició final quarta del reial decret fixa les dates: contribuents de l'Impost sobre Societats abans de l'1 de gener de 2027; la resta, abans de l'1 de juliol de 2027.

Registre d'esdeveniments d'un SIF a Odoo 19 amb l'alta del sistema i la declaració responsable de la versió
Registre d'esdeveniments d'una instal·lació nova a Odoo 19: alta del sistema i declaració responsable d'aquesta versió.

Facturae, FACe i el B2B privat: tres camins diferents

Facturae i FACe són el sector públic. La Llei 25/2013 exigeix «un formato estructurado» signat amb «firma electrónica avanzada basada en un certificado reconocido» (art. 5) i crea el punt general d'entrada (art. 6). A la pràctica el problema mai és el format, són els tres codis DIR3 (oficina comptable, òrgan gestor i unitat tramitadora): si en falta un, el rebutja el punt d'entrada, no el client. A l'API de B2Brouter són cin1, cin2 i cin3 amb esquema 8014, transport es.face i format xml.facturae.3.2; si l'XML importat ja compleix, l'envien tal qual, i si ve sense signar el signen ells.

La factura electrònica B2B és una altra cosa i encara no ha començat. El Reial decret 238/2026 (BOE-A-2026-7295) fixa el model EN 16931 i quatre sintaxis: CII, UBL, EDIFACT i Facturae. El termini no compta des del reglament sinó des de l'ordre ministerial de la Solución Pública de Facturación Electrónica (un any per a qui factura més de 8 milions, dos per a la resta), i el rellotge no arrenca fins que aquesta ordre entri en vigor.

VERI*FACTU ni és un format ni és un enviament al client: és un registre paral·lel de cada factura, generat en expedir-la. I els dos règims no s'exclouen: l'article 2 bis.6 de la Llei 56/2007 exigeix que els programes de factura electrònica compleixin també l'article 29.2.j) de la Ley General Tributaria, que és d'on penja VERI*FACTU. S'acumulen. Si vens de zero, comença per què és VERI*FACTU i com complir-lo amb Odoo.

Què s'envia des d'Odoo i què torna

Cap a fora va la factura com a JSON, amb numeració, dates, impostos, imports i els codis d'enrutament del destinatari. El detall que més temps costa és quadrar els cèntims: si deixes que la plataforma recalculi les bases a partir de quantitat × preu, una línia amb descompte acabarà sortint amb un cèntim de diferència respecte a Odoo.

Cap a dins torna l'estat, i aquí hi ha l'error més repetit. L'API distingeix 22 estats de lectura i només 9 que puguis fixar tu:

EstatQuè significa de debòQui el posa
sentEl document ha sortit pel transportLa xarxa
registeredHi ha resposta d'una administració tributàriaL'administració
acceptedAlgú de l'altre costat l'ha donat per boEl client
refused / errorRebuig, o fallada d'enviamentTots dos costats

Col·lapsar-los en un únic booleà «enviat» és còmode el primer dia i car el dia que algú pregunta, vuit mesos després, si aquella factura va arribar a l'administració. I un matís que només s'aprèn en producció: una resposta correcta no vol dir transmès. La crida d'enviament retorna 204 i el lliurament continua sent asíncron; i hi ha respostes de 200 que porten errors a dins, en un errors[] que ningú mira. La tornada va per webhook signat amb HMAC-SHA256, sense política de reintents documentada: un webhook perdut és un estat que mai s'actualitza, de manera que calen deduplicació i un cron de sondeig de reserva.

L'empremta encadenada i per què es calcula malament

El registre d'alta no és la factura: són vuit camps encadenats amb l'anterior mitjançant una empremta SHA-256. L'article 13.1 de l'Ordre HAC/1177/2024 en llista l'ordre (NIF de l'emissor, número i sèrie, data d'expedició, tipus de factura, quota total, import total, empremta anterior i data-hora-fus), però l'apartat 2 remet «l'algoritme i la codificació» a un document tècnic de la seu de l'AEAT. El BOE et dona una llista ordenada; no et dona el format.

Si et quedes al BOE, el natural és concatenar els vuit valors i aplicar SHA-256. És exactament el que vam fer al nostre propi mòdul de VERI*FACTU, i està malament. L'especificació de l'AEAT exigeix parells etiquetats clave=valor units per &:

IDEmisorFactura=B12345678&NumSerieFactura=FA/2026/0001&FechaExpedicionFactura=15-06-2026
&TipoFactura=F1&CuotaTotal=21.00&ImporteTotal=121.00&Huella=
&FechaHoraHusoGenRegistro=2026-06-15T11:04:33+02:00

SHA-256 en hexadecimal i majúscules sobre aquesta cadena. I compte amb el penúltim camp: al primer registre, Huella va buit. Nosaltres l'havíem sembrat amb 64 zeros, que és el que un escriu per instint. Va ser la segona fallada, trobada dos dies després de la primera.

Què ho delatava: res

La suite estava verda. Una fallada d'empremta no s'assembla a una fallada normal: cada empremta continua sent un hexadecimal de 64 caràcters vàlid, la cadena s'enllaça amb si mateixa sense cap forat, i la verificació d'integritat del mòdul passa (perquè recalcula amb la mateixa fórmula equivocada). El test que ho havia d'haver enxampat era aquest:

def test_genesis_huella_anterior(self):
    genesis = self.cadena.genesis_id
    if genesis:
        self.assertEqual(genesis.huella_anterior, '0' * 64,
                         'Genesis record must have all-zeros huella_anterior')

Dos defectes en quatre línies: el if genesis: el converteix en un aprovat automàtic quan no hi ha registre gènesi, i la constant que comprova és precisament l'equivocada. Un test buit que a més codificava l'error. Ara és així:

def test_genesis_huella_anterior(self):
    self._make_invoice()
    genesis = self.cadena.genesis_id
    self.assertTrue(genesis, 'Expected the first posted invoice to become the genesis record')
    self.assertEqual(genesis.huella_anterior, '',
                     'Genesis record must have empty huella_anterior per AEAT spec')

La regla que va quedar: un test que cau si esborres el codi que protegeix és un test; la resta és decoració.

Contrasta la teva empremta amb l'exemple resolt que publica l'AEAT abans d'emetre la primera factura: l'article 8.2.a) impedeix reescriure registres ja generats, de manera que una cadena mal calculada no s'arregla, s'arrossega.

Llista buida de registres de facturació a Odoo 19 amb les columnes número, número de sèrie, data d'expedició, tipus de factura i estat
El registre de facturació a Odoo 19 recent instal·lat: les columnes són les del reglament i, com avisa la mateixa llista buida, cada fila neix en validar una factura, no en enviar-la.

Quan B2Brouter et sobra i quan t'estalvia mesos

  • T'estalvia mesos si envies a més d'un país o xarxa, tens clients del sector públic amb codis DIR3, no vols custodiar un certificat qualificat o vols una capa que ja parli les quatre sintaxis de Crea y Crece.
  • Et sobra si factures només a Espanya, sense administracions com a clients, i l'única cosa que t'obliga és VERI*FACTU: aquí un mòdul que encadeni i remeti des d'Odoo fa la feina sense afegir un salt de xarxa, un cost per transacció ni un segon lloc on mirar quan alguna cosa falla.

La incompatibilitat que ningú t'explica

Si tries B2Brouter per a VERI*FACTU, no pots mantenir alhora la teva pròpia cadena a Odoo. L'ajust és de compte, no de factura: un cop actiu, encadena totes les factures d'aquest compte. I si importes un XML que ja porta empremta, la descarten; la seva documentació ho diu sense embuts: aquesta informació s'ignora i el seu sistema fa igualment el procés d'encadenament. És la decisió correcta (una cadena amb dos autors no és una cadena), però implica que les dues solucions s'exclouen per empresa: si hi conviuen, l'AEAT rep dues sèries de registres per a les mateixes factures.

Al connector que hem construït contra la seva API això és una exclusió dura: o una o l'altra, mai les dues. El mòdul porta una única suite de 778 tests, la mateixa a les tres branques, i cadascuna es tanca executant-la contra un Odoo real de la seva versió: 19, 18 i 17. El camí d'enviament està exercitat contra el seu entorn de proves fins a registered, amb els camins de rebuig i d'error inclosos. Per aquí va aparèixer que el mòdul ni tan sols s'instal·lava a la 17: un xpath heretat apuntava a la plantilla kanban card, el nom de la 18 endavant (la 17 la diu kanban-box), i un xpath que no troba la seva destinació tomba la instal·lació sencera. La branca 17 va arrencar zero tests. Un mòdul que compila no és un mòdul que s'instal·la.

Connectar el teu programari amb OdooCom treballem amb partners tecnològics que necessiten un connector d'Odoo.Integracions i automatitzacióIntegracions fiscals i de marketplace sobre Odoo 17, 18 i 19.Què és VERI*FACTU i com complir-loEl reglament, els terminis i què mirar al teu Odoo abans de 2027.e-Factura i SAF-T de RomaniaEl mateix problema en un altre país: registre, enviament i estat de tornada.

Preguntes freqüents

B2Brouter substitueix un mòdul de VERI*FACTU a Odoo?

El substitueix com a motor d'encadenament i remissió, no com a sistema emissor: l'article 9 del RD 1007/2023 exigeix que el registre es generi de forma simultània o immediatament anterior a l'expedició, i qui expedeix continua sent Odoo. A més, les dues solucions s'exclouen per empresa.

Puc enviar les factures a B2Brouter amb un cron nocturn?

Per al document (Peppol, FACe, correu) sí, dins del termini de cada canal. Per al registre de VERI*FACTU no: l'article 9 només admet «simultánea o inmediatamente anterior» a l'expedició.

Facturae i factura electrònica B2B són el mateix?

No. Facturae signada amb signatura electrònica avançada és el que exigeix la Llei 25/2013 per facturar a administracions públiques. La factura electrònica B2B del RD 238/2026 admet quatre sintaxis sobre el model EN 16931, i el seu termini encara no ha començat a comptar.

Quin estat he de guardar a Odoo?

Els tres per separat: transport (sent), administració (registered) i client (accepted o refused). L'API en distingeix 22 de lectura i només 9 que es puguin fixar a mà.

El que fem sobre això

Connector B2BrouterQuè fa, captures, versions i preu.

Integres B2Brouter amb Odoo?

Mirem la teva numeració, les teves sèries, el moment en què es genera el registre i els estats que tornen, i et diem què es queda a Odoo i què pot anar-se'n a la xarxa. Reserva una trucada a Calendly o truca'ns al +34 616 809 504.

Parlar amb un enginyer