0
0
Fork 0

Sale tracking

This commit is contained in:
William Buezas 2024-06-30 17:43:21 -03:00
parent 86a016e375
commit 768b619904
6 changed files with 588 additions and 0 deletions

View File

@ -448,6 +448,7 @@ ticket:
futureTickets: Future tickets
purchaseRequest: Purchase request
weeklyTickets: Weekly tickets
saleTracking: Sale tracking
list:
nickname: Nickname
state: State

View File

@ -447,6 +447,7 @@ ticket:
futureTickets: Tickets a futuro
purchaseRequest: Petición de compra
weeklyTickets: Tickets programados
saleTracking: Líneas preparadas
list:
nickname: Alias
state: Estado

View File

@ -0,0 +1,539 @@
<script setup>
import { ref, computed, nextTick, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import FetchData from 'components/FetchData.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import { dashIfEmpty } from 'src/filters';
import useNotify from 'src/composables/useNotify.js';
import { toDateTimeFormat } from 'src/filters/date';
import axios from 'axios';
const route = useRoute();
const { t } = useI18n();
const { notify } = useNotify();
const saleTrackingTableDialogRef = ref(null);
const itemShelvingSaleDialogRef = ref(null);
const saleTrackingFetchDataRef = ref(null);
const sales = ref([]);
const saleTrackings = ref([]);
const itemShelvignsSales = ref([]);
const shelvingsOptions = ref([]);
const parkingsOptions = ref([]);
const saleTrackingUrl = computed(() => `SaleTrackings/${route.params.id}/filter`);
watch(
() => route.params.id,
async () => nextTick(async () => await saleTrackingFetchDataRef.value.fetch())
);
const columns = computed(() => [
{
label: t('ticketSaleTracking.isChecked'),
name: 'isChecked',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.item'),
name: 'item',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.description'),
name: 'description',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.parking'),
name: 'parking',
field: 'parkingCode',
align: 'left',
sortable: true,
format: (value) => dashIfEmpty(value),
},
{
label: '',
name: 'actions',
align: 'left',
sortable: true,
},
]);
const logTableColumns = computed(() => [
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.original'),
name: 'original',
field: 'originalQuantity',
align: 'original',
sortable: true,
},
{
label: t('ticketSaleTracking.worker'),
name: 'worker',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.state'),
name: 'state',
field: 'state',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.created'),
name: 'created',
field: 'created',
align: 'left',
sortable: true,
format: (value) => toDateTimeFormat(value),
},
]);
const shelvingsTableColumns = computed(() => [
{
label: t('ticketSaleTracking.quantity'),
name: 'quantity',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.worker'),
name: 'worker',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.shelving'),
name: 'shelving',
align: 'original',
sortable: true,
},
{
label: t('ticketSaleTracking.parking'),
name: 'parking',
align: 'left',
sortable: true,
},
{
label: t('ticketSaleTracking.created'),
name: 'created',
field: 'created',
align: 'left',
sortable: true,
format: (value) => toDateTimeFormat(value),
},
]);
const getSaleTrackings = async (sale) => {
try {
const filter = {
where: { saleFk: sale.saleFk },
order: ['itemFk DESC'],
};
const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
params: { filter: JSON.stringify(filter) },
});
saleTrackings.value = data;
} catch (error) {
console.error(error);
}
};
const showLog = async (sale) => {
await getSaleTrackings(sale);
saleTrackingTableDialogRef.value.show();
};
const getItemShelvingSales = async (sale) => {
try {
const filter = {
where: { saleFk: sale.saleFk },
};
const { data } = await axios.get(`ItemShelvingSales/filter`, {
params: { filter: JSON.stringify(filter) },
});
itemShelvignsSales.value = data;
} catch (error) {
console.error(error);
}
};
const showShelving = async (sale) => {
await getItemShelvingSales(sale);
itemShelvingSaleDialogRef.value.show();
};
const updateQuantity = async (sale) => {
try {
const params = {
quantity: sale.quantity,
};
await axios.patch(`ItemShelvingSales/${sale.id}`, params);
} catch (error) {
console.error(error);
}
};
const updateParking = async (sale) => {
try {
const filter = {
fields: ['id'],
where: {
code: sale.shelvingFk,
},
};
const { data } = await axios.get(`Shelvings/findOne`, {
params: { filter: JSON.stringify(filter) },
});
const params = {
parkingFk: sale.parkingFk,
};
await axios.patch(`Shelvings/${data.id}`, params);
} catch (error) {
console.error(error);
}
};
const updateShelving = async (sale) => {
const params = {
shelvingFk: sale.shelvingFk,
};
const { data: patchResponseData } = await axios.patch(
`ItemShelvings/${sale.itemShelvingFk}`,
params
);
const filter = {
fields: ['parkingFk'],
where: {
code: patchResponseData.shelvingFk,
},
};
const { data: getResponseData } = await axios.get(`Shelvings/findOne`, { filter });
sale.parkingFk = getResponseData.parkingFk;
};
const saleTrackingNew = async (sale, stateCode, isChecked) => {
try {
const params = {
saleFk: sale.saleFk,
isChecked: isChecked,
quantity: sale.quantity,
stateCode: stateCode,
};
await axios.post(`SaleTrackings/new`, params);
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const saleTrackingDel = async (sale, stateCode) => {
try {
const params = {
saleFk: sale.saleFk,
stateCodes: [stateCode],
};
await axios.post(`SaleTrackings/delete`, params);
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const clickSaleGroupDetail = async (sale) => {
try {
if (!sale.saleGroupDetailFk) return;
await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
sale.hasSaleGroupDetail = false;
notify(t('globals.dataSaved'), 'positive');
} catch (error) {
console.error(error);
}
};
const clickPreviousSelected = (sale) => {
try {
if (!sale.isPreviousSelected) {
saleTrackingNew(sale, 'PREVIOUS_PREPARATION', false);
sale.isPreviousSelected = true;
} else {
saleTrackingDel(sale, 'PREVIOUS_PREPARATION');
sale.isPreviousSelected = false;
sale.isPrevious = false;
}
} catch (error) {
console.error(error);
}
};
const clickPrevious = (sale) => {
try {
if (!sale.isPrevious) {
saleTrackingNew(sale, 'PREVIOUS_PREPARATION', true);
sale.isPrevious = true;
sale.isPreviousSelected = true;
} else {
saleTrackingNew(sale, 'PREVIOUS_PREPARATION', false);
sale.isPrevious = false;
}
} catch (error) {
console.error(error);
}
};
const clickPrepared = (sale) => {
try {
if (!sale.isPrepared) {
saleTrackingNew(sale, 'PREPARED', true);
sale.isPrepared = true;
} else {
saleTrackingDel(sale, 'PREPARED');
sale.isPrepared = false;
}
} catch (error) {
console.error(error);
}
};
const clickControled = (sale) => {
try {
if (!sale.isControled) {
saleTrackingNew(sale, 'CHECKED', true);
sale.isControled = true;
} else {
saleTrackingDel(sale, 'CHECKED');
sale.isControled = false;
}
} catch (error) {
console.error(error);
}
};
</script>
<template>
<FetchData
ref="saleTrackingFetchDataRef"
:url="saleTrackingUrl"
:filter="{ order: ['concept ASC', 'quantity DESC'] }"
auto-load
@on-fetch="(data) => (sales = data)"
/>
<FetchData
url="Shelvings"
auto-load
@on-fetch="(data) => (shelvingsOptions = data)"
/>
<FetchData url="Parkings" auto-load @on-fetch="(data) => (parkingsOptions = data)" />
<QTable
:rows="sales"
:columns="columns"
row-key="id"
:pagination="{ rowsPerPage: 0 }"
class="full-width q-mt-md"
:no-data-label="t('globals.noResults')"
>
<template #body-cell-isChecked="{ row }">
<QTd @click.stop>
<QCheckbox
:model-value="!!row.hasSaleGroupDetail"
color="pink"
:toggle-indeterminate="false"
@update:model-value="clickSaleGroupDetail(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.saleGroupDetail') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPreviousSelected"
color="info"
:toggle-indeterminate="false"
@update:model-value="clickPreviousSelected(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.previousSelected') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPrevious"
color="cyan"
:toggle-indeterminate="false"
@update:model-value="clickPrevious(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.previous') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isPrepared"
color="warning"
:toggle-indeterminate="false"
@update:model-value="clickPrepared(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.prepared') }}
</QTooltip>
</QCheckbox>
<QCheckbox
:model-value="!!row.isControled"
color="yellow"
:toggle-indeterminate="false"
@update:model-value="clickControled(row)"
>
<QTooltip>
{{ t('ticketSaleTracking.checked') }}
</QTooltip>
</QCheckbox>
</QTd>
</template>
<template #body-cell-item="{ row }">
<QTd @click.stop>
<div>
<QBtn flat color="primary">
{{ row.itemFk }}
</QBtn>
<ItemDescriptorProxy :id="row.itemFk" />
</div>
</QTd>
</template>
<template #body-cell-description="{ row }">
<QTd class="col">
<div class="column">
<span>{{ row.concept }}</span>
<span v-if="row.subName" class="color-vn-label">
{{ row.subName }}
</span>
<FetchedTags :item="row" :max-length="6" />
</div>
</QTd>
</template>
<template #body-cell-actions="{ row }">
<QTd>
<QBtn
@click.stop="showLog(row)"
color="primary"
icon="history"
size="md"
flat
>
<QTooltip class="text-no-wrap">
{{ t('ticketSaleTracking.historyAction') }}
</QTooltip>
</QBtn>
<QBtn
@click.stop="showShelving(row)"
color="primary"
icon="vn:inventory"
size="md"
flat
>
<QTooltip class="text-no-wrap">
{{ t('ticketSaleTracking.shelvingAction') }}
</QTooltip>
</QBtn>
</QTd>
</template>
</QTable>
<QDialog
ref="saleTrackingTableDialogRef"
transition-show="scale"
transition-hide="scale"
>
<QTable
data-key="saleTrackingLog"
:rows="saleTrackings"
:columns="logTableColumns"
class="q-pa-sm"
>
<template #body-cell-worker="{ row }">
<QTd auto-width>
<QBtn flat dense color="primary">{{ row.name }}</QBtn>
<WorkerDescriptorProxy :id="row.workerFk" />
</QTd>
</template>
</QTable>
</QDialog>
<QDialog
ref="itemShelvingSaleDialogRef"
transition-show="scale"
transition-hide="scale"
>
<QTable
data-key="itemShelvingsSales"
:rows="itemShelvignsSales"
:columns="shelvingsTableColumns"
class="q-pa-sm"
>
<template #body-cell-quantity="{ row }">
<QTd auto-width>
<VnInput
v-model.number="row.quantity"
@keyup.enter="updateQuantity(row)"
@blur="updateQuantity(row)"
@focus="edit.oldQuantity = row.quantity"
/>
</QTd>
</template>
<template #body-cell-worker="{ row }">
<QTd auto-width>
<QBtn flat dense color="primary">{{ row.name }}</QBtn>
<WorkerDescriptorProxy :id="row.userFk" />
</QTd>
</template>
<template #body-cell-shelving="{ row }">
<QTd auto-width>
<VnSelect
:options="shelvingsOptions"
hide-selected
option-label="code"
option-value="code"
v-model="row.shelvingFk"
@update:model-value="updateShelving(row)"
style="max-width: 120px"
/>
</QTd>
</template>
<template #body-cell-parking="{ row }">
<QTd auto-width>
<VnSelect
:options="parkingsOptions"
hide-selected
option-label="code"
option-value="id"
v-model="row.parkingFk"
@update:model-value="updateParking(row)"
style="max-width: 120px"
/>
</QTd>
</template>
</QTable>
</QDialog>
</template>

View File

@ -136,3 +136,21 @@ weeklyTickets:
salesperson: Salesperson
search: Search weekly tickets
searchInfo: Search weekly tickets by id or client id
ticketSaleTracking:
isChecked: Is checked
item: Item
description: Description
quantity: Quantity
parking: Parking
historyAction: Log states
shelvingAction: Shelvings sale
original: Original
worker: Worker
state: State
created: Created
shelving: Shelving
saleGroupDetail: sale group detail
previousSelected: previous selected
previous: previous
prepared: prepared
checked: checked

View File

@ -138,3 +138,21 @@ ticketSale:
shipped: F. Envío
agency: Agencia
address: Consignatario
ticketSaleTracking:
isChecked: Comprobado
item: Artículo
description: Descripción
quantity: Cantidad
parking: Parking
historyAction: Historial estados
shelvingAction: Carros línea
original: Original
worker: Trabajador
state: Estado
created: Fecha creación
shelving: Matrícula
saleGroupDetail: detalle grupo líneas
previousSelected: previa seleccionado
previous: previa
prepared: preparado
checked: revisado

View File

@ -19,6 +19,7 @@ export default {
'TicketSale',
'TicketLog',
'TicketPurchaseRequest',
'TicketSaleTracking',
],
},
children: [
@ -147,6 +148,16 @@ export default {
},
component: () => import('src/pages/Ticket/Card/TicketSms.vue'),
},
{
path: 'sale-tracking',
name: 'TicketSaleTracking',
meta: {
title: 'saleTracking',
icon: 'vn:buyrequest',
},
component: () =>
import('src/pages/Ticket/Card/TicketSaleTracking.vue'),
},
],
},
],