Merge pull request 'Ticket advance filter' (!533) from hyervoni/salix-front-mindshore:feature/TicketAdvanceFilter into dev
gitea/salix-front/pipeline/head This commit looks good Details

Reviewed-on: #533
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-07-15 09:54:06 +00:00
commit a0b6455b4c
6 changed files with 268 additions and 38 deletions

View File

@ -213,10 +213,20 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
delete store.userParams[param];
delete params[param];
if (store.filter?.where) {
const key = Object.keys(exprBuilder ? exprBuilder(param) : param);
if (key[0]) delete store.filter.where[key[0]];
if (Object.keys(store.filter.where).length === 0) {
delete store.filter.where;
let key;
if (exprBuilder) {
const result = exprBuilder(param);
if (result !== undefined && result !== null)
key = Object.keys(result);
} else {
if (typeof param === 'object' && param !== null)
key = Object.keys(param);
}
if (key && key[0]) {
delete store.filter.where[key[0]];
if (Object.keys(store.filter.where).length === 0) {
delete store.filter.where;
}
}
}
}

View File

@ -197,6 +197,12 @@ globals:
autonomous: Autonomous
suppliers: Suppliers
supplier: Supplier
expedition: Expedition
services: Service
components: Components
pictures: Pictures
packages: Packages
tracking: Tracking
labeler: Labeler
supplierCreate: New supplier
accounts: Accounts
@ -553,15 +559,8 @@ ticket:
observation: Notes
ticketAdvance: Advance tickets
futureTickets: Future tickets
expedition: Expedition
purchaseRequest: Purchase request
weeklyTickets: Weekly tickets
saleTracking: Sale tracking
services: Service
tracking: Tracking
components: Components
pictures: Pictures
packages: Packages
list:
nickname: Nickname
state: State

View File

