ADR 028: Perfil UBL Cortex y hooks de documento¶
Estado¶
Aceptado — 2026-07
Relacionado con ADR 017, ADR 021, ADR 023 y ADR 024.
Contexto¶
Los plugins de negocio (billing, clients, payments, sales, store, ledger) modelan hoy entidades ad hoc en JSON o tablas propias sin contrato de intercambio compartido. Para integración entre plugins, exportación y adaptadores nacionales (p. ej. DIAN en Colombia) hace falta un estándar de documentos de negocio independiente del regulador.
UBL 2.1 (OASIS Universal Business Language) define facturas, notas crédito, órdenes y partes (Party) en XML. DIAN y otros entes consumen perfiles UBL; no son el estándar.
Complemento futuro para actores y contactos: schema.org (Person, Organization, Event) y vCard 4.0 para import/export de contactos.
Decisión¶
Capas¶
| Capa | Paquete | Responsabilidad |
|---|---|---|
| Contrato UBL | cortex-ubl (ubl/cortex_ubl/) | Modelos Pydantic del perfil, nombres de hooks, validación |
| Runtime hooks | cortex_framework.hooks | HookManager: apply_filters, do_action |
| Pipeline | cortex_framework.ubl | UblDocumentPipeline, serialización XML subset |
| Persistencia | Plugins (billing_*) | Tablas propias; columna ubl_snapshot JSONB |
| Adaptadores | Plugins opcionales (dian-adapter) | Perfil nacional, firma, envío |
core y cortex-ubl no importan framework ni plugins.
Perfil Cortex UBL (fase 1)¶
Subset documentado; no UBL 2.1 completo.
| Tipo UBL | Plugin dueño | Fase |
|---|---|---|
Invoice | billing | 1 |
CreditNote | billing | 1.1 |
Order | sales / store | 2 |
Party / CustomerParty | clients | 2 |
Invoice mínimo: ID, IssueDate, DocumentCurrencyCode, AccountingSupplierParty, AccountingCustomerParty, InvoiceLine[], TaxTotal, LegalMonetaryTotal, CustomizationID (vacío en core; perfiles nacionales en adaptadores).
Hooks de documento (filters vs actions)¶
| Hook | Tipo | Uso |
|---|---|---|
ubl.invoice.before_build | action | Preparar contexto |
ubl.invoice.after_build | filter | Mutar InvoiceDocument tras construcción |
ubl.invoice.before_validate | action | — |
ubl.invoice.on_calculate_taxes | filter | Impuestos, descuentos |
ubl.invoice.after_calculate_taxes | action | — |
ubl.invoice.before_serialize | action | — |
ubl.invoice.after_serialize | filter | Ajustar XML/string |
ubl.invoice.issued | action | Puente a billing.invoice.issued (EventDispatcher) |
Los filters mutan el documento en cadena con prioridad. Los actions no sustituyen a EventDispatcher para hechos públicos cross-plugin.
Vocabulario document_type¶
| Término | Dominio | Plugin |
|---|---|---|
IdentityDocumentType | CC, NIT, pasaporte | clients |
FiscalDocumentType | FV, NC | billing |
LedgerDocumentType | FV, CE, NC contable | ledger |
No unificar tablas; unificar semántica en ADR y mapeos UBL.
schema.org y vCard (fase 2)¶
Partyinterno mapeable aschema:Organization/schema:Person.- Export vCard 4.0 desde
clients. - Eventos de dominio con payload inspirado en
schema:Eventdonde aplique.
Fase 1: AccountingCustomerParty con party_id opcional + snapshot textual.
DIAN y adaptadores nacionales¶
Fuera del núcleo. Plugin opcional escucha billing.invoice.issued, aplica CustomizationID Colombia, firma y envía XML. El estándar de negocio permanece UBL.
IO provisional (broadcast y mail)¶
- Broadcast:
Broadcaster+ WebSocket propio; puente aio.ws; escala con Redis pub/sub (ADR 009). Pusher solo como driver opcional, no default. - Notifications: canal
mailvíaNotificationManager; plugins no abren SMTP directo.
Consecuencias¶
billingexponeGET .../ublyPOST .../exportademás del CRUD actual.- Plugins registran
register_ubl_hooksen bootstrap. - Tests TDD en
ubl/tests,framework/tests,plugins/billing/tests.
Referencias¶
- Guía hooks UBL
- Eventos de dominio
- OASIS UBL 2.1: https://docs.oasis-open.org/ubl/os-UBL-2.1/