396 lines
14 KiB
Vue
396 lines
14 KiB
Vue
<script setup>
|
|
import { onBeforeMount, computed, ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
|
import WorkerSummary from './Card/WorkerSummary.vue';
|
|
import VnRow from 'src/components/ui/VnRow.vue';
|
|
import VnInput from 'src/components/common/VnInput.vue';
|
|
import VnRadio from 'src/components/common/VnRadio.vue';
|
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
|
import VnLocation from 'src/components/common/VnLocation.vue';
|
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
|
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
|
|
import FetchData from 'src/components/FetchData.vue';
|
|
import WorkerFilter from './WorkerFilter.vue';
|
|
import { useState } from 'src/composables/useState';
|
|
import axios from 'axios';
|
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
|
import VnSection from 'src/components/common/VnSection.vue';
|
|
const { t } = useI18n();
|
|
const tableRef = ref();
|
|
const { viewSummary } = useSummaryDialog();
|
|
const companiesOptions = ref([]);
|
|
const payMethodsOptions = ref([]);
|
|
const bankEntitiesOptions = ref([]);
|
|
const postcodesOptions = ref([]);
|
|
|
|
const user = useState().getUser();
|
|
const defaultPayMethod = ref();
|
|
const bankEntitiesRef = ref();
|
|
const dataKey = 'WorkerList';
|
|
const columns = computed(() => [
|
|
{
|
|
align: 'left',
|
|
name: 'id',
|
|
label: t('id'),
|
|
field: 'id',
|
|
isId: true,
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'firstName',
|
|
label: t('tableColumns.firstName'),
|
|
isTitle: true,
|
|
columnFilter: {
|
|
name: 'firstName',
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'lastName',
|
|
label: t('tableColumns.lastName'),
|
|
isTitle: true,
|
|
columnFilter: {
|
|
name: 'lastName',
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'nickname',
|
|
label: t('tableColumns.userName'),
|
|
isTitle: true,
|
|
columnFilter: {
|
|
name: 'userName',
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'departmentFk',
|
|
label: t('tableColumns.department'),
|
|
cardVisible: true,
|
|
columnFilter: {
|
|
component: 'select',
|
|
name: 'departmentFk',
|
|
attrs: {
|
|
url: 'Departments',
|
|
},
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.department),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'email',
|
|
label: t('tableColumns.email'),
|
|
cardVisible: true,
|
|
columnFilter: {
|
|
name: 'email',
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'extension',
|
|
label: t('tableColumns.extension'),
|
|
cardVisible: true,
|
|
columnFilter: {
|
|
name: 'extension',
|
|
},
|
|
},
|
|
{
|
|
align: 'right',
|
|
label: '',
|
|
name: 'tableActions',
|
|
actions: [
|
|
{
|
|
title: t('components.smartCard.viewSummary'),
|
|
icon: 'preview',
|
|
action: (row) => viewSummary(row.id, WorkerSummary),
|
|
isPrimary: true,
|
|
},
|
|
],
|
|
},
|
|
]);
|
|
|
|
onBeforeMount(async () => {
|
|
defaultPayMethod.value = (
|
|
await axios.get('WorkerConfigs/findOne', {
|
|
params: { field: ['payMethodFk'] },
|
|
})
|
|
).data?.payMethodFk;
|
|
});
|
|
|
|
async function handleNewBankEntity(data, resp) {
|
|
await bankEntitiesRef.value.fetch();
|
|
data.bankEntityFk = resp.id;
|
|
bankEntitiesOptions.value.push(resp);
|
|
}
|
|
|
|
function handleLocation(data, location) {
|
|
const { town, code, provinceFk, countryFk } = location ?? {};
|
|
data.postcode = code;
|
|
data.city = town;
|
|
data.provinceFk = provinceFk;
|
|
data.countryFk = countryFk;
|
|
}
|
|
|
|
function uppercaseStreetModel(data) {
|
|
return {
|
|
get: () => (data.street ? data.street.toUpperCase() : ''),
|
|
set: (value) => {
|
|
if (value) {
|
|
data.street = value.toUpperCase();
|
|
} else {
|
|
data.street = null;
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
function generateCodeUser(worker) {
|
|
if (!worker.firstName || !worker.lastNames) return;
|
|
|
|
const totalName = worker.firstName.concat(' ' + worker.lastNames).toLowerCase();
|
|
const totalNameArray = totalName.split(' ');
|
|
let newCode = '';
|
|
|
|
for (let part of totalNameArray) newCode += part.charAt(0);
|
|
|
|
worker.code = newCode.toUpperCase().slice(0, 3);
|
|
worker.name = totalNameArray[0] + newCode.slice(1);
|
|
|
|
if (!worker.companyFk) worker.companyFk = user.companyFk;
|
|
}
|
|
|
|
async function autofillBic(worker) {
|
|
if (!worker || !worker.iban) return;
|
|
|
|
let bankEntityId = parseInt(worker.iban.substr(4, 4));
|
|
let filter = { where: { id: bankEntityId } };
|
|
|
|
const { data } = await axios.get(`BankEntities`, { params: { filter } });
|
|
worker.bankEntityFk = data?.[0]?.id ?? undefined;
|
|
}
|
|
</script>
|
|
<template>
|
|
<FetchData
|
|
url="Companies"
|
|
@on-fetch="(data) => (companiesOptions = data)"
|
|
auto-load
|
|
/>
|
|
<FetchData
|
|
url="Paymethods"
|
|
@on-fetch="(data) => (payMethodsOptions = data)"
|
|
auto-load
|
|
/>
|
|
<FetchData
|
|
ref="bankEntitiesRef"
|
|
url="BankEntities"
|
|
@on-fetch="(data) => (bankEntitiesOptions = data)"
|
|
auto-load
|
|
/>
|
|
|
|
<VnSection
|
|
:data-key="dataKey"
|
|
:columns="columns"
|
|
prefix="workerSearch"
|
|
:array-data-props="{
|
|
url: 'Workers/filter',
|
|
order: ['id DESC'],
|
|
}"
|
|
>
|
|
<template #rightMenu>
|
|
<WorkerFilter data-key="WorkerList" />
|
|
</template>
|
|
<template #body>
|
|
<VnTable
|
|
v-if="defaultPayMethod"
|
|
ref="tableRef"
|
|
:data-key="dataKey"
|
|
:create="{
|
|
urlCreate: 'Workers/new',
|
|
title: t('Create worker'),
|
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
|
formInitialData: {
|
|
payMethodFk: defaultPayMethod,
|
|
companyFk: user.companyFk,
|
|
isFreelance: false,
|
|
},
|
|
}"
|
|
default-mode="table"
|
|
:columns="columns"
|
|
redirect="worker"
|
|
:right-search="false"
|
|
>
|
|
<template #more-create-dialog="{ data }">
|
|
<div class="q-pa-lg full-width">
|
|
<VnRadio
|
|
v-model="data.isFreelance"
|
|
:val="false"
|
|
:label="`${t('Internal')}`"
|
|
@update:model-value="data.payMethodFk = defaultPayMethod"
|
|
/>
|
|
<VnRadio
|
|
v-model="data.isFreelance"
|
|
:val="true"
|
|
:label="`${t('External')}`"
|
|
@update:model-value="delete data.payMethodFk"
|
|
/>
|
|
<VnRow>
|
|
<VnInput
|
|
next
|
|
v-model="data.firstName"
|
|
:label="t('globals.name')"
|
|
@update:model-value="generateCodeUser(data)"
|
|
/>
|
|
<VnInput
|
|
v-model="data.lastNames"
|
|
:label="t('worker.create.lastName')"
|
|
@update:model-value="generateCodeUser(data)"
|
|
/>
|
|
<VnInput
|
|
v-model="data.code"
|
|
:label="t('worker.create.code')"
|
|
/>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnInput
|
|
v-model="data.name"
|
|
:label="t('worker.create.webUser')"
|
|
/>
|
|
<VnInput
|
|
v-model="data.email"
|
|
type="email"
|
|
:label="t('worker.create.personalEmail')"
|
|
/>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnSelect
|
|
:label="t('globals.company')"
|
|
v-model="data.companyFk"
|
|
:options="companiesOptions"
|
|
option-value="id"
|
|
option-label="code"
|
|
hide-selected
|
|
/>
|
|
<VnSelectWorker
|
|
:label="t('worker.summary.boss')"
|
|
v-model="data.bossFk"
|
|
/>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnInput v-model="data.fi" :label="t('worker.create.fi')" />
|
|
<VnInputDate
|
|
v-model="data.birth"
|
|
:label="t('worker.create.birth')"
|
|
:disable="data.isFreelance"
|
|
/>
|
|
<VnInput
|
|
v-model="data.phone"
|
|
:label="t('globals.phone')"
|
|
:disable="data.isFreelance"
|
|
/>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnLocation
|
|
:roles-allowed-to-create="['deliveryAssistant']"
|
|
:acls="[
|
|
{ model: 'Town', props: '*', accessType: 'WRITE' },
|
|
]"
|
|
:options="postcodesOptions"
|
|
@update:model-value="
|
|
(location) => handleLocation(data, location)
|
|
"
|
|
:disable="data.isFreelance"
|
|
>
|
|
</VnLocation>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnInput
|
|
:label="t('globals.street')"
|
|
:model-value="uppercaseStreetModel(data).get()"
|
|
@update:model-value="uppercaseStreetModel(data).set"
|
|
:disable="data.isFreelance"
|
|
/>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnSelect
|
|
:label="t('worker.create.payMethods')"
|
|
v-model="data.payMethodFk"
|
|
:options="payMethodsOptions"
|
|
option-value="id"
|
|
option-label="name"
|
|
map-options
|
|
hide-selected
|
|
:disable="data.isFreelance"
|
|
@update:model-value="
|
|
(val) => !val && delete data.payMethodFk
|
|
"
|
|
/>
|
|
<VnInput
|
|
v-model="data.iban"
|
|
:label="t('worker.create.iban')"
|
|
:disable="data.isFreelance"
|
|
@update:model-value="autofillBic(data)"
|
|
>
|
|
<template #append>
|
|
<QIcon name="info" class="cursor-info">
|
|
<QTooltip>{{
|
|
t('components.iban_tooltip')
|
|
}}</QTooltip>
|
|
</QIcon>
|
|
</template>
|
|
</VnInput>
|
|
</VnRow>
|
|
<VnRow>
|
|
<VnSelectDialog
|
|
:label="t('worker.create.bankEntity')"
|
|
v-model="data.bankEntityFk"
|
|
:options="bankEntitiesOptions"
|
|
option-label="name"
|
|
option-value="id"
|
|
hide-selected
|
|
:acls="[
|
|
{
|
|
model: 'BankEntity',
|
|
props: '*',
|
|
accessType: 'WRITE',
|
|
},
|
|
]"
|
|
:disable="data.isFreelance"
|
|
@update:model-value="autofillBic(data)"
|
|
:filter-options="['bic', 'name']"
|
|
>
|
|
<template #form>
|
|
<CreateBankEntityForm
|
|
@on-data-saved="
|
|
(_, resp) => handleNewBankEntity(data, resp)
|
|
"
|
|
/>
|
|
</template>
|
|
<template #option="scope">
|
|
<QItem v-bind="scope.itemProps">
|
|
<QItemSection v-if="scope.opt">
|
|
<QItemLabel
|
|
>{{ scope.opt.bic }}
|
|
{{ scope.opt.name }}</QItemLabel
|
|
>
|
|
</QItemSection>
|
|
</QItem>
|
|
</template>
|
|
</VnSelectDialog>
|
|
</VnRow>
|
|
</div>
|
|
</template>
|
|
</VnTable>
|
|
</template>
|
|
</VnSection>
|
|
</template>
|
|
|
|
<i18n>
|
|
es:
|
|
Create worker: Crear trabajador
|
|
Search worker: Buscar trabajador
|
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
|
</i18n>
|