@ -111,7 +111,7 @@ const columns = computed(() => [
const getBase = computed(() => {
let sum = 0;
for (let sale of ticketComponents.value) {
for (let sale of components.value) {
for (let saleComponent of sale.components) {
if (saleComponent.component.componentType.isBase) {
sum += sale.quantity * saleComponent.value;
@ -123,7 +123,7 @@ const getBase = computed(() => {
const getTotal = computed(() => {
let total = 0;
for (let sale of ticketComponents.value) {
for (let sale of components.value) {
for (let saleComponent of sale.components) {
total += sale.quantity * saleComponent.value;
}

View File

@ -9,6 +9,8 @@ import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.v
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnProgress from 'src/components/common/VnProgressModal.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import TicketAdvanceFilter from './TicketAdvanceFilter.vue';
import { dashIfEmpty, toCurrency } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm';
@ -42,9 +44,9 @@ const exprBuilder = (param, value) => {
case 'notMovableLines':
case 'futureZoneFk':
return { [param]: value };
case 'ipt':
case 'iptColFilter':
return { ipt: { like: `%${value}%` } };
case 'futureIpt':
case 'futureIptColFilter':
return { futureIpt: { like: `%${value}%` } };
}
};
@ -55,6 +57,7 @@ const arrayData = useArrayData('AdvanceTickets', {
url: 'Tickets/getTicketsAdvance',
userParams: userParams,
exprBuilder: exprBuilder,
limit: 0,
});
const { store } = arrayData;
const tickets = computed(() =>
@ -110,7 +113,7 @@ const ticketColumns = computed(() => [
sortable: true,
columnFilter: {
component: VnSelect,
filterParamKey: 'ipt',
filterParamKey: 'iptColFilter',
type: 'select',
filterValue: null,
event: getInputEvents,
@ -194,7 +197,7 @@ const ticketColumns = computed(() => [
sortable: true,
columnFilter: {
component: VnSelect,
filterParamKey: 'futureIpt',
filterParamKey: 'futureIptColFilter',
type: 'select',
filterValue: null,
event: getInputEvents,
@ -451,7 +454,8 @@ onMounted(async () => {
userParams.dateFuture = tomorrow;
userParams.dateToAdvance = today;
userParams.warehouseFk = user.value.warehouseFk;
await arrayData.addFilter({ userParams });
const filter = { limit: 0 };
await arrayData.addFilter({ filter, userParams });
});
</script>
@ -521,6 +525,11 @@ onMounted(async () => {
</QBtn>
</template>
</VnSubToolbar>
<RightMenu>
<template #right-panel>
<TicketAdvanceFilter data-key="AdvanceTickets" />
</template>
</RightMenu>
<QPage class="column items-center q-pa-md">
<QTable
:rows="tickets"

View File

@ -0,0 +1,173 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import axios from 'axios';
import { onMounted } from 'vue';
const { t } = useI18n();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
exprBuilder: {
type: Function,
default: null,
},
});
const warehousesOptions = ref([]);
const itemPackingTypes = ref([]);
const getItemPackingTypes = async () => {
try {
const filter = {
where: { isActive: true },
};
const { data } = await axios.get('ItemPackingTypes', {
params: { filter: JSON.stringify(filter) },
});
itemPackingTypes.value = data.map((ipt) => ({
description: t(ipt.description),
code: ipt.code,
}));
} catch (error) {
console.error(error);
}
};
onMounted(async () => await getItemPackingTypes());
</script>
<template>
<FetchData
url="Warehouses"
@on-fetch="(data) => (warehousesOptions = data)"
auto-load
/>
<VnFilterPanel
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="['search']"
:unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']"
>
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
<template #body="{ params, searchFn }">
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate
v-model="params.dateFuture"
:label="t('params.dateFuture')"
is-outlined
@update:model-value="searchFn()"
/>
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate
v-model="params.dateToAdvance"
:label="t('params.dateToAdvance')"
is-outlined
@update:model-value="searchFn()"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('params.futureIpt')"
v-model="params.futureIpt"
:options="itemPackingTypes"
option-value="code"
option-label="description"
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
>
</VnSelect>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('params.ipt')"
v-model="params.ipt"
:options="itemPackingTypes"
option-value="code"
option-label="description"
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
>
</VnSelect>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QCheckbox
:label="t('params.itemPackingTypes')"
v-model="params.itemPackingTypes"
toggle-indeterminate
:false-value="null"
@update:model-value="searchFn()"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
:label="t('params.warehouseFk')"
v-model="params.warehouseFk"
:options="warehousesOptions"
option-value="id"
option-label="name"
@update:model-value="searchFn()"
dense
outlined
rounded
>
</VnSelect>
</QItemSection>
</QItem>
</template>
</VnFilterPanel>
</template>
<i18n>
en:
iptInfo: IPT
params:
dateFuture: Origin date
dateToAdvance: Destination date
futureIpt: Origin IPT
ipt: Destination IPT
itemPackingTypes: 100% movable
warehouseFk: Warehouse
es:
Horizontal: Horizontal
Vertical: Vertical
iptInfo: Encajado
params:
dateFuture: fecha origen
dateToAdvance: Fecha destino
futureIpt: IPT Origen
ipt: IPT destino
itemPackingTypes: 100% movible
warehouseFk: Almacén
</i18n>

View File

@ -21,7 +21,10 @@ export default {
'TicketPurchaseRequest',
'TicketTracking',
'TicketNotes',
'TicketPicture',
'TicketVolume',
'TicketComponents',
'TicketPackage',
'TicketService',
'TicketSaleTracking',
'TicketBoxing',
@ -146,13 +149,40 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketLog.vue'),
},
{
path: 'boxing',
name: 'TicketBoxing',
path: 'observation',
name: 'TicketNotes',
meta: {
title: 'boxing',
title: 'notes',
icon: 'vn:notes',
},
component: () => import('src/pages/Ticket/Card/TicketNotes.vue'),
},
{
path: 'picture',
name: 'TicketPicture',
meta: {
title: 'pictures',
icon: 'vn:photo',
},
component: () => import('src/pages/Ticket/Card/TicketPicture.vue'),
},
{
path: 'volume',
name: 'TicketVolume',
meta: {
title: 'volume',
icon: 'vn:volume',
},
component: () => import('src/pages/Ticket/Card/TicketVolume.vue'),
},
{
path: 'expedition',
name: 'TicketExpedition',
meta: {
title: 'expedition',
icon: 'vn:package',
},
component: () => import('src/pages/Ticket/Card/TicketBoxing.vue'),
component: () => import('src/pages/Ticket/Card/TicketExpedition.vue'),
},
{
path: 'service',
@ -164,23 +194,33 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketService.vue'),
},
{
path: 'volume',
name: 'TicketVolume',
path: 'package',
name: 'TicketPackage',
meta: {
title: 'volume',
icon: 'vn:volume',
title: 'packages',
icon: 'vn:bin',
},
component: () => import('src/pages/Ticket/Card/TicketVolume.vue'),
component: () => import('src/pages/Ticket/Card/TicketPackage.vue'),
},
{
path: 'components',
name: 'TicketComponents',
meta: {
title: 'components',
icon: 'vn:components',
},
component: () => import('src/pages/Ticket/Card/TicketComponents.vue'),
},
{
path: 'observation',
name: 'TicketNotes',
path: 'sale-tracking',
name: 'TicketSaleTracking',
meta: {
title: 'notes',
icon: 'vn:notes',
title: 'saleTracking',
icon: 'assignment',
},
component: () => import('src/pages/Ticket/Card/TicketNotes.vue'),
component: () =>
import('src/pages/Ticket/Card/TicketSaleTracking.vue'),
},
{
path: 'dms',
@ -192,14 +232,13 @@ export default {
component: () => import('src/pages/Ticket/Card/TicketDms.vue'),
},
{
path: 'sale-tracking',
name: 'TicketSaleTracking',
path: 'boxing',
name: 'TicketBoxing',
meta: {
title: 'saleTracking',
icon: 'vn:buyrequest',
title: 'boxing',
icon: 'science',
},
component: () =>
import('src/pages/Ticket/Card/TicketSaleTracking.vue'),
component: () => import('src/pages/Ticket/Card/TicketBoxing.vue'),
},
{
path: 'sms',