forked from verdnatura/salix-front
perf: customerSummaryTable
This commit is contained in:
parent
9a48cb0742
commit
10747d7a4f
|
@ -65,6 +65,10 @@ const $props = defineProps({
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disableInfiniteScroll: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
hasSubToolbar: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
@ -335,11 +339,13 @@ defineExpose({
|
|||
<div class="q-px-md">
|
||||
<CrudModel
|
||||
v-bind="$attrs"
|
||||
:limit="20"
|
||||
:limit="$attrs['limit'] ?? 20"
|
||||
ref="CrudModelRef"
|
||||
@on-fetch="(...args) => emit('onFetch', ...args)"
|
||||
:search-url="searchUrl"
|
||||
:disable-infinite-scroll="isTableMode"
|
||||
:disable-infinite-scroll="
|
||||
$attrs['disableInfiniteScroll'] ? isTableMode : disableInfiniteScroll
|
||||
"
|
||||
@save-changes="reload"
|
||||
:has-sub-toolbar="$attrs['hasSubToolbar'] ?? isEditable"
|
||||
:auto-load="hasParams || $attrs['auto-load']"
|
||||
|
@ -486,11 +492,7 @@ defineExpose({
|
|||
:icon="btn.icon"
|
||||
class="q-px-sm"
|
||||
flat
|
||||
:class="
|
||||
btn.isPrimary
|
||||
? 'text-primary-light'
|
||||
: 'color-vn-text '
|
||||
"
|
||||
:class="'text-primary-light'"
|
||||
:style="`visibility: ${
|
||||
(btn.show && btn.show(row)) ?? true
|
||||
? 'visible'
|
||||
|
|
|
@ -375,6 +375,7 @@ customer:
|
|||
averageInvoiced: Average invoiced
|
||||
claimRate: Claming rate
|
||||
risk: Risk
|
||||
maximumRisk: Solunion's maximum risk
|
||||
riskInfo: Invoices minus payments plus orders not yet invoiced
|
||||
credit: Credit
|
||||
creditInfo: Company's maximum risk
|
||||
|
|
|
@ -373,6 +373,8 @@ customer:
|
|||
priceIncreasingRate: Ratio de incremento de precio
|
||||
averageInvoiced: Facturación media
|
||||
claimRate: Ratio de reclamaciones
|
||||
maximumRisk: Riesgo máximo asumido por Solunion
|
||||
|
||||
risk: Riesgo
|
||||
riskInfo: Facturas menos recibos mas pedidos sin facturar
|
||||
credit: Crédito
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import { computed, ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||
|
||||
import { toCurrency, toPercentage, toDate } from 'src/filters';
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import { getUrl } from 'src/composables/getUrl';
|
||||
|
@ -40,11 +42,11 @@ const balanceDue = computed(() => {
|
|||
const balanceDueWarning = computed(() => (balanceDue.value ? 'negative' : ''));
|
||||
|
||||
const claimRate = computed(() => {
|
||||
return customer.value.claimsRatio.claimingRate;
|
||||
return customer.value.claimsRatio?.claimingRate ?? 0;
|
||||
});
|
||||
|
||||
const priceIncreasingRate = computed(() => {
|
||||
return customer.value.claimsRatio.priceIncreasing / 100;
|
||||
return customer.value.claimsRatio?.priceIncreasing ?? 0 / 100;
|
||||
});
|
||||
|
||||
const debtWarning = computed(() => {
|
||||
|
@ -91,7 +93,13 @@ const creditWarning = computed(() => {
|
|||
<VnLv
|
||||
:label="t('customer.summary.salesPerson')"
|
||||
:value="entity?.salesPersonUser?.name"
|
||||
/>
|
||||
>
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
:name="entity.salesPersonUser?.name"
|
||||
:worker-id="entity.salesPersonFk"
|
||||
/> </template
|
||||
></VnLv>
|
||||
<VnLv
|
||||
:label="t('customer.summary.contactChannel')"
|
||||
:value="entity?.contactChannel?.name"
|
||||
|
@ -131,7 +139,7 @@ const creditWarning = computed(() => {
|
|||
:url="`#/customer/${entityId}/fiscal-data`"
|
||||
:text="t('customer.summary.fiscalData')"
|
||||
/>
|
||||
<VnRow>
|
||||
<VnRow class="block">
|
||||
<VnLv
|
||||
:label="t('customer.summary.isEqualizated')"
|
||||
:value="entity.isEqualizated"
|
||||
|
@ -140,8 +148,8 @@ const creditWarning = computed(() => {
|
|||
:label="t('customer.summary.isActive')"
|
||||
:value="entity.isActive"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<!-- </VnRow>
|
||||
<VnRow> -->
|
||||
<VnLv
|
||||
:label="t('customer.summary.verifiedData')"
|
||||
:value="entity.isTaxDataChecked"
|
||||
|
@ -150,8 +158,8 @@ const creditWarning = computed(() => {
|
|||
:label="t('customer.summary.hasToInvoice')"
|
||||
:value="entity.hasToInvoice"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<!-- </VnRow>
|
||||
<VnRow> -->
|
||||
<VnLv
|
||||
:label="t('customer.summary.notifyByEmail')"
|
||||
:value="entity.isToBeMailed"
|
||||
|
@ -170,7 +178,7 @@ const creditWarning = computed(() => {
|
|||
/>
|
||||
<VnLv :label="t('customer.summary.bankAccount')" :value="entity.iban" />
|
||||
<VnLv :label="t('customer.summary.dueDay')" :value="entity.dueDay" />
|
||||
<VnRow class="q-mt-sm" wrap>
|
||||
<VnRow class="q-mt-sm block">
|
||||
<VnLv :label="t('customer.summary.hasLcr')" :value="entity.hasLcr" />
|
||||
<VnLv
|
||||
:label="t('customer.summary.hasCoreVnl')"
|
||||
|
@ -227,7 +235,6 @@ const creditWarning = computed(() => {
|
|||
:value="toCurrency(entity?.mana?.mana)"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="entity.claimsRatio"
|
||||
:label="t('customer.summary.priceIncreasingRate')"
|
||||
:value="toPercentage(priceIncreasingRate)"
|
||||
/>
|
||||
|
@ -236,7 +243,6 @@ const creditWarning = computed(() => {
|
|||
:value="toCurrency(entity?.averageInvoiced?.invoiced)"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="entity.claimsRatio"
|
||||
:label="t('customer.summary.claimRate')"
|
||||
:value="toPercentage(claimRate)"
|
||||
/>
|
||||
|
@ -262,12 +268,10 @@ const creditWarning = computed(() => {
|
|||
/>
|
||||
|
||||
<VnLv
|
||||
v-if="entity.creditInsurance"
|
||||
:label="t('customer.summary.securedCredit')"
|
||||
:value="toCurrency(entity.creditInsurance)"
|
||||
:info="t('customer.summary.securedCreditInfo')"
|
||||
/>
|
||||
|
||||
<VnLv
|
||||
:label="t('customer.summary.balance')"
|
||||
:value="toCurrency(entity.sumRisk) || toCurrency(0)"
|
||||
|
@ -297,7 +301,7 @@ const creditWarning = computed(() => {
|
|||
:value="entity.recommendedCredit"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-one">
|
||||
<QCard>
|
||||
<VnTitle :text="t('Latest tickets')" />
|
||||
<CustomerSummaryTable />
|
||||
</QCard>
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { QBtn, date } from 'quasar';
|
||||
import { date } from 'quasar';
|
||||
import { toDateFormat } from 'src/filters/date.js';
|
||||
|
||||
import { toCurrency } from 'src/filters';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import CustomerSummaryTableActions from './CustomerSummaryTableActions.vue';
|
||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
|
||||
|
||||
import InvoiceOutDescriptorProxy from 'pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
|
||||
// import FetchData from 'components/FetchData.vue';
|
||||
import RouteDescriptorProxy from 'src/pages/Route/Card/RouteDescriptorProxy.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const rows = ref([]);
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
|
||||
const filter = {
|
||||
include: [
|
||||
|
@ -32,57 +35,6 @@ const filter = {
|
|||
],
|
||||
where: { clientFk: route.params.id },
|
||||
order: ['shipped DESC', 'id'],
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
const tableColumnComponents = {
|
||||
id: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
nickname: {
|
||||
component: QBtn,
|
||||
props: () => ({ flat: true, color: 'blue', noCaps: true }),
|
||||
event: () => {},
|
||||
},
|
||||
agency: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
route: {
|
||||
component: QBtn,
|
||||
props: () => ({ flat: true, color: 'blue' }),
|
||||
event: () => {},
|
||||
},
|
||||
packages: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
date: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
state: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
total: {
|
||||
component: 'span',
|
||||
props: () => {},
|
||||
event: () => {},
|
||||
},
|
||||
actions: {
|
||||
component: CustomerSummaryTableActions,
|
||||
props: (prop) => ({
|
||||
id: prop.row.id,
|
||||
}),
|
||||
event: () => {},
|
||||
},
|
||||
};
|
||||
|
||||
const columns = computed(() => [
|
||||
|
@ -94,21 +46,18 @@ const columns = computed(() => [
|
|||
},
|
||||
{
|
||||
align: 'left',
|
||||
field: 'nickname',
|
||||
label: t('Nickname'),
|
||||
name: 'nickname',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
field: (row) => row?.agencyMode?.name,
|
||||
format: (row) => row.agencyMode.name,
|
||||
label: t('Agency'),
|
||||
name: 'agency',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
field: 'routeFk',
|
||||
name: 'routeFk',
|
||||
label: t('Route'),
|
||||
name: 'route',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -118,13 +67,12 @@ const columns = computed(() => [
|
|||
},
|
||||
{
|
||||
align: 'left',
|
||||
field: (row) => date.formatDate(row?.shipped, 'DD/MM/YYYY'),
|
||||
format: ({ shipped }) => date.formatDate(shipped, 'DD/MM/YYYY'),
|
||||
label: t('Date'),
|
||||
name: 'date',
|
||||
name: 'shipped',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
field: (row) => row?.ticketState?.state?.name,
|
||||
label: t('State'),
|
||||
name: 'state',
|
||||
},
|
||||
|
@ -134,11 +82,26 @@ const columns = computed(() => [
|
|||
label: t('Total'),
|
||||
name: 'total',
|
||||
},
|
||||
|
||||
{
|
||||
align: 'left',
|
||||
field: 'totalWithVat',
|
||||
align: 'right',
|
||||
label: '',
|
||||
name: 'actions',
|
||||
name: 'tableActions',
|
||||
actions: [
|
||||
{
|
||||
title: t('Client ticket list'),
|
||||
icon: 'vn:lines',
|
||||
action: ({ id }) =>
|
||||
router.push({ params: { id }, name: 'TicketSummary' }),
|
||||
isPrimary: true,
|
||||
},
|
||||
{
|
||||
title: t('Client ticket list'),
|
||||
icon: 'preview',
|
||||
isPrimary: true,
|
||||
action: (row) => viewSummary(row.id, TicketSummary),
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -156,83 +119,89 @@ const setTotalPriceColor = (ticket) => {
|
|||
if (total > 0 && total < 50) return 'warning';
|
||||
};
|
||||
|
||||
const navigateToticketSummary = (id) => {
|
||||
router.push({
|
||||
name: 'TicketSummary',
|
||||
params: { id },
|
||||
});
|
||||
const setShippedColor = (date) => {
|
||||
const today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const ticketShipped = new Date(date);
|
||||
ticketShipped.setHours(0, 0, 0, 0);
|
||||
|
||||
const difference = today - ticketShipped;
|
||||
|
||||
if (difference == 0) return 'warning';
|
||||
if (difference < 0) return 'success';
|
||||
};
|
||||
const commonColumns = (col) =>
|
||||
['date', 'state', 'total', 'route', 'nickname'].includes(col);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
<VnTable
|
||||
data-key="CustomerTickets"
|
||||
:filter="filter"
|
||||
@on-fetch="(data) => (rows = data)"
|
||||
auto-load
|
||||
url="Tickets"
|
||||
/>
|
||||
<QCard class="vn-one q-py-sm flex justify-between">
|
||||
<QTable
|
||||
:columns="columns"
|
||||
:pagination="{ rowsPerPage: 12 }"
|
||||
:rows="rows"
|
||||
class="full-width"
|
||||
row-key="id"
|
||||
>
|
||||
<template #body-cell="props">
|
||||
<QTd :props="props" @click="navigateToticketSummary(props.row.id)">
|
||||
<QTr :props="props" class="cursor-pointer">
|
||||
<component
|
||||
:is="tableColumnComponents[props.col.name].component"
|
||||
@click="tableColumnComponents[props.col.name].event(props)"
|
||||
class="rounded-borders"
|
||||
v-bind="tableColumnComponents[props.col.name].props(props)"
|
||||
>
|
||||
<template v-if="!commonColumns(props.col.name)">
|
||||
<span>
|
||||
{{ props.value }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="props.col.name === 'route'">
|
||||
<span class="link" @click.stop>
|
||||
<RouteDescriptorProxy :id="props.row.routeFk" />
|
||||
{{ props.value }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="props.col.name === 'nickname'">
|
||||
<span class="link" @click.stop>
|
||||
<CustomerDescriptorProxy :id="props.row.clientFk" />
|
||||
{{ props.value }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="props.col.name === 'date'">
|
||||
<QBadge class="q-pa-sm" color="warning">
|
||||
{{ props.value }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template v-if="props.col.name === 'state'">
|
||||
<QBadge :color="setStateColor(props.row)" class="q-pa-sm">
|
||||
{{ props.value }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template v-if="props.col.name === 'total'">
|
||||
<QBadge
|
||||
:color="setTotalPriceColor(props.row)"
|
||||
class="q-pa-sm"
|
||||
v-if="setTotalPriceColor(props.row)"
|
||||
>
|
||||
{{ toCurrency(props.value) }}
|
||||
</QBadge>
|
||||
<div v-else>{{ toCurrency(props.value) }}</div>
|
||||
</template>
|
||||
</component>
|
||||
</QTr>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
:columns="columns"
|
||||
search-url="tickets"
|
||||
:without-header="true"
|
||||
auto-load
|
||||
order="shipped DESC, id"
|
||||
limit="5"
|
||||
>
|
||||
<template #column-nickname="{ row }">
|
||||
<span class="link">
|
||||
{{ row.nickname }}
|
||||
<TicketDescriptorProxy :id="row.nickname" />
|
||||
</span>
|
||||
</template>
|
||||
<template #column-ticketFk="{ row }">
|
||||
<span class="link">
|
||||
{{ row.ticketFk }}
|
||||
<TicketDescriptorProxy :id="row.ticketFk" />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #column-routeFk="{ row }">
|
||||
<span class="link">
|
||||
{{ row.routeFk }}
|
||||
<RouteDescriptorProxy :id="row.ticketFk" />
|
||||
</span>
|
||||
</template>
|
||||
<template #column-total="{ row }">
|
||||
<QBadge
|
||||
class="q-pa-sm"
|
||||
v-if="setTotalPriceColor(row)"
|
||||
:color="setTotalPriceColor(row)"
|
||||
>
|
||||
<!-- {{ setTotalPriceColor(row) }} -->
|
||||
{{ toCurrency(row.totalWithVat) }}
|
||||
</QBadge>
|
||||
<span v-else> {{ toCurrency(row.totalWithVat) }}</span>
|
||||
</template>
|
||||
<template #column-state="{ row }">
|
||||
<span v-if="row.invoiceOut">
|
||||
<span :class="{ link: row.invoiceOut.ref }">
|
||||
{{ row.invoiceOut.ref }}
|
||||
<InvoiceOutDescriptorProxy :id="row.invoiceOut.id" />
|
||||
</span>
|
||||
</span>
|
||||
<QBadge
|
||||
class="q-pa-sm"
|
||||
:color="setStateColor(row)"
|
||||
v-else-if="setStateColor(row)"
|
||||
>
|
||||
{{ row?.ticketState?.state.name }}
|
||||
</QBadge>
|
||||
<span v-else> {{ row?.ticketState?.state.name }}</span>
|
||||
</template>
|
||||
<template #column-shipped="{ row }">
|
||||
<QBadge
|
||||
class="q-pa-sm"
|
||||
:color="setShippedColor(row.shipped)"
|
||||
v-if="setShippedColor(row.shipped)"
|
||||
>
|
||||
{{ toDateFormat(row.shipped) }}
|
||||
</QBadge>
|
||||
<span v-else> {{ toDateFormat(row.shipped) }}</span>
|
||||
</template>
|
||||
</VnTable>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ id }}
|
||||
<QIcon
|
||||
color="primary"
|
||||
name="vn:lines"
|
||||
size="sm"
|
||||
@click.stop="router.push({ params: { id }, name: 'TicketSale' })"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('Go to lines') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
@click.stop="viewSummary(id, TicketSummary)"
|
||||
class="q-ml-md"
|
||||
color="primary"
|
||||
name="preview"
|
||||
size="sm"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('Preview') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Go to lines: Ir a lineas
|
||||
Preview: Vista previa
|
||||
</i18n>
|
Loading…
Reference in New Issue