502 lines
14 KiB
Vue
502 lines
14 KiB
Vue
<script setup>
|
|
import { ref, computed, markRaw } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useRouter } from 'vue-router';
|
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
|
import { toDate } from 'src/filters';
|
|
|
|
import CustomerSummary from './Card/CustomerSummary.vue';
|
|
import CustomerFilter from './CustomerFilter.vue';
|
|
import VnTable from 'components/VnTable/VnTable.vue';
|
|
import VnLocation from 'src/components/common/VnLocation.vue';
|
|
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
|
import VnSection from 'src/components/common/VnSection.vue';
|
|
|
|
const { t } = useI18n();
|
|
const router = useRouter();
|
|
const tableRef = ref();
|
|
const dataKey = 'CustomerList';
|
|
|
|
const columns = computed(() => [
|
|
{
|
|
align: 'left',
|
|
name: 'id',
|
|
label: t('customer.extendedList.tableVisibleColumns.id'),
|
|
chip: {
|
|
condition: () => true,
|
|
},
|
|
isId: true,
|
|
columnFilter: {
|
|
component: 'select',
|
|
name: 'search',
|
|
attrs: {
|
|
url: 'Clients',
|
|
fields: ['id', 'name'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'name',
|
|
label: t('globals.name'),
|
|
isTitle: true,
|
|
create: true,
|
|
columnClass: 'expand',
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'socialName',
|
|
label: t('customer.extendedList.tableVisibleColumns.socialName'),
|
|
isTitle: true,
|
|
create: true,
|
|
columnClass: 'expand',
|
|
columnFilter: {
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'Clients',
|
|
fields: ['socialName'],
|
|
optionLabel: 'socialName',
|
|
optionValue: 'socialName',
|
|
uppercase: false,
|
|
},
|
|
},
|
|
attrs: {
|
|
uppercase: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'fi',
|
|
label: t('customer.extendedList.tableVisibleColumns.fi'),
|
|
create: true,
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'salesPersonFk',
|
|
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'Workers/activeWithInheritedRole',
|
|
fields: ['id', 'name'],
|
|
where: { role: 'salesPerson' },
|
|
optionFilter: 'firstName',
|
|
},
|
|
create: false,
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'credit',
|
|
label: t('customer.summary.credit'),
|
|
columnFilter: {
|
|
component: 'number',
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'creditInsurance',
|
|
label: t('customer.extendedList.tableVisibleColumns.creditInsurance'),
|
|
columnFilter: {
|
|
component: 'number',
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'phone',
|
|
label: t('customer.extendedList.tableVisibleColumns.phone'),
|
|
cardVisible: true,
|
|
columnFilter: {
|
|
component: 'number',
|
|
},
|
|
columnField: {
|
|
component: null,
|
|
after: {
|
|
component: markRaw(VnLinkPhone),
|
|
attrs: ({ model }) => {
|
|
return {
|
|
'phone-number': model,
|
|
};
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'mobile',
|
|
label: t('customer.summary.mobile'),
|
|
cardVisible: true,
|
|
columnFilter: {
|
|
component: 'number',
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'street',
|
|
label: t('customer.extendedList.tableVisibleColumns.street'),
|
|
create: true,
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
columnClass: 'expand',
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'countryFk',
|
|
label: t('customer.extendedList.tableVisibleColumns.countryFk'),
|
|
columnFilter: {
|
|
component: 'select',
|
|
inWhere: true,
|
|
alias: 'c',
|
|
attrs: {
|
|
url: 'Countries',
|
|
},
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.country),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'provinceFk',
|
|
label: t('customer.extendedList.tableVisibleColumns.provinceFk'),
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'Provinces',
|
|
},
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.province),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'city',
|
|
label: t('customer.summary.city'),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'postcode',
|
|
label: t('customer.summary.postcode'),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'email',
|
|
label: t('globals.params.email'),
|
|
cardVisible: true,
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'created',
|
|
label: t('customer.extendedList.tableVisibleColumns.created'),
|
|
format: ({ created }) => toDate(created),
|
|
columnFilter: {
|
|
component: 'date',
|
|
alias: 'c',
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'businessTypeFk',
|
|
label: t('customer.extendedList.tableVisibleColumns.businessTypeFk'),
|
|
create: true,
|
|
component: 'select',
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
attrs: {
|
|
url: 'BusinessTypes',
|
|
fields: ['code', 'description'],
|
|
sortBy: 'description ASC ',
|
|
optionLabel: 'description',
|
|
optionValue: 'code',
|
|
},
|
|
columnField: {
|
|
component: null,
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.businessType),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'payMethodFk',
|
|
label: t('customer.summary.payMethodFk'),
|
|
columnFilter: {
|
|
component: 'select',
|
|
attrs: {
|
|
url: 'PayMethods',
|
|
},
|
|
inWhere: true,
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.payMethod),
|
|
},
|
|
{
|
|
align: 'left',
|
|
label: t('customer.extendedList.tableVisibleColumns.sageTaxTypeFk'),
|
|
name: 'sageTaxTypeFk',
|
|
columnFilter: {
|
|
component: 'select',
|
|
attrs: {
|
|
optionLabel: 'vat',
|
|
url: 'SageTaxTypes',
|
|
},
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.sageTaxType),
|
|
},
|
|
{
|
|
align: 'left',
|
|
label: t('customer.extendedList.tableVisibleColumns.sageTransactionTypeFk'),
|
|
name: 'sageTransactionTypeFk',
|
|
columnFilter: {
|
|
component: 'select',
|
|
attrs: {
|
|
optionLabel: 'transaction',
|
|
url: 'SageTransactionTypes',
|
|
},
|
|
},
|
|
format: (row, dashIfEmpty) => dashIfEmpty(row.sageTransactionType),
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isActive',
|
|
label: t('customer.summary.isActive'),
|
|
chip: {
|
|
color: null,
|
|
condition: (value) => !value,
|
|
icon: 'vn:disabled',
|
|
},
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isVies',
|
|
label: t('globals.isVies'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isTaxDataChecked',
|
|
label: t('customer.extendedList.tableVisibleColumns.isTaxDataChecked'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isEqualizated',
|
|
label: t('customer.summary.isEqualizated'),
|
|
create: true,
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isFreezed',
|
|
label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
|
|
chip: {
|
|
color: null,
|
|
condition: (value) => value,
|
|
icon: 'vn:frozen',
|
|
},
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hasToInvoice',
|
|
label: t('customer.extendedList.tableVisibleColumns.hasToInvoice'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hasToInvoiceByAddress',
|
|
label: t('customer.extendedList.tableVisibleColumns.hasToInvoiceByAddress'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'isToBeMailed',
|
|
label: t('customer.extendedList.tableVisibleColumns.isToBeMailed'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hasLcr',
|
|
label: t('customer.summary.hasLcr'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hasCoreVnl',
|
|
label: t('customer.summary.hasCoreVnl'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'left',
|
|
name: 'hasSepaVnl',
|
|
label: t('customer.extendedList.tableVisibleColumns.hasSepaVnl'),
|
|
columnFilter: {
|
|
inWhere: true,
|
|
},
|
|
},
|
|
{
|
|
align: 'right',
|
|
label: '',
|
|
name: 'tableActions',
|
|
actions: [
|
|
{
|
|
title: t('Client ticket list'),
|
|
icon: 'vn:ticket',
|
|
action: redirectToTicketsList,
|
|
isPrimary: true,
|
|
},
|
|
{
|
|
title: t('components.smartCard.viewSummary'),
|
|
icon: 'preview',
|
|
isPrimary: true,
|
|
action: (row) => viewSummary(row.id, CustomerSummary),
|
|
},
|
|
],
|
|
},
|
|
]);
|
|
|
|
const { viewSummary } = useSummaryDialog();
|
|
const redirectToTicketsList = (row) => {
|
|
router.push({
|
|
name: 'TicketList',
|
|
|
|
query: {
|
|
table: JSON.stringify({
|
|
clientFk: row.id,
|
|
}),
|
|
},
|
|
});
|
|
};
|
|
|
|
function handleLocation(data, location) {
|
|
const { town, code, provinceFk, countryFk } = location ?? {};
|
|
data.postcode = code;
|
|
data.city = town;
|
|
data.provinceFk = provinceFk;
|
|
data.countryFk = countryFk;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<VnSection
|
|
:data-key="dataKey"
|
|
:columns="columns"
|
|
prefix="customer"
|
|
:array-data-props="{
|
|
url: 'Clients/filter',
|
|
order: ['id DESC'],
|
|
}"
|
|
>
|
|
<template #advanced-menu>
|
|
<CustomerFilter data-key="CustomerList" />
|
|
</template>
|
|
<template #body>
|
|
<VnTable
|
|
ref="tableRef"
|
|
:data-key="dataKey"
|
|
url="Clients/extendedListFilter"
|
|
:create="{
|
|
urlCreate: 'Clients/createWithUser',
|
|
title: t('globals.pageTitles.customerCreate'),
|
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
|
formInitialData: {
|
|
active: true,
|
|
isEqualizated: false,
|
|
},
|
|
}"
|
|
:columns="columns"
|
|
:right-search="false"
|
|
redirect="customer"
|
|
>
|
|
<template #more-create-dialog="{ data }">
|
|
<VnSelectWorker
|
|
:label="t('customer.summary.salesPerson')"
|
|
v-model="data.salesPersonFk"
|
|
:params="{
|
|
departmentCodes: ['VT', 'shopping'],
|
|
}"
|
|
:has-avatar="true"
|
|
:id-value="data.salesPersonFk"
|
|
emit-value
|
|
auto-load
|
|
>
|
|
<template #prepend>
|
|
<VnAvatar
|
|
:worker-id="data.salesPersonFk"
|
|
color="primary"
|
|
:title="title"
|
|
/>
|
|
</template>
|
|
<template #option="scope">
|
|
<QItem v-bind="scope.itemProps">
|
|
<QItemSection>
|
|
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
<QItemLabel caption
|
|
>{{ scope.opt?.nickname }},
|
|
{{ scope.opt?.code }}</QItemLabel
|
|
>
|
|
</QItemSection>
|
|
</QItem>
|
|
</template>
|
|
</VnSelectWorker>
|
|
<VnLocation
|
|
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
|
|
v-model="data.location"
|
|
@update:model-value="(location) => handleLocation(data, location)"
|
|
/>
|
|
<QInput v-model="data.userName" :label="t('Web user')" />
|
|
<QInput
|
|
:label="t('Email')"
|
|
clearable
|
|
type="email"
|
|
v-model="data.email"
|
|
>
|
|
<template #append>
|
|
<QIcon name="info" class="cursor-info">
|
|
<QTooltip max-width="400px">{{
|
|
t('customer.basicData.youCanSaveMultipleEmails')
|
|
}}</QTooltip>
|
|
</QIcon>
|
|
</template>
|
|
</QInput>
|
|
</template>
|
|
</VnTable>
|
|
</template>
|
|
</VnSection>
|
|
</template>
|
|
<i18n>
|
|
es:
|
|
Web user: Usuario web
|
|
</i18n>
|
|
<style lang="scss" scoped>
|
|
.col-content {
|
|
border-radius: 4px;
|
|
padding: 6px;
|
|
}
|
|
</style>
|