Servicio de Depreciación de Activo Fijo
Orchestrator Services
Activo fijoOrchestratorDepreciación
Propósito
Section titled “Propósito”El servicio de depreciación de activo fijo coordina el cálculo mensual de una cuota por activo, la persistencia del resultado y la contabilización posterior del detalle contable asociado. Su función es convertir el estado de cada activo en registros auditables que puedan consultarse, contabilizarse, reversarse o anularse.
Esta página describe el flujo técnico actual de forma pública. No incluye rutas locales, credenciales, nombres de bases de datos de clientes ni detalles operativos que dependan de un entorno privado.
Responsabilidades del Servicio
Section titled “Responsabilidades del Servicio”El servicio concentra cuatro responsabilidades:
- leer el activo, su categoría y cuotas anteriores;
- validar el periodo, el estado del activo y el tipo de depreciación solicitado;
- calcular y registrar una cuota mensual del periodo;
- contabilizar la cuota generando líneas para gasto, depreciación acumulada y corrección monetaria aplicable.
La lógica no recalcula periodos cerrados. Cada cuota persistida conserva el estado usado en el cálculo para mantener trazabilidad y para impedir duplicidad de cuotas no anuladas en el mismo periodo.
Dependencias Conceptuales
Section titled “Dependencias Conceptuales”DirectoryOrchestrator
- DepreciacionService
- DepreciacionRepository
- ActivoFijoRepository
DirectoryMother
- activo_fijo.categorias_activo
- activo_fijo.activos
- activo_fijo.depreciacion
- activo_fijo.depreciacion_detalle
- parametros.correccion_monetaria
Flujo de Generación
Section titled “Flujo de Generación”Los fragmentos siguientes muestran el flujo público del servicio por etapa. Los nombres de repositorio y los campos corresponden al dominio actual; los identificadores reales se expresan como parámetros o placeholders.
-
Recibir el contexto de servicio y el DTO de generación.
async generar(ctx: ServiceContext,data: GenerarDepreciacionDTO,): Promise<ServiceResult<DepreciacionEntry>> {this.validateRequired(data, ['activo_id','periodo_mes','tipo_depreciacion',]);} -
Validar el tipo de depreciación y que el periodo sea el primer día del mes.
if (!['NORMAL', 'ACELERADA'].includes(data.tipo_depreciacion)) {throw new ValidationError('tipo_depreciacion debe ser NORMAL o ACELERADA');}if (!/^\d{4}-\d{2}-01$/.test(data.periodo_mes)) {throw new ValidationError('periodo_mes debe ser el primer día del mes (formato YYYY-MM-01)',);} -
Abrir una transacción, cargar el activo y exigir que esté en estado
ACTIVO.return this.withTransaction(ctx, async (client, outbox) => {const activo = await ActivoFijoRepository.findActivoById(client,data.activo_id,);this.assertExists(activo, 'ActivoFijo', String(data.activo_id));if (activo.estado !== 'ACTIVO') {throw new ValidationError('Solo se puede depreciar activos en estado ACTIVO',);}}); -
Verificar que el periodo no sea anterior al inicio de depreciación del activo.
const periodoDate = this.parsePeriodMonth(data.periodo_mes);const fechaBase = activo.fecha_inicio_dep ?? activo.fecha_compra;const inicioDepMes = this.toMonthStart(fechaBase);if (periodoDate < inicioDepMes) {throw new ValidationError('El período es anterior al inicio de depreciación del activo',);} -
Impedir cuotas duplicadas o periodos anteriores al último periodo depreciado.
const existe = await DepreciacionRepository.existePeriodo(client,data.activo_id,data.periodo_mes,);if (existe) {throw new ValidationError(`Ya existe una cuota para el período ${data.periodo_mes}`,);}const ultimaCuota = await DepreciacionRepository.getUltimaCuota(client,data.activo_id,); -
Resolver vida útil remanente según el tipo solicitado en el DTO.
const mesesYaDepreciados = ultimaCuota?.periodo_numero ?? 0;const anosVidaUtil =data.tipo_depreciacion === 'ACELERADA'? activo.dep_acelerada_anos ?? activo.vida_util_anos: activo.vida_util_anos;const mesesVidaUtilTotal = anosVidaUtil * 12;const mesesVidaUtilRemanente = mesesVidaUtilTotal - mesesYaDepreciados;if (mesesVidaUtilRemanente <= 0) {throw new ValidationError('El activo ya agotó su vida útil');} -
Obtener el factor de corrección monetaria y actualizar la base del cálculo.
const cm = await this.getCorreccionMonetaria(anioPeriodo,mesOrigenCM,mesPeriodo,);const montoNetoActualizado = Number((montoNetoBase * cm.factor).toFixed(2),);const depAnterior = Number((depBase * cm.factor).toFixed(2));const montoDepreciableRemanente = Number((montoNetoActualizado - depAnterior).toFixed(2),); -
Calcular una cuota mensual para el periodo.
const cuotaBaseMensual =montoDepreciableRemanente / mesesVidaUtilRemanente;let cuota = Number(Math.min(cuotaBaseMensual, montoDepreciableRemanente).toFixed(2),);if (cuota <= 0) {cuota = Number(montoDepreciableRemanente.toFixed(2));} -
Persistir la cuota calculada en
activo_fijo.depreciacion.const entry = await DepreciacionRepository.create(client,{activo_id: data.activo_id,periodo_mes: data.periodo_mes,tipo_depreciacion: data.tipo_depreciacion,periodo_numero: mesesYaDepreciados + 1,meses_aplicados: 1,cuota_depreciacion: cuota,dep_acumulada_anterior: depAnterior,dep_acumulada_posterior: depPosterior,valor_libro: valorLibro,cm_factor: cm.factor,cm_mes_origen: mesOrigenCM,notas: data.notas?.trim() || null,},ctx.userId,); -
Publicar el evento de dominio y devolver la cuota generada.
outbox.queue('depreciacion:calculada', {activoFijoId: String(data.activo_id),periodo: { anio: anioPeriodo, mes: mesPeriodo },monto: cuota,vidaUtilRestanteMeses: Math.max(mesesVidaUtilRemanente - 1, 0),});return this.success(entry);
Flujo de Contabilización
Section titled “Flujo de Contabilización”La generación de la cuota no inserta líneas en activo_fijo.depreciacion_detalle. El detalle contable se crea cuando una cuota PENDIENTE se contabiliza.
-
Cargar la cuota pendiente y el activo asociado.
const dep = await DepreciacionRepository.findById(client, id);if (!dep || dep.estado !== 'PENDIENTE') {throw new ValidationError('Cuota no encontrada o no está en estado PENDIENTE',);}const activo = await ActivoFijoRepository.findActivoById(client, dep.activo_id);if (!activo) {throw new ValidationError('Activo no encontrado');} -
Cargar la categoría para obtener las cuentas contables.
const categoria = await ActivoFijoRepository.findCategoriaById(client,activo.categoria_id,);if (!categoria) {throw new ValidationError('Categoría del activo no encontrada');} -
Crear las dos líneas base de depreciación.
const cuota = Number(dep.cuota_depreciacion);const detalleRows = [];detalleRows.push({depreciacion_id: id,tipo_linea: 'CUOTA_DEP',cuenta_codigo: categoria.cuenta_gasto_dep_codigo,monto: cuota,es_debito: true,},{depreciacion_id: id,tipo_linea: 'CUOTA_DEP',cuenta_codigo: categoria.cuenta_dep_acumulada_codigo,monto: cuota,es_debito: false,},); -
Agregar líneas de corrección monetaria si el factor aplicado es distinto de
1.if (Number(dep.cm_factor) !== 1) {detalleRows.push({depreciacion_id: id,tipo_linea: 'CM_ACTIVO',cuenta_codigo: categoria.cuenta_activo_codigo,monto: ajusteCMActivo,es_debito: true,},{depreciacion_id: id,tipo_linea: 'CM_ACTIVO',cuenta_codigo: '4201002',monto: ajusteCMActivo,es_debito: false,},);} -
Insertar el detalle y cambiar la cuota a estado
CONTABILIZADO.await DepreciacionRepository.insertDetalle(client, detalleRows, ctx.userId);const entry = await DepreciacionRepository.contabilizar(client,id,ctx.userId,);return this.success(entry);
Entradas
Section titled “Entradas”| Entrada | Descripción |
|---|---|
ctx | Contexto de servicio con base tenant y usuario ejecutor. |
activo_id | Activo específico sobre el cual se genera la cuota. |
periodo_mes | Mes contable en formato YYYY-MM-01. |
tipo_depreciacion | Valor explícito NORMAL o ACELERADA. |
notas | Texto opcional asociado a la cuota. |
Los identificadores reales deben tratarse como datos de entorno. En documentación pública, usar placeholders como $TENANT_ID, $PERIODO o $ACTIVO_ID.
Cálculo de Cuota
Section titled “Cálculo de Cuota”La cuota periódica se expresa conceptualmente así:
Donde:
A_actualizadoes el monto neto base actualizado por corrección monetaria;D_acum. actualizadaes la depreciación acumulada base actualizada por corrección monetaria;V_útil remanentecorresponde a los meses de vida útil total menos los meses ya depreciados.
El servicio registra una cuota mensual única para el periodo, con meses_aplicados igual a 1.
Persistencia
Section titled “Persistencia”activo_fijo.depreciacion
Section titled “activo_fijo.depreciacion”Registra una cuota por activo y periodo. Conserva el tipo de depreciación aplicado, la cuota, el valor libro, el factor de corrección monetaria y los acumulados antes y después del cálculo.
| Campo conceptual | Uso |
|---|---|
periodo_mes | Mes contable al que pertenece la cuota. |
tipo_depreciacion | NORMAL o ACELERADA. |
periodo_numero | Número secuencial de cuota del activo. |
meses_aplicados | Meses depreciados por la cuota; actualmente 1. |
cuota_depreciacion | Monto calculado. |
dep_acumulada_anterior | Estado previo actualizado. |
dep_acumulada_posterior | Estado posterior actualizado. |
valor_libro | Valor contable restante. |
cm_factor | Factor de corrección monetaria aplicado. |
cm_mes_origen | Mes origen usado para consultar corrección monetaria. |
estado | Controla si la cuota está pendiente, contabilizada o anulada. |
activo_fijo.depreciacion_detalle
Section titled “activo_fijo.depreciacion_detalle”Registra las líneas contables generadas al contabilizar una cuota.
| Tipo de línea | Debe | Haber |
|---|---|---|
CUOTA_DEP | gasto por depreciación de la categoría | depreciación acumulada de la categoría |
CM_ACTIVO | cuenta de activo de la categoría | 4201002 |
CM_DEP_ACUM | 3401004 | depreciación acumulada de la categoría |
Separar la cuota base de los ajustes permite reportar depreciación y corrección monetaria sin mezclar sus efectos.
Tipo de Depreciación
Section titled “Tipo de Depreciación”El servicio no decide el tipo de depreciación desde configuración de empresa. El llamador envía tipo_depreciacion en el DTO y el servicio valida que sea NORMAL o ACELERADA.
Cuando el tipo es NORMAL, usa vida_util_anos. Cuando el tipo es ACELERADA, usa dep_acelerada_anos si existe; si no existe, usa vida_util_anos como respaldo. La cuota persistida conserva el tipo aplicado.
Consultas
Section titled “Consultas”Depreciación por activo
Section titled “Depreciación por activo”DepreciacionRepository.findByActivo consulta las cuotas de un activo y agrega nombre de activo y categoría.
Depreciación por periodo
Section titled “Depreciación por periodo”DepreciacionRepository.findByPeriodo consulta las cuotas de un mes contable y permite filtrar por estado.
Depreciación por identificador
Section titled “Depreciación por identificador”DepreciacionRepository.findById consulta una cuota específica y se usa como entrada de contabilización, reversa y validaciones de estado.
Estados Operacionales
Section titled “Estados Operacionales”| Operación | Estado esperado | Resultado |
|---|---|---|
generar | Sin cuota no anulada para el periodo | Crea una cuota nueva. |
contabilizar | PENDIENTE | Inserta detalle y cambia a CONTABILIZADO. |
reversarContabilizacion | CONTABILIZADO | Borra detalle y vuelve a PENDIENTE. |
anular | Distinto de ANULADO | Cambia a ANULADO con motivo. |
eliminar | PENDIENTE | Elimina la cuota. |
Reglas de Diseño
Section titled “Reglas de Diseño”| Regla | Motivo |
|---|---|
Validar periodo_mes como YYYY-MM-01 | Alinea el cálculo al cierre mensual. |
| Impedir duplicidad por activo y periodo | Evita cuotas repetidas mientras no estén anuladas. |
| Persistir cuota antes del detalle | Separa cálculo de contabilización. |
| Generar detalle solo al contabilizar | Mantiene la cuota calculada en estado PENDIENTE hasta su aprobación. |
| Usar estados | Diferencia cuotas pendientes, contabilizadas y anuladas. |
Consideraciones Públicas
Section titled “Consideraciones Públicas”Esta documentación nombra servicios, schemas, tablas y conceptos de dominio porque forman parte del contrato técnico del sistema. No publica rutas locales de desarrollo, credenciales, endpoints internos protegidos ni datos reales de empresas.
Cuando se requiera un ejemplo operativo, usar placeholders:
{ "tenantId": "$TENANT_ID", "periodo": "$PERIODO", "activoId": "$ACTIVO_ID"}Ver También
Section titled “Ver También”- Depreciación de activo fijo - Explicación contable y tributaria.
- Depreciación de activo fijo en Sevastopol - Vista frontend que consume este flujo desde
ActivosFijosIsland. - Chart of Accounts Service - Servicio relacionado con cuentas contables.
- Mother Database - Persistencia y arquitectura de base de datos.