Skip to content

Mapa de schemas: baseline y objetivo ​

Este documento describe el mapa de schemas para el repositorio actual; el backend actual es NestJS. La propiedad de hechos se conserva. La fundación multi-business ya está implementada; la clasificación de verticales y las separaciones físicas siguientes siguen siendo objetivo. Ningún schema fue renombrado ni dividido en esta entrega.

Capas y dirección de dependencia ​

Las flechas indican consumidor → proveedor. La topología siguiente es objetivo conceptual, no el grafo FK actual.

El core cubre tenant, identidad y capacidades. Los módulos compartidos son capacidades de negocio que se componen por caso de uso. Los servicios transversales no deben incorporar todas las fuentes de negocio como dependencias obligatorias. Una integración tiene relaciones tipadas a sus participantes; no permite mutaciones arbitrarias entre módulos.

Matriz completa de los 41 SQL ​

Las dependencias exactas detectadas y las líneas están en INVENTORY.md e inventory.json. Cada fila explica por qué existe el archivo y qué se hará con él.

SQLPropiedad y caso de usoClasificación objetivoDecisión de refinamiento
0000_extensionsCapacidades PostgreSQL para exclusiones y rangosInstalaciónConservar como bootstrap técnico; comprobar extensión/versiones soportadas
0010_referenceMonedas, países, idiomas y unidades/conversionesBase compartidaConservar; concentrar propiedad de uso de unidades hoy extendida en 0170 sin romper historial
0020_organizationTenant, Business Unit, entidad legal, marca, site, outlet y canalesCoreBusiness Unit y asignaciones efectivas Outlet→BU/Legal Entity implementadas; no confundir BU con Vertical
0030_partyPersona/empresa y contactos tenant-ownedCompartido básicoConservar; cliente/proveedor/empleado son roles externos, sin identidad global B2B automática
0040_identityPrincipales, membresías, permisos y scopesCoreScopes Organization/BU/Legal Entity/Brand/Site/Outlet; resolvers BU y Legal Entity probados contra Outlet
0050_security_rlsHelpers identity y políticas de organization/party/identityInstalación de seguridadNo es schema independiente; resolver localización por propietario y fase de activación
0060_platformVerticales, capacidades, mercados, planes, versiones y suscripcionesCore de productoVertical global y activación por BU implementadas; reserva de provisión idempotente pertenece al control-plane
0070_assetsIdentidad de archivos y copias de almacenamientoTransversalConservar; no obligar a conocer significado de todos sus consumidores. Diseño del módulo en ASSETS_USE_CASES.md. Implementado: el módulo src/modules/assets/ expone rutas para reservar una subida y confirmarla (POST /assets/uploads y POST /assets/uploads/{uploadId}/completion), leer un asset (GET /assets/{assetId}), listar la biblioteca (GET /assets), renombrar (PATCH /assets/{assetId}), archivar (POST /assets/{assetId}/archival) y restaurar (POST /assets/{assetId}/restoration); publica AssetUsageContract y AssetDeliveryContract (src/modules/assets/contracts/), que Catalog ya consume para las imágenes de artículos y la lectura de la caja; el servicio aparte media-worker (src/media-worker.ts) reclama trabajos de la cola propia del módulo (assets.processing_jobs, D31), verifica, sanea y genera las variantes, reintenta los errores de almacenamiento sin tope y los de procesamiento con tope, purga los assets borrables del almacenamiento y del CDN por URL, y la función de runbook assets.requeue_dead_letters reencola los trabajos en dead letter. Los dominios guardan solo asset_id, nunca URL, bucket ni clave; los bytes viajan del cliente al almacenamiento de objetos con un POST prefirmado y nunca por la API; AWS S3 guarda subidas, masters y variantes privadas, y Cloudflare R2 detrás del CDN guarda las variantes públicas, entregadas por URL inmutable. El runtime solo crea y cambia de estado un asset mediante funciones SECURITY DEFINER; un asset referenciado por cualquier dominio nunca se purga; catalog.item_assets es del catálogo y solo pasa por los dos contratos. Pendiente: la entrega private/sensitive por URL firmada de corta vida (A7, bloqueada por OD15) y la generación de imágenes con IA (A8a a A8d, bloqueada por la revisión legal y OD17); la declaración de media-worker en .railway/railway.ts existe en código y la aplica el dueño con railway config plan después de A0
0080_catalogProducto/variante, modificadores, bundles, menús y datos alimentariosCompartido, con extensionesSeparar contenido alimentario opcional; menús/publicación requieren evaluación específica, no traslado automático. Desde la migración 0075 (K1) es dueño también de catalog.catalog_versions, una versión por organización que crea un disparador sobre organization.organizations y suben las escrituras del catálogo, y de catalog.listed_items; las etiquetas genéricas (tags, tag_groups, item_tags, menu_tags y sus traducciones) se eliminaron. Desde la migración 0076 (K2) catalog.items guarda creation_idempotency_key con un índice único parcial por organización. Implementado (con escritor en TypeScript, src/modules/catalog): artículos y su variante por defecto, variantes y su matriz, códigos de barras de variante y su búsqueda, categorías y la clasificación de artículos, grupos y opciones de modificadores y su oferta en artículos (con valores por defecto), el surtido por unidad de negocio (business_unit_catalogs, business_unit_items) e imágenes de artículos (item_assets, solo mediante los contratos de Assets), y desde la migración 0100 (rebanada B1) la composición de combos, kits y paquetes (bundle_groups, bundle_group_items: grupos y opciones con id estable que se retiran en vez de borrarse; el precio sigue en Pricing), y desde la migración 0101 (rebanada M1) la estructura de una carta (menus, menu_sections, menu_entries, menu_entry_variants: secciones con un nivel de subsecciones y entradas que muestran artículos con todas o algunas de sus variantes, con id estable y retiro en vez de borrado, carta en borrador, activa o archivada; el precio por carta es de Pricing y el agotado de Operations), desde la migración 0105 (rebanada M2a) qué cartas muestra un punto de venta y en qué orden (outlet_menus, solo organiza: nunca limita lo que se vende) desde la migración 0106 (rebanada K16) qué artículos del surtido de su unidad de negocio no vende un punto de venta (outlet_hidden_items: excepciones que solo ocultan, nunca agregan; D32) y desde la migración 0107 (rebanada S1) a qué horas muestra el punto de venta cada una de sus cartas (outlet_menu_windows y outlet_menu_window_weekdays: franjas por asignación, en la hora local del sitio, que el servidor evalúa al leer; D33), desde la migración 0108 (rebanada K14a) el límite de cada opción por oferta (item_modifier_group_option_overrides: una fila por oferta y opción con un máximo de 0 a 999; D35) y desde la migración 0109 (rebanada K13a) las dimensiones estructuradas de variante (variant_dimensions, variant_dimension_values, item_variant_dimensions e item_variant_dimension_values: Talla o Color como dato del catálogo, que define las variantes de un artículo con a lo sumo tres dimensiones; D34) y desde la migración 0110 (rebanada K14c) modifier_options admite el tipo text (texto libre del cliente, como un grabado) y guarda solo como indicaciones su largo máximo, su prefijo y si se imprime en el recibo y en el ticket de cocina; no agrega tablas (D36) y desde la migración 0111 (rebanada K15a) item_regulatory_flags declara qué marcas regulatorias tiene un artículo (alcohol, tabaco, receta, farmacia, mercancía peligrosa; D37), item_variants guarda el contenido neto de la etiqueta y las descripciones están acotadas, y desde la migración 0113 (rebanada K15d) item_variant_identifiers guarda los identificadores propios del fabricante de una variante (MPN, ISBN, código del fabricante), uno por esquema y sin unicidad entre variantes (D39). 0112 (rebanada K15c) product_brands guarda las marcas del fabricante del catálogo (Coca-Cola, Bosch) que un artículo puede nombrar con product_brand_id, sin relación con organization.brands (D38). Desde la rebanada K8 el catálogo publica CatalogSellableContract (src/modules/catalog/contracts/), la única puerta por la que sales y pricing podrán leer lo vendible y admitir una variante en una unidad de negocio; ninguno de los dos lee las tablas de catalog directamente. Preparado solo en SQL (sin escritor en TypeScript): traducciones (también las de grupos de bundle y de cartas), alérgenos, etiquetas dietarias y nutrición. Pendiente: sus rebanadas de escritura; la publicación en tienda en línea sigue en Commerce
0090_pricingListas, vigencias, precios y descuentosCompartido comercialConservar; revalidar reglas deterministas, snapshots y limitaciones offline
0100_commerceStorefront, publicaciones, carrito e intención de checkoutCompartido opcionalAislar su vínculo con Sales para que POS no requiera carrito/storefront ficticios
0110_salesVenta, líneas, cancelación/sucesión, cálculos y devolucionesCompartido comercialCongela BU y Legal Entity efectivas; replay offline exige evidencia Sync tardía; extraer dependencia opcional de commerce después
0120_settlementDistribución de una venta en cuentas y asignacionesCompartido comercialConservar cuenta simple por defecto; split avanzado progresivo; no usar como folio hotelero universal
0130_paymentsIntención, intento, resultado, cobro, reverso y reembolsoCompartido financieroPayment Intent congela Legal Entity; hijos preservan el Intent para no perder ownership; efectivo y tarjeta mantienen contratos distintos
0140_operationsMesas/reservas/sesiones y horarios/bloqueos de outletMixtoProponer restaurant_service para atención; availability para horarios/cierres e indisponibilidad comercial explícita
0150_kitchenEstaciones, cursos, batches y trabajo de preparaciónVertical alimentaria/restauranteConservar schema kitchen; puede habilitarse en un hotel con restaurante; no hacerlo infraestructura universal
0160_fulfillmentEntrega, recogida, despacho y ejecución del servicioCompartido con integraciónExtraer enlace a operations.service_sessions; mantener entrega independiente de salón
0170_inventoryCustodia, lotes, reservas, movimientos, conteos y valoraciónCompartido operativoConservar ledger; concentrar reference.quantity_unit_uses en su propietario; verificar saldos, admisión y costo
0180_productionRecetas/formulaciones, consumo y transformación realCompartido productivo opcionalConservar transformación; extraer vínculo kitchen.work_items para producir lotes sin KDS
0190_procurementProveedor, oferta, compra, recepción y devoluciónCompartido operativoConservar; recepción parcial y unidades proveedor; B2B futura no comparte automáticamente sus tablas
0200_crmRelación comercial, preferencias y consentimientosCompartido opcionalConservar; revisar extensiones alimentarias y minimizar copias de datos personales
0210_loyaltyPuntos, programas, reservas y recompensasCompartido opcionalConservar ledger; beneficio offline exige límites explícitos, no saldo global supuesto
0220_receivablesDeuda cliente, aplicaciones, límites y estados de cuentaCompartido financieroConservar; crédito offline requiere capacidad asignada o aprobación online
0230_payablesObligación proveedor y propuestas de pagoCompartido financieroConservar; distinguir recepción, documento proveedor y obligación
0240_cashCustodia de efectivo, caja, conteos y diferenciasCompartido operativoPosting exige mismo Outlet y Legal Entity entre Payment, Shift y Custody; conservar hechos offline y cierre
0250_treasuryBanco/wallet, liquidación de procesadores, FX y conciliaciónCompartido financieroPosting exige misma Legal Entity entre Payment y Financial Account; no confundir Treasury con Payments
0260_taxClasificación, reglas y resultados impositivosCompartido regulatorioConservar; recuperar tablas de 0400 y conciliar llamadas a Fiscal; puentes de sujetos opcionales
0270_fiscalPresencia legal, numeración y contexto regulatorioCompartido regulatorioRecuperar calificaciones/presentación de 0400; capacidad offline no equivale a aceptación de autoridad
0280_invoicingDocumento emitido, snapshots y correccionesCompartido documentalConservar; resolver origen explícito, emisión, pago y representación como hechos separados
0290_accountingLibros, solicitudes de contabilización y asientosCompartido financiero avanzadoConservar motor; separar adaptadores de fuentes, especialmente nómina definida en 0300
0300_workforceEmpleo, asistencia y nóminaCompartido avanzadoRecuperar calendarios de 0400 y extraer cambios del motor accounting; no exigir nómina para imprimir
0310_documentsPlantillas y representaciones inmutablesTransversal con fuentes opcionalesExtraer puentes de fuentes hoy obligatorias, incluidas workforce y accounting
0320_printingImpresoras, rutas, comandos, trabajos e intentosTransversal con integraciónSeparar referencias kitchen; persistencia local y estado de resultado incierto
0330_notificationsIntención y entrega de avisosTransversal con fuentes opcionalesExtraer vínculo de reservas de restaurante y otras fuentes que fuercen instalación
0340_communicationsConversación, participantes e historialCompartido transversalExtraer vínculo de reservas; providers y mapeos siguen en integrations
0350_integrationsConexiones, proveedores, traducción y entregas externasTransversal con adaptadoresSeparar plataforma de conexión de puentes por proveedor/dominio, sin entidad polimórfica canónica
0360_eventsContratos, outbox, entregas y checkpointsTransversalBuen candidato a base temprana; validar dependencias runtime e instalación por transacción. Publica events.append_tenant_event (MODULE_CONTRACTS.md §4.5): Catalog escribe en events solo por esa función, desde la revisión 124
0370_syncDispositivos, comandos, resultados, conflictos y cambiosTransversal con extensionesSeparar enlaces fiscal/printing opcionales; preservar sobre JSON versionado y snapshots coherentes
0380_auditMódulo audit (transversal): evidencia administrativa y de seguridad, propietario único de todo audit.*. identity escribe su rastro de plataforma (contraseña, método de inicio de sesión, sesión, segundo factor, bloqueo de cuenta y códigos de recuperación) exclusivamente a través de PlatformAuditContract (src/modules/audit/contracts/platform-audit.contract.ts); las acciones de tenant escriben audit.records a través de TenantAuditContract (src/modules/audit/contracts/tenant-audit.contract.ts)Transversal con extensionesEvitar que sync completo sea requisito del mínimo de auditoría; no duplicar ledgers
0390_analyticsProyecciones y reportes reconstruiblesMotor transversal + proyecciones por móduloExtraer proyecciones de cocina; no imponer toda la suite para reportar una tienda
0400_cross_domain_contractsCompleta tablas y reglas de ocho schemasInstalación heredadaDistribuir ocho tablas y reglas por propietario; reservar solo orden/finalización técnica realmente necesaria. Aquí vive el invariante que cruza identity, organization y platform: una organización activa y admitida conserva administración, definido en DECISIONS.md

