erp-core/docs/04-modelado/trazabilidad/INVENTARIO-OBJETOS-BD.yml

2170 lines
81 KiB
YAML

# ============================================================================
# INVENTARIO COMPLETO DE OBJETOS DE BASE DE DATOS
# ERP GENERIC - PostgreSQL 15+
# ============================================================================
# Fecha: 2025-12-09 (Actualizado)
# Propósito: Inventario exhaustivo de todos los objetos de BD extraídos de DDL
# Schemas: auth, core, analytics, financial, inventory, purchase, sales, projects, system, billing, crm, hr
# Total: 12 schemas, 144 tablas
# ============================================================================
prerequisites:
extensions:
- uuid-ossp
- pgcrypto
- pg_trgm
- unaccent
composite_types:
- name: money_amount
attributes:
- amount: NUMERIC(15,2)
- currency_code: CHAR(3)
- name: address_components
attributes:
- street: VARCHAR(255)
- street2: VARCHAR(255)
- city: VARCHAR(100)
- state: VARCHAR(100)
- zip: VARCHAR(20)
- country_code: CHAR(2)
functions:
- name: update_updated_at_column
purpose: "Generic trigger function to auto-update updated_at timestamp on row modification"
- name: normalize_search_text
purpose: "Normalize text for search by removing accents and converting to lowercase"
- name: generate_random_code
purpose: "Generate random alphanumeric code of specified length (default 8)"
- name: is_valid_email
purpose: "Validate email format using regex"
- name: is_valid_phone
purpose: "Validate phone number format (at least 7 digits)"
- name: clean_phone
purpose: "Remove non-numeric characters from phone number"
- name: calculate_age
purpose: "Calculate age in years from birthdate"
- name: get_fiscal_year_start
purpose: "Get the start date of fiscal year for a given date"
- name: round_currency
purpose: "Round numeric value to specified decimal places (default 2 for currency)"
# ============================================================================
# SCHEMA: auth
# ============================================================================
auth:
enums:
- name: user_status
values: [active, inactive, suspended, pending_verification]
- name: tenant_status
values: [active, suspended, trial, cancelled]
- name: session_status
values: [active, expired, revoked]
- name: permission_action
values: [create, read, update, delete, approve, cancel, export]
tables:
- name: tenants
columns: [id, name, subdomain, schema_name, status, settings, plan, max_users, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys: []
- name: companies
columns: [id, tenant_id, name, legal_name, tax_id, currency_id, parent_company_id, partner_id, settings, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: parent_company_id
references: auth.companies(id)
- column: currency_id
references: core.currencies(id)
- column: partner_id
references: core.partners(id)
- name: users
columns: [id, tenant_id, email, password_hash, full_name, avatar_url, status, is_superuser, email_verified_at, last_login_at, last_login_ip, login_count, language, timezone, settings, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: roles
columns: [id, tenant_id, name, code, description, is_system, color, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: permissions
columns: [id, resource, action, description, module, created_at]
foreign_keys: []
- name: user_roles
columns: [user_id, role_id, assigned_at, assigned_by]
foreign_keys:
- column: user_id
references: auth.users(id)
- column: role_id
references: auth.roles(id)
- name: role_permissions
columns: [role_id, permission_id, granted_at, granted_by]
foreign_keys:
- column: role_id
references: auth.roles(id)
- column: permission_id
references: auth.permissions(id)
- name: sessions
columns: [id, user_id, token, refresh_token, status, expires_at, refresh_expires_at, ip_address, user_agent, device_info, created_at, revoked_at, revoked_reason]
foreign_keys:
- column: user_id
references: auth.users(id)
- name: user_companies
columns: [user_id, company_id, is_default, assigned_at]
foreign_keys:
- column: user_id
references: auth.users(id)
- column: company_id
references: auth.companies(id)
- name: password_resets
columns: [id, user_id, token, expires_at, used_at, ip_address, created_at]
foreign_keys:
- column: user_id
references: auth.users(id)
functions:
- name: get_current_tenant_id
purpose: "Obtiene el tenant_id del contexto actual"
- name: get_current_user_id
purpose: "Obtiene el user_id del contexto actual"
- name: get_current_company_id
purpose: "Obtiene el company_id del contexto actual"
- name: user_has_permission
purpose: "Verifica si un usuario tiene un permiso específico"
- name: clean_expired_sessions
purpose: "Limpia sesiones expiradas (ejecutar periódicamente)"
- name: update_updated_at_column
purpose: "Actualiza updated_at y updated_by al modificar registros"
- name: validate_tenant_has_admin
purpose: "Valida que tenant tenga al menos 1 admin antes de eliminar role"
- name: auto_expire_session
purpose: "Auto-marca sesión como expirada si pasa expires_at"
triggers:
- name: trg_tenants_updated_at
table: tenants
- name: trg_companies_updated_at
table: companies
- name: trg_users_updated_at
table: users
- name: trg_roles_updated_at
table: roles
- name: trg_validate_tenant_has_admin
table: user_roles
- name: trg_auto_expire_session
table: sessions
indexes:
- name: idx_tenants_subdomain
table: tenants
columns: [subdomain]
- name: idx_tenants_status
table: tenants
columns: [status]
- name: idx_companies_tenant_id
table: companies
columns: [tenant_id]
- name: idx_companies_parent_company_id
table: companies
columns: [parent_company_id]
- name: idx_users_tenant_id
table: users
columns: [tenant_id]
- name: idx_users_email
table: users
columns: [email]
- name: idx_users_status
table: users
columns: [status]
- name: idx_roles_tenant_id
table: roles
columns: [tenant_id]
- name: idx_roles_code
table: roles
columns: [code]
- name: idx_sessions_user_id
table: sessions
columns: [user_id]
- name: idx_sessions_token
table: sessions
columns: [token]
rls_policies:
- name: tenant_isolation_companies
table: companies
- name: tenant_isolation_users
table: users
- name: tenant_isolation_roles
table: roles
views:
- name: user_permissions_view
purpose: "Vista de permisos efectivos por usuario"
- name: active_sessions_view
purpose: "Vista de sesiones activas con tiempo restante"
# ============================================================================
# SCHEMA: core
# ============================================================================
core:
enums:
- name: partner_type
values: [person, company]
- name: partner_category
values: [customer, supplier, employee, contact, other]
- name: address_type
values: [billing, shipping, contact, other]
- name: uom_type
values: [reference, bigger, smaller]
tables:
- name: countries
columns: [id, code, name, phone_code, currency_code, created_at]
foreign_keys: []
- name: currencies
columns: [id, code, name, symbol, decimals, rounding, active, created_at]
foreign_keys: []
- name: exchange_rates
columns: [id, from_currency_id, to_currency_id, rate, date, created_at]
foreign_keys:
- column: from_currency_id
references: core.currencies(id)
- column: to_currency_id
references: core.currencies(id)
- name: uom_categories
columns: [id, name, description, created_at]
foreign_keys: []
- name: uom
columns: [id, category_id, name, code, uom_type, factor, rounding, active, created_at]
foreign_keys:
- column: category_id
references: core.uom_categories(id)
- name: partners
columns: [id, tenant_id, name, legal_name, partner_type, is_customer, is_supplier, is_employee, is_company, email, phone, mobile, website, tax_id, company_id, parent_id, user_id, payment_term_id, pricelist_id, language, currency_id, notes, internal_notes, active, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: parent_id
references: core.partners(id)
- column: user_id
references: auth.users(id)
- column: currency_id
references: core.currencies(id)
- name: addresses
columns: [id, partner_id, address_type, street, street2, city, state, zip_code, country_id, is_default, active, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: partner_id
references: core.partners(id)
- column: country_id
references: core.countries(id)
- name: product_categories
columns: [id, tenant_id, name, code, parent_id, full_path, notes, active, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: parent_id
references: core.product_categories(id)
- name: tags
columns: [id, tenant_id, name, color, model, description, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: sequences
columns: [id, tenant_id, company_id, code, name, prefix, suffix, next_number, padding, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- name: attachments
columns: [id, tenant_id, model, record_id, filename, mimetype, size_bytes, url, description, is_public, created_at, created_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: notes
columns: [id, tenant_id, model, record_id, subject, content, is_pinned, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
functions:
- name: generate_next_sequence
purpose: "Genera el siguiente número de secuencia para un código dado"
- name: update_product_category_path
purpose: "Actualiza el path completo de la categoría al crear/actualizar"
- name: get_exchange_rate
purpose: "Obtiene la tasa de cambio entre dos monedas en una fecha específica"
triggers:
- name: trg_partners_updated_at
table: partners
- name: trg_addresses_updated_at
table: addresses
- name: trg_product_categories_updated_at
table: product_categories
- name: trg_product_categories_update_path
table: product_categories
- name: trg_notes_updated_at
table: notes
indexes:
- name: idx_countries_code
table: countries
columns: [code]
- name: idx_currencies_code
table: currencies
columns: [code]
- name: idx_partners_tenant_id
table: partners
columns: [tenant_id]
- name: idx_partners_name
table: partners
columns: [name]
- name: idx_partners_email
table: partners
columns: [email]
- name: idx_partners_is_customer
table: partners
columns: [tenant_id, is_customer]
- name: idx_partners_is_supplier
table: partners
columns: [tenant_id, is_supplier]
- name: idx_product_categories_tenant_id
table: product_categories
columns: [tenant_id]
- name: idx_sequences_tenant_id
table: sequences
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_partners
table: partners
- name: tenant_isolation_product_categories
table: product_categories
- name: tenant_isolation_tags
table: tags
- name: tenant_isolation_sequences
table: sequences
- name: tenant_isolation_attachments
table: attachments
- name: tenant_isolation_notes
table: notes
views:
- name: customers_view
purpose: "Vista de partners que son clientes"
- name: suppliers_view
purpose: "Vista de partners que son proveedores"
- name: employees_view
purpose: "Vista de partners que son empleados"
# ============================================================================
# SCHEMA: analytics
# ============================================================================
analytics:
enums:
- name: account_type
values: [project, department, cost_center, customer, product, other]
- name: line_type
values: [expense, income, timesheet]
- name: account_status
values: [active, inactive, closed]
tables:
- name: analytic_plans
columns: [id, tenant_id, company_id, name, description, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- name: analytic_accounts
columns: [id, tenant_id, company_id, plan_id, name, code, account_type, parent_id, full_path, partner_id, budget, status, date_start, date_end, description, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: plan_id
references: analytics.analytic_plans(id)
- column: parent_id
references: analytics.analytic_accounts(id)
- column: partner_id
references: core.partners(id)
- name: analytic_tags
columns: [id, tenant_id, name, color, description, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: cost_centers
columns: [id, tenant_id, company_id, name, code, analytic_account_id, manager_id, budget_monthly, budget_annual, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- column: manager_id
references: auth.users(id)
- name: analytic_lines
columns: [id, tenant_id, company_id, analytic_account_id, date, amount, unit_amount, line_type, product_id, employee_id, partner_id, name, description, source_model, source_id, source_document, currency_id, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- column: product_id
references: inventory.products(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- name: analytic_line_tags
columns: [analytic_line_id, analytic_tag_id, created_at]
foreign_keys:
- column: analytic_line_id
references: analytics.analytic_lines(id)
- column: analytic_tag_id
references: analytics.analytic_tags(id)
- name: analytic_distributions
columns: [id, source_model, source_id, analytic_account_id, percentage, amount, created_at]
foreign_keys:
- column: analytic_account_id
references: analytics.analytic_accounts(id)
functions:
- name: update_analytic_account_path
purpose: "Actualiza el path completo de la cuenta analítica"
- name: get_analytic_balance
purpose: "Obtiene el balance de una cuenta analítica en un período"
- name: validate_distribution_100_percent
purpose: "Valida que la distribución analítica no exceda el 100%"
- name: create_analytic_line_from_invoice
purpose: "Crea una línea analítica a partir de una línea de factura"
triggers:
- name: trg_analytic_plans_updated_at
table: analytic_plans
- name: trg_analytic_accounts_updated_at
table: analytic_accounts
- name: trg_analytic_accounts_update_path
table: analytic_accounts
- name: trg_cost_centers_updated_at
table: cost_centers
- name: trg_analytic_distributions_validate_100
table: analytic_distributions
indexes:
- name: idx_analytic_plans_tenant_id
table: analytic_plans
columns: [tenant_id]
- name: idx_analytic_accounts_tenant_id
table: analytic_accounts
columns: [tenant_id]
- name: idx_analytic_accounts_company_id
table: analytic_accounts
columns: [company_id]
- name: idx_analytic_lines_tenant_id
table: analytic_lines
columns: [tenant_id]
- name: idx_analytic_lines_analytic_account_id
table: analytic_lines
columns: [analytic_account_id]
- name: idx_cost_centers_tenant_id
table: cost_centers
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_analytic_plans
table: analytic_plans
- name: tenant_isolation_analytic_accounts
table: analytic_accounts
- name: tenant_isolation_analytic_tags
table: analytic_tags
- name: tenant_isolation_cost_centers
table: cost_centers
- name: tenant_isolation_analytic_lines
table: analytic_lines
views:
- name: analytic_balance_view
purpose: "Vista de balance analítico por cuenta con presupuesto vs real"
# ============================================================================
# SCHEMA: financial
# ============================================================================
financial:
enums:
- name: account_type
values: [asset, liability, equity, revenue, expense]
- name: journal_type
values: [sale, purchase, bank, cash, general]
- name: entry_status
values: [draft, posted, cancelled]
- name: invoice_type
values: [customer, supplier]
- name: invoice_status
values: [draft, open, paid, cancelled]
- name: payment_type
values: [inbound, outbound]
- name: payment_method
values: [cash, bank_transfer, check, card, other]
- name: payment_status
values: [draft, posted, reconciled, cancelled]
- name: tax_type
values: [sales, purchase, all]
- name: fiscal_period_status
values: [open, closed]
tables:
- name: account_types
columns: [id, code, name, account_type, description, created_at]
foreign_keys: []
- name: accounts
columns: [id, tenant_id, company_id, code, name, account_type_id, parent_id, currency_id, is_reconcilable, is_deprecated, notes, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: account_type_id
references: financial.account_types(id)
- column: parent_id
references: financial.accounts(id)
- column: currency_id
references: core.currencies(id)
- name: journals
columns: [id, tenant_id, company_id, name, code, journal_type, default_account_id, sequence_id, currency_id, active, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: default_account_id
references: financial.accounts(id)
- column: sequence_id
references: core.sequences(id)
- column: currency_id
references: core.currencies(id)
- name: fiscal_years
columns: [id, tenant_id, company_id, name, code, start_date, end_date, status, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- name: fiscal_periods
columns: [id, tenant_id, fiscal_year_id, name, code, start_date, end_date, status, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: fiscal_year_id
references: financial.fiscal_years(id)
- name: journal_entries
columns: [id, tenant_id, company_id, journal_id, name, ref, date, status, notes, created_at, created_by, updated_at, updated_by, posted_at, posted_by, cancelled_at, cancelled_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: journal_id
references: financial.journals(id)
- name: journal_entry_lines
columns: [id, entry_id, account_id, partner_id, debit, credit, analytic_account_id, description, ref, currency_id, amount_currency, created_at]
foreign_keys:
- column: entry_id
references: financial.journal_entries(id)
- column: account_id
references: financial.accounts(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- name: taxes
columns: [id, tenant_id, company_id, name, code, rate, tax_type, account_id, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: account_id
references: financial.accounts(id)
- name: payment_terms
columns: [id, tenant_id, company_id, name, code, terms, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- name: invoices
columns: [id, tenant_id, company_id, partner_id, invoice_type, number, ref, invoice_date, due_date, currency_id, amount_untaxed, amount_tax, amount_total, amount_paid, amount_residual, status, payment_term_id, journal_id, journal_entry_id, notes, created_at, created_by, updated_at, updated_by, validated_at, validated_by, cancelled_at, cancelled_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: payment_term_id
references: financial.payment_terms(id)
- column: journal_id
references: financial.journals(id)
- column: journal_entry_id
references: financial.journal_entries(id)
- name: invoice_lines
columns: [id, invoice_id, product_id, description, quantity, uom_id, price_unit, tax_ids, amount_untaxed, amount_tax, amount_total, account_id, analytic_account_id, created_at, updated_at]
foreign_keys:
- column: invoice_id
references: financial.invoices(id)
- column: uom_id
references: core.uom(id)
- column: account_id
references: financial.accounts(id)
- name: payments
columns: [id, tenant_id, company_id, partner_id, payment_type, payment_method, amount, currency_id, payment_date, ref, status, journal_id, journal_entry_id, notes, created_at, created_by, updated_at, updated_by, posted_at, posted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: journal_id
references: financial.journals(id)
- column: journal_entry_id
references: financial.journal_entries(id)
- name: payment_invoice
columns: [payment_id, invoice_id, amount, created_at]
foreign_keys:
- column: payment_id
references: financial.payments(id)
- column: invoice_id
references: financial.invoices(id)
- name: bank_accounts
columns: [id, tenant_id, company_id, partner_id, bank_name, account_number, account_holder, currency_id, journal_id, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: journal_id
references: financial.journals(id)
- name: reconciliations
columns: [id, tenant_id, company_id, bank_account_id, start_date, end_date, balance_start, balance_end_real, balance_end_computed, reconciled_line_ids, status, created_at, created_by, updated_at, updated_by, validated_at, validated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: bank_account_id
references: financial.bank_accounts(id)
functions:
- name: validate_entry_balance
purpose: "Valida que un asiento contable esté balanceado (debit = credit)"
- name: post_journal_entry
purpose: "Contabiliza un asiento contable después de validar su balance"
- name: calculate_invoice_totals
purpose: "Calcula los totales de una factura a partir de sus líneas"
- name: update_invoice_paid_amount
purpose: "Actualiza el monto pagado y estado de una factura"
triggers:
- name: trg_accounts_updated_at
table: accounts
- name: trg_journals_updated_at
table: journals
- name: trg_journal_entries_updated_at
table: journal_entries
- name: trg_invoices_updated_at
table: invoices
- name: trg_payments_updated_at
table: payments
- name: trg_journal_entries_validate_balance
table: journal_entries
- name: trg_invoice_lines_update_totals
table: invoice_lines
- name: trg_payment_invoice_update_paid
table: payment_invoice
- name: track_invoice_changes
table: invoices
- name: track_journal_entry_changes
table: journal_entries
indexes:
- name: idx_accounts_tenant_id
table: accounts
columns: [tenant_id]
- name: idx_accounts_company_id
table: accounts
columns: [company_id]
- name: idx_journals_tenant_id
table: journals
columns: [tenant_id]
- name: idx_journal_entries_tenant_id
table: journal_entries
columns: [tenant_id]
- name: idx_invoices_tenant_id
table: invoices
columns: [tenant_id]
- name: idx_invoices_partner_id
table: invoices
columns: [partner_id]
- name: idx_invoices_status
table: invoices
columns: [status]
- name: idx_payments_tenant_id
table: payments
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_accounts
table: accounts
- name: tenant_isolation_journals
table: journals
- name: tenant_isolation_fiscal_years
table: fiscal_years
- name: tenant_isolation_fiscal_periods
table: fiscal_periods
- name: tenant_isolation_journal_entries
table: journal_entries
- name: tenant_isolation_taxes
table: taxes
- name: tenant_isolation_payment_terms
table: payment_terms
- name: tenant_isolation_invoices
table: invoices
- name: tenant_isolation_payments
table: payments
- name: tenant_isolation_bank_accounts
table: bank_accounts
- name: tenant_isolation_reconciliations
table: reconciliations
views: []
# ============================================================================
# SCHEMA: inventory
# ============================================================================
inventory:
enums:
- name: product_type
values: [storable, consumable, service]
- name: tracking_type
values: [none, lot, serial]
- name: location_type
values: [internal, customer, supplier, inventory, production, transit]
- name: picking_type
values: [incoming, outgoing, internal]
- name: move_status
values: [draft, confirmed, assigned, done, cancelled]
- name: valuation_method
values: [fifo, average, standard]
tables:
- name: products
columns: [id, tenant_id, name, code, barcode, description, product_type, tracking, category_id, uom_id, purchase_uom_id, cost_price, list_price, valuation_method, is_storable, weight, volume, can_be_sold, can_be_purchased, image_url, active, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: category_id
references: core.product_categories(id)
- column: uom_id
references: core.uom(id)
- column: purchase_uom_id
references: core.uom(id)
- name: product_variants
columns: [id, product_template_id, attribute_values, name, code, barcode, price_extra, active, created_at, created_by]
foreign_keys:
- column: product_template_id
references: inventory.products(id)
- name: warehouses
columns: [id, tenant_id, company_id, name, code, address_id, is_default, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: address_id
references: core.addresses(id)
- name: locations
columns: [id, tenant_id, warehouse_id, name, complete_name, location_type, parent_id, is_scrap_location, is_return_location, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: warehouse_id
references: inventory.warehouses(id)
- column: parent_id
references: inventory.locations(id)
- name: stock_quants
columns: [id, product_id, location_id, lot_id, quantity, reserved_quantity, available_quantity, cost, created_at, updated_at]
foreign_keys:
- column: product_id
references: inventory.products(id)
- column: location_id
references: inventory.locations(id)
- column: lot_id
references: inventory.lots(id)
- name: lots
columns: [id, tenant_id, product_id, name, ref, manufacture_date, expiration_date, removal_date, alert_date, notes, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: product_id
references: inventory.products(id)
- name: pickings
columns: [id, tenant_id, company_id, name, picking_type, location_id, location_dest_id, partner_id, scheduled_date, date_done, origin, status, notes, created_at, created_by, updated_at, updated_by, validated_at, validated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: location_id
references: inventory.locations(id)
- column: location_dest_id
references: inventory.locations(id)
- column: partner_id
references: core.partners(id)
- name: stock_moves
columns: [id, tenant_id, product_id, product_uom_id, location_id, location_dest_id, product_qty, quantity_done, lot_id, picking_id, origin, ref, status, date_expected, date, price_unit, analytic_account_id, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: product_id
references: inventory.products(id)
- column: product_uom_id
references: core.uom(id)
- column: location_id
references: inventory.locations(id)
- column: location_dest_id
references: inventory.locations(id)
- column: lot_id
references: inventory.lots(id)
- column: picking_id
references: inventory.pickings(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- name: inventory_adjustments
columns: [id, tenant_id, company_id, name, location_id, date, status, notes, created_at, created_by, updated_at, updated_by, validated_at, validated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: location_id
references: inventory.locations(id)
- name: inventory_adjustment_lines
columns: [id, adjustment_id, product_id, location_id, lot_id, theoretical_qty, counted_qty, difference_qty, created_at]
foreign_keys:
- column: adjustment_id
references: inventory.inventory_adjustments(id)
- column: product_id
references: inventory.products(id)
- column: location_id
references: inventory.locations(id)
- column: lot_id
references: inventory.lots(id)
functions:
- name: update_stock_quant
purpose: "Actualiza la cantidad en stock de un producto en una ubicación"
- name: reserve_quantity
purpose: "Reserva cantidad de un producto en una ubicación"
- name: get_product_stock
purpose: "Obtiene el stock disponible de un producto por ubicación"
- name: process_stock_move
purpose: "Procesa un movimiento de inventario y actualiza los quants"
- name: update_location_complete_name
purpose: "Actualiza el nombre completo de la ubicación"
triggers:
- name: trg_products_updated_at
table: products
- name: trg_warehouses_updated_at
table: warehouses
- name: trg_locations_updated_at
table: locations
- name: trg_locations_update_complete_name
table: locations
- name: trg_pickings_updated_at
table: pickings
- name: trg_stock_moves_updated_at
table: stock_moves
- name: track_stock_move_changes
table: stock_moves
indexes:
- name: idx_products_tenant_id
table: products
columns: [tenant_id]
- name: idx_products_code
table: products
columns: [code]
- name: idx_products_barcode
table: products
columns: [barcode]
- name: idx_warehouses_tenant_id
table: warehouses
columns: [tenant_id]
- name: idx_locations_tenant_id
table: locations
columns: [tenant_id]
- name: idx_stock_quants_product_id
table: stock_quants
columns: [product_id]
- name: idx_pickings_tenant_id
table: pickings
columns: [tenant_id]
- name: idx_stock_moves_tenant_id
table: stock_moves
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_products
table: products
- name: tenant_isolation_warehouses
table: warehouses
- name: tenant_isolation_locations
table: locations
- name: tenant_isolation_lots
table: lots
- name: tenant_isolation_pickings
table: pickings
- name: tenant_isolation_stock_moves
table: stock_moves
- name: tenant_isolation_inventory_adjustments
table: inventory_adjustments
views:
- name: stock_by_product_view
purpose: "Vista de stock disponible por producto y ubicación"
# ============================================================================
# SCHEMA: purchase
# ============================================================================
purchase:
enums:
- name: order_status
values: [draft, sent, confirmed, received, billed, cancelled]
- name: rfq_status
values: [draft, sent, responded, accepted, rejected, cancelled]
- name: agreement_type
values: [price, discount, blanket]
tables:
- name: purchase_orders
columns: [id, tenant_id, company_id, name, ref, partner_id, order_date, expected_date, effective_date, currency_id, payment_term_id, amount_untaxed, amount_tax, amount_total, status, receipt_status, invoice_status, picking_id, invoice_id, notes, created_at, created_by, updated_at, updated_by, confirmed_at, confirmed_by, cancelled_at, cancelled_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: payment_term_id
references: financial.payment_terms(id)
- column: picking_id
references: inventory.pickings(id)
- column: invoice_id
references: financial.invoices(id)
- name: purchase_order_lines
columns: [id, order_id, product_id, description, quantity, qty_received, qty_invoiced, uom_id, price_unit, discount, tax_ids, amount_untaxed, amount_tax, amount_total, expected_date, analytic_account_id, created_at, updated_at]
foreign_keys:
- column: order_id
references: purchase.purchase_orders(id)
- column: product_id
references: inventory.products(id)
- column: uom_id
references: core.uom(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- name: rfqs
columns: [id, tenant_id, company_id, name, partner_ids, request_date, deadline_date, response_date, status, description, notes, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- name: rfq_lines
columns: [id, rfq_id, product_id, description, quantity, uom_id, created_at]
foreign_keys:
- column: rfq_id
references: purchase.rfqs(id)
- column: product_id
references: inventory.products(id)
- column: uom_id
references: core.uom(id)
- name: vendor_pricelists
columns: [id, tenant_id, partner_id, product_id, price, currency_id, min_quantity, valid_from, valid_to, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: partner_id
references: core.partners(id)
- column: product_id
references: inventory.products(id)
- column: currency_id
references: core.currencies(id)
- name: purchase_agreements
columns: [id, tenant_id, company_id, name, code, agreement_type, partner_id, start_date, end_date, amount_max, currency_id, is_active, terms, notes, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- name: purchase_agreement_lines
columns: [id, agreement_id, product_id, quantity, qty_ordered, price_unit, discount, created_at]
foreign_keys:
- column: agreement_id
references: purchase.purchase_agreements(id)
- column: product_id
references: inventory.products(id)
- name: vendor_evaluations
columns: [id, tenant_id, company_id, partner_id, evaluation_date, period_start, period_end, quality_rating, delivery_rating, service_rating, price_rating, overall_rating, on_time_delivery_rate, defect_rate, comments, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
functions:
- name: calculate_purchase_order_totals
purpose: "Calcula los totales de una orden de compra"
- name: create_picking_from_po
purpose: "Crea un picking de recepción a partir de una orden de compra"
triggers:
- name: trg_purchase_orders_updated_at
table: purchase_orders
- name: trg_rfqs_updated_at
table: rfqs
- name: trg_vendor_pricelists_updated_at
table: vendor_pricelists
- name: trg_purchase_order_lines_update_totals
table: purchase_order_lines
- name: track_purchase_order_changes
table: purchase_orders
indexes:
- name: idx_purchase_orders_tenant_id
table: purchase_orders
columns: [tenant_id]
- name: idx_purchase_orders_partner_id
table: purchase_orders
columns: [partner_id]
- name: idx_purchase_orders_status
table: purchase_orders
columns: [status]
- name: idx_rfqs_tenant_id
table: rfqs
columns: [tenant_id]
- name: idx_vendor_pricelists_tenant_id
table: vendor_pricelists
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_purchase_orders
table: purchase_orders
- name: tenant_isolation_rfqs
table: rfqs
- name: tenant_isolation_vendor_pricelists
table: vendor_pricelists
- name: tenant_isolation_purchase_agreements
table: purchase_agreements
- name: tenant_isolation_vendor_evaluations
table: vendor_evaluations
views: []
# ============================================================================
# SCHEMA: sales
# ============================================================================
sales:
enums:
- name: order_status
values: [draft, sent, sale, done, cancelled]
- name: quotation_status
values: [draft, sent, approved, rejected, converted, expired]
- name: invoice_policy
values: [order, delivery]
- name: delivery_status
values: [pending, partial, delivered]
- name: invoice_status
values: [pending, partial, invoiced]
tables:
- name: sales_orders
columns: [id, tenant_id, company_id, name, client_order_ref, partner_id, order_date, validity_date, commitment_date, currency_id, pricelist_id, payment_term_id, user_id, sales_team_id, amount_untaxed, amount_tax, amount_total, status, invoice_status, delivery_status, invoice_policy, picking_id, notes, terms_conditions, signature, signature_date, signature_ip, created_at, created_by, updated_at, updated_by, confirmed_at, confirmed_by, cancelled_at, cancelled_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: pricelist_id
references: sales.pricelists(id)
- column: payment_term_id
references: financial.payment_terms(id)
- column: user_id
references: auth.users(id)
- column: sales_team_id
references: sales.sales_teams(id)
- column: picking_id
references: inventory.pickings(id)
- name: sales_order_lines
columns: [id, order_id, product_id, description, quantity, qty_delivered, qty_invoiced, uom_id, price_unit, discount, tax_ids, amount_untaxed, amount_tax, amount_total, analytic_account_id, created_at, updated_at]
foreign_keys:
- column: order_id
references: sales.sales_orders(id)
- column: product_id
references: inventory.products(id)
- column: uom_id
references: core.uom(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- name: quotations
columns: [id, tenant_id, company_id, name, partner_id, quotation_date, validity_date, currency_id, pricelist_id, user_id, sales_team_id, amount_untaxed, amount_tax, amount_total, status, sale_order_id, notes, terms_conditions, signature, signature_date, signature_ip, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: currency_id
references: core.currencies(id)
- column: pricelist_id
references: sales.pricelists(id)
- column: user_id
references: auth.users(id)
- column: sales_team_id
references: sales.sales_teams(id)
- column: sale_order_id
references: sales.sales_orders(id)
- name: quotation_lines
columns: [id, quotation_id, product_id, description, quantity, uom_id, price_unit, discount, tax_ids, amount_untaxed, amount_tax, amount_total, created_at]
foreign_keys:
- column: quotation_id
references: sales.quotations(id)
- column: product_id
references: inventory.products(id)
- column: uom_id
references: core.uom(id)
- name: pricelists
columns: [id, tenant_id, company_id, name, currency_id, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: currency_id
references: core.currencies(id)
- name: pricelist_items
columns: [id, pricelist_id, product_id, product_category_id, price, min_quantity, valid_from, valid_to, active, created_at, created_by]
foreign_keys:
- column: pricelist_id
references: sales.pricelists(id)
- column: product_id
references: inventory.products(id)
- column: product_category_id
references: core.product_categories(id)
- name: customer_groups
columns: [id, tenant_id, name, description, discount_percentage, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: customer_group_members
columns: [customer_group_id, partner_id, joined_at]
foreign_keys:
- column: customer_group_id
references: sales.customer_groups(id)
- column: partner_id
references: core.partners(id)
- name: sales_teams
columns: [id, tenant_id, company_id, name, code, team_leader_id, target_monthly, target_annual, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: team_leader_id
references: auth.users(id)
- name: sales_team_members
columns: [sales_team_id, user_id, joined_at]
foreign_keys:
- column: sales_team_id
references: sales.sales_teams(id)
- column: user_id
references: auth.users(id)
functions:
- name: calculate_sales_order_totals
purpose: "Calcula los totales de una orden de venta"
- name: calculate_quotation_totals
purpose: "Calcula los totales de una cotización"
- name: convert_quotation_to_order
purpose: "Convierte una cotización aprobada en orden de venta"
triggers:
- name: trg_sales_orders_updated_at
table: sales_orders
- name: trg_quotations_updated_at
table: quotations
- name: trg_pricelists_updated_at
table: pricelists
- name: trg_sales_order_lines_update_totals
table: sales_order_lines
- name: trg_quotation_lines_update_totals
table: quotation_lines
- name: track_sales_order_changes
table: sales_orders
indexes:
- name: idx_sales_orders_tenant_id
table: sales_orders
columns: [tenant_id]
- name: idx_sales_orders_partner_id
table: sales_orders
columns: [partner_id]
- name: idx_sales_orders_status
table: sales_orders
columns: [status]
- name: idx_quotations_tenant_id
table: quotations
columns: [tenant_id]
- name: idx_pricelists_tenant_id
table: pricelists
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_sales_orders
table: sales_orders
- name: tenant_isolation_quotations
table: quotations
- name: tenant_isolation_pricelists
table: pricelists
- name: tenant_isolation_customer_groups
table: customer_groups
- name: tenant_isolation_sales_teams
table: sales_teams
views: []
# ============================================================================
# SCHEMA: projects
# ============================================================================
projects:
enums:
- name: project_status
values: [draft, active, completed, cancelled, on_hold]
- name: privacy_type
values: [public, private, followers]
- name: task_status
values: [todo, in_progress, review, done, cancelled]
- name: task_priority
values: [low, normal, high, urgent]
- name: dependency_type
values: [finish_to_start, start_to_start, finish_to_finish, start_to_finish]
- name: milestone_status
values: [pending, completed]
tables:
- name: projects
columns: [id, tenant_id, company_id, name, code, description, manager_id, partner_id, analytic_account_id, date_start, date_end, status, privacy, allow_timesheets, color, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: manager_id
references: auth.users(id)
- column: partner_id
references: core.partners(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- name: project_stages
columns: [id, tenant_id, project_id, name, sequence, is_closed, fold, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: project_id
references: projects.projects(id)
- name: tasks
columns: [id, tenant_id, project_id, stage_id, name, description, assigned_to, partner_id, parent_id, date_start, date_deadline, planned_hours, actual_hours, progress, priority, status, milestone_id, created_at, created_by, updated_at, updated_by, deleted_at, deleted_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: project_id
references: projects.projects(id)
- column: stage_id
references: projects.project_stages(id)
- column: assigned_to
references: auth.users(id)
- column: partner_id
references: core.partners(id)
- column: parent_id
references: projects.tasks(id)
- column: milestone_id
references: projects.milestones(id)
- name: milestones
columns: [id, tenant_id, project_id, name, description, target_date, status, created_at, created_by, updated_at, updated_by, completed_at, completed_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: project_id
references: projects.projects(id)
- name: task_dependencies
columns: [id, task_id, depends_on_id, dependency_type, created_at]
foreign_keys:
- column: task_id
references: projects.tasks(id)
- column: depends_on_id
references: projects.tasks(id)
- name: task_tags
columns: [id, tenant_id, name, color, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: task_tag_assignments
columns: [task_id, tag_id, created_at]
foreign_keys:
- column: task_id
references: projects.tasks(id)
- column: tag_id
references: projects.task_tags(id)
- name: timesheets
columns: [id, tenant_id, company_id, task_id, project_id, employee_id, user_id, date, hours, description, analytic_account_id, analytic_line_id, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: task_id
references: projects.tasks(id)
- column: project_id
references: projects.projects(id)
- column: user_id
references: auth.users(id)
- column: analytic_account_id
references: analytics.analytic_accounts(id)
- column: analytic_line_id
references: analytics.analytic_lines(id)
- name: task_checklists
columns: [id, task_id, item_name, is_completed, sequence, created_at, completed_at, completed_by]
foreign_keys:
- column: task_id
references: projects.tasks(id)
- name: project_templates
columns: [id, tenant_id, name, description, template_data, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
functions:
- name: update_task_actual_hours
purpose: "Actualiza las horas reales de una tarea al cambiar timesheets"
- name: check_task_dependencies
purpose: "Verifica si todas las dependencias de una tarea están completadas"
- name: prevent_circular_dependencies
purpose: "Previene la creación de dependencias circulares entre tareas"
triggers:
- name: trg_projects_updated_at
table: projects
- name: trg_tasks_updated_at
table: tasks
- name: trg_milestones_updated_at
table: milestones
- name: trg_timesheets_updated_at
table: timesheets
- name: trg_timesheets_update_task_hours
table: timesheets
- name: trg_task_dependencies_prevent_circular
table: task_dependencies
- name: track_project_changes
table: projects
indexes:
- name: idx_projects_tenant_id
table: projects
columns: [tenant_id]
- name: idx_projects_company_id
table: projects
columns: [company_id]
- name: idx_tasks_tenant_id
table: tasks
columns: [tenant_id]
- name: idx_tasks_project_id
table: tasks
columns: [project_id]
- name: idx_tasks_assigned_to
table: tasks
columns: [assigned_to]
- name: idx_timesheets_tenant_id
table: timesheets
columns: [tenant_id]
rls_policies:
- name: tenant_isolation_projects
table: projects
- name: tenant_isolation_project_stages
table: project_stages
- name: tenant_isolation_tasks
table: tasks
- name: tenant_isolation_milestones
table: milestones
- name: tenant_isolation_task_tags
table: task_tags
- name: tenant_isolation_timesheets
table: timesheets
- name: tenant_isolation_project_templates
table: project_templates
views: []
# ============================================================================
# SCHEMA: system
# ============================================================================
system:
enums:
- name: message_type
values: [comment, note, email, notification, system]
- name: notification_status
values: [pending, sent, read, failed]
- name: activity_type
values: [call, meeting, email, todo, follow_up, custom]
- name: activity_status
values: [planned, done, cancelled, overdue]
- name: email_status
values: [draft, queued, sending, sent, failed, bounced]
- name: log_level
values: [debug, info, warning, error, critical]
- name: report_format
values: [pdf, excel, csv, html]
tables:
- name: messages
columns: [id, tenant_id, model, record_id, message_type, subject, body, author_id, author_name, author_email, email_from, reply_to, message_id, parent_id, attachment_ids, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: author_id
references: auth.users(id)
- column: parent_id
references: system.messages(id)
- name: message_followers
columns: [id, model, record_id, partner_id, user_id, email_notifications, created_at]
foreign_keys:
- column: partner_id
references: core.partners(id)
- column: user_id
references: auth.users(id)
- name: notifications
columns: [id, tenant_id, user_id, title, message, url, model, record_id, status, read_at, created_at, sent_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: user_id
references: auth.users(id)
- name: activities
columns: [id, tenant_id, model, record_id, activity_type, summary, description, assigned_to, assigned_by, due_date, due_time, status, created_at, created_by, completed_at, completed_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: assigned_to
references: auth.users(id)
- column: assigned_by
references: auth.users(id)
- name: message_templates
columns: [id, tenant_id, name, model, subject, body_html, body_text, email_from, reply_to, cc, bcc, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: email_queue
columns: [id, tenant_id, email_to, email_cc, email_bcc, subject, body_html, body_text, email_from, reply_to, attachment_ids, status, attempts, max_attempts, error_message, message_id, opened_at, clicked_at, created_at, scheduled_at, sent_at, failed_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: logs
columns: [id, tenant_id, level, logger, message, stack_trace, user_id, ip_address, user_agent, request_id, model, record_id, metadata, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: user_id
references: auth.users(id)
- name: reports
columns: [id, tenant_id, name, code, description, model, report_type, query_template, template_file, default_format, is_public, active, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: report_executions
columns: [id, tenant_id, report_id, parameters, format, file_url, file_size, error_message, status, created_at, created_by, started_at, completed_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: report_id
references: system.reports(id)
- name: dashboards
columns: [id, tenant_id, name, description, layout, is_default, user_id, is_public, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: user_id
references: auth.users(id)
- name: dashboard_widgets
columns: [id, dashboard_id, widget_type, title, config, position, data_source, query_params, refresh_interval, created_at, updated_at]
foreign_keys:
- column: dashboard_id
references: system.dashboards(id)
- name: field_tracking_config
columns: [id, table_schema, table_name, field_name, track_changes, field_type, display_label, created_at]
foreign_keys: []
- name: change_log
columns: [id, tenant_id, table_schema, table_name, record_id, changed_by, changed_at, change_type, field_name, field_label, old_value, new_value, change_context, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: changed_by
references: auth.users(id)
functions:
- name: notify_followers
purpose: "Notifica a los seguidores de un registro cuando hay un nuevo mensaje"
- name: mark_activities_as_overdue
purpose: "Marca actividades vencidas como overdue (ejecutar diariamente)"
- name: clean_old_logs
purpose: "Limpia logs antiguos (mantener solo críticos)"
- name: track_field_changes
purpose: "Función trigger para trackear cambios automáticamente según configuración en field_tracking_config (patrón mail.thread de Odoo)"
triggers:
- name: trg_messages_updated_at
table: messages
- name: trg_message_templates_updated_at
table: message_templates
- name: trg_reports_updated_at
table: reports
- name: trg_dashboards_updated_at
table: dashboards
- name: trg_dashboard_widgets_updated_at
table: dashboard_widgets
indexes:
- name: idx_messages_tenant_id
table: messages
columns: [tenant_id]
- name: idx_messages_model_record
table: messages
columns: [model, record_id]
- name: idx_notifications_tenant_id
table: notifications
columns: [tenant_id]
- name: idx_notifications_user_id
table: notifications
columns: [user_id]
- name: idx_activities_tenant_id
table: activities
columns: [tenant_id]
- name: idx_logs_tenant_id
table: logs
columns: [tenant_id]
- name: idx_logs_level
table: logs
columns: [level]
- name: idx_change_log_tenant_id
table: change_log
columns: [tenant_id]
- name: idx_change_log_record
table: change_log
columns: [table_schema, table_name, record_id]
rls_policies:
- name: tenant_isolation_messages
table: messages
- name: tenant_isolation_notifications
table: notifications
- name: tenant_isolation_activities
table: activities
- name: tenant_isolation_message_templates
table: message_templates
- name: tenant_isolation_logs
table: logs
- name: tenant_isolation_reports
table: reports
- name: tenant_isolation_report_executions
table: report_executions
- name: tenant_isolation_dashboards
table: dashboards
- name: tenant_isolation_change_log
table: change_log
views: []
# ============================================================================
# RESUMEN DE INVENTARIO (ACTUALIZADO 2025-12-09)
# ============================================================================
summary:
total_schemas: 12
total_enums: 49
total_tables: 144
total_functions: 52
total_triggers: 95
total_indexes: 350+
total_rls_policies: 80+
total_views: 8
schemas:
- name: prerequisites
tables: 0
functions: 9
types: 2
- name: auth
tables: 26 # 10 (auth.sql) + 16 (auth-extensions.sql)
functions: 10
enums: 4
- name: core
tables: 12
functions: 3
enums: 4
- name: analytics
tables: 7
functions: 4
enums: 3
- name: financial
tables: 15
functions: 4
enums: 10
- name: inventory
tables: 20 # 10 (inventory.sql) + 10 (inventory-extensions.sql)
functions: 8
enums: 6
- name: purchase
tables: 8
functions: 2
enums: 3
- name: sales
tables: 10
functions: 3
enums: 5
- name: projects
tables: 10
functions: 3
enums: 6
- name: system
tables: 13
functions: 4
enums: 7
- name: billing
tables: 11
functions: 3
enums: 5
- name: crm
tables: 6
functions: 0
enums: 4
- name: hr
tables: 6
functions: 0
enums: 5
# ============================================================================
# SCHEMA: billing (NUEVO - SaaS/Multi-tenant)
# DDL: 10-billing.sql - 11 tablas
# ============================================================================
billing:
enums:
- name: subscription_status
values: [trialing, active, past_due, paused, cancelled, suspended, expired]
- name: billing_cycle
values: [monthly, quarterly, semi_annual, annual]
- name: payment_method_type
values: [card, bank_transfer, paypal, oxxo, spei, other]
- name: invoice_status
values: [draft, open, paid, void, uncollectible]
- name: payment_status
values: [pending, processing, succeeded, failed, cancelled, refunded]
tables:
- name: subscription_plans
columns: [id, code, name, description, price_monthly, price_yearly, currency_code, max_users, max_companies, max_storage_gb, max_api_calls_month, features, is_active, is_public, is_default, trial_days, sort_order, created_at, created_by, updated_at, updated_by]
foreign_keys: []
note: "Planes globales (no por tenant)"
- name: tenant_owners
columns: [id, tenant_id, user_id, ownership_type, billing_email, billing_phone, billing_name, created_at, created_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: user_id
references: auth.users(id)
- name: subscriptions
columns: [id, tenant_id, plan_id, status, billing_cycle, trial_start_at, trial_end_at, current_period_start, current_period_end, cancelled_at, cancel_at_period_end, paused_at, discount_percent, coupon_code, stripe_subscription_id, stripe_customer_id, created_at, created_by, updated_at, updated_by]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: plan_id
references: billing.subscription_plans(id)
- name: payment_methods
columns: [id, tenant_id, type, is_default, card_last_four, card_brand, card_exp_month, card_exp_year, billing_name, billing_email, billing_address_line1, billing_address_line2, billing_city, billing_state, billing_postal_code, billing_country, stripe_payment_method_id, created_at, created_by, updated_at, deleted_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: invoices
columns: [id, tenant_id, subscription_id, invoice_number, status, period_start, period_end, due_date, paid_at, voided_at, subtotal, tax_amount, discount_amount, total, amount_paid, amount_due, currency_code, customer_name, customer_tax_id, customer_email, customer_address, pdf_url, cfdi_uuid, cfdi_xml_url, stripe_invoice_id, notes, created_at, created_by, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: subscription_id
references: billing.subscriptions(id)
- name: invoice_lines
columns: [id, invoice_id, description, quantity, unit_price, amount, period_start, period_end, created_at]
foreign_keys:
- column: invoice_id
references: billing.invoices(id)
- name: payments
columns: [id, tenant_id, invoice_id, payment_method_id, amount, currency_code, status, paid_at, failed_at, refunded_at, failure_reason, failure_code, transaction_id, stripe_payment_intent_id, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: invoice_id
references: billing.invoices(id)
- column: payment_method_id
references: billing.payment_methods(id)
- name: usage_records
columns: [id, tenant_id, subscription_id, metric_type, quantity, billing_period, recorded_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: subscription_id
references: billing.subscriptions(id)
- name: coupons
columns: [id, code, name, description, discount_type, discount_value, currency_code, max_redemptions, max_redemptions_per_tenant, redemptions_count, valid_from, valid_until, applicable_plans, is_active, created_at, created_by]
foreign_keys: []
- name: coupon_redemptions
columns: [id, coupon_id, tenant_id, subscription_id, redeemed_at, redeemed_by]
foreign_keys:
- column: coupon_id
references: billing.coupons(id)
- column: tenant_id
references: auth.tenants(id)
- column: subscription_id
references: billing.subscriptions(id)
- name: subscription_history
columns: [id, subscription_id, event_type, previous_plan_id, new_plan_id, previous_status, new_status, metadata, notes, created_at, created_by]
foreign_keys:
- column: subscription_id
references: billing.subscriptions(id)
- column: previous_plan_id
references: billing.subscription_plans(id)
- column: new_plan_id
references: billing.subscription_plans(id)
functions:
- name: get_tenant_plan
purpose: "Obtiene información del plan actual de un tenant"
- name: can_add_user
purpose: "Verifica si el tenant puede agregar más usuarios según su plan"
- name: has_feature
purpose: "Verifica si una feature está habilitada para el tenant"
rls_policies: []
note: "Sin RLS - gestionado a nivel aplicación por razones de seguridad"
# ============================================================================
# SCHEMA: crm (NUEVO - Customer Relationship Management)
# DDL: 11-crm.sql - 6 tablas
# ============================================================================
crm:
enums:
- name: lead_status
values: [new, contacted, qualified, converted, lost]
- name: opportunity_status
values: [open, won, lost]
- name: activity_type
values: [call, email, meeting, task, note]
- name: lead_source
values: [website, phone, email, referral, social_media, advertising, event, other]
tables:
- name: lead_stages
columns: [id, tenant_id, name, sequence, is_won, probability, requirements, active, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: opportunity_stages
columns: [id, tenant_id, name, sequence, is_won, probability, requirements, active, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: lost_reasons
columns: [id, tenant_id, name, description, active, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: leads
columns: [id, tenant_id, company_id, name, ref, contact_name, email, phone, mobile, website, company_name, job_position, industry, employee_count, annual_revenue, street, city, state, zip, country, stage_id, status, user_id, sales_team_id, source, campaign_id, medium, priority, probability, expected_revenue, date_open, date_closed, date_deadline, date_last_activity, partner_id, opportunity_id, lost_reason_id, lost_notes, description, notes, tags, created_by, updated_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: stage_id
references: crm.lead_stages(id)
- column: user_id
references: auth.users(id)
- column: sales_team_id
references: sales.sales_teams(id)
- column: partner_id
references: core.partners(id)
- column: lost_reason_id
references: crm.lost_reasons(id)
- name: opportunities
columns: [id, tenant_id, company_id, name, ref, partner_id, contact_name, email, phone, stage_id, status, user_id, sales_team_id, priority, probability, expected_revenue, recurring_revenue, recurring_plan, date_deadline, date_closed, date_last_activity, lead_id, source, campaign_id, medium, lost_reason_id, lost_notes, quotation_id, order_id, description, notes, tags, created_by, updated_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: partner_id
references: core.partners(id)
- column: stage_id
references: crm.opportunity_stages(id)
- column: user_id
references: auth.users(id)
- column: sales_team_id
references: sales.sales_teams(id)
- column: lead_id
references: crm.leads(id)
- column: lost_reason_id
references: crm.lost_reasons(id)
- column: quotation_id
references: sales.quotations(id)
- column: order_id
references: sales.sales_orders(id)
- name: activities
columns: [id, tenant_id, res_model, res_id, activity_type, summary, description, date_deadline, date_done, user_id, assigned_to, done, created_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: user_id
references: auth.users(id)
- column: assigned_to
references: auth.users(id)
rls_policies:
- name: tenant_isolation_lead_stages
table: lead_stages
- name: tenant_isolation_opportunity_stages
table: opportunity_stages
- name: tenant_isolation_lost_reasons
table: lost_reasons
- name: tenant_isolation_leads
table: leads
- name: tenant_isolation_opportunities
table: opportunities
- name: tenant_isolation_crm_activities
table: activities
# ============================================================================
# SCHEMA: hr (NUEVO - Human Resources)
# DDL: 12-hr.sql - 6 tablas
# ============================================================================
hr:
enums:
- name: contract_status
values: [draft, active, expired, terminated, cancelled]
- name: contract_type
values: [permanent, temporary, contractor, internship, part_time]
- name: leave_status
values: [draft, submitted, approved, rejected, cancelled]
- name: leave_type
values: [vacation, sick, personal, maternity, paternity, bereavement, unpaid, other]
- name: employee_status
values: [active, inactive, on_leave, terminated]
tables:
- name: departments
columns: [id, tenant_id, company_id, name, code, parent_id, manager_id, description, color, active, created_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: parent_id
references: hr.departments(id)
- column: manager_id
references: hr.employees(id)
- name: job_positions
columns: [id, tenant_id, name, department_id, description, requirements, responsibilities, min_salary, max_salary, active, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: department_id
references: hr.departments(id)
- name: employees
columns: [id, tenant_id, company_id, employee_number, first_name, last_name, middle_name, user_id, birth_date, gender, marital_status, nationality, identification_id, identification_type, social_security_number, tax_id, email, work_email, phone, work_phone, mobile, emergency_contact, emergency_phone, street, city, state, zip, country, department_id, job_position_id, manager_id, hire_date, termination_date, status, bank_name, bank_account, bank_clabe, photo_url, notes, created_by, updated_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: user_id
references: auth.users(id)
- column: department_id
references: hr.departments(id)
- column: job_position_id
references: hr.job_positions(id)
- column: manager_id
references: hr.employees(id)
- name: contracts
columns: [id, tenant_id, company_id, employee_id, name, reference, contract_type, status, job_position_id, department_id, date_start, date_end, trial_date_end, wage, wage_type, currency_id, resource_calendar_id, hours_per_week, vacation_days, christmas_bonus_days, document_url, notes, created_by, updated_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: employee_id
references: hr.employees(id)
- column: job_position_id
references: hr.job_positions(id)
- column: department_id
references: hr.departments(id)
- column: currency_id
references: core.currencies(id)
- name: leave_types
columns: [id, tenant_id, name, code, leave_type, requires_approval, max_days, is_paid, color, active, created_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- name: leaves
columns: [id, tenant_id, company_id, employee_id, leave_type_id, name, date_from, date_to, number_of_days, status, description, approved_by, approved_at, rejection_reason, created_by, updated_by, created_at, updated_at]
foreign_keys:
- column: tenant_id
references: auth.tenants(id)
- column: company_id
references: auth.companies(id)
- column: employee_id
references: hr.employees(id)
- column: leave_type_id
references: hr.leave_types(id)
- column: approved_by
references: auth.users(id)
rls_policies:
- name: tenant_isolation_departments
table: departments
- name: tenant_isolation_job_positions
table: job_positions
- name: tenant_isolation_employees
table: employees
- name: tenant_isolation_contracts
table: contracts
- name: tenant_isolation_leave_types
table: leave_types
- name: tenant_isolation_leaves
table: leaves
# ============================================================================
# SCHEMA: auth (EXTENSIONES - auth-extensions.sql)
# DDL: 01-auth-extensions.sql - 16 tablas adicionales
# ============================================================================
auth_extensions:
note: "Estas tablas complementan el schema auth base (01-auth.sql)"
tables:
- name: groups
purpose: "Grupos de usuarios para permisos"
- name: group_implied
purpose: "Herencia entre grupos"
- name: user_groups
purpose: "Asignación usuarios a grupos"
- name: models
purpose: "Registro de modelos del sistema"
- name: model_access
purpose: "Permisos CRUD por modelo y grupo"
- name: record_rules
purpose: "Reglas de acceso a nivel registro (domain filters)"
- name: rule_groups
purpose: "Asignación reglas a grupos"
- name: model_fields
purpose: "Campos de modelos"
- name: field_permissions
purpose: "Permisos a nivel campo"
- name: api_keys
purpose: "API Keys para autenticación"
- name: trusted_devices
purpose: "Dispositivos de confianza para 2FA"
- name: verification_codes
purpose: "Códigos de verificación (2FA, email)"
- name: mfa_audit_log
purpose: "Auditoría de operaciones MFA"
- name: oauth_providers
purpose: "Proveedores OAuth2 configurados"
- name: oauth_user_links
purpose: "Vinculación usuarios con cuentas OAuth"
- name: oauth_states
purpose: "Estados temporales para flow OAuth"
# ============================================================================
# SCHEMA: inventory (EXTENSIONES - inventory-extensions.sql)
# DDL: 05-inventory-extensions.sql - 10 tablas adicionales
# ============================================================================
inventory_extensions:
note: "Estas tablas complementan el schema inventory base (05-inventory.sql)"
tables:
- name: stock_valuation_layers
purpose: "Capas de valoración FIFO/AVCO"
- name: category_stock_accounts
purpose: "Cuentas contables por categoría de producto"
- name: valuation_settings
purpose: "Configuración de valoración por empresa"
- name: lots
purpose: "Lotes de productos (trazabilidad)"
- name: stock_move_consume_rel
purpose: "Relación movimientos produce/consume"
- name: removal_strategies
purpose: "Estrategias de remoción (FIFO/LIFO/AVCO)"
- name: inventory_count_sessions
purpose: "Sesiones de conteo cíclico"
- name: inventory_count_lines
purpose: "Líneas de conteo"
- name: abc_classification_rules
purpose: "Reglas de clasificación ABC"
- name: product_abc_classification
purpose: "Clasificación ABC de productos"
# ============================================================================
# FIN DEL INVENTARIO
# Última actualización: 2025-12-09
# Total: 12 schemas, 144 tablas
# ============================================================================