363 lines
12 KiB
Vue
363 lines
12 KiB
Vue
<script setup>
|
|
import { useI18n } from 'vue-i18n';
|
|
import { computed, ref, onMounted, watch } from 'vue';
|
|
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
|
import { toDateTimeFormat } from 'src/filters/date';
|
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import axios from 'axios';
|
|
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
|
import OrderFilter from './Card/OrderFilter.vue';
|
|
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
|
|
|
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
import VnSection from 'src/components/common/VnSection.vue';
|
|
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
|
import { getAddresses } from '../Customer/composables/getAddresses';
|
|
|
|
const { t } = useI18n();
|
|
const { viewSummary } = useSummaryDialog();
|
|
const tableRef = ref();
|
|
const agencyList = ref([]);
|
|
const route = useRoute();
|
|
const addressOptions = ref([]);
|
|
const dataKey = 'OrderList';
|
|
const formInitialData = ref({
|
|
active: true,
|
|
addressId: null,
|
|
clientFk: null,
|
|
});
|
|
|
|
const columns = computed(() => [
|
|
{
|
|
align: 'left',
|
|
name: 'id',
|
|
label: t('module.id'),
|
|
chip: {
|
|
condition: () => true,
|
|
},
|
|
isId: true,
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'clientFk',
|
|
label: t('module.customer'),
|
|
isTitle: true,
|
|
cardVisible: true,
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'Clients',
|
|
fields: ['id', 'name'],
|
|
},
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
format: (row) => row?.clientName,
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'departmentFk',
|
|
label: t('customer.summary.team'),
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'Departments',
|
|
},
|
|
create: true,
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.departmentName),
|
|
},
|
|
{
|
|
align: 'center',
|
|
name: 'isConfirmed',
|
|
component: 'checkbox',
|
|
label: t('module.isConfirmed'),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'created',
|
|
label: t('module.created'),
|
|
component: 'date',
|
|
cardVisible: true,
|
|
format: (row) => toDateTimeFormat(row?.created),
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'landed',
|
|
label: t('module.landed'),
|
|
component: 'date',
|
|
format: (row) => toDate(row?.landed),
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
style: () => {
|
|
return { color: 'positive' };
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hour',
|
|
label: t('module.hour'),
|
|
format: ({ hourTheoretical, hourEffective }) =>
|
|
dashIfEmpty(hourTheoretical || hourEffective),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'agencyModeFk',
|
|
label: t('module.agency'),
|
|
format: (row) => row?.agencyName,
|
|
columnFilter: {
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'agencyModes',
|
|
fields: ['id', 'name'],
|
|
find: {
|
|
value: 'agencyModeFk',
|
|
label: 'agencyName',
|
|
},
|
|
},
|
|
},
|
|
cardVisible: true,
|
|
columnClass: 'expand',
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'total',
|
|
label: t('module.total'),
|
|
format: ({ total }) => toCurrency(total),
|
|
cardVisible: true,
|
|
},
|
|
{
|
|
align: 'right',
|
|
label: '',
|
|
name: 'tableActions',
|
|
actions: [
|
|
{
|
|
title: t('globals.pageTitles.summary'),
|
|
icon: 'preview',
|
|
action: (row) => viewSummary(row.id, OrderSummary),
|
|
isPrimary: true,
|
|
},
|
|
],
|
|
},
|
|
]);
|
|
onMounted(async () => {
|
|
if (!route.query) return;
|
|
if (route.query?.createForm) {
|
|
await onClientSelected(JSON.parse(route.query?.createForm));
|
|
} else if (route.query?.table) {
|
|
const query = JSON.parse(route.query?.table);
|
|
const clientFk = query?.clientFk;
|
|
if (clientFk) await onClientSelected({ clientFk });
|
|
}
|
|
if (tableRef.value) tableRef.value.create.formInitialData = formInitialData.value;
|
|
});
|
|
|
|
watch(
|
|
() => route.query.table,
|
|
async (newValue) => {
|
|
if (newValue) {
|
|
const clientFk = +JSON.parse(newValue)?.clientFk;
|
|
if (clientFk) await onClientSelected({ clientFk });
|
|
if (tableRef.value)
|
|
tableRef.value.create.formInitialData = formInitialData.value;
|
|
}
|
|
},
|
|
);
|
|
|
|
async function onClientSelected({ clientFk }, formData = {}) {
|
|
if (!clientFk) {
|
|
addressOptions.value = [];
|
|
formData.defaultAddressFk = null;
|
|
formData.addressId = null;
|
|
return;
|
|
}
|
|
const { data } = await getAddresses(clientFk);
|
|
addressOptions.value = data;
|
|
formData.defaultAddressFk = data[0].client.defaultAddressFk;
|
|
formData.addressId = formData.defaultAddressFk;
|
|
formInitialData.value = { ...formData, clientFk };
|
|
await fetchAgencies(formData);
|
|
}
|
|
|
|
async function fetchAgencies(formData) {
|
|
const { landed, addressId } = formData;
|
|
if (!landed || !addressId) {
|
|
formData.defaultAddressFk = formInitialData.value.defaultAddressFk;
|
|
|
|
return (agencyList.value = []);
|
|
}
|
|
|
|
const { data } = await axios.get('Agencies/landsThatDay', {
|
|
params: {
|
|
filter: JSON.stringify({
|
|
order: ['name ASC', 'agencyMode DESC', 'agencyModeFk ASC'],
|
|
}),
|
|
addressFk: addressId,
|
|
landed,
|
|
},
|
|
});
|
|
agencyList.value = data;
|
|
}
|
|
|
|
const getDateColor = (date) => {
|
|
const today = Date.vnNew();
|
|
today.setHours(0, 0, 0, 0);
|
|
const timeTicket = new Date(date);
|
|
timeTicket.setHours(0, 0, 0, 0);
|
|
const difference = today - timeTicket;
|
|
if (difference == 0) return 'bg-warning';
|
|
if (difference < 0) return 'bg-success';
|
|
};
|
|
|
|
const isDefaultAddress = (opt, data) => {
|
|
const addressId = data.defaultAddressFk ?? data.addressId;
|
|
return addressId === opt.id && opt.isActive;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<VnSection
|
|
:data-key="dataKey"
|
|
:columns="columns"
|
|
prefix="order"
|
|
:array-data-props="{
|
|
url: 'Orders/filter',
|
|
order: ['landed DESC', 'clientFk ASC', 'id DESC'],
|
|
}"
|
|
>
|
|
<template #advanced-menu>
|
|
<OrderFilter data-key="OrderList" />
|
|
</template>
|
|
<template #body>
|
|
<VnTable
|
|
ref="tableRef"
|
|
:data-key="dataKey"
|
|
:create="{
|
|
urlCreate: 'Orders/new',
|
|
title: t('module.cerateOrder'),
|
|
onDataSaved: (url) => {
|
|
tableRef.redirect(`${url}/catalog`);
|
|
},
|
|
formInitialData,
|
|
}"
|
|
:user-params="{ showEmpty: false }"
|
|
:columns="columns"
|
|
:right-search="false"
|
|
redirect="order"
|
|
>
|
|
<template #column-clientFk="{ row }">
|
|
<span class="link" @click.stop>
|
|
{{ row?.clientName }}
|
|
<CustomerDescriptorProxy :id="row?.clientFk" />
|
|
</span>
|
|
</template>
|
|
<template #column-departmentFk="{ row }">
|
|
<span class="link" @click.stop>
|
|
{{ row?.departmentName }}
|
|
<DepartmentDescriptorProxy :id="row?.departmentFk" />
|
|
</span>
|
|
</template>
|
|
<template #column-landed="{ row }">
|
|
<span v-if="getDateColor(row.landed)">
|
|
<QChip :class="getDateColor(row.landed)" dense square>
|
|
{{ toDate(row?.landed) }}
|
|
</QChip>
|
|
</span>
|
|
</template>
|
|
<template #more-create-dialog="{ data }">
|
|
<VnSelect
|
|
url="Clients"
|
|
:include="{ relation: 'addresses' }"
|
|
v-model="data.clientFk"
|
|
:label="t('module.customer')"
|
|
@update:model-value="
|
|
(id) => onClientSelected({ clientFk: id }, data)
|
|
"
|
|
>
|
|
<template #option="scope">
|
|
<QItem v-bind="scope.itemProps">
|
|
<QItemSection>
|
|
<QItemLabel>
|
|
{{ scope.opt.name }}
|
|
</QItemLabel>
|
|
<QItemLabel caption>
|
|
{{ `#${scope.opt.id}` }}
|
|
</QItemLabel>
|
|
</QItemSection>
|
|
</QItem>
|
|
</template>
|
|
</VnSelect>
|
|
<VnSelect
|
|
:disable="!data.clientFk"
|
|
v-model="data.addressId"
|
|
:options="addressOptions"
|
|
:label="t('module.address')"
|
|
option-value="id"
|
|
option-label="nickname"
|
|
@update:model-value="() => fetchAgencies(data)"
|
|
>
|
|
<template #option="scope">
|
|
<QItem
|
|
v-bind="scope.itemProps"
|
|
:class="{ disabled: !scope.opt.isActive }"
|
|
>
|
|
<QItemSection style="min-width: min-content" avatar>
|
|
<QIcon
|
|
v-if="isDefaultAddress(scope.opt, data)"
|
|
size="sm"
|
|
color="grey"
|
|
name="star"
|
|
class="fill-icon"
|
|
/>
|
|
</QItemSection>
|
|
<QItemSection>
|
|
<QItemLabel
|
|
:class="{
|
|
'color-vn-label': !scope.opt?.isActive,
|
|
}"
|
|
>
|
|
{{
|
|
`${
|
|
!scope.opt?.isActive
|
|
? t('basicData.inactive')
|
|
: ''
|
|
} `
|
|
}}
|
|
{{ scope.opt?.nickname }}:
|
|
{{ scope.opt?.street }},
|
|
{{ scope.opt?.city }}
|
|
</QItemLabel>
|
|
<QItemLabel caption>
|
|
{{ `#${scope.opt?.id}` }}
|
|
</QItemLabel>
|
|
</QItemSection>
|
|
</QItem>
|
|
</template>
|
|
</VnSelect>
|
|
<VnInputDate
|
|
v-model="data.landed"
|
|
:label="t('module.landed')"
|
|
data-cy="landedDate"
|
|
@update:model-value="() => fetchAgencies(data)"
|
|
/>
|
|
<VnSelect
|
|
v-model="data.agencyModeId"
|
|
:label="t('module.agency')"
|
|
:options="agencyList"
|
|
option-value="agencyModeFk"
|
|
option-label="agencyMode"
|
|
/>
|
|
</template>
|
|
</VnTable>
|
|
</template>
|
|
</VnSection>
|
|
</template>
|