10 KiB
MODELO DE DOMINIO: Contabilidad Analítica
Módulos: MGN-008 (Contabilidad Analítica) Fecha: 2025-11-24 Referencia Odoo: analytic Referencia Gamilit: No implementado
Diagrama de Entidades (Texto UML)
[AnalyticAccount]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- name: String
- code: String
- account_type: ENUM (project, department, cost_center, customer)
- parent_id: UUID (FK self)
- partner_id: UUID (FK)
- budget: Decimal
- status: ENUM (active, inactive, closed)
1 <----> * [AnalyticLine]
1 <----> * [AnalyticDistribution]
[AnalyticLine]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- analytic_account_id: UUID (FK)
- date: Date
- amount: Decimal
- unit_amount: Decimal (horas, cantidad)
- product_id: UUID (FK)
- employee_id: UUID (FK)
- description: String
- line_type: ENUM (expense, income, timesheet)
- source_document: String (ej: "invoice/123")
- source_model: String (ej: "Invoice")
- source_id: UUID
* <----> * [AnalyticTag]
[AnalyticDistribution]
- id: UUID (PK)
- source_line_id: UUID (FK)
- source_model: String (ej: "PurchaseOrderLine")
- analytic_account_id: UUID (FK)
- percentage: Decimal
- amount: Decimal
[AnalyticTag]
- id: UUID (PK)
- tenant_id: UUID (FK)
- name: String
- color: String
- tag_type: ENUM (phase, location, category)
* <----> * [AnalyticLine]
[AnalyticPlan]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- name: String
- description: Text
1 <----> * [AnalyticAccount]
Entidades Principales
1. AnalyticAccount (Cuenta Analítica)
Descripción: Cuenta para tracking de costos/ingresos por proyecto, departamento, centro de costo.
Atributos:
id: UUIDname: Nombre (ej: "Proyecto Torre A")code: Código (ej: "PRJ-001")account_type: project, department, cost_center, customerparent_id: Cuenta padre (jerarquía)partner_id: Cliente/Partner asociadobudget: Presupuesto asignadostatus: active, inactive, closed
Relaciones:
- 1 AnalyticAccount → N AnalyticLines
- 1 AnalyticAccount → N Subdepartments
- 1 AnalyticAccount → 1 Project (MGN-011)
Patrón Odoo: account.analytic.account Tipos:
- project: Proyectos (vinculado a MGN-011)
- department: Departamentos
- cost_center: Centros de costo
- customer: Por cliente
2. AnalyticLine (Línea Analítica)
Descripción: Registro individual de costo o ingreso en cuenta analítica.
Atributos:
id: UUIDanalytic_account_id: Cuenta analíticadate: Fecha del registroamount: Monto (negativo=costo, positivo=ingreso)unit_amount: Cantidad (horas para timesheet, unidades para productos)product_id: Producto asociado (opcional)employee_id: Empleado asociado (para timesheet)description: Descripciónline_type: expense, income, timesheetsource_document: Documento origen (ej: "invoice/123")source_model: Modelo origen (ej: "Invoice")source_id: ID del registro origen
Relaciones:
- N AnalyticLines → 1 AnalyticAccount
- N AnalyticLines ←→ N AnalyticTags
Patrón Odoo: account.analytic.line Creación:
- Manual: Usuario crea línea directamente
- Automática: Generada desde transacciones (facturas, PO, SO, timesheet)
3. AnalyticDistribution (Distribución Analítica)
Descripción: Distribución de un monto a múltiples cuentas analíticas.
Atributos:
id: UUIDsource_line_id: Línea origen (ej: PurchaseOrderLine)source_model: Modelo origenanalytic_account_id: Cuenta analítica destinopercentage: Porcentaje (ej: 60%)amount: Monto calculado
Relaciones:
- N AnalyticDistributions → 1 AnalyticAccount
Patrón Odoo: account.analytic.distribution (Odoo 16+) Validación: SUM(percentage) = 100% por source_line_id
Ejemplo:
Compra de $10,000
- 60% → Proyecto A ($6,000)
- 40% → Proyecto B ($4,000)
4. AnalyticTag (Etiqueta Analítica)
Descripción: Etiqueta adicional para clasificación analítica.
Atributos:
id: UUIDname: Nombre (ej: "Fase 1", "Torre Norte")color: Color para UItag_type: phase, location, category
Relaciones:
- N AnalyticTags ←→ N AnalyticLines
Patrón Odoo: account.analytic.tag Uso: Clasificación adicional cross-cutting (no jerárquica)
Ejemplos:
- Tags de fase: "Planeación", "Ejecución", "Cierre"
- Tags de ubicación: "Torre A", "Torre B", "Área Común"
- Tags de categoría: "CAPEX", "OPEX"
5. AnalyticPlan (Plan Analítico)
Descripción: Agrupación de cuentas analíticas (opcional, para multi-dimensión).
Atributos:
id: UUIDname: Nombre del plandescription: Descripción
Relaciones:
- 1 AnalyticPlan → N AnalyticAccounts
Patrón Odoo: account.analytic.plan (Odoo 16+) Uso: Análisis multi-dimensional (por proyecto, por departamento, etc.)
Reglas de Negocio
RN-ANA-001: Generación Automática de Líneas
- Al validar factura: generar líneas analíticas desde invoice_lines con analytic_account_id
- Al validar PO: generar líneas desde purchase_order_lines
- Al validar SO: generar líneas desde sale_order_lines
- Al validar timesheet: generar líneas desde timesheet
RN-ANA-002: Tipo de Línea
- expense: Monto negativo (costos)
- Compras, gastos, timesheet
- income: Monto positivo (ingresos)
- Ventas, facturación
- timesheet: Tipo especial (puede ser expense si se valora)
RN-ANA-003: Distribución 100%
- Si línea tiene distribución analítica, SUM(percentage) = 100%
- Validación antes de guardar
RN-ANA-004: Balance Analítico
- Balance = SUM(amount WHERE analytic_account_id = X)
- Balance positivo: más ingresos que costos
- Balance negativo: más costos que ingresos
RN-ANA-005: Jerarquía de Cuentas
- Cuentas pueden tener parent_id (jerarquía)
- Balance se puede calcular recursivamente (cuenta + subcuentas)
RN-ANA-006: Presupuesto vs Real
- budget: Presupuesto asignado
- real: SUM(amount WHERE line_type='expense')
- variance: budget - real
- Alertas si variance < 0 (sobre presupuesto)
RN-ANA-007: Tags Multi-Dimensionales
- Una línea puede tener múltiples tags
- Filtros combinados: Proyecto X + Fase 1 + CAPEX
RN-ANA-008: Inmutabilidad
- Líneas analíticas generadas automáticamente no se editan manualmente
- Si se corrige documento origen, se regeneran líneas
Casos de Uso Principales
- UC-ANA-001: Administrador crea cuenta analítica para proyecto
- UC-ANA-002: Usuario asigna cuenta analítica a línea de PO
- UC-ANA-003: Usuario distribuye costo a múltiples cuentas (60%-40%)
- UC-ANA-004: Sistema genera líneas analíticas al validar factura
- UC-ANA-005: Empleado registra timesheet → genera línea analítica
- UC-ANA-006: Usuario consulta balance por cuenta analítica (P&L por proyecto)
- UC-ANA-007: Usuario compara presupuesto vs real
- UC-ANA-008: Usuario filtra líneas analíticas por tags
- UC-ANA-009: Gerente consulta reporte de rentabilidad por proyecto
Validaciones y Constraints
-- Code único por company
UNIQUE (tenant_id, company_id, code)
-- Cuenta no puede ser su propia padre
CHECK (parent_id != id)
-- Presupuesto >= 0
CHECK (budget >= 0)
-- Distribución: percentage entre 0 y 100
CHECK (percentage >= 0 AND percentage <= 100)
-- SUM(percentage) = 100 por source_line_id
-- (trigger custom)
-- unit_amount >= 0 (para timesheet)
CHECK (unit_amount >= 0)
Índices Requeridos
CREATE INDEX idx_analytic_accounts_company_id ON analytics.analytic_accounts(company_id);
CREATE INDEX idx_analytic_accounts_parent_id ON analytics.analytic_accounts(parent_id);
CREATE INDEX idx_analytic_accounts_status ON analytics.analytic_accounts(status);
CREATE INDEX idx_analytic_lines_analytic_account_id ON analytics.analytic_lines(analytic_account_id);
CREATE INDEX idx_analytic_lines_date ON analytics.analytic_lines(date);
CREATE INDEX idx_analytic_lines_employee_id ON analytics.analytic_lines(employee_id);
CREATE INDEX idx_analytic_lines_line_type ON analytics.analytic_lines(line_type);
CREATE INDEX idx_analytic_distributions_source_line_id ON analytics.analytic_distributions(source_line_id);
CREATE INDEX idx_analytic_distributions_analytic_account_id ON analytics.analytic_distributions(analytic_account_id);
Integración con Otros Módulos
Con MGN-004 (Financiero)
- Invoice lines tienen analytic_account_id
- Al validar invoice, genera analytic lines
Con MGN-006 (Compras)
- Purchase order lines tienen analytic_account_id
- Al validar PO, genera analytic lines (expense)
Con MGN-007 (Ventas)
- Sale order lines tienen analytic_account_id
- Al validar SO, genera analytic lines (income)
Con MGN-010 (RRHH)
- Timesheet tiene analytic_account_id
- Al validar timesheet, genera analytic lines (expense o neutral)
Con MGN-011 (Proyectos)
- Project tiene analytic_account_id (1-1)
- Todos los costos/ingresos del proyecto se registran en su cuenta analítica
Con MGN-012 (Reportes)
- Reportes analíticos:
- P&L por cuenta analítica
- Balance por proyecto
- Presupuesto vs Real
- Análisis por tags
Vistas y Reportes Estándar
1. Balance Analítico
SELECT
analytic_account_id,
SUM(CASE WHEN line_type = 'expense' THEN amount ELSE 0 END) as total_costs,
SUM(CASE WHEN line_type = 'income' THEN amount ELSE 0 END) as total_income,
SUM(amount) as balance
FROM analytics.analytic_lines
WHERE tenant_id = :tenant_id
GROUP BY analytic_account_id
2. Presupuesto vs Real
SELECT
aa.name,
aa.budget,
SUM(al.amount) as real_cost,
aa.budget - SUM(al.amount) as variance
FROM analytics.analytic_accounts aa
LEFT JOIN analytics.analytic_lines al ON aa.id = al.analytic_account_id
WHERE al.line_type = 'expense'
GROUP BY aa.id
Referencias
Importancia: ⭐⭐⭐⭐⭐ CRÍTICO para ERPs de proyectos