erp-core/orchestration/inventarios/DATABASE_INVENTORY.yml
rckrdmrd 4c4e27d9ba feat: Documentation and orchestration updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:35:20 -06:00

858 lines
33 KiB
YAML

# DATABASE_INVENTORY.yml - ERP Core
# Inventario canonico de objetos de base de datos
# Ubicacion Canonica: orchestration/inventarios/
# Ultima actualizacion: 2026-01-07
version: "3.0"
project: erp-core
updated_at: "2026-01-07"
updated_by: Backend-Agent (Sprint 6-7)
# =============================================================================
# CONFIGURACION DE MOTOR
# =============================================================================
engine:
name: PostgreSQL
version: "15+"
extensions:
- name: uuid-ossp
purpose: Generacion de UUIDs
- name: pg_trgm
purpose: Busqueda fuzzy por trigram
- name: btree_gist
purpose: Indices GiST para exclusion
- name: pgcrypto
purpose: Funciones criptograficas
# =============================================================================
# RESUMEN
# =============================================================================
summary:
total_schemas: 14
total_tables: 191
total_tables_base: 118
total_tables_extensions: 73
total_functions: 70
total_triggers: 100
total_rls_policies: 102
total_ddl_files: 20
implemented_extensions: 6
documented: 30
# =============================================================================
# POLITICA DE CARGA LIMPIA
# =============================================================================
clean_load_policy:
directiva: "core/orchestration/directivas/legacy/DIRECTIVA-POLITICA-CARGA-LIMPIA.md"
principio: "DDL-First - Los archivos DDL son la fuente de verdad"
prohibiciones:
- "Ejecutar ALTER TABLE directo en BD sin actualizar DDL"
- "Crear carpeta migrations/"
- "Crear archivos fix-*.sql, patch-*.sql, hotfix-*.sql"
- "Dejar BD y DDL desincronizados"
paths:
db_ddl_path: "database/ddl"
db_scripts_path: "database/scripts"
db_seeds_path: "database/seeds"
db_name: "erp_generic"
comandos:
crear: "./scripts/create-database.sh"
recrear: "./scripts/reset-database.sh"
eliminar: "./scripts/drop-database.sh"
seeds_dev: "./scripts/load-seeds.sh dev"
seeds_prod: "./scripts/load-seeds.sh prod"
# =============================================================================
# ARCHIVOS DDL IMPLEMENTADOS
# =============================================================================
ddl_files:
orden_ejecucion:
1: "00-prerequisites.sql"
2: "01-auth.sql"
3: "01-auth-extensions.sql"
4: "01-auth-mfa-email-verification.sql"
5: "02-core.sql"
6: "02-core-extensions.sql"
7: "03-analytics.sql"
8: "04-financial.sql"
9: "05-inventory.sql"
10: "05-inventory-extensions.sql"
11: "06-purchase.sql"
12: "07-sales.sql"
13: "08-projects.sql"
14: "09-system.sql"
15: "09-system-extensions.sql"
16: "10-billing.sql"
17: "11-crm.sql"
18: "12-hr.sql"
19: "13-audit.sql"
20: "14-reports.sql"
extensiones_nuevas:
- archivo: "01-auth-extensions.sql"
fecha: "2025-12-08"
estado: IMPLEMENTADO
specs:
- SPEC-TWO-FACTOR-AUTHENTICATION.md
- SPEC-SEGURIDAD-API-KEYS-PERMISOS.md
- SPEC-OAUTH2-SOCIAL-LOGIN.md
tablas: 16
funciones: 6
vistas: 2
triggers: 3
detalle:
groups_herencia: [auth.groups, auth.group_implied, auth.user_groups]
acl: [auth.models, auth.model_access, auth.record_rules, auth.rule_groups, auth.model_fields, auth.field_permissions]
api_keys: [auth.api_keys]
two_factor: [auth.trusted_devices, auth.verification_codes, auth.mfa_audit_log]
oauth2: [auth.oauth_providers, auth.oauth_user_links, auth.oauth_states]
- archivo: "05-inventory-extensions.sql"
fecha: "2025-12-08"
estado: IMPLEMENTADO
specs:
- SPEC-VALORACION-INVENTARIO.md
- SPEC-TRAZABILIDAD-LOTES-SERIES.md
- SPEC-INVENTARIOS-CICLICOS.md
tablas: 10
funciones: 7
vistas: 3
triggers: 4
detalle:
valoracion_svl: [inventory.stock_valuation_layers, inventory.category_stock_accounts, inventory.valuation_settings]
lotes_series: [inventory.lots, inventory.move_line_consume_rel, inventory.removal_strategies]
conteos_ciclicos: [inventory.inventory_count_sessions, inventory.inventory_count_lines, inventory.abc_classification_rules, inventory.product_abc_classification]
- archivo: "01-auth-mfa-email-verification.sql"
fecha: "2026-01-07"
estado: IMPLEMENTADO
sprint: 5
specs:
- Sprint 5: MFA Implementation
- Sprint 5: Email Verification Flow
tablas: 2
detalle:
mfa: [auth.user_mfa_secrets]
email_verification: [auth.email_verification_tokens]
- archivo: "02-core-extensions.sql"
fecha: "2026-01-07"
estado: IMPLEMENTADO
sprint: 6
specs:
- BE-013: Currency Exchange Rates
tablas: 1
detalle:
currency: [core.currency_rates]
- archivo: "09-system-extensions.sql"
fecha: "2026-01-07"
estado: IMPLEMENTADO
sprint: 6
specs:
- BE-016: Settings Service 3-Level
tablas: 3
funciones: 1
triggers: 3
detalle:
settings: [system.system_settings, tenants.tenant_settings, auth.user_preferences]
caracteristicas:
- Cascada 3 niveles (User -> Tenant -> System)
- RLS Policies por tenant y usuario
- Seed data con configuraciones base
- archivo: "13-audit.sql"
fecha: "2026-01-07"
estado: IMPLEMENTADO
sprint: 7
specs:
- BE-017: Audit Trail
- BE-018: Access Logs
- BE-019: Security Events
tablas: 3
funciones: 3
detalle:
audit: [audit.audit_logs, audit.access_logs, audit.security_events]
enums:
- audit.audit_action (INSERT, UPDATE, DELETE)
- audit.access_event_type (LOGIN_SUCCESS, LOGIN_FAILED, LOGOUT, etc)
- audit.security_severity (LOW, MEDIUM, HIGH, CRITICAL)
caracteristicas:
- Funciones de limpieza automatica
- Indices optimizados para consultas
- Partial indexes para filtros comunes
- archivo: "14-reports.sql"
fecha: "2026-01-07"
estado: IMPLEMENTADO
sprint: 8
specs:
- RF-REPORT-001: Reportes Predefinidos
- RF-REPORT-002: Dashboards
- RF-REPORT-003: Report Builder
- RF-REPORT-004: Reportes Programados
- BE-021: DashboardsService
- BE-022: WidgetsService
- BE-023: ExportService
tablas: 12
funciones: 0
detalle:
reportes: [reports.report_definitions, reports.report_executions, reports.report_schedules, reports.report_recipients, reports.schedule_executions, reports.custom_reports]
dashboards: [reports.dashboards, reports.dashboard_widgets, reports.widget_queries]
data_model: [reports.data_model_entities, reports.data_model_fields, reports.data_model_relationships]
enums:
- reports.report_type (financial, accounting, tax, management, operational, custom)
- reports.execution_status (pending, running, completed, failed, cancelled)
- reports.export_format (pdf, xlsx, csv, json, html)
- reports.delivery_method (none, email, storage, webhook)
- reports.widget_type (15 tipos)
- reports.param_type (string, number, date, etc)
- reports.filter_operator (eq, ne, gt, gte, lt, lte, like, in, etc)
caracteristicas:
- RLS policies para aislamiento multi-tenant
- 15 tipos de widgets soportados
- Soporte para reportes programados con cron
- Data model para Report Builder visual
# =============================================================================
# SCHEMAS
# =============================================================================
schemas:
# ---------------------------------------------------------------------------
# CORE_AUTH - Autenticacion
# ---------------------------------------------------------------------------
- name: core_auth
description: Autenticacion, sesiones y tokens
module: MGN-001
rf: [RF-AUTH-001, RF-AUTH-002, RF-AUTH-003, RF-AUTH-004]
status: documented
ddl_file: apps/database/ddl/schemas/core_auth/
tables:
- name: users_auth
description: Credenciales de autenticacion
rf: RF-AUTH-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: user_id, type: UUID, fk: core_users.users.id}
- {name: email, type: VARCHAR(255), unique: true}
- {name: password_hash, type: VARCHAR(255)}
- {name: is_active, type: BOOLEAN, default: true}
- {name: email_verified_at, type: TIMESTAMPTZ}
- {name: last_login_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_users_auth_email, columns: [email], unique: true}
- {name: idx_users_auth_tenant, columns: [tenant_id]}
rls_policies:
- {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"}
- name: sessions
description: Sesiones activas
rf: RF-AUTH-002
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth.id}
- {name: token_hash, type: VARCHAR(255)}
- {name: ip_address, type: INET}
- {name: user_agent, type: TEXT}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_sessions_user, columns: [user_id]}
- {name: idx_sessions_expires, columns: [expires_at]}
- name: refresh_tokens
description: Tokens de refresco JWT
rf: RF-AUTH-002
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth.id}
- {name: token_hash, type: VARCHAR(255)}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: revoked_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_refresh_tokens_user, columns: [user_id]}
- name: password_resets
description: Tokens de recuperacion de password
rf: RF-AUTH-003
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth.id}
- {name: token_hash, type: VARCHAR(255)}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: used_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- name: login_attempts
description: Intentos de login fallidos (brute force protection)
rf: RF-AUTH-004
columns:
- {name: id, type: UUID, pk: true}
- {name: email, type: VARCHAR(255)}
- {name: ip_address, type: INET}
- {name: attempted_at, type: TIMESTAMPTZ, default: NOW()}
- {name: success, type: BOOLEAN}
indexes:
- {name: idx_login_attempts_email, columns: [email]}
- {name: idx_login_attempts_ip, columns: [ip_address]}
- name: oauth_accounts
description: Cuentas OAuth vinculadas
rf: RF-AUTH-005
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth.id}
- {name: provider, type: VARCHAR(50)}
- {name: provider_user_id, type: VARCHAR(255)}
- {name: access_token, type: TEXT}
- {name: refresh_token, type: TEXT}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_oauth_provider_user, columns: [provider, provider_user_id], unique: true}
functions:
- name: validate_password
params: [user_id UUID, password TEXT]
returns: BOOLEAN
rf: RF-AUTH-001
description: Valida password contra hash
- name: cleanup_expired_sessions
params: []
returns: INTEGER
rf: RF-AUTH-002
description: Elimina sesiones expiradas
triggers:
- name: trg_update_users_auth_timestamp
table: users_auth
event: BEFORE UPDATE
function: update_updated_at()
# ---------------------------------------------------------------------------
# CORE_USERS - Usuarios
# ---------------------------------------------------------------------------
- name: core_users
description: Gestion de usuarios y perfiles
module: MGN-002
rf: [RF-USERS-001, RF-USERS-002, RF-USERS-003]
status: documented
ddl_file: apps/database/ddl/schemas/core_users/
tables:
- name: users
description: Usuarios del sistema
rf: RF-USERS-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: first_name, type: VARCHAR(100)}
- {name: last_name, type: VARCHAR(100)}
- {name: display_name, type: VARCHAR(200)}
- {name: avatar_url, type: TEXT}
- {name: phone, type: VARCHAR(20)}
- {name: timezone, type: VARCHAR(50), default: "'UTC'"}
- {name: locale, type: VARCHAR(10), default: "'es-MX'"}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
- {name: deleted_at, type: TIMESTAMPTZ}
indexes:
- {name: idx_users_tenant, columns: [tenant_id]}
- {name: idx_users_name_search, columns: [first_name, last_name], type: gin_trgm}
rls_policies:
- {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"}
- name: user_profiles
description: Perfil extendido de usuarios
rf: RF-USERS-002
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users.id, unique: true}
- {name: bio, type: TEXT}
- {name: company, type: VARCHAR(200)}
- {name: job_title, type: VARCHAR(100)}
- {name: address, type: JSONB}
- {name: social_links, type: JSONB}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
- name: user_preferences
description: Preferencias de usuario
rf: RF-USERS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users.id, unique: true}
- {name: theme, type: VARCHAR(20), default: "'light'"}
- {name: notifications_email, type: BOOLEAN, default: true}
- {name: notifications_push, type: BOOLEAN, default: true}
- {name: language, type: VARCHAR(10), default: "'es'"}
- {name: date_format, type: VARCHAR(20), default: "'DD/MM/YYYY'"}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
# ---------------------------------------------------------------------------
# CORE_RBAC - Roles y Permisos
# ---------------------------------------------------------------------------
- name: core_rbac
description: Control de acceso basado en roles
module: MGN-003
rf: [RF-RBAC-001, RF-RBAC-002, RF-RBAC-003]
status: documented
ddl_file: apps/database/ddl/schemas/core_rbac/
tables:
- name: roles
description: Definicion de roles
rf: RF-RBAC-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: name, type: VARCHAR(100)}
- {name: slug, type: VARCHAR(100)}
- {name: description, type: TEXT}
- {name: is_system, type: BOOLEAN, default: false}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_roles_tenant_slug, columns: [tenant_id, slug], unique: true}
rls_policies:
- {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"}
- name: permissions
description: Definicion de permisos
rf: RF-RBAC-002
columns:
- {name: id, type: UUID, pk: true}
- {name: module, type: VARCHAR(50)}
- {name: action, type: VARCHAR(50)}
- {name: resource, type: VARCHAR(100)}
- {name: description, type: TEXT}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_permissions_module_action, columns: [module, action, resource], unique: true}
- name: role_permissions
description: Asignacion permisos a roles
rf: RF-RBAC-002
columns:
- {name: role_id, type: UUID, fk: roles.id}
- {name: permission_id, type: UUID, fk: permissions.id}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
constraints:
- {type: pk, columns: [role_id, permission_id]}
- name: user_roles
description: Asignacion roles a usuarios
rf: RF-RBAC-003
columns:
- {name: user_id, type: UUID, fk: core_users.users.id}
- {name: role_id, type: UUID, fk: roles.id}
- {name: assigned_at, type: TIMESTAMPTZ, default: NOW()}
- {name: assigned_by, type: UUID, fk: core_users.users.id}
constraints:
- {type: pk, columns: [user_id, role_id]}
functions:
- name: user_has_permission
params: [p_user_id UUID, p_module VARCHAR, p_action VARCHAR, p_resource VARCHAR]
returns: BOOLEAN
rf: RF-RBAC-002
description: Verifica si usuario tiene permiso especifico
- name: get_user_permissions
params: [p_user_id UUID]
returns: TABLE
rf: RF-RBAC-002
description: Retorna todos los permisos del usuario
# ---------------------------------------------------------------------------
# CORE_TENANTS - Multi-tenancy
# ---------------------------------------------------------------------------
- name: core_tenants
description: Gestion multi-tenant
module: MGN-004
rf: [RF-TENANTS-001, RF-TENANTS-002, RF-TENANTS-003]
status: documented
ddl_file: apps/database/ddl/schemas/core_tenants/
tables:
- name: tenants
description: Organizaciones/empresas
rf: RF-TENANTS-001
columns:
- {name: id, type: UUID, pk: true}
- {name: name, type: VARCHAR(200)}
- {name: slug, type: VARCHAR(100), unique: true}
- {name: domain, type: VARCHAR(255)}
- {name: logo_url, type: TEXT}
- {name: settings, type: JSONB, default: "'{}'"}
- {name: is_active, type: BOOLEAN, default: true}
- {name: trial_ends_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
- {name: deleted_at, type: TIMESTAMPTZ}
indexes:
- {name: idx_tenants_slug, columns: [slug], unique: true}
- {name: idx_tenants_domain, columns: [domain]}
- name: tenant_settings
description: Configuracion por tenant
rf: RF-TENANTS-002
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: tenants.id, unique: true}
- {name: currency, type: VARCHAR(3), default: "'MXN'"}
- {name: timezone, type: VARCHAR(50), default: "'America/Mexico_City'"}
- {name: date_format, type: VARCHAR(20), default: "'DD/MM/YYYY'"}
- {name: fiscal_config, type: JSONB}
- {name: modules_enabled, type: JSONB}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
- name: plans
description: Planes de suscripcion
rf: RF-TENANTS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: name, type: VARCHAR(100)}
- {name: slug, type: VARCHAR(50), unique: true}
- {name: description, type: TEXT}
- {name: price_monthly, type: DECIMAL(10,2)}
- {name: price_yearly, type: DECIMAL(10,2)}
- {name: features, type: JSONB}
- {name: limits, type: JSONB}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- name: subscriptions
description: Suscripciones de tenants
rf: RF-TENANTS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: tenants.id}
- {name: plan_id, type: UUID, fk: plans.id}
- {name: status, type: VARCHAR(20)}
- {name: starts_at, type: TIMESTAMPTZ}
- {name: ends_at, type: TIMESTAMPTZ}
- {name: canceled_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_subscriptions_tenant, columns: [tenant_id]}
- {name: idx_subscriptions_status, columns: [status]}
# ---------------------------------------------------------------------------
# CORE_CATALOGS - Catalogos Maestros
# ---------------------------------------------------------------------------
- name: core_catalogs
description: Catalogos maestros compartidos
module: MGN-005
rf: [RF-CATALOGS-001, RF-CATALOGS-002, RF-CATALOGS-003]
status: planned
ddl_file: apps/database/ddl/schemas/core_catalogs/
tables:
- name: partners
description: Clientes, proveedores, contactos
rf: RF-CATALOGS-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: name, type: VARCHAR(200)}
- {name: tax_id, type: VARCHAR(20)}
- {name: email, type: VARCHAR(255)}
- {name: phone, type: VARCHAR(20)}
- {name: is_customer, type: BOOLEAN, default: false}
- {name: is_supplier, type: BOOLEAN, default: false}
- {name: is_contact, type: BOOLEAN, default: false}
- {name: credit_limit, type: DECIMAL(15,2), default: 0}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
- {name: deleted_at, type: TIMESTAMPTZ}
indexes:
- {name: idx_partners_tenant_tax, columns: [tenant_id, tax_id], unique: true}
- {name: idx_partners_name_search, columns: [name], type: gin_trgm}
rls_policies:
- {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"}
- name: products
description: Productos y servicios
rf: RF-CATALOGS-002
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: sku, type: VARCHAR(50)}
- {name: name, type: VARCHAR(200)}
- {name: description, type: TEXT}
- {name: category_id, type: UUID, fk: categories.id}
- {name: unit_id, type: UUID, fk: units.id}
- {name: price, type: DECIMAL(15,4)}
- {name: cost, type: DECIMAL(15,4)}
- {name: is_service, type: BOOLEAN, default: false}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_products_tenant_sku, columns: [tenant_id, sku], unique: true}
- name: categories
description: Categorias jerarquicas
rf: RF-CATALOGS-002
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: core_tenants.tenants.id}
- {name: parent_id, type: UUID, fk: categories.id}
- {name: name, type: VARCHAR(100)}
- {name: slug, type: VARCHAR(100)}
- {name: path, type: LTREE}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- name: units
description: Unidades de medida
rf: RF-CATALOGS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: code, type: VARCHAR(10)}
- {name: name, type: VARCHAR(50)}
- {name: category, type: VARCHAR(20)}
- {name: is_base, type: BOOLEAN, default: false}
- {name: conversion_factor, type: DECIMAL(15,6), default: 1}
- name: currencies
description: Monedas
rf: RF-CATALOGS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: code, type: VARCHAR(3)}
- {name: name, type: VARCHAR(50)}
- {name: symbol, type: VARCHAR(5)}
- {name: decimal_places, type: INTEGER, default: 2}
- {name: is_active, type: BOOLEAN, default: true}
- name: countries
description: Paises
rf: RF-CATALOGS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: code, type: VARCHAR(3)}
- {name: name, type: VARCHAR(100)}
- {name: phone_code, type: VARCHAR(5)}
- {name: is_active, type: BOOLEAN, default: true}
- name: states
description: Estados/Provincias
rf: RF-CATALOGS-003
columns:
- {name: id, type: UUID, pk: true}
- {name: country_id, type: UUID, fk: countries.id}
- {name: code, type: VARCHAR(10)}
- {name: name, type: VARCHAR(100)}
- {name: is_active, type: BOOLEAN, default: true}
# ---------------------------------------------------------------------------
# CORE_AUDIT - Auditoria
# ---------------------------------------------------------------------------
- name: core_audit
description: Logs de auditoria
module: MGN-019
rf: [RF-AUDIT-001, RF-AUDIT-002]
status: planned
ddl_file: apps/database/ddl/schemas/core_audit/
tables:
- name: audit_logs
description: Log de cambios en entidades
rf: RF-AUDIT-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID}
- {name: user_id, type: UUID}
- {name: entity_type, type: VARCHAR(100)}
- {name: entity_id, type: UUID}
- {name: action, type: VARCHAR(20)}
- {name: old_values, type: JSONB}
- {name: new_values, type: JSONB}
- {name: ip_address, type: INET}
- {name: user_agent, type: TEXT}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_audit_tenant_entity, columns: [tenant_id, entity_type, entity_id]}
- {name: idx_audit_created, columns: [created_at]}
partitioning:
type: RANGE
column: created_at
interval: MONTHLY
- name: activity_logs
description: Log de actividad de usuarios
rf: RF-AUDIT-002
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID}
- {name: user_id, type: UUID}
- {name: action, type: VARCHAR(100)}
- {name: resource, type: VARCHAR(100)}
- {name: details, type: JSONB}
- {name: ip_address, type: INET}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
# ---------------------------------------------------------------------------
# CORE_NOTIFICATIONS - Notificaciones
# ---------------------------------------------------------------------------
- name: core_notifications
description: Sistema de notificaciones
module: MGN-008
rf: [RF-NOTIF-001, RF-NOTIF-002]
status: planned
ddl_file: apps/database/ddl/schemas/core_notifications/
tables:
- name: notifications
description: Notificaciones de usuarios
rf: RF-NOTIF-001
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID}
- {name: user_id, type: UUID}
- {name: type, type: VARCHAR(50)}
- {name: title, type: VARCHAR(200)}
- {name: message, type: TEXT}
- {name: data, type: JSONB}
- {name: read_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
indexes:
- {name: idx_notifications_user_read, columns: [user_id, read_at]}
rls_policies:
- {name: tenant_isolation, using: "tenant_id = current_setting('app.current_tenant_id')::uuid"}
- name: notification_templates
description: Templates de notificaciones
rf: RF-NOTIF-002
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID}
- {name: code, type: VARCHAR(50)}
- {name: name, type: VARCHAR(100)}
- {name: subject, type: VARCHAR(200)}
- {name: body, type: TEXT}
- {name: channels, type: JSONB}
- {name: is_active, type: BOOLEAN, default: true}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
# =============================================================================
# CONVENCIONES Y ESTANDARES
# =============================================================================
conventions:
naming:
schemas: "core_{nombre}"
tables: snake_case_plural
columns: snake_case
foreign_keys: "fk_{tabla_origen}_{tabla_destino}"
indexes: "idx_{tabla}_{columnas}"
primary_keys: "{tabla}_pkey"
triggers: "trg_{tabla}_{evento}"
functions: snake_case
mandatory_columns:
- {name: id, type: UUID, description: "Primary key"}
- {name: tenant_id, type: UUID, description: "Multi-tenant isolation (si aplica)"}
- {name: created_at, type: TIMESTAMPTZ, default: NOW()}
- {name: updated_at, type: TIMESTAMPTZ, default: NOW()}
soft_delete:
column: deleted_at
type: TIMESTAMPTZ
rls:
pattern: tenant_isolation
context_variable: app.current_tenant_id
mandatory_indexes:
- "idx_{tabla}_tenant_id"
- "idx_{tabla}_created_at"
# =============================================================================
# HISTORIAL
# =============================================================================
history:
- date: "2026-01-07"
action: "Implementacion DDL Sprint 8 - Reports & Dashboards"
author: Database-Agent
changes:
- "Creado 14-reports.sql (12 tablas: reportes, dashboards, data model)"
- "Actualizado create-database.sh con 20 DDL files"
- "Validado recreacion completa de BD con --force"
sprints_cubiertos:
- Sprint 8: Reports & Dashboards
specs_cubiertas:
- RF-REPORT-001: Reportes Predefinidos
- RF-REPORT-002: Dashboards
- RF-REPORT-003: Report Builder
- RF-REPORT-004: Reportes Programados
tablas_nuevas: 12
enums_nuevos: 7
rls_policies_nuevas: 7
- date: "2026-01-07"
action: "Implementacion DDL Sprint 5-7"
author: Backend-Agent
changes:
- "Creado 01-auth-mfa-email-verification.sql (2 tablas: MFA + Email Verification)"
- "Creado 02-core-extensions.sql (1 tabla: currency_rates)"
- "Creado 09-system-extensions.sql (3 tablas: settings 3-level cascade)"
- "Creado 13-audit.sql (3 tablas: audit_logs, access_logs, security_events)"
- "Creado recreate-database.sh (wrapper para recreacion)"
- "Actualizado create-database.sh con 19 DDL files"
- "Validado recreacion completa de BD"
sprints_cubiertos:
- Sprint 5: MFA + Email Verification
- Sprint 6: Catalogs & Settings
- Sprint 7: Audit & Notifications
tablas_nuevas: 9
funciones_nuevas: 4
triggers_nuevos: 3
- date: "2025-12-08"
action: "Implementacion DDL extensiones Auth e Inventory"
author: Database-Agent
changes:
- "Creado 01-auth-extensions.sql (16 tablas, 6 funciones, 2 vistas)"
- "Creado 05-inventory-extensions.sql (10 tablas, 7 funciones, 3 vistas)"
- "Actualizado create-database.sh con orden de ejecucion completo"
- "Agregada seccion clean_load_policy y ddl_files"
specs_cubiertas:
- SPEC-TWO-FACTOR-AUTHENTICATION.md
- SPEC-SEGURIDAD-API-KEYS-PERMISOS.md
- SPEC-OAUTH2-SOCIAL-LOGIN.md
- SPEC-VALORACION-INVENTARIO.md
- SPEC-TRAZABILIDAD-LOTES-SERIES.md
- SPEC-INVENTARIOS-CICLICOS.md
- date: "2025-12-05"
action: "Reestructuracion completa siguiendo filosofia GAMILIT"
author: Requirements-Analyst
changes:
- "Agregada trazabilidad RF por tabla"
- "Documentadas columnas con tipos"
- "Agregados indices y RLS policies"
- "Documentadas funciones y triggers"