Merge branch 'dev' of https: refs #8409//gitea.verdnatura.es/verdnatura/salix-front into 8409-VnSelectSupplier

This commit is contained in:
Jon Elias 2025-01-27 13:21:27 +01:00
commit 8642089bc7
74 changed files with 1178 additions and 732 deletions

View File

@ -149,7 +149,7 @@ function filter(value, update, filterOptions) {
(ref) => { (ref) => {
ref.setOptionIndex(-1); ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true); ref.moveOptionSelection(1, true);
} },
); );
} }
@ -215,7 +215,7 @@ async function remove(data) {
if (preRemove.length) { if (preRemove.length) {
newData = newData.filter( newData = newData.filter(
(form) => !preRemove.some((index) => index == form.$index) (form) => !preRemove.some((index) => index == form.$index),
); );
const changes = getChanges(); const changes = getChanges();
if (!changes.creates?.length && !changes.updates?.length) if (!changes.creates?.length && !changes.updates?.length)

View File

@ -61,7 +61,6 @@ onMounted(() => stateStore.setMounted());
/> />
<QSpace /> <QSpace />
<div id="searchbar" class="searchbar"></div> <div id="searchbar" class="searchbar"></div>
<div id="searchbar-after"></div>
<QSpace /> <QSpace />
<div class="q-pl-sm q-gutter-sm row items-center no-wrap"> <div class="q-pl-sm q-gutter-sm row items-center no-wrap">
<div id="actions-prepend"></div> <div id="actions-prepend"></div>

View File

@ -20,7 +20,7 @@ watch(
(val) => { (val) => {
if (stateStore) stateStore.rightAdvancedDrawer = val; if (stateStore) stateStore.rightAdvancedDrawer = val;
}, },
{ immediate: true } { immediate: true },
); );
</script> </script>
<template> <template>
@ -30,8 +30,8 @@ watch(
flat flat
@click="stateStore.toggleRightAdvancedDrawer()" @click="stateStore.toggleRightAdvancedDrawer()"
round round
dense
icon="tune" icon="tune"
color="white"
> >
<QTooltip bottom anchor="bottom right"> <QTooltip bottom anchor="bottom right">
{{ t('globals.advancedMenu') }} {{ t('globals.advancedMenu') }}

View File

@ -202,7 +202,7 @@ const columns = computed(() => [
prop.row.id, prop.row.id,
$props.downloadModel, $props.downloadModel,
undefined, undefined,
prop.row.download prop.row.download,
), ),
}, },
{ {
@ -374,7 +374,7 @@ defineExpose({
v-if=" v-if="
shouldRenderButton( shouldRenderButton(
button.name, button.name,
props.row.isDocuware props.row.isDocuware,
) )
" "
:is="button.component" :is="button.component"

View File

@ -75,6 +75,7 @@ const focus = () => {
defineExpose({ defineExpose({
focus, focus,
vnInputRef,
}); });
const mixinRules = [ const mixinRules = [

View File

@ -804,7 +804,7 @@ watch(
<QItem class="q-mt-sm"> <QItem class="q-mt-sm">
<QInput <QInput
class="full-width" class="full-width"
:label="t('to')" :label="t('globals.to')"
@click="dateToDialog = true" @click="dateToDialog = true"
@focus="(evt) => evt.target.blur()" @focus="(evt) => evt.target.blur()"
@clear="selectFilter('date', 'from')" @clear="selectFilter('date', 'from')"
@ -1059,9 +1059,9 @@ en:
Deletes: Deletes Deletes: Deletes
Accesses: Accesses Accesses: Accesses
Users: Users:
User: Usuario User: User
All: Todo All: All
System: Sistema System: System
properties: properties:
id: ID id: ID
claimFk: Claim ID claimFk: Claim ID

View File

@ -75,6 +75,10 @@ onMounted(() => {
onUnmounted(unsubscribe); onUnmounted(unsubscribe);
}); });
onUnmounted(() => {
if (arrayData) arrayData.destroy();
});
function checkIsMain() { function checkIsMain() {
isMainSection.value = sectionValue.value == route.name; isMainSection.value = sectionValue.value == route.name;
if (!isMainSection.value && arrayData) { if (!isMainSection.value && arrayData) {
@ -94,8 +98,8 @@ function checkIsMain() {
/> />
<div :id="searchbarId"></div> <div :id="searchbarId"></div>
</slot> </slot>
<RightAdvancedMenu :is-main-section="isMainSection"> <RightAdvancedMenu :is-main-section="isMainSection && rightFilter">
<template #advanced-menu v-if="$slots[advancedMenuSlot] || rightFilter"> <template #advanced-menu v-if="$slots[advancedMenuSlot]">
<slot :name="advancedMenuSlot"> <slot :name="advancedMenuSlot">
<VnTableFilter <VnTableFilter
v-if="rightFilter && columns" v-if="rightFilter && columns"

View File

@ -9,9 +9,9 @@ const $props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
hasInfo: { info: {
type: Boolean, type: String,
default: false, default: undefined,
}, },
modelValue: { modelValue: {
type: [String, Number, Object], type: [String, Number, Object],
@ -57,9 +57,9 @@ const url = computed(() => {
<template #prepend v-if="$props.hasAvatar"> <template #prepend v-if="$props.hasAvatar">
<VnAvatar :worker-id="value" color="primary" v-bind="$attrs" /> <VnAvatar :worker-id="value" color="primary" v-bind="$attrs" />
</template> </template>
<template #append v-if="$props.hasInfo"> <template #append v-if="$props.info">
<QIcon name="info" class="cursor-pointer"> <QIcon name="info" class="cursor-pointer">
<QTooltip>{{ $t($props.hasInfo) }}</QTooltip> <QTooltip>{{ $t($props.info) }}</QTooltip>
</QIcon> </QIcon>
</template> </template>
<template #option="scope"> <template #option="scope">

View File

@ -10,6 +10,10 @@ defineProps({
type: Object, type: Object,
required: true, required: true,
}, },
width: {
type: String,
default: 'md-width',
},
}); });
defineEmits([...useDialogPluginComponent.emits]); defineEmits([...useDialogPluginComponent.emits]);
@ -17,7 +21,19 @@ defineEmits([...useDialogPluginComponent.emits]);
const { dialogRef, onDialogHide } = useDialogPluginComponent(); const { dialogRef, onDialogHide } = useDialogPluginComponent();
</script> </script>
<template> <template>
<QDialog ref="dialogRef" @hide="onDialogHide" full-width> <QDialog ref="dialogRef" @hide="onDialogHide">
<component :is="summary" :id="id" /> <component :is="summary" :id="id" :class="width" />
</QDialog> </QDialog>
</template> </template>
<style lang="scss" scoped>
.md-width {
max-width: $width-md;
}
.lg-width {
max-width: $width-lg;
}
.xlg-width {
max-width: $width-xl;
}
</style>

View File

@ -37,6 +37,10 @@ const $props = defineProps({
type: Object, type: Object,
default: null, default: null,
}, },
width: {
type: String,
default: 'md-width',
},
}); });
const state = useState(); const state = useState();
@ -128,9 +132,8 @@ const toModule = computed(() =>
</QTooltip> </QTooltip>
</QBtn></slot </QBtn></slot
> >
<QBtn <QBtn
@click.stop="viewSummary(entity.id, $props.summary)" @click.stop="viewSummary(entity.id, $props.summary, $props.width)"
round round
flat flat
dense dense

View File

@ -102,7 +102,7 @@ watch(
(val) => { (val) => {
arrayData = useArrayData(val, { ...props }); arrayData = useArrayData(val, { ...props });
store = arrayData.store; store = arrayData.store;
} },
); );
onMounted(() => { onMounted(() => {
@ -176,6 +176,7 @@ async function search() {
> >
<QTooltip>{{ t(props.info) }}</QTooltip> <QTooltip>{{ t(props.info) }}</QTooltip>
</QIcon> </QIcon>
<div id="searchbar-after"></div>
</template> </template>
</VnInput> </VnInput>
</QForm> </QForm>

View File

@ -4,10 +4,10 @@ import { useQuasar } from 'quasar';
export function useSummaryDialog() { export function useSummaryDialog() {
const quasar = useQuasar(); const quasar = useQuasar();
function viewSummary(id, summary) { function viewSummary(id, summary, width) {
quasar.dialog({ quasar.dialog({
component: VnSummaryDialog, component: VnSummaryDialog,
componentProps: { id, summary }, componentProps: { id, summary, width },
}); });
} }

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
@font-face { @font-face {
font-family: 'icon'; font-family: 'icon';
src: url('fonts/icon.eot?y0x93o'); src: url('fonts/icon.eot?7j3xju');
src: url('fonts/icon.eot?y0x93o#iefix') format('embedded-opentype'), src: url('fonts/icon.eot?7j3xju#iefix') format('embedded-opentype'),
url('fonts/icon.ttf?y0x93o') format('truetype'), url('fonts/icon.ttf?7j3xju') format('truetype'),
url('fonts/icon.woff?y0x93o') format('woff'), url('fonts/icon.woff?7j3xju') format('woff'),
url('fonts/icon.svg?y0x93o#icon') format('svg'); url('fonts/icon.svg?7j3xju#icon') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
font-display: block; font-display: block;
@ -25,8 +25,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-entry_lastbuys:before { .icon-hasItemLost:before {
content: "\e91a"; content: "\e957";
}
.icon-hasItemDelay:before {
content: "\e96d";
}
.icon-add_entries:before {
content: "\e953";
} }
.icon-100:before { .icon-100:before {
content: "\e901"; content: "\e901";
@ -52,6 +58,9 @@
.icon-addperson:before { .icon-addperson:before {
content: "\e908"; content: "\e908";
} }
.icon-agencia_tributaria:before {
content: "\e948";
}
.icon-agency:before { .icon-agency:before {
content: "\e92a"; content: "\e92a";
} }
@ -189,6 +198,9 @@
.icon-entry:before { .icon-entry:before {
content: "\e937"; content: "\e937";
} }
.icon-entry_lastbuys:before {
content: "\e91a";
}
.icon-exit:before { .icon-exit:before {
content: "\e938"; content: "\e938";
} }

View File

@ -33,6 +33,11 @@ $dark-shadow-color: black;
$layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d; $layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d;
$spacing-md: 16px; $spacing-md: 16px;
$color-font-secondary: #777; $color-font-secondary: #777;
$width-xs: 400px;
$width-sm: 544px;
$width-md: 800px;
$width-lg: 1280px;
$width-xl: 1600px;
.bg-success { .bg-success {
background-color: $positive; background-color: $positive;
} }

View File

@ -53,6 +53,7 @@ const debtWarning = computed(() => {
@on-fetch="setData" @on-fetch="setData"
:summary="$props.summary" :summary="$props.summary"
data-key="customer" data-key="customer"
width="lg-width"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<CustomerDescriptorMenu :customer="entity" /> <CustomerDescriptorMenu :customer="entity" />

View File

@ -2,7 +2,7 @@
import { onBeforeMount, ref } from 'vue'; import { onBeforeMount, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useQuasar } from 'quasar';
import axios from 'axios'; import axios from 'axios';
import VnLocation from 'src/components/common/VnLocation.vue'; import VnLocation from 'src/components/common/VnLocation.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
@ -13,11 +13,12 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue'; import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue'; import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue'; import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import VnConfirm from 'components/ui/VnConfirm.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const quasar = useQuasar();
const urlUpdate = ref(''); const urlUpdate = ref('');
const agencyModes = ref([]); const agencyModes = ref([]);
const incoterms = ref([]); const incoterms = ref([]);
@ -83,8 +84,26 @@ const deleteNote = (id, index) => {
notes.value.splice(index, 1); notes.value.splice(index, 1);
}; };
const onDataSaved = async () => { const updateAddress = async (data) => {
let payload = { await axios.patch(urlUpdate.value, data);
};
const updateAddressTicket = async () => {
urlUpdate.value += '?updateObservations=true';
};
const updateObservations = async (payload) => {
await axios.post('AddressObservations/crud', payload);
notes.value = [];
deletes.value = [];
toCustomerAddress();
};
async function updateAll({ data, payload }) {
await updateObservations(payload);
await updateAddress(data);
}
function getPayload() {
return {
creates: notes.value.filter((note) => note.$isNew), creates: notes.value.filter((note) => note.$isNew),
deletes: deletes.value, deletes: deletes.value,
updates: notes.value updates: notes.value
@ -101,14 +120,40 @@ const onDataSaved = async () => {
where: { id: note.id }, where: { id: note.id },
})), })),
}; };
}
await axios.post('AddressObservations/crud', payload); async function handleDialog(data) {
notes.value = []; const payload = getPayload();
deletes.value = []; const body = { data, payload };
toCustomerAddress(); if (payload.updates.length) {
}; quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t(
'confirmTicket'
),
message: t('confirmDeletionMessage'),
},
})
.onOk(async () => {
await updateAddressTicket();
await updateAll(body);
toCustomerAddress();
})
.onCancel(async () => {
await updateAll(body);
toCustomerAddress();
});
} else {
updateAll(body);
toCustomerAddress();
}
}
const toCustomerAddress = () => { const toCustomerAddress = () => {
notes.value = [];
deletes.value = [];
router.push({ router.push({
name: 'CustomerAddress', name: 'CustomerAddress',
params: { params: {
@ -143,7 +188,7 @@ function handleLocation(data, location) {
:observe-form-changes="false" :observe-form-changes="false"
:url-update="urlUpdate" :url-update="urlUpdate"
:url="`Addresses/${route.params.addressId}`" :url="`Addresses/${route.params.addressId}`"
@on-data-saved="onDataSaved()" :save-fn="handleDialog"
auto-load auto-load
> >
<template #moreActions> <template #moreActions>
@ -336,4 +381,9 @@ es:
Remove note: Eliminar nota Remove note: Eliminar nota
Longitude: Longitud Longitude: Longitud
Latitude: Latitud Latitude: Latitud
confirmTicket: ¿Desea modificar también los estados de todos los tickets que están a punto de ser servidos?
confirmDeletionMessage: Si le das a aceptar, se modificaran todas las notas de los ticket a futuro
en:
confirmTicket: Do you also want to modify the states of all the tickets that are about to be served?
confirmDeletionMessage: If you click accept, all the notes of the future tickets will be modified
</i18n> </i18n>

View File

@ -0,0 +1,33 @@
import { describe, it, expect, vi, afterEach } from 'vitest';
import axios from 'axios';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
vi.mock('axios');
describe('getAddresses', () => {
afterEach(() => {
vi.clearAllMocks();
});
it('should fetch addresses with correct parameters for a valid clientId', async () => {
const clientId = '12345';
await getAddresses(clientId);
expect(axios.get).toHaveBeenCalledWith(`Clients/${clientId}/addresses`, {
params: {
filter: JSON.stringify({
fields: ['nickname', 'street', 'city', 'id'],
where: { isActive: true },
order: 'nickname ASC',
}),
},
});
});
it('should return undefined when clientId is not provided', async () => {
await getAddresses(undefined);
expect(axios.get).not.toHaveBeenCalled();
});
});

View File

@ -0,0 +1,41 @@
import { describe, it, expect, vi, afterEach } from 'vitest';
import axios from 'axios';
import { getClient } from 'src/pages/Customer/composables/getClient';
vi.mock('axios');
describe('getClient', () => {
afterEach(() => {
vi.clearAllMocks();
});
const generateParams = (clientId) => ({
params: {
filter: JSON.stringify({
include: {
relation: 'defaultAddress',
scope: {
fields: ['id', 'agencyModeFk'],
},
},
where: { id: clientId },
}),
},
});
it('should fetch client data with correct parameters for a valid clientId', async () => {
const clientId = '12345';
await getClient(clientId);
expect(axios.get).toHaveBeenCalledWith('Clients', generateParams(clientId));
});
it('should return undefined when clientId is not provided', async () => {
const clientId = undefined;
await getClient(clientId);
expect(axios.get).toHaveBeenCalledWith('Clients', generateParams(clientId));
});
});

View File

@ -0,0 +1,14 @@
import axios from 'axios';
export async function getAddresses(clientId) {
if (!clientId) return;
const filter = {
fields: ['nickname', 'street', 'city', 'id'],
where: { isActive: true },
order: 'nickname ASC',
};
const params = { filter: JSON.stringify(filter) };
return await axios.get(`Clients/${clientId}/addresses`, {
params,
});
};

View File

@ -0,0 +1,15 @@
import axios from 'axios';
export async function getClient(clientId) {
const filter = {
include: {
relation: 'defaultAddress',
scope: {
fields: ['id', 'agencyModeFk'],
},
},
where: { id: clientId },
};
const params = { filter: JSON.stringify(filter) };
return await axios.get('Clients', { params });
};

View File

@ -2,13 +2,10 @@
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import { getUrl } from 'src/composables/getUrl'; import { getUrl } from 'src/composables/getUrl';
import filter from './EntryFilter.js';
import EntryDescriptorMenu from './EntryDescriptorMenu.vue'; import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
const $props = defineProps({ const $props = defineProps({
@ -23,7 +20,42 @@ const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const entryDescriptorRef = ref(null); const entryDescriptorRef = ref(null);
const url = ref(); const url = ref();
const entryFilter = {
include: [
{
relation: 'travel',
scope: {
fields: ['id', 'landed', 'shipped', 'agencyModeFk', 'warehouseOutFk'],
include: [
{
relation: 'agency',
scope: {
fields: ['name'],
},
},
{
relation: 'warehouseOut',
scope: {
fields: ['name'],
},
},
{
relation: 'warehouseIn',
scope: {
fields: ['name'],
},
},
],
},
},
{
relation: 'supplier',
scope: {
fields: ['id', 'nickname'],
},
},
],
};
const entityId = computed(() => { const entityId = computed(() => {
return $props.id || route.params.id; return $props.id || route.params.id;
}); });
@ -58,9 +90,10 @@ const getEntryRedirectionFilter = (entry) => {
ref="entryDescriptorRef" ref="entryDescriptorRef"
module="Entry" module="Entry"
:url="`Entries/${entityId}`" :url="`Entries/${entityId}`"
:filter="filter" :userFilter="entryFilter"
title="supplier.nickname" title="supplier.nickname"
data-key="Entry" data-key="Entry"
width="lg-width"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<EntryDescriptorMenu :id="entity.id" /> <EntryDescriptorMenu :id="entity.id" />

View File

@ -1,5 +1,11 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { useQuasar } from 'quasar';
import axios from 'axios';
import { usePrintService } from 'composables/usePrintService'; import { usePrintService } from 'composables/usePrintService';
import useNotify from 'src/composables/useNotify.js';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
const { openReport } = usePrintService(); const { openReport } = usePrintService();
@ -9,14 +15,47 @@ const $props = defineProps({
required: true, required: true,
}, },
}); });
const { t } = useI18n();
const { notify } = useNotify();
const quasar = useQuasar();
const route = useRoute();
function showEntryReport() { function showEntryReport() {
openReport(`Entries/${$props.id}/entry-order-pdf`); openReport(`Entries/${$props.id}/entry-order-pdf`);
} }
const openDialog = () => {
quasar.dialog({
component: VnConfirm,
componentProps: {
title: t('transferEntryDialog'),
promise: transferEntry,
},
});
};
const transferEntry = async () => {
const { data } = await axios.post(`Entries/${route.params.id}/transfer`);
notify('globals.dataSaved', 'positive');
const url = `#/entry/${data.newEntryFk.newEntryFk}/summary`;
window.open(url, '_blank');
};
</script> </script>
<template> <template>
<QItem v-ripple clickable @click="showEntryReport"> <QItem v-ripple clickable @click="showEntryReport">
<QItemSection>{{ $t('entryList.list.showEntryReport') }}</QItemSection> <QItemSection>{{ $t('entryList.list.showEntryReport') }}</QItemSection>
</QItem> </QItem>
<QItem v-ripple clickable @click="openDialog">
<QItemSection>{{ t('transferEntry') }}</QItemSection>
</QItem>
</template> </template>
<i18n>
en:
transferEntryDialog: The entries will be transferred to the next day
transferEntry: Transfer Entry
es:
transferEntryDialog: Se van a transferir las compras al dia siguiente
transferEntry: Transferir Entrada
</i18n>

View File

@ -254,7 +254,7 @@ function deleteFile(dmsFk) {
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnSelect <VnSelect
:label="t('invoicein.summary.sage')" :label="t('invoiceIn.summary.sage')"
v-model="data.withholdingSageFk" v-model="data.withholdingSageFk"
:options="sageWithholdings" :options="sageWithholdings"
option-value="id" option-value="id"

View File

@ -1,10 +1,6 @@
<script setup> <script setup>
import VnCard from 'components/common/VnCard.vue'; import VnCardBeta from 'components/common/VnCardBeta.vue';
import InvoiceInDescriptor from './InvoiceInDescriptor.vue'; import InvoiceInDescriptor from './InvoiceInDescriptor.vue';
import InvoiceInFilter from '../InvoiceInFilter.vue';
import InvoiceInSearchbar from '../InvoiceInSearchbar.vue';
import { onBeforeRouteUpdate } from 'vue-router';
import { setRectificative } from '../composables/setRectificative';
const filter = { const filter = {
include: [ include: [
@ -39,20 +35,13 @@ const filter = {
}, },
], ],
}; };
onBeforeRouteUpdate(async (to) => await setRectificative(to));
</script> </script>
<template> <template>
<VnCard <VnCardBeta
data-key="InvoiceIn" data-key="InvoiceIn"
base-url="InvoiceIns" base-url="InvoiceIns"
:filter="filter"
:descriptor="InvoiceInDescriptor" :descriptor="InvoiceInDescriptor"
:filter-panel="InvoiceInFilter" :user-filter="filter"
search-data-key="InvoiceInList" />
>
<template #searchbar>
<InvoiceInSearchbar />
</template>
</VnCard>
</template> </template>

View File

@ -105,7 +105,7 @@ async function setInvoiceCorrection(id) {
if (correctingData[0]) invoiceInCorrection.corrected = correctingData[0].correctedFk; if (correctingData[0]) invoiceInCorrection.corrected = correctingData[0].correctedFk;
invoiceInCorrection.correcting = correctedData.map( invoiceInCorrection.correcting = correctedData.map(
(corrected) => corrected.correctingFk (corrected) => corrected.correctingFk,
); );
} }
</script> </script>
@ -117,18 +117,19 @@ async function setInvoiceCorrection(id) {
:url="`InvoiceIns/${entityId}`" :url="`InvoiceIns/${entityId}`"
:filter="filter" :filter="filter"
title="supplierRef" title="supplierRef"
width="xlg-width"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<InvoiceInDescriptorMenu :invoice="entity" /> <InvoiceInDescriptorMenu :invoice="entity" />
</template> </template>
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('invoicein.list.issued')" :value="toDate(entity.issued)" /> <VnLv :label="t('invoiceIn.list.issued')" :value="toDate(entity.issued)" />
<VnLv <VnLv
:label="t('invoicein.summary.bookedDate')" :label="t('invoiceIn.summary.bookedDate')"
:value="toDate(entity.booked)" :value="toDate(entity.booked)"
/> />
<VnLv :label="t('invoicein.list.amount')" :value="toCurrency(totalAmount)" /> <VnLv :label="t('invoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
<VnLv :label="t('invoicein.list.supplier')"> <VnLv :label="t('invoiceIn.list.supplier')">
<template #value> <template #value>
<span class="link"> <span class="link">
{{ entity?.supplier?.nickname }} {{ entity?.supplier?.nickname }}
@ -145,7 +146,7 @@ async function setInvoiceCorrection(id) {
color="primary" color="primary"
:to="routes.getSupplier(entity.supplierFk)" :to="routes.getSupplier(entity.supplierFk)"
> >
<QTooltip>{{ t('invoicein.list.supplier') }}</QTooltip> <QTooltip>{{ t('globals.supplier') }}</QTooltip>
</QBtn> </QBtn>
<QBtn <QBtn
size="md" size="md"
@ -153,7 +154,7 @@ async function setInvoiceCorrection(id) {
color="primary" color="primary"
:to="routes.getEntry(entity.entryFk)" :to="routes.getEntry(entity.entryFk)"
> >
<QTooltip>{{ t('Entry') }}</QTooltip> <QTooltip>{{ t('globals.entry') }}</QTooltip>
</QBtn> </QBtn>
<QBtn <QBtn
size="md" size="md"
@ -161,7 +162,7 @@ async function setInvoiceCorrection(id) {
color="primary" color="primary"
:to="routes.getTickets(entity.supplierFk)" :to="routes.getTickets(entity.supplierFk)"
> >
<QTooltip>{{ t('InvoiceOut.card.ticketList') }}</QTooltip> <QTooltip>{{ t('globals.ticketList') }}</QTooltip>
</QBtn> </QBtn>
<QBtn <QBtn
v-if=" v-if="

View File

@ -40,15 +40,15 @@ const cplusRectificationTypes = ref([]);
const siiTypeInvoiceIns = ref([]); const siiTypeInvoiceIns = ref([]);
const actions = { const actions = {
unbook: { unbook: {
title: t('assertAction', { action: t('invoicein.descriptorMenu.unbook') }), title: t('assertAction', { action: t('invoiceIn.descriptorMenu.unbook') }),
action: toUnbook, action: toUnbook,
}, },
delete: { delete: {
title: t('assertAction', { action: t('invoicein.descriptorMenu.delete') }), title: t('assertAction', { action: t('invoiceIn.descriptorMenu.delete') }),
action: deleteInvoice, action: deleteInvoice,
}, },
clone: { clone: {
title: t('assertAction', { action: t('invoicein.descriptorMenu.clone') }), title: t('assertAction', { action: t('invoiceIn.descriptorMenu.clone') }),
action: cloneInvoice, action: cloneInvoice,
}, },
showPdf: { cb: showPdfInvoice }, showPdf: { cb: showPdfInvoice },
@ -96,7 +96,7 @@ async function deleteInvoice() {
await axios.delete(`InvoiceIns/${entityId.value}`); await axios.delete(`InvoiceIns/${entityId.value}`);
quasar.notify({ quasar.notify({
type: 'positive', type: 'positive',
message: t('invoicein.descriptorMenu.invoiceDeleted'), message: t('invoiceIn.descriptorMenu.invoiceDeleted'),
}); });
push({ path: '/invoice-in' }); push({ path: '/invoice-in' });
} }
@ -105,7 +105,7 @@ async function cloneInvoice() {
const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`); const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`);
quasar.notify({ quasar.notify({
type: 'positive', type: 'positive',
message: t('invoicein.descriptorMenu.invoiceCloned'), message: t('invoiceIn.descriptorMenu.invoiceCloned'),
}); });
push({ path: `/invoice-in/${data.id}/summary` }); push({ path: `/invoice-in/${data.id}/summary` });
} }
@ -149,7 +149,7 @@ function sendPdfInvoice({ address }) {
const createInvoiceInCorrection = async () => { const createInvoiceInCorrection = async () => {
const { data: correctingId } = await axios.post( const { data: correctingId } = await axios.post(
'InvoiceIns/corrective', 'InvoiceIns/corrective',
Object.assign(correctionFormData, { id: entityId.value }) Object.assign(correctionFormData, { id: entityId.value }),
); );
push({ path: `/invoice-in/${correctingId}/summary` }); push({ path: `/invoice-in/${correctingId}/summary` });
}; };
@ -186,7 +186,7 @@ const createInvoiceInCorrection = async () => {
clickable clickable
@click="book(entityId)" @click="book(entityId)"
> >
<QItemSection>{{ t('invoicein.descriptorMenu.toBook') }}</QItemSection> <QItemSection>{{ t('invoiceIn.descriptorMenu.toBook') }}</QItemSection>
</QItem> </QItem>
</template> </template>
</InvoiceInToBook> </InvoiceInToBook>
@ -197,7 +197,7 @@ const createInvoiceInCorrection = async () => {
@click="triggerMenu('unbook')" @click="triggerMenu('unbook')"
> >
<QItemSection> <QItemSection>
{{ t('invoicein.descriptorMenu.toUnbook') }} {{ t('invoiceIn.descriptorMenu.toUnbook') }}
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem <QItem
@ -206,19 +206,19 @@ const createInvoiceInCorrection = async () => {
clickable clickable
@click="triggerMenu('delete')" @click="triggerMenu('delete')"
> >
<QItemSection>{{ t('invoicein.descriptorMenu.deleteInvoice') }}</QItemSection> <QItemSection>{{ t('invoiceIn.descriptorMenu.deleteInvoice') }}</QItemSection>
</QItem> </QItem>
<QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')"> <QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')">
<QItemSection>{{ t('invoicein.descriptorMenu.cloneInvoice') }}</QItemSection> <QItemSection>{{ t('invoiceIn.descriptorMenu.cloneInvoice') }}</QItemSection>
</QItem> </QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')"> <QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
<QItemSection>{{ <QItemSection>{{
t('invoicein.descriptorMenu.showAgriculturalPdf') t('invoiceIn.descriptorMenu.showAgriculturalPdf')
}}</QItemSection> }}</QItemSection>
</QItem> </QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')"> <QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
<QItemSection <QItemSection
>{{ t('invoicein.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection >{{ t('invoiceIn.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
> >
</QItem> </QItem>
<QItem <QItem
@ -228,7 +228,7 @@ const createInvoiceInCorrection = async () => {
@click="triggerMenu('correct')" @click="triggerMenu('correct')"
> >
<QItemSection <QItemSection
>{{ t('invoicein.descriptorMenu.createCorrective') }}...</QItemSection >{{ t('invoiceIn.descriptorMenu.createCorrective') }}...</QItemSection
> >
</QItem> </QItem>
<QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)"> <QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)">
@ -272,7 +272,6 @@ const createInvoiceInCorrection = async () => {
> >
<template #option="{ itemProps, opt }"> <template #option="{ itemProps, opt }">
<QItem v-bind="itemProps"> <QItem v-bind="itemProps">
{{ console.log('opt: ', opt) }}
<QItemSection> <QItemSection>
<QItemLabel <QItemLabel
>{{ opt.id }} - >{{ opt.id }} -
@ -311,11 +310,11 @@ const createInvoiceInCorrection = async () => {
<i18n> <i18n>
en: en:
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
isLinked: The entry has been linked to Sage. Please contact administration for further information isLinked: The entry has been linked to Sage. Please contact administration for further information
assertAction: Are you sure you want to {action} this invoice? assertAction: Are you sure you want to {action} this invoice?
es: es:
isNotLinked: Se ha eliminado el asiento {bookEntry} con {accountingEntries} apuntes isNotLinked: Se ha eliminado el asiento {bookEntry} con {accountingEntries} apuntes
isLinked: El asiento fue enlazado a Sage, por favor contacta con administración isLinked: El asiento fue enlazado a Sage, por favor contacta con administración
assertAction: Estas seguro de querer {action} esta factura? assertAction: Estas seguro de querer {action} esta factura?
</i18n> </i18n>

View File

@ -27,14 +27,14 @@ const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 });
const vatColumns = ref([ const vatColumns = ref([
{ {
name: 'expense', name: 'expense',
label: 'invoicein.summary.expense', label: 'invoiceIn.summary.expense',
field: (row) => row.expenseFk, field: (row) => row.expenseFk,
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'landed', name: 'landed',
label: 'invoicein.summary.taxableBase', label: 'invoiceIn.summary.taxableBase',
field: (row) => row.taxableBase, field: (row) => row.taxableBase,
format: (value) => toCurrency(value), format: (value) => toCurrency(value),
sortable: true, sortable: true,
@ -42,7 +42,7 @@ const vatColumns = ref([
}, },
{ {
name: 'vat', name: 'vat',
label: 'invoicein.summary.sageVat', label: 'invoiceIn.summary.sageVat',
field: (row) => { field: (row) => {
if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`; if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`;
}, },
@ -52,7 +52,7 @@ const vatColumns = ref([
}, },
{ {
name: 'transaction', name: 'transaction',
label: 'invoicein.summary.sageTransaction', label: 'invoiceIn.summary.sageTransaction',
field: (row) => { field: (row) => {
if (row.transactionTypeSage) if (row.transactionTypeSage)
return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`; return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`;
@ -63,7 +63,7 @@ const vatColumns = ref([
}, },
{ {
name: 'rate', name: 'rate',
label: 'invoicein.summary.rate', label: 'invoiceIn.summary.rate',
field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate), field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
format: (value) => toCurrency(value), format: (value) => toCurrency(value),
sortable: true, sortable: true,
@ -71,7 +71,7 @@ const vatColumns = ref([
}, },
{ {
name: 'currency', name: 'currency',
label: 'invoicein.summary.currency', label: 'invoiceIn.summary.currency',
field: (row) => row.foreignValue, field: (row) => row.foreignValue,
format: (val) => val && toCurrency(val, currency.value), format: (val) => val && toCurrency(val, currency.value),
sortable: true, sortable: true,
@ -82,21 +82,21 @@ const vatColumns = ref([
const dueDayColumns = ref([ const dueDayColumns = ref([
{ {
name: 'date', name: 'date',
label: 'invoicein.summary.dueDay', label: 'invoiceIn.summary.dueDay',
field: (row) => toDate(row.dueDated), field: (row) => toDate(row.dueDated),
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'bank', name: 'bank',
label: 'invoicein.summary.bank', label: 'invoiceIn.summary.bank',
field: (row) => row.bank.bank, field: (row) => row.bank.bank,
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'amount', name: 'amount',
label: 'invoicein.list.amount', label: 'invoiceIn.list.amount',
field: (row) => row.amount, field: (row) => row.amount,
format: (value) => toCurrency(value), format: (value) => toCurrency(value),
sortable: true, sortable: true,
@ -104,7 +104,7 @@ const dueDayColumns = ref([
}, },
{ {
name: 'landed', name: 'landed',
label: 'invoicein.summary.foreignValue', label: 'invoiceIn.summary.foreignValue',
field: (row) => row.foreignValue, field: (row) => row.foreignValue,
format: (val) => val && toCurrency(val, currency.value), format: (val) => val && toCurrency(val, currency.value),
sortable: true, sortable: true,
@ -115,7 +115,7 @@ const dueDayColumns = ref([
const intrastatColumns = ref([ const intrastatColumns = ref([
{ {
name: 'code', name: 'code',
label: 'invoicein.summary.code', label: 'invoiceIn.summary.code',
field: (row) => { field: (row) => {
return `${row.intrastat.id}: ${row.intrastat?.description}`; return `${row.intrastat.id}: ${row.intrastat?.description}`;
}, },
@ -124,21 +124,21 @@ const intrastatColumns = ref([
}, },
{ {
name: 'amount', name: 'amount',
label: 'invoicein.list.amount', label: 'invoiceIn.list.amount',
field: (row) => toCurrency(row.amount), field: (row) => toCurrency(row.amount),
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'net', name: 'net',
label: 'invoicein.summary.net', label: 'invoiceIn.summary.net',
field: (row) => row.net, field: (row) => row.net,
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'stems', name: 'stems',
label: 'invoicein.summary.stems', label: 'invoiceIn.summary.stems',
field: (row) => row.stems, field: (row) => row.stems,
format: (value) => value, format: (value) => value,
sortable: true, sortable: true,
@ -146,7 +146,7 @@ const intrastatColumns = ref([
}, },
{ {
name: 'landed', name: 'landed',
label: 'invoicein.summary.country', label: 'invoiceIn.summary.country',
field: (row) => row.country?.code, field: (row) => row.country?.code,
format: (value) => value, format: (value) => value,
sortable: true, sortable: true,
@ -214,7 +214,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
/> />
</QCardSection> </QCardSection>
<VnLv <VnLv
:label="t('invoicein.list.supplier')" :label="t('invoiceIn.list.supplier')"
:value="entity.supplier?.name" :value="entity.supplier?.name"
> >
<template #value> <template #value>
@ -225,14 +225,14 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</template> </template>
</VnLv> </VnLv>
<VnLv <VnLv
:label="t('invoicein.list.supplierRef')" :label="t('invoiceIn.list.supplierRef')"
:value="entity.supplierRef" :value="entity.supplierRef"
/> />
<VnLv <VnLv
:label="t('invoicein.summary.currency')" :label="t('invoiceIn.summary.currency')"
:value="entity.currency?.code" :value="entity.currency?.code"
/> />
<VnLv :label="t('invoicein.serial')" :value="`${entity.serial}`" /> <VnLv :label="t('invoiceIn.serial')" :value="`${entity.serial}`" />
<VnLv <VnLv
:label="t('globals.country')" :label="t('globals.country')"
:value="entity.supplier?.country?.code" :value="entity.supplier?.country?.code"
@ -247,19 +247,19 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</QCardSection> </QCardSection>
<VnLv <VnLv
:ellipsis-value="false" :ellipsis-value="false"
:label="t('invoicein.summary.issued')" :label="t('invoiceIn.summary.issued')"
:value="toDate(entity.issued)" :value="toDate(entity.issued)"
/> />
<VnLv <VnLv
:label="t('invoicein.summary.operated')" :label="t('invoiceIn.summary.operated')"
:value="toDate(entity.operated)" :value="toDate(entity.operated)"
/> />
<VnLv <VnLv
:label="t('invoicein.summary.bookEntried')" :label="t('invoiceIn.summary.bookEntried')"
:value="toDate(entity.bookEntried)" :value="toDate(entity.bookEntried)"
/> />
<VnLv <VnLv
:label="t('invoicein.summary.bookedDate')" :label="t('invoiceIn.summary.bookedDate')"
:value="toDate(entity.booked)" :value="toDate(entity.booked)"
/> />
<VnLv :label="t('globals.isVies')" :value="entity.supplier?.isVies" /> <VnLv :label="t('globals.isVies')" :value="entity.supplier?.isVies" />
@ -272,18 +272,18 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
/> />
</QCardSection> </QCardSection>
<VnLv <VnLv
:label="t('invoicein.summary.sage')" :label="t('invoiceIn.summary.sage')"
:value="entity.sageWithholding?.withholding" :value="entity.sageWithholding?.withholding"
/> />
<VnLv <VnLv
:label="t('invoicein.summary.vat')" :label="t('invoiceIn.summary.vat')"
:value="entity.expenseDeductible?.name" :value="entity.expenseDeductible?.name"
/> />
<VnLv <VnLv
:label="t('invoicein.card.company')" :label="t('invoiceIn.card.company')"
:value="entity.company?.code" :value="entity.company?.code"
/> />
<VnLv :label="t('invoicein.isBooked')" :value="invoiceIn?.isBooked" /> <VnLv :label="t('invoiceIn.isBooked')" :value="invoiceIn?.isBooked" />
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<QCardSection class="q-pa-none"> <QCardSection class="q-pa-none">
@ -294,11 +294,11 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</QCardSection> </QCardSection>
<QCardSection class="q-pa-none"> <QCardSection class="q-pa-none">
<VnLv <VnLv
:label="t('invoicein.summary.taxableBase')" :label="t('invoiceIn.summary.taxableBase')"
:value="toCurrency(entity.totals.totalTaxableBase)" :value="toCurrency(entity.totals.totalTaxableBase)"
/> />
<VnLv label="Total" :value="toCurrency(entity.totals.totalVat)" /> <VnLv label="Total" :value="toCurrency(entity.totals.totalVat)" />
<VnLv :label="t('invoicein.summary.dueTotal')"> <VnLv :label="t('invoiceIn.summary.dueTotal')">
<template #value> <template #value>
<QChip <QChip
dense dense
@ -306,8 +306,8 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
:color="amountsNotMatch ? 'negative' : 'transparent'" :color="amountsNotMatch ? 'negative' : 'transparent'"
:title=" :title="
amountsNotMatch amountsNotMatch
? t('invoicein.summary.noMatch') ? t('invoiceIn.summary.noMatch')
: t('invoicein.summary.dueTotal') : t('invoiceIn.summary.dueTotal')
" "
> >
{{ toCurrency(entity.totals.totalDueDay) }} {{ toCurrency(entity.totals.totalDueDay) }}
@ -318,7 +318,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</QCard> </QCard>
<!--Vat--> <!--Vat-->
<QCard v-if="entity.invoiceInTax.length" class="vat"> <QCard v-if="entity.invoiceInTax.length" class="vat">
<VnTitle :url="getLink('vat')" :text="t('invoicein.card.vat')" /> <VnTitle :url="getLink('vat')" :text="t('invoiceIn.card.vat')" />
<QTable <QTable
:columns="vatColumns" :columns="vatColumns"
:rows="entity.invoiceInTax" :rows="entity.invoiceInTax"
@ -366,7 +366,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</QCard> </QCard>
<!--Due Day--> <!--Due Day-->
<QCard v-if="entity.invoiceInDueDay.length" class="due-day"> <QCard v-if="entity.invoiceInDueDay.length" class="due-day">
<VnTitle :url="getLink('due-day')" :text="t('invoicein.card.dueDay')" /> <VnTitle :url="getLink('due-day')" :text="t('invoiceIn.card.dueDay')" />
<QTable :columns="dueDayColumns" :rows="entity.invoiceInDueDay" flat> <QTable :columns="dueDayColumns" :rows="entity.invoiceInDueDay" flat>
<template #header="dueDayProps"> <template #header="dueDayProps">
<QTr :props="dueDayProps" class="bg"> <QTr :props="dueDayProps" class="bg">
@ -404,7 +404,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
<QCard v-if="entity.invoiceInIntrastat.length"> <QCard v-if="entity.invoiceInIntrastat.length">
<VnTitle <VnTitle
:url="getLink('intrastat')" :url="getLink('intrastat')"
:text="t('invoicein.card.intrastat')" :text="t('invoiceIn.card.intrastat')"
/> />
<QTable <QTable
:columns="intrastatColumns" :columns="intrastatColumns"

View File

@ -68,7 +68,7 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
:rules="validate('entry.supplierFk')" :rules="validate('entry.supplierFk')"
/> />
<VnInput <VnInput
:label="t('invoicein.list.supplierRef')" :label="t('invoiceIn.list.supplierRef')"
v-model="data.supplierRef" v-model="data.supplierRef"
/> />
</VnRow> </VnRow>
@ -82,10 +82,10 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
map-options map-options
hide-selected hide-selected
:required="true" :required="true"
:rules="validate('invoicein.companyFk')" :rules="validate('invoiceIn.companyFk')"
/> />
<VnInputDate <VnInputDate
:label="t('invoicein.summary.issued')" :label="t('invoiceIn.summary.issued')"
v-model="data.issued" v-model="data.issued"
/> />
</VnRow> </VnRow>

View File

@ -148,7 +148,7 @@ function handleDaysAgo(params, daysAgo) {
<QItem> <QItem>
<QItemSection> <QItemSection>
<QCheckbox <QCheckbox
:label="$t('invoicein.isBooked')" :label="$t('invoiceIn.isBooked')"
v-model="params.isBooked" v-model="params.isBooked"
@update:model-value="searchFn()" @update:model-value="searchFn()"
toggle-indeterminate toggle-indeterminate

View File

@ -8,18 +8,18 @@ import InvoiceInFilter from './InvoiceInFilter.vue';
import InvoiceInSummary from './Card/InvoiceInSummary.vue'; import InvoiceInSummary from './Card/InvoiceInSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue'; import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import InvoiceInSearchbar from 'src/pages/InvoiceIn/InvoiceInSearchbar.vue';
import VnTable from 'src/components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import VnSection from 'src/components/common/VnSection.vue';
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue'; import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
const user = useState().getUser(); const user = useState().getUser();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const { t } = useI18n(); const { t } = useI18n();
const dataKey = 'InvoiceInList';
const tableRef = ref(); const tableRef = ref();
const companies = ref([]); const companies = ref([]);
@ -27,7 +27,7 @@ const cols = computed(() => [
{ {
align: 'left', align: 'left',
name: 'isBooked', name: 'isBooked',
label: t('invoicein.isBooked'), label: t('invoiceIn.isBooked'),
columnFilter: false, columnFilter: false,
}, },
{ {
@ -42,7 +42,7 @@ const cols = computed(() => [
{ {
align: 'left', align: 'left',
name: 'supplierFk', name: 'supplierFk',
label: t('invoicein.list.supplier'), label: t('invoiceIn.list.supplier'),
columnFilter: { columnFilter: {
component: 'select', component: 'select',
attrs: { attrs: {
@ -56,16 +56,16 @@ const cols = computed(() => [
{ {
align: 'left', align: 'left',
name: 'supplierRef', name: 'supplierRef',
label: t('invoicein.list.supplierRef'), label: t('invoiceIn.list.supplierRef'),
}, },
{ {
align: 'left', align: 'left',
name: 'serial', name: 'serial',
label: t('invoicein.serial'), label: t('invoiceIn.serial'),
}, },
{ {
align: 'left', align: 'left',
label: t('invoicein.list.issued'), label: t('invoiceIn.list.issued'),
name: 'issued', name: 'issued',
component: null, component: null,
columnFilter: { columnFilter: {
@ -75,7 +75,7 @@ const cols = computed(() => [
}, },
{ {
align: 'left', align: 'left',
label: t('invoicein.list.dueDated'), label: t('invoiceIn.list.dueDated'),
name: 'dueDated', name: 'dueDated',
component: null, component: null,
columnFilter: { columnFilter: {
@ -87,12 +87,12 @@ const cols = computed(() => [
{ {
align: 'left', align: 'left',
name: 'awbCode', name: 'awbCode',
label: t('invoicein.list.awb'), label: t('invoiceIn.list.awb'),
}, },
{ {
align: 'left', align: 'left',
name: 'amount', name: 'amount',
label: t('invoicein.list.amount'), label: t('invoiceIn.list.amount'),
format: ({ amount }) => toCurrency(amount), format: ({ amount }) => toCurrency(amount),
cardVisible: true, cardVisible: true,
}, },
@ -131,14 +131,23 @@ const cols = computed(() => [
}, },
]); ]);
</script> </script>
<template> <template>
<FetchData url="Companies" @on-fetch="(data) => (companies = data)" auto-load /> <FetchData url="Companies" @on-fetch="(data) => (companies = data)" auto-load />
<InvoiceInSearchbar /> <VnSection
<RightMenu> :data-key
<template #right-panel> :columns="cols"
<InvoiceInFilter data-key="InvoiceInList" /> prefix="invoiceIn"
:array-data-props="{
url: 'InvoiceIns/filter',
order: ['issued DESC', 'id DESC'],
}"
>
<template #advanced-menu>
<InvoiceInFilter :data-key />
</template> </template>
</RightMenu> </RightMenu>
<template #body>
<VnTable <VnTable
ref="tableRef" ref="tableRef"
data-key="InvoiceInList" data-key="InvoiceInList"
@ -163,7 +172,25 @@ const cols = computed(() => [
</span> </span>
</template> </template>
<template #more-create-dialog="{ data }"> <template #more-create-dialog="{ data }">
<VnSelectSupplier v-model="data.supplierFk" hide-selected :required="true" /> <VnSelect
v-model="data.supplierFk"
url="Suppliers"
:fields="['id', 'nickname', 'name']"
:label="t('globals.supplier')"
option-value="id"
option-label="nickname"
:filter-options="['id', 'name', 'nickname']"
:required="true"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.nickname }}</QItemLabel>
<QItemLabel caption> #{{ scope.opt?.id }}, {{ scope.opt?.name }} </QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInput <VnInput
:label="t('invoicein.list.supplierRef')" :label="t('invoicein.list.supplierRef')"
v-model="data.supplierRef" v-model="data.supplierRef"
@ -179,5 +206,7 @@ const cols = computed(() => [
/> />
<VnInputDate :label="t('invoicein.summary.issued')" v-model="data.issued" /> <VnInputDate :label="t('invoicein.summary.issued')" v-model="data.issued" />
</template> </template>
</VnTable> </VnTable>
</template>
</VnSection>
</template> </template>

View File

@ -1,18 +0,0 @@
<script setup>
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
</script>
<template>
<VnSearchbar
data-key="InvoiceInList"
:label="t('Search invoice')"
:info="t('Search invoices in by id or supplier fiscal name')"
url="InvoiceIns/filter"
/>
</template>
<i18n>
es:
Search invoice: Buscar factura recibida
Search invoices in by id or supplier fiscal name: Buscar facturas recibidas por id o por nombre fiscal del proveedor
</i18n>

View File

@ -1,4 +1,6 @@
invoicein: invoiceIn:
search: Search invoice
searchInfo: Search incoming invoices by ID or supplier fiscal name
serial: Serial serial: Serial
isBooked: Is booked isBooked: Is booked
list: list:

View File

@ -1,4 +1,6 @@
invoicein: invoiceIn:
search: Buscar factura recibida
searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
serial: Serie serial: Serie
isBooked: Contabilizada isBooked: Contabilizada
list: list:
@ -63,6 +65,7 @@ invoicein:
params: params:
search: Id o nombre proveedor search: Id o nombre proveedor
correctedFk: Rectificada correctedFk: Rectificada
isBooked: Contabilizada
account: Cuenta contable account: Cuenta contable
correctingFk: Rectificativa correctingFk: Rectificativa

View File

@ -62,6 +62,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
:subtitle="data.subtitle" :subtitle="data.subtitle"
@on-fetch="setData" @on-fetch="setData"
data-key="invoiceOutData" data-key="invoiceOutData"
width="lg-width"
> >
<template #menu="{ entity, menuRef }"> <template #menu="{ entity, menuRef }">
<InvoiceOutDescriptorMenu :invoice-out-data="entity" :menu-ref="menuRef" /> <InvoiceOutDescriptorMenu :invoice-out-data="entity" :menu-ref="menuRef" />

View File

@ -13,10 +13,9 @@ import axios from 'axios';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const itemTagsRef = ref(null); const itemTagsRef = ref();
const tagOptions = ref([]); const tagOptions = ref([]);
const valueOptionsMap = ref(new Map()); const valueOptionsMap = ref(new Map());
const getSelectedTagValues = async (tag) => { const getSelectedTagValues = async (tag) => {
if (!tag.tagFk && tag.tag.isFree) return; if (!tag.tagFk && tag.tag.isFree) return;
const filter = { const filter = {
@ -59,10 +58,6 @@ const insertTag = (rows) => {
itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority = itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority =
getHighestPriority(rows); getHighestPriority(rows);
}; };
const submitTags = async (data) => {
itemTagsRef.value.onSubmit(data);
};
</script> </script>
<template> <template>
@ -149,7 +144,7 @@ const submitTags = async (data) => {
v-model="row.value" v-model="row.value"
:label="t('itemTags.value')" :label="t('itemTags.value')"
:is-clearable="false" :is-clearable="false"
@keyup.enter.stop="submitTags(row)" @keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
/> />
<VnInput <VnInput
:label="t('itemBasicData.relevancy')" :label="t('itemBasicData.relevancy')"
@ -157,7 +152,7 @@ const submitTags = async (data) => {
v-model="row.priority" v-model="row.priority"
:required="true" :required="true"
:rules="validate('itemTag.priority')" :rules="validate('itemTag.priority')"
@keyup.enter.stop="submitTags(row)" @keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
/> />
<div class="row justify-center" style="flex: 0"> <div class="row justify-center" style="flex: 0">
<QIcon <QIcon
@ -197,4 +192,5 @@ const submitTags = async (data) => {
<i18n> <i18n>
es: es:
Tags can not be repeated: Las etiquetas no pueden repetirse Tags can not be repeated: Las etiquetas no pueden repetirse
The value must be a number or a range of numbers: El valor debe ser un número o un rango de números
</i18n> </i18n>

View File

@ -272,11 +272,12 @@ const onDenyAccept = (_, responseData) => {
<template #column-achieved="{ row }"> <template #column-achieved="{ row }">
<span> <span>
<VnInput <VnInput
ref="achievedRef"
type="number" type="number"
v-model.number="row.saleQuantity" v-model.number="row.saleQuantity"
:disable="!row.itemFk || row.isOk != null" :disable="!row.itemFk || row.isOk != null"
@blur="changeQuantity(row)" @blur="changeQuantity(row)"
@keyup.enter="changeQuantity(row)" @keyup.enter="$refs.achievedRef.vnInputRef.blur()"
dense dense
/> />
</span> </span>

View File

@ -2,11 +2,12 @@
import { computed } from 'vue'; import { computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n(); const { t } = useI18n();
const router = useRouter(); const router = useRouter();
const dataKey = 'AgencyList';
function navigate(id) { function navigate(id) {
router.push({ path: `/agency/${id}` }); router.push({ path: `/agency/${id}` });
} }
@ -67,26 +68,28 @@ const columns = computed(() => [
]); ]);
</script> </script>
<template> <template>
<VnSearchbar <VnSection
:info="t('You can search by name')" :data-key
:label="t('Search agency')" :columns="columns"
data-key="AgencyList" prefix="agency"
:expr-builder="exprBuilder" :right-filter="false"
/> :array-data-props="{
<div class="list-container"> url: 'Agencies',
<div class="list"> order: 'name',
exprBuilder,
}"
>
<template #body>
<VnTable <VnTable
data-key="AgencyList" :data-key
url="Agencies"
order="name"
:columns="columns" :columns="columns"
:right-search="false" :right-search="false"
:use-model="true" :use-model="true"
redirect="agency" redirect="route/agency"
default-mode="card" default-mode="card"
/> />
</div> </template>
</div> </VnSection>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.list { .list {
@ -104,8 +107,6 @@ const columns = computed(() => [
es: es:
isOwn: Tiene propietario isOwn: Tiene propietario
isAnyVolumeAllowed: Permite cualquier volumen isAnyVolumeAllowed: Permite cualquier volumen
Search agency: Buscar agencia
You can search by name: Puedes buscar por nombre
en: en:
isOwn: Has owner isOwn: Has owner
isAnyVolumeAllowed: Allows any volume isAnyVolumeAllowed: Allows any volume

View File

@ -1,17 +1,7 @@
<script setup> <script setup>
import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue'; import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
import VnCard from 'components/common/VnCard.vue'; import VnCardBeta from 'src/components/common/VnCardBeta.vue';
</script> </script>
<template> <template>
<VnCard <VnCardBeta data-key="Agency" base-url="Agencies" :descriptor="AgencyDescriptor" />
data-key="Agency"
base-url="Agencies"
:descriptor="AgencyDescriptor"
search-data-key="AgencyList"
:searchbar-props="{
url: 'Agencies',
label: 'agency.searchBar.label',
info: 'agency.searchBar.info',
}"
/>
</template> </template>

View File

@ -0,0 +1,55 @@
import { describe, it, expect, vi, afterEach } from 'vitest';
import axios from 'axios';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
vi.mock('axios');
describe('getAgencies', () => {
afterEach(() => {
vi.clearAllMocks();
});
const generateParams = (formData) => ({
params: {
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
},
});
it('should fetch agencies data with correct parameters for valid formData', async () => {
const formData = {
warehouseId: '123',
addressId: '456',
landed: 'true',
};
await getAgencies(formData);
expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData));
});
it('should not call API when formData is missing required landed field', async () => {
const formData = { warehouseId: '123', addressId: '456' };
await getAgencies(formData);
expect(axios.get).not.toHaveBeenCalled();
});
it('should not call API when formData is missing required addressId field', async () => {
const formData = { warehouseId: '123', landed: 'true' };
await getAgencies(formData);
expect(axios.get).not.toHaveBeenCalled();
});
it('should not call API when formData is missing required warehouseId field', async () => {
const formData = { addressId: '456', landed: 'true' };
await getAgencies(formData);
expect(axios.get).not.toHaveBeenCalled();
});
});

View File

@ -0,0 +1,12 @@
import axios from 'axios';
export async function getAgencies(formData) {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return;
let params = {
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
};
return await axios.get('Agencies/getAgenciesWithWarehouse', { params });
}

View File

@ -1,4 +1,6 @@
agency: agency:
search: Search agency
searchInfo: You can search by name
isOwn: Own isOwn: Own
isAnyVolumeAllowed: Any volume allowed isAnyVolumeAllowed: Any volume allowed
notification: notification:

View File

@ -1,4 +1,6 @@
agency: agency:
search: Buscar agencia
searchInfo: Puedes buscar por nombre
isOwn: Propio isOwn: Propio
isAnyVolumeAllowed: Cualquier volumen isAnyVolumeAllowed: Cualquier volumen
removeItem: Agencia eliminada correctamente removeItem: Agencia eliminada correctamente

View File

@ -1,19 +1,8 @@
<script setup> <script setup>
import VnCard from 'components/common/VnCard.vue';
import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue'; import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
import RouteFilter from './RouteFilter.vue'; import VnCardBeta from 'src/components/common/VnCardBeta.vue';
import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue';
</script> </script>
<template> <template>
<VnCard <VnCardBeta data-key="Route" base-url="Routes" :descriptor="RouteDescriptor" />
data-key="Route"
base-url="Routes"
:descriptor="RouteDescriptor"
:filter-panel="RouteFilter"
search-data-key="RouteList"
>
<template #searchbar>
<RouteSearchbar />
</template>
</VnCard>
</template> </template>

View File

@ -76,6 +76,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
:subtitle="data.subtitle" :subtitle="data.subtitle"
data-key="routeData" data-key="routeData"
@on-fetch="setData" @on-fetch="setData"
width="lg-width"
> >
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('Date')" :value="toDate(entity?.dated)" /> <VnLv :label="t('Date')" :value="toDate(entity?.dated)" />

View File

@ -1,19 +1,7 @@
<script setup> <script setup>
import VnCard from 'components/common/VnCard.vue'; import VnCardBeta from 'components/common/VnCardBeta.vue';
import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue'; import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue';
import RoadmapFilter from 'pages/Route/Roadmap/RoadmapFilter.vue';
</script> </script>
<template> <template>
<VnCard <VnCardBeta data-key="Roadmap" base-url="Roadmaps" :descriptor="RoadmapDescriptor" />
data-key="Roadmap"
base-url="Roadmaps"
:descriptor="RoadmapDescriptor"
:filter-panel="RoadmapFilter"
search-data-key="RoadmapList"
:searchbar-props="{
url: 'Roadmaps',
label: 'Search roadmap',
info: 'You can search by roadmap id or customer name',
}"
/>
</template> </template>

View File

@ -17,6 +17,7 @@ const props = defineProps({
const emit = defineEmits(['search']); const emit = defineEmits(['search']);
const supplierList = ref([]);
const exprBuilder = (param, value) => { const exprBuilder = (param, value) => {
switch (param) { switch (param) {
case 'tractorPlate': case 'tractorPlate':
@ -39,7 +40,6 @@ const exprBuilder = (param, value) => {
<VnFilterPanel <VnFilterPanel
:data-key="props.dataKey" :data-key="props.dataKey"
:search-button="true" :search-button="true"
:expr-builder="exprBuilder"
@search="emit('search')" @search="emit('search')"
> >
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">

View File

@ -3,17 +3,16 @@ import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { toHour } from 'src/filters'; import { toHour } from 'src/filters';
import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue';
import RouteSummary from 'pages/Route/Card/RouteSummary.vue'; import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue'; import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const tableRef = ref([]); const tableRef = ref([]);
const dataKey = 'RouteList';
const routeFilter = { const routeFilter = {
include: [ include: [
{ {
@ -110,32 +109,39 @@ const columns = computed(() => [
]); ]);
</script> </script>
<template> <template>
<RouteSearchbar /> <VnSection
<RightMenu> :data-key
<template #right-panel>
<RouteFilter data-key="RouteList" />
</template>
</RightMenu>
<VnTable
data-key="RouteList"
url="Routes/filter"
:columns="columns" :columns="columns"
:right-search="false" prefix="route"
:filter="routeFilter" :array-data-props="{
redirect="route" url: 'Routes/filter',
:create="{ userFilter: routeFilter,
urlCreate: 'Routes',
title: t('route.createRoute'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}" }"
table-height="85vh"
> >
<template #column-workerFk="{ row }"> <template #advanced-menu>
<span class="link" @click.stop> <RouteFilter :data-key />
{{ row?.workerUserName }}
<WorkerDescriptorProxy :id="row?.workerFk" v-if="row?.workerFk" />
</span>
</template> </template>
</VnTable> <template #body>
<VnTable
:data-key
:columns="columns"
:right-search="false"
redirect="route"
:create="{
urlCreate: 'Routes',
title: t('route.createRoute'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
table-height="85vh"
>
<template #column-workerFk="{ row }">
<span class="link" @click.stop>
{{ row?.workerUserName }}
<WorkerDescriptorProxy :id="row?.workerFk" v-if="row?.workerFk" />
</span>
</template>
</VnTable>
</template>
</VnSection>
</template> </template>

View File

@ -15,11 +15,14 @@ import RoadmapSummary from 'pages/Route/Roadmap/RoadmapSummary.vue';
import VnConfirm from 'components/ui/VnConfirm.vue'; import VnConfirm from 'components/ui/VnConfirm.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'src/components/common/VnInputTime.vue'; import VnInputTime from 'src/components/common/VnInputTime.vue';
import VnSection from 'src/components/common/VnSection.vue';
import RoadmapFilter from './Roadmap/RoadmapFilter.vue';
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const { t } = useI18n(); const { t } = useI18n();
const quasar = useQuasar(); const quasar = useQuasar();
const selectedRows = ref([]); const selectedRows = ref([]);
const dataKey = 'RoadmapList';
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left', align: 'left',
@ -128,14 +131,28 @@ function confirmRemove() {
}) })
.onOk(() => tableRef.value++); .onOk(() => tableRef.value++);
} }
function exprBuilder(param, value) {
switch (param) {
case 'search':
return /^\d+$/.test(value) ? { id: value } : { name: { like: `%${value}%` } };
case 'tractorPlate':
case 'trailerPlate':
case 'driverName':
case 'phone':
return { [param]: { like: `%${value}%` } };
case 'supplierFk':
case 'price':
return { [param]: value };
case 'from':
return { etd: { gte: value } };
case 'to':
return { etd: { lte: value } };
}
}
</script> </script>
<template> <template>
<VnSearchbar
data-key="RoadmapList"
:label="t('Search roadmaps')"
:info="t('You can search by roadmap reference')"
/>
<QDialog v-model="isCloneDialogOpen"> <QDialog v-model="isCloneDialogOpen">
<QCard style="min-width: 350px"> <QCard style="min-width: 350px">
<QCardSection> <QCardSection>
@ -177,39 +194,53 @@ function confirmRemove() {
</QBtn> </QBtn>
</template> </template>
</VnSubToolbar> </VnSubToolbar>
<VnTable <VnSection
ref="tableRef" :data-key
data-key="RoadmapList"
url="roadmaps"
:columns="columns" :columns="columns"
:right-search="true" prefix="route.roadmap"
:use-model="true" :array-data-props="{
default-mode="table" url: 'roadmaps',
v-model:selected="selectedRows" exprBuilder,
table-height="85vh"
:table="{
selection: 'multiple',
}" }"
redirect="route/roadmap"
:create="{
urlCreate: 'Roadmaps',
title: t('Create routemap'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
:disable-option="{ card: true }"
> >
<template #column-etd="{ row }"> <template #advanced-menu>
{{ toDateHourMin(row.etd) }} <RoadmapFilter :dataKey />
</template> </template>
<template #column-supplierFk="{ row }"> <template #body>
{{ row.supplierFk }} <VnTable
ref="tableRef"
:data-key
:columns="columns"
:right-search="false"
:use-model="true"
default-mode="table"
v-model:selected="selectedRows"
table-height="85vh"
:table="{
selection: 'multiple',
}"
redirect="route/roadmap"
:create="{
urlCreate: 'Roadmaps',
title: t('Create routemap'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
:disable-option="{ card: true }"
>
<template #column-etd="{ row }">
{{ toDateHourMin(row.etd) }}
</template>
<template #column-supplierFk="{ row }">
{{ row.supplierFk }}
</template>
<template #more-create-dialog="{ data }">
<VnInputDate v-model="data.etd" />
<VnInputTime v-model="data.etd" />
</template>
</VnTable>
</template> </template>
<template #more-create-dialog="{ data }"> </VnSection>
<VnInputDate v-model="data.etd" />
<VnInputTime v-model="data.etd" />
</template>
</VnTable>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,4 +1,7 @@
route: route:
roadmap:
search: Search roadmap
searchInfo: You can search by roadmap reference
params: params:
etd: ETD etd: ETD
tractorPlate: Plate tractorPlate: Plate
@ -36,6 +39,8 @@ route:
Summary: Summary Summary: Summary
Route is closed: Route is closed Route is closed: Route is closed
Route is not served: Route is not served Route is not served: Route is not served
search: Search route
searchInfo: You can search by route reference
cmr: cmr:
list: list:
results: results results: results
@ -49,4 +54,4 @@ route:
clientFk: Client id clientFk: Client id
shipped: Preparation date shipped: Preparation date
viewCmr: View CMR viewCmr: View CMR
downloadCmrs: Download CMRs downloadCmrs: Download CMRs

View File

@ -1,4 +1,7 @@
route: route:
roadmap:
search: Buscar troncales
searchInfo: Puedes buscar por referencia del troncal
params: params:
agencyModeName: Agencia Ruta agencyModeName: Agencia Ruta
agencyAgreement: Agencia Acuerdo agencyAgreement: Agencia Acuerdo
@ -37,6 +40,8 @@ route:
Summary: Resumen Summary: Resumen
Route is closed: La ruta está cerrada Route is closed: La ruta está cerrada
Route is not served: La ruta no está servida Route is not served: La ruta no está servida
search: Buscar rutas
searchInfo: Puedes buscar por referencia de la ruta
cmr: cmr:
list: list:
results: resultados results: resultados
@ -50,4 +55,4 @@ route:
clientFk: Id cliente clientFk: Id cliente
shipped: Fecha preparación shipped: Fecha preparación
viewCmr: Ver CMR viewCmr: Ver CMR
downloadCmrs: Descargar CMRs downloadCmrs: Descargar CMRs

View File

@ -36,7 +36,7 @@ const companySizes = [
/> />
<VnSelectWorker <VnSelectWorker
v-model="data.workerFk" v-model="data.workerFk"
has-info="Responsible for approving invoices" info="Responsible for approving invoices"
:rules="validate('supplier.workerFk')" :rules="validate('supplier.workerFk')"
/> />
<VnSelect <VnSelect

View File

@ -94,7 +94,7 @@ function handleLocation(data, location) {
<VnInput <VnInput
v-model="data.name" v-model="data.name"
:label="t('supplier.fiscalData.name')" :label="t('supplier.fiscalData.name')"
uppercase="true" :uppercase="true"
clearable clearable
/> />
<VnInput <VnInput

View File

@ -16,6 +16,10 @@ const $props = defineProps({
required: false, required: false,
default: null, default: null,
}, },
summary: {
type: Object,
default: null,
},
}); });
const route = useRoute(); const route = useRoute();
@ -102,6 +106,10 @@ const data = ref(useCardDescription());
function ticketFilter(ticket) { function ticketFilter(ticket) {
return JSON.stringify({ clientFk: ticket.clientFk }); return JSON.stringify({ clientFk: ticket.clientFk });
} }
const setData = (entity) => {
data.value = useCardDescription(entity.ref, entity.id);
};
</script> </script>
<template> <template>
@ -111,7 +119,10 @@ function ticketFilter(ticket) {
:filter="filter" :filter="filter"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
@on-fetch="setData"
:summary="$props.summary"
data-key="ticketData" data-key="ticketData"
width="lg-width"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<TicketDescriptorMenu :ticket="entity" /> <TicketDescriptorMenu :ticket="entity" />
@ -157,7 +168,7 @@ function ticketFilter(ticket) {
<VnLv :label="t('globals.alias')" :value="entity.nickname" /> <VnLv :label="t('globals.alias')" :value="entity.nickname" />
</template> </template>
<template #icons="{ entity }"> <template #icons="{ entity }">
<QCardActions class="q-gutter-x-xs"> <QCardActions class="q-gutter-x-md">
<QIcon <QIcon
v-if="entity.client.isActive == false" v-if="entity.client.isActive == false"
name="vn:disabled" name="vn:disabled"
@ -201,7 +212,7 @@ function ticketFilter(ticket) {
</QCardActions> </QCardActions>
</template> </template>
<template #actions="{ entity }"> <template #actions="{ entity }">
<QCardActions> <QCardActions class="flex justify-center" style="padding-inline: 0">
<QBtn <QBtn
size="md" size="md"
icon="vn:client" icon="vn:client"

View File

@ -16,6 +16,8 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
import { useAcl } from 'src/composables/useAcl'; import { useAcl } from 'src/composables/useAcl';
import VnInputNumber from 'src/components/common/VnInputNumber.vue'; import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import { useArrayData } from 'src/composables/useArrayData'; import { useArrayData } from 'src/composables/useArrayData';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
import { getClient } from 'src/pages/Customer/composables/getClient';
const props = defineProps({ const props = defineProps({
ticket: { ticket: {
@ -40,7 +42,10 @@ const { openReport, sendEmail } = usePrintService();
const ticketSummary = useArrayData('TicketSummary'); const ticketSummary = useArrayData('TicketSummary');
const { ticket } = toRefs(props); const { ticket } = toRefs(props);
const ticketId = computed(() => props.ticket.id ?? currentRoute.value.params.id); const ticketId = computed(() => props.ticket.id ?? currentRoute.value.params.id);
const client = ref(); const client = ref(null);
const address = ref(null);
const addressesOptions = ref([]);
const selectedClient = ref();
const showTransferDialog = ref(false); const showTransferDialog = ref(false);
const showTurnDialog = ref(false); const showTurnDialog = ref(false);
const showChangeTimeDialog = ref(false); const showChangeTimeDialog = ref(false);
@ -52,6 +57,31 @@ const weight = ref();
const hasDocuwareFile = ref(); const hasDocuwareFile = ref();
const quasar = useQuasar(); const quasar = useQuasar();
const canRestoreTicket = ref(false); const canRestoreTicket = ref(false);
const onClientSelected = async(clientId) =>{
client.value = clientId;
await fetchClient();
await fetchAddresses();
};
const onAddressSelected = (addressId) => {
address.value = addressId;
}
const fetchClient = async () => {
const { data } = await getClient(client.value)
const [retrievedClient] = data;
selectedClient.value = retrievedClient;
};
const fetchAddresses = async () => {
const { data } = await getAddresses(client.value);
addressesOptions.value = data;
const { defaultAddress } = selectedClient.value;
address.value = defaultAddress.id;
};
const actions = { const actions = {
clone: async () => { clone: async () => {
const opts = { message: t('Ticket cloned'), type: 'positive' }; const opts = { message: t('Ticket cloned'), type: 'positive' };
@ -260,17 +290,14 @@ async function makeInvoice() {
window.location.reload(); window.location.reload();
} }
async function transferClient(client) { async function transferClient() {
const params = { const params = {
clientFk: client, clientFk: client.value,
addressFk: address.value,
}; };
const { data } = await axios.patch( await axios.patch( `Tickets/${ticketId.value}/transferClient`, params );
`Tickets/${ticketId.value}/transferClient`, window.location.reload();
params
);
if (data) window.location.reload();
} }
async function addTurn(day) { async function addTurn(day) {
@ -446,7 +473,7 @@ async function ticketToRestore() {
</QItem> </QItem>
<QDialog ref="dialogRef" v-model="showTransferDialog"> <QDialog ref="dialogRef" v-model="showTransferDialog">
<FormPopup <FormPopup
@on-submit="transferClient(client)" @on-submit="transferClient()"
:title="t('Transfer client')" :title="t('Transfer client')"
:custom-submit-button-label="t('Transfer client')" :custom-submit-button-label="t('Transfer client')"
:default-cancel-button="false" :default-cancel-button="false"
@ -454,10 +481,11 @@ async function ticketToRestore() {
<template #form-inputs> <template #form-inputs>
<VnSelect <VnSelect
url="Clients" url="Clients"
:fields="['id', 'name']" :fields="['id', 'name', 'defaultAddressFk']"
v-model="client" v-model="client"
:label="t('Client')" :label="t('Client')"
auto-load auto-load
@update:model-value="() => onClientSelected(client)"
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem v-bind="scope.itemProps">
@ -470,6 +498,29 @@ async function ticketToRestore() {
</QItem> </QItem>
</template> </template>
</VnSelect> </VnSelect>
<VnSelect
:disable="!client"
:options="addressesOptions"
:fields="['id', 'nickname']"
option-value="id"
option-label="nickname"
v-model="address"
:label="t('ticketList.addressNickname')"
auto-load
:hint="!client ? t('Select a client to enable') : ''"
@update:model-value="() => onAddressSelected(address)"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ `#${scope.opt.id} - ` }}
{{ scope.opt.nickname }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</template> </template>
</FormPopup> </FormPopup>
</QDialog> </QDialog>
@ -762,7 +813,7 @@ async function ticketToRestore() {
en: en:
addTurn: Add turn addTurn: Add turn
invoiceIds: "Invoices have been generated with the following ids: {invoiceIds}" invoiceIds: "Invoices have been generated with the following ids: {invoiceIds}"
es: es:
Show Delivery Note...: Ver albarán... Show Delivery Note...: Ver albarán...
Send Delivery Note...: Enviar albarán... Send Delivery Note...: Enviar albarán...
@ -814,4 +865,5 @@ es:
Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket? Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket?
You are going to restore this ticket: Vas a restaurar este ticket You are going to restore this ticket: Vas a restaurar este ticket
Ticket restored: Ticket restaurado Ticket restored: Ticket restaurado
Select a client to enable: Selecciona un cliente para habilitar
</i18n> </i18n>

View File

@ -6,7 +6,6 @@ import { useI18n } from 'vue-i18n';
import axios from 'axios'; import axios from 'axios';
import { dashIfEmpty, toDate, toCurrency } from 'src/filters'; import { dashIfEmpty, toDate, toCurrency } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import FetchData from 'components/FetchData.vue';
import FetchedTags from 'components/ui/FetchedTags.vue'; import FetchedTags from 'components/ui/FetchedTags.vue';
import InvoiceOutDescriptorProxy from 'pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue'; import InvoiceOutDescriptorProxy from 'pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
@ -29,15 +28,14 @@ const { t } = useI18n();
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
required: false,
default: null, default: null,
}, },
}); });
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const summaryRef = ref(); const summary = ref();
const ticket = computed(() => summaryRef.value?.entity); const ticket = computed(() => summary.value?.entity);
const editableStates = ref([]); const editableStates = ref([]);
const ticketUrl = ref(); const ticketUrl = ref();
const grafanaUrl = 'https://grafana.verdnatura.es'; const grafanaUrl = 'https://grafana.verdnatura.es';
@ -76,26 +74,27 @@ async function changeState(value) {
}; };
await axios.post(`Tickets/state`, formData); await axios.post(`Tickets/state`, formData);
notify('globals.dataSaved', 'positive'); notify('globals.dataSaved', 'positive');
summaryRef.value?.fetch(); summary.value?.fetch();
descriptorData.fetch({}); descriptorData.fetch({});
} }
function toTicketUrl(section) { function toTicketUrl(section) {
return '#/ticket/' + entityId.value + '/' + section; return '#/ticket/' + entityId.value + '/' + section;
} }
onMounted(async () => {
const filter = { fields: ['code', 'name', 'id', 'alertLevel'] };
const params = { filter: JSON.stringify(filter) };
editableStates.value = (await axios.get('States/editableStates', { params }))?.data;
});
</script> </script>
<template> <template>
<FetchData
url="States/editableStates"
:filter="{ fields: ['code', 'name', 'id', 'alertLevel'], order: 'name ASC' }"
auto-load
@on-fetch="(data) => (editableStates = data)"
/>
<CardSummary <CardSummary
ref="summaryRef" ref="summary"
:url="`Tickets/${entityId}/summary`" :url="`Tickets/${entityId}/summary`"
data-key="TicketSummary" data-key="TicketSummary"
v-bind="$attrs.width"
> >
<template #header-left> <template #header-left>
<VnToSummary <VnToSummary
@ -207,7 +206,7 @@ function toTicketUrl(section) {
</VnLv> </VnLv>
<VnLv :label="t('globals.weight')" :value="dashIfEmpty(entity.weight)" /> <VnLv :label="t('globals.weight')" :value="dashIfEmpty(entity.weight)" />
</QCard> </QCard>
<QCard class="vn-one" style="flex: 2 1"> <QCard class="vn-one">
<VnTitle <VnTitle
:url="toTicketUrl('basic-data')" :url="toTicketUrl('basic-data')"
:text="t('globals.summary.basicData')" :text="t('globals.summary.basicData')"
@ -454,7 +453,7 @@ function toTicketUrl(section) {
toCurrency( toCurrency(
props.row.quantity * props.row.quantity *
props.row.price * props.row.price *
((100 - props.row.discount) / 100) ((100 - props.row.discount) / 100),
) )
}} }}
</QTd> </QTd>

View File

@ -9,9 +9,11 @@ import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { getClient } from 'src/pages/Customer/composables/getClient';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
import { useState } from 'composables/useState'; import { useState } from 'composables/useState';
import axios from 'axios';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -37,33 +39,13 @@ onBeforeMount(async () => {
}); });
const fetchClient = async (formData) => { const fetchClient = async (formData) => {
const filter = { const { data } = await getClient(formData.clientId);
include: {
relation: 'defaultAddress',
scope: {
fields: ['id', 'agencyModeFk'],
},
},
where: { id: formData.clientId },
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get('Clients', { params });
const [client] = data; const [client] = data;
selectedClient.value = client; selectedClient.value = client;
}; };
const fetchAddresses = async (formData) => { const fetchAddresses = async (formData) => {
if (!formData.clientId) return; const { data } = await getAddresses(formData.clientId);
const filter = {
fields: ['nickname', 'street', 'city', 'id'],
where: { isActive: true },
order: 'nickname ASC',
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`Clients/${formData.clientId}/addresses`, {
params,
});
addressesOptions.value = data; addressesOptions.value = data;
const { defaultAddress } = selectedClient.value; const { defaultAddress } = selectedClient.value;
@ -76,15 +58,7 @@ const onClientSelected = async (formData) => {
}; };
const fetchAvailableAgencies = async (formData) => { const fetchAvailableAgencies = async (formData) => {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return; const { data } = await getAgencies(formData);
let params = {
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
};
const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params });
agenciesOptions.value = data; agenciesOptions.value = data;
const defaultAgency = agenciesOptions.value.find( const defaultAgency = agenciesOptions.value.find(

View File

@ -9,9 +9,11 @@ import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import { getClient } from 'src/pages/Customer/composables/getClient';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
import { useState } from 'composables/useState'; import { useState } from 'composables/useState';
import axios from 'axios';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -37,33 +39,13 @@ onBeforeMount(async () => {
}); });
const fetchClient = async (formData) => { const fetchClient = async (formData) => {
const filter = { const { data } = await getClient(formData.clientId);
include: {
relation: 'defaultAddress',
scope: {
fields: ['id', 'agencyModeFk'],
},
},
where: { id: formData.clientId },
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get('Clients', { params });
const [client] = data; const [client] = data;
selectedClient.value = client; selectedClient.value = client;
}; };
const fetchAddresses = async (formData) => { const fetchAddresses = async (formData) => {
if (!formData.clientId) return; const { data } = await getAddresses(formData.clientId);
const filter = {
fields: ['nickname', 'street', 'city', 'id'],
where: { isActive: true },
order: 'nickname ASC',
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`Clients/${formData.clientId}/addresses`, {
params,
});
addressesOptions.value = data; addressesOptions.value = data;
const { defaultAddress } = selectedClient.value; const { defaultAddress } = selectedClient.value;
@ -76,15 +58,7 @@ const onClientSelected = async (formData) => {
}; };
const fetchAvailableAgencies = async (formData) => { const fetchAvailableAgencies = async (formData) => {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return; const { data } = await getAgencies(formData);
let params = {
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
};
const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params });
agenciesOptions.value = data; agenciesOptions.value = data;
const defaultAgency = agenciesOptions.value.find( const defaultAgency = agenciesOptions.value.find(

View File

@ -22,6 +22,9 @@ import { toTimeFormat } from 'src/filters/date';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue'; import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
import TicketProblems from 'src/components/TicketProblems.vue'; import TicketProblems from 'src/components/TicketProblems.vue';
import VnSection from 'src/components/common/VnSection.vue'; import VnSection from 'src/components/common/VnSection.vue';
import { getClient } from 'src/pages/Customer/composables/getClient';
import { getAddresses } from 'src/pages/Customer/composables/getAddresses';
import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -237,15 +240,7 @@ const onClientSelected = async (formData) => {
}; };
const fetchAvailableAgencies = async (formData) => { const fetchAvailableAgencies = async (formData) => {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return; const { data } = await getAgencies(formData);
let params = {
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,
landed: formData.landed,
};
const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params });
agenciesOptions.value = data; agenciesOptions.value = data;
const defaultAgency = agenciesOptions.value.find( const defaultAgency = agenciesOptions.value.find(
@ -257,34 +252,13 @@ const fetchAvailableAgencies = async (formData) => {
}; };
const fetchClient = async (formData) => { const fetchClient = async (formData) => {
const filter = { const { data } = await getClient(formData.clientId);
include: {
relation: 'defaultAddress',
scope: {
fields: ['id', 'agencyModeFk'],
},
},
where: { id: formData.clientId },
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get('Clients', { params });
const [client] = data; const [client] = data;
selectedClient.value = client; selectedClient.value = client;
}; };
const fetchAddresses = async (formData) => { const fetchAddresses = async (formData) => {
if (!formData.clientId) return; const { data } = await getAddresses(formData.clientId);
const filter = {
fields: ['nickname', 'street', 'city', 'id', 'isActive'],
order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`Clients/${formData.clientId}/addresses`, {
params,
});
addressesOptions.value = data;
addressesOptions.value = data; addressesOptions.value = data;
const { defaultAddress } = selectedClient.value; const { defaultAddress } = selectedClient.value;

View File

@ -1,91 +1,112 @@
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
const agencyCard = {
path: ':id',
name: 'AgencyCard',
component: () => import('src/pages/Route/Agency/Card/AgencyCard.vue'),
redirect: { name: 'AgencySummary' },
meta: {
menu: ['AgencyBasicData', 'AgencyModes', 'AgencyWorkCenters', 'AgencyLog'],
},
children: [
{
name: 'AgencySummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'view_list',
},
component: () => import('src/pages/Route/Agency/Card/AgencySummary.vue'),
},
{
name: 'AgencyBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Agency/Card/AgencyBasicData.vue'),
},
{
path: 'workCenter',
name: 'AgencyWorkCenterCard',
redirect: { name: 'AgencyWorkCenters' },
children: [
{
path: '',
name: 'AgencyWorkCenters',
meta: {
icon: 'apartment',
title: 'workCenters',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencyWorkcenter.vue'),
},
],
},
{
path: 'modes',
name: 'AgencyModesCard',
redirect: { name: 'AgencyModes' },
children: [
{
path: '',
name: 'AgencyModes',
meta: {
icon: 'format_list_bulleted',
title: 'modes',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencyModes.vue'),
},
],
},
{
name: 'AgencyLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Route/Agency/Card/AgencyLog.vue'),
},
],
};
export default { export default {
path: '/agency',
name: 'Agency', name: 'Agency',
path: '/agency',
meta: { meta: {
title: 'agency', title: 'agency',
icon: 'garage_home', icon: 'garage_home',
moduleName: 'Agency', moduleName: 'Agency',
}, },
component: RouterView, component: RouterView,
redirect: { name: 'AgencyCard' }, redirect: { name: 'RouteMain' },
menus: {
main: [],
card: ['AgencyBasicData', 'AgencyModes', 'AgencyWorkCenters', 'AgencyLog'],
},
children: [ children: [
{ {
path: '/agency/:id', name: 'AgencyMain',
name: 'AgencyCard', path: '',
component: () => import('src/pages/Route/Agency/Card/AgencyCard.vue'), component: () => import('src/components/common/VnModule.vue'),
redirect: { name: 'AgencySummary' }, redirect: { name: 'AgencyIndexMain' },
children: [ children: [
{ {
name: 'AgencySummary', name: 'AgencyIndexMain',
path: 'summary', path: '',
meta: { redirect: { name: 'AgencyList' },
title: 'summary', component: () => import('src/pages/Route/Agency/AgencyList.vue'),
icon: 'view_list',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencySummary.vue'),
},
{
name: 'AgencyBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () =>
import('pages/Route/Agency/Card/AgencyBasicData.vue'),
},
{
path: 'workCenter',
name: 'AgencyWorkCenterCard',
redirect: { name: 'AgencyWorkCenters' },
children: [ children: [
{ {
path: '', name: 'AgencyList',
name: 'AgencyWorkCenters', path: 'list',
meta: { meta: {
icon: 'apartment', title: 'list',
title: 'workCenters', icon: 'view_list',
}, },
component: () =>
import(
'src/pages/Route/Agency/Card/AgencyWorkcenter.vue'
),
}, },
agencyCard,
], ],
}, },
{
path: 'modes',
name: 'AgencyModesCard',
redirect: { name: 'AgencyModes' },
children: [
{
path: '',
name: 'AgencyModes',
meta: {
icon: 'format_list_bulleted',
title: 'modes',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencyModes.vue'),
},
],
},
{
name: 'AgencyLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Route/Agency/Card/AgencyLog.vue'),
},
], ],
}, },
], ],

View File

@ -12,8 +12,6 @@ import Supplier from './supplier';
import Travel from './travel'; import Travel from './travel';
import Order from './order'; import Order from './order';
import Entry from './entry'; import Entry from './entry';
import roadmap from './roadmap';
import Agency from './agency';
import Zone from './zone'; import Zone from './zone';
import Account from './account'; import Account from './account';
import Monitor from './monitor'; import Monitor from './monitor';
@ -33,8 +31,6 @@ export default [
Order, Order,
invoiceIn, invoiceIn,
Entry, Entry,
roadmap,
Agency,
Zone, Zone,
Account, Account,
Monitor, Monitor,

View File

@ -1,18 +1,12 @@
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
import { setRectificative } from 'src/pages/InvoiceIn/composables/setRectificative';
export default { const invoiceInCard = {
path: '/invoice-in', name: 'InvoiceInCard',
name: 'InvoiceIn', path: ':id',
component: () => import('src/pages/InvoiceIn/Card/InvoiceInCard.vue'),
redirect: { name: 'InvoiceInSummary' },
meta: { meta: {
title: 'invoiceIns', menu: [
icon: 'vn:invoice-in',
moduleName: 'InvoiceIn',
},
component: RouterView,
redirect: { name: 'InvoiceInMain' },
menus: {
main: ['InvoiceInList', 'InvoiceInSerial'],
card: [
'InvoiceInBasicData', 'InvoiceInBasicData',
'InvoiceInVat', 'InvoiceInVat',
'InvoiceInDueDay', 'InvoiceInDueDay',
@ -23,29 +17,109 @@ export default {
}, },
children: [ children: [
{ {
path: '', path: 'summary',
name: 'InvoiceInSummary',
meta: {
title: 'summary',
icon: 'view_list',
},
component: () => import('src/pages/InvoiceIn/Card/InvoiceInSummary.vue'),
},
{
name: 'InvoiceInBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInBasicData.vue'),
},
{
name: 'InvoiceInVat',
path: 'vat',
meta: {
title: 'vat',
icon: 'vn:tax',
},
component: () => import('src/pages/InvoiceIn/Card/InvoiceInVat.vue'),
},
{
name: 'InvoiceInDueDay',
path: 'due-day',
meta: {
title: 'dueDay',
icon: 'vn:calendar',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInDueDay.vue'),
},
{
name: 'InvoiceInIntrastat',
path: 'intrastat',
meta: {
title: 'intrastat',
icon: 'vn:lines',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue'),
},
{
name: 'InvoiceInCorrective',
path: 'corrective',
meta: {
title: 'corrective',
icon: 'attachment',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInCorrective.vue'),
},
{
name: 'InvoiceInLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/InvoiceIn/Card/InvoiceInLog.vue'),
},
],
};
export default {
name: 'InvoiceIn',
path: '/invoice-in',
meta: {
title: 'invoiceIns',
icon: 'vn:invoice-in',
moduleName: 'InvoiceIn',
menu: ['InvoiceInList', 'InvoiceInSerial'],
},
component: RouterView,
redirect: { name: 'InvoiceInMain' },
children: [
{
name: 'InvoiceInMain', name: 'InvoiceInMain',
path: '',
component: () => import('src/components/common/VnModule.vue'), component: () => import('src/components/common/VnModule.vue'),
redirect: { name: 'InvoiceInList' }, redirect: { name: 'InvoiceInIndexMain' },
children: [ children: [
{ {
path: 'list', path: '',
name: 'InvoiceInList', name: 'InvoiceInIndexMain',
meta: { redirect: { name: 'InvoiceInList' },
title: 'list',
icon: 'view_list',
},
component: () => import('src/pages/InvoiceIn/InvoiceInList.vue'), component: () => import('src/pages/InvoiceIn/InvoiceInList.vue'),
}, children: [
{ {
path: 'serial', name: 'InvoiceInList',
name: 'InvoiceInSerial', path: 'list',
meta: { meta: {
title: 'serial', title: 'list',
icon: 'view_list', icon: 'view_list',
}, },
component: () => },
import('src/pages/InvoiceIn/Serial/InvoiceInSerial.vue'), invoiceInCard,
],
}, },
{ {
path: 'create', path: 'create',
@ -56,87 +130,16 @@ export default {
}, },
component: () => import('src/pages/InvoiceIn/InvoiceInCreate.vue'), component: () => import('src/pages/InvoiceIn/InvoiceInCreate.vue'),
}, },
],
},
{
name: 'InvoiceInCard',
path: ':id',
component: () => import('src/pages/InvoiceIn/Card/InvoiceInCard.vue'),
redirect: { name: 'InvoiceInSummary' },
beforeEnter: async (to, from, next) => {
await setRectificative(to);
next();
},
children: [
{ {
name: 'InvoiceInSummary', path: 'serial',
path: 'summary', name: 'InvoiceInSerial',
meta: { meta: {
title: 'summary', title: 'serial',
icon: 'view_list', icon: 'view_list',
}, },
component: () => component: () => import('src/pages/InvoiceIn/Serial/InvoiceInSerial.vue'),
import('src/pages/InvoiceIn/Card/InvoiceInSummary.vue'),
},
{
name: 'InvoiceInBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInBasicData.vue'),
},
{
name: 'InvoiceInVat',
path: 'vat',
meta: {
title: 'vat',
icon: 'vn:tax',
},
component: () => import('src/pages/InvoiceIn/Card/InvoiceInVat.vue'),
},
{
name: 'InvoiceInDueDay',
path: 'due-day',
meta: {
title: 'dueDay',
icon: 'vn:calendar',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInDueDay.vue'),
},
{
name: 'InvoiceInIntrastat',
path: 'intrastat',
meta: {
title: 'intrastat',
icon: 'vn:lines',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue'),
},
{
name: 'InvoiceInLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/InvoiceIn/Card/InvoiceInLog.vue'),
},
{
name: 'InvoiceInCorrective',
path: 'corrective',
meta: {
title: 'corrective',
icon: 'attachment',
},
component: () =>
import('src/pages/InvoiceIn/Card/InvoiceInCorrective.vue'),
}, },
], ],
}, },
], ],
}; };

View File

@ -1,53 +0,0 @@
import { RouterView } from 'vue-router';
export default {
path: '/route/roadmap',
name: 'Roadmap',
meta: {
title: 'roadmap',
icon: 'vn:troncales',
moduleName: 'Roadmap',
},
component: RouterView,
redirect: { name: 'RouteMain' },
menus: {
card: ['RoadmapBasicData', 'RoadmapStops'],
},
children: [
{
name: 'RouteRoadmapCard',
path: ':id',
component: () => import('src/pages/Route/Roadmap/RoadmapCard.vue'),
redirect: { name: 'RoadmapSummary' },
children: [
{
name: 'RoadmapSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'open_in_new',
},
component: () => import('pages/Route/Roadmap/RoadmapSummary.vue'),
},
{
name: 'RoadmapBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Roadmap/RoadmapBasicData.vue'),
},
{
name: 'RoadmapStops',
path: 'stops',
meta: {
title: 'stops',
icon: 'vn:lines',
},
component: () => import('pages/Route/Roadmap/RoadmapStops.vue'),
},
],
},
],
};

View File

@ -1,17 +1,173 @@
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
const routeCard = {
name: 'RouteCard',
path: ':id',
component: () => import('src/pages/Route/Card/RouteCard.vue'),
redirect: { name: 'RouteSummary' },
meta: {
menu: ['RouteBasicData', 'RouteTickets', 'RouteLog'],
},
children: [
{
name: 'RouteBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Card/RouteForm.vue'),
},
{
name: 'RouteSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'open_in_new',
},
component: () => import('pages/Route/Card/RouteSummary.vue'),
},
{
path: 'tickets',
name: 'RouteTickets',
meta: {
title: 'tickets',
icon: 'vn:ticket',
},
component: () => import('src/pages/Route/RouteTickets.vue'),
},
{
path: 'log',
name: 'RouteLog',
meta: {
title: 'log',
icon: 'vn:History',
},
component: () => import('src/pages/Route/RouteLog.vue'),
},
],
};
const agencyCard = {
path: ':id',
name: 'AgencyCard',
component: () => import('src/pages/Route/Agency/Card/AgencyCard.vue'),
redirect: { name: 'AgencySummary' },
meta: {
menu: ['AgencyBasicData', 'AgencyModes', 'AgencyWorkCenters', 'AgencyLog'],
},
children: [
{
name: 'AgencySummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'view_list',
},
component: () => import('src/pages/Route/Agency/Card/AgencySummary.vue'),
},
{
name: 'AgencyBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Agency/Card/AgencyBasicData.vue'),
},
{
path: 'workCenter',
name: 'AgencyWorkCenterCard',
redirect: { name: 'AgencyWorkCenters' },
children: [
{
path: '',
name: 'AgencyWorkCenters',
meta: {
icon: 'apartment',
title: 'workCenters',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencyWorkcenter.vue'),
},
],
},
{
path: 'modes',
name: 'AgencyModesCard',
redirect: { name: 'AgencyModes' },
children: [
{
path: '',
name: 'AgencyModes',
meta: {
icon: 'format_list_bulleted',
title: 'modes',
},
component: () =>
import('src/pages/Route/Agency/Card/AgencyModes.vue'),
},
],
},
{
name: 'AgencyLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Route/Agency/Card/AgencyLog.vue'),
},
],
};
const roadmapCard = {
path: ':id',
name: 'RoadmapCard',
component: () => import('src/pages/Route/Roadmap/RoadmapCard.vue'),
redirect: { name: 'RoadmapSummary' },
meta: {
menu: ['RoadmapBasicData', 'RoadmapStops'],
},
children: [
{
name: 'RoadmapSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'open_in_new',
},
component: () => import('pages/Route/Roadmap/RoadmapSummary.vue'),
},
{
name: 'RoadmapBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Roadmap/RoadmapBasicData.vue'),
},
{
name: 'RoadmapStops',
path: 'stops',
meta: {
title: 'stops',
icon: 'vn:lines',
},
component: () => import('pages/Route/Roadmap/RoadmapStops.vue'),
},
],
};
export default { export default {
path: '/route',
name: 'Route', name: 'Route',
path: '/route',
meta: { meta: {
title: 'routes', title: 'routes',
icon: 'vn:delivery', icon: 'vn:delivery',
moduleName: 'Route', moduleName: 'Route',
}, menu: [
component: RouterView,
redirect: { name: 'RouteMain' },
menus: {
main: [
'RouteList', 'RouteList',
'RouteExtendedList', 'RouteExtendedList',
'RouteAutonomous', 'RouteAutonomous',
@ -19,23 +175,32 @@ export default {
'CmrList', 'CmrList',
'AgencyList', 'AgencyList',
], ],
card: ['RouteBasicData', 'RouteTickets', 'RouteLog'],
}, },
component: RouterView,
redirect: { name: 'RouteMain' },
children: [ children: [
{ {
path: '/route',
name: 'RouteMain', name: 'RouteMain',
path: '',
component: () => import('src/components/common/VnModule.vue'), component: () => import('src/components/common/VnModule.vue'),
redirect: { name: 'RouteList' }, redirect: { name: 'RouteIndexMain' },
children: [ children: [
{ {
path: 'list', path: '',
name: 'RouteList', name: 'RouteIndexMain',
meta: { redirect: { name: 'RouteList' },
title: 'RouteList',
icon: 'view_list',
},
component: () => import('src/pages/Route/RouteList.vue'), component: () => import('src/pages/Route/RouteList.vue'),
children: [
{
name: 'RouteList',
path: 'list',
meta: {
title: 'list',
icon: 'view_list',
},
},
routeCard,
],
}, },
{ {
path: 'extended-list', path: 'extended-list',
@ -67,11 +232,23 @@ export default {
{ {
path: 'roadmap', path: 'roadmap',
name: 'RouteRoadmap', name: 'RouteRoadmap',
redirect: { name: 'RoadmapList' },
meta: { meta: {
title: 'RouteRoadmap', title: 'RouteRoadmap',
icon: 'vn:troncales', icon: 'vn:troncales',
}, },
component: () => import('src/pages/Route/RouteRoadmap.vue'), component: () => import('src/pages/Route/RouteRoadmap.vue'),
children: [
{
name: 'RoadmapList',
path: 'list',
meta: {
title: 'list',
icon: 'view_list',
},
},
roadmapCard,
],
}, },
{ {
path: 'cmr', path: 'cmr',
@ -83,66 +260,27 @@ export default {
component: () => import('src/pages/Route/Cmr/CmrList.vue'), component: () => import('src/pages/Route/Cmr/CmrList.vue'),
}, },
{ {
path: '/agency', path: 'agency',
name: 'RouteAgency',
redirect: { name: 'AgencyList' }, redirect: { name: 'AgencyList' },
meta: {
title: 'agency',
icon: 'garage_home',
},
component: () => import('src/pages/Route/Agency/AgencyList.vue'),
children: [ children: [
{ {
path: 'list',
name: 'AgencyList', name: 'AgencyList',
path: 'list',
meta: { meta: {
title: 'agencyList', title: 'list',
icon: 'list', icon: 'view_list',
}, },
component: () =>
import('src/pages/Route/Agency/AgencyList.vue'),
}, },
agencyCard,
], ],
}, },
], ],
}, },
{
name: 'RouteCard',
path: ':id',
component: () => import('src/pages/Route/Card/RouteCard.vue'),
redirect: { name: 'RouteSummary' },
children: [
{
name: 'RouteBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('pages/Route/Card/RouteForm.vue'),
},
{
name: 'RouteSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'open_in_new',
},
component: () => import('pages/Route/Card/RouteSummary.vue'),
},
{
path: 'tickets',
name: 'RouteTickets',
meta: {
title: 'tickets',
icon: 'vn:ticket',
},
component: () => import('src/pages/Route/RouteTickets.vue'),
},
{
path: 'log',
name: 'RouteLog',
meta: {
title: 'log',
icon: 'vn:History',
},
component: () => import('src/pages/Route/RouteLog.vue'),
},
],
},
], ],
}; };

View File

@ -12,8 +12,6 @@ import travel from './modules/travel';
import shelving from 'src/router/modules/shelving'; import shelving from 'src/router/modules/shelving';
import order from 'src/router/modules/order'; import order from 'src/router/modules/order';
import entry from 'src/router/modules/entry'; import entry from 'src/router/modules/entry';
import roadmap from 'src/router/modules/roadmap';
import agency from 'src/router/modules/agency';
import zone from 'src/router/modules/zone'; import zone from 'src/router/modules/zone';
import account from './modules/account'; import account from './modules/account';
import monitor from 'src/router/modules/monitor'; import monitor from 'src/router/modules/monitor';
@ -82,9 +80,7 @@ const routes = [
route, route,
supplier, supplier,
travel, travel,
roadmap,
entry, entry,
agency,
zone, zone,
account, account,
{ {

View File

@ -2,7 +2,7 @@ describe('AgencyWorkCenter', () => {
beforeEach(() => { beforeEach(() => {
cy.viewport(1920, 1080); cy.viewport(1920, 1080);
cy.login('developer'); cy.login('developer');
cy.visit(`/#/agency/11/workCenter`); cy.visit(`/#/route/agency/11/workCenter`);
}); });
const createButton = '.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon'; const createButton = '.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon';
const workCenterCombobox = 'input[role="combobox"]'; const workCenterCombobox = 'input[role="combobox"]';

View File

@ -1,12 +1,11 @@
describe('RoadMap', () => { describe('RoadMap', () => {
beforeEach(() => { beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer'); cy.login('developer');
cy.visit(`/#/route/roadmap`); cy.visit(`/#/route/roadmap`);
}); });
it('Route list create roadmap and redirect', () => { it('Route list create roadmap and redirect', () => {
cy.addBtnClick(); cy.addBtnClick();
cy.get('input[name="name"]').eq(1).type('roadMapTestOne{enter}'); cy.get('input[name="name"]').type('roadMapTestOne{enter}');
cy.get('.q-notification__message').should('have.text', 'Data created'); cy.get('.q-notification__message').should('have.text', 'Data created');
cy.url().should('include', '/summary'); cy.url().should('include', '/summary');
}); });

View File

@ -30,14 +30,15 @@ describe('TicketList', () => {
cy.get(firstRow).find('.q-btn:first').click(); cy.get(firstRow).find('.q-btn:first').click();
cy.get('@windowOpen').should('be.calledWithMatch', /\/ticket\/\d+\/sale/); cy.get('@windowOpen').should('be.calledWithMatch', /\/ticket\/\d+\/sale/);
}); });
// https://redmine.verdnatura.es/issues/8424
it.skip('should open ticket summary', () => { it('should open ticket summary', () => {
searchResults(); searchResults();
cy.get(firstRow).find('.q-btn:last').click(); cy.get(firstRow).find('.q-btn:last').click();
cy.dataCy('ticketSummary').should('exist'); cy.get('.summaryHeader').should('exist');
cy.get('.summaryBody').should('exist');
}); });
it.skip('Client list create new client', () => { it('Client list create new client', () => {
cy.dataCy('vnTableCreateBtn').should('exist'); cy.dataCy('vnTableCreateBtn').should('exist');
cy.dataCy('vnTableCreateBtn').click(); cy.dataCy('vnTableCreateBtn').click();
const data = { const data = {
@ -45,9 +46,9 @@ describe('TicketList', () => {
Warehouse: { val: 'Warehouse One', type: 'select' }, Warehouse: { val: 'Warehouse One', type: 'select' },
Address: { val: 'employee', type: 'select' }, Address: { val: 'employee', type: 'select' },
Landed: { val: '01-01-2024', type: 'date' }, Landed: { val: '01-01-2024', type: 'date' },
Agency: { val: 'Other agency', type: 'select' },
}; };
cy.fillInForm(data); cy.fillInForm(data);
cy.dataCy('Agency_select').click();
cy.dataCy('FormModelPopup_save').click(); cy.dataCy('FormModelPopup_save').click();
cy.checkNotification('Data created'); cy.checkNotification('Data created');
cy.url().should('match', /\/ticket\/\d+\/summary/); cy.url().should('match', /\/ticket\/\d+\/summary/);

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('TicketRequest', () => { describe('TicketNotes', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.viewport(1920, 1080); cy.viewport(1920, 1080);
@ -13,7 +13,7 @@ describe('TicketRequest', () => {
cy.selectOption('[data-cy="ticketNotesObservationType"]:last', 'Weight'); cy.selectOption('[data-cy="ticketNotesObservationType"]:last', 'Weight');
cy.dataCy('ticketNotesDescription').should('exist'); cy.dataCy('ticketNotesDescription').should('exist');
cy.get('[data-cy="ticketNotesDescription"]:last').type( cy.get('[data-cy="ticketNotesDescription"]:last').type(
'This is a note description' 'This is a note description',
); );
cy.dataCy('crudModelDefaultSaveBtn').click(); cy.dataCy('crudModelDefaultSaveBtn').click();
cy.checkNotification('Data saved'); cy.checkNotification('Data saved');

View File

@ -6,7 +6,7 @@ describe('TicketRequest', () => {
cy.visit('/#/ticket/31/request'); cy.visit('/#/ticket/31/request');
}); });
it.skip('Creates a new request', () => { it('Creates a new request', () => {
cy.dataCy('vnTableCreateBtn').should('exist'); cy.dataCy('vnTableCreateBtn').should('exist');
cy.dataCy('vnTableCreateBtn').click(); cy.dataCy('vnTableCreateBtn').click();
const data = { const data = {