Nuevas separaciones propuestas, no nuevas tablas todavía ​

LímiteAlcanceLo que no posee
restaurant_serviceMesas, áreas de atención, reservas, sesiones, ocupación, depósitos y asignación de personalHabitaciones/estadías, stock o cobros
availabilityHorarios de outlet, excepciones, cierres y bloqueo comercial explícito de varianteStock, reservas hoteleras o un booleano universal de disponibilidad
catalog_foodDeclaraciones alimentarias ligadas a productos: alérgenos, nutrición y dietas, con evidenciaProducto comercial, receta o verdad del consumo físico
Integraciones tipadas opcionalesEj. restaurant_printing une cocina con impresión; restaurant_production une preparación con ejecuciónEstado propietario de los módulos conectados
Colaboración B2B futuraAcuerdos de intercambio, alcances, correlación y mapeos consentidosUn pedido compartido editable por ambos tenants o acceso global a Party

Los nombres de las nuevas integraciones se fijan al implementar un flujo, no se generan decenas de schemas vacíos. catalog_food también puede servir a retail alimentario: específico de alimentos no significa exclusivo de restaurantes. Modificadores y bundles pueden ser comerciales reutilizables. El vínculo entre menú y publicación debe evaluarse a partir de consumidores reales.

Primeras unidades de instalación a demostrar ​

Perfil objetivoResultado visibleBloqueos actuales
CoreAlta de tenant y contexto autorizadoHelpers/RLS repartidos; identity consume platform en funciones; bootstrap no implementado aquí
Core + inventarioEntrada, reserva, traslado, conteo y salida directaHistorial de unidades en 0170; falta probar seguridad y todo el flujo con mínimos reales
Retail mínimoVenta directa y efectivo, sin cocina/salónSales requiere commerce; Payments requiere settlement; impresión arrastra documents y dominios avanzados
Restaurante mínimoVenta, atención opcional, cocina opcional e impresiónSeparar motores compartidos de puentes y probar composición

Ningún perfil se entrega instalable en este PR. El baseline completo se conserva. Extraer un módulo exige revisar tanto FK como funciones, triggers, políticas, bootstrap y consumidores. La ausencia de ciclos en las FK léxicas no demuestra ausencia de dependencias runtime.

Application Foundation in progress. Tracked in issue #13.