164 lines
5.6 KiB
Vue
164 lines
5.6 KiB
Vue
<script setup lang="ts">
|
|
import { onMounted, ref } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import { useToast } from 'primevue/usetoast';
|
|
import Toast from 'primevue/toast';
|
|
import Button from 'primevue/button';
|
|
import AssignmentAssetSelectorCard from './AssignmentAssetSelectorCard.vue';
|
|
import AssignmentEmployeeSelectorCard from './AssignmentEmployeeSelectorCard.vue';
|
|
import AssignmentDetailsCard from './AssignmentDetailsCard.vue';
|
|
import type {
|
|
AssignmentAssetOption,
|
|
AssignmentEmployeeOption,
|
|
FixedAssetAssignmentFormData
|
|
} from '../../types/fixedAssetAssignment';
|
|
import { fixedAssetsService, type UserOption } from '../../services/fixedAssetsService';
|
|
import { employeesService } from '@/modules/rh/components/employees/employees.services';
|
|
|
|
const router = useRouter();
|
|
const toast = useToast();
|
|
const loading = ref(false);
|
|
const loadingData = ref(false);
|
|
const assetSearch = ref('');
|
|
const employeeSearch = ref('');
|
|
|
|
const assets = ref<AssignmentAssetOption[]>([]);
|
|
const employees = ref<AssignmentEmployeeOption[]>([]);
|
|
const users = ref<UserOption[]>([]);
|
|
|
|
const form = ref<FixedAssetAssignmentFormData>({
|
|
assetId: null,
|
|
employeeId: null,
|
|
authorizedById: null,
|
|
assignedAt: new Date().toISOString().slice(0, 10),
|
|
receiptFolio: '',
|
|
notes: ''
|
|
});
|
|
|
|
onMounted(async () => {
|
|
loadingData.value = true;
|
|
try {
|
|
const [assetsRes, employeesRes, usersRes] = await Promise.all([
|
|
fixedAssetsService.getAssets({ paginate: false, status: 1 }),
|
|
employeesService.getEmployees({ paginate: false }),
|
|
fixedAssetsService.getUsers(),
|
|
]);
|
|
|
|
const allAssets = (assetsRes as any).data?.data ?? [];
|
|
assets.value = allAssets
|
|
.filter((a: any) => !a.active_assignment)
|
|
.map((a: any): AssignmentAssetOption => ({
|
|
id: a.id,
|
|
code: a.sku,
|
|
name: a.inventory_warehouse?.product?.name ?? a.sku,
|
|
serial: a.inventory_warehouse?.product?.serial_number ?? '—',
|
|
category: a.inventory_warehouse?.product?.category ?? '—',
|
|
}));
|
|
|
|
const allEmployees = (employeesRes as any).data ?? [];
|
|
employees.value = allEmployees.map((e: any): AssignmentEmployeeOption => ({
|
|
id: e.id,
|
|
initials: `${e.name[0]}${e.paternal[0]}`.toUpperCase(),
|
|
fullName: `${e.name} ${e.paternal} ${e.maternal}`.trim(),
|
|
role: e.job_position?.name ?? '—',
|
|
department: e.department?.name ?? '—',
|
|
}));
|
|
|
|
users.value = usersRes;
|
|
} catch {
|
|
toast.add({
|
|
severity: 'error',
|
|
summary: 'Error',
|
|
detail: 'No se pudieron cargar los datos. Intente de nuevo.',
|
|
life: 4000
|
|
});
|
|
} finally {
|
|
loadingData.value = false;
|
|
}
|
|
});
|
|
|
|
const cancel = () => router.push('/fixed-assets/assignments');
|
|
|
|
const save = async () => {
|
|
if (!form.value.assetId || !form.value.employeeId) {
|
|
toast.add({
|
|
severity: 'warn',
|
|
summary: 'Campos pendientes',
|
|
detail: 'Seleccione un activo y un colaborador para confirmar la asignacion.',
|
|
life: 3000
|
|
});
|
|
return;
|
|
}
|
|
|
|
loading.value = true;
|
|
try {
|
|
await fixedAssetsService.assignAsset(form.value.assetId, {
|
|
employee_id: form.value.employeeId,
|
|
assigned_at: form.value.assignedAt,
|
|
receipt_folio: form.value.receiptFolio || undefined,
|
|
authorized_by: form.value.authorizedById ?? undefined,
|
|
notes: form.value.notes || undefined,
|
|
});
|
|
|
|
toast.add({
|
|
severity: 'success',
|
|
summary: 'Asignacion registrada',
|
|
detail: 'La asignacion del activo al colaborador se registro correctamente.',
|
|
life: 2500
|
|
});
|
|
|
|
router.push('/fixed-assets/assignments');
|
|
} catch (error: any) {
|
|
const message = error?.response?.data?.message ?? 'Error al registrar la asignacion.';
|
|
toast.add({ severity: 'error', summary: 'Error', detail: message, life: 4000 });
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<section class="space-y-6">
|
|
<Toast position="bottom-right" />
|
|
|
|
<div>
|
|
<h1 class="text-3xl font-black tracking-tight text-surface-900 dark:text-surface-0">
|
|
Asignacion de Activo a Empleado
|
|
</h1>
|
|
<p class="mt-1 text-surface-500 dark:text-surface-400">
|
|
Registre la entrega de una herramienta o equipo a un colaborador del almacen.
|
|
</p>
|
|
</div>
|
|
|
|
<AssignmentAssetSelectorCard
|
|
:assets="assets"
|
|
:search-term="assetSearch"
|
|
:selected-asset-id="form.assetId"
|
|
:loading="loadingData"
|
|
@update:search-term="assetSearch = $event"
|
|
@update:selected-asset-id="form.assetId = $event"
|
|
/>
|
|
|
|
<AssignmentEmployeeSelectorCard
|
|
:employees="employees"
|
|
:search-term="employeeSearch"
|
|
:selected-employee-id="form.employeeId"
|
|
@update:search-term="employeeSearch = $event"
|
|
@update:selected-employee-id="form.employeeId = $event"
|
|
/>
|
|
|
|
<AssignmentDetailsCard :form="form" :users="users" />
|
|
|
|
<div class="flex flex-wrap items-center justify-end gap-3">
|
|
<Button label="Cancelar" text severity="secondary" @click="cancel" />
|
|
<Button
|
|
label="Confirmar Asignacion"
|
|
icon="pi pi-check-circle"
|
|
:loading="loading"
|
|
:disabled="loadingData"
|
|
@click="save"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</template>
|