feat: 6321_fix_ticketNegative
This commit is contained in:
parent
3b88f5e5cf
commit
c5f83d43f6
|
@ -0,0 +1,31 @@
|
|||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useQuasar } from 'quasar';
|
||||
export function showResultsAsTable() {
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
function openTable(dialog, results, tag, action, title) {
|
||||
quasar.notify({
|
||||
message: t('bulkEdit.completed'),
|
||||
color: 'positive',
|
||||
actions: [
|
||||
{
|
||||
label: t('bulkEdit.openTable'),
|
||||
color: 'white',
|
||||
handler: () => {
|
||||
quasar.dialog({
|
||||
component: dialog,
|
||||
componentProps: {
|
||||
title,
|
||||
results,
|
||||
tag,
|
||||
action,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
return { openTable };
|
||||
}
|
|
@ -11,7 +11,7 @@ const $props = defineProps({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<QPopupProxy>
|
||||
<QPopupProxy data-cy="customerDescriptorProxy">
|
||||
<CustomerDescriptor v-if="$props.id" :id="$props.id" :summary="CustomerSummary" />
|
||||
</QPopupProxy>
|
||||
</template>
|
||||
|
|
|
@ -22,7 +22,7 @@ const $props = defineProps({
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<QPopupProxy style="max-width: 10px">
|
||||
<QPopupProxy style="max-width: 10px" data-cy="itemDescriptorProxy">
|
||||
<ItemDescriptor
|
||||
v-if="$props.id"
|
||||
:id="$props.id"
|
||||
|
|
|
@ -6,9 +6,10 @@ import { toCurrency } from 'filters/index';
|
|||
import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import axios from 'axios';
|
||||
import notifyResults from 'src/utils/notifyResults';
|
||||
import { showResultsAsTable } from 'src/composables/showResultsTable';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
|
||||
const { openTable } = showResultsAsTable();
|
||||
import HandleSplitDialog from 'src/pages/Ticket/Negative/components/HandleSplitDialog.vue';
|
||||
const MATCH = 'match';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
@ -32,7 +33,10 @@ const $props = defineProps({
|
|||
const proposalSelected = ref([]);
|
||||
const ticketConfig = ref({});
|
||||
const proposalTableRef = ref(null);
|
||||
|
||||
const isLoading = ref(true);
|
||||
const filterTicketConfig = {
|
||||
fields: ['lackAlertPrice'],
|
||||
};
|
||||
const sale = computed(() => $props.sales[0]);
|
||||
const saleFk = computed(() => sale.value.saleFk);
|
||||
const filter = computed(() => ({
|
||||
|
@ -77,7 +81,7 @@ const columns = computed(() => [
|
|||
},
|
||||
|
||||
{
|
||||
align: 'left',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
label: t('proposal.longName'),
|
||||
name: 'longName',
|
||||
|
@ -85,7 +89,7 @@ const columns = computed(() => [
|
|||
columnClass: 'expand',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
label: t('item.list.color'),
|
||||
name: 'tag5',
|
||||
|
@ -93,7 +97,7 @@ const columns = computed(() => [
|
|||
columnClass: 'expand',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
label: t('item.list.stems'),
|
||||
name: 'tag6',
|
||||
|
@ -101,7 +105,7 @@ const columns = computed(() => [
|
|||
columnClass: 'expand',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
label: t('item.list.producer'),
|
||||
name: 'tag7',
|
||||
|
@ -197,9 +201,10 @@ const isSelectionAvailable = (itemProposal) => {
|
|||
|
||||
async function change({ itemFk: substitutionFk }) {
|
||||
try {
|
||||
const promises = $props.sales.map(({ saleFk, quantity }) => {
|
||||
const promises = $props.sales.map(({ saleFk, quantity, ticketFk }) => {
|
||||
const params = {
|
||||
saleFk,
|
||||
ticketFk,
|
||||
substitutionFk,
|
||||
quantity,
|
||||
};
|
||||
|
@ -207,10 +212,9 @@ async function change({ itemFk: substitutionFk }) {
|
|||
});
|
||||
const results = await Promise.allSettled(promises);
|
||||
|
||||
notifyResults(results, 'saleFk');
|
||||
openTable(HandleSplitDialog, results, 'ticketFk', 'changeItem');
|
||||
emit('itemReplaced', {
|
||||
type: 'refresh',
|
||||
quantity: quantity.value,
|
||||
itemProposal: proposalSelected.value[0],
|
||||
});
|
||||
proposalSelected.value = [];
|
||||
|
@ -221,18 +225,20 @@ async function change({ itemFk: substitutionFk }) {
|
|||
|
||||
async function handleTicketConfig(data) {
|
||||
ticketConfig.value = data[0];
|
||||
isLoading.value = false;
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="TicketConfigs"
|
||||
:filter="{ fields: ['lackAlertPrice'] }"
|
||||
@on-fetch="handleTicketConfig"
|
||||
:filter="filterTicketConfig"
|
||||
auto-load
|
||||
/>
|
||||
@on-fetch="handleTicketConfig"
|
||||
></FetchData>
|
||||
<QSpinner v-if="isLoading" color="primary" size="md"></QSpinner>
|
||||
|
||||
<VnTable
|
||||
v-if="ticketConfig"
|
||||
v-else
|
||||
auto-load
|
||||
data-cy="proposalTable"
|
||||
ref="proposalTableRef"
|
||||
|
@ -242,7 +248,7 @@ async function handleTicketConfig(data) {
|
|||
:columns="columns"
|
||||
class="full-width q-mt-md"
|
||||
row-key="id"
|
||||
:row-click="change"
|
||||
redirect="false"
|
||||
:is-editable="false"
|
||||
:right-search="false"
|
||||
:without-header="true"
|
||||
|
@ -260,10 +266,10 @@ async function handleTicketConfig(data) {
|
|||
<QTooltip> {{ statusConditionalValue(row) }}% </QTooltip>
|
||||
</div>
|
||||
<div style="flex: 2 0 100%; align-content: center">
|
||||
<div>
|
||||
<span class="link">{{ row.longName }}</span>
|
||||
<ItemDescriptorProxy :id="row.id" />
|
||||
</div>
|
||||
<span class="link" @click.stop>
|
||||
{{ row.longName }}
|
||||
<ItemDescriptorProxy :id="row.itemFk" />
|
||||
</span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
|
|
|
@ -19,16 +19,18 @@ const $props = defineProps({
|
|||
default: () => [],
|
||||
},
|
||||
});
|
||||
const { dialogRef } = useDialogPluginComponent();
|
||||
const emit = defineEmits([
|
||||
'onDialogClosed',
|
||||
'itemReplaced',
|
||||
...useDialogPluginComponent.emits,
|
||||
]);
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
||||
useDialogPluginComponent();
|
||||
const emit = defineEmits(['onDialogClosed', ...useDialogPluginComponent.emits]);
|
||||
defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
|
||||
</script>
|
||||
<template>
|
||||
<QDialog ref="dialogRef" transition-show="scale" transition-hide="scale">
|
||||
<QDialog
|
||||
ref="dialogRef"
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
@hide="onDialogHide"
|
||||
>
|
||||
<QCard class="dialog-width">
|
||||
<QCardSection class="row items-center q-pb-none">
|
||||
<span class="text-h6 text-grey">{{ $t('Item proposal') }}</span>
|
||||
|
@ -39,8 +41,8 @@ defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.h
|
|||
<ItemProposal
|
||||
v-bind="$props"
|
||||
@item-replaced="
|
||||
(data) => {
|
||||
emit('itemReplaced', data);
|
||||
() => {
|
||||
emit('onDialogClosed', true);
|
||||
dialogRef.hide();
|
||||
}
|
||||
"
|
||||
|
|
|
@ -44,6 +44,7 @@ function ticketFilter(ticket) {
|
|||
@on-fetch="(data) => ([problems] = data)"
|
||||
/>
|
||||
<CardDescriptor
|
||||
:id="entityId"
|
||||
:url="`Tickets/${entityId}`"
|
||||
:filter="filter"
|
||||
data-key="Ticket"
|
||||
|
|
|
@ -10,7 +10,7 @@ const $props = defineProps({
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<QPopupProxy>
|
||||
<QPopupProxy data-cy="ticketDescriptorProxy">
|
||||
<TicketDescriptor v-if="$props.id" :id="$props.id" :summary="TicketSummary" />
|
||||
</QPopupProxy>
|
||||
</template>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { ref } from 'vue';
|
||||
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import split from './components/split';
|
||||
import { splitTicket } from './components/split';
|
||||
const emit = defineEmits(['ticketTransfered']);
|
||||
|
||||
const $props = defineProps({
|
||||
|
@ -12,6 +12,8 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const { split } = splitTicket();
|
||||
|
||||
const splitDate = ref(Date.vnNew());
|
||||
|
||||
const splitSelectedRows = async () => {
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<script setup>
|
||||
import TicketProblems from 'src/components/TicketProblems.vue';
|
||||
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||
import { dashIfEmpty, toDate, toCurrency } from 'src/filters';
|
||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
sales: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
ticket: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const sales = ref(props?.sales);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QTable v-if="sales" :rows="sales" style="text-align: center">
|
||||
<template #body-cell="{ value }">
|
||||
<QTd>{{ value }}</QTd>
|
||||
</template>
|
||||
<template #header="props">
|
||||
<QTr class="tr-header" :props="props">
|
||||
<QTh auto-width></QTh>
|
||||
<QTh auto-width>{{ $t('globals.item') }}</QTh>
|
||||
<QTh auto-width>{{ $t('globals.visible') }}</QTh>
|
||||
<QTh auto-width>{{ $t('ticket.summary.available') }}</QTh>
|
||||
<QTh auto-width>{{ $t('globals.quantity') }}</QTh>
|
||||
<QTh auto-width>{{ $t('globals.description') }}</QTh>
|
||||
<QTh auto-width>{{ $t('globals.price') }}</QTh>
|
||||
<QTh auto-width>{{ $t('ticket.summary.discount') }}</QTh>
|
||||
<QTh auto-width>{{ $t('globals.amount') }}</QTh>
|
||||
<QTh auto-width>{{ $t('ticket.summary.packing') }}</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<QTr :props="props">
|
||||
<QTd class="q-gutter-x-xs">
|
||||
<TicketProblems :row="props.row" />
|
||||
</QTd>
|
||||
<QTd>
|
||||
<QBtn class="link" flat>
|
||||
{{ props.row.itemFk }}
|
||||
<ItemDescriptorProxy
|
||||
:id="props.row.itemFk"
|
||||
:sale-fk="props.row.id"
|
||||
:warehouse-fk="$props.ticket.warehouseFk"
|
||||
/>
|
||||
</QBtn>
|
||||
</QTd>
|
||||
<QTd>
|
||||
<QChip
|
||||
v-if="props.row.visible < 0"
|
||||
dense
|
||||
rounded
|
||||
:color="'negative'"
|
||||
text-color="white"
|
||||
>
|
||||
{{ props.row.visible }}
|
||||
</QChip>
|
||||
<span v-else>
|
||||
{{ props.row.visible }}
|
||||
</span>
|
||||
</QTd>
|
||||
<QTd>
|
||||
<QChip
|
||||
v-if="props.row.available < 0"
|
||||
dense
|
||||
rounded
|
||||
:color="'negative'"
|
||||
text-color="white"
|
||||
>
|
||||
{{ props.row.available }}
|
||||
</QChip>
|
||||
<span v-else>
|
||||
{{ props.row.available }}
|
||||
</span>
|
||||
</QTd>
|
||||
<QTd>{{ props.row.quantity }}</QTd>
|
||||
<QTd class="description-cell">
|
||||
<div class="row full-width justify-between">
|
||||
{{ props.row.concept }}
|
||||
<div v-if="props.row.item.subName" class="subName">
|
||||
{{ props.row.item.subName.toUpperCase() }}
|
||||
</div>
|
||||
</div>
|
||||
<FetchedTags
|
||||
class="fetched-tags"
|
||||
:item="props.row.item"
|
||||
></FetchedTags>
|
||||
</QTd>
|
||||
<QTd>{{ props.row.price }} €</QTd>
|
||||
<QTd>{{ props.row.discount }} %</QTd>
|
||||
<QTd
|
||||
>{{
|
||||
toCurrency(
|
||||
props.row.quantity *
|
||||
props.row.price *
|
||||
((100 - props.row.discount) / 100),
|
||||
)
|
||||
}}
|
||||
</QTd>
|
||||
<QTd>{{ dashIfEmpty(props.row.item.itemPackingTypeFk) }}</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
|
@ -0,0 +1,42 @@
|
|||
<script setup>
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import { dashIfEmpty, toDate, toCurrency } from 'src/filters';
|
||||
import { ref } from 'vue';
|
||||
import TicketSaleTable from './TicketSaleTable.vue';
|
||||
|
||||
const props = defineProps({
|
||||
sales: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
ticket: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const sales = ref(props?.sales);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QDialog ref="dialogRef" full-width data-cy="ticketSaleTableDialog">
|
||||
<FetchData
|
||||
v-if="!sales"
|
||||
:url="`Tickets/${$props.ticket}/getSales`"
|
||||
@on-fetch="(data) => (sales = data)"
|
||||
auto-load
|
||||
></FetchData>
|
||||
<QCard class="q-pa-sm">
|
||||
<QCardSection class="row items-center q-pb-none">
|
||||
<span class="text-h6 text-grey">{{
|
||||
$t('ticket.summary.saleLines')
|
||||
}}</span>
|
||||
<QSpace />
|
||||
<QBtn icon="close" flat round dense v-close-popup />
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<TicketSaleTable v-if="sales" :ticket="$props.ticket" :sales="sales" />
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
</template>
|
|
@ -1,22 +1,24 @@
|
|||
import axios from 'axios';
|
||||
import notifyResults from 'src/utils/notifyResults';
|
||||
import { showResultsAsTable } from 'src/composables/showResultsTable';
|
||||
import HandleSplitDialog from 'src/pages/Ticket/Negative/components/HandleSplitDialog.vue';
|
||||
export function splitTicket() {
|
||||
const { openTable } = showResultsAsTable();
|
||||
|
||||
export default async function (data, date) {
|
||||
const reducedData = data.reduce((acc, item) => {
|
||||
const existing = acc.find(({ ticketFk }) => ticketFk === item.id);
|
||||
if (existing) {
|
||||
existing.sales.push(item.saleFk);
|
||||
} else {
|
||||
acc.push({ ticketFk: item.id, sales: [item.saleFk], date });
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
async function split(data, date) {
|
||||
const reducedData = data.reduce((acc, item) => {
|
||||
const existing = acc.find(({ ticketFk }) => ticketFk === item.ticketFk);
|
||||
if (existing) {
|
||||
existing.sales.push(item.saleFk);
|
||||
} else {
|
||||
acc.push({ ticketFk: item.ticketFk, sales: [item.saleFk], landed: date });
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const promises = reducedData.map((params) => axios.post(`Tickets/split`, params));
|
||||
const promises = reducedData.map((params) => axios.post(`Tickets/split`, params));
|
||||
|
||||
const results = await Promise.allSettled(promises);
|
||||
|
||||
notifyResults(results, 'ticketFk');
|
||||
|
||||
return results;
|
||||
const result = await Promise.allSettled(promises);
|
||||
openTable(HandleSplitDialog, result, 'ticket', 'split');
|
||||
}
|
||||
return { split };
|
||||
}
|
||||
|
|
|
@ -68,7 +68,8 @@ const showItemProposal = () => {
|
|||
sales: selectedRows.value,
|
||||
},
|
||||
})
|
||||
.onOk(itemProposalEvt);
|
||||
.onOk(reload)
|
||||
.onCancel(reload);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -146,7 +147,12 @@ const showItemProposal = () => {
|
|||
<template v-slot="{ popup }">
|
||||
<ChangeItemDialog
|
||||
ref="changeItemDialogRef"
|
||||
@update-item="popup.hide()"
|
||||
@update-item="
|
||||
() => {
|
||||
popup.hide();
|
||||
reload();
|
||||
}
|
||||
"
|
||||
:selected-rows="selectedRows"
|
||||
/></template>
|
||||
</VnPopupProxy>
|
||||
|
@ -160,7 +166,12 @@ const showItemProposal = () => {
|
|||
<template v-slot="{ popup }">
|
||||
<ChangeStateDialog
|
||||
ref="changeStateDialogRef"
|
||||
@update-state="popup.hide()"
|
||||
@update-state="
|
||||
() => {
|
||||
popup.hide();
|
||||
reload();
|
||||
}
|
||||
"
|
||||
:selected-rows="selectedRows"
|
||||
/></template>
|
||||
</VnPopupProxy>
|
||||
|
@ -175,7 +186,12 @@ const showItemProposal = () => {
|
|||
<template v-slot="{ popup }">
|
||||
<ChangeQuantityDialog
|
||||
ref="changeQuantityDialogRef"
|
||||
@update-quantity="popup.hide()"
|
||||
@update-quantity="
|
||||
() => {
|
||||
popup.hide();
|
||||
reload();
|
||||
}
|
||||
"
|
||||
:selected-rows="selectedRows"
|
||||
/></template>
|
||||
</VnPopupProxy> </QBtnGroup
|
||||
|
|
|
@ -94,7 +94,7 @@ const setUserParams = (params) => {
|
|||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
v-model="params.id"
|
||||
v-model="params.itemFk"
|
||||
:label="t('negative.id')"
|
||||
dense
|
||||
is-outlined
|
||||
|
@ -102,25 +102,6 @@ const setUserParams = (params) => {
|
|||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
v-model="params.producer"
|
||||
:label="t('negative.producer')"
|
||||
dense
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
v-model="params.origen"
|
||||
:label="t('negative.origen')"
|
||||
dense
|
||||
is-outlined
|
||||
/>
|
||||
</QItemSection> </QItem
|
||||
><QItem>
|
||||
<QItemSection v-if="categoriesOptions">
|
||||
<VnSelect
|
||||
:label="t('negative.categoryFk')"
|
||||
|
|
|
@ -65,15 +65,19 @@ const columns = computed(() => [
|
|||
columnFilter: {
|
||||
component: 'input',
|
||||
type: 'number',
|
||||
columnClass: 'shrink',
|
||||
inWhere: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'longName',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
label: t('negative.longName'),
|
||||
field: ({ longName }) => longName,
|
||||
|
||||
columnFilter: {
|
||||
component: 'input',
|
||||
inWhere: false,
|
||||
useLike: true,
|
||||
},
|
||||
sortable: true,
|
||||
headerStyle: 'width: 350px',
|
||||
cardVisible: true,
|
||||
|
@ -94,6 +98,11 @@ const columns = computed(() => [
|
|||
field: ({ inkFk }) => inkFk,
|
||||
sortable: true,
|
||||
cardVisible: true,
|
||||
columnFilter: {
|
||||
component: 'input',
|
||||
columnClass: 'shrink',
|
||||
inWhere: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'size',
|
||||
|
@ -155,7 +164,6 @@ const setUserParams = (params) => {
|
|||
<TicketLackFilter data-key="NegativeList" @set-user-params="setUserParams" />
|
||||
</template>
|
||||
</RightMenu>
|
||||
{{ filterRef }}
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="NegativeList"
|
||||
|
|
|
@ -5,7 +5,7 @@ import { computed, ref, watch } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import axios from 'axios';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import { toDate, toHour } from 'src/filters';
|
||||
import { toDate } from 'src/filters';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import ZoneDescriptorProxy from 'pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
@ -22,14 +22,6 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => $props.filter,
|
||||
(v) => {
|
||||
filterLack.value.where = v;
|
||||
tableRef.value.reload(filterLack);
|
||||
},
|
||||
);
|
||||
|
||||
const filterLack = ref({
|
||||
include: [
|
||||
{
|
||||
|
@ -90,6 +82,7 @@ const columns = computed(() => [
|
|||
},
|
||||
{
|
||||
name: 'alertLevelCode',
|
||||
field: 'alertLevelCode',
|
||||
label: t('negative.detail.state'),
|
||||
columnFilter: {
|
||||
name: 'alertLevelCode',
|
||||
|
@ -108,14 +101,14 @@ const columns = computed(() => [
|
|||
name: 'zoneName',
|
||||
label: t('negative.detail.zoneName'),
|
||||
field: 'zoneName',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'nickname',
|
||||
label: t('negative.detail.nickname'),
|
||||
field: 'nickname',
|
||||
align: 'center',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
|
@ -139,27 +132,22 @@ const getInputEvents = ({ col, ...rows }) => ({
|
|||
'keyup.enter': () => saveChange(col.name, rows),
|
||||
});
|
||||
const saveChange = async (field, { row }) => {
|
||||
try {
|
||||
switch (field) {
|
||||
case 'alertLevelCode':
|
||||
await axios.post(`Tickets/state`, {
|
||||
ticketFk: row.ticketFk,
|
||||
code: row[field],
|
||||
});
|
||||
break;
|
||||
switch (field) {
|
||||
case 'alertLevelCode':
|
||||
await axios.post(`Tickets/state`, {
|
||||
ticketFk: row.ticketFk,
|
||||
code: row[field],
|
||||
});
|
||||
break;
|
||||
|
||||
case 'quantity':
|
||||
await axios.post(`Sales/${row.saleFk}/updateQuantity`, {
|
||||
quantity: +row.quantity,
|
||||
});
|
||||
break;
|
||||
}
|
||||
notify('globals.dataSaved', 'positive');
|
||||
fetchItemLack.value.fetch();
|
||||
} catch (err) {
|
||||
console.error('Error saving changes', err);
|
||||
f;
|
||||
case 'quantity':
|
||||
await axios.post(`Sales/${row.saleFk}/updateQuantity`, {
|
||||
quantity: +row.quantity,
|
||||
});
|
||||
break;
|
||||
}
|
||||
notify('globals.dataSaved', 'positive');
|
||||
fetchItemLack.value.fetch();
|
||||
};
|
||||
|
||||
function onBuysFetched(data) {
|
||||
|
@ -171,7 +159,7 @@ function onBuysFetched(data) {
|
|||
<FetchData
|
||||
ref="fetchItemLack"
|
||||
:url="`Tickets/itemLack`"
|
||||
:params="{ id: entityId }"
|
||||
:params="{ itemFk: entityId }"
|
||||
@on-fetch="(data) => (itemLack = data[0])"
|
||||
auto-load
|
||||
/>
|
||||
|
@ -238,65 +226,59 @@ function onBuysFetched(data) {
|
|||
</template>
|
||||
|
||||
<template #column-status="{ row }">
|
||||
<QTd style="min-width: 150px">
|
||||
<div class="icon-container">
|
||||
<QIcon
|
||||
v-if="row.isBasket"
|
||||
name="vn:basket"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.isBasket') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.hasToIgnore"
|
||||
name="star"
|
||||
color="primary"
|
||||
class="cursor-pointer fill-icon"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.hasToIgnore') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.hasObservation"
|
||||
name="change_circle"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{
|
||||
t('negative.detail.hasObservation')
|
||||
}}</QTooltip> </QIcon
|
||||
><QIcon
|
||||
v-if="row.isRookie"
|
||||
name="vn:Person"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.isRookie') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.peticionCompra"
|
||||
name="vn:buyrequest"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.peticionCompra') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.turno"
|
||||
name="vn:calendar"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.turno') }}</QTooltip>
|
||||
</QIcon>
|
||||
</div></QTd
|
||||
<QIcon
|
||||
v-if="row.isBasket"
|
||||
name="vn:basket"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.isBasket') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.hasToIgnore"
|
||||
name="star"
|
||||
color="primary"
|
||||
class="cursor-pointer fill-icon"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.hasToIgnore') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.hasObservation"
|
||||
name="change_circle"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
size="xs"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.hasObservation') }}</QTooltip> </QIcon
|
||||
><QIcon
|
||||
v-if="row.isRookie"
|
||||
name="vn:Person"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.isRookie') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.peticionCompra"
|
||||
name="vn:buyrequest"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.peticionCompra') }}</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon
|
||||
v-if="row.turno"
|
||||
name="vn:calendar"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<QTooltip>{{ t('negative.detail.turno') }}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
<template #column-nickname="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
|
@ -305,9 +287,9 @@ function onBuysFetched(data) {
|
|||
</span>
|
||||
</template>
|
||||
<template #column-ticketFk="{ row }">
|
||||
<span class="q-pa-sm link">
|
||||
{{ row.id }}
|
||||
<TicketDescriptorProxy :id="row.id" />
|
||||
<span class="link" @click.stop>
|
||||
{{ row.ticketFk }}
|
||||
<TicketDescriptorProxy :id="row.ticketFk" />
|
||||
</span>
|
||||
</template>
|
||||
<template #column-alertLevelCode="props">
|
||||
|
@ -335,15 +317,6 @@ function onBuysFetched(data) {
|
|||
</VnTable>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.icon-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 0.2fr);
|
||||
row-gap: 5px; /* Ajusta el espacio entre los iconos según sea necesario */
|
||||
}
|
||||
.icon-container > * {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 1s ease;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import notifyResults from 'src/utils/notifyResults';
|
||||
import { showResultsAsTable } from 'src/composables/showResultsTable';
|
||||
import HandleSplitDialog from './HandleSplitDialog.vue';
|
||||
const { openTable } = showResultsAsTable();
|
||||
const emit = defineEmits(['update-item']);
|
||||
|
||||
const showChangeItemDialog = ref(false);
|
||||
|
@ -17,15 +20,17 @@ const $props = defineProps({
|
|||
const updateItem = async () => {
|
||||
try {
|
||||
showChangeItemDialog.value = true;
|
||||
const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
|
||||
const rowsToUpdate = $props.selectedRows.map(({ ticketFk, saleFk, quantity }) =>
|
||||
axios.post(`Sales/replaceItem`, {
|
||||
ticketFk,
|
||||
saleFk,
|
||||
substitutionFk: newItem.value,
|
||||
quantity,
|
||||
}),
|
||||
);
|
||||
const result = await Promise.allSettled(rowsToUpdate);
|
||||
notifyResults(result, 'saleFk');
|
||||
|
||||
openTable(HandleSplitDialog, result, 'ticketFk', 'changeItem');
|
||||
emit('update-item', newItem.value);
|
||||
} catch (err) {
|
||||
console.error('Error updating item:', err);
|
||||
|
@ -37,9 +42,9 @@ const updateItem = async () => {
|
|||
<template>
|
||||
<QCard class="q-pa-sm">
|
||||
<QCardSection class="row items-center justify-center column items-stretch">
|
||||
{{ showChangeItemDialog }}
|
||||
<span>{{ $t('negative.detail.modal.changeItem.title') }}</span>
|
||||
<VnSelect
|
||||
:label="$t('negative.detail.modal.changeItem.placeholder')"
|
||||
url="Items/WithName"
|
||||
:fields="['id', 'name']"
|
||||
:sort-by="['id DESC']"
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import notifyResults from 'src/utils/notifyResults';
|
||||
|
||||
import { showResultsAsTable } from 'src/composables/showResultsTable';
|
||||
import HandleSplitDialog from './HandleSplitDialog.vue';
|
||||
const { openTable } = showResultsAsTable();
|
||||
const showChangeQuantityDialog = ref(false);
|
||||
const newQuantity = ref(null);
|
||||
const $props = defineProps({
|
||||
|
@ -14,22 +15,17 @@ const $props = defineProps({
|
|||
});
|
||||
const emit = defineEmits(['update-quantity']);
|
||||
const updateQuantity = async () => {
|
||||
try {
|
||||
showChangeQuantityDialog.value = true;
|
||||
const rowsToUpdate = $props.selectedRows.map(({ saleFk }) =>
|
||||
axios.post(`Sales/${saleFk}/updateQuantity`, {
|
||||
saleFk,
|
||||
quantity: +newQuantity.value,
|
||||
}),
|
||||
);
|
||||
showChangeQuantityDialog.value = true;
|
||||
const rowsToUpdate = $props.selectedRows.map(({ saleFk }) =>
|
||||
axios.post(`Sales/${saleFk}/updateQuantity`, {
|
||||
saleFk,
|
||||
quantity: +newQuantity.value,
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await Promise.allSettled(rowsToUpdate);
|
||||
notifyResults(result, 'saleFk');
|
||||
|
||||
emit('update-quantity', newQuantity.value);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
const result = await Promise.allSettled(rowsToUpdate);
|
||||
openTable(HandleSplitDialog, result, 'ticketFk', 'changeQuantity');
|
||||
emit('update-quantity', newQuantity.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ import { ref } from 'vue';
|
|||
import axios from 'axios';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import notifyResults from 'src/utils/notifyResults';
|
||||
import { showResultsAsTable } from 'src/composables/showResultsTable';
|
||||
import HandleSplitDialog from './HandleSplitDialog.vue';
|
||||
const { openTable } = showResultsAsTable();
|
||||
|
||||
const emit = defineEmits(['update-state']);
|
||||
const editableStates = ref([]);
|
||||
|
@ -16,21 +18,18 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
const updateState = async () => {
|
||||
try {
|
||||
showChangeStateDialog.value = true;
|
||||
const rowsToUpdate = $props.selectedRows.map(({ id }) =>
|
||||
const rowsToUpdate = $props.selectedRows.map(({ ticketFk }) =>
|
||||
axios.post(`Tickets/state`, {
|
||||
ticketFk: id,
|
||||
ticketFk,
|
||||
code: newState.value,
|
||||
}),
|
||||
);
|
||||
const result = await Promise.allSettled(rowsToUpdate);
|
||||
notifyResults(result, 'ticketFk');
|
||||
|
||||
const result = await Promise.allSettled(rowsToUpdate);
|
||||
|
||||
openTable(HandleSplitDialog, result, 'ticketFk', 'changeState');
|
||||
emit('update-state', newState.value);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -47,8 +46,6 @@ const updateState = async () => {
|
|||
:label="$t('negative.detail.modal.changeState.placeholder')"
|
||||
v-model="newState"
|
||||
:options="editableStates"
|
||||
option-label="name"
|
||||
option-value="code"
|
||||
/>
|
||||
</QCardSection>
|
||||
<QCardActions align="right">
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||
import TicketSaleTable from 'src/pages/Ticket/Card/components/TicketSaleTable.vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import TicketSaleTableDialog from '../../Card/components/TicketSaleTableDialog.vue';
|
||||
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
const $props = defineProps({
|
||||
results: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'ticketFk',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'bulkEdit.edit',
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const results = ref($props.results);
|
||||
const states = ref([]);
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
name: 'status',
|
||||
label: t('negative.split.status'),
|
||||
field: ({ status }) => status,
|
||||
sortable: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
label: t('negative.split.ticket'),
|
||||
sortable: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'statusText',
|
||||
label: t('negative.split.message'),
|
||||
sortable: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
label: '',
|
||||
sortable: false,
|
||||
align: 'right',
|
||||
},
|
||||
]);
|
||||
function getState(value) {
|
||||
return states.value.find((state) => state.id === value)?.name;
|
||||
}
|
||||
function getTicketRejected(row) {
|
||||
return JSON.parse(row.reason.config.data)?.ticketFk;
|
||||
}
|
||||
function getTicketFulFilled(row) {
|
||||
return JSON.parse(row.value.config.data).ticketFk;
|
||||
}
|
||||
function getIcon(value) {
|
||||
const icons = {
|
||||
fulfilled: {
|
||||
name: 'check_circle',
|
||||
color: 'secondary',
|
||||
},
|
||||
noSplit: {
|
||||
name: 'warning',
|
||||
color: 'primary',
|
||||
},
|
||||
rejected: {
|
||||
name: 'close',
|
||||
color: 'negative',
|
||||
},
|
||||
};
|
||||
return icons[value];
|
||||
}
|
||||
|
||||
function openLinesDialog(row) {
|
||||
const ticket =
|
||||
row.status === 'fulfilled'
|
||||
? (row.value.data[$props.tag] ?? getTicketFulFilled(row))
|
||||
: getTicketRejected(row);
|
||||
quasar.dialog({
|
||||
component: TicketSaleTableDialog,
|
||||
componentProps: {
|
||||
ticket: ticket,
|
||||
sales: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QDialog ref="dialogRef" @hide="onDialogHide" data-cy="handleSplitDialog" persistent>
|
||||
<FetchData
|
||||
v-if="$props.action === 'changeState'"
|
||||
url="States"
|
||||
@on-fetch="(data) => (states = data)"
|
||||
auto-load
|
||||
/>
|
||||
<QCard class="q-pa-sm" style="width: 60vw; max-width: 80vw">
|
||||
<QCardSection class="row items-center q-pb-none">
|
||||
<QAvatar
|
||||
:icon="icon"
|
||||
color="primary"
|
||||
text-color="white"
|
||||
size="xl"
|
||||
v-if="icon"
|
||||
/>
|
||||
<span class="text-h6 text-grey"
|
||||
>{{ t($props.title) }} ({{ $props.action }})
|
||||
</span>
|
||||
<QSpace />
|
||||
<QBtn icon="close" flat round dense v-close-popup />
|
||||
</QCardSection>
|
||||
<QCardSection class="row items-center justify-center column items-stretch">
|
||||
<QTable
|
||||
:rows="results"
|
||||
:columns="columns"
|
||||
row-key="newTicket"
|
||||
:no-data-label="t('globals.noResults')"
|
||||
flat
|
||||
dense
|
||||
hide-bottom
|
||||
auto-load
|
||||
>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ t(col.label) }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body-cell-status="{ value }">
|
||||
<QTd align="center">
|
||||
<QIcon
|
||||
:name="`${getIcon(value)?.name}`"
|
||||
size="xs"
|
||||
class="cursor-pointer"
|
||||
:color="getIcon(value)?.color"
|
||||
>
|
||||
</QIcon
|
||||
></QTd>
|
||||
</template>
|
||||
<template #body-cell-value="{ row }">
|
||||
<QTd align="center">
|
||||
<div class="link" @click.stop>
|
||||
<div v-if="row.status === 'fulfilled'">
|
||||
<span v-if="$props.action !== 'changeItem'">
|
||||
{{ row.value.data[$props.tag] }}
|
||||
<TicketDescriptorProxy
|
||||
:id="row.value.data[$props.tag]"
|
||||
>
|
||||
</TicketDescriptorProxy>
|
||||
</span>
|
||||
<span v-else
|
||||
>{{ getTicketFulFilled(row)
|
||||
}}<TicketDescriptorProxy
|
||||
:id="getTicketFulFilled(row)"
|
||||
>
|
||||
</TicketDescriptorProxy>
|
||||
</span>
|
||||
</div>
|
||||
<span v-else>
|
||||
{{ getTicketRejected(row)
|
||||
}}<TicketDescriptorProxy :id="getTicketRejected(row)">
|
||||
</TicketDescriptorProxy
|
||||
></span>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-statusText="{ row }">
|
||||
<QTd align="center">
|
||||
<div v-if="row.status === 'fulfilled'">
|
||||
<div v-if="$props.action === 'changeState'">
|
||||
{{ getState(row.value.data.stateFk) }}
|
||||
</div>
|
||||
<div v-if="$props.action === 'split'">
|
||||
<span>
|
||||
{{ row.value.data.status }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="$props.action === 'changeItem'">
|
||||
<span class="link" @click.stop>
|
||||
{{ value }}
|
||||
<ItemDescriptorProxy :id="value">
|
||||
</ItemDescriptorProxy>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="$props.action === 'changeQuantity'">
|
||||
{{ row.value.data.quantity }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>{{ row.reason.response.data.error.message }}</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-actions="props">
|
||||
<QTd align="center">
|
||||
<div v-if="['changeItem'].includes($props.action)">
|
||||
<QIcon
|
||||
name="list"
|
||||
size="xs"
|
||||
color="primary"
|
||||
class="cursor-pointer"
|
||||
@click="openLinesDialog(props.row)"
|
||||
>
|
||||
<QTooltip>{{ t('ticketList.toLines') }} </QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
</template>
|
|
@ -286,7 +286,7 @@ negative:
|
|||
title: Gestionar tickets spliteados
|
||||
subTitle: Confir fecha y agencia
|
||||
split:
|
||||
ticket: Ticket viejo
|
||||
ticket: Ticket origen
|
||||
newTicket: Ticket nuevo
|
||||
status: Estado
|
||||
message: Mensaje
|
||||
|
|
|
@ -11,7 +11,12 @@ const $props = defineProps({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<QPopupProxy>
|
||||
<ZoneDescriptor v-if="$props.id" :id="$props.id" :summary="ZoneSummary" />
|
||||
<QPopupProxy data-cy="zoneDescriptorProxy">
|
||||
<ZoneDescriptor
|
||||
v-if="$props.id"
|
||||
:id="$props.id"
|
||||
:summary="ZoneSummary"
|
||||
data-cy="zoneDescriptorProxy"
|
||||
/>
|
||||
</QPopupProxy>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue