From 817e6c76c4f51e2b0639248f4ea5b4a0788a60fd Mon Sep 17 00:00:00 2001 From: Juan Felipe Zapata Moreno Date: Wed, 1 Apr 2026 11:33:07 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20agregar=20secciones=20de=20vida=20?= =?UTF-8?q?=C3=BAtil=20y=20depreciaci=C3=B3n=20a=20la=20gesti=C3=B3n=20de?= =?UTF-8?q?=20activos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/FixedAssetDepreciationSection.vue | 114 ++++++++++++++++++ .../components/assets/FixedAssetForm.vue | 18 ++- .../assets/FixedAssetUsefulLifeSection.vue | 106 ++++++++++++++++ .../services/fixedAssetsService.ts | 20 +++ src/modules/fixed-assets/types/fixedAsset.ts | 23 ++++ 5 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 src/modules/fixed-assets/components/assets/FixedAssetDepreciationSection.vue create mode 100644 src/modules/fixed-assets/components/assets/FixedAssetUsefulLifeSection.vue diff --git a/src/modules/fixed-assets/components/assets/FixedAssetDepreciationSection.vue b/src/modules/fixed-assets/components/assets/FixedAssetDepreciationSection.vue new file mode 100644 index 0000000..b171d78 --- /dev/null +++ b/src/modules/fixed-assets/components/assets/FixedAssetDepreciationSection.vue @@ -0,0 +1,114 @@ + + + diff --git a/src/modules/fixed-assets/components/assets/FixedAssetForm.vue b/src/modules/fixed-assets/components/assets/FixedAssetForm.vue index c875010..c2dc1b2 100644 --- a/src/modules/fixed-assets/components/assets/FixedAssetForm.vue +++ b/src/modules/fixed-assets/components/assets/FixedAssetForm.vue @@ -6,7 +6,8 @@ import Toast from 'primevue/toast'; import Button from 'primevue/button'; import Card from 'primevue/card'; import FixedAssetGeneralInfoSection from './FixedAssetGeneralInfoSection.vue'; -import FixedAssetAcquisitionSection from './FixedAssetAcquisitionSection.vue'; +import FixedAssetUsefulLifeSection from './FixedAssetUsefulLifeSection.vue'; +import FixedAssetDepreciationSection from './FixedAssetDepreciationSection.vue'; import FixedAssetAssignmentSection from './FixedAssetAssignmentSection.vue'; import fixedAssetsService from '../../services/fixedAssetsService'; import type { FixedAssetFormData } from '../../types/fixedAsset'; @@ -23,6 +24,8 @@ const currentProductName = ref(''); const form = ref({ inventory_warehouse_id: null, + useful_life_catalog_id: null, + fiscal_depreciation_rate_id: null, estimated_useful_life: null, depreciation_method: 'straight_line', residual_value: null, @@ -39,6 +42,8 @@ const loadAsset = async () => { const asset = response.data.data; form.value = { inventory_warehouse_id: asset.inventory_warehouse?.id ?? null, + useful_life_catalog_id: asset.useful_life_catalog_id ?? null, + fiscal_depreciation_rate_id: asset.fiscal_depreciation_rate_id ?? null, estimated_useful_life: asset.estimated_useful_life, depreciation_method: asset.depreciation_method ?? 'straight_line', residual_value: asset.residual_value ? parseFloat(asset.residual_value) : null, @@ -67,8 +72,8 @@ const saveAsset = async () => { toast.add({ severity: 'warn', summary: 'Campo requerido', detail: 'Selecciona un producto del almacén.', life: 3000 }); return; } - if (!form.value.estimated_useful_life) { - toast.add({ severity: 'warn', summary: 'Campo requerido', detail: 'Indica la vida útil estimada.', life: 3000 }); + if (!form.value.estimated_useful_life && !form.value.useful_life_catalog_id) { + toast.add({ severity: 'warn', summary: 'Campo requerido', detail: 'Indica la vida útil estimada o selecciona un catálogo.', life: 3000 }); return; } @@ -80,6 +85,8 @@ const saveAsset = async () => { depreciation_method: form.value.depreciation_method || 'straight_line', }; + if (form.value.useful_life_catalog_id != null) payload.useful_life_catalog_id = form.value.useful_life_catalog_id; + if (form.value.fiscal_depreciation_rate_id != null) payload.fiscal_depreciation_rate_id = form.value.fiscal_depreciation_rate_id; if (form.value.residual_value != null) payload.residual_value = form.value.residual_value; if (form.value.asset_tag) payload.asset_tag = form.value.asset_tag; if (form.value.warranty_days != null) payload.warranty_days = form.value.warranty_days; @@ -139,8 +146,9 @@ const saveAsset = async () => {
- - + + +
diff --git a/src/modules/fixed-assets/components/assets/FixedAssetUsefulLifeSection.vue b/src/modules/fixed-assets/components/assets/FixedAssetUsefulLifeSection.vue new file mode 100644 index 0000000..3424a3c --- /dev/null +++ b/src/modules/fixed-assets/components/assets/FixedAssetUsefulLifeSection.vue @@ -0,0 +1,106 @@ + + + diff --git a/src/modules/fixed-assets/services/fixedAssetsService.ts b/src/modules/fixed-assets/services/fixedAssetsService.ts index fa1c3e5..50718e3 100644 --- a/src/modules/fixed-assets/services/fixedAssetsService.ts +++ b/src/modules/fixed-assets/services/fixedAssetsService.ts @@ -1,4 +1,5 @@ import api from '../../../services/api'; +import type { UsefulLifeCatalogOption, FiscalDepreciationRateOption, UsefulLifeCalculationResult } from '../types/fixedAsset'; export interface Asset { id: number; @@ -12,6 +13,10 @@ export interface Asset { book_value: string; warranty_days: number | null; warranty_end_date: string | null; + fiscal_depreciation_rate_id: number | null; + useful_life_catalog_id: number | null; + fiscal_depreciation_rate: { id: number; name: string; depreciation_rate: string } | null; + useful_life_catalog: { id: number; name: string; min_years: number; max_years: number } | null; inventory_warehouse: { id: number; product: { @@ -207,6 +212,21 @@ class FixedAssetsService { })); } + async getUsefulLifeCatalog(): Promise { + const response = await api.get('/api/catalogs/useful-life-catalog', { params: { paginate: false } }); + return response.data.data.data; + } + + async getFiscalDepreciationRates(): Promise { + const response = await api.get('/api/catalogs/fiscal-depreciation-rates', { params: { paginate: false } }); + return response.data.data.data; + } + + async calculateUsefulLife(params: { useful_life_catalog_id?: number }): Promise { + const response = await api.get('/api/assets/options/calculate-useful-life', { params }); + return response.data.data; + } + async downloadResguardo(assetId: number, assignmentId: number): Promise { const response = await api.get( `/api/assets/${assetId}/assignments/${assignmentId}/resguardo`, diff --git a/src/modules/fixed-assets/types/fixedAsset.ts b/src/modules/fixed-assets/types/fixedAsset.ts index 38268ba..f2cb698 100644 --- a/src/modules/fixed-assets/types/fixedAsset.ts +++ b/src/modules/fixed-assets/types/fixedAsset.ts @@ -1,5 +1,7 @@ export interface FixedAssetFormData { inventory_warehouse_id: number | null; + useful_life_catalog_id: number | null; + fiscal_depreciation_rate_id: number | null; estimated_useful_life: number | null; depreciation_method: string; residual_value: number | null; @@ -8,6 +10,27 @@ export interface FixedAssetFormData { warranty_end_date: string; } +export interface UsefulLifeCatalogOption { + id: number; + name: string; + min_years: number; + max_years: number; + practical_comment: string | null; + is_active: boolean; +} + +export interface FiscalDepreciationRateOption { + id: number; + name: string; + depreciation_rate: string; + is_active: boolean; +} + +export interface UsefulLifeCalculationResult { + from_useful_life_catalog?: { months: number; label: string }; + from_fiscal_rate?: { months: number; label: string }; +} + export interface InventoryWarehouseOption { id: number; serial_number: string | null;