feat: updates

This commit is contained in:
Javier Segarra 2025-04-11 12:30:37 +02:00
parent 37bc464a98
commit b32a889dfe
17 changed files with 83 additions and 57 deletions

View File

@ -44,7 +44,8 @@ onBeforeMount(async () => {
}); });
// It enables to load data only once if the module is the same as the dataKey // It enables to load data only once if the module is the same as the dataKey
if (!isSameDataKey.value || !route.params.id) await getData(); if (!isSameDataKey.value || !route.params.id || $props.id !== route.params.id)
await getData();
watch( watch(
() => [$props.url, $props.filter], () => [$props.url, $props.filter],
async () => { async () => {

View File

@ -19,6 +19,7 @@ globals:
logOut: Log out logOut: Log out
date: Date date: Date
dataSaved: Data saved dataSaved: Data saved
openDetail: Open detail
dataDeleted: Data deleted dataDeleted: Data deleted
delete: Delete delete: Delete
search: Search search: Search

View File

@ -20,10 +20,11 @@ globals:
date: Fecha date: Fecha
dataSaved: Datos guardados dataSaved: Datos guardados
dataDeleted: Datos eliminados dataDeleted: Datos eliminados
dataCreated: Datos creados
openDetail: Ver detalle
delete: Eliminar delete: Eliminar
search: Buscar search: Buscar
changes: Cambios changes: Cambios
dataCreated: Datos creados
add: Añadir add: Añadir
create: Crear create: Crear
edit: Modificar edit: Modificar

View File

@ -6,10 +6,12 @@ import { toCurrency } from 'filters/index';
import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue'; import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
import VnTable from 'src/components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import axios from 'axios'; import axios from 'axios';
import notifyResults from 'src/utils/notifyResults'; import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import { useState } from 'src/composables/useState';
const MATCH = 'match'; const MATCH = 'match';
const { notifyResults } = displayResults();
const { t } = useI18n(); const { t } = useI18n();
const $props = defineProps({ const $props = defineProps({
@ -18,14 +20,20 @@ const $props = defineProps({
required: true, required: true,
default: () => {}, default: () => {},
}, },
filter: {
type: Object,
required: true,
default: () => {},
},
replaceAction: { replaceAction: {
type: Boolean, type: Boolean,
required: false, required: true,
default: false, default: false,
}, },
sales: { sales: {
type: Array, type: Array,
required: false, required: true,
default: () => [], default: () => [],
}, },
}); });
@ -36,6 +44,8 @@ const proposalTableRef = ref(null);
const sale = computed(() => $props.sales[0]); const sale = computed(() => $props.sales[0]);
const saleFk = computed(() => sale.value.saleFk); const saleFk = computed(() => sale.value.saleFk);
const filter = computed(() => ({ const filter = computed(() => ({
where: $props.filter,
itemFk: $props.itemLack.itemFk, itemFk: $props.itemLack.itemFk,
sales: saleFk.value, sales: saleFk.value,
})); }));

View File

@ -1,13 +1,17 @@
<script setup> <script setup>
import ItemProposal from './ItemProposal.vue'; import ItemProposal from './ItemProposal.vue';
import { useDialogPluginComponent } from 'quasar'; import { useDialogPluginComponent } from 'quasar';
const $props = defineProps({ const $props = defineProps({
itemLack: { itemLack: {
type: Object, type: Object,
required: true, required: true,
default: () => {}, default: () => {},
}, },
filter: {
type: Object,
required: true,
default: () => {},
},
replaceAction: { replaceAction: {
type: Boolean, type: Boolean,
required: false, required: false,
@ -31,7 +35,7 @@ defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.h
<QDialog ref="dialogRef" transition-show="scale" transition-hide="scale"> <QDialog ref="dialogRef" transition-show="scale" transition-hide="scale">
<QCard class="dialog-width"> <QCard class="dialog-width">
<QCardSection class="row items-center q-pb-none"> <QCardSection class="row items-center q-pb-none">
<span class="text-h6 text-grey">{{ $t('Item proposal') }}</span> <span class="text-h6 text-grey">{{ $t('itemProposal') }}</span>
<QSpace /> <QSpace />
<QBtn icon="close" flat round dense v-close-popup /> <QBtn icon="close" flat round dense v-close-popup />
</QCardSection> </QCardSection>

View File

@ -1,7 +1,6 @@
<script setup> <script setup>
import TicketDescriptor from './TicketDescriptor.vue'; import TicketDescriptor from './TicketDescriptor.vue';
import TicketSummary from './TicketSummary.vue'; import TicketSummary from './TicketSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,

View File

@ -3,6 +3,8 @@ import { ref } from 'vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import split from './components/split'; import split from './components/split';
import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
const { notifyResults } = displayResults();
const emit = defineEmits(['ticketTransferred']); const emit = defineEmits(['ticketTransferred']);
const $props = defineProps({ const $props = defineProps({
@ -16,7 +18,8 @@ const splitDate = ref(Date.vnNew());
const splitSelectedRows = async () => { const splitSelectedRows = async () => {
const tickets = Array.isArray($props.ticket) ? $props.ticket : [$props.ticket]; const tickets = Array.isArray($props.ticket) ? $props.ticket : [$props.ticket];
await split(tickets, splitDate.value); const results = await split(tickets, splitDate.value);
notifyResults(results, 'ticketFk');
emit('ticketTransferred', tickets); emit('ticketTransferred', tickets);
}; };
</script> </script>

View File

@ -1,13 +1,11 @@
import axios from 'axios'; import axios from 'axios';
import notifyResults from 'src/utils/notifyResults';
export default async function (data, date) { export default async function (data, date) {
const reducedData = data.reduce((acc, item) => { const reducedData = data.reduce((acc, item) => {
const existing = acc.find(({ ticketFk }) => ticketFk === item.id); const existing = acc.find(({ ticketFk }) => ticketFk === item.id);
if (existing) { if (existing) {
existing.sales.push(item.saleFk); existing.sales.push(item.saleFk);
} else { } else {
acc.push({ ticketFk: item.id, sales: [item.saleFk], date }); acc.push({ ticketFk: item.ticketFk, sales: [item.saleFk], date });
} }
return acc; return acc;
}, []); }, []);
@ -16,7 +14,5 @@ export default async function (data, date) {
const results = await Promise.allSettled(promises); const results = await Promise.allSettled(promises);
notifyResults(results, 'ticketFk');
return results; return results;
} }

View File

@ -23,7 +23,6 @@ const tableRef = ref();
const changeItemDialogRef = ref(null); const changeItemDialogRef = ref(null);
const changeStateDialogRef = ref(null); const changeStateDialogRef = ref(null);
const changeQuantityDialogRef = ref(null); const changeQuantityDialogRef = ref(null);
const showProposalDialog = ref(false);
const showChangeQuantityDialog = ref(false); const showChangeQuantityDialog = ref(false);
const selectedRows = ref([]); const selectedRows = ref([]);
const route = useRoute(); const route = useRoute();
@ -63,6 +62,7 @@ const showItemProposal = () => {
.dialog({ .dialog({
component: ItemProposalProxy, component: ItemProposalProxy,
componentProps: { componentProps: {
filter: filter.value,
itemLack: tableRef.value.itemLack, itemLack: tableRef.value.itemLack,
replaceAction: true, replaceAction: true,
sales: selectedRows.value, sales: selectedRows.value,
@ -123,15 +123,11 @@ const showItemProposal = () => {
</QBtn> </QBtn>
<QBtn <QBtn
color="primary" color="primary"
@click="showProposalDialog = true" @click="showItemProposal"
:disable="selectedRows.length < 1" :disable="selectedRows.length < 1"
data-cy="itemProposal" data-cy="itemProposal"
> >
<QIcon <QIcon name="import_export" class="rotate-90" />
name="import_export"
class="rotate-90"
@click="showItemProposal"
></QIcon>
<QTooltip bottom anchor="bottom right"> <QTooltip bottom anchor="bottom right">
{{ t('itemProposal') }} {{ t('itemProposal') }}
</QTooltip> </QTooltip>

View File

@ -151,7 +151,6 @@ const saveChange = async (field, { row }) => {
fetchItemLack.value.fetch(); fetchItemLack.value.fetch();
} catch (err) { } catch (err) {
console.error('Error saving changes', err); console.error('Error saving changes', err);
f;
} }
}; };

View File

@ -2,7 +2,9 @@
import { ref } from 'vue'; import { ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import notifyResults from 'src/utils/notifyResults'; import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
const { notifyResults } = displayResults();
const emit = defineEmits(['update-item']); const emit = defineEmits(['update-item']);
const showChangeItemDialog = ref(false); const showChangeItemDialog = ref(false);
@ -37,7 +39,6 @@ const updateItem = async () => {
<template> <template>
<QCard class="q-pa-sm"> <QCard class="q-pa-sm">
<QCardSection class="row items-center justify-center column items-stretch"> <QCardSection class="row items-center justify-center column items-stretch">
{{ showChangeItemDialog }}
<span>{{ $t('negative.detail.modal.changeItem.title') }}</span> <span>{{ $t('negative.detail.modal.changeItem.title') }}</span>
<VnSelect <VnSelect
url="Items/WithName" url="Items/WithName"

View File

@ -2,8 +2,9 @@
import { ref } from 'vue'; import { ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import notifyResults from 'src/utils/notifyResults'; import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
const { notifyResults } = displayResults();
const showChangeQuantityDialog = ref(false); const showChangeQuantityDialog = ref(false);
const newQuantity = ref(null); const newQuantity = ref(null);
const $props = defineProps({ const $props = defineProps({
@ -16,15 +17,16 @@ const emit = defineEmits(['update-quantity']);
const updateQuantity = async () => { const updateQuantity = async () => {
try { try {
showChangeQuantityDialog.value = true; showChangeQuantityDialog.value = true;
const rowsToUpdate = $props.selectedRows.map(({ saleFk }) => const rowsToUpdate = $props.selectedRows.map(({ saleFk, ticketFk }) =>
axios.post(`Sales/${saleFk}/updateQuantity`, { axios.post(`Sales/${saleFk}/updateQuantity`, {
saleFk, saleFk,
ticketFk,
quantity: +newQuantity.value, quantity: +newQuantity.value,
}), }),
); );
const result = await Promise.allSettled(rowsToUpdate); const result = await Promise.allSettled(rowsToUpdate);
notifyResults(result, 'saleFk'); notifyResults(result, 'ticketFk');
emit('update-quantity', newQuantity.value); emit('update-quantity', newQuantity.value);
} catch (err) { } catch (err) {

View File

@ -3,8 +3,9 @@ import { ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import notifyResults from 'src/utils/notifyResults'; import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
const { notifyResults } = displayResults();
const emit = defineEmits(['update-state']); const emit = defineEmits(['update-state']);
const editableStates = ref([]); const editableStates = ref([]);
const showChangeStateDialog = ref(false); const showChangeStateDialog = ref(false);

View File

@ -0,0 +1,39 @@
import { Notify } from 'quasar';
import useOpenURL from 'src/composables/useOpenURL';
import { useI18n } from 'vue-i18n';
export function displayResults() {
const { t } = useI18n();
const notifyResults = (results, key, path = 'sale') =>
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const data = JSON.parse(result.value.config.data);
if (result.value.data.status === 'noSplit') {
Notify.create({
type: 'warning',
message: `Ticket ${data[key]}: ${t('negative.split.noSplit')}`,
});
} else
Notify.create({
type: 'positive',
message: t('globals.dataSaved'),
actions: [
{
label: t('globals.openDetail'),
color: 'white',
handler: () => {
useOpenURL(`#/ticket/${data[key]}/${path}`);
},
},
],
});
} else {
const data = JSON.parse(result.reason.config.data);
Notify.create({
type: 'negative',
message: `Ticket ${data[key]}: ${result.reason.response?.data?.error?.message ?? result.reason.message}`,
});
}
});
return { notifyResults };
}

View File

@ -289,3 +289,4 @@ negative:
newTicket: New ticket newTicket: New ticket
status: Result status: Result
message: Message message: Message
noSplit: No split

View File

@ -290,6 +290,7 @@ negative:
newTicket: Ticket nuevo newTicket: Ticket nuevo
status: Estado status: Estado
message: Mensaje message: Mensaje
noSplit: No se puede splitar
rounding: Redondeo rounding: Redondeo
noVerifiedData: Sin datos comprobados noVerifiedData: Sin datos comprobados
purchaseRequest: Petición de compra purchaseRequest: Petición de compra

View File

@ -1,29 +0,0 @@
import { Notify } from 'quasar';
import useOpenURL from 'src/composables/useOpenURL';
export default function (results, key) {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const data = JSON.parse(result.value.config.data);
Notify.create({
type: 'positive',
message: `Operación (${index + 1}) ${data[key]} completada con éxito.`,
actions: [
{
label: 'Ver',
color: 'white',
handler: () => {
useOpenURL(`#/ticket/${data[key]}/summary`);
},
},
],
});
} else {
const data = JSON.parse(result.reason.config.data);
Notify.create({
type: 'negative',
message: `Operación (${index + 1}) ${data[key]} fallida: ${result.reason.message}`,
});
}
});
}