forked from verdnatura/salix-front
Ticket components
This commit is contained in:
parent
2961c813a5
commit
5c36ad14f4
|
@ -452,6 +452,7 @@ ticket:
|
|||
weeklyTickets: Weekly tickets
|
||||
services: Service
|
||||
tracking: Tracking
|
||||
components: Components
|
||||
list:
|
||||
nickname: Nickname
|
||||
state: State
|
||||
|
|
|
@ -451,6 +451,7 @@ ticket:
|
|||
weeklyTickets: Tickets programados
|
||||
services: Servicios
|
||||
tracking: Estados
|
||||
components: Componentes
|
||||
list:
|
||||
nickname: Alias
|
||||
state: Estado
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
import { toCurrency } from 'filters/index';
|
||||
import axios from 'axios';
|
||||
|
||||
const route = useRoute();
|
||||
const stateStore = useStateStore();
|
||||
const { t } = useI18n();
|
||||
const salesRef = ref(null);
|
||||
const arrayData = useArrayData('ticketData');
|
||||
const { store } = arrayData;
|
||||
|
||||
const ticketData = computed(() => store.data);
|
||||
const components = ref([]);
|
||||
const componentsList = ref([]);
|
||||
const theoricalCost = ref(0);
|
||||
const ticketVolume = ref(null);
|
||||
|
||||
watch(
|
||||
() => ticketData.value,
|
||||
async () => {
|
||||
await nextTick();
|
||||
salesRef.value.fetch();
|
||||
getComponentsSum();
|
||||
getTheoricalCost();
|
||||
if (ticketData.value?.zone && ticketData.value?.zone?.isVolumetric)
|
||||
getTicketVolume();
|
||||
}
|
||||
);
|
||||
|
||||
const salesFilter = computed(() => ({
|
||||
order: 'concept ASC',
|
||||
include: [
|
||||
{
|
||||
relation: 'item',
|
||||
},
|
||||
{
|
||||
relation: 'components',
|
||||
scope: {
|
||||
fields: ['componentFk', 'value'],
|
||||
include: {
|
||||
relation: 'component',
|
||||
scope: {
|
||||
fields: ['typeFk', 'name'],
|
||||
include: {
|
||||
relation: 'componentType',
|
||||
scope: {
|
||||
fields: ['type', 'isBase'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
where: { ticketFk: route.params.id },
|
||||
}));
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
label: t('components.item'),
|
||||
name: 'item',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('components.description'),
|
||||
name: 'description',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('components.quantity'),
|
||||
name: 'quantity',
|
||||
field: 'quantity',
|
||||
align: 'left',
|
||||
format: (val) => dashIfEmpty(val),
|
||||
},
|
||||
{
|
||||
label: t('components.serie'),
|
||||
name: 'serie',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('components.components'),
|
||||
name: 'components',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('components.import'),
|
||||
name: 'import',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('components.total'),
|
||||
name: 'total',
|
||||
align: 'left',
|
||||
},
|
||||
]);
|
||||
|
||||
const getBase = computed(() => {
|
||||
let sum = 0;
|
||||
for (let sale of components.value) {
|
||||
for (let saleComponent of sale.components) {
|
||||
if (saleComponent.component.componentType.isBase) {
|
||||
sum += sale.quantity * saleComponent.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
});
|
||||
|
||||
const getTotal = computed(() => {
|
||||
let total = 0;
|
||||
for (let sale of components.value) {
|
||||
for (let saleComponent of sale.components) {
|
||||
total += sale.quantity * saleComponent.value;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
});
|
||||
|
||||
const getComponentsSum = async () => {
|
||||
try {
|
||||
const { data } = await axios.get(`Tickets/${route.params.id}/getComponentsSum`);
|
||||
componentsList.value = data;
|
||||
console.log('componentsList', componentsList.value);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getTheoricalCost = async () => {
|
||||
try {
|
||||
const { data } = await axios.get(`Tickets/${route.params.id}/freightCost`);
|
||||
theoricalCost.value = data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getTicketVolume = async () => {
|
||||
try {
|
||||
if (!ticketData.value) return;
|
||||
const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`);
|
||||
console.log('data volume: ', data);
|
||||
ticketVolume.value = data[0].volume;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
stateStore.rightDrawer = true;
|
||||
});
|
||||
|
||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
ref="salesRef"
|
||||
url="sales"
|
||||
:filter="salesFilter"
|
||||
@on-fetch="(data) => (components = data)"
|
||||
auto-load
|
||||
/>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
<QCard
|
||||
class="q-pa-sm color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('components.total') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label"
|
||||
>{{ t('components.baseToCommission') }}:
|
||||
</span>
|
||||
<span>{{ toCurrency(getBase) }}</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label"
|
||||
>{{ t('components.totalWithoutVat') }}:
|
||||
</span>
|
||||
<span>{{ toCurrency(getTotal) }}</span>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard
|
||||
class="q-pa-sm color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('components.components') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection
|
||||
v-for="(component, index) in componentsList"
|
||||
:key="index"
|
||||
class="justify-center"
|
||||
horizontal
|
||||
>
|
||||
<span class="q-mr-xs color-vn-label"> {{ component.name }}: </span>
|
||||
<span>{{ toCurrency(component.value, 'EUR', 3) }}</span>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard
|
||||
class="q-pa-sm color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('components.zoneBreakdown') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.price') }}:
|
||||
</span>
|
||||
<span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.bonus') }}:
|
||||
</span>
|
||||
<span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.zone') }}:
|
||||
</span>
|
||||
<span class="link">
|
||||
{{ dashIfEmpty(ticketData?.zone?.name) }}
|
||||
<ZoneDescriptorProxy :id="ticketData?.zone?.id" />
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection
|
||||
v-if="ticketData?.zone?.isVolumetric"
|
||||
class="justify-center"
|
||||
horizontal
|
||||
>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.volume') }}:
|
||||
</span>
|
||||
<span>{{ ticketVolume }}</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.packages') }}:
|
||||
</span>
|
||||
<span>{{ dashIfEmpty(ticketData?.packages) }}</span>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard
|
||||
class="q-pa-sm color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('components.theoricalCost') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="justify-center" horizontal>
|
||||
<span class="q-mr-xs color-vn-label">
|
||||
{{ t('components.totalPrice') }}:
|
||||
</span>
|
||||
<span>{{ toCurrency(theoricalCost, 'EUR', 2) }}</span>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</template>
|
||||
</RightMenu>
|
||||
<QTable
|
||||
:rows="components"
|
||||
:columns="columns"
|
||||
row-key="id"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
class="full-width q-mt-md"
|
||||
:no-data-label="t('globals.noResults')"
|
||||
>
|
||||
<template #body-cell-item="{ row }">
|
||||
<QTd>
|
||||
<QBtn flat color="primary">
|
||||
{{ row.itemFk }}
|
||||
<ItemDescriptorProxy :id="row.itemFk" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-description="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span>{{ row.item.name }}</span>
|
||||
<span class="color-vn-label">{{ row.item.subName }}</span>
|
||||
<FetchedTags :item="row.item" :max-length="6" />
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-serie="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span v-for="(saleComponent, index) in row.components" :key="index">
|
||||
{{ saleComponent.component?.componentType?.type }}
|
||||
</span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-components="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span v-for="(saleComponent, index) in row.components" :key="index">
|
||||
{{ saleComponent.component?.name }}
|
||||
</span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-import="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span v-for="(saleComponent, index) in row.components" :key="index">
|
||||
{{ toCurrency(saleComponent.value, 'EUR', 3) }}
|
||||
</span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-total="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span v-for="(saleComponent, index) in row.components" :key="index">
|
||||
{{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
|
||||
</span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
|
@ -66,6 +66,23 @@ const filter = {
|
|||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
{
|
||||
relation: 'zone',
|
||||
scope: {
|
||||
fields: [
|
||||
'agencyModeFk',
|
||||
'bonus',
|
||||
'hour',
|
||||
'id',
|
||||
'isVolumetric',
|
||||
'itemMaxSize',
|
||||
'm3Max',
|
||||
'name',
|
||||
'price',
|
||||
'travelingDays',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -159,6 +159,24 @@ service:
|
|||
addService: Add service
|
||||
quantityInfo: To create services with negative amounts mark the service on the source ticket and press the pay button.
|
||||
createRefundSuccess: 'The following refund ticket have been created: { ticketId }'
|
||||
components:
|
||||
item: Item
|
||||
description: Description
|
||||
quantity: Quantity
|
||||
serie: Serie
|
||||
components: Components
|
||||
import: Import
|
||||
total: Total
|
||||
baseToCommission: Base to commission
|
||||
totalWithoutVat: Total without VAT
|
||||
zoneBreakdown: Zone breakdown
|
||||
price: Price
|
||||
bonus: Bonus
|
||||
zone: Zone
|
||||
volume: Volume
|
||||
theoricalCost: Theorical cost
|
||||
totalPrice: Total price
|
||||
packages: Packages
|
||||
tracking:
|
||||
state: State
|
||||
worker: Worker
|
||||
|
|
|
@ -164,5 +164,23 @@ ticketSale:
|
|||
shipped: F. Envío
|
||||
agency: Agencia
|
||||
address: Consignatario
|
||||
components:
|
||||
item: Artículo
|
||||
description: Descripción
|
||||
quantity: Cantidad
|
||||
serie: Serie
|
||||
components: Componentes
|
||||
import: Importe
|
||||
total: Total
|
||||
baseToCommission: Base comisionable
|
||||
totalWithoutVat: Total sin IVA
|
||||
zoneBreakdown: Desglose zona
|
||||
price: Precio
|
||||
bonus: Bonificación
|
||||
zone: Zona
|
||||
volume: Volúmen
|
||||
theoricalCost: Porte teórico
|
||||
totalPrice: Precio total
|
||||
packages: Bultos
|
||||
Search ticket: Buscar tickets
|
||||
You can search by ticket id or alias: Puedes buscar por id o alias del ticket
|
||||
|
|
|
@ -23,6 +23,7 @@ export default {
|
|||
'TicketTracking',
|
||||
'TicketVolume',
|
||||
'TicketNotes',
|
||||
'TicketComponents',
|
||||
],
|
||||
},
|
||||
children: [
|
||||
|
@ -179,6 +180,15 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Ticket/Card/TicketVolume.vue'),
|
||||
},
|
||||
{
|
||||
path: 'components',
|
||||
name: 'TicketComponents',
|
||||
meta: {
|
||||
title: 'components',
|
||||
icon: 'vn:components',
|
||||
},
|
||||
component: () => import('src/pages/Ticket/Card/TicketComponents.vue'),
|
||||
},
|
||||
{
|
||||
path: 'observation',
|
||||
name: 'TicketNotes',
|
||||
|
|
Loading…
Reference in New Issue