Saltar al contenido principal

Guía de Administrador — Renglones Presupuestarios y Centros de Costo

Cambio importante (mayo 2026): Tras el Sub-proyecto 1, los antiguos "centros de costo" se separaron en tres tablas independientes. Esta guía cubre la administración de las 3:

  • Renglones presupuestarios (budget_positions, ex cost_centers) — partidas presupuestarias.
  • Áreas funcionales (functional_areas) — clasificador PDVSA (26 códigos).
  • Centros de costo (cost_centers nuevo) — unidades organizacionales (22 con responsable y departamento).

Guía técnica para administradores de las dimensiones contables del ERP del Consorcio Alvorada & Cladoca.


Configuración Inicial

1. Crear un Renglón Presupuestario

Acceda a Presupuesto → Renglones Presupuestarios o use la API:

POST /api/budget/positions
Content-Type: application/json

{
"code": "ACE-1-1AL-LEV",
"name": "Levantamiento Topográfico - Proyecto Norte",
"description": "Servicios de levantamiento topográfico OPEX",
"costType": "OPEX",
"functionalAreaId": "<UUID del área 'LEV'>",
"category": "Servicios Técnicos",
"subCategory": "Levantamiento",
"status": "ACTIVE"
}

Campos requeridos:

  • code — Código único en el sistema (patrón ACE-{Cat}-{Sub}-{Área}).
  • name — Nombre descriptivo.
  • costTypeOPEX o CAPEX.
  • functionalAreaId — FK NOT NULL al área funcional PDVSA.

2. Crear un Centro de Costo (organizacional)

POST /api/accounting/cost-centers
Content-Type: application/json

{
"code": "CC-OPS-NORTE",
"name": "Operaciones Norte",
"type": "PRODUCTIVE",
"departmentId": "<UUID departamento OPS>",
"parentId": "<UUID CC-OPS>",
"managerId": "<UUID empleado responsable>",
"status": "ACTIVE"
}

3. Crear un Área Funcional

POST /api/accounting/functional-areas
Content-Type: application/json

{
"code": "WELL",
"name": "Pozos Especiales",
"description": "Servicios a pozos no clasificados en LEV/SCT/SST",
"category": "UPSTREAM_OPERATIONS",
"status": "ACTIVE"
}

Las 26 áreas funcionales iniciales se cargan automáticamente con la migración 20260501000001-create-functional-areas-table.js.

4. Importación Masiva de Renglones

Para cargar múltiples renglones use el endpoint de importación:

POST /api/budget/positions/import
Content-Type: multipart/form-data

file: renglones-presupuestarios.xlsx

Formato del archivo Excel:

codenamecostTypefunctionalAreaCodecategorysubCategory
ACE-1-1AL-LEVAlimentación LevantamientoOPEXLEVLogísticaAlimentación
ACE-CAPEX-INPRInversión Producción 2026CAPEXINPRConstrucciónProducción

El sistema resuelve functionalAreaCodefunctionalAreaId durante la importación.


Configuración de Permisos

Permisos del Módulo

PermisoDescripciónQuién debe tenerlo
budget:readVer dashboards y reportes de presupuestoTodos los usuarios con acceso a presupuestos
budget:positions:readVer renglones presupuestariosTodos los usuarios
budget:positions:writeCrear y editar renglonesAdministradores y Jefes de Área
accounting:cost-centers:readVer centros de costoTodos los usuarios
accounting:cost-centers:writeCrear/editar CCsAdministradores
accounting:functional-areas:readVer áreas funcionalesTodos los usuarios
accounting:functional-areas:writeCrear/editar áreasAdministradores y Gerencia Finanzas
accounting:mappings:readVer mapeos cuenta↔renglónContabilidad y Finanzas
accounting:mappings:writeCrear/editar mapeosContadores

Permisos legacy DEPRECATED: cost-centers:read|write redirigen a budget:positions:read|write durante 1 release.

Asignar Permisos en el Sistema

POST /api/roles/{roleId}/permissions
{
"permissions": [
"budget:positions:read",
"accounting:cost-centers:read",
"budget:read"
]
}

GET /api/users/{userId}/permissions

Vinculación con Planes Presupuestarios

Crear un Plan con Renglones y Centros de Costo

  1. Crear el BudgetPlan con budgetType: "OPEX" o "CAPEX".
  2. Crear BudgetLine referenciando budgetPositionId y costCenterId.
# 1. Crear plan OPEX
POST /api/budget/plans
{
"fiscalYear": 2026,
"budgetType": "OPEX",
"departmentId": "<UUID dept>",
"description": "Presupuesto Operacional 2026"
}

# 2. Crear línea con renglón + CC
POST /api/budget/lines
{
"budgetPlanId": "<UUID plan>",
"budgetPositionId": "<UUID renglón>",
"costCenterId": "<UUID CC>",
"categoryId": "<UUID categoría>",
"description": "Servicios de levantamiento Q1",
"plannedAmount": 150000
}

functional_area_id se infiere automáticamente desde budget_position.functional_area_id si no se proporciona.

Importante: BudgetLine no tiene columna budgetType. El tipo OPEX/CAPEX se determina siempre a través del BudgetPlan asociado. Nunca filtre directamente en BudgetLine.budgetType.

Validación: budget_position.cost_type debe coincidir con BudgetPlan.budgetType. Si no coinciden, la creación de la línea falla con 422.


