0
0
Fork 0

Solucion a comentarios 10

This commit is contained in:
carlosfonseca 2024-02-15 21:42:29 -05:00
parent 5e2c668fec
commit 17a0afda73
5 changed files with 387 additions and 42 deletions

View File

@ -16,6 +16,7 @@ import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import CustomerNewPayment from 'src/pages/Customer/components/CustomerNewPayment.vue'; import CustomerNewPayment from 'src/pages/Customer/components/CustomerNewPayment.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
const { t } = useI18n(); const { t } = useI18n();
const { validate } = useValidator(); const { validate } = useValidator();
@ -44,28 +45,27 @@ const filter = {
}; };
const tableColumnComponents = { const tableColumnComponents = {
payed: { date: {
component: 'span', component: 'span',
props: () => {}, props: () => {},
event: () => {}, event: () => {},
}, },
created: { creationDate: {
component: 'span', component: 'span',
props: () => {}, props: () => {},
event: () => {}, event: () => {},
}, },
userName: { employee: {
component: QBtn, component: QBtn,
props: () => ({ flat: true, color: 'blue' }), props: () => ({ flat: true, color: 'blue' }),
event: () => {}, event: () => {},
}, },
description: { reference: {
component: QField, component: 'div',
attrs: () => ({ readonly: true, dense: true }),
props: () => {}, props: () => {},
event: () => {}, event: () => {},
}, },
bankFk: { bank: {
component: 'span', component: 'span',
props: () => {}, props: () => {},
event: () => {}, event: () => {},
@ -75,7 +75,7 @@ const tableColumnComponents = {
props: () => {}, props: () => {},
event: () => {}, event: () => {},
}, },
credit: { havings: {
component: 'span', component: 'span',
props: () => {}, props: () => {},
event: () => {}, event: () => {},
@ -85,7 +85,7 @@ const tableColumnComponents = {
props: () => {}, props: () => {},
event: () => {}, event: () => {},
}, },
isConciliate: { conciliated: {
component: QCheckbox, component: QCheckbox,
props: (prop) => ({ props: (prop) => ({
disable: true, disable: true,
@ -101,32 +101,32 @@ const columns = computed(() => [
field: 'payed', field: 'payed',
format: (value) => toDate(value), format: (value) => toDate(value),
label: t('Date'), label: t('Date'),
name: 'payed', name: 'date',
}, },
{ {
align: 'left', align: 'left',
field: 'created', field: 'created',
format: (value) => toDateHour(value), format: (value) => toDateHour(value),
label: t('Creation date'), label: t('Creation date'),
name: 'created', name: 'creationDate',
}, },
{ {
align: 'left', align: 'left',
field: 'userName', field: 'userName',
label: t('Employee'), label: t('Employee'),
name: 'userName', name: 'employee',
}, },
{ {
align: 'left', align: 'left',
field: 'description', field: 'description',
label: t('Reference'), label: t('Reference'),
name: 'description', name: 'reference',
}, },
{ {
align: 'left', align: 'left',
field: 'bankFk', field: 'bankFk',
label: t('Bank'), label: t('Bank'),
name: 'bankFk', name: 'bank',
}, },
{ {
align: 'left', align: 'left',
@ -139,7 +139,7 @@ const columns = computed(() => [
field: 'credit', field: 'credit',
format: (value) => toCurrency(value), format: (value) => toCurrency(value),
label: t('Havings'), label: t('Havings'),
name: 'credit', name: 'havings',
}, },
{ {
align: 'left', align: 'left',
@ -152,7 +152,7 @@ const columns = computed(() => [
align: 'left', align: 'left',
field: 'isConciliate', field: 'isConciliate',
label: t('Conciliated'), label: t('Conciliated'),
name: 'isConciliate', name: 'conciliated',
}, },
]); ]);
@ -237,17 +237,32 @@ const saveFieldValue = async (event) => {
> >
<template <template
v-if=" v-if="
props.col.name !== 'isConciliate' && props.col.name !== 'conciliated' &&
props.col.name !== 'description' props.col.name !== 'reference'
" "
> >
{{ props.value }} {{ props.value }}
</template> </template>
<template v-if="props.col.name === 'description'" #control> <template v-if="props.col.name === 'reference'">
<div class="self-center full-width no-outline" tabindex="0"> <div v-if="props.row.isInvoice">
{{ props.value }} <QBtn color="blue" dense flat>
{{ t('bill', { ref: props.value }) }}
</QBtn>
<InvoiceOutDescriptorProxy
:id="props.row.id"
v-if="props.col.name === 'reference'"
/>
</div> </div>
<div v-else>
<QBtn
:label="props.value"
flat
rounded
class="dotted-border-btn"
no-caps
/>
<QPopupEdit <QPopupEdit
:key="props.col.name" :key="props.col.name"
label-cancel="Close" label-cancel="Close"
@ -262,11 +277,12 @@ const saveFieldValue = async (event) => {
v-model="props.row.description" v-model="props.row.description"
/> />
</QPopupEdit> </QPopupEdit>
</div>
</template> </template>
<WorkerDescriptorProxy <WorkerDescriptorProxy
:id="props.row.workerFk" :id="props.row.workerFk"
v-if="props.col.name === 'userName'" v-if="props.col.name === 'employee'"
/> />
</component> </component>
</QTr> </QTr>
@ -318,9 +334,17 @@ const saveFieldValue = async (event) => {
border-radius: 4px; border-radius: 4px;
padding: 6px; padding: 6px;
} }
.dotted-border-btn {
border: 1px dotted var(--vn-label);
&:hover {
border: 1px dotted $primary;
}
}
</style> </style>
<i18n> <i18n>
en:
bill: 'N/FRA {ref}'
es: es:
Company: Empresa Company: Empresa
Total by company: Total por empresa Total by company: Total por empresa
@ -329,6 +353,7 @@ es:
Creation date: Fecha de creación Creation date: Fecha de creación
Employee: Empleado Employee: Empleado
Reference: Referencia Reference: Referencia
bill: 'N/INV {ref}'
Bank: Caja Bank: Caja
Debit: Debe Debit: Debe
Havings: Haber Havings: Haber

View File

@ -7,6 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
import { getUrl } from 'src/composables/getUrl'; import { getUrl } from 'src/composables/getUrl';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -277,6 +278,12 @@ const creditWarning = computed(() => {
:value="toDate(entity.recovery.started)" :value="toDate(entity.recovery.started)"
/> />
</QCard> </QCard>
<QCard>
<div class="header">
{{ t('Latest tickets') }}
</div>
<CustomerSummaryTable />
</QCard>
</template> </template>
</CardSummary> </CardSummary>
</template> </template>

View File

@ -32,9 +32,8 @@ const workersOptions = ref([]);
const businessTypesOptions = ref([]); const businessTypesOptions = ref([]);
const postcodesOptions = ref([]); const postcodesOptions = ref([]);
function handleLocation(data, location) { function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {} const { town, code, provinceFk, countryFk } = location ?? {};
data.postcode = code; data.postcode = code;
data.city = town; data.city = town;
data.provinceFk = provinceFk; data.provinceFk = provinceFk;
@ -95,7 +94,7 @@ function handleLocation(data, location ) {
<div class="col"> <div class="col">
<QInput <QInput
:label="t('Business name')" :label="t('Business name')"
:rules="validate('Client.socialName')" :rules="validate('client.socialName')"
v-model="data.socialName" v-model="data.socialName"
/> />
</div> </div>
@ -104,7 +103,7 @@ function handleLocation(data, location ) {
<div class="col"> <div class="col">
<QInput <QInput
:label="t('Street')" :label="t('Street')"
:rules="validate('Client.street')" :rules="validate('client.street')"
v-model="data.street" v-model="data.street"
/> />
</div> </div>
@ -129,7 +128,21 @@ function handleLocation(data, location ) {
<QInput v-model="data.userName" :label="t('Web user')" /> <QInput v-model="data.userName" :label="t('Web user')" />
</div> </div>
<div class="col"> <div class="col">
<QInput v-model="data.email" :label="t('Email')" /> <QInput
:label="t('Email')"
:rules="validate('client.email')"
clearable
type="email"
v-model="data.email"
>
<template #append>
<QIcon name="info" class="cursor-info">
<QTooltip>{{
t('customer.basicData.youCanSaveMultipleEmails')
}}</QTooltip>
</QIcon>
</template>
</QInput>
</div> </div>
</VnRow> </VnRow>
<QCheckbox <QCheckbox

View File

@ -0,0 +1,247 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { QBtn, date } from 'quasar';
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 RouteDescriptorProxy from 'src/pages/Route/Card/RouteDescriptorProxy.vue';
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const rows = ref([]);
const filter = {
include: [
{
relation: 'ticketState',
scope: {
fields: ['stateFk', 'code', 'alertLevel'],
include: { relation: 'state' },
},
},
{ relation: 'invoiceOut', scope: { fields: ['id'] } },
{ relation: 'agencyMode', scope: { fields: ['name'] } },
],
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' }),
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(() => [
{
align: 'left',
field: 'id',
label: t('Id'),
name: 'id',
},
{
align: 'left',
field: 'nickname',
label: t('Nickname'),
name: 'nickname',
},
{
align: 'left',
field: (row) => row?.agencyMode?.name,
label: t('Agency'),
name: 'agency',
},
{
align: 'left',
field: 'routeFk',
label: t('Route'),
name: 'route',
},
{
align: 'left',
field: 'packages',
label: t('Packages'),
name: 'packages',
},
{
align: 'left',
field: (row) => date.formatDate(row?.shipped, 'DD/MM/YYYY'),
label: t('Date'),
name: 'date',
},
{
align: 'left',
field: (row) => row?.ticketState?.state?.name,
label: t('State'),
name: 'state',
},
{
align: 'left',
field: 'totalWithVat',
label: t('Total'),
name: 'total',
},
{
align: 'left',
field: 'totalWithVat',
label: '',
name: 'actions',
},
]);
const setStateColor = (ticket) => {
const { ticketState } = ticket;
if (!ticketState) return;
const codeColorMap = { OK: 'success', FREE: 'notice' };
const alertLevelColorMap = { 0: 'alert', 1: 'warning' };
if (codeColorMap[ticketState.code]) return codeColorMap[ticketState.code];
return alertLevelColorMap[ticketState.alertLevel];
};
const setTotalPriceColor = (ticket) => {
const total = parseInt(ticket.totalWithVat);
if (total > 0 && total < 50) return 'warning';
};
const navigateToticketSummary = (id) => {
router.push({
name: 'TicketSummary',
params: { id },
});
};
</script>
<template>
<FetchData
:filter="filter"
@on-fetch="(data) => (rows = data)"
auto-load
url="Tickets"
/>
<QTable
:columns="columns"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<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 q-pa-sm"
v-bind="tableColumnComponents[props.col.name].props(props)"
>
<template
v-if="
props.col.name === 'id' ||
props.col.name === 'nickname' ||
props.col.name === 'agency' ||
props.col.name === 'route' ||
props.col.name === 'packages'
"
>
{{ props.value }}
</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>
<CustomerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'nickname'"
/>
<RouteDescriptorProxy
:id="props.row.routeFk"
v-if="props.col.name === 'route'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
</template>
<i18n>
es:
Id: Id
Nickname: Alias
Agency: Agencia
Route: Ruta
Packages: Bultos
Date: Fecha
State: Estado
Total: Total
</i18n>

View File

@ -0,0 +1,53 @@
<script setup>
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import TicketSummaryDialog from 'src/pages/Ticket/Card/TicketSummaryDialog.vue';
const { t } = useI18n();
const quasar = useQuasar();
const $props = defineProps({
id: {
type: Number,
required: true,
},
});
const viewSummary = () => {
quasar.dialog({
component: TicketSummaryDialog,
componentProps: {
id: $props.id,
},
});
};
</script>
<template>
<div>
<QIcon color="primary" name="vn:lines" size="sm">
<QTooltip>
{{ t('Go to lines') }}
</QTooltip>
</QIcon>
<QIcon
@click.stop="viewSummary"
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>