Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 8599-ModifyAndCreateInvoiceOutTests

This commit is contained in:
Jon Elias 2025-02-20 07:57:11 +01:00
commit 763d7679a1
35 changed files with 418 additions and 417 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "25.08.0", "version": "25.10.0",
"description": "Salix frontend", "description": "Salix frontend",
"productName": "Salix", "productName": "Salix",
"author": "Verdnatura", "author": "Verdnatura",

View File

@ -30,22 +30,5 @@ export default {
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
form.addEventListener('keyup', function (evt) {
if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
const input = evt.target;
if (input.type == 'textarea' && evt.shiftKey) {
evt.preventDefault();
let { selectionStart, selectionEnd } = input;
input.value =
input.value.substring(0, selectionStart) +
'\n' +
input.value.substring(selectionEnd);
selectionStart = selectionEnd = selectionStart + 1;
return;
}
evt.preventDefault();
that.onSubmit();
}
});
}, },
}; };

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import axios from 'axios'; import axios from 'axios';
import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue'; import { onMounted, onUnmounted, computed, ref, watch, nextTick, useAttrs } from 'vue';
import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router'; import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
@ -22,6 +22,7 @@ const { validate } = useValidator();
const { notify } = useNotify(); const { notify } = useNotify();
const route = useRoute(); const route = useRoute();
const myForm = ref(null); const myForm = ref(null);
const attrs = useAttrs();
const $props = defineProps({ const $props = defineProps({
url: { url: {
type: String, type: String,
@ -106,14 +107,14 @@ const isLoading = ref(false);
const isResetting = ref(false); const isResetting = ref(false);
const hasChanges = ref(!$props.observeFormChanges); const hasChanges = ref(!$props.observeFormChanges);
const originalData = computed(() => state.get(modelValue)); const originalData = computed(() => state.get(modelValue));
const formData = ref({}); const formData = ref();
const defaultButtons = computed(() => ({ const defaultButtons = computed(() => ({
save: { save: {
dataCy: 'saveDefaultBtn', dataCy: 'saveDefaultBtn',
color: 'primary', color: 'primary',
icon: 'save', icon: 'save',
label: 'globals.save', label: 'globals.save',
click: () => myForm.value.onSubmit(false), click: async () => await save(),
type: 'submit', type: 'submit',
}, },
reset: { reset: {
@ -208,8 +209,7 @@ async function fetch() {
} }
} }
async function save(prevent = false) { async function save() {
if (prevent) return;
if ($props.observeFormChanges && !hasChanges.value) if ($props.observeFormChanges && !hasChanges.value)
return notify('globals.noChanges', 'negative'); return notify('globals.noChanges', 'negative');
@ -284,6 +284,22 @@ function trimData(data) {
return data; return data;
} }
async function onKeyup(evt) {
if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
const input = evt.target;
if (input.type == 'textarea' && evt.shiftKey) {
let { selectionStart, selectionEnd } = input;
input.value =
input.value.substring(0, selectionStart) +
'\n' +
input.value.substring(selectionEnd);
selectionStart = selectionEnd = selectionStart + 1;
return;
}
await save();
}
}
defineExpose({ defineExpose({
save, save,
isLoading, isLoading,
@ -298,12 +314,12 @@ defineExpose({
<QForm <QForm
ref="myForm" ref="myForm"
v-if="formData" v-if="formData"
@submit="save(!!$event)" @submit.prevent
@keyup.prevent="onKeyup"
@reset="reset" @reset="reset"
class="q-pa-md" class="q-pa-md"
:style="maxWidth ? 'max-width: ' + maxWidth : ''" :style="maxWidth ? 'max-width: ' + maxWidth : ''"
id="formModel" id="formModel"
:prevent-submit="$attrs['prevent-submit']"
> >
<QCard> <QCard>
<slot <slot

View File

@ -27,10 +27,15 @@ const formModelRef = ref(null);
const closeButton = ref(null); const closeButton = ref(null);
const isSaveAndContinue = ref(false); const isSaveAndContinue = ref(false);
const onDataSaved = (formData, requestResponse) => { const onDataSaved = (formData, requestResponse) => {
if (closeButton.value && isSaveAndContinue) closeButton.value.click(); if (closeButton.value && !isSaveAndContinue.value) closeButton.value.click();
emit('onDataSaved', formData, requestResponse); emit('onDataSaved', formData, requestResponse);
}; };
const onClick = async (saveAndContinue) => {
isSaveAndContinue.value = saveAndContinue;
await formModelRef.value.save();
};
const isLoading = computed(() => formModelRef.value?.isLoading); const isLoading = computed(() => formModelRef.value?.isLoading);
const reset = computed(() => formModelRef.value?.reset); const reset = computed(() => formModelRef.value?.reset);
@ -78,10 +83,7 @@ defineExpose({
:flat="showSaveAndContinueBtn" :flat="showSaveAndContinueBtn"
:label="t('globals.save')" :label="t('globals.save')"
:title="t('globals.save')" :title="t('globals.save')"
@click=" @click="onClick(false)"
formModelRef.save();
isSaveAndContinue = false;
"
color="primary" color="primary"
class="q-ml-sm" class="q-ml-sm"
:disabled="isLoading" :disabled="isLoading"
@ -99,10 +101,7 @@ defineExpose({
:loading="isLoading" :loading="isLoading"
data-cy="FormModelPopup_isSaveAndContinue" data-cy="FormModelPopup_isSaveAndContinue"
z-max z-max
@click=" @click="onClick(true)"
isSaveAndContinue = true;
formModelRef.save();
"
/> />
</div> </div>
</template> </template>

View File

@ -5,6 +5,18 @@ defineProps({ row: { type: Object, required: true } });
</script> </script>
<template> <template>
<span class="q-gutter-x-xs"> <span class="q-gutter-x-xs">
<router-link
v-if="row.claim?.claimFk"
:to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
class="link"
>
<QIcon name="vn:claims" size="xs">
<QTooltip>
{{ t('ticketSale.claim') }}:
{{ row.claim?.claimFk }}
</QTooltip>
</QIcon>
</router-link>
<QIcon <QIcon
v-if="row?.risk" v-if="row?.risk"
name="vn:risk" name="vn:risk"
@ -56,7 +68,7 @@ defineProps({ row: { type: Object, required: true } });
<QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip> <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
</QIcon> </QIcon>
<QIcon <QIcon
v-if="!row?.isTaxDataChecked === 0" v-if="row?.isTaxDataChecked !== 0"
name="vn:no036" name="vn:no036"
color="primary" color="primary"
size="xs" size="xs"

View File

@ -164,7 +164,6 @@ const app = inject('app');
const editingRow = ref(null); const editingRow = ref(null);
const editingField = ref(null); const editingField = ref(null);
const isTableMode = computed(() => mode.value == TABLE_MODE); const isTableMode = computed(() => mode.value == TABLE_MODE);
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
const selectRegex = /select/; const selectRegex = /select/;
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']); const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
const tableModes = [ const tableModes = [
@ -618,14 +617,6 @@ function cardClick(_, row) {
dense dense
:options="tableModes.filter((mode) => !mode.disable)" :options="tableModes.filter((mode) => !mode.disable)"
/> />
<QBtn
v-if="showRightIcon"
icon="filter_alt"
class="bg-vn-section-color q-ml-sm"
dense
@click="stateStore.toggleRightDrawer()"
/>
</template> </template>
<template #header-cell="{ col }"> <template #header-cell="{ col }">
<QTh <QTh
@ -783,7 +774,7 @@ function cardClick(_, row) {
<QCardSection <QCardSection
vertical vertical
class="no-margin no-padding" class="no-margin no-padding"
:class="colsMap.tableActions ? '' : 'fit'" :class="colsMap.tableActions ? 'w-80' : 'fit'"
> >
<!-- Chips --> <!-- Chips -->
<QCardSection <QCardSection
@ -822,11 +813,11 @@ function cardClick(_, row) {
col, index col, index
) of splittedColumns.cardVisible" ) of splittedColumns.cardVisible"
:key="col.name" :key="col.name"
class="fields"
> >
<VnLv :label="col.label + ':'"> <VnLv :label="col.label + ':'">
<template #value> <template #value>
<span <span
class="q-pl-xs"
@click="stopEventPropagation($event)" @click="stopEventPropagation($event)"
> >
<slot <slot

View File

@ -57,6 +57,7 @@ describe('FormModel', () => {
vm.state.set(model, formInitialData); vm.state.set(model, formInitialData);
expect(vm.hasChanges).toBe(false); expect(vm.hasChanges).toBe(false);
await vm.$nextTick();
vm.formData.mockKey = 'newVal'; vm.formData.mockKey = 'newVal';
await vm.$nextTick(); await vm.$nextTick();
expect(vm.hasChanges).toBe(true); expect(vm.hasChanges).toBe(true);
@ -94,8 +95,12 @@ describe('FormModel', () => {
it('should call axios.patch with the right data', async () => { it('should call axios.patch with the right data', async () => {
const spy = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} }); const spy = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
const { vm } = mount({ propsData: { url, model } }); const { vm } = mount({ propsData: { url, model } });
vm.formData.mockKey = 'newVal';
vm.formData = {};
await vm.$nextTick(); await vm.$nextTick();
vm.formData = { mockKey: 'newVal' };
await vm.$nextTick();
await vm.save(); await vm.save();
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
vm.formData.mockKey = 'mockVal'; vm.formData.mockKey = 'mockVal';

View File

@ -193,22 +193,24 @@ const toModule = computed(() =>
</div> </div>
</QItemLabel> </QItemLabel>
<QItem> <QItem>
<QItemLabel class="subtitle" caption> <QItemLabel class="subtitle">
#{{ getValueFromPath(subtitle) ?? entity.id }} #{{ getValueFromPath(subtitle) ?? entity.id }}
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
</QItemLabel> </QItemLabel>
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
<!-- </QItemLabel> -->
</QItem> </QItem>
</QList> </QList>
<div class="list-box q-mt-xs"> <div class="list-box q-mt-xs">

View File

@ -11,7 +11,7 @@ export async function useCau(res, message) {
const { config, headers, request, status, statusText, data } = res || {}; const { config, headers, request, status, statusText, data } = res || {};
const { params, url, method, signal, headers: confHeaders } = config || {}; const { params, url, method, signal, headers: confHeaders } = config || {};
const { message: resMessage, code, name } = data?.error || {}; const { message: resMessage, code, name } = data?.error || {};
delete confHeaders.Authorization; delete confHeaders?.Authorization;
const additionalData = { const additionalData = {
path: location.hash, path: location.hash,

View File

@ -335,3 +335,7 @@ input::-webkit-inner-spin-button {
border: 1px solid; border: 1px solid;
box-shadow: 0 4px 6px #00000000; box-shadow: 0 4px 6px #00000000;
} }
.containerShrinked {
width: 80%;
}

View File

@ -233,7 +233,7 @@ function handleLocation(data, location) {
postcode: data.postalCode, postcode: data.postalCode,
city: data.city, city: data.city,
province: data.province, province: data.province,
country: data.province.country, country: data.province?.country,
}" }"
@update:model-value="(location) => handleLocation(data, location)" @update:model-value="(location) => handleLocation(data, location)"
></VnLocation> ></VnLocation>

View File

@ -114,7 +114,7 @@ function onBeforeSave(data) {
if (isCash.value && shouldSendEmail.value && !data.email) if (isCash.value && shouldSendEmail.value && !data.email)
return notify(t('There is no assigned email for this client'), 'negative'); return notify(t('There is no assigned email for this client'), 'negative');
data.bankFk = data.bankFk.id; data.bankFk = data.bankFk?.id;
return data; return data;
} }
@ -189,7 +189,7 @@ async function getAmountPaid() {
:url-create="urlCreate" :url-create="urlCreate"
:mapper="onBeforeSave" :mapper="onBeforeSave"
@on-data-saved="onDataSaved" @on-data-saved="onDataSaved"
:prevent-submit="true" prevent-submit
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<span ref="closeButton" class="row justify-end close-icon" v-close-popup> <span ref="closeButton" class="row justify-end close-icon" v-close-popup>

View File

@ -103,7 +103,7 @@ const refundInvoice = async (withWarehouse) => {
t('refundInvoiceSuccessMessage', { t('refundInvoiceSuccessMessage', {
refundTicket: data[0].id, refundTicket: data[0].id,
}), }),
'positive' 'positive',
); );
}; };
@ -124,6 +124,13 @@ const showRefundInvoiceForm = () => {
}, },
}); });
}; };
const showExportationLetter = () => {
openReport(`InvoiceOuts/${$props.invoiceOutData.ref}/exportation-pdf`, {
recipientId: $props.invoiceOutData.client.id,
refFk: $props.invoiceOutData.ref,
});
};
</script> </script>
<template> <template>
@ -172,7 +179,7 @@ const showRefundInvoiceForm = () => {
t('Confirm deletion'), t('Confirm deletion'),
t('Are you sure you want to delete this invoice?'), t('Are you sure you want to delete this invoice?'),
deleteInvoice, deleteInvoice,
redirectToInvoiceOutList redirectToInvoiceOutList,
) )
" "
> >
@ -185,7 +192,7 @@ const showRefundInvoiceForm = () => {
openConfirmationModal( openConfirmationModal(
'', '',
t('Are you sure you want to book this invoice?'), t('Are you sure you want to book this invoice?'),
bookInvoice bookInvoice,
) )
" "
> >
@ -198,7 +205,7 @@ const showRefundInvoiceForm = () => {
openConfirmationModal( openConfirmationModal(
t('Generate PDF invoice document'), t('Generate PDF invoice document'),
t('Are you sure you want to generate/regenerate the PDF invoice?'), t('Are you sure you want to generate/regenerate the PDF invoice?'),
generateInvoicePdf generateInvoicePdf,
) )
" "
> >
@ -226,6 +233,14 @@ const showRefundInvoiceForm = () => {
{{ t('Create a single ticket with all the content of the current invoice') }} {{ t('Create a single ticket with all the content of the current invoice') }}
</QTooltip> </QTooltip>
</QItem> </QItem>
<QItem
v-if="$props.invoiceOutData.serial === 'E'"
v-ripple
clickable
@click="showExportationLetter()"
>
<QItemSection>{{ t('Show CITES letter') }}</QItemSection>
</QItem>
</template> </template>
<i18n> <i18n>
@ -255,7 +270,7 @@ es:
Create a single ticket with all the content of the current invoice: Crear un ticket único con todo el contenido de la factura actual Create a single ticket with all the content of the current invoice: Crear un ticket único con todo el contenido de la factura actual
refundInvoiceSuccessMessage: Se ha creado el siguiente ticket de abono {refundTicket} refundInvoiceSuccessMessage: Se ha creado el siguiente ticket de abono {refundTicket}
The email can't be empty: El email no puede estar vacío The email can't be empty: El email no puede estar vacío
Show CITES letter: Ver carta CITES
en: en:
refundInvoiceSuccessMessage: The following refund ticket have been created {refundTicket} refundInvoiceSuccessMessage: The following refund ticket have been created {refundTicket}
</i18n> </i18n>

View File

@ -22,7 +22,7 @@ const states = ref();
<VnFilterPanel :data-key="props.dataKey" :search-button="true"> <VnFilterPanel :data-key="props.dataKey" :search-button="true">
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong> <strong>{{ t(`invoiceOut.params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span> <span>{{ formatFn(tag.value) }}</span>
</div> </div>
</template> </template>
@ -84,15 +84,6 @@ const states = ref();
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnInputDate
v-model="params.issued"
:label="t('Issued')"
is-outlined
/>
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInputDate <VnInputDate
@ -110,37 +101,3 @@ const states = ref();
</template> </template>
</VnFilterPanel> </VnFilterPanel>
</template> </template>
<i18n>
en:
params:
search: Contains
clientFk: Customer
fi: FI
amount: Amount
min: Min
max: Max
hasPdf: Has PDF
issued: Issued
created: Created
dued: Dued
es:
params:
search: Contiene
clientFk: Cliente
fi: CIF
amount: Importe
min: Min
max: Max
hasPdf: Tiene PDF
issued: Emitida
created: Creada
dued: Vencida
Customer ID: ID cliente
FI: CIF
Amount: Importe
Has PDF: Tiene PDF
Issued: Fecha emisión
Created: Fecha creación
Dued: Fecha vencimiento
</i18n>

View File

@ -71,14 +71,6 @@ const columns = computed(() => [
inWhere: true, inWhere: true,
}, },
}, },
{
align: 'left',
name: 'issued',
label: t('invoiceOut.summary.issued'),
component: 'date',
format: (row) => toDate(row.issued),
columnField: { component: null },
},
{ {
align: 'left', align: 'left',
name: 'clientFk', name: 'clientFk',

View File

@ -10,6 +10,8 @@ import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vu
import TicketDescriptorProxy from '../Ticket/Card/TicketDescriptorProxy.vue'; import TicketDescriptorProxy from '../Ticket/Card/TicketDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import InvoiceOutNegativeBasesFilter from './InvoiceOutNegativeBasesFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
@ -97,16 +99,19 @@ const columns = computed(() => [
align: 'left', align: 'left',
name: 'isActive', name: 'isActive',
label: t('invoiceOut.negativeBases.active'), label: t('invoiceOut.negativeBases.active'),
component: 'checkbox',
}, },
{ {
align: 'left', align: 'left',
name: 'hasToInvoice', name: 'hasToInvoice',
label: t('invoiceOut.negativeBases.hasToInvoice'), label: t('invoiceOut.negativeBases.hasToInvoice'),
component: 'checkbox',
}, },
{ {
align: 'left', align: 'left',
name: 'hasVerifiedData', name: 'isTaxDataChecked',
label: t('invoiceOut.negativeBases.verifiedData'), label: t('invoiceOut.negativeBases.verifiedData'),
component: 'checkbox',
}, },
{ {
align: 'left', align: 'left',
@ -142,7 +147,7 @@ const downloadCSV = async () => {
await invoiceOutGlobalStore.getNegativeBasesCsv( await invoiceOutGlobalStore.getNegativeBasesCsv(
userParams.from, userParams.from,
userParams.to, userParams.to,
filterParams filterParams,
); );
}; };
</script> </script>
@ -154,6 +159,11 @@ const downloadCSV = async () => {
</QBtn> </QBtn>
</template> </template>
</VnSubToolbar> </VnSubToolbar>
<RightMenu>
<template #right-panel>
<InvoiceOutNegativeBasesFilter data-key="negativeFilter" />
</template>
</RightMenu>
<VnTable <VnTable
ref="tableRef" ref="tableRef"
data-key="negativeFilter" data-key="negativeFilter"
@ -174,6 +184,7 @@ const downloadCSV = async () => {
auto-load auto-load
:is-editable="false" :is-editable="false"
:use-model="true" :use-model="true"
:right-search="false"
> >
<template #column-clientId="{ row }"> <template #column-clientId="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>

View File

@ -2,9 +2,10 @@
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue'; import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -24,11 +25,11 @@ const props = defineProps({
> >
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong> <strong>{{ t(`invoiceOut.params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span> <span>{{ formatFn(tag.value) }}</span>
</div> </div>
</template> </template>
<template #body="{ params }"> <template #body="{ params, searchFn }">
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInputDate <VnInputDate
@ -49,38 +50,70 @@ const props = defineProps({
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnSelect
v-model="params.company" url="Companies"
:label="t('globals.company')" :label="t('globals.company')"
is-outlined v-model="params.company"
/> option-label="code"
option-value="code"
dense
outlined
rounded
@update:model-value="searchFn()"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt?.code }}
</QItemLabel>
<QItemLabel caption>
{{ `#${scope.opt?.id}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnSelect
url="Countries"
:label="t('globals.params.countryFk')"
v-model="params.country" v-model="params.country"
:label="t('globals.country')" option-label="name"
is-outlined option-value="name"
/> outlined
</QItemSection> dense
</QItem> rounded
@update:model-value="searchFn()"
<QItem> >
<QItemSection> <template #option="scope">
<VnInput <QItem v-bind="scope.itemProps">
v-model="params.clientId" <QItemSection>
:label="t('invoiceOut.negativeBases.clientId')" <QItemLabel>
is-outlined {{ scope.opt?.name }}
/> </QItemLabel>
<QItemLabel caption>
{{ `#${scope.opt?.id}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnSelect
v-model="params.clientSocialName" url="Clients"
:label="t('globals.client')" :label="t('globals.client')"
is-outlined v-model="params.clientId"
outlined
dense
rounded
@update:model-value="searchFn()"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
@ -90,15 +123,18 @@ const props = defineProps({
v-model="params.amount" v-model="params.amount"
:label="t('globals.amount')" :label="t('globals.amount')"
is-outlined is-outlined
:positive="false"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnSelectWorker
v-model="params.comercialName"
:label="t('invoiceOut.negativeBases.comercial')" :label="t('invoiceOut.negativeBases.comercial')"
v-model="params.workerName"
option-value="name"
is-outlined is-outlined
@update:model-value="searchFn()"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>

View File

@ -4,7 +4,7 @@ invoiceOut:
params: params:
company: Company company: Company
country: Country country: Country
clientId: Client ID clientId: Client
clientSocialName: Client clientSocialName: Client
taxableBase: Base taxableBase: Base
ticketFk: Ticket ticketFk: Ticket
@ -12,6 +12,18 @@ invoiceOut:
hasToInvoice: Has to invoice hasToInvoice: Has to invoice
hasVerifiedData: Verified data hasVerifiedData: Verified data
workerName: Worker workerName: Worker
isTaxDataChecked: Verified data
amount: Amount
clientFk: Client
companyFk: Company
created: Created
dued: Dued
customsAgentFk: Custom Agent
ref: Reference
fi: FI
min: Min
max: Max
hasPdf: Has PDF
card: card:
issued: Issued issued: Issued
customerCard: Customer card customerCard: Customer card
@ -53,7 +65,7 @@ invoiceOut:
active: Active active: Active
hasToInvoice: Has to Invoice hasToInvoice: Has to Invoice
verifiedData: Verified Data verifiedData: Verified Data
comercial: Commercial comercial: Sales person
errors: errors:
downloadCsvFailed: CSV download failed downloadCsvFailed: CSV download failed
invoiceOutModule: invoiceOutModule:

View File

@ -4,7 +4,7 @@ invoiceOut:
params: params:
company: Empresa company: Empresa
country: País country: País
clientId: ID del cliente clientId: Cliente
clientSocialName: Cliente clientSocialName: Cliente
taxableBase: Base taxableBase: Base
ticketFk: Ticket ticketFk: Ticket
@ -12,6 +12,18 @@ invoiceOut:
hasToInvoice: Debe facturar hasToInvoice: Debe facturar
hasVerifiedData: Datos verificados hasVerifiedData: Datos verificados
workerName: Comercial workerName: Comercial
isTaxDataChecked: Datos comprobados
amount: Importe
clientFk: Cliente
companyFk: Empresa
created: Creada
dued: Vencida
customsAgentFk: Agente aduanas
ref: Referencia
fi: CIF
min: Min
max: Max
hasPdf: Tiene PDF
card: card:
issued: Fecha emisión issued: Fecha emisión
customerCard: Ficha del cliente customerCard: Ficha del cliente

View File

@ -6,6 +6,8 @@ import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDate } from 'src/filters'; import { dashIfEmpty, toDate } from 'src/filters';
import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue'; import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
import filter from './RouteFilter.js'; import filter from './RouteFilter.js';
import useCardDescription from 'src/composables/useCardDescription';
import axios from 'axios';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -16,7 +18,6 @@ const $props = defineProps({
}); });
const route = useRoute(); const route = useRoute();
const { t } = useI18n();
const zone = ref(); const zone = ref();
const zoneId = ref(); const zoneId = ref();
const entityId = computed(() => { const entityId = computed(() => {
@ -50,9 +51,9 @@ onMounted(async () => {
width="lg-width" 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)" />
<VnLv :label="t('Agency')" :value="entity?.agencyMode?.name" /> <VnLv :label="$t('Agency')" :value="entity?.agencyMode?.name" />
<VnLv :label="t('Zone')" :value="zone" /> <VnLv :label="$t('Zone')" :value="zone" />
<VnLv <VnLv
:label="$t('Volume')" :label="$t('Volume')"
:value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty( :value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty(

View File

@ -14,7 +14,6 @@ export default {
'started', 'started',
'finished', 'finished',
'cost', 'cost',
'zoneFk',
'isOk', 'isOk',
], ],
include: [ include: [
@ -23,7 +22,6 @@ export default {
relation: 'vehicle', relation: 'vehicle',
scope: { fields: ['id', 'm3'] }, scope: { fields: ['id', 'm3'] },
}, },
{ relation: 'zone', scope: { fields: ['id', 'name'] } },
{ {
relation: 'worker', relation: 'worker',
scope: { scope: {

View File

@ -28,52 +28,6 @@ const defaultInitialData = {
isOk: false, isOk: false,
}; };
const maxDistance = ref(); const maxDistance = ref();
const routeFilter = {
fields: [
'id',
'workerFk',
'agencyModeFk',
'dated',
'm3',
'warehouseFk',
'description',
'vehicleFk',
'kmStart',
'kmEnd',
'started',
'finished',
'cost',
'isOk',
],
include: [
{ relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
{
relation: 'vehicle',
scope: { fields: ['id', 'm3'] },
},
{
relation: 'ticket',
scope: {
fields: ['id', 'name', 'zoneFk'],
include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
},
},
{
relation: 'worker',
scope: {
fields: ['id'],
include: {
relation: 'user',
scope: {
fields: ['id'],
include: { relation: 'emailUser', scope: { fields: ['email'] } },
},
},
},
},
],
};
const onSave = (data, response) => { const onSave = (data, response) => {
if (isNew) { if (isNew) {
axios.post(`Routes/${response?.id}/updateWorkCenter`); axios.post(`Routes/${response?.id}/updateWorkCenter`);

View File

@ -16,6 +16,7 @@ import useNotify from 'src/composables/useNotify.js';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import { toDateTimeFormat } from 'src/filters/date.js'; import { toDateTimeFormat } from 'src/filters/date.js';
import axios from 'axios'; import axios from 'axios';
import TicketProblems from 'src/components/TicketProblems.vue';
const state = useState(); const state = useState();
const { t } = useI18n(); const { t } = useI18n();
@ -286,71 +287,7 @@ watch(
</span> </span>
</QTooltip> </QTooltip>
</QIcon> </QIcon>
<QIcon <TicketProblems :row />
v-if="row.isTaxDataChecked === 0"
color="primary"
name="vn:no036"
size="xs"
>
<QTooltip>
{{ t('futureTickets.noVerified') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row.hasTicketRequest"
color="primary"
name="vn:buyrequest"
size="xs"
>
<QTooltip>
{{ t('futureTickets.purchaseRequest') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row.itemShortage"
color="primary"
name="vn:unavailable"
size="xs"
>
<QTooltip>
{{ t('ticketSale.noVisible') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row.isFreezed"
color="primary"
name="vn:frozen"
size="xs"
>
<QTooltip>
{{ t('futureTickets.clientFrozen') }}
</QTooltip>
</QIcon>
<QIcon v-if="row.risk" color="primary" name="vn:risk" size="xs">
<QTooltip>
{{ t('futureTickets.risk') }}: {{ row.risk }}
</QTooltip>
</QIcon>
<QIcon
v-if="row.hasComponentLack"
color="primary"
name="vn:components"
size="xs"
>
<QTooltip>
{{ t('futureTickets.componentLack') }}
</QTooltip>
</QIcon>
<QIcon
v-if="row.hasRounding"
color="primary"
name="sync_problem"
size="xs"
>
<QTooltip>
{{ t('futureTickets.rounding') }}
</QTooltip>
</QIcon>
</span> </span>
</template> </template>
<template #column-id="{ row }"> <template #column-id="{ row }">

View File

@ -2,6 +2,7 @@
import { onMounted, ref, computed, watch } from 'vue'; import { onMounted, ref, computed, watch } from 'vue';
import { QBtn } from 'quasar'; import { QBtn } from 'quasar';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue'; import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue'; import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
@ -22,6 +23,8 @@ import VnPopup from 'src/components/common/VnPopup.vue';
const stateStore = useStateStore(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
const { openReport } = usePrintService(); const { openReport } = usePrintService();
const route = useRoute();
const tableParams = ref();
const shippedFrom = ref(Date.vnNew()); const shippedFrom = ref(Date.vnNew());
const landedTo = ref(Date.vnNew()); const landedTo = ref(Date.vnNew());
@ -143,7 +146,7 @@ const columns = computed(() => [
sortable: true, sortable: true,
}, },
{ {
label: t('globals.pageTitles.supplier'), label: t('extraCommunity.cargoShip'),
field: 'cargoSupplierNickname', field: 'cargoSupplierNickname',
name: 'cargoSupplierNickname', name: 'cargoSupplierNickname',
align: 'left', align: 'left',
@ -171,7 +174,7 @@ const columns = computed(() => [
? value.reduce((sum, entry) => { ? value.reduce((sum, entry) => {
return sum + (entry.invoiceAmount || 0); return sum + (entry.invoiceAmount || 0);
}, 0) }, 0)
: 0 : 0,
), ),
}, },
{ {
@ -200,7 +203,7 @@ const columns = computed(() => [
sortable: true, sortable: true,
}, },
{ {
label: t('kg'), label: t('extraCommunity.kg'),
field: 'kg', field: 'kg',
name: 'kg', name: 'kg',
align: 'left', align: 'left',
@ -208,7 +211,7 @@ const columns = computed(() => [
sortable: true, sortable: true,
}, },
{ {
label: t('physicKg'), label: t('extraCommunity.physicKg'),
field: 'loadedKg', field: 'loadedKg',
name: 'loadedKg', name: 'loadedKg',
align: 'left', align: 'left',
@ -232,7 +235,7 @@ const columns = computed(() => [
sortable: true, sortable: true,
}, },
{ {
label: t('shipped'), label: t('extraCommunity.shipped'),
field: 'shipped', field: 'shipped',
name: 'shipped', name: 'shipped',
align: 'left', align: 'left',
@ -249,7 +252,7 @@ const columns = computed(() => [
sortable: true, sortable: true,
}, },
{ {
label: t('landed'), label: t('extraCommunity.landed'),
field: 'landed', field: 'landed',
name: 'landed', name: 'landed',
align: 'left', align: 'left',
@ -258,7 +261,7 @@ const columns = computed(() => [
format: (value) => toDate(value), format: (value) => toDate(value),
}, },
{ {
label: t('notes'), label: t('extraCommunity.notes'),
field: '', field: '',
name: 'notes', name: 'notes',
align: 'center', align: 'center',
@ -284,7 +287,7 @@ watch(
if (!arrayData.store.data) return; if (!arrayData.store.data) return;
onStoreDataChange(); onStoreDataChange();
}, },
{ deep: true, immediate: true } { deep: true, immediate: true },
); );
const openReportPdf = () => { const openReportPdf = () => {
@ -451,13 +454,24 @@ const getColor = (percentage) => {
for (const { value, className } of travelKgPercentages.value) for (const { value, className } of travelKgPercentages.value)
if (percentage > value) return className; if (percentage > value) return className;
}; };
const filteredEntries = (entries) => {
if (!tableParams?.value?.entrySupplierFk) return entries;
return entries?.filter(
(entry) => entry.supplierFk === tableParams?.value?.entrySupplierFk,
);
};
watch(route, () => {
tableParams.value = JSON.parse(route.query.table);
});
</script> </script>
<template> <template>
<VnSearchbar <VnSearchbar
data-key="ExtraCommunity" data-key="ExtraCommunity"
:limit="20" :limit="20"
:label="t('searchExtraCommunity')" :label="t('extraCommunity.searchExtraCommunity')"
/> />
<RightMenu> <RightMenu>
<template #right-panel> <template #right-panel>
@ -521,7 +535,7 @@ const getColor = (percentage) => {
? tableColumnComponents[col.name].event( ? tableColumnComponents[col.name].event(
rows[props.rowIndex][col.field], rows[props.rowIndex][col.field],
col.field, col.field,
props.rowIndex props.rowIndex,
) )
: {} : {}
" "
@ -546,7 +560,7 @@ const getColor = (percentage) => {
}, },
{ {
link: ['id', 'cargoSupplierNickname'].includes( link: ['id', 'cargoSupplierNickname'].includes(
col.name col.name,
), ),
}, },
]" ]"
@ -564,9 +578,8 @@ const getColor = (percentage) => {
</component> </component>
</QTd> </QTd>
</QTr> </QTr>
<QTr <QTr
v-for="(entry, index) in props.row.entries" v-for="(entry, index) in filteredEntries(props.row.entries)"
:key="index" :key="index"
:props="props" :props="props"
class="bg-vn-secondary-row cursor-pointer" class="bg-vn-secondary-row cursor-pointer"
@ -598,7 +611,7 @@ const getColor = (percentage) => {
name="warning" name="warning"
color="negative" color="negative"
size="md" size="md"
:title="t('requiresInspection')" :title="t('extraCommunity.requiresInspection')"
> >
</QIcon> </QIcon>
</QTd> </QTd>
@ -709,24 +722,3 @@ const getColor = (percentage) => {
width: max-content; width: max-content;
} }
</style> </style>
<i18n>
en:
searchExtraCommunity: Search for extra community shipping
kg: BI. KG
physicKg: Phy. KG
shipped: W. shipped
landed: W. landed
requiresInspection: Requires inspection
BIP: Boder Inspection Point
notes: Notes
es:
searchExtraCommunity: Buscar por envío extra comunitario
kg: KG Bloq.
physicKg: KG físico
shipped: F. envío
landed: F. llegada
notes: Notas
Open as PDF: Abrir como PDF
requiresInspection: Requiere inspección
BIP: Punto de Inspección Fronteriza
</i18n>

View File

@ -79,7 +79,7 @@ warehouses();
<VnFilterPanel :data-key="props.dataKey" :search-button="true"> <VnFilterPanel :data-key="props.dataKey" :search-button="true">
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong> <strong>{{ t(`extraCommunity.filter.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span> <span>{{ formatFn(tag.value) }}</span>
</div> </div>
</template> </template>
@ -92,7 +92,7 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnInput
:label="t('params.reference')" :label="t('extraCommunity.filter.reference')"
v-model="params.reference" v-model="params.reference"
is-outlined is-outlined
/> />
@ -103,7 +103,7 @@ warehouses();
<QInput <QInput
v-model="params.totalEntries" v-model="params.totalEntries"
type="number" type="number"
:label="t('params.totalEntries')" :label="t('extraCommunity.filter.totalEntries')"
dense dense
outlined outlined
rounded rounded
@ -133,10 +133,10 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelect
:label="t('params.agencyModeFk')" :label="t('extraCommunity.filter.agencyModeFk')"
v-model="params.agencyModeFk" v-model="params.agencyModeFk"
:options="agenciesOptions" :options="agenciesOptions"
option-value="agencyFk" option-value="id"
option-label="name" option-label="name"
hide-selected hide-selected
dense dense
@ -148,7 +148,7 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInputDate <VnInputDate
:label="t('params.shippedFrom')" :label="t('extraCommunity.filter.shippedFrom')"
v-model="params.shippedFrom" v-model="params.shippedFrom"
@update:model-value="searchFn()" @update:model-value="searchFn()"
is-outlined is-outlined
@ -158,7 +158,7 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInputDate <VnInputDate
:label="t('params.landedTo')" :label="t('extraCommunity.filter.landedTo')"
v-model="params.landedTo" v-model="params.landedTo"
@update:model-value="searchFn()" @update:model-value="searchFn()"
is-outlined is-outlined
@ -168,7 +168,7 @@ warehouses();
<QItem v-if="warehousesByContinent[params.continent]"> <QItem v-if="warehousesByContinent[params.continent]">
<QItemSection> <QItemSection>
<VnSelect <VnSelect
:label="t('params.warehouseOutFk')" :label="t('extraCommunity.filter.warehouseOutFk')"
v-model="params.warehouseOutFk" v-model="params.warehouseOutFk"
:options="warehousesByContinent[params.continent]" :options="warehousesByContinent[params.continent]"
option-value="id" option-value="id"
@ -183,7 +183,7 @@ warehouses();
<QItem v-else> <QItem v-else>
<QItemSection> <QItemSection>
<VnSelect <VnSelect
:label="t('params.warehouseOutFk')" :label="t('extraCommunity.filter.warehouseOutFk')"
v-model="params.warehouseOutFk" v-model="params.warehouseOutFk"
:options="warehousesOptions" :options="warehousesOptions"
option-value="id" option-value="id"
@ -198,7 +198,7 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelect
:label="t('params.warehouseInFk')" :label="t('extraCommunity.filter.warehouseInFk')"
v-model="params.warehouseInFk" v-model="params.warehouseInFk"
:options="warehousesOptions" :options="warehousesOptions"
option-value="id" option-value="id"
@ -213,6 +213,7 @@ warehouses();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelectSupplier <VnSelectSupplier
:label="t('extraCommunity.cargoShip')"
v-model="params.cargoSupplierFk" v-model="params.cargoSupplierFk"
hide-selected hide-selected
dense dense
@ -221,10 +222,21 @@ warehouses();
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnSelectSupplier
v-model="params.entrySupplierFk"
hide-selected
dense
outlined
rounded
/>
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelect
:label="t('params.continent')" :label="t('extraCommunity.filter.continent')"
v-model="params.continent" v-model="params.continent"
:options="continentsOptions" :options="continentsOptions"
option-value="code" option-value="code"
@ -240,30 +252,3 @@ warehouses();
</template> </template>
</VnFilterPanel> </VnFilterPanel>
</template> </template>
<i18n>
en:
params:
id: Id
reference: Reference
totalEntries: Total entries
agencyModeFk: Agency
warehouseInFk: Warehouse In
warehouseOutFk: Warehouse Out
shippedFrom: Shipped from
landedTo: Landed to
cargoSupplierFk: Supplier
continent: Continent out
es:
params:
id: Id
reference: Referencia
totalEntries: Ent. totales
agencyModeFk: Agencia
warehouseInFk: Alm. entrada
warehouseOutFk: Alm. salida
shippedFrom: Llegada desde
landedTo: Llegada hasta
cargoSupplierFk: Proveedor
continent: Cont. Salida
</i18n>

View File

@ -0,0 +1,22 @@
extraCommunity:
cargoShip: Cargo ship
searchExtraCommunity: Search for extra community shipping
kg: BI. KG
physicKg: Phy. KG
shipped: W. shipped
landed: W. landed
requiresInspection: Requires inspection
BIP: Boder Inspection Point
notes: Notes
filter:
id: Id
reference: Reference
totalEntries: Total entries
agencyModeFk: Agency
warehouseInFk: Warehouse In
warehouseOutFk: Warehouse Out
shippedFrom: Shipped from
landedTo: Landed to
cargoSupplierFk: Cargo supplier
continent: Continent out
entrySupplierFk: Supplier

View File

@ -0,0 +1,23 @@
extraCommunity:
cargoShip: Carguera
searchExtraCommunity: Buscar por envío extra comunitario
kg: KG Bloq.
physicKg: KG físico
shipped: F. envío
landed: F. llegada
notes: Notas
Open as PDF: Abrir como PDF
requiresInspection: Requiere inspección
BIP: Punto de Inspección Fronteriza
filter:
id: Id
reference: Referencia
totalEntries: Ent. totales
agencyModeFk: Agencia
warehouseInFk: Alm. entrada
warehouseOutFk: Alm. salida
shippedFrom: Llegada desde
landedTo: Llegada hasta
cargoSupplierFk: Carguera
continent: Cont. Salida
entrySupplierFk: Proveedor

View File

@ -25,7 +25,7 @@ const setFilteredAddresses = (data) => {
@on-fetch="(data) => (validAddresses = data)" @on-fetch="(data) => (validAddresses = data)"
/> />
<FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" /> <FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
<FormModel auto-load model="zone"> <FormModel auto-load model="Zone">
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow> <VnRow>
<VnInput <VnInput
@ -33,6 +33,7 @@ const setFilteredAddresses = (data) => {
:label="t('Name')" :label="t('Name')"
clearable clearable
v-model="data.name" v-model="data.name"
:required="true"
/> />
</VnRow> </VnRow>
<VnRow> <VnRow>
@ -83,7 +84,7 @@ const setFilteredAddresses = (data) => {
type="number" type="number"
min="0" min="0"
/> />
<VnInputTime v-model="data.hour" :label="t('Closing')" /> <VnInputTime v-model="data.hour" :label="t('Closing')" :required="true" />
</VnRow> </VnRow>
<VnRow> <VnRow>
@ -92,7 +93,7 @@ const setFilteredAddresses = (data) => {
:label="t('Price')" :label="t('Price')"
type="number" type="number"
min="0" min="0"
required="true" :required="true"
clearable clearable
/> />
<VnInput <VnInput
@ -100,7 +101,7 @@ const setFilteredAddresses = (data) => {
:label="t('Price optimum')" :label="t('Price optimum')"
type="number" type="number"
min="0" min="0"
required="true" :required="true"
clearable clearable
/> />
</VnRow> </VnRow>

View File

@ -38,7 +38,12 @@ const agencies = ref([]);
<template #body="{ params, searchFn }"> <template #body="{ params, searchFn }">
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput :label="t('list.name')" v-model="params.name" is-outlined /> <VnInput
:label="t('list.name')"
v-model="params.name"
is-outlined
data-cy="zoneFilterPanelNameInput"
/>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
@ -53,6 +58,7 @@ const agencies = ref([]);
dense dense
outlined outlined
rounded rounded
data-cy="zoneFilterPanelAgencySelect"
> >
</VnSelect> </VnSelect>
</QItemSection> </QItemSection>

View File

@ -65,7 +65,6 @@ const tableFilter = {
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left',
name: 'id', name: 'id',
label: t('list.id'), label: t('list.id'),
chip: { chip: {
@ -75,6 +74,8 @@ const columns = computed(() => [
columnFilter: { columnFilter: {
inWhere: true, inWhere: true,
}, },
columnClass: 'shrink-column',
component: 'number',
}, },
{ {
align: 'left', align: 'left',
@ -106,7 +107,6 @@ const columns = computed(() => [
format: (row, dashIfEmpty) => dashIfEmpty(row?.agencyMode?.name), format: (row, dashIfEmpty) => dashIfEmpty(row?.agencyMode?.name),
}, },
{ {
align: 'left',
name: 'price', name: 'price',
label: t('list.price'), label: t('list.price'),
cardVisible: true, cardVisible: true,
@ -114,9 +114,11 @@ const columns = computed(() => [
columnFilter: { columnFilter: {
inWhere: true, inWhere: true,
}, },
columnClass: 'shrink-column',
component: 'number',
}, },
{ {
align: 'left', align: 'center',
name: 'hour', name: 'hour',
label: t('list.close'), label: t('list.close'),
cardVisible: true, cardVisible: true,
@ -129,6 +131,7 @@ const columns = computed(() => [
label: t('list.addressFk'), label: t('list.addressFk'),
cardVisible: true, cardVisible: true,
columnFilter: false, columnFilter: false,
columnClass: 'expand',
}, },
{ {
align: 'right', align: 'right',
@ -177,67 +180,73 @@ function formatRow(row) {
<ZoneFilterPanel data-key="ZonesList" /> <ZoneFilterPanel data-key="ZonesList" />
</template> </template>
</RightMenu> </RightMenu>
<VnTable <div class="table-container">
ref="tableRef" <div class="column items-center">
data-key="ZonesList" <VnTable
url="Zones" ref="tableRef"
:create="{ data-key="ZonesList"
urlCreate: 'Zones', url="Zones"
title: t('list.createZone'), :create="{
onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`), urlCreate: 'Zones',
formInitialData: {}, title: t('list.createZone'),
}" onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`),
:user-filter="tableFilter" formInitialData: {},
:columns="columns" }"
redirect="zone" :user-filter="tableFilter"
:right-search="false" :columns="columns"
> redirect="zone"
<template #column-addressFk="{ row }"> :right-search="false"
{{ dashIfEmpty(formatRow(row)) }} table-height="85vh"
</template> order="id ASC"
<template #more-create-dialog="{ data }"> >
<VnSelect <template #column-addressFk="{ row }">
url="AgencyModes" {{ dashIfEmpty(formatRow(row)) }}
v-model="data.agencyModeFk" </template>
option-value="id" <template #more-create-dialog="{ data }">
option-label="name" <VnSelect
:label="t('list.agency')" url="AgencyModes"
/> v-model="data.agencyModeFk"
<VnInput option-value="id"
v-model="data.price" option-label="name"
:label="t('list.price')" :label="t('list.agency')"
min="0" />
type="number" <VnInput
required="true" v-model="data.price"
/> :label="t('list.price')"
<VnInput min="0"
v-model="data.bonus" type="number"
:label="t('zone.bonus')" required="true"
min="0" />
type="number" <VnInput
/> v-model="data.bonus"
<VnInput :label="t('zone.bonus')"
v-model="data.travelingDays" min="0"
:label="t('zone.travelingDays')" type="number"
type="number" />
min="0" <VnInput
/> v-model="data.travelingDays"
<VnInputTime v-model="data.hour" :label="t('list.close')" /> :label="t('zone.travelingDays')"
<VnSelect type="number"
url="Warehouses" min="0"
v-model="data.warehouseFK" />
option-value="id" <VnInputTime v-model="data.hour" :label="t('list.close')" />
option-label="name" <VnSelect
:label="t('list.warehouse')" url="Warehouses"
:options="warehouseOptions" v-model="data.warehouseFK"
/> option-value="id"
<QCheckbox option-label="name"
v-model="data.isVolumetric" :label="t('list.warehouse')"
:label="t('list.isVolumetric')" :options="warehouseOptions"
:toggle-indeterminate="false" />
/> <QCheckbox
</template> v-model="data.isVolumetric"
</VnTable> :label="t('list.isVolumetric')"
:toggle-indeterminate="false"
/>
</template>
</VnTable>
</div>
</div>
</template> </template>
<i18n> <i18n>
@ -245,3 +254,20 @@ es:
Search zone: Buscar zona Search zone: Buscar zona
You can search zones by id or name: Puedes buscar zonas por id o nombre You can search zones by id or name: Puedes buscar zonas por id o nombre
</i18n> </i18n>
<style lang="scss" scoped>
.table-container {
display: flex;
justify-content: center;
}
.column {
display: flex;
flex-direction: column;
align-items: center;
min-width: 70%;
}
:deep(.shrink-column) {
width: 8%;
}
</style>

View File

@ -56,7 +56,7 @@ onMounted(() => weekdayStore.initStore());
<ZoneSearchbar /> <ZoneSearchbar />
<VnSubToolbar /> <VnSubToolbar />
<QPage class="column items-center q-pa-md"> <QPage class="column items-center q-pa-md">
<QCard class="full-width q-pa-md"> <QCard class="containerShrinked q-pa-md">
<div <div
v-for="(detail, index) in details" v-for="(detail, index) in details"
:key="index" :key="index"

View File

@ -44,6 +44,8 @@ summary:
filterPanel: filterPanel:
name: Name name: Name
agencyModeFk: Agency agencyModeFk: Agency
id: ID
price: Price
deliveryPanel: deliveryPanel:
pickup: Pick up pickup: Pick up
delivery: Delivery delivery: Delivery

View File

@ -45,6 +45,8 @@ summary:
filterPanel: filterPanel:
name: Nombre name: Nombre
agencyModeFk: Agencia agencyModeFk: Agencia
id: ID
price: Precio
deliveryPanel: deliveryPanel:
pickup: Recogida pickup: Recogida
delivery: Entrega delivery: Entrega

View File

@ -1,4 +1,5 @@
describe('ZoneList', () => { describe('ZoneList', () => {
const agency = 'inhouse pickup';
beforeEach(() => { beforeEach(() => {
cy.viewport(1280, 720); cy.viewport(1280, 720);
cy.login('developer'); cy.login('developer');
@ -6,11 +7,15 @@ describe('ZoneList', () => {
}); });
it('should filter by agency', () => { it('should filter by agency', () => {
cy.get('input[aria-label="Agency"]').type('{downArrow}{enter}'); cy.dataCy('zoneFilterPanelNameInput').type('{downArrow}{enter}');
}); });
it('should open the zone summary', () => { it('should open the zone summary', () => {
cy.get('input[aria-label="Name"]').type('zone refund'); cy.dataCy('zoneFilterPanelAgencySelect').type(agency);
cy.get('.q-scrollarea__content > .q-btn--standard > .q-btn__content').click(); cy.get('.q-menu .q-item').contains(agency).click();
cy.get(':nth-child(1) > [data-col-field="agencyModeFk"]').should(
'include.text',
agency,
);
}); });
}); });