Configurar Mapeos Cuenta ↔ Renglón

Reemplaza el JSONB cost_centers.accounting_accounts viejo. Use:

POST /api/accounting/account-position-links
{
"accountId": "<UUID cuenta 6.3.01.018>",
"budgetPositionId": "<UUID ACE-1-1AL-LEV>",
"role": "DEBIT_DEFAULT"
}

Reglas:

  • Sólo un DEBIT_DEFAULT por cuenta.
  • Sólo un CREDIT_DEFAULT por cuenta.
  • Múltiples ALLOWED por cuenta (whitelist amplia).

Migración de Datos Existentes

Los datos del modelo viejo se migraron automáticamente con las migraciones M1-M9 del Sub-proyecto 1. Snapshot del proceso:

MigraciónAcción
M1CREATE functional_areas + seed 26 áreas
M2RENAME cost_centersbudget_positions (preserva UUIDs)
M3ARCHIVE columnas mensuales en budget_positions_legacy_excel
M4UPDATE budget_positions.functional_area_id desde pdvsa_code
M5CREATE nueva cost_centers (organizacional) + seed 22 CCs
M6CREATE account_budget_position_links
M7EXTEND journal_entry_lines con dimensiones
M8EXTEND budget_lines, budget_commitments, afe_expenses con dimensiones
M9DROP columnas DEPRECATED

Si necesita reasignar áreas funcionales o renglones a CCs después del Sub-proyecto 1, use los endpoints PUT correspondientes — la lógica viene en journalEntryService y budgetLineService.


Configuración de Alertas Presupuestarias

Las alertas se generan automáticamente cuando la ejecución supera umbrales configurados. Para ajustar los umbrales, modifique las constantes en:

backend_erp/src/modules/budget/services/budgetAlertService.js

const ALERT_THRESHOLDS = {
WARNING: 0.80, // Alerta amarilla al 80%
CRITICAL: 0.95, // Alerta roja al 95%
};

Monitoreo y Resolución de Problemas

Verificar endpoint de ejecución por renglón

curl -H "Authorization: Bearer {token}" \
"http://localhost:5001/api/budget/dashboard/execution-by-position?fiscalYear=2026&costType=opex"

Respuesta esperada:

{
"fiscalYear": 2026,
"costType": "opex",
"positions": [
{
"budgetPositionId": "bp-...",
"code": "ACE-1-1AL-LEV",
"name": "Levantamiento - Alimentación",
"functionalAreaCode": "LEV",
"costType": "OPEX",
"totalPlanned": 150000,
"totalCommitted": 45000,
"totalExecuted": 80000,
"totalAvailable": 25000,
"executionPercentage": "53.33"
}
]
}

Problemas Comunes

Error: "column BudgetLine.budgetType does not exist"

Este error ocurre si el código intenta filtrar directamente en BudgetLine por budgetType. La columna no existe en esa tabla. El filtro debe aplicarse en el include de BudgetPlan:

// ❌ Incorrecto
where: { budgetType: 'OPEX' } // en BudgetLine

// ✅ Correcto
include: [{
model: BudgetPlan,
where: { budgetType: 'OPEX' },
attributes: []
}]

Error 422 al crear JournalEntryLine: "cost_center_id requerido para cuenta EXPENSE"

journalEntryService.create() valida que toda línea cuya cuenta sea EXPENSE o REVENUE lleve cost_center_id. Para FIXED_ASSET o INTANGIBLE_ASSET exige project_id. Asegure que los formularios y servicios upstream propaguen las dimensiones correctas.

Error 422: "no existe link en account_budget_position_links"

Si una línea trae budget_position_id, debe existir un link configurado para esa cuenta. Cree el link con POST /api/accounting/account-position-links.

Dashboard no muestra datos de renglones o CCs

  1. Verificar permisos: budget:positions:read, accounting:cost-centers:read.
  2. Verificar que las BudgetLines tienen budgetPositionId y costCenterId asignados.
  3. Revisar los logs del backend.

Respaldo y Mantenimiento

Tablas involucradas en el módulo

TablaDescripción
budget_positionsRenglones presupuestarios (149 en producción)
budget_positions_legacy_excelArchivo histórico de columnas mensuales
cost_centersCentros de costo organizacionales (22)
functional_areasÁreas funcionales PDVSA (26)
account_budget_position_linksMapeo cuenta ↔ renglón con rol
budget_plansPlanes presupuestarios (tiene budget_type)
budget_linesLíneas con budget_position_id, cost_center_id, functional_area_id
budget_executionsEjecuciones registradas
budget_commitmentsCompromisos con dimensiones propagadas
journal_entry_lines5 dimensiones contables por línea

Índices recomendados

-- Acelerar consultas de dashboard por dimensión
CREATE INDEX IF NOT EXISTS idx_budget_lines_position
ON budget_lines(budget_position_id);

CREATE INDEX IF NOT EXISTS idx_budget_lines_cost_center
ON budget_lines(cost_center_id);

CREATE INDEX IF NOT EXISTS idx_budget_positions_functional_area
ON budget_positions(functional_area_id) WHERE status = 'ACTIVE';

CREATE INDEX IF NOT EXISTS idx_je_lines_dim_combo
ON journal_entry_lines(cost_center_id, functional_area_id);

Referencias