Compare commits
19 Commits
dev
...
7731-clien
Author | SHA1 | Date |
---|---|---|
|
307355ba3f | |
|
4e85e30e41 | |
|
fe3ea3fa6a | |
|
0c3650c9e3 | |
|
da0540a748 | |
|
9ecb734b1b | |
|
f019c55b72 | |
|
d966be60da | |
|
c884c09943 | |
|
32191fe713 | |
|
fdaa3ea72a | |
|
dab45277da | |
|
4de85126cd | |
|
08f247900a | |
|
82fce46999 | |
|
6b99039e68 | |
|
6e164cda14 | |
|
6d0e99faa3 | |
|
5a1317da77 |
|
@ -14,8 +14,8 @@ export default defineConfig({
|
||||||
downloadsFolder: 'test/cypress/downloads',
|
downloadsFolder: 'test/cypress/downloads',
|
||||||
video: false,
|
video: false,
|
||||||
specPattern: 'test/cypress/integration/**/*.spec.js',
|
specPattern: 'test/cypress/integration/**/*.spec.js',
|
||||||
experimentalRunAllSpecs: false,
|
experimentalRunAllSpecs: true,
|
||||||
watchForFileChanges: false,
|
watchForFileChanges: true,
|
||||||
reporter: 'cypress-mochawesome-reporter',
|
reporter: 'cypress-mochawesome-reporter',
|
||||||
reporterOptions: {
|
reporterOptions: {
|
||||||
charts: true,
|
charts: true,
|
||||||
|
|
|
@ -30,6 +30,7 @@ export default configure(function (/* ctx */) {
|
||||||
// --> boot files are part of "main.js"
|
// --> boot files are part of "main.js"
|
||||||
// https://v2.quasar.dev/quasar-cli/boot-files
|
// https://v2.quasar.dev/quasar-cli/boot-files
|
||||||
boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'],
|
boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'],
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||||
css: ['app.scss'],
|
css: ['app.scss'],
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const langs = ['en', 'es'];
|
|
||||||
export const decimalPlaces = 2;
|
|
|
@ -51,5 +51,4 @@ export default boot(({ app }) => {
|
||||||
|
|
||||||
await useCau(response, message);
|
await useCau(response, message);
|
||||||
};
|
};
|
||||||
app.provide('app', app);
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -64,10 +64,6 @@ const $props = defineProps({
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
beforeSaveFn: {
|
|
||||||
type: Function,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
goTo: {
|
goTo: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
|
@ -180,11 +176,7 @@ async function saveChanges(data) {
|
||||||
hasChanges.value = false;
|
hasChanges.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let changes = data || getChanges();
|
const changes = data || getChanges();
|
||||||
if ($props.beforeSaveFn) {
|
|
||||||
changes = await $props.beforeSaveFn(changes, getChanges);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios.post($props.saveUrl || $props.url + '/crud', changes);
|
await axios.post($props.saveUrl || $props.url + '/crud', changes);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -237,12 +229,12 @@ async function remove(data) {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
title: t('globals.confirmDeletion'),
|
title: t('globals.confirmDeletion'),
|
||||||
message: t('globals.confirmDeletionMessage'),
|
message: t('globals.confirmDeletionMessage'),
|
||||||
data: { deletes: ids },
|
newData,
|
||||||
ids,
|
ids,
|
||||||
promise: saveChanges,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.onOk(async () => {
|
.onOk(async () => {
|
||||||
|
await saveChanges({ deletes: ids });
|
||||||
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
|
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
|
||||||
fetch(newData);
|
fetch(newData);
|
||||||
});
|
});
|
||||||
|
@ -382,8 +374,6 @@ watch(formUrl, async () => {
|
||||||
@click="onSubmit"
|
@click="onSubmit"
|
||||||
:disable="!hasChanges"
|
:disable="!hasChanges"
|
||||||
:title="t('globals.save')"
|
:title="t('globals.save')"
|
||||||
v-shortcut="'s'"
|
|
||||||
shortcut="s"
|
|
||||||
data-cy="crudModelDefaultSaveBtn"
|
data-cy="crudModelDefaultSaveBtn"
|
||||||
/>
|
/>
|
||||||
<slot name="moreAfterActions" />
|
<slot name="moreAfterActions" />
|
||||||
|
|
|
@ -181,7 +181,6 @@ const selectTravel = ({ id }) => {
|
||||||
color="primary"
|
color="primary"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
data-cy="save-filter-travel-form"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<QTable
|
<QTable
|
||||||
|
@ -192,10 +191,9 @@ const selectTravel = ({ id }) => {
|
||||||
:no-data-label="t('Enter a new search')"
|
:no-data-label="t('Enter a new search')"
|
||||||
class="q-mt-lg"
|
class="q-mt-lg"
|
||||||
@row-click="(_, row) => selectTravel(row)"
|
@row-click="(_, row) => selectTravel(row)"
|
||||||
data-cy="table-filter-travel-form"
|
|
||||||
>
|
>
|
||||||
<template #body-cell-id="{ row }">
|
<template #body-cell-id="{ row }">
|
||||||
<QTd auto-width @click.stop data-cy="travelFk-travel-form">
|
<QTd auto-width @click.stop>
|
||||||
<QBtn flat color="blue">{{ row.id }}</QBtn>
|
<QBtn flat color="blue">{{ row.id }}</QBtn>
|
||||||
<TravelDescriptorProxy :id="row.id" />
|
<TravelDescriptorProxy :id="row.id" />
|
||||||
</QTd>
|
</QTd>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
@ -15,30 +15,23 @@ defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
showSaveAndContinueBtn: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const formModelRef = ref(null);
|
const formModelRef = ref(null);
|
||||||
const closeButton = ref(null);
|
const closeButton = ref(null);
|
||||||
const isSaveAndContinue = ref(false);
|
|
||||||
const onDataSaved = (formData, requestResponse) => {
|
const onDataSaved = (formData, requestResponse) => {
|
||||||
if (closeButton.value && isSaveAndContinue) closeButton.value.click();
|
if (closeButton.value) closeButton.value.click();
|
||||||
emit('onDataSaved', formData, requestResponse);
|
emit('onDataSaved', formData, requestResponse);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isLoading = computed(() => formModelRef.value?.isLoading);
|
const isLoading = computed(() => formModelRef.value?.isLoading);
|
||||||
const reset = computed(() => formModelRef.value?.reset);
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
isLoading,
|
isLoading,
|
||||||
onDataSaved,
|
onDataSaved,
|
||||||
isSaveAndContinue,
|
|
||||||
reset,
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -58,19 +51,6 @@ defineExpose({
|
||||||
<p>{{ subtitle }}</p>
|
<p>{{ subtitle }}</p>
|
||||||
<slot name="form-inputs" :data="data" :validate="validate" />
|
<slot name="form-inputs" :data="data" :validate="validate" />
|
||||||
<div class="q-mt-lg row justify-end">
|
<div class="q-mt-lg row justify-end">
|
||||||
<QBtn
|
|
||||||
v-if="showSaveAndContinueBtn"
|
|
||||||
:label="t('globals.isSaveAndContinue')"
|
|
||||||
:title="t('globals.isSaveAndContinue')"
|
|
||||||
type="submit"
|
|
||||||
color="primary"
|
|
||||||
class="q-ml-sm"
|
|
||||||
:disabled="isLoading"
|
|
||||||
:loading="isLoading"
|
|
||||||
data-cy="FormModelPopup_isSaveAndContinue"
|
|
||||||
z-max
|
|
||||||
@click="() => (isSaveAndContinue = true)"
|
|
||||||
/>
|
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('globals.cancel')"
|
:label="t('globals.cancel')"
|
||||||
:title="t('globals.cancel')"
|
:title="t('globals.cancel')"
|
||||||
|
@ -79,15 +59,10 @@ defineExpose({
|
||||||
flat
|
flat
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
data-cy="FormModelPopup_cancel"
|
@click="emit('onDataCanceled')"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
|
data-cy="FormModelPopup_cancel"
|
||||||
z-max
|
z-max
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
isSaveAndContinue = false;
|
|
||||||
emit('onDataCanceled');
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('globals.save')"
|
:label="t('globals.save')"
|
||||||
|
@ -99,7 +74,6 @@ defineExpose({
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
data-cy="FormModelPopup_save"
|
data-cy="FormModelPopup_save"
|
||||||
z-max
|
z-max
|
||||||
@click="() => (isSaveAndContinue = false)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -328,6 +328,7 @@ en:
|
||||||
active: Is active
|
active: Is active
|
||||||
visible: Is visible
|
visible: Is visible
|
||||||
floramondo: Is floramondo
|
floramondo: Is floramondo
|
||||||
|
salesPersonFk: Buyer
|
||||||
categoryFk: Category
|
categoryFk: Category
|
||||||
|
|
||||||
es:
|
es:
|
||||||
|
@ -338,6 +339,7 @@ es:
|
||||||
active: Activo
|
active: Activo
|
||||||
visible: Visible
|
visible: Visible
|
||||||
floramondo: Floramondo
|
floramondo: Floramondo
|
||||||
|
salesPersonFk: Comprador
|
||||||
categoryFk: Categoría
|
categoryFk: Categoría
|
||||||
Plant: Planta natural
|
Plant: Planta natural
|
||||||
Flower: Flor fresca
|
Flower: Flor fresca
|
||||||
|
|
|
@ -26,7 +26,6 @@ const itemComputed = computed(() => {
|
||||||
:to="{ name: itemComputed.name }"
|
:to="{ name: itemComputed.name }"
|
||||||
clickable
|
clickable
|
||||||
v-ripple
|
v-ripple
|
||||||
:data-cy="`${itemComputed.name}-menu-item`"
|
|
||||||
>
|
>
|
||||||
<QItemSection avatar v-if="itemComputed.icon">
|
<QItemSection avatar v-if="itemComputed.icon">
|
||||||
<QIcon :name="itemComputed.icon" />
|
<QIcon :name="itemComputed.icon" />
|
||||||
|
|
|
@ -9,7 +9,6 @@ import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import FormPopup from './FormPopup.vue';
|
import FormPopup from './FormPopup.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
invoiceOutData: {
|
invoiceOutData: {
|
||||||
|
@ -132,11 +131,15 @@ const refund = async () => {
|
||||||
:required="true"
|
:required="true"
|
||||||
/> </VnRow
|
/> </VnRow
|
||||||
><VnRow>
|
><VnRow>
|
||||||
<VnCheckbox
|
<div>
|
||||||
v-model="invoiceParams.inheritWarehouse"
|
<QCheckbox
|
||||||
:label="t('Inherit warehouse')"
|
:label="t('Inherit warehouse')"
|
||||||
:info="t('Inherit warehouse tooltip')"
|
v-model="invoiceParams.inheritWarehouse"
|
||||||
/>
|
/>
|
||||||
|
<QIcon name="info" class="cursor-info q-ml-sm" size="sm">
|
||||||
|
<QTooltip>{{ t('Inherit warehouse tooltip') }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormPopup>
|
</FormPopup>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import FormPopup from './FormPopup.vue';
|
import FormPopup from './FormPopup.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import VnCheckbox from './common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
invoiceOutData: {
|
invoiceOutData: {
|
||||||
|
@ -187,11 +186,15 @@ const makeInvoice = async () => {
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnCheckbox
|
<div>
|
||||||
v-model="checked"
|
<QCheckbox
|
||||||
:label="t('Bill destination client')"
|
:label="t('Bill destination client')"
|
||||||
:info="t('transferInvoiceInfo')"
|
v-model="checked"
|
||||||
/>
|
/>
|
||||||
|
<QIcon name="info" class="cursor-info q-ml-sm" size="sm">
|
||||||
|
<QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormPopup>
|
</FormPopup>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw, computed } from 'vue';
|
import { markRaw, computed } from 'vue';
|
||||||
import { QIcon, QCheckbox, QToggle } from 'quasar';
|
import { QIcon, QCheckbox } from 'quasar';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
import { dashIfEmpty } from 'src/filters';
|
||||||
|
|
||||||
|
/* basic input */
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnSelectCache from 'components/common/VnSelectCache.vue';
|
import VnSelectCache from 'components/common/VnSelectCache.vue';
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
|
@ -11,11 +12,8 @@ import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||||
import VnComponent from 'components/common/VnComponent.vue';
|
import VnComponent from 'components/common/VnComponent.vue';
|
||||||
import VnUserLink from 'components/ui/VnUserLink.vue';
|
import VnUserLink from 'components/ui/VnUserLink.vue';
|
||||||
import VnSelectEnum from '../common/VnSelectEnum.vue';
|
|
||||||
import VnCheckbox from '../common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const model = defineModel(undefined, { required: true });
|
const model = defineModel(undefined, { required: true });
|
||||||
const emit = defineEmits(['blur']);
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
column: {
|
column: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -41,18 +39,10 @@ const $props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
autofocus: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
showLabel: {
|
showLabel: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
eventHandlers: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultSelect = {
|
const defaultSelect = {
|
||||||
|
@ -109,8 +99,7 @@ const defaultComponents = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
checkbox: {
|
checkbox: {
|
||||||
ref: 'checkbox',
|
component: markRaw(QCheckbox),
|
||||||
component: markRaw(VnCheckbox),
|
|
||||||
attrs: ({ model }) => {
|
attrs: ({ model }) => {
|
||||||
const defaultAttrs = {
|
const defaultAttrs = {
|
||||||
disable: !$props.isEditable,
|
disable: !$props.isEditable,
|
||||||
|
@ -126,10 +115,6 @@ const defaultComponents = {
|
||||||
},
|
},
|
||||||
forceAttrs: {
|
forceAttrs: {
|
||||||
label: $props.showLabel && $props.column.label,
|
label: $props.showLabel && $props.column.label,
|
||||||
autofocus: true,
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
blur: () => emit('blur'),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
|
@ -140,19 +125,12 @@ const defaultComponents = {
|
||||||
component: markRaw(VnSelect),
|
component: markRaw(VnSelect),
|
||||||
...defaultSelect,
|
...defaultSelect,
|
||||||
},
|
},
|
||||||
selectEnum: {
|
|
||||||
component: markRaw(VnSelectEnum),
|
|
||||||
...defaultSelect,
|
|
||||||
},
|
|
||||||
icon: {
|
icon: {
|
||||||
component: markRaw(QIcon),
|
component: markRaw(QIcon),
|
||||||
},
|
},
|
||||||
userLink: {
|
userLink: {
|
||||||
component: markRaw(VnUserLink),
|
component: markRaw(VnUserLink),
|
||||||
},
|
},
|
||||||
toggle: {
|
|
||||||
component: markRaw(QToggle),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const value = computed(() => {
|
const value = computed(() => {
|
||||||
|
@ -182,28 +160,7 @@ const col = computed(() => {
|
||||||
return newColumn;
|
return newColumn;
|
||||||
});
|
});
|
||||||
|
|
||||||
const components = computed(() => {
|
const components = computed(() => $props.components ?? defaultComponents);
|
||||||
const sourceComponents = $props.components ?? defaultComponents;
|
|
||||||
|
|
||||||
return Object.keys(sourceComponents).reduce((acc, key) => {
|
|
||||||
const component = sourceComponents[key];
|
|
||||||
|
|
||||||
if (!component || typeof component !== 'object') {
|
|
||||||
acc[key] = component;
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
acc[key] = {
|
|
||||||
...component,
|
|
||||||
attrs: {
|
|
||||||
...(component.attrs || {}),
|
|
||||||
autofocus: $props.autofocus,
|
|
||||||
},
|
|
||||||
event: { ...component?.event, ...$props?.eventHandlers },
|
|
||||||
};
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="row no-wrap">
|
<div class="row no-wrap">
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw, computed } from 'vue';
|
import { markRaw, computed } from 'vue';
|
||||||
import { QCheckbox, QToggle } from 'quasar';
|
import { QCheckbox } from 'quasar';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
|
/* basic input */
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||||
import VnColumn from 'components/VnTable/VnColumn.vue';
|
import VnTableColumn from 'components/VnTable/VnColumn.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
column: {
|
column: {
|
||||||
|
@ -25,10 +27,6 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: 'table',
|
default: 'table',
|
||||||
},
|
},
|
||||||
customClass: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose({ addFilter, props: $props });
|
defineExpose({ addFilter, props: $props });
|
||||||
|
@ -36,7 +34,7 @@ defineExpose({ addFilter, props: $props });
|
||||||
const model = defineModel(undefined, { required: true });
|
const model = defineModel(undefined, { required: true });
|
||||||
const arrayData = useArrayData(
|
const arrayData = useArrayData(
|
||||||
$props.dataKey,
|
$props.dataKey,
|
||||||
$props.searchUrl ? { searchUrl: $props.searchUrl } : null,
|
$props.searchUrl ? { searchUrl: $props.searchUrl } : null
|
||||||
);
|
);
|
||||||
const columnFilter = computed(() => $props.column?.columnFilter);
|
const columnFilter = computed(() => $props.column?.columnFilter);
|
||||||
|
|
||||||
|
@ -48,18 +46,19 @@ const enterEvent = {
|
||||||
|
|
||||||
const defaultAttrs = {
|
const defaultAttrs = {
|
||||||
filled: !$props.showTitle,
|
filled: !$props.showTitle,
|
||||||
|
class: 'q-px-xs q-pb-xs q-pt-none fit',
|
||||||
dense: true,
|
dense: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const forceAttrs = {
|
const forceAttrs = {
|
||||||
label: $props.showTitle ? '' : (columnFilter.value?.label ?? $props.column.label),
|
label: $props.showTitle ? '' : columnFilter.value?.label ?? $props.column.label,
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectComponent = {
|
const selectComponent = {
|
||||||
component: markRaw(VnSelect),
|
component: markRaw(VnSelect),
|
||||||
event: updateEvent,
|
event: updateEvent,
|
||||||
attrs: {
|
attrs: {
|
||||||
class: `q-pt-none fit ${$props.customClass}`,
|
class: 'q-px-sm q-pb-xs q-pt-none fit',
|
||||||
dense: true,
|
dense: true,
|
||||||
filled: !$props.showTitle,
|
filled: !$props.showTitle,
|
||||||
},
|
},
|
||||||
|
@ -110,24 +109,14 @@ const components = {
|
||||||
component: markRaw(QCheckbox),
|
component: markRaw(QCheckbox),
|
||||||
event: updateEvent,
|
event: updateEvent,
|
||||||
attrs: {
|
attrs: {
|
||||||
class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
|
dense: true,
|
||||||
|
class: $props.showTitle ? 'q-py-sm q-mt-md' : 'q-px-md q-py-xs fit',
|
||||||
'toggle-indeterminate': true,
|
'toggle-indeterminate': true,
|
||||||
size: 'sm',
|
|
||||||
},
|
},
|
||||||
forceAttrs,
|
forceAttrs,
|
||||||
},
|
},
|
||||||
select: selectComponent,
|
select: selectComponent,
|
||||||
rawSelect: selectComponent,
|
rawSelect: selectComponent,
|
||||||
toggle: {
|
|
||||||
component: markRaw(QToggle),
|
|
||||||
event: updateEvent,
|
|
||||||
attrs: {
|
|
||||||
class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
|
|
||||||
'toggle-indeterminate': true,
|
|
||||||
size: 'sm',
|
|
||||||
},
|
|
||||||
forceAttrs,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function addFilter(value, name) {
|
async function addFilter(value, name) {
|
||||||
|
@ -143,8 +132,19 @@ async function addFilter(value, name) {
|
||||||
await arrayData.addFilter({ params: { [field]: value } });
|
await arrayData.addFilter({ params: { [field]: value } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function alignRow() {
|
||||||
|
switch ($props.column.align) {
|
||||||
|
case 'left':
|
||||||
|
return 'justify-start items-start';
|
||||||
|
case 'right':
|
||||||
|
return 'justify-end items-end';
|
||||||
|
default:
|
||||||
|
return 'flex-center';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const showFilter = computed(
|
const showFilter = computed(
|
||||||
() => $props.column?.columnFilter !== false && $props.column.name != 'tableActions',
|
() => $props.column?.columnFilter !== false && $props.column.name != 'tableActions'
|
||||||
);
|
);
|
||||||
|
|
||||||
const onTabPressed = async () => {
|
const onTabPressed = async () => {
|
||||||
|
@ -152,8 +152,13 @@ const onTabPressed = async () => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div v-if="showFilter" class="full-width flex-center" style="overflow: hidden">
|
<div
|
||||||
<VnColumn
|
v-if="showFilter"
|
||||||
|
class="full-width"
|
||||||
|
:class="alignRow()"
|
||||||
|
style="max-height: 45px; overflow: hidden"
|
||||||
|
>
|
||||||
|
<VnTableColumn
|
||||||
:column="$props.column"
|
:column="$props.column"
|
||||||
default="input"
|
default="input"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
@ -163,8 +168,3 @@ const onTabPressed = async () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
|
||||||
label.vn-label-padding > .q-field__inner > .q-field__control {
|
|
||||||
padding: inherit !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ async function orderBy(name, direction) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!direction) return await arrayData.deleteOrder(name);
|
if (!direction) return await arrayData.deleteOrder(name);
|
||||||
|
|
||||||
await arrayData.addOrder(name, direction);
|
await arrayData.addOrder(name, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,11 +51,11 @@ defineExpose({ orderBy });
|
||||||
@mouseenter="hover = true"
|
@mouseenter="hover = true"
|
||||||
@mouseleave="hover = false"
|
@mouseleave="hover = false"
|
||||||
@click="orderBy(name, model?.direction)"
|
@click="orderBy(name, model?.direction)"
|
||||||
class="row items-center no-wrap cursor-pointer title"
|
class="row items-center no-wrap cursor-pointer"
|
||||||
>
|
>
|
||||||
<span :title="label">{{ label }}</span>
|
<span :title="label">{{ label }}</span>
|
||||||
<sup v-if="name && model?.index">
|
|
||||||
<QChip
|
<QChip
|
||||||
|
v-if="name"
|
||||||
:label="!vertical ? model?.index : ''"
|
:label="!vertical ? model?.index : ''"
|
||||||
:icon="
|
:icon="
|
||||||
(model?.index || hover) && !vertical
|
(model?.index || hover) && !vertical
|
||||||
|
@ -72,7 +71,7 @@ defineExpose({ orderBy });
|
||||||
]"
|
]"
|
||||||
class="no-box-shadow"
|
class="no-box-shadow"
|
||||||
:clickable="true"
|
:clickable="true"
|
||||||
style="min-width: 40px; max-height: 30px"
|
style="min-width: 40px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="column flex-center"
|
class="column flex-center"
|
||||||
|
@ -92,20 +91,5 @@ defineExpose({ orderBy });
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</QChip>
|
</QChip>
|
||||||
</sup>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 30px;
|
|
||||||
width: 100%;
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
}
|
|
||||||
sup {
|
|
||||||
vertical-align: super; /* Valor predeterminado */
|
|
||||||
/* También puedes usar otros valores como "baseline", "top", "text-top", etc. */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,37 +1,22 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { ref, onBeforeMount, onMounted, computed, watch, useAttrs } from 'vue';
|
||||||
ref,
|
|
||||||
onBeforeMount,
|
|
||||||
onMounted,
|
|
||||||
onUnmounted,
|
|
||||||
computed,
|
|
||||||
watch,
|
|
||||||
h,
|
|
||||||
render,
|
|
||||||
inject,
|
|
||||||
useAttrs,
|
|
||||||
} from 'vue';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
|
||||||
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 { useQuasar } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useFilterParams } from 'src/composables/useFilterParams';
|
import { useFilterParams } from 'src/composables/useFilterParams';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
|
||||||
|
|
||||||
import CrudModel from 'src/components/CrudModel.vue';
|
import CrudModel from 'src/components/CrudModel.vue';
|
||||||
import FormModelPopup from 'components/FormModelPopup.vue';
|
import FormModelPopup from 'components/FormModelPopup.vue';
|
||||||
|
|
||||||
import VnColumn from 'components/VnTable/VnColumn.vue';
|
import VnTableColumn from 'components/VnTable/VnColumn.vue';
|
||||||
import VnFilter from 'components/VnTable/VnFilter.vue';
|
import VnFilter from 'components/VnTable/VnFilter.vue';
|
||||||
import VnTableChip from 'components/VnTable/VnChip.vue';
|
import VnTableChip from 'components/VnTable/VnChip.vue';
|
||||||
import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
|
import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
|
import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
|
||||||
import VnTableFilter from './VnTableFilter.vue';
|
import VnTableFilter from './VnTableFilter.vue';
|
||||||
import { getColAlign } from 'src/composables/getColAlign';
|
|
||||||
|
|
||||||
const arrayData = useArrayData(useAttrs()['data-key']);
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
columns: {
|
columns: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -57,6 +42,10 @@ const $props = defineProps({
|
||||||
type: [Function, Boolean],
|
type: [Function, Boolean],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
rowCtrlClick: {
|
||||||
|
type: [Function, Boolean],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
redirect: {
|
redirect: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
|
@ -125,19 +114,7 @@ const $props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
withFilters: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
overlay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
createComplement: {
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -155,18 +132,10 @@ const showForm = ref(false);
|
||||||
const splittedColumns = ref({ columns: [] });
|
const splittedColumns = ref({ columns: [] });
|
||||||
const columnsVisibilitySkipped = ref();
|
const columnsVisibilitySkipped = ref();
|
||||||
const createForm = ref();
|
const createForm = ref();
|
||||||
const createRef = ref(null);
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const params = ref(useFilterParams($attrs['data-key']).params);
|
const params = ref(useFilterParams($attrs['data-key']).params);
|
||||||
const orders = ref(useFilterParams($attrs['data-key']).orders);
|
const orders = ref(useFilterParams($attrs['data-key']).orders);
|
||||||
const app = inject('app');
|
|
||||||
|
|
||||||
const editingRow = ref(null);
|
|
||||||
const editingField = ref(null);
|
|
||||||
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
|
||||||
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
|
|
||||||
const selectRegex = /select/;
|
|
||||||
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
|
||||||
const tableModes = [
|
const tableModes = [
|
||||||
{
|
{
|
||||||
icon: 'view_column',
|
icon: 'view_column',
|
||||||
|
@ -187,8 +156,7 @@ onBeforeMount(() => {
|
||||||
hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
|
hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
if ($props.isEditable) document.addEventListener('click', clickHandler);
|
|
||||||
mode.value =
|
mode.value =
|
||||||
quasar.platform.is.mobile && !$props.disableOption?.card
|
quasar.platform.is.mobile && !$props.disableOption?.card
|
||||||
? CARD_MODE
|
? CARD_MODE
|
||||||
|
@ -210,25 +178,14 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(async () => {
|
|
||||||
if ($props.isEditable) document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => $props.columns,
|
() => $props.columns,
|
||||||
(value) => splitColumns(value),
|
(value) => splitColumns(value),
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
defineExpose({
|
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
||||||
create: createForm,
|
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
|
||||||
reload,
|
|
||||||
redirect: redirectFn,
|
|
||||||
selected,
|
|
||||||
CrudModelRef,
|
|
||||||
params,
|
|
||||||
tableRef,
|
|
||||||
});
|
|
||||||
|
|
||||||
function splitColumns(columns) {
|
function splitColumns(columns) {
|
||||||
splittedColumns.value = {
|
splittedColumns.value = {
|
||||||
|
@ -274,6 +231,16 @@ const rowClickFunction = computed(() => {
|
||||||
return () => {};
|
return () => {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rowCtrlClickFunction = computed(() => {
|
||||||
|
if ($props.rowCtrlClick != undefined) return $props.rowCtrlClick;
|
||||||
|
if ($props.redirect)
|
||||||
|
return (evt, { id }) => {
|
||||||
|
stopEventPropagation(evt);
|
||||||
|
window.open(`/#/${$props.redirect}/${id}`, '_blank');
|
||||||
|
};
|
||||||
|
return () => {};
|
||||||
|
});
|
||||||
|
|
||||||
function redirectFn(id) {
|
function redirectFn(id) {
|
||||||
router.push({ path: `/${$props.redirect}/${id}` });
|
router.push({ path: `/${$props.redirect}/${id}` });
|
||||||
}
|
}
|
||||||
|
@ -295,6 +262,21 @@ function columnName(col) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getColAlign(col) {
|
||||||
|
return 'text-' + (col.align ?? 'left');
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
||||||
|
defineExpose({
|
||||||
|
create: createForm,
|
||||||
|
reload,
|
||||||
|
redirect: redirectFn,
|
||||||
|
selected,
|
||||||
|
CrudModelRef,
|
||||||
|
params,
|
||||||
|
tableRef,
|
||||||
|
});
|
||||||
|
|
||||||
function handleOnDataSaved(_) {
|
function handleOnDataSaved(_) {
|
||||||
if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
|
if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
|
||||||
else $props.create.onDataSaved(_);
|
else $props.create.onDataSaved(_);
|
||||||
|
@ -322,214 +304,6 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEditableColumn(column) {
|
|
||||||
const isEditableCol = column?.isEditable ?? true;
|
|
||||||
const isVisible = column?.visible ?? true;
|
|
||||||
const hasComponent = column?.component;
|
|
||||||
|
|
||||||
return $props.isEditable && isVisible && hasComponent && isEditableCol;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasEditableFormat(column) {
|
|
||||||
if (isEditableColumn(column)) return 'editable-text';
|
|
||||||
}
|
|
||||||
|
|
||||||
const clickHandler = async (event) => {
|
|
||||||
const clickedElement = event.target.closest('td');
|
|
||||||
|
|
||||||
const isDateElement = event.target.closest('.q-date');
|
|
||||||
const isTimeElement = event.target.closest('.q-time');
|
|
||||||
|
|
||||||
if (isDateElement || isTimeElement) return;
|
|
||||||
|
|
||||||
if (clickedElement === null) {
|
|
||||||
destroyInput(editingRow.value, editingField.value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const rowIndex = clickedElement.getAttribute('data-row-index');
|
|
||||||
const colField = clickedElement.getAttribute('data-col-field');
|
|
||||||
const column = $props.columns.find((col) => col.name === colField);
|
|
||||||
|
|
||||||
if (editingRow.value !== null && editingField.value !== null) {
|
|
||||||
if (editingRow.value === rowIndex && editingField.value === colField) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyInput(editingRow.value, editingField.value);
|
|
||||||
}
|
|
||||||
if (isEditableColumn(column))
|
|
||||||
await renderInput(Number(rowIndex), colField, clickedElement);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function handleTabKey(event, rowIndex, colField) {
|
|
||||||
if (editingRow.value == rowIndex && editingField.value == colField)
|
|
||||||
destroyInput(editingRow.value, editingField.value);
|
|
||||||
|
|
||||||
const direction = event.shiftKey ? -1 : 1;
|
|
||||||
const { nextRowIndex, nextColumnName } = await handleTabNavigation(
|
|
||||||
rowIndex,
|
|
||||||
colField,
|
|
||||||
direction,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return;
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
await renderInput(nextRowIndex, nextColumnName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function renderInput(rowId, field, clickedElement) {
|
|
||||||
editingField.value = field;
|
|
||||||
editingRow.value = rowId;
|
|
||||||
|
|
||||||
const originalColumn = $props.columns.find((col) => col.name === field);
|
|
||||||
const column = { ...originalColumn, ...{ label: '' } };
|
|
||||||
const row = CrudModelRef.value.formData[rowId];
|
|
||||||
const oldValue = CrudModelRef.value.formData[rowId][column?.name];
|
|
||||||
|
|
||||||
if (!clickedElement)
|
|
||||||
clickedElement = document.querySelector(
|
|
||||||
`[data-row-index="${rowId}"][data-col-field="${field}"]`,
|
|
||||||
);
|
|
||||||
|
|
||||||
Array.from(clickedElement.childNodes).forEach((child) => {
|
|
||||||
child.style.visibility = 'hidden';
|
|
||||||
child.style.position = 'relative';
|
|
||||||
});
|
|
||||||
|
|
||||||
const isSelect = selectRegex.test(column?.component);
|
|
||||||
if (isSelect) column.attrs = { ...column.attrs, 'emit-value': false };
|
|
||||||
|
|
||||||
const node = h(VnColumn, {
|
|
||||||
row: row,
|
|
||||||
class: 'temp-input',
|
|
||||||
column: column,
|
|
||||||
modelValue: row[column.name],
|
|
||||||
componentProp: 'columnField',
|
|
||||||
autofocus: true,
|
|
||||||
focusOnMount: true,
|
|
||||||
eventHandlers: {
|
|
||||||
'update:modelValue': async (value) => {
|
|
||||||
if (isSelect) {
|
|
||||||
row[column.name] = value[column.attrs?.optionValue ?? 'id'];
|
|
||||||
row[column?.name + 'TextValue'] =
|
|
||||||
value[column.attrs?.optionLabel ?? 'name'];
|
|
||||||
await column?.cellEvent?.['update:modelValue']?.(
|
|
||||||
value,
|
|
||||||
oldValue,
|
|
||||||
row,
|
|
||||||
);
|
|
||||||
} else row[column.name] = value;
|
|
||||||
await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
|
|
||||||
},
|
|
||||||
keyup: async (event) => {
|
|
||||||
if (event.key === 'Enter') handleBlur(rowId, field, clickedElement);
|
|
||||||
},
|
|
||||||
keydown: async (event) => {
|
|
||||||
switch (event.key) {
|
|
||||||
case 'Tab':
|
|
||||||
await handleTabKey(event, rowId, field);
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
case 'Escape':
|
|
||||||
destroyInput(rowId, field, clickedElement);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
click: (event) => {
|
|
||||||
column?.cellEvent?.['click']?.(event, row);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
node.appContext = app._context;
|
|
||||||
render(node, clickedElement);
|
|
||||||
|
|
||||||
if (['checkbox', 'toggle', undefined].includes(column?.component))
|
|
||||||
node.el?.querySelector('span > div').focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function destroyInput(rowIndex, field, clickedElement) {
|
|
||||||
if (!clickedElement)
|
|
||||||
clickedElement = document.querySelector(
|
|
||||||
`[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
|
|
||||||
);
|
|
||||||
if (clickedElement) {
|
|
||||||
render(null, clickedElement);
|
|
||||||
Array.from(clickedElement.childNodes).forEach((child) => {
|
|
||||||
child.style.visibility = 'visible';
|
|
||||||
child.style.position = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (editingRow.value !== rowIndex || editingField.value !== field) return;
|
|
||||||
editingRow.value = null;
|
|
||||||
editingField.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBlur(rowIndex, field, clickedElement) {
|
|
||||||
destroyInput(rowIndex, field, clickedElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleTabNavigation(rowIndex, colName, direction) {
|
|
||||||
const columns = $props.columns;
|
|
||||||
const totalColumns = columns.length;
|
|
||||||
let currentColumnIndex = columns.findIndex((col) => col.name === colName);
|
|
||||||
|
|
||||||
let iterations = 0;
|
|
||||||
let newColumnIndex = currentColumnIndex;
|
|
||||||
|
|
||||||
do {
|
|
||||||
iterations++;
|
|
||||||
newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns;
|
|
||||||
|
|
||||||
if (isEditableColumn(columns[newColumnIndex])) break;
|
|
||||||
} while (iterations < totalColumns);
|
|
||||||
|
|
||||||
if (iterations >= totalColumns) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction === 1 && newColumnIndex <= currentColumnIndex) {
|
|
||||||
rowIndex++;
|
|
||||||
} else if (direction === -1 && newColumnIndex >= currentColumnIndex) {
|
|
||||||
rowIndex--;
|
|
||||||
}
|
|
||||||
return { nextRowIndex: rowIndex, nextColumnName: columns[newColumnIndex].name };
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCheckboxIcon(value) {
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'boolean':
|
|
||||||
return value ? 'check' : 'close';
|
|
||||||
case 'number':
|
|
||||||
return value === 0 ? 'close' : 'check';
|
|
||||||
case 'undefined':
|
|
||||||
return 'indeterminate_check_box';
|
|
||||||
default:
|
|
||||||
return 'indeterminate_check_box';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getToggleIcon(value) {
|
|
||||||
if (value === null) return 'help_outline';
|
|
||||||
return value ? 'toggle_on' : 'toggle_off';
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatColumnValue(col, row, dashIfEmpty) {
|
|
||||||
if (col?.format) {
|
|
||||||
if (selectRegex.test(col?.component) && row[col?.name + 'TextValue']) {
|
|
||||||
return dashIfEmpty(row[col?.name + 'TextValue']);
|
|
||||||
} else {
|
|
||||||
return col.format(row, dashIfEmpty);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return dashIfEmpty(row[col?.name]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const checkbox = ref(null);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<QDrawer
|
<QDrawer
|
||||||
|
@ -537,7 +311,7 @@ const checkbox = ref(null);
|
||||||
v-model="stateStore.rightDrawer"
|
v-model="stateStore.rightDrawer"
|
||||||
side="right"
|
side="right"
|
||||||
:width="256"
|
:width="256"
|
||||||
:overlay="$props.overlay"
|
show-if-above
|
||||||
>
|
>
|
||||||
<QScrollArea class="fit">
|
<QScrollArea class="fit">
|
||||||
<VnTableFilter
|
<VnTableFilter
|
||||||
|
@ -558,7 +332,7 @@ const checkbox = ref(null);
|
||||||
<CrudModel
|
<CrudModel
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:class="$attrs['class'] ?? 'q-px-md'"
|
:class="$attrs['class'] ?? 'q-px-md'"
|
||||||
:limit="$attrs['limit'] ?? 100"
|
:limit="$attrs['limit'] ?? 20"
|
||||||
ref="CrudModelRef"
|
ref="CrudModelRef"
|
||||||
@on-fetch="(...args) => emit('onFetch', ...args)"
|
@on-fetch="(...args) => emit('onFetch', ...args)"
|
||||||
:search-url="searchUrl"
|
:search-url="searchUrl"
|
||||||
|
@ -574,12 +348,8 @@ const checkbox = ref(null);
|
||||||
<QTable
|
<QTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
v-bind="table"
|
v-bind="table"
|
||||||
:class="[
|
class="vnTable"
|
||||||
'vnTable',
|
:class="{ 'last-row-sticky': $props.footer }"
|
||||||
table ? 'selection-cell' : '',
|
|
||||||
$props.footer ? 'last-row-sticky' : '',
|
|
||||||
]"
|
|
||||||
wrap-cells
|
|
||||||
:columns="splittedColumns.columns"
|
:columns="splittedColumns.columns"
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
v-model:selected="selected"
|
v-model:selected="selected"
|
||||||
|
@ -598,7 +368,6 @@ const checkbox = ref(null);
|
||||||
<slot name="top-left"></slot>
|
<slot name="top-left"></slot>
|
||||||
</template>
|
</template>
|
||||||
<template #top-right v-if="!$props.withoutHeader">
|
<template #top-right v-if="!$props.withoutHeader">
|
||||||
<slot name="top-right"></slot>
|
|
||||||
<VnVisibleColumn
|
<VnVisibleColumn
|
||||||
v-if="isTableMode"
|
v-if="isTableMode"
|
||||||
v-model="splittedColumns.columns"
|
v-model="splittedColumns.columns"
|
||||||
|
@ -612,7 +381,6 @@ const checkbox = ref(null);
|
||||||
dense
|
dense
|
||||||
:options="tableModes.filter((mode) => !mode.disable)"
|
:options="tableModes.filter((mode) => !mode.disable)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="showRightIcon"
|
v-if="showRightIcon"
|
||||||
icon="filter_alt"
|
icon="filter_alt"
|
||||||
|
@ -624,38 +392,32 @@ const checkbox = ref(null);
|
||||||
<template #header-cell="{ col }">
|
<template #header-cell="{ col }">
|
||||||
<QTh
|
<QTh
|
||||||
v-if="col.visible ?? true"
|
v-if="col.visible ?? true"
|
||||||
class="body-cell"
|
:style="col.headerStyle"
|
||||||
:style="col?.width ? `max-width: ${col?.width}` : ''"
|
:class="col.headerClass"
|
||||||
style="padding: inherit"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="no-padding"
|
class="column ellipsis"
|
||||||
:style="
|
:class="`text-${col?.align ?? 'left'}`"
|
||||||
withFilters && $props.columnSearch ? 'height: 75px' : ''
|
:style="$props.columnSearch ? 'height: 75px' : ''"
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="text-center" style="height: 30px">
|
<div class="row items-center no-wrap" style="height: 30px">
|
||||||
<QTooltip v-if="col.toolTip">{{ col.toolTip }}</QTooltip>
|
<QTooltip v-if="col.toolTip">{{ col.toolTip }}</QTooltip>
|
||||||
<VnTableOrder
|
<VnTableOrder
|
||||||
v-model="orders[col.orderBy ?? col.name]"
|
v-model="orders[col.orderBy ?? col.name]"
|
||||||
:name="col.orderBy ?? col.name"
|
:name="col.orderBy ?? col.name"
|
||||||
:label="col?.labelAbbreviation ?? col?.label"
|
:label="col?.label"
|
||||||
:data-key="$attrs['data-key']"
|
:data-key="$attrs['data-key']"
|
||||||
:search-url="searchUrl"
|
:search-url="searchUrl"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<VnFilter
|
<VnFilter
|
||||||
v-if="
|
v-if="$props.columnSearch"
|
||||||
$props.columnSearch &&
|
|
||||||
col.columnSearch !== false &&
|
|
||||||
withFilters
|
|
||||||
"
|
|
||||||
:column="col"
|
:column="col"
|
||||||
:show-title="true"
|
:show-title="true"
|
||||||
:data-key="$attrs['data-key']"
|
:data-key="$attrs['data-key']"
|
||||||
v-model="params[columnName(col)]"
|
v-model="params[columnName(col)]"
|
||||||
:search-url="searchUrl"
|
:search-url="searchUrl"
|
||||||
customClass="header-filter"
|
class="full-width"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</QTh>
|
</QTh>
|
||||||
|
@ -673,27 +435,16 @@ const checkbox = ref(null);
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell="{ col, row, rowIndex }">
|
<template #body-cell="{ col, row, rowIndex }">
|
||||||
|
<!-- Columns -->
|
||||||
<QTd
|
<QTd
|
||||||
class="no-margin q-px-xs"
|
auto-width
|
||||||
|
class="no-margin"
|
||||||
|
:class="[getColAlign(col), col.columnClass]"
|
||||||
|
:style="col.style"
|
||||||
v-if="col.visible ?? true"
|
v-if="col.visible ?? true"
|
||||||
:style="{
|
@click.ctrl="
|
||||||
'max-width': col?.width ?? false,
|
($event) =>
|
||||||
position: 'relative',
|
rowCtrlClickFunction && rowCtrlClickFunction($event, row)
|
||||||
}"
|
|
||||||
:class="[
|
|
||||||
col.columnClass,
|
|
||||||
'body-cell no-margin no-padding',
|
|
||||||
getColAlign(col),
|
|
||||||
]"
|
|
||||||
:data-row-index="rowIndex"
|
|
||||||
:data-col-field="col?.name"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="no-padding no-margin peter"
|
|
||||||
style="
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<slot
|
<slot
|
||||||
|
@ -702,34 +453,14 @@ const checkbox = ref(null);
|
||||||
:row="row"
|
:row="row"
|
||||||
:row-index="rowIndex"
|
:row-index="rowIndex"
|
||||||
>
|
>
|
||||||
<QIcon
|
<VnTableColumn
|
||||||
v-if="col?.component === 'toggle'"
|
:column="col"
|
||||||
:name="
|
:row="row"
|
||||||
col?.getIcon
|
:is-editable="col.isEditable ?? isEditable"
|
||||||
? col.getIcon(row[col?.name])
|
v-model="row[col.name]"
|
||||||
: getToggleIcon(row[col?.name])
|
component-prop="columnField"
|
||||||
"
|
|
||||||
style="color: var(--vn-text-color)"
|
|
||||||
:class="hasEditableFormat(col)"
|
|
||||||
size="14px"
|
|
||||||
/>
|
/>
|
||||||
<QIcon
|
|
||||||
v-else-if="col?.component === 'checkbox'"
|
|
||||||
:name="getCheckboxIcon(row[col?.name])"
|
|
||||||
style="color: var(--vn-text-color)"
|
|
||||||
:class="hasEditableFormat(col)"
|
|
||||||
size="14px"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
:class="hasEditableFormat(col)"
|
|
||||||
:style="col?.style ? col.style(row) : null"
|
|
||||||
style="bottom: 0"
|
|
||||||
>
|
|
||||||
{{ formatColumnValue(col, row, dashIfEmpty) }}
|
|
||||||
</span>
|
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-tableActions="{ col, row }">
|
<template #body-cell-tableActions="{ col, row }">
|
||||||
|
@ -832,7 +563,7 @@ const checkbox = ref(null);
|
||||||
:row="row"
|
:row="row"
|
||||||
:row-index="index"
|
:row-index="index"
|
||||||
>
|
>
|
||||||
<VnColumn
|
<VnTableColumn
|
||||||
:column="col"
|
:column="col"
|
||||||
:row="row"
|
:row="row"
|
||||||
:is-editable="false"
|
:is-editable="false"
|
||||||
|
@ -872,17 +603,14 @@ const checkbox = ref(null);
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
<template #bottom-row="{ cols }" v-if="$props.footer">
|
<template #bottom-row="{ cols }" v-if="$props.footer">
|
||||||
<QTr v-if="rows.length" style="height: 45px">
|
<QTr v-if="rows.length" style="height: 30px">
|
||||||
<QTh v-if="table.selection" />
|
|
||||||
<QTh
|
<QTh
|
||||||
v-for="col of cols.filter((cols) => cols.visible ?? true)"
|
v-for="col of cols.filter((cols) => cols.visible ?? true)"
|
||||||
:key="col?.id"
|
:key="col?.id"
|
||||||
|
class="text-center"
|
||||||
:class="getColAlign(col)"
|
:class="getColAlign(col)"
|
||||||
>
|
>
|
||||||
<slot
|
<slot :name="`column-footer-${col.name}`" />
|
||||||
:name="`column-footer-${col.name}`"
|
|
||||||
:isEditableColumn="isEditableColumn(col)"
|
|
||||||
/>
|
|
||||||
</QTh>
|
</QTh>
|
||||||
</QTr>
|
</QTr>
|
||||||
</template>
|
</template>
|
||||||
|
@ -926,33 +654,14 @@ const checkbox = ref(null);
|
||||||
{{ createForm?.title }}
|
{{ createForm?.title }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QPageSticky>
|
</QPageSticky>
|
||||||
<QDialog
|
<QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
|
||||||
v-model="showForm"
|
|
||||||
transition-show="scale"
|
|
||||||
transition-hide="scale"
|
|
||||||
:full-width="createComplement?.isFullWidth ?? false"
|
|
||||||
@before-hide="
|
|
||||||
() => {
|
|
||||||
if (createRef.isSaveAndContinue) {
|
|
||||||
showForm = true;
|
|
||||||
createForm.formInitialData = { ...create.formInitialData };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"
|
|
||||||
data-cy="vn-table-create-dialog"
|
|
||||||
>
|
|
||||||
<FormModelPopup
|
<FormModelPopup
|
||||||
ref="createRef"
|
|
||||||
v-bind="createForm"
|
v-bind="createForm"
|
||||||
:model="$attrs['data-key'] + 'Create'"
|
:model="$attrs['data-key'] + 'Create'"
|
||||||
@on-data-saved="(_, res) => createForm.onDataSaved(res)"
|
@on-data-saved="(_, res) => createForm.onDataSaved(res)"
|
||||||
>
|
>
|
||||||
<template #form-inputs="{ data }">
|
<template #form-inputs="{ data }">
|
||||||
<div :style="createComplement?.containerStyle">
|
<div class="grid-create">
|
||||||
<div>
|
|
||||||
<slot name="previous-create-dialog" :data="data" />
|
|
||||||
</div>
|
|
||||||
<div class="grid-create" :style="createComplement?.columnGridStyle">
|
|
||||||
<slot
|
<slot
|
||||||
v-for="column of splittedColumns.create"
|
v-for="column of splittedColumns.create"
|
||||||
:key="column.name"
|
:key="column.name"
|
||||||
|
@ -961,19 +670,17 @@ const checkbox = ref(null);
|
||||||
:column-name="column.name"
|
:column-name="column.name"
|
||||||
:label="column.label"
|
:label="column.label"
|
||||||
>
|
>
|
||||||
<VnColumn
|
<VnTableColumn
|
||||||
:column="column"
|
:column="column"
|
||||||
:row="{}"
|
:row="{}"
|
||||||
default="input"
|
default="input"
|
||||||
v-model="data[column.name]"
|
v-model="data[column.name]"
|
||||||
:show-label="true"
|
:show-label="true"
|
||||||
component-prop="columnCreate"
|
component-prop="columnCreate"
|
||||||
:data-cy="`${column.name}-create-popup`"
|
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
<slot name="more-create-dialog" :data="data" />
|
<slot name="more-create-dialog" :data="data" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</FormModelPopup>
|
</FormModelPopup>
|
||||||
</QDialog>
|
</QDialog>
|
||||||
|
@ -990,42 +697,6 @@ es:
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.selection-cell {
|
|
||||||
table td:first-child {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.side-padding {
|
|
||||||
padding-left: 1px;
|
|
||||||
padding-right: 1px;
|
|
||||||
}
|
|
||||||
.editable-text:hover {
|
|
||||||
border-bottom: 1px dashed var(--q-primary);
|
|
||||||
@extend .side-padding;
|
|
||||||
}
|
|
||||||
.editable-text {
|
|
||||||
border-bottom: 1px dashed var(--vn-label-color);
|
|
||||||
@extend .side-padding;
|
|
||||||
}
|
|
||||||
.cell-input {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
padding-top: 0px !important;
|
|
||||||
}
|
|
||||||
.q-field--labeled .q-field__native,
|
|
||||||
.q-field--labeled .q-field__prefix,
|
|
||||||
.q-field--labeled .q-field__suffix {
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body-cell {
|
|
||||||
padding-left: 2px !important;
|
|
||||||
padding-right: 2px !important;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.bg-chip-secondary {
|
.bg-chip-secondary {
|
||||||
background-color: var(--vn-page-color);
|
background-color: var(--vn-page-color);
|
||||||
color: var(--vn-text-color);
|
color: var(--vn-text-color);
|
||||||
|
@ -1042,7 +713,7 @@ es:
|
||||||
|
|
||||||
.grid-three {
|
.grid-three {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
|
grid-template-columns: repeat(auto-fit, minmax(350px, max-content));
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
grid-gap: 20px;
|
grid-gap: 20px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
@ -1051,6 +722,7 @@ es:
|
||||||
.grid-create {
|
.grid-create {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
|
grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
|
||||||
|
max-width: 100%;
|
||||||
grid-gap: 20px;
|
grid-gap: 20px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
@ -1066,9 +738,7 @@ es:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.q-table tbody tr td {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.q-table {
|
.q-table {
|
||||||
th {
|
th {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -1168,15 +838,4 @@ es:
|
||||||
.q-table__middle.q-virtual-scroll.q-virtual-scroll--vertical.scroll {
|
.q-table__middle.q-virtual-scroll.q-virtual-scroll--vertical.scroll {
|
||||||
background-color: var(--vn-section-color);
|
background-color: var(--vn-section-color);
|
||||||
}
|
}
|
||||||
.temp-input {
|
|
||||||
top: 0;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.header-filter > .q-field__inner > .q-field__control {
|
|
||||||
padding: inherit;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -27,13 +27,12 @@ function columnName(col) {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnFilterPanel v-bind="$attrs" :search-button="true" :disable-submit-event="true">
|
<VnFilterPanel v-bind="$attrs" :search-button="true" :disable-submit-event="true">
|
||||||
<template #body="{ params, orders, searchFn }">
|
<template #body="{ params, orders }">
|
||||||
<div
|
<div
|
||||||
class="container"
|
class="row no-wrap flex-center"
|
||||||
v-for="col of columns.filter((c) => c.columnFilter ?? true)"
|
v-for="col of columns.filter((c) => c.columnFilter ?? true)"
|
||||||
:key="col.id"
|
:key="col.id"
|
||||||
>
|
>
|
||||||
<div class="filter">
|
|
||||||
<VnFilter
|
<VnFilter
|
||||||
ref="tableFilterRef"
|
ref="tableFilterRef"
|
||||||
:column="col"
|
:column="col"
|
||||||
|
@ -41,8 +40,6 @@ function columnName(col) {
|
||||||
v-model="params[columnName(col)]"
|
v-model="params[columnName(col)]"
|
||||||
:search-url="searchUrl"
|
:search-url="searchUrl"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div class="order">
|
|
||||||
<VnTableOrder
|
<VnTableOrder
|
||||||
v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
|
v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
|
||||||
v-model="orders[col.orderBy ?? col.name]"
|
v-model="orders[col.orderBy ?? col.name]"
|
||||||
|
@ -52,11 +49,9 @@ function columnName(col) {
|
||||||
:vertical="true"
|
:vertical="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<slot
|
<slot
|
||||||
name="moreFilterPanel"
|
name="moreFilterPanel"
|
||||||
:params="params"
|
:params="params"
|
||||||
:search-fn="searchFn"
|
|
||||||
:orders="orders"
|
:orders="orders"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
/>
|
/>
|
||||||
|
@ -72,21 +67,3 @@ function columnName(col) {
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 45px;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter {
|
|
||||||
width: 70%;
|
|
||||||
height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.order {
|
|
||||||
width: 10%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -32,21 +32,16 @@ const areAllChecksMarked = computed(() => {
|
||||||
|
|
||||||
function setUserConfigViewData(data, isLocal) {
|
function setUserConfigViewData(data, isLocal) {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
// Importante: El name de las columnas de la tabla debe conincidir con el name de las variables que devuelve la view config
|
||||||
if (!isLocal) localColumns.value = [];
|
if (!isLocal) localColumns.value = [];
|
||||||
|
// Array to Object
|
||||||
const skippeds = $props.skip.reduce((a, v) => ({ ...a, [v]: v }), {});
|
const skippeds = $props.skip.reduce((a, v) => ({ ...a, [v]: v }), {});
|
||||||
|
|
||||||
for (let column of columns.value) {
|
for (let column of columns.value) {
|
||||||
const { label, name, labelAbbreviation } = column;
|
const { label, name } = column;
|
||||||
if (skippeds[name]) continue;
|
if (skippeds[name]) continue;
|
||||||
column.visible = data[name] ?? true;
|
column.visible = data[name] ?? true;
|
||||||
if (!isLocal)
|
if (!isLocal) localColumns.value.push({ name, label, visible: column.visible });
|
||||||
localColumns.value.push({
|
|
||||||
name,
|
|
||||||
label,
|
|
||||||
labelAbbreviation,
|
|
||||||
visible: column.visible,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,11 +152,7 @@ onMounted(async () => {
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
v-for="col in localColumns"
|
v-for="col in localColumns"
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
:label="
|
:label="col.label ?? col.name"
|
||||||
col?.labelAbbreviation
|
|
||||||
? col.labelAbbreviation + ` (${col.label ?? col.name})`
|
|
||||||
: (col.label ?? col.name)
|
|
||||||
"
|
|
||||||
v-model="col.visible"
|
v-model="col.visible"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import { vi, describe, expect, it, beforeEach, afterEach } from 'vitest';
|
import { vi, describe, expect, it, beforeEach, beforeAll, afterEach } from 'vitest';
|
||||||
import { createWrapper } from 'app/test/vitest/helper';
|
import { createWrapper } from 'app/test/vitest/helper';
|
||||||
import UserPanel from 'src/components/UserPanel.vue';
|
import UserPanel from 'src/components/UserPanel.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
|
||||||
vi.mock('src/utils/quasarLang', () => ({
|
|
||||||
default: vi.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('UserPanel', () => {
|
describe('UserPanel', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let vm;
|
let vm;
|
||||||
|
@ -43,7 +39,7 @@ describe('UserPanel', () => {
|
||||||
await vm.saveDarkMode(true);
|
await vm.saveDarkMode(true);
|
||||||
expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
|
expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
|
||||||
expect(vm.user.darkMode).toBe(true);
|
expect(vm.user.darkMode).toBe(true);
|
||||||
await vm.updatePreferences();
|
vm.updatePreferences();
|
||||||
expect(vm.darkMode).toBe(true);
|
expect(vm.darkMode).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,7 +48,7 @@ describe('UserPanel', () => {
|
||||||
await vm.saveLanguage(userLanguage);
|
await vm.saveLanguage(userLanguage);
|
||||||
expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
|
expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
|
||||||
expect(vm.user.lang).toBe(userLanguage);
|
expect(vm.user.lang).toBe(userLanguage);
|
||||||
await vm.updatePreferences();
|
vm.updatePreferences();
|
||||||
expect(vm.locale).toBe(userLanguage);
|
expect(vm.locale).toBe(userLanguage);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
const model = defineModel({ type: [Number, Boolean] });
|
|
||||||
const $props = defineProps({
|
|
||||||
info: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const checkboxModel = computed({
|
|
||||||
get() {
|
|
||||||
if (typeof model.value === 'number') {
|
|
||||||
return model.value !== 0;
|
|
||||||
}
|
|
||||||
return model.value;
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
if (typeof model.value === 'number') {
|
|
||||||
model.value = value ? 1 : 0;
|
|
||||||
} else {
|
|
||||||
model.value = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<QCheckbox v-bind="$attrs" v-on="$attrs" v-model="checkboxModel" />
|
|
||||||
<QIcon
|
|
||||||
v-if="info"
|
|
||||||
v-bind="$attrs"
|
|
||||||
class="cursor-info q-ml-sm"
|
|
||||||
name="info"
|
|
||||||
size="sm"
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ info }}
|
|
||||||
</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,32 +0,0 @@
|
||||||
<script setup>
|
|
||||||
const $props = defineProps({
|
|
||||||
colors: {
|
|
||||||
type: String,
|
|
||||||
default: '{"value":[]}',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorArray = JSON.parse($props.colors)?.value;
|
|
||||||
const maxHeight = 30;
|
|
||||||
const colorHeight = maxHeight / colorArray?.length;
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div class="color-div" :style="{ height: `${maxHeight}px` }">
|
|
||||||
<div
|
|
||||||
v-for="(color, index) in colorArray"
|
|
||||||
:key="index"
|
|
||||||
:style="{
|
|
||||||
backgroundColor: `#${color}`,
|
|
||||||
height: `${colorHeight}px`,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style scoped>
|
|
||||||
.color-div {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -17,8 +17,6 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['blur']);
|
|
||||||
|
|
||||||
const componentArray = computed(() => {
|
const componentArray = computed(() => {
|
||||||
if (typeof $props.prop === 'object') return [$props.prop];
|
if (typeof $props.prop === 'object') return [$props.prop];
|
||||||
return $props.prop;
|
return $props.prop;
|
||||||
|
@ -56,7 +54,6 @@ function toValueAttrs(attrs) {
|
||||||
v-bind="mix(toComponent).attrs"
|
v-bind="mix(toComponent).attrs"
|
||||||
v-on="mix(toComponent).event ?? {}"
|
v-on="mix(toComponent).event ?? {}"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
@blur="emit('blur')"
|
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,7 +11,6 @@ const emit = defineEmits([
|
||||||
'update:options',
|
'update:options',
|
||||||
'keyup.enter',
|
'keyup.enter',
|
||||||
'remove',
|
'remove',
|
||||||
'blur',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
|
@ -137,7 +136,6 @@ const handleUppercase = () => {
|
||||||
:type="$attrs.type"
|
:type="$attrs.type"
|
||||||
:class="{ required: isRequired }"
|
:class="{ required: isRequired }"
|
||||||
@keyup.enter="emit('keyup.enter')"
|
@keyup.enter="emit('keyup.enter')"
|
||||||
@blur="emit('blur')"
|
|
||||||
@keydown="handleKeydown"
|
@keydown="handleKeydown"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
:rules="mixinRules"
|
:rules="mixinRules"
|
||||||
|
@ -145,7 +143,7 @@ const handleUppercase = () => {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
:data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
|
:data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
|
||||||
>
|
>
|
||||||
<template #prepend v-if="$slots.prepend">
|
<template #prepend>
|
||||||
<slot name="prepend" />
|
<slot name="prepend" />
|
||||||
</template>
|
</template>
|
||||||
<template #append>
|
<template #append>
|
||||||
|
@ -174,7 +172,7 @@ const handleUppercase = () => {
|
||||||
<QIcon
|
<QIcon
|
||||||
name="match_case"
|
name="match_case"
|
||||||
size="xs"
|
size="xs"
|
||||||
v-if="!$attrs.disabled && !$attrs.readonly && $props.uppercase"
|
v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
|
||||||
@click="handleUppercase"
|
@click="handleUppercase"
|
||||||
class="uppercase-icon"
|
class="uppercase-icon"
|
||||||
>
|
>
|
||||||
|
@ -196,9 +194,7 @@ const handleUppercase = () => {
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.uppercase-icon {
|
.uppercase-icon {
|
||||||
transition:
|
transition: color 0.3s, transform 0.2s;
|
||||||
color 0.3s,
|
|
||||||
transform 0.2s;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ const formattedDate = computed({
|
||||||
if (value.at(2) == '/') value = value.split('/').reverse().join('/');
|
if (value.at(2) == '/') value = value.split('/').reverse().join('/');
|
||||||
value = date.formatDate(
|
value = date.formatDate(
|
||||||
new Date(value).toISOString(),
|
new Date(value).toISOString(),
|
||||||
'YYYY-MM-DDTHH:mm:ss.SSSZ',
|
'YYYY-MM-DDTHH:mm:ss.SSSZ'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const [year, month, day] = value.split('-').map((e) => parseInt(e));
|
const [year, month, day] = value.split('-').map((e) => parseInt(e));
|
||||||
|
@ -55,7 +55,7 @@ const formattedDate = computed({
|
||||||
orgDate.getHours(),
|
orgDate.getHours(),
|
||||||
orgDate.getMinutes(),
|
orgDate.getMinutes(),
|
||||||
orgDate.getSeconds(),
|
orgDate.getSeconds(),
|
||||||
orgDate.getMilliseconds(),
|
orgDate.getMilliseconds()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ const formattedDate = computed({
|
||||||
});
|
});
|
||||||
|
|
||||||
const popupDate = computed(() =>
|
const popupDate = computed(() =>
|
||||||
model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value,
|
model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
|
||||||
);
|
);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// fix quasar bug
|
// fix quasar bug
|
||||||
|
@ -73,7 +73,7 @@ onMounted(() => {
|
||||||
watch(
|
watch(
|
||||||
() => model.value,
|
() => model.value,
|
||||||
(val) => (formattedDate.value = val),
|
(val) => (formattedDate.value = val),
|
||||||
{ immediate: true },
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const styleAttrs = computed(() => {
|
const styleAttrs = computed(() => {
|
||||||
|
|
|
@ -8,7 +8,6 @@ defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const model = defineModel({ type: [Number, String] });
|
const model = defineModel({ type: [Number, String] });
|
||||||
const emit = defineEmits(['blur']);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
@ -25,6 +24,5 @@ const emit = defineEmits(['blur']);
|
||||||
model = parseFloat(val).toFixed(decimalPlaces);
|
model = parseFloat(val).toFixed(decimalPlaces);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@blur="emit('blur')"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
type: String,
|
|
||||||
default: 'primary',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const popupProxyRef = ref(null);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<QBtn :color="$props.color" :icon="$props.icon" :label="$t($props.label)">
|
|
||||||
<template #default>
|
|
||||||
<slot name="extraIcon"></slot>
|
|
||||||
<QPopupProxy ref="popupProxyRef" style="max-width: none">
|
|
||||||
<QCard>
|
|
||||||
<slot :popup="popupProxyRef"></slot>
|
|
||||||
</QCard>
|
|
||||||
</QPopupProxy>
|
|
||||||
<QTooltip>{{ $t($props.tooltip) }}</QTooltip>
|
|
||||||
</template>
|
|
||||||
</QBtn>
|
|
||||||
</template>
|
|
|
@ -106,14 +106,7 @@ function checkIsMain() {
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
:array-data="arrayData"
|
:array-data="arrayData"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
>
|
|
||||||
<template #moreFilterPanel="{ params, orders, searchFn }">
|
|
||||||
<slot
|
|
||||||
name="moreFilterPanel"
|
|
||||||
v-bind="{ params, orders, searchFn }"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
</VnTableFilter>
|
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
</RightAdvancedMenu>
|
</RightAdvancedMenu>
|
||||||
|
|
|
@ -171,8 +171,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const arrayDataKey =
|
const arrayDataKey =
|
||||||
$props.dataKey ??
|
$props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label);
|
||||||
($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
|
|
||||||
|
|
||||||
const arrayData = useArrayData(arrayDataKey, {
|
const arrayData = useArrayData(arrayDataKey, {
|
||||||
url: $props.url,
|
url: $props.url,
|
||||||
|
@ -221,7 +220,7 @@ async function fetchFilter(val) {
|
||||||
optionFilterValue.value ??
|
optionFilterValue.value ??
|
||||||
(new RegExp(/\d/g).test(val)
|
(new RegExp(/\d/g).test(val)
|
||||||
? optionValue.value
|
? optionValue.value
|
||||||
: (optionFilter.value ?? optionLabel.value));
|
: optionFilter.value ?? optionLabel.value);
|
||||||
|
|
||||||
let defaultWhere = {};
|
let defaultWhere = {};
|
||||||
if ($props.filterOptions.length) {
|
if ($props.filterOptions.length) {
|
||||||
|
@ -240,7 +239,7 @@ async function fetchFilter(val) {
|
||||||
|
|
||||||
const { data } = await arrayData.applyFilter(
|
const { data } = await arrayData.applyFilter(
|
||||||
{ filter: filterOptions },
|
{ filter: filterOptions },
|
||||||
{ updateRouter: false },
|
{ updateRouter: false }
|
||||||
);
|
);
|
||||||
setOptions(data);
|
setOptions(data);
|
||||||
return data;
|
return data;
|
||||||
|
@ -273,7 +272,7 @@ async function filterHandler(val, update) {
|
||||||
ref.setOptionIndex(-1);
|
ref.setOptionIndex(-1);
|
||||||
ref.moveOptionSelection(1, true);
|
ref.moveOptionSelection(1, true);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +308,7 @@ function handleKeyDown(event) {
|
||||||
if (inputValue) {
|
if (inputValue) {
|
||||||
const matchingOption = myOptions.value.find(
|
const matchingOption = myOptions.value.find(
|
||||||
(option) =>
|
(option) =>
|
||||||
option[optionLabel.value].toLowerCase() === inputValue.toLowerCase(),
|
option[optionLabel.value].toLowerCase() === inputValue.toLowerCase()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchingOption) {
|
if (matchingOption) {
|
||||||
|
@ -321,11 +320,11 @@ function handleKeyDown(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusableElements = document.querySelectorAll(
|
const focusableElements = document.querySelectorAll(
|
||||||
'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])',
|
'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])'
|
||||||
);
|
);
|
||||||
const currentIndex = Array.prototype.indexOf.call(
|
const currentIndex = Array.prototype.indexOf.call(
|
||||||
focusableElements,
|
focusableElements,
|
||||||
event.target,
|
event.target
|
||||||
);
|
);
|
||||||
if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) {
|
if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) {
|
||||||
focusableElements[currentIndex + 1].focus();
|
focusableElements[currentIndex + 1].focus();
|
||||||
|
|
|
@ -14,7 +14,7 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const options = ref([]);
|
const options = ref([]);
|
||||||
const emit = defineEmits(['blur']);
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
const { url, optionValue, optionLabel } = useAttrs();
|
const { url, optionValue, optionLabel } = useAttrs();
|
||||||
const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
|
const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
|
||||||
|
@ -35,5 +35,5 @@ onBeforeMount(async () => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnSelect v-bind="$attrs" :options="$attrs.options ?? options" @blur="emit('blur')" />
|
<VnSelect v-bind="$attrs" :options="$attrs.options ?? options" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -37,6 +37,7 @@ const isAllowedToCreate = computed(() => {
|
||||||
|
|
||||||
defineExpose({ vnSelectDialogRef: select });
|
defineExpose({ vnSelectDialogRef: select });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
ref="select"
|
ref="select"
|
||||||
|
@ -66,6 +67,7 @@ defineExpose({ vnSelectDialogRef: select });
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.default-icon {
|
.default-icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
|
|
||||||
const model = defineModel({ type: [String, Number, Object] });
|
const model = defineModel({ type: [String, Number, Object] });
|
||||||
|
const url = 'Suppliers';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -9,13 +11,11 @@ const model = defineModel({ type: [String, Number, Object] });
|
||||||
:label="$t('globals.supplier')"
|
:label="$t('globals.supplier')"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
url="Suppliers"
|
:url="url"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="nickname"
|
option-label="nickname"
|
||||||
:fields="['id', 'name', 'nickname', 'nif']"
|
:fields="['id', 'name', 'nickname', 'nif']"
|
||||||
:filter-options="['id', 'name', 'nickname', 'nif']"
|
|
||||||
sort-by="name ASC"
|
sort-by="name ASC"
|
||||||
data-cy="vnSupplierSelect"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import VnSelectDialog from './VnSelectDialog.vue';
|
|
||||||
import FilterTravelForm from 'src/components/FilterTravelForm.vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { toDate } from 'src/filters';
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const $props = defineProps({
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
onFilterTravelSelected: {
|
|
||||||
type: Function,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<VnSelectDialog
|
|
||||||
:label="t('entry.basicData.travel')"
|
|
||||||
v-bind="$attrs"
|
|
||||||
url="Travels/filter"
|
|
||||||
:fields="['id', 'warehouseInName']"
|
|
||||||
option-value="id"
|
|
||||||
option-label="warehouseInName"
|
|
||||||
map-options
|
|
||||||
hide-selected
|
|
||||||
:required="true"
|
|
||||||
action-icon="filter_alt"
|
|
||||||
:roles-allowed-to-create="['buyer']"
|
|
||||||
>
|
|
||||||
<template #form>
|
|
||||||
<FilterTravelForm @travel-selected="onFilterTravelSelected(data, $event)" />
|
|
||||||
</template>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>
|
|
||||||
{{ scope.opt?.agencyModeName }} -
|
|
||||||
{{ scope.opt?.warehouseInName }}
|
|
||||||
({{ toDate(scope.opt?.shipped) }}) →
|
|
||||||
{{ scope.opt?.warehouseOutName }}
|
|
||||||
({{ toDate(scope.opt?.landed) }})
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelectDialog>
|
|
||||||
</template>
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const model = defineModel({ type: String, required: true });
|
||||||
|
const countriesOption = ref([]);
|
||||||
|
const countriesOptionCopy = ref([]);
|
||||||
|
const lastVal = ref();
|
||||||
|
|
||||||
|
function handleBlur() {
|
||||||
|
if (lastVal.value == '') lastVal.value = null;
|
||||||
|
model.value = lastVal.value && lastVal.value.toUpperCase().slice(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterFn(val, update) {
|
||||||
|
update(
|
||||||
|
() => {
|
||||||
|
if (val === '') {
|
||||||
|
countriesOptionCopy.value = JSON.parse(
|
||||||
|
JSON.stringify(countriesOption.value)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exist = countriesOption.value.filter((c) =>
|
||||||
|
c.code.toLowerCase().includes(val.toLowerCase())
|
||||||
|
);
|
||||||
|
if (exist) return (countriesOptionCopy.value = exist);
|
||||||
|
countriesOptionCopy.value = JSON.parse(JSON.stringify([{ code: val }]));
|
||||||
|
},
|
||||||
|
(ref) => {
|
||||||
|
if (val !== '' && ref.options.length > 0) {
|
||||||
|
ref.setOptionIndex(-1);
|
||||||
|
ref.moveOptionSelection(1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<FetchData auto-load @on-fetch="(data) => (countriesOption = data)" url="Countries" />
|
||||||
|
<VnSelect
|
||||||
|
:label="t('Vies')"
|
||||||
|
v-model="model"
|
||||||
|
:input-debounce="0"
|
||||||
|
:options="countriesOptionCopy"
|
||||||
|
@input-value="(evt) => (lastVal = evt) && handleBlur()"
|
||||||
|
@filter="filterFn"
|
||||||
|
option-label="code"
|
||||||
|
option-value="code"
|
||||||
|
v-bind="$attrs"
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>{{ scope.opt?.code }}</QItemLabel>
|
||||||
|
<QItemLabel caption>
|
||||||
|
{{ scope.opt?.code }},
|
||||||
|
{{ scope.opt?.name }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
<template #after>
|
||||||
|
<QIcon name="info" class="cursor-pointer">
|
||||||
|
<QTooltip>{{ t('viesTip') }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
</template>
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
viesTip: El campo puede contener valores que no este en la lista
|
||||||
|
|
||||||
|
en:
|
||||||
|
viesTip: The field may contain value that are not in the list
|
||||||
|
|
||||||
|
</i18n>
|
|
@ -29,6 +29,10 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
module: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
summary: {
|
summary: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
|
@ -53,7 +57,7 @@ defineExpose({ getData });
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
arrayData = useArrayData($props.dataKey, {
|
arrayData = useArrayData($props.dataKey, {
|
||||||
url: $props.url,
|
url: $props.url,
|
||||||
userFilter: $props.filter,
|
filter: $props.filter,
|
||||||
skip: 0,
|
skip: 0,
|
||||||
oneRecord: true,
|
oneRecord: true,
|
||||||
});
|
});
|
||||||
|
@ -144,9 +148,7 @@ const toModule = computed(() =>
|
||||||
{{ t('components.smartCard.openSummary') }}
|
{{ t('components.smartCard.openSummary') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
<RouterLink
|
<RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }">
|
||||||
:to="{ name: `${dataKey}Summary`, params: { id: entity.id } }"
|
|
||||||
>
|
|
||||||
<QBtn
|
<QBtn
|
||||||
class="link"
|
class="link"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -1,32 +1,53 @@
|
||||||
<script setup>
|
|
||||||
defineProps({
|
|
||||||
hasImage: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
<template>
|
||||||
<div id="descriptor-skeleton" class="bg-vn-page">
|
<div id="descriptor-skeleton">
|
||||||
<div class="row justify-between q-pa-sm">
|
<div class="row justify-between q-pa-sm">
|
||||||
<QSkeleton square size="30px" v-for="i in 3" :key="i" />
|
<QSkeleton square size="40px" />
|
||||||
|
<QSkeleton square size="40px" />
|
||||||
|
<QSkeleton square height="40px" width="20px" />
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-xs" v-if="hasImage">
|
<div class="col justify-between q-pa-sm q-gutter-y-xs">
|
||||||
<QSkeleton square height="200px" width="100%" />
|
<QSkeleton square height="40px" width="150px" />
|
||||||
|
<QSkeleton square height="30px" width="70px" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col justify-between q-pa-md q-gutter-y-xs">
|
<div class="col q-pl-sm q-pa-sm q-mb-md">
|
||||||
<QSkeleton square height="25px" width="150px" />
|
<div class="row justify-between">
|
||||||
<QSkeleton square height="15px" width="70px" />
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pl-sm q-pa-sm q-mb-md">
|
<div class="row justify-between">
|
||||||
<div class="row q-gutter-x-sm q-pa-none q-ma-none" v-for="i in 5" :key="i">
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
<QSkeleton type="text" square height="20px" width="30%" />
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
<QSkeleton type="text" square height="20px" width="60%" />
|
</div>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<QSkeleton type="text" square height="30px" width="20%" />
|
||||||
|
<QSkeleton type="text" square height="30px" width="60%" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<QCardActions class="q-gutter-x-sm justify-between">
|
<QCardActions>
|
||||||
<QSkeleton size="40px" v-for="i in 5" :key="i" />
|
<QSkeleton size="40px" />
|
||||||
|
<QSkeleton size="40px" />
|
||||||
|
<QSkeleton size="40px" />
|
||||||
|
<QSkeleton size="40px" />
|
||||||
|
<QSkeleton size="40px" />
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#descriptor-skeleton .q-card__actions {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -82,7 +82,7 @@ function cancel() {
|
||||||
@click="cancel()"
|
@click="cancel()"
|
||||||
/>
|
/>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QCardSection class="q-pb-none" data-cy="VnConfirm_message">
|
<QCardSection class="q-pb-none">
|
||||||
<span v-if="message !== false" v-html="message" />
|
<span v-if="message !== false" v-html="message" />
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QCardSection class="row items-center q-pt-none">
|
<QCardSection class="row items-center q-pt-none">
|
||||||
|
@ -95,7 +95,6 @@ function cancel() {
|
||||||
:disable="isLoading"
|
:disable="isLoading"
|
||||||
flat
|
flat
|
||||||
@click="cancel()"
|
@click="cancel()"
|
||||||
data-cy="VnConfirm_cancel"
|
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('globals.confirm')"
|
:label="t('globals.confirm')"
|
||||||
|
|
|
@ -293,9 +293,6 @@ const getLocale = (label) => {
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.q-field__label.no-pointer-events.absolute.ellipsis {
|
|
||||||
margin-left: 6px !important;
|
|
||||||
}
|
|
||||||
.list {
|
.list {
|
||||||
width: 256px;
|
width: 256px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<QTooltip>
|
<QTooltip>
|
||||||
{{ $t('components.cardDescriptor.moreOptions') }}
|
{{ $t('components.cardDescriptor.moreOptions') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
<QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
|
<QMenu ref="menuRef">
|
||||||
<QList>
|
<QList>
|
||||||
<slot name="menu" :menu-ref="$refs.menuRef" />
|
<slot name="menu" :menu-ref="$refs.menuRef" />
|
||||||
</QList>
|
</QList>
|
||||||
|
|
|
@ -18,12 +18,7 @@ import VnInput from 'components/common/VnInput.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['onFetch']);
|
const emit = defineEmits(['onFetch']);
|
||||||
|
|
||||||
const originalAttrs = useAttrs();
|
const $attrs = useAttrs();
|
||||||
|
|
||||||
const $attrs = computed(() => {
|
|
||||||
const { style, ...rest } = originalAttrs;
|
|
||||||
return rest;
|
|
||||||
});
|
|
||||||
|
|
||||||
const isRequired = computed(() => {
|
const isRequired = computed(() => {
|
||||||
return Object.keys($attrs).includes('required')
|
return Object.keys($attrs).includes('required')
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { toPercentage } from 'filters/index';
|
|
||||||
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
value: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const valueClass = computed(() =>
|
|
||||||
props.value === 0 ? 'neutral' : props.value > 0 ? 'positive' : 'negative',
|
|
||||||
);
|
|
||||||
const iconName = computed(() =>
|
|
||||||
props.value === 0 ? 'equal' : props.value > 0 ? 'arrow_upward' : 'arrow_downward',
|
|
||||||
);
|
|
||||||
const formattedValue = computed(() => props.value);
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<span :class="valueClass">
|
|
||||||
<QIcon :name="iconName" size="sm" class="value-icon" />
|
|
||||||
{{ toPercentage(formattedValue) }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.positive {
|
|
||||||
color: $secondary;
|
|
||||||
}
|
|
||||||
.negative {
|
|
||||||
color: $negative;
|
|
||||||
}
|
|
||||||
.neutral {
|
|
||||||
color: $primary;
|
|
||||||
}
|
|
||||||
.value-icon {
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,65 +0,0 @@
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import axios from 'axios';
|
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
|
||||||
|
|
||||||
export async function checkEntryLock(entryFk, userFk) {
|
|
||||||
const { t } = useI18n();
|
|
||||||
const quasar = useQuasar();
|
|
||||||
const { push } = useRouter();
|
|
||||||
const { data } = await axios.get(`Entries/${entryFk}`, {
|
|
||||||
params: {
|
|
||||||
filter: JSON.stringify({
|
|
||||||
fields: ['id', 'locked', 'lockerUserFk'],
|
|
||||||
include: { relation: 'user', scope: { fields: ['id', 'nickname'] } },
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const entryConfig = await axios.get('EntryConfigs/findOne');
|
|
||||||
|
|
||||||
if (data?.lockerUserFk && data?.locked) {
|
|
||||||
const now = new Date(Date.vnNow()).getTime();
|
|
||||||
const lockedTime = new Date(data.locked).getTime();
|
|
||||||
const timeDiff = (now - lockedTime) / 1000;
|
|
||||||
const isMaxTimeLockExceeded = entryConfig.data.maxLockTime > timeDiff;
|
|
||||||
|
|
||||||
if (data?.lockerUserFk !== userFk && isMaxTimeLockExceeded) {
|
|
||||||
quasar
|
|
||||||
.dialog({
|
|
||||||
component: VnConfirm,
|
|
||||||
componentProps: {
|
|
||||||
'data-cy': 'entry-lock-confirm',
|
|
||||||
title: t('entry.lock.title'),
|
|
||||||
message: t('entry.lock.message', {
|
|
||||||
userName: data?.user?.nickname,
|
|
||||||
time: timeDiff / 60,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.onOk(
|
|
||||||
async () =>
|
|
||||||
await axios.patch(`Entries/${entryFk}`, {
|
|
||||||
locked: Date.vnNow(),
|
|
||||||
lockerUserFk: userFk,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.onCancel(() => {
|
|
||||||
push({ path: `summary` });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await axios
|
|
||||||
.patch(`Entries/${entryFk}`, {
|
|
||||||
locked: Date.vnNow(),
|
|
||||||
lockerUserFk: userFk,
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
quasar.notify({
|
|
||||||
message: t('entry.lock.success'),
|
|
||||||
color: 'positive',
|
|
||||||
group: false,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
export function getColAlign(col) {
|
|
||||||
let align;
|
|
||||||
switch (col.component) {
|
|
||||||
case 'select':
|
|
||||||
align = 'left';
|
|
||||||
break;
|
|
||||||
case 'number':
|
|
||||||
align = 'right';
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
case 'checkbox':
|
|
||||||
align = 'center';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
align = col?.align;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^is[A-Z]/.test(col.name) || /^has[A-Z]/.test(col.name)) align = 'center';
|
|
||||||
|
|
||||||
return 'text-' + (align ?? 'center');
|
|
||||||
}
|
|
|
@ -27,15 +27,6 @@ export function useRole() {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function likeAny(roles) {
|
|
||||||
const roleStore = state.getRoles();
|
|
||||||
for (const role of roles) {
|
|
||||||
if (!roleStore.value.findIndex((rs) => rs.startsWith(role)) !== -1)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
function isEmployee() {
|
function isEmployee() {
|
||||||
return hasAny(['employee']);
|
return hasAny(['employee']);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +35,6 @@ export function useRole() {
|
||||||
isEmployee,
|
isEmployee,
|
||||||
fetch,
|
fetch,
|
||||||
hasAny,
|
hasAny,
|
||||||
likeAny,
|
|
||||||
state,
|
state,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,7 @@ body.body--light {
|
||||||
.q-header .q-toolbar {
|
.q-header .q-toolbar {
|
||||||
color: var(--vn-text-color);
|
color: var(--vn-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
--vn-color-negative: $negative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body.body--dark {
|
body.body--dark {
|
||||||
--vn-header-color: #5d5d5d;
|
--vn-header-color: #5d5d5d;
|
||||||
--vn-page-color: #222;
|
--vn-page-color: #222;
|
||||||
|
@ -40,8 +37,6 @@ body.body--dark {
|
||||||
--vn-text-color-contrast: black;
|
--vn-text-color-contrast: black;
|
||||||
|
|
||||||
background-color: var(--vn-page-color);
|
background-color: var(--vn-page-color);
|
||||||
|
|
||||||
--vn-color-negative: $negative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -80,6 +75,7 @@ a {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes chrome autofill background
|
||||||
input:-webkit-autofill,
|
input:-webkit-autofill,
|
||||||
select:-webkit-autofill {
|
select:-webkit-autofill {
|
||||||
color: var(--vn-text-color);
|
color: var(--vn-text-color);
|
||||||
|
@ -153,6 +149,11 @@ select:-webkit-autofill {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vn-table-separation-row {
|
||||||
|
height: 16px !important;
|
||||||
|
background-color: var(--vn-section-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Estilo para el asterisco en campos requeridos */
|
/* Estilo para el asterisco en campos requeridos */
|
||||||
.q-field.required .q-field__label:after {
|
.q-field.required .q-field__label:after {
|
||||||
content: ' *';
|
content: ' *';
|
||||||
|
@ -229,12 +230,10 @@ input::-webkit-inner-spin-button {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-bg {
|
|
||||||
filter: brightness(1.1);
|
|
||||||
mix-blend-mode: multiply;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q-table__container {
|
.q-table__container {
|
||||||
|
/* ===== Scrollbar CSS ===== /
|
||||||
|
/ Firefox */
|
||||||
|
|
||||||
* {
|
* {
|
||||||
scrollbar-width: auto;
|
scrollbar-width: auto;
|
||||||
scrollbar-color: var(--vn-label-color) transparent;
|
scrollbar-color: var(--vn-label-color) transparent;
|
||||||
|
@ -275,6 +274,8 @@ input::-webkit-inner-spin-button {
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
|
font-size: 11pt;
|
||||||
|
border-top: 1px solid var(--vn-page-color);
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,6 +319,9 @@ input::-webkit-inner-spin-button {
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row > .column:has(.q-checkbox) {
|
||||||
|
max-width: fit-content;
|
||||||
|
}
|
||||||
.q-field__inner {
|
.q-field__inner {
|
||||||
.q-field__control {
|
.q-field__control {
|
||||||
min-height: auto !important;
|
min-height: auto !important;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// Tip: Use the "Theme Builder" on Quasar's documentation website.
|
// Tip: Use the "Theme Builder" on Quasar's documentation website.
|
||||||
// Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors
|
// Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors
|
||||||
$primary: #ec8916;
|
$primary: #ec8916;
|
||||||
$secondary: #89be34;
|
$secondary: $primary;
|
||||||
$positive: #c8e484;
|
$positive: #c8e484;
|
||||||
$negative: #fb5252;
|
$negative: #fb5252;
|
||||||
$info: #84d0e2;
|
$info: #84d0e2;
|
||||||
|
@ -30,9 +30,7 @@ $color-spacer: #7979794d;
|
||||||
$border-thin-light: 1px solid $color-spacer-light;
|
$border-thin-light: 1px solid $color-spacer-light;
|
||||||
$primary-light: #f5b351;
|
$primary-light: #f5b351;
|
||||||
$dark-shadow-color: black;
|
$dark-shadow-color: black;
|
||||||
$layout-shadow-dark:
|
$layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d;
|
||||||
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-xs: 400px;
|
||||||
|
|
|
@ -33,7 +33,6 @@ globals:
|
||||||
reset: Reset
|
reset: Reset
|
||||||
close: Close
|
close: Close
|
||||||
cancel: Cancel
|
cancel: Cancel
|
||||||
isSaveAndContinue: Save and continue
|
|
||||||
clone: Clone
|
clone: Clone
|
||||||
confirm: Confirm
|
confirm: Confirm
|
||||||
assign: Assign
|
assign: Assign
|
||||||
|
@ -168,7 +167,6 @@ globals:
|
||||||
workCenters: Work centers
|
workCenters: Work centers
|
||||||
modes: Modes
|
modes: Modes
|
||||||
zones: Zones
|
zones: Zones
|
||||||
negative: Negative
|
|
||||||
zonesList: List
|
zonesList: List
|
||||||
deliveryDays: Delivery days
|
deliveryDays: Delivery days
|
||||||
upcomingDeliveries: Upcoming deliveries
|
upcomingDeliveries: Upcoming deliveries
|
||||||
|
@ -176,7 +174,6 @@ globals:
|
||||||
alias: Alias
|
alias: Alias
|
||||||
aliasUsers: Users
|
aliasUsers: Users
|
||||||
subRoles: Subroles
|
subRoles: Subroles
|
||||||
myAccount: Mi cuenta
|
|
||||||
inheritedRoles: Inherited Roles
|
inheritedRoles: Inherited Roles
|
||||||
customers: Customers
|
customers: Customers
|
||||||
customerCreate: New customer
|
customerCreate: New customer
|
||||||
|
@ -409,106 +406,6 @@ cau:
|
||||||
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
|
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
|
||||||
inputLabel: Explain why this error should not appear
|
inputLabel: Explain why this error should not appear
|
||||||
askPrivileges: Ask for privileges
|
askPrivileges: Ask for privileges
|
||||||
entry:
|
|
||||||
list:
|
|
||||||
newEntry: New entry
|
|
||||||
tableVisibleColumns:
|
|
||||||
isExcludedFromAvailable: Exclude from inventory
|
|
||||||
isOrdered: Ordered
|
|
||||||
isConfirmed: Ready to label
|
|
||||||
isReceived: Received
|
|
||||||
isRaid: Raid
|
|
||||||
landed: Date
|
|
||||||
supplierFk: Supplier
|
|
||||||
reference: Ref/Alb/Guide
|
|
||||||
invoiceNumber: Invoice
|
|
||||||
agencyModeId: Agency
|
|
||||||
isBooked: Booked
|
|
||||||
companyFk: Company
|
|
||||||
evaNotes: Notes
|
|
||||||
warehouseOutFk: Origin
|
|
||||||
warehouseInFk: Destiny
|
|
||||||
entryTypeDescription: Entry type
|
|
||||||
invoiceAmount: Import
|
|
||||||
travelFk: Travel
|
|
||||||
summary:
|
|
||||||
invoiceAmount: Amount
|
|
||||||
commission: Commission
|
|
||||||
currency: Currency
|
|
||||||
invoiceNumber: Invoice number
|
|
||||||
ordered: Ordered
|
|
||||||
booked: Booked
|
|
||||||
excludedFromAvailable: Inventory
|
|
||||||
travelReference: Reference
|
|
||||||
travelAgency: Agency
|
|
||||||
travelShipped: Shipped
|
|
||||||
travelDelivered: Delivered
|
|
||||||
travelLanded: Landed
|
|
||||||
travelReceived: Received
|
|
||||||
buys: Buys
|
|
||||||
stickers: Stickers
|
|
||||||
package: Package
|
|
||||||
packing: Pack.
|
|
||||||
grouping: Group.
|
|
||||||
buyingValue: Buying value
|
|
||||||
import: Import
|
|
||||||
pvp: PVP
|
|
||||||
basicData:
|
|
||||||
travel: Travel
|
|
||||||
currency: Currency
|
|
||||||
commission: Commission
|
|
||||||
observation: Observation
|
|
||||||
booked: Booked
|
|
||||||
excludedFromAvailable: Inventory
|
|
||||||
buys:
|
|
||||||
observations: Observations
|
|
||||||
packagingFk: Box
|
|
||||||
color: Color
|
|
||||||
printedStickers: Printed stickers
|
|
||||||
notes:
|
|
||||||
observationType: Observation type
|
|
||||||
latestBuys:
|
|
||||||
tableVisibleColumns:
|
|
||||||
image: Picture
|
|
||||||
itemFk: Item ID
|
|
||||||
weightByPiece: Weight/Piece
|
|
||||||
isActive: Active
|
|
||||||
family: Family
|
|
||||||
entryFk: Entry
|
|
||||||
freightValue: Freight value
|
|
||||||
comissionValue: Commission value
|
|
||||||
packageValue: Package value
|
|
||||||
isIgnored: Is ignored
|
|
||||||
price2: Grouping
|
|
||||||
price3: Packing
|
|
||||||
minPrice: Min
|
|
||||||
ektFk: Ekt
|
|
||||||
packingOut: Package out
|
|
||||||
landing: Landing
|
|
||||||
isExcludedFromAvailable: Exclude from inventory
|
|
||||||
isRaid: Raid
|
|
||||||
invoiceNumber: Invoice
|
|
||||||
reference: Ref/Alb/Guide
|
|
||||||
params:
|
|
||||||
isExcludedFromAvailable: Excluir del inventario
|
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Lista para etiquetar
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Redada
|
|
||||||
landed: Fecha
|
|
||||||
supplierFk: Proveedor
|
|
||||||
invoiceNumber: Nº Factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
agencyModeId: Agencia
|
|
||||||
isBooked: Asentado
|
|
||||||
companyFk: Empresa
|
|
||||||
travelFk: Envio
|
|
||||||
evaNotes: Notas
|
|
||||||
warehouseOutFk: Origen
|
|
||||||
warehouseInFk: Destino
|
|
||||||
entryTypeDescription: Tipo entrada
|
|
||||||
invoiceAmount: Importe
|
|
||||||
dated: Fecha
|
|
||||||
ticket:
|
ticket:
|
||||||
params:
|
params:
|
||||||
ticketFk: Ticket ID
|
ticketFk: Ticket ID
|
||||||
|
@ -738,8 +635,6 @@ wagon:
|
||||||
name: Name
|
name: Name
|
||||||
|
|
||||||
supplier:
|
supplier:
|
||||||
search: Search supplier
|
|
||||||
searchInfo: Search supplier by id or name
|
|
||||||
list:
|
list:
|
||||||
payMethod: Pay method
|
payMethod: Pay method
|
||||||
account: Account
|
account: Account
|
||||||
|
|
|
@ -33,11 +33,9 @@ globals:
|
||||||
reset: Restaurar
|
reset: Restaurar
|
||||||
close: Cerrar
|
close: Cerrar
|
||||||
cancel: Cancelar
|
cancel: Cancelar
|
||||||
isSaveAndContinue: Guardar y continuar
|
|
||||||
clone: Clonar
|
clone: Clonar
|
||||||
confirm: Confirmar
|
confirm: Confirmar
|
||||||
assign: Asignar
|
assign: Asignar
|
||||||
replace: Sustituir
|
|
||||||
back: Volver
|
back: Volver
|
||||||
yes: Si
|
yes: Si
|
||||||
no: No
|
no: No
|
||||||
|
@ -50,7 +48,6 @@ globals:
|
||||||
rowRemoved: Fila eliminada
|
rowRemoved: Fila eliminada
|
||||||
pleaseWait: Por favor espera...
|
pleaseWait: Por favor espera...
|
||||||
noPinnedModules: No has fijado ningún módulo
|
noPinnedModules: No has fijado ningún módulo
|
||||||
split: Split
|
|
||||||
summary:
|
summary:
|
||||||
basicData: Datos básicos
|
basicData: Datos básicos
|
||||||
daysOnward: Días adelante
|
daysOnward: Días adelante
|
||||||
|
@ -58,8 +55,8 @@ globals:
|
||||||
today: Hoy
|
today: Hoy
|
||||||
yesterday: Ayer
|
yesterday: Ayer
|
||||||
dateFormat: es-ES
|
dateFormat: es-ES
|
||||||
noSelectedRows: No tienes ninguna línea seleccionada
|
|
||||||
microsip: Abrir en MicroSIP
|
microsip: Abrir en MicroSIP
|
||||||
|
noSelectedRows: No tienes ninguna línea seleccionada
|
||||||
downloadCSVSuccess: Descarga de CSV exitosa
|
downloadCSVSuccess: Descarga de CSV exitosa
|
||||||
reference: Referencia
|
reference: Referencia
|
||||||
agency: Agencia
|
agency: Agencia
|
||||||
|
@ -79,10 +76,8 @@ globals:
|
||||||
requiredField: Campo obligatorio
|
requiredField: Campo obligatorio
|
||||||
class: clase
|
class: clase
|
||||||
type: Tipo
|
type: Tipo
|
||||||
reason: Motivo
|
reason: motivo
|
||||||
removeSelection: Eliminar selección
|
|
||||||
noResults: Sin resultados
|
noResults: Sin resultados
|
||||||
results: resultados
|
|
||||||
system: Sistema
|
system: Sistema
|
||||||
notificationSent: Notificación enviada
|
notificationSent: Notificación enviada
|
||||||
warehouse: Almacén
|
warehouse: Almacén
|
||||||
|
@ -171,7 +166,6 @@ globals:
|
||||||
agency: Agencia
|
agency: Agencia
|
||||||
workCenters: Centros de trabajo
|
workCenters: Centros de trabajo
|
||||||
modes: Modos
|
modes: Modos
|
||||||
negative: Tickets negativos
|
|
||||||
zones: Zonas
|
zones: Zonas
|
||||||
zonesList: Listado
|
zonesList: Listado
|
||||||
deliveryDays: Días de entrega
|
deliveryDays: Días de entrega
|
||||||
|
@ -292,9 +286,9 @@ globals:
|
||||||
buyRequest: Peticiones de compra
|
buyRequest: Peticiones de compra
|
||||||
wasteBreakdown: Deglose de mermas
|
wasteBreakdown: Deglose de mermas
|
||||||
itemCreate: Nuevo artículo
|
itemCreate: Nuevo artículo
|
||||||
tax: IVA
|
tax: 'IVA'
|
||||||
botanical: Botánico
|
botanical: 'Botánico'
|
||||||
barcode: Código de barras
|
barcode: 'Código de barras'
|
||||||
itemTypeCreate: Nueva familia
|
itemTypeCreate: Nueva familia
|
||||||
family: Familia
|
family: Familia
|
||||||
lastEntries: Últimas entradas
|
lastEntries: Últimas entradas
|
||||||
|
@ -358,7 +352,7 @@ globals:
|
||||||
from: Desde
|
from: Desde
|
||||||
to: Hasta
|
to: Hasta
|
||||||
supplierFk: Proveedor
|
supplierFk: Proveedor
|
||||||
supplierRef: Nº factura
|
supplierRef: Ref. proveedor
|
||||||
serial: Serie
|
serial: Serie
|
||||||
amount: Importe
|
amount: Importe
|
||||||
awbCode: AWB
|
awbCode: AWB
|
||||||
|
@ -403,87 +397,6 @@ cau:
|
||||||
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
||||||
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
|
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
|
||||||
askPrivileges: Solicitar permisos
|
askPrivileges: Solicitar permisos
|
||||||
entry:
|
|
||||||
list:
|
|
||||||
newEntry: Nueva entrada
|
|
||||||
tableVisibleColumns:
|
|
||||||
isExcludedFromAvailable: Excluir del inventario
|
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Lista para etiquetar
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Redada
|
|
||||||
landed: Fecha
|
|
||||||
supplierFk: Proveedor
|
|
||||||
invoiceNumber: Nº Factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
agencyModeId: Agencia
|
|
||||||
isBooked: Asentado
|
|
||||||
companyFk: Empresa
|
|
||||||
travelFk: Envio
|
|
||||||
evaNotes: Notas
|
|
||||||
warehouseOutFk: Origen
|
|
||||||
warehouseInFk: Destino
|
|
||||||
entryTypeDescription: Tipo entrada
|
|
||||||
invoiceAmount: Importe
|
|
||||||
summary:
|
|
||||||
invoiceAmount: Importe
|
|
||||||
commission: Comisión
|
|
||||||
currency: Moneda
|
|
||||||
invoiceNumber: Núm. factura
|
|
||||||
ordered: Pedida
|
|
||||||
booked: Contabilizada
|
|
||||||
excludedFromAvailable: Inventario
|
|
||||||
travelReference: Referencia
|
|
||||||
travelAgency: Agencia
|
|
||||||
travelShipped: F. envio
|
|
||||||
travelWarehouseOut: Alm. salida
|
|
||||||
travelDelivered: Enviada
|
|
||||||
travelLanded: F. entrega
|
|
||||||
travelReceived: Recibida
|
|
||||||
buys: Compras
|
|
||||||
stickers: Etiquetas
|
|
||||||
package: Embalaje
|
|
||||||
packing: Pack.
|
|
||||||
grouping: Group.
|
|
||||||
buyingValue: Coste
|
|
||||||
import: Importe
|
|
||||||
pvp: PVP
|
|
||||||
basicData:
|
|
||||||
travel: Envío
|
|
||||||
currency: Moneda
|
|
||||||
observation: Observación
|
|
||||||
commission: Comisión
|
|
||||||
booked: Asentado
|
|
||||||
excludedFromAvailable: Inventario
|
|
||||||
buys:
|
|
||||||
observations: Observaciónes
|
|
||||||
packagingFk: Embalaje
|
|
||||||
color: Color
|
|
||||||
printedStickers: Etiquetas impresas
|
|
||||||
notes:
|
|
||||||
observationType: Tipo de observación
|
|
||||||
latestBuys:
|
|
||||||
tableVisibleColumns:
|
|
||||||
image: Foto
|
|
||||||
itemFk: Id Artículo
|
|
||||||
weightByPiece: Peso (gramos)/tallo
|
|
||||||
isActive: Activo
|
|
||||||
family: Familia
|
|
||||||
entryFk: Entrada
|
|
||||||
freightValue: Porte
|
|
||||||
comissionValue: Comisión
|
|
||||||
packageValue: Embalaje
|
|
||||||
isIgnored: Ignorado
|
|
||||||
price2: Grouping
|
|
||||||
price3: Packing
|
|
||||||
minPrice: Min
|
|
||||||
ektFk: Ekt
|
|
||||||
packingOut: Embalaje envíos
|
|
||||||
landing: Llegada
|
|
||||||
isExcludedFromAvailable: Excluir del inventario
|
|
||||||
isRaid: Redada
|
|
||||||
invoiceNumber: Nº Factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
ticket:
|
ticket:
|
||||||
params:
|
params:
|
||||||
ticketFk: ID de ticket
|
ticketFk: ID de ticket
|
||||||
|
@ -497,38 +410,6 @@ ticket:
|
||||||
freightItemName: Nombre
|
freightItemName: Nombre
|
||||||
packageItemName: Embalaje
|
packageItemName: Embalaje
|
||||||
longName: Descripción
|
longName: Descripción
|
||||||
pageTitles:
|
|
||||||
tickets: Tickets
|
|
||||||
list: Listado
|
|
||||||
ticketCreate: Nuevo ticket
|
|
||||||
summary: Resumen
|
|
||||||
basicData: Datos básicos
|
|
||||||
boxing: Encajado
|
|
||||||
sms: Sms
|
|
||||||
notes: Notas
|
|
||||||
sale: Lineas del pedido
|
|
||||||
dms: Gestión documental
|
|
||||||
negative: Tickets negativos
|
|
||||||
volume: Volumen
|
|
||||||
observation: Notas
|
|
||||||
ticketAdvance: Adelantar tickets
|
|
||||||
futureTickets: Tickets a futuro
|
|
||||||
expedition: Expedición
|
|
||||||
purchaseRequest: Petición de compra
|
|
||||||
weeklyTickets: Tickets programados
|
|
||||||
saleTracking: Líneas preparadas
|
|
||||||
services: Servicios
|
|
||||||
tracking: Estados
|
|
||||||
components: Componentes
|
|
||||||
pictures: Fotos
|
|
||||||
packages: Bultos
|
|
||||||
list:
|
|
||||||
nickname: Alias
|
|
||||||
state: Estado
|
|
||||||
shipped: Enviado
|
|
||||||
landed: Entregado
|
|
||||||
salesPerson: Comercial
|
|
||||||
total: Total
|
|
||||||
card:
|
card:
|
||||||
customerId: ID cliente
|
customerId: ID cliente
|
||||||
customerCard: Ficha del cliente
|
customerCard: Ficha del cliente
|
||||||
|
@ -575,48 +456,6 @@ ticket:
|
||||||
consigneeStreet: Dirección
|
consigneeStreet: Dirección
|
||||||
create:
|
create:
|
||||||
address: Dirección
|
address: Dirección
|
||||||
invoiceOut:
|
|
||||||
card:
|
|
||||||
issued: Fecha emisión
|
|
||||||
customerCard: Ficha del cliente
|
|
||||||
ticketList: Listado de tickets
|
|
||||||
summary:
|
|
||||||
issued: Fecha
|
|
||||||
dued: Fecha límite
|
|
||||||
booked: Contabilizada
|
|
||||||
taxBreakdown: Desglose impositivo
|
|
||||||
taxableBase: Base imp.
|
|
||||||
rate: Tarifa
|
|
||||||
fee: Cuota
|
|
||||||
tickets: Tickets
|
|
||||||
totalWithVat: Importe
|
|
||||||
globalInvoices:
|
|
||||||
errors:
|
|
||||||
chooseValidClient: Selecciona un cliente válido
|
|
||||||
chooseValidCompany: Selecciona una empresa válida
|
|
||||||
chooseValidPrinter: Selecciona una impresora válida
|
|
||||||
chooseValidSerialType: Selecciona una tipo de serie válida
|
|
||||||
fillDates: La fecha de la factura y la fecha máxima deben estar completas
|
|
||||||
invoiceDateLessThanMaxDate: La fecha de la factura no puede ser menor que la fecha máxima
|
|
||||||
invoiceWithFutureDate: Existe una factura con una fecha futura
|
|
||||||
noTicketsToInvoice: No existen tickets para facturar
|
|
||||||
criticalInvoiceError: Error crítico en la facturación proceso detenido
|
|
||||||
invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
|
|
||||||
table:
|
|
||||||
addressId: Id dirección
|
|
||||||
streetAddress: Dirección fiscal
|
|
||||||
statusCard:
|
|
||||||
percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
|
|
||||||
pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
|
|
||||||
negativeBases:
|
|
||||||
clientId: Id cliente
|
|
||||||
base: Base
|
|
||||||
active: Activo
|
|
||||||
hasToInvoice: Facturar
|
|
||||||
verifiedData: Datos comprobados
|
|
||||||
comercial: Comercial
|
|
||||||
errors:
|
|
||||||
downloadCsvFailed: Error al descargar CSV
|
|
||||||
order:
|
order:
|
||||||
field:
|
field:
|
||||||
salesPersonFk: Comercial
|
salesPersonFk: Comercial
|
||||||
|
@ -627,34 +466,15 @@ order:
|
||||||
list:
|
list:
|
||||||
newOrder: Nuevo Pedido
|
newOrder: Nuevo Pedido
|
||||||
summary:
|
summary:
|
||||||
basket: Cesta
|
issued: Fecha
|
||||||
notConfirmed: No confirmada
|
dued: Fecha límite
|
||||||
created: Creado
|
booked: Contabilizada
|
||||||
createdFrom: Creado desde
|
taxBreakdown: Desglose impositivo
|
||||||
address: Dirección
|
taxableBase: Base imp.
|
||||||
total: Total
|
rate: Tarifa
|
||||||
vat: IVA
|
fee: Cuota
|
||||||
state: Estado
|
tickets: Tickets
|
||||||
alias: Alias
|
totalWithVat: Importe
|
||||||
items: Artículos
|
|
||||||
orderTicketList: Tickets del pedido
|
|
||||||
amount: Monto
|
|
||||||
confirm: Confirmar
|
|
||||||
confirmLines: Confirmar lineas
|
|
||||||
shelving:
|
|
||||||
list:
|
|
||||||
parking: Parking
|
|
||||||
priority: Prioridad
|
|
||||||
newShelving: Nuevo Carro
|
|
||||||
summary:
|
|
||||||
recyclable: Reciclable
|
|
||||||
parking:
|
|
||||||
pickingOrder: Orden de recogida
|
|
||||||
row: Fila
|
|
||||||
column: Columna
|
|
||||||
searchBar:
|
|
||||||
info: Puedes buscar por código de parking
|
|
||||||
label: Buscar parking...
|
|
||||||
department:
|
department:
|
||||||
chat: Chat
|
chat: Chat
|
||||||
bossDepartment: Jefe de departamento
|
bossDepartment: Jefe de departamento
|
||||||
|
@ -815,8 +635,8 @@ wagon:
|
||||||
volumeNotEmpty: El volumen no puede estar vacío
|
volumeNotEmpty: El volumen no puede estar vacío
|
||||||
typeNotEmpty: El tipo no puede estar vacío
|
typeNotEmpty: El tipo no puede estar vacío
|
||||||
maxTrays: Has alcanzado el número máximo de bandejas
|
maxTrays: Has alcanzado el número máximo de bandejas
|
||||||
minHeightBetweenTrays: La distancia mínima entre bandejas es
|
minHeightBetweenTrays: 'La distancia mínima entre bandejas es '
|
||||||
maxWagonHeight: La altura máxima del vagón es
|
maxWagonHeight: 'La altura máxima del vagón es '
|
||||||
uncompleteTrays: Hay bandejas sin completar
|
uncompleteTrays: Hay bandejas sin completar
|
||||||
params:
|
params:
|
||||||
label: Etiqueta
|
label: Etiqueta
|
||||||
|
@ -824,8 +644,6 @@ wagon:
|
||||||
volume: Volumen
|
volume: Volumen
|
||||||
name: Nombre
|
name: Nombre
|
||||||
supplier:
|
supplier:
|
||||||
search: Buscar proveedor
|
|
||||||
searchInfo: Buscar proveedor por id o nombre
|
|
||||||
list:
|
list:
|
||||||
payMethod: Método de pago
|
payMethod: Método de pago
|
||||||
account: Cuenta
|
account: Cuenta
|
||||||
|
@ -963,7 +781,7 @@ components:
|
||||||
cardDescriptor:
|
cardDescriptor:
|
||||||
mainList: Listado principal
|
mainList: Listado principal
|
||||||
summary: Resumen
|
summary: Resumen
|
||||||
moreOptions: Más opciones
|
moreOptions: 'Más opciones'
|
||||||
leftMenu:
|
leftMenu:
|
||||||
addToPinned: Añadir a fijados
|
addToPinned: Añadir a fijados
|
||||||
removeFromPinned: Eliminar de fijados
|
removeFromPinned: Eliminar de fijados
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Dark, Quasar } from 'quasar';
|
import { Dark, Quasar } from 'quasar';
|
||||||
import { computed, onMounted } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { localeEquivalence } from 'src/i18n/index';
|
import { localeEquivalence } from 'src/i18n/index';
|
||||||
import quasarLang from 'src/utils/quasarLang';
|
import quasarLang from 'src/utils/quasarLang';
|
||||||
import { langs } from 'src/boot/defaults/constants.js';
|
|
||||||
|
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
|
|
||||||
const userLocale = computed({
|
const userLocale = computed({
|
||||||
get() {
|
get() {
|
||||||
return locale.value;
|
return locale.value;
|
||||||
|
@ -28,6 +28,7 @@ const darkMode = computed({
|
||||||
Dark.set(value);
|
Dark.set(value);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const langs = ['en', 'es'];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -51,6 +51,7 @@ const removeAlias = () => {
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
:url="`MailAliases/${entityId}`"
|
:url="`MailAliases/${entityId}`"
|
||||||
|
module="Alias"
|
||||||
data-key="Alias"
|
data-key="Alias"
|
||||||
title="alias"
|
title="alias"
|
||||||
>
|
>
|
||||||
|
|
|
@ -23,7 +23,8 @@ onMounted(async () => {
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
:url="`VnUsers/preview`"
|
:url="`VnUsers/preview`"
|
||||||
:filter="{ ...filter, where: { id: entityId } }"
|
:filter="filter"
|
||||||
|
module="Account"
|
||||||
data-key="Account"
|
data-key="Account"
|
||||||
title="nickname"
|
title="nickname"
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,7 +12,6 @@ import VnInputPassword from 'src/components/common/VnInputPassword.vue';
|
||||||
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
hasAccount: {
|
hasAccount: {
|
||||||
|
@ -122,14 +121,18 @@ onMounted(() => {
|
||||||
:promise="sync"
|
:promise="sync"
|
||||||
>
|
>
|
||||||
<template #customHTML>
|
<template #customHTML>
|
||||||
<VnCheckbox
|
{{ shouldSyncPassword }}
|
||||||
v-model="shouldSyncPassword"
|
<QCheckbox
|
||||||
:label="t('account.card.actions.sync.checkbox')"
|
:label="t('account.card.actions.sync.checkbox')"
|
||||||
:info="t('account.card.actions.sync.tooltip')"
|
v-model="shouldSyncPassword"
|
||||||
|
class="full-width"
|
||||||
clearable
|
clearable
|
||||||
clear-icon="close"
|
clear-icon="close"
|
||||||
color="primary"
|
>
|
||||||
/>
|
<QIcon style="padding-left: 10px" color="primary" name="info" size="sm">
|
||||||
|
<QTooltip>{{ t('account.card.actions.sync.tooltip') }}</QTooltip>
|
||||||
|
</QIcon></QCheckbox
|
||||||
|
>
|
||||||
<VnInputPassword
|
<VnInputPassword
|
||||||
v-if="shouldSyncPassword"
|
v-if="shouldSyncPassword"
|
||||||
:label="t('login.password')"
|
:label="t('login.password')"
|
||||||
|
|
|
@ -35,6 +35,7 @@ const removeRole = async () => {
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
url="VnRoles"
|
url="VnRoles"
|
||||||
:filter="{ where: { id: entityId } }"
|
:filter="{ where: { id: entityId } }"
|
||||||
|
module="Role"
|
||||||
data-key="Role"
|
data-key="Role"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
>
|
>
|
||||||
|
|
|
@ -46,6 +46,7 @@ onMounted(async () => {
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
:url="`Claims/${entityId}`"
|
:url="`Claims/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
|
module="Claim"
|
||||||
title="client.name"
|
title="client.name"
|
||||||
data-key="Claim"
|
data-key="Claim"
|
||||||
>
|
>
|
||||||
|
@ -85,7 +86,7 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv v-if="entity.ticket?.zone?.id" :label="t('claim.zone')">
|
<VnLv :label="t('claim.zone')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">
|
<span class="link">
|
||||||
{{ entity.ticket?.zone?.name }}
|
{{ entity.ticket?.zone?.name }}
|
||||||
|
@ -97,10 +98,11 @@ onMounted(async () => {
|
||||||
:label="t('claim.province')"
|
:label="t('claim.province')"
|
||||||
:value="entity.ticket?.address?.province?.name"
|
:value="entity.ticket?.address?.province?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv v-if="entity.ticketFk" :label="t('claim.ticketId')">
|
<VnLv :label="t('claim.ticketId')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">
|
<span class="link">
|
||||||
{{ entity.ticketFk }}
|
{{ entity.ticketFk }}
|
||||||
|
|
||||||
<TicketDescriptorProxy :id="entity.ticketFk" />
|
<TicketDescriptorProxy :id="entity.ticketFk" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, useAttrs } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import VnNotes from 'src/components/ui/VnNotes.vue';
|
import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||||
|
@ -7,7 +7,6 @@ import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const user = state.getUser();
|
const user = state.getUser();
|
||||||
const $attrs = useAttrs();
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: { type: [Number, String], default: null },
|
id: { type: [Number, String], default: null },
|
||||||
|
|
|
@ -131,7 +131,7 @@ const STATE_COLOR = {
|
||||||
prefix="claim"
|
prefix="claim"
|
||||||
:array-data-props="{
|
:array-data-props="{
|
||||||
url: 'Claims/filter',
|
url: 'Claims/filter',
|
||||||
order: 'cs.priority ASC, created ASC',
|
order: ['cs.priority ASC', 'created ASC'],
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #advanced-menu>
|
<template #advanced-menu>
|
||||||
|
|
|
@ -117,7 +117,7 @@ const toCustomerAddressEdit = (addressId) => {
|
||||||
data-key="CustomerAddresses"
|
data-key="CustomerAddresses"
|
||||||
order="id DESC"
|
order="id DESC"
|
||||||
ref="vnPaginateRef"
|
ref="vnPaginateRef"
|
||||||
:filter="addressFilter"
|
:user-filter="addressFilter"
|
||||||
:url="`Clients/${route.params.id}/addresses`"
|
:url="`Clients/${route.params.id}/addresses`"
|
||||||
/>
|
/>
|
||||||
<div class="full-width flex justify-center">
|
<div class="full-width flex justify-center">
|
||||||
|
@ -189,11 +189,11 @@ const toCustomerAddressEdit = (addressId) => {
|
||||||
|
|
||||||
<QSeparator
|
<QSeparator
|
||||||
class="q-mx-lg"
|
class="q-mx-lg"
|
||||||
v-if="item?.observations?.length"
|
v-if="item.observations.length"
|
||||||
vertical
|
vertical
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="item?.observations?.length">
|
<div v-if="item.observations.length">
|
||||||
<div
|
<div
|
||||||
:key="obIndex"
|
:key="obIndex"
|
||||||
class="flex q-mb-sm"
|
class="flex q-mb-sm"
|
||||||
|
|
|
@ -61,23 +61,6 @@ const columns = computed(() => [
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
name: 'buyerId',
|
|
||||||
label: t('customer.params.buyerId'),
|
|
||||||
component: 'select',
|
|
||||||
attrs: {
|
|
||||||
url: 'TicketRequests/getItemTypeWorker',
|
|
||||||
optionLabel: 'nickname',
|
|
||||||
optionValue: 'id',
|
|
||||||
|
|
||||||
fields: ['id', 'nickname'],
|
|
||||||
sortBy: ['nickname ASC'],
|
|
||||||
optionFilter: 'firstName',
|
|
||||||
},
|
|
||||||
cardVisible: false,
|
|
||||||
visible: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -91,7 +74,6 @@ const columns = computed(() => [
|
||||||
name: 'quantity',
|
name: 'quantity',
|
||||||
label: t('globals.quantity'),
|
label: t('globals.quantity'),
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
visible: true,
|
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
inWhere: true,
|
inWhere: true,
|
||||||
},
|
},
|
||||||
|
@ -137,7 +119,7 @@ const openSendEmailDialog = async () => {
|
||||||
openConfirmationModal(
|
openConfirmationModal(
|
||||||
t('The consumption report will be sent'),
|
t('The consumption report will be sent'),
|
||||||
t('Please, confirm'),
|
t('Please, confirm'),
|
||||||
() => sendCampaignMetricsEmail({ address: arrayData.store.data.email }),
|
() => sendCampaignMetricsEmail({ address: arrayData.store.data.email })
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const sendCampaignMetricsEmail = ({ address }) => {
|
const sendCampaignMetricsEmail = ({ address }) => {
|
||||||
|
@ -156,11 +138,11 @@ const updateDateParams = (value, params) => {
|
||||||
const campaign = campaignList.value.find((c) => c.id === value);
|
const campaign = campaignList.value.find((c) => c.id === value);
|
||||||
if (!campaign) return;
|
if (!campaign) return;
|
||||||
|
|
||||||
const { dated, scopeDays } = campaign;
|
const { dated, previousDays, scopeDays } = campaign;
|
||||||
const from = new Date(dated);
|
const _date = new Date(dated);
|
||||||
from.setDate(from.getDate() - scopeDays);
|
const [from, to] = dateRange(_date);
|
||||||
params.from = from;
|
params.from = new Date(from.setDate(from.getDate() - previousDays)).toISOString();
|
||||||
params.to = dated;
|
params.to = new Date(to.setDate(to.getDate() + scopeDays)).toISOString();
|
||||||
return params;
|
return params;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -218,62 +200,29 @@ const updateDateParams = (value, params) => {
|
||||||
<div v-if="row.subName" class="subName">
|
<div v-if="row.subName" class="subName">
|
||||||
{{ row.subName }}
|
{{ row.subName }}
|
||||||
</div>
|
</div>
|
||||||
<FetchedTags :item="row" />
|
<FetchedTags :item="row" :max-length="3" />
|
||||||
</template>
|
</template>
|
||||||
<template #moreFilterPanel="{ params }">
|
<template #moreFilterPanel="{ params }">
|
||||||
<div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
|
<div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
|
||||||
<VnSelect
|
|
||||||
:filled="true"
|
|
||||||
class="q-px-sm q-pt-none fit"
|
|
||||||
url="ItemTypes"
|
|
||||||
v-model="params.typeId"
|
|
||||||
:label="t('item.list.typeName')"
|
|
||||||
:fields="['id', 'name', 'categoryFk']"
|
|
||||||
:include="'category'"
|
|
||||||
:sortBy="'name ASC'"
|
|
||||||
dense
|
|
||||||
@update:model-value="(data) => updateDateParams(data, params)"
|
|
||||||
>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>{{
|
|
||||||
scope.opt?.category?.name
|
|
||||||
}}</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnSelect
|
|
||||||
:filled="true"
|
|
||||||
class="q-px-sm q-pt-none fit"
|
|
||||||
url="ItemCategories"
|
|
||||||
v-model="params.categoryId"
|
|
||||||
:label="t('item.list.category')"
|
|
||||||
:fields="['id', 'name']"
|
|
||||||
:sortBy="'name ASC'"
|
|
||||||
dense
|
|
||||||
@update:model-value="(data) => updateDateParams(data, params)"
|
|
||||||
/>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="params.campaign"
|
v-model="params.campaign"
|
||||||
:options="campaignList"
|
:options="campaignList"
|
||||||
:label="t('globals.campaign')"
|
:label="t('globals.campaign')"
|
||||||
:filled="true"
|
:filled="true"
|
||||||
class="q-px-sm q-pt-none fit"
|
class="q-px-sm q-pt-none fit"
|
||||||
:option-label="(opt) => t(opt.code)"
|
|
||||||
:fields="['id', 'code', 'dated', 'scopeDays']"
|
|
||||||
@update:model-value="(data) => updateDateParams(data, params)"
|
|
||||||
dense
|
dense
|
||||||
|
option-label="code"
|
||||||
|
@update:model-value="(data) => updateDateParams(data, params)"
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel> {{ t(scope.opt?.code) }} </QItemLabel>
|
<QItemLabel>
|
||||||
<QItemLabel caption>
|
{{ scope.opt?.code }}
|
||||||
{{ new Date(scope.opt?.dated).getFullYear() }}
|
{{
|
||||||
</QItemLabel>
|
new Date(scope.opt?.dated).getFullYear()
|
||||||
|
}}</QItemLabel
|
||||||
|
>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
|
@ -298,19 +247,7 @@ const updateDateParams = (value, params) => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
|
||||||
|
|
||||||
valentinesDay: Valentine's Day
|
|
||||||
mothersDay: Mother's Day
|
|
||||||
allSaints: All Saints' Day
|
|
||||||
es:
|
es:
|
||||||
Enter a new search: Introduce una nueva búsqueda
|
Enter a new search: Introduce una nueva búsqueda
|
||||||
Group by items: Agrupar por artículos
|
Group by items: Agrupar por artículos
|
||||||
valentinesDay: Día de San Valentín
|
|
||||||
mothersDay: Día de la Madre
|
|
||||||
allSaints: Día de Todos los Santos
|
|
||||||
Campaign consumption: Consumo campaña
|
|
||||||
Campaign: Campaña
|
|
||||||
From: Desde
|
|
||||||
To: Hasta
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -55,6 +55,7 @@ const debtWarning = computed(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
|
module="Customer"
|
||||||
:url="`Clients/${entityId}/getCard`"
|
:url="`Clients/${entityId}/getCard`"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
data-key="Customer"
|
data-key="Customer"
|
||||||
|
@ -109,21 +110,7 @@ const debtWarning = computed(() => {
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
|
<QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
|
||||||
<QIcon
|
|
||||||
v-if="entity?.substitutionAllowed"
|
|
||||||
name="help"
|
|
||||||
size="xs"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<QTooltip>{{ t('Allowed substitution') }}</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
<QIcon
|
|
||||||
v-if="customer?.isFreezed"
|
|
||||||
name="vn:frozen"
|
|
||||||
size="xs"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
<QIcon
|
||||||
|
|
|
@ -61,16 +61,6 @@ const openCreateForm = (type) => {
|
||||||
.join('&');
|
.join('&');
|
||||||
useOpenURL(`/#/${type}/list?${params}`);
|
useOpenURL(`/#/${type}/list?${params}`);
|
||||||
};
|
};
|
||||||
const updateSubstitutionAllowed = async () => {
|
|
||||||
try {
|
|
||||||
await axios.patch(`Clients/${route.params.id}`, {
|
|
||||||
substitutionAllowed: !$props.customer.substitutionAllowed,
|
|
||||||
});
|
|
||||||
notify('globals.notificationSent', 'positive');
|
|
||||||
} catch (error) {
|
|
||||||
notify(error.message, 'positive');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -79,13 +69,6 @@ const updateSubstitutionAllowed = async () => {
|
||||||
{{ t('globals.pageTitles.createTicket') }}
|
{{ t('globals.pageTitles.createTicket') }}
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem v-ripple clickable>
|
|
||||||
<QItemSection @click="updateSubstitutionAllowed()">{{
|
|
||||||
$props.customer.substitutionAllowed
|
|
||||||
? t('Disable substitution')
|
|
||||||
: t('Allow substitution')
|
|
||||||
}}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem v-ripple clickable>
|
<QItem v-ripple clickable>
|
||||||
<QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
|
<QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
|
@ -8,8 +8,8 @@ import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSelectVies from 'src/components/common/VnSelectVies.vue';
|
||||||
import VnLocation from 'src/components/common/VnLocation.vue';
|
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -104,6 +104,7 @@ function handleLocation(data, location) {
|
||||||
:required="true"
|
:required="true"
|
||||||
@update:model-value="(location) => handleLocation(data, location)"
|
@update:model-value="(location) => handleLocation(data, location)"
|
||||||
/>
|
/>
|
||||||
|
<VnSelectVies v-model="data.viesCode" style="max-width: 30%" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<QCheckbox :label="t('Active')" v-model="data.isActive" />
|
<QCheckbox :label="t('Active')" v-model="data.isActive" />
|
||||||
|
@ -111,11 +112,7 @@ function handleLocation(data, location) {
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<QCheckbox :label="t('Has to invoice')" v-model="data.hasToInvoice" />
|
<QCheckbox :label="t('Has to invoice')" v-model="data.hasToInvoice" />
|
||||||
<VnCheckbox
|
<QCheckbox :label="t('Verified data')" v-model="data.isTaxDataChecked" />
|
||||||
v-model="data.isVies"
|
|
||||||
:label="t('globals.isVies')"
|
|
||||||
:info="t('whenActivatingIt')"
|
|
||||||
/>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
||||||
<VnRow>
|
<VnRow>
|
||||||
|
@ -127,11 +124,17 @@ function handleLocation(data, location) {
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnCheckbox
|
<div>
|
||||||
v-model="data.isEqualizated"
|
<QCheckbox
|
||||||
:label="t('Is equalizated')"
|
:label="t('Is equalizated')"
|
||||||
:info="t('inOrderToInvoice')"
|
v-model="data.isEqualizated"
|
||||||
/>
|
/>
|
||||||
|
<QIcon class="cursor-info q-ml-sm" name="info" size="sm">
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('inOrderToInvoice') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
<QCheckbox :label="t('Daily invoice')" v-model="data.hasDailyInvoice" />
|
<QCheckbox :label="t('Daily invoice')" v-model="data.hasDailyInvoice" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
||||||
|
@ -139,9 +142,6 @@ function handleLocation(data, location) {
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('Electronic invoice')"
|
:label="t('Electronic invoice')"
|
||||||
v-model="data.hasElectronicInvoice"
|
v-model="data.hasElectronicInvoice"
|
||||||
/><QCheckbox
|
|
||||||
:label="t('Verified data')"
|
|
||||||
v-model="data.isTaxDataChecked"
|
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
|
@ -169,11 +169,9 @@ es:
|
||||||
Incoterms authorization: Autorización incoterms
|
Incoterms authorization: Autorización incoterms
|
||||||
Electronic invoice: Factura electrónica
|
Electronic invoice: Factura electrónica
|
||||||
onlyLetters: Sólo se pueden usar letras, números y espacios
|
onlyLetters: Sólo se pueden usar letras, números y espacios
|
||||||
whenActivatingIt: Al activarlo, no informar el código del país en el campo nif
|
|
||||||
inOrderToInvoice: Para facturar no se consulta este campo, sino el RE de consignatario. Al modificar este campo si no esta marcada la casilla Facturar por consignatario, se propagará automaticamente el cambio a todos lo consignatarios, en caso contrario preguntará al usuario si quiere o no propagar
|
inOrderToInvoice: Para facturar no se consulta este campo, sino el RE de consignatario. Al modificar este campo si no esta marcada la casilla Facturar por consignatario, se propagará automaticamente el cambio a todos lo consignatarios, en caso contrario preguntará al usuario si quiere o no propagar
|
||||||
Daily invoice: Facturación diaria
|
Daily invoice: Facturación diaria
|
||||||
en:
|
en:
|
||||||
onlyLetters: Only letters, numbers and spaces can be used
|
onlyLetters: Only letters, numbers and spaces can be used
|
||||||
whenActivatingIt: When activating it, do not enter the country code in the ID field
|
|
||||||
inOrderToInvoice: In order to invoice, this field is not contulted, but the consignee's ET. When modifiying this field if the invoice by address option is not checked, the change will be automatically propagated to all addresses, otherwise the user will be asked if he wants to propagate it or not
|
inOrderToInvoice: In order to invoice, this field is not contulted, but the consignee's ET. When modifiying this field if the invoice by address option is not checked, the change will be automatically propagated to all addresses, otherwise the user will be asked if he wants to propagate it or not
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
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';
|
||||||
|
@ -51,7 +52,11 @@ const exprBuilder = (param, value) => {
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput :label="t('Name')" v-model="params.name" is-outlined />
|
<VnInput
|
||||||
|
:label="t('globals.name')"
|
||||||
|
v-model="params.name"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
|
|
|
@ -264,7 +264,6 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'isActive',
|
name: 'isActive',
|
||||||
label: t('customer.summary.isActive'),
|
label: t('customer.summary.isActive'),
|
||||||
component: 'checkbox',
|
|
||||||
chip: {
|
chip: {
|
||||||
color: null,
|
color: null,
|
||||||
condition: (value) => !value,
|
condition: (value) => !value,
|
||||||
|
@ -303,7 +302,6 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'isFreezed',
|
name: 'isFreezed',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
|
label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
|
||||||
component: 'checkbox',
|
|
||||||
chip: {
|
chip: {
|
||||||
color: null,
|
color: null,
|
||||||
condition: (value) => value,
|
condition: (value) => value,
|
||||||
|
@ -421,7 +419,7 @@ function handleLocation(data, location) {
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
url="Clients/extendedListFilter"
|
url="Clients/filter"
|
||||||
:create="{
|
:create="{
|
||||||
urlCreate: 'Clients/createWithUser',
|
urlCreate: 'Clients/createWithUser',
|
||||||
title: t('globals.pageTitles.customerCreate'),
|
title: t('globals.pageTitles.customerCreate'),
|
||||||
|
|
|
@ -9,7 +9,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
|
||||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import CustomerDefaulterAddObservation from './CustomerDefaulterAddObservation.vue';
|
import CustomerDefaulterAddObservation from './CustomerDefaulterAddObservation.vue';
|
||||||
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,6 @@ customer:
|
||||||
defaulterSinced: Defaulted Since
|
defaulterSinced: Defaulted Since
|
||||||
hasRecovery: Has Recovery
|
hasRecovery: Has Recovery
|
||||||
socialName: Social name
|
socialName: Social name
|
||||||
typeId: Type
|
|
||||||
buyerId: Buyer
|
|
||||||
categoryId: Category
|
|
||||||
city: City
|
city: City
|
||||||
phone: Phone
|
phone: Phone
|
||||||
postcode: Postcode
|
postcode: Postcode
|
||||||
|
|
|
@ -108,9 +108,6 @@ customer:
|
||||||
hasRecovery: Tiene recobro
|
hasRecovery: Tiene recobro
|
||||||
socialName: Razón social
|
socialName: Razón social
|
||||||
campaign: Campaña
|
campaign: Campaña
|
||||||
typeId: Familia
|
|
||||||
buyerId: Comprador
|
|
||||||
categoryId: Reino
|
|
||||||
city: Ciudad
|
city: Ciudad
|
||||||
phone: Teléfono
|
phone: Teléfono
|
||||||
postcode: Código postal
|
postcode: Código postal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||||
import DepartmentDescriptor from 'pages/Worker/Department/Card/DepartmentDescriptor.vue';
|
import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnCardBeta
|
<VnCardBeta
|
|
@ -42,6 +42,7 @@ const { openConfirmationModal } = useVnConfirm();
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="DepartmentDescriptorRef"
|
ref="DepartmentDescriptorRef"
|
||||||
|
module="Department"
|
||||||
:url="`Departments/${entityId}`"
|
:url="`Departments/${entityId}`"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
:to-module="{ name: 'WorkerDepartment' }"
|
:to-module="{ name: 'WorkerDepartment' }"
|
|
@ -1,32 +1,30 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useRole } from 'src/composables/useRole';
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
import { checkEntryLock } from 'src/composables/checkEntryLock';
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||||
|
import FilterTravelForm from 'src/components/FilterTravelForm.vue';
|
||||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
|
import { toDate } from 'src/filters';
|
||||||
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
|
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useRole();
|
||||||
const isAdministrative = () => hasAny(['administrative']);
|
const isAdministrative = () => hasAny(['administrative']);
|
||||||
const state = useState();
|
|
||||||
const user = state.getUser().fn();
|
|
||||||
|
|
||||||
const companiesOptions = ref([]);
|
const companiesOptions = ref([]);
|
||||||
const currenciesOptions = ref([]);
|
const currenciesOptions = ref([]);
|
||||||
|
|
||||||
onMounted(() => {
|
const onFilterTravelSelected = (formData, id) => {
|
||||||
checkEntryLock(route.params.id, user.id);
|
formData.travelFk = id;
|
||||||
});
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -54,24 +52,46 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelectTravelExtended
|
|
||||||
:data="data"
|
|
||||||
v-model="data.travelFk"
|
|
||||||
:onFilterTravelSelected="(data, result) => (data.travelFk = result)"
|
|
||||||
/>
|
|
||||||
<VnSelectSupplier
|
<VnSelectSupplier
|
||||||
v-model="data.supplierFk"
|
v-model="data.supplierFk"
|
||||||
hide-selected
|
hide-selected
|
||||||
:required="true"
|
:required="true"
|
||||||
|
map-options
|
||||||
/>
|
/>
|
||||||
|
<VnSelectDialog
|
||||||
|
:label="t('entry.basicData.travel')"
|
||||||
|
v-model="data.travelFk"
|
||||||
|
url="Travels/filter"
|
||||||
|
:fields="['id', 'warehouseInName']"
|
||||||
|
option-value="id"
|
||||||
|
option-label="warehouseInName"
|
||||||
|
map-options
|
||||||
|
hide-selected
|
||||||
|
:required="true"
|
||||||
|
action-icon="filter_alt"
|
||||||
|
>
|
||||||
|
<template #form>
|
||||||
|
<FilterTravelForm
|
||||||
|
@travel-selected="onFilterTravelSelected(data, $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt?.agencyModeName }} -
|
||||||
|
{{ scope.opt?.warehouseInName }}
|
||||||
|
({{ toDate(scope.opt?.shipped) }}) →
|
||||||
|
{{ scope.opt?.warehouseOutName }}
|
||||||
|
({{ toDate(scope.opt?.landed) }})
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelectDialog>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput v-model="data.reference" :label="t('globals.reference')" />
|
<VnInput v-model="data.reference" :label="t('globals.reference')" />
|
||||||
<VnInputNumber
|
|
||||||
v-model="data.invoiceAmount"
|
|
||||||
:label="t('entry.summary.invoiceAmount')"
|
|
||||||
:positive="false"
|
|
||||||
/>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
@ -93,7 +113,8 @@ onMounted(() => {
|
||||||
<VnInputNumber
|
<VnInputNumber
|
||||||
:label="t('entry.summary.commission')"
|
:label="t('entry.summary.commission')"
|
||||||
v-model="data.commission"
|
v-model="data.commission"
|
||||||
:step="1"
|
step="1"
|
||||||
|
autofocus
|
||||||
:positive="false"
|
:positive="false"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
@ -140,7 +161,7 @@ onMounted(() => {
|
||||||
:label="t('entry.summary.excludedFromAvailable')"
|
:label="t('entry.summary.excludedFromAvailable')"
|
||||||
/>
|
/>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:disable="!isAdministrative()"
|
v-if="isAdministrative()"
|
||||||
v-model="data.isBooked"
|
v-model="data.isBooked"
|
||||||
:label="t('entry.basicData.booked')"
|
:label="t('entry.basicData.booked')"
|
||||||
/>
|
/>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toDate } from 'src/filters';
|
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
|
||||||
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 TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
import { toDate } from 'src/filters';
|
||||||
import axios from 'axios';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
|
||||||
const quasar = useQuasar();
|
|
||||||
const { push } = useRouter();
|
|
||||||
const { openReport } = usePrintService();
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -90,63 +83,12 @@ const getEntryRedirectionFilter = (entry) => {
|
||||||
to,
|
to,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function showEntryReport() {
|
|
||||||
openReport(`Entries/${entityId.value}/entry-order-pdf`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showNotification(type, message) {
|
|
||||||
quasar.notify({
|
|
||||||
type: type,
|
|
||||||
message: t(message),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function recalculateRates(entity) {
|
|
||||||
try {
|
|
||||||
const entryConfig = await axios.get('EntryConfigs/findOne');
|
|
||||||
if (entryConfig.data?.inventorySupplierFk === entity.supplierFk) {
|
|
||||||
showNotification(
|
|
||||||
'negative',
|
|
||||||
'Cannot recalculate prices because this is an inventory entry',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);
|
|
||||||
showNotification('positive', 'Entry prices recalculated');
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('negative', 'Failed to recalculate rates');
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function cloneEntry() {
|
|
||||||
try {
|
|
||||||
const response = await axios.post(`Entries/${entityId.value}/cloneEntry`);
|
|
||||||
push({ path: `/entry/${response.data}` });
|
|
||||||
showNotification('positive', 'Entry cloned');
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('negative', 'Failed to clone entry');
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteEntry() {
|
|
||||||
try {
|
|
||||||
await axios.post(`Entries/${entityId.value}/deleteEntry`);
|
|
||||||
push({ path: `/entry/list` });
|
|
||||||
showNotification('positive', 'Entry deleted');
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('negative', 'Failed to delete entry');
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="entryDescriptorRef"
|
ref="entryDescriptorRef"
|
||||||
|
module="Entry"
|
||||||
:url="`Entries/${entityId}`"
|
:url="`Entries/${entityId}`"
|
||||||
:userFilter="entryFilter"
|
:userFilter="entryFilter"
|
||||||
title="supplier.nickname"
|
title="supplier.nickname"
|
||||||
|
@ -154,56 +96,15 @@ async function deleteEntry() {
|
||||||
width="lg-width"
|
width="lg-width"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<QItem
|
<EntryDescriptorMenu :id="entity.id" />
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="showEntryReport(entity)"
|
|
||||||
data-cy="show-entry-report"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Show entry report') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="recalculateRates(entity)"
|
|
||||||
data-cy="recalculate-rates"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Recalculate rates') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry">
|
|
||||||
<QItemSection>{{ t('Clone') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry">
|
|
||||||
<QItemSection>{{ t('Delete') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('Travel')">
|
<VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
|
||||||
<template #value>
|
<VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
|
||||||
<span class="link" v-if="entity?.travelFk">
|
<VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
|
||||||
{{ entity.travel?.agency?.name }}
|
|
||||||
{{ entity.travel?.warehouseOut?.code }} →
|
|
||||||
{{ entity.travel?.warehouseIn?.code }}
|
|
||||||
<TravelDescriptorProxy :id="entity?.travelFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</VnLv>
|
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('entry.summary.travelShipped')"
|
:label="t('globals.warehouseOut')"
|
||||||
:value="toDate(entity.travel?.shipped)"
|
:value="entity.travel?.warehouseOut?.name"
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('entry.summary.travelLanded')"
|
|
||||||
:value="toDate(entity.travel?.landed)"
|
|
||||||
/>
|
|
||||||
<VnLv :label="t('entry.summary.currency')" :value="entity?.currency?.code" />
|
|
||||||
<VnLv
|
|
||||||
:label="t('entry.summary.invoiceAmount')"
|
|
||||||
:value="entity?.invoiceAmount"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('entry.summary.entryType')"
|
|
||||||
:value="entity?.entryType?.description"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #icons="{ entity }">
|
<template #icons="{ entity }">
|
||||||
|
@ -230,14 +131,6 @@ async function deleteEntry() {
|
||||||
}}</QTooltip
|
}}</QTooltip
|
||||||
>
|
>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
|
||||||
v-if="!entity?.travelFk"
|
|
||||||
name="vn:deletedTicket"
|
|
||||||
size="xs"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<QTooltip>{{ t('This entry is deleted') }}</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{ entity }">
|
<template #actions="{ entity }">
|
||||||
|
@ -250,6 +143,21 @@ async function deleteEntry() {
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('Supplier card') }}</QTooltip>
|
<QTooltip>{{ t('Supplier card') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
|
<QBtn
|
||||||
|
:to="{
|
||||||
|
name: 'TravelMain',
|
||||||
|
query: {
|
||||||
|
params: JSON.stringify({
|
||||||
|
agencyModeFk: entity.travel?.agencyModeFk,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
size="md"
|
||||||
|
icon="local_airport"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('All travels with current agency') }}</QTooltip>
|
||||||
|
</QBtn>
|
||||||
<QBtn
|
<QBtn
|
||||||
:to="{
|
:to="{
|
||||||
name: 'EntryMain',
|
name: 'EntryMain',
|
||||||
|
@ -269,24 +177,10 @@ async function deleteEntry() {
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Travel: Envío
|
|
||||||
Supplier card: Ficha del proveedor
|
Supplier card: Ficha del proveedor
|
||||||
All travels with current agency: Todos los envíos con la agencia actual
|
All travels with current agency: Todos los envíos con la agencia actual
|
||||||
All entries with current supplier: Todas las entradas con el proveedor actual
|
All entries with current supplier: Todas las entradas con el proveedor actual
|
||||||
Show entry report: Ver informe del pedido
|
Show entry report: Ver informe del pedido
|
||||||
Inventory entry: Es inventario
|
Inventory entry: Es inventario
|
||||||
Virtual entry: Es una redada
|
Virtual entry: Es una redada
|
||||||
shipped: Enviado
|
|
||||||
landed: Recibido
|
|
||||||
This entry is deleted: Esta entrada está eliminada
|
|
||||||
Cannot recalculate prices because this is an inventory entry: No se pueden recalcular los precios porque es una entrada de inventario
|
|
||||||
Entry deleted: Entrada eliminada
|
|
||||||
Entry cloned: Entrada clonada
|
|
||||||
Entry prices recalculated: Precios de la entrada recalculados
|
|
||||||
Failed to recalculate rates: No se pudieron recalcular las tarifas
|
|
||||||
Failed to clone entry: No se pudo clonar la entrada
|
|
||||||
Failed to delete entry: No se pudo eliminar la entrada
|
|
||||||
Recalculate rates: Recalcular tarifas
|
|
||||||
Clone: Clonar
|
|
||||||
Delete: Eliminar
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -54,8 +54,8 @@ const transferEntry = async () => {
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
transferEntryDialog: The entries will be transferred to the next day
|
transferEntryDialog: The entries will be transferred to the next day
|
||||||
transferEntry: Partial delay
|
transferEntry: Transfer Entry
|
||||||
es:
|
es:
|
||||||
transferEntryDialog: Se van a transferir las compras al dia siguiente
|
transferEntryDialog: Se van a transferir las compras al dia siguiente
|
||||||
transferEntry: Retraso parcial
|
transferEntry: Transferir Entrada
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -9,7 +9,6 @@ export default {
|
||||||
'shipped',
|
'shipped',
|
||||||
'agencyModeFk',
|
'agencyModeFk',
|
||||||
'warehouseOutFk',
|
'warehouseOutFk',
|
||||||
'warehouseInFk',
|
|
||||||
'daysInForward',
|
'daysInForward',
|
||||||
],
|
],
|
||||||
include: [
|
include: [
|
||||||
|
@ -22,13 +21,13 @@ export default {
|
||||||
{
|
{
|
||||||
relation: 'warehouseOut',
|
relation: 'warehouseOut',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['name', 'code'],
|
fields: ['name'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
relation: 'warehouseIn',
|
relation: 'warehouseIn',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['name', 'code'],
|
fields: ['name'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -40,17 +39,5 @@ export default {
|
||||||
fields: ['id', 'nickname'],
|
fields: ['id', 'nickname'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
relation: 'currency',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'code'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'entryType',
|
|
||||||
scope: {
|
|
||||||
fields: ['code', 'description'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,17 +2,19 @@
|
||||||
import { onMounted, ref, computed } from 'vue';
|
import { onMounted, ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toDate } from 'src/filters';
|
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import CardSummary from 'components/ui/CardSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
||||||
import EntryBuys from './EntryBuys.vue';
|
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import { toDate, toCurrency, toCelsius } from 'src/filters';
|
||||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
import axios from 'axios';
|
||||||
|
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||||
|
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
|
||||||
|
import VnRow from 'src/components/ui/VnRow.vue';
|
||||||
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -31,6 +33,117 @@ const entry = ref();
|
||||||
const entryBuys = ref([]);
|
const entryBuys = ref([]);
|
||||||
const entryUrl = ref();
|
const entryUrl = ref();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
entryUrl.value = (await getUrl('entry/')) + entityId.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableColumnComponents = {
|
||||||
|
quantity: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
},
|
||||||
|
stickers: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
packagingFk: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
weight: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
packing: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
grouping: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
buyingValue: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
pvp: {
|
||||||
|
component: () => 'span',
|
||||||
|
props: () => {},
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const entriesTableColumns = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: t('globals.quantity'),
|
||||||
|
field: 'quantity',
|
||||||
|
name: 'quantity',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.stickers'),
|
||||||
|
field: 'stickers',
|
||||||
|
name: 'stickers',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.package'),
|
||||||
|
field: 'packagingFk',
|
||||||
|
name: 'packagingFk',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('globals.weight'),
|
||||||
|
field: 'weight',
|
||||||
|
name: 'weight',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.packing'),
|
||||||
|
field: 'packing',
|
||||||
|
name: 'packing',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.grouping'),
|
||||||
|
field: 'grouping',
|
||||||
|
name: 'grouping',
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.buyingValue'),
|
||||||
|
field: 'buyingValue',
|
||||||
|
name: 'buyingValue',
|
||||||
|
align: 'left',
|
||||||
|
format: (value) => toCurrency(value),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.import'),
|
||||||
|
name: 'amount',
|
||||||
|
align: 'left',
|
||||||
|
format: (_, row) => toCurrency(row.buyingValue * row.quantity),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.summary.pvp'),
|
||||||
|
name: 'pvp',
|
||||||
|
align: 'left',
|
||||||
|
format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
async function setEntryData(data) {
|
async function setEntryData(data) {
|
||||||
if (data) entry.value = data;
|
if (data) entry.value = data;
|
||||||
await fetchEntryBuys();
|
await fetchEntryBuys();
|
||||||
|
@ -40,18 +153,14 @@ const fetchEntryBuys = async () => {
|
||||||
const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
|
const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
|
||||||
if (data) entryBuys.value = data;
|
if (data) entryBuys.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
entryUrl.value = (await getUrl('entry/')) + entityId.value;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardSummary
|
<CardSummary
|
||||||
ref="summaryRef"
|
ref="summaryRef"
|
||||||
:url="`Entries/${entityId}/getEntry`"
|
:url="`Entries/${entityId}/getEntry`"
|
||||||
@on-fetch="(data) => setEntryData(data)"
|
@on-fetch="(data) => setEntryData(data)"
|
||||||
data-key="EntrySummary"
|
data-key="EntrySummary"
|
||||||
data-cy="entry-summary"
|
|
||||||
>
|
>
|
||||||
<template #header-left>
|
<template #header-left>
|
||||||
<VnToSummary
|
<VnToSummary
|
||||||
|
@ -64,67 +173,40 @@ onMounted(async () => {
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
|
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<EntryDescriptorMenu :id="entity.id" />
|
||||||
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="`#/entry/${entityId}/basic-data`"
|
:url="`#/entry/${entityId}/basic-data`"
|
||||||
:text="t('globals.summary.basicData')"
|
:text="t('globals.summary.basicData')"
|
||||||
/>
|
/>
|
||||||
<div class="card-group">
|
<VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
|
||||||
<div class="card-content">
|
|
||||||
<VnLv
|
|
||||||
:label="t('entry.summary.commission')"
|
|
||||||
:value="entry?.commission"
|
|
||||||
/>
|
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('entry.summary.currency')"
|
:label="t('entry.summary.currency')"
|
||||||
:value="entry?.currency?.name"
|
:value="entry.currency?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv :label="t('globals.company')" :value="entry.company.code" />
|
||||||
:label="t('globals.company')"
|
<VnLv :label="t('globals.reference')" :value="entry.reference" />
|
||||||
:value="entry?.company?.code"
|
|
||||||
/>
|
|
||||||
<VnLv :label="t('globals.reference')" :value="entry?.reference" />
|
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('entry.summary.invoiceNumber')"
|
:label="t('entry.summary.invoiceNumber')"
|
||||||
:value="entry?.invoiceNumber"
|
:value="entry.invoiceNumber"
|
||||||
/>
|
/>
|
||||||
</div>
|
<VnLv
|
||||||
<div class="card-content">
|
:label="t('entry.basicData.initialTemperature')"
|
||||||
<VnCheckbox
|
:value="toCelsius(entry.initialTemperature)"
|
||||||
:label="t('entry.summary.ordered')"
|
|
||||||
v-model="entry.isOrdered"
|
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
/>
|
||||||
<VnCheckbox
|
<VnLv
|
||||||
:label="t('globals.confirmed')"
|
:label="t('entry.basicData.finalTemperature')"
|
||||||
v-model="entry.isConfirmed"
|
:value="toCelsius(entry.finalTemperature)"
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
/>
|
||||||
<VnCheckbox
|
|
||||||
:label="t('entry.summary.booked')"
|
|
||||||
v-model="entry.isBooked"
|
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
|
||||||
<VnCheckbox
|
|
||||||
:label="t('entry.summary.excludedFromAvailable')"
|
|
||||||
v-model="entry.isExcludedFromAvailable"
|
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one" v-if="entry?.travelFk">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="`#/travel/${entry.travel.id}/summary`"
|
:url="`#/entry/${entityId}/basic-data`"
|
||||||
:text="t('Travel')"
|
:text="t('globals.summary.basicData')"
|
||||||
/>
|
/>
|
||||||
<div class="card-group">
|
|
||||||
<div class="card-content">
|
|
||||||
<VnLv :label="t('entry.summary.travelReference')">
|
<VnLv :label="t('entry.summary.travelReference')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">
|
<span class="link">
|
||||||
|
@ -138,7 +220,7 @@ onMounted(async () => {
|
||||||
:value="entry.travel.agency?.name"
|
:value="entry.travel.agency?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('entry.summary.travelShipped')"
|
:label="t('globals.shipped')"
|
||||||
:value="toDate(entry.travel.shipped)"
|
:value="toDate(entry.travel.shipped)"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
|
@ -146,72 +228,104 @@ onMounted(async () => {
|
||||||
:value="entry.travel.warehouseOut?.name"
|
:value="entry.travel.warehouseOut?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('entry.summary.travelLanded')"
|
:label="t('entry.summary.travelDelivered')"
|
||||||
:value="toDate(entry.travel.landed)"
|
:value="entry.travel.isDelivered"
|
||||||
/>
|
/>
|
||||||
|
<VnLv :label="t('globals.landed')" :value="toDate(entry.travel.landed)" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('globals.warehouseIn')"
|
:label="t('globals.warehouseIn')"
|
||||||
:value="entry.travel.warehouseIn?.name"
|
:value="entry.travel.warehouseIn?.name"
|
||||||
/>
|
/>
|
||||||
</div>
|
<VnLv
|
||||||
<div class="card-content">
|
|
||||||
<VnCheckbox
|
|
||||||
:label="t('entry.summary.travelDelivered')"
|
|
||||||
v-model="entry.travel.isDelivered"
|
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
|
||||||
<VnCheckbox
|
|
||||||
:label="t('entry.summary.travelReceived')"
|
:label="t('entry.summary.travelReceived')"
|
||||||
v-model="entry.travel.isReceived"
|
:value="entry.travel.isReceived"
|
||||||
:disable="true"
|
|
||||||
size="xs"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</QCard>
|
||||||
</div>
|
<QCard class="vn-one">
|
||||||
|
<VnTitle :url="`#/travel/${entityId}/summary`" :text="t('Travel data')" />
|
||||||
|
<VnRow class="block">
|
||||||
|
<VnLv :label="t('entry.summary.ordered')" :value="entry.isOrdered" />
|
||||||
|
<VnLv :label="t('globals.confirmed')" :value="entry.isConfirmed" />
|
||||||
|
<VnLv :label="t('entry.summary.booked')" :value="entry.isBooked" />
|
||||||
|
<VnLv
|
||||||
|
:label="t('entry.summary.excludedFromAvailable')"
|
||||||
|
:value="entry.isExcludedFromAvailable"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-max">
|
<QCard class="vn-max">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="`#/entry/${entityId}/buys`"
|
:url="`#/entry/${entityId}/buys`"
|
||||||
:text="t('entry.summary.buys')"
|
:text="t('entry.summary.buys')"
|
||||||
/>
|
/>
|
||||||
<EntryBuys
|
<QTable
|
||||||
v-if="entityId"
|
:rows="entryBuys"
|
||||||
:id="Number(entityId)"
|
:columns="entriesTableColumns"
|
||||||
:editable-mode="false"
|
row-key="index"
|
||||||
table-height="49vh"
|
class="full-width q-mt-md"
|
||||||
/>
|
:no-data-label="t('globals.noResults')"
|
||||||
|
>
|
||||||
|
<template #body="{ cols, row, rowIndex }">
|
||||||
|
<QTr no-hover>
|
||||||
|
<QTd v-for="col in cols" :key="col?.name">
|
||||||
|
<component
|
||||||
|
:is="tableColumnComponents[col?.name].component()"
|
||||||
|
v-bind="tableColumnComponents[col?.name].props()"
|
||||||
|
@click="tableColumnComponents[col?.name].event()"
|
||||||
|
class="col-content"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-if="
|
||||||
|
col?.name !== 'observation' &&
|
||||||
|
col?.name !== 'isConfirmed'
|
||||||
|
"
|
||||||
|
>{{ col.value }}</template
|
||||||
|
>
|
||||||
|
<QTooltip v-if="col.toolTip">{{
|
||||||
|
col.toolTip
|
||||||
|
}}</QTooltip>
|
||||||
|
</component>
|
||||||
|
</QTd>
|
||||||
|
</QTr>
|
||||||
|
<QTr no-hover>
|
||||||
|
<QTd>
|
||||||
|
<span>{{ row.item.itemType.code }}</span>
|
||||||
|
</QTd>
|
||||||
|
<QTd>
|
||||||
|
<span>{{ row.item.id }}</span>
|
||||||
|
</QTd>
|
||||||
|
<QTd>
|
||||||
|
<span>{{ row.item.size }}</span>
|
||||||
|
</QTd>
|
||||||
|
<QTd>
|
||||||
|
<span>{{ toCurrency(row.item.minPrice) }}</span>
|
||||||
|
</QTd>
|
||||||
|
<QTd colspan="6">
|
||||||
|
<span>{{ row.item.concept }}</span>
|
||||||
|
<span v-if="row.item.subName" class="subName">
|
||||||
|
{{ row.item.subName }}
|
||||||
|
</span>
|
||||||
|
<FetchedTags :item="row.item" />
|
||||||
|
</QTd>
|
||||||
|
</QTr>
|
||||||
|
<!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
|
||||||
|
<QTr v-if="rowIndex !== entryBuys.length - 1">
|
||||||
|
<QTd colspan="10" class="vn-table-separation-row" />
|
||||||
|
</QTr>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
</QCard>
|
</QCard>
|
||||||
</template>
|
</template>
|
||||||
</CardSummary>
|
</CardSummary>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.card-group {
|
.separation-row {
|
||||||
display: flex;
|
background-color: var(--vn-section-color) !important;
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
> div {
|
|
||||||
max-height: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1010px) {
|
|
||||||
.card-group {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
.card-content {
|
|
||||||
flex: 1;
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Travel: Envío
|
Travel data: Datos envío
|
||||||
InvoiceIn data: Datos factura
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -19,7 +19,6 @@ const props = defineProps({
|
||||||
|
|
||||||
const currenciesOptions = ref([]);
|
const currenciesOptions = ref([]);
|
||||||
const companiesOptions = ref([]);
|
const companiesOptions = ref([]);
|
||||||
const entryFilterPanel = ref();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -39,7 +38,7 @@ const entryFilterPanel = ref();
|
||||||
@on-fetch="(data) => (currenciesOptions = data)"
|
@on-fetch="(data) => (currenciesOptions = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<VnFilterPanel ref="entryFilterPanel" :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(`entryFilter.params.${tag.label}`) }}: </strong>
|
<strong>{{ t(`entryFilter.params.${tag.label}`) }}: </strong>
|
||||||
|
@ -49,65 +48,70 @@ const entryFilterPanel = ref();
|
||||||
<template #body="{ params, searchFn }">
|
<template #body="{ params, searchFn }">
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<VnInput
|
||||||
:label="t('params.isExcludedFromAvailable')"
|
v-model="params.search"
|
||||||
v-model="params.isExcludedFromAvailable"
|
:label="t('entryFilter.params.search')"
|
||||||
toggle-indeterminate
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('params.isExcludedFromAvailable') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QCheckbox>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('params.isOrdered')"
|
|
||||||
v-model="params.isOrdered"
|
|
||||||
toggle-indeterminate
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('entry.list.tableVisibleColumns.isOrdered') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QCheckbox>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('params.isReceived')"
|
|
||||||
v-model="params.isReceived"
|
|
||||||
toggle-indeterminate
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('entry.list.tableVisibleColumns.isReceived') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QCheckbox>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('entry.list.tableVisibleColumns.isConfirmed')"
|
|
||||||
v-model="params.isConfirmed"
|
|
||||||
toggle-indeterminate
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('entry.list.tableVisibleColumns.isConfirmed') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QCheckbox>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInputDate
|
|
||||||
:label="t('params.landed')"
|
|
||||||
v-model="params.landed"
|
|
||||||
@update:model-value="searchFn()"
|
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput v-model="params.id" label="Id" is-outlined />
|
<VnInput
|
||||||
|
v-model="params.reference"
|
||||||
|
:label="t('entryFilter.params.reference')"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.invoiceNumber"
|
||||||
|
:label="t('entryFilter.params.invoiceNumber')"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnInput
|
||||||
|
v-model="params.travelFk"
|
||||||
|
:label="t('entryFilter.params.travelFk')"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('entryFilter.params.companyFk')"
|
||||||
|
v-model="params.companyFk"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
:options="companiesOptions"
|
||||||
|
option-value="id"
|
||||||
|
option-label="code"
|
||||||
|
hide-selected
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('entryFilter.params.currencyFk')"
|
||||||
|
v-model="params.currencyFk"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
:options="currenciesOptions"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
hide-selected
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
|
@ -121,165 +125,62 @@ const entryFilterPanel = ref();
|
||||||
rounded
|
rounded
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
|
||||||
v-model="params.invoiceNumber"
|
|
||||||
:label="t('params.invoiceNumber')"
|
|
||||||
is-outlined
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInputDate
|
||||||
v-model="params.reference"
|
:label="t('entryFilter.params.created')"
|
||||||
:label="t('entry.list.tableVisibleColumns.reference')"
|
v-model="params.created"
|
||||||
is-outlined
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnSelect
|
|
||||||
:label="t('params.agencyModeId')"
|
|
||||||
v-model="params.agencyModeId"
|
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
url="AgencyModes"
|
|
||||||
:fields="['id', 'name']"
|
|
||||||
hide-selected
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
|
||||||
v-model="params.evaNotes"
|
|
||||||
:label="t('params.evaNotes')"
|
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnInputDate
|
||||||
:label="t('params.warehouseOutFk')"
|
:label="t('entryFilter.params.from')"
|
||||||
v-model="params.warehouseOutFk"
|
v-model="params.from"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
url="Warehouses"
|
|
||||||
:fields="['id', 'name']"
|
|
||||||
hide-selected
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnSelect
|
|
||||||
:label="t('params.warehouseInFk')"
|
|
||||||
v-model="params.warehouseInFk"
|
|
||||||
@update:model-value="searchFn()"
|
|
||||||
url="Warehouses"
|
|
||||||
:fields="['id', 'name']"
|
|
||||||
hide-selected
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>
|
|
||||||
{{ scope.opt?.name }}
|
|
||||||
</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ `#${scope.opt?.id} , ${scope.opt?.nickname}` }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
|
||||||
v-model="params.invoiceNumber"
|
|
||||||
:label="t('params.invoiceNumber')"
|
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnInputDate
|
||||||
:label="t('params.entryTypeCode')"
|
:label="t('entryFilter.params.to')"
|
||||||
v-model="params.entryTypeCode"
|
v-model="params.to"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
url="EntryTypes"
|
is-outlined
|
||||||
:fields="['code', 'description']"
|
|
||||||
option-value="code"
|
|
||||||
option-label="description"
|
|
||||||
hide-selected
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<QCheckbox
|
||||||
v-model="params.evaNotes"
|
:label="t('entryFilter.params.isBooked')"
|
||||||
:label="t('params.evaNotes')"
|
v-model="params.isBooked"
|
||||||
is-outlined
|
toggle-indeterminate
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection>
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('entryFilter.params.isConfirmed')"
|
||||||
|
v-model="params.isConfirmed"
|
||||||
|
toggle-indeterminate
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('entryFilter.params.isOrdered')"
|
||||||
|
v-model="params.isOrdered"
|
||||||
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
en:
|
|
||||||
params:
|
|
||||||
isExcludedFromAvailable: Inventory
|
|
||||||
isOrdered: Ordered
|
|
||||||
isReceived: Received
|
|
||||||
isConfirmed: Confirmed
|
|
||||||
isRaid: Raid
|
|
||||||
landed: Date
|
|
||||||
id: Id
|
|
||||||
supplierFk: Supplier
|
|
||||||
invoiceNumber: Invoice number
|
|
||||||
reference: Ref/Alb/Guide
|
|
||||||
agencyModeId: Agency mode
|
|
||||||
evaNotes: Notes
|
|
||||||
warehouseOutFk: Origin
|
|
||||||
warehouseInFk: Destiny
|
|
||||||
entryTypeCode: Entry type
|
|
||||||
hasToShowDeletedEntries: Show deleted entries
|
|
||||||
es:
|
|
||||||
params:
|
|
||||||
isExcludedFromAvailable: Inventario
|
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Confirmado
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Raid
|
|
||||||
landed: Fecha
|
|
||||||
id: Id
|
|
||||||
supplierFk: Proveedor
|
|
||||||
invoiceNumber: Núm. factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
agencyModeId: Modo agencia
|
|
||||||
evaNotes: Notas
|
|
||||||
warehouseOutFk: Origen
|
|
||||||
warehouseInFk: Destino
|
|
||||||
entryTypeCode: Tipo de entrada
|
|
||||||
hasToShowDeletedEntries: Mostrar entradas eliminadas
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
|
||||||
import VnSection from 'src/components/common/VnSection.vue';
|
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
import { onBeforeMount } from 'vue';
|
|
||||||
|
|
||||||
import EntryFilter from './EntryFilter.vue';
|
import EntryFilter from './EntryFilter.vue';
|
||||||
import VnTable from 'components/VnTable/VnTable.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
|
import { toCelsius, toDate } from 'src/filters';
|
||||||
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
|
import EntrySummary from './Card/EntrySummary.vue';
|
||||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
|
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
||||||
import { toDate } from 'src/filters';
|
import VnSection from 'src/components/common/VnSection.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const defaultEntry = ref({});
|
|
||||||
const state = useState();
|
|
||||||
const user = state.getUser();
|
|
||||||
const dataKey = 'EntryList';
|
const dataKey = 'EntryList';
|
||||||
|
|
||||||
const entryQueryFilter = {
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
const entryFilter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
relation: 'suppliers',
|
relation: 'suppliers',
|
||||||
|
@ -44,53 +40,44 @@ const entryQueryFilter = {
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
label: 'Ex',
|
name: 'status',
|
||||||
toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
|
columnFilter: false,
|
||||||
name: 'isExcludedFromAvailable',
|
|
||||||
component: 'checkbox',
|
|
||||||
width: '35px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Pe',
|
|
||||||
toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
|
|
||||||
name: 'isOrdered',
|
|
||||||
component: 'checkbox',
|
|
||||||
width: '35px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Le',
|
|
||||||
toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
|
|
||||||
name: 'isConfirmed',
|
|
||||||
component: 'checkbox',
|
|
||||||
width: '35px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Re',
|
|
||||||
toolTip: t('entry.list.tableVisibleColumns.isReceived'),
|
|
||||||
name: 'isReceived',
|
|
||||||
component: 'checkbox',
|
|
||||||
width: '35px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('entry.list.tableVisibleColumns.landed'),
|
|
||||||
name: 'landed',
|
|
||||||
component: 'date',
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
|
|
||||||
width: '105px',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
align: 'left',
|
||||||
label: t('globals.id'),
|
label: t('globals.id'),
|
||||||
name: 'id',
|
name: 'id',
|
||||||
isId: true,
|
isId: true,
|
||||||
component: 'number',
|
|
||||||
chip: {
|
chip: {
|
||||||
condition: () => true,
|
condition: () => true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('globals.reference'),
|
||||||
|
name: 'reference',
|
||||||
|
isTitle: true,
|
||||||
|
component: 'input',
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
create: true,
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('entry.list.tableVisibleColumns.created'),
|
||||||
|
name: 'created',
|
||||||
|
create: true,
|
||||||
|
cardVisible: true,
|
||||||
|
component: 'date',
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.created)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
label: t('entry.list.tableVisibleColumns.supplierFk'),
|
label: t('entry.list.tableVisibleColumns.supplierFk'),
|
||||||
name: 'supplierFk',
|
name: 'supplierFk',
|
||||||
create: true,
|
create: true,
|
||||||
|
@ -100,205 +87,164 @@ const columns = computed(() => [
|
||||||
url: 'suppliers',
|
url: 'suppliers',
|
||||||
fields: ['id', 'name'],
|
fields: ['id', 'name'],
|
||||||
},
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
|
format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('entry.list.tableVisibleColumns.invoiceNumber'),
|
label: t('entry.list.tableVisibleColumns.isBooked'),
|
||||||
name: 'invoiceNumber',
|
name: 'isBooked',
|
||||||
component: 'input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.reference'),
|
|
||||||
name: 'reference',
|
|
||||||
isTitle: true,
|
|
||||||
component: 'input',
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: 'AWB',
|
|
||||||
name: 'awbCode',
|
|
||||||
component: 'input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.agencyModeId'),
|
|
||||||
name: 'agencyModeId',
|
|
||||||
cardVisible: true,
|
|
||||||
component: 'select',
|
|
||||||
attrs: {
|
|
||||||
url: 'agencyModes',
|
|
||||||
fields: ['id', 'name'],
|
|
||||||
},
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(row.agencyModeName),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.evaNotes'),
|
|
||||||
name: 'evaNotes',
|
|
||||||
component: 'input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.warehouseOutFk'),
|
|
||||||
name: 'warehouseOutFk',
|
|
||||||
cardVisible: true,
|
|
||||||
component: 'select',
|
|
||||||
attrs: {
|
|
||||||
url: 'warehouses',
|
|
||||||
fields: ['id', 'name'],
|
|
||||||
},
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseOutName),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.warehouseInFk'),
|
|
||||||
name: 'warehouseInFk',
|
|
||||||
cardVisible: true,
|
|
||||||
component: 'select',
|
|
||||||
attrs: {
|
|
||||||
url: 'warehouses',
|
|
||||||
fields: ['id', 'name'],
|
|
||||||
},
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseInName),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
align: 'left',
|
|
||||||
label: t('entry.list.tableVisibleColumns.entryTypeDescription'),
|
|
||||||
name: 'entryTypeCode',
|
|
||||||
cardVisible: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'dated',
|
|
||||||
label: t('entry.list.tableVisibleColumns.dated'),
|
|
||||||
component: 'date',
|
|
||||||
cardVisible: false,
|
|
||||||
visible: false,
|
|
||||||
create: true,
|
create: true,
|
||||||
|
component: 'checkbox',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'companyFk',
|
align: 'left',
|
||||||
|
label: t('entry.list.tableVisibleColumns.isConfirmed'),
|
||||||
|
name: 'isConfirmed',
|
||||||
|
cardVisible: true,
|
||||||
|
create: true,
|
||||||
|
component: 'checkbox',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('entry.list.tableVisibleColumns.isOrdered'),
|
||||||
|
name: 'isOrdered',
|
||||||
|
cardVisible: true,
|
||||||
|
create: true,
|
||||||
|
component: 'checkbox',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
label: t('entry.list.tableVisibleColumns.companyFk'),
|
label: t('entry.list.tableVisibleColumns.companyFk'),
|
||||||
cardVisible: false,
|
name: 'companyFk',
|
||||||
visible: false,
|
|
||||||
create: true,
|
|
||||||
component: 'select',
|
component: 'select',
|
||||||
attrs: {
|
attrs: {
|
||||||
optionValue: 'id',
|
url: 'companies',
|
||||||
|
fields: ['id', 'code'],
|
||||||
optionLabel: 'code',
|
optionLabel: 'code',
|
||||||
url: 'Companies',
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
create: true,
|
||||||
|
|
||||||
|
format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('entry.list.tableVisibleColumns.travelFk'),
|
||||||
|
name: 'travelFk',
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'travels',
|
||||||
|
fields: ['id', 'ref'],
|
||||||
|
optionLabel: 'ref',
|
||||||
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
create: true,
|
||||||
|
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('entry.list.tableVisibleColumns.invoiceAmount'),
|
||||||
|
name: 'invoiceAmount',
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'initialTemperature',
|
||||||
|
label: t('entry.basicData.initialTemperature'),
|
||||||
|
field: 'initialTemperature',
|
||||||
|
format: (row) => toCelsius(row.initialTemperature),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'finalTemperature',
|
||||||
|
label: t('entry.basicData.finalTemperature'),
|
||||||
|
field: 'finalTemperature',
|
||||||
|
format: (row) => toCelsius(row.finalTemperature),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
|
||||||
|
name: 'isExcludedFromAvailable',
|
||||||
|
columnFilter: {
|
||||||
|
inWhere: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'travelFk',
|
align: 'right',
|
||||||
label: t('entry.list.tableVisibleColumns.travelFk'),
|
name: 'tableActions',
|
||||||
cardVisible: false,
|
actions: [
|
||||||
visible: false,
|
{
|
||||||
create: true,
|
title: t('components.smartCard.viewSummary'),
|
||||||
|
icon: 'preview',
|
||||||
|
action: (row) => viewSummary(row.id, EntrySummary),
|
||||||
|
isPrimary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
function getBadgeAttrs(row) {
|
|
||||||
const date = row.landed;
|
|
||||||
let today = Date.vnNew();
|
|
||||||
today.setHours(0, 0, 0, 0);
|
|
||||||
let timeTicket = new Date(date);
|
|
||||||
timeTicket.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
let timeDiff = today - timeTicket;
|
|
||||||
|
|
||||||
if (timeDiff > 0) return { color: 'warning', 'text-color': 'black' };
|
|
||||||
switch (row.entryTypeCode) {
|
|
||||||
case 'regularization':
|
|
||||||
case 'life':
|
|
||||||
case 'internal':
|
|
||||||
case 'inventory':
|
|
||||||
if (!row.isOrdered || !row.isConfirmed)
|
|
||||||
return { color: 'negative', 'text-color': 'black' };
|
|
||||||
break;
|
|
||||||
case 'product':
|
|
||||||
case 'packaging':
|
|
||||||
case 'devaluation':
|
|
||||||
case 'payment':
|
|
||||||
case 'transport':
|
|
||||||
if (
|
|
||||||
row.invoiceAmount === null ||
|
|
||||||
(row.invoiceNumber === null && row.reference === null) ||
|
|
||||||
!row.isOrdered ||
|
|
||||||
!row.isConfirmed
|
|
||||||
)
|
|
||||||
return { color: 'negative', 'text-color': 'black' };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timeDiff < 0) return { color: 'info', 'text-color': 'black' };
|
|
||||||
return { color: 'transparent' };
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
defaultEntry.value = (await axios.get('EntryConfigs/findOne')).data;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSection
|
<VnSection
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
|
:columns="columns"
|
||||||
prefix="entry"
|
prefix="entry"
|
||||||
url="Entries/filter"
|
url="Entries/filter"
|
||||||
:array-data-props="{
|
:array-data-props="{
|
||||||
url: 'Entries/filter',
|
url: 'Entries/filter',
|
||||||
order: 'landed DESC',
|
order: 'id DESC',
|
||||||
userFilter: EntryFilter,
|
userFilter: entryFilter,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #advanced-menu>
|
<template #advanced-menu>
|
||||||
<EntryFilter :data-key="dataKey" />
|
<EntryFilter data-key="EntryList" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<VnTable
|
<VnTable
|
||||||
v-if="defaultEntry.defaultSupplierFk"
|
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
url="Entries/filter"
|
|
||||||
:filter="entryQueryFilter"
|
|
||||||
order="landed DESC"
|
|
||||||
:create="{
|
:create="{
|
||||||
urlCreate: 'Entries',
|
urlCreate: 'Entries',
|
||||||
title: t('Create entry'),
|
title: t('entry.list.newEntry'),
|
||||||
onDataSaved: ({ id }) => tableRef.redirect(id),
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||||
formInitialData: {
|
formInitialData: {},
|
||||||
supplierFk: defaultEntry.defaultSupplierFk,
|
|
||||||
dated: Date.vnNew(),
|
|
||||||
companyFk: user?.companyFk,
|
|
||||||
},
|
|
||||||
}"
|
}"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
redirect="entry"
|
redirect="entry"
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
>
|
>
|
||||||
<template #column-landed="{ row }">
|
<template #column-status="{ row }">
|
||||||
<QBadge
|
<div class="row q-gutter-xs">
|
||||||
v-if="row?.travelFk"
|
<QIcon
|
||||||
v-bind="getBadgeAttrs(row)"
|
v-if="!!row.isExcludedFromAvailable"
|
||||||
class="q-pa-sm"
|
name="vn:inventory"
|
||||||
style="font-size: 14px"
|
color="primary"
|
||||||
>
|
>
|
||||||
{{ toDate(row.landed) }}
|
<QTooltip>{{
|
||||||
</QBadge>
|
t(
|
||||||
|
'entry.list.tableVisibleColumns.isExcludedFromAvailable',
|
||||||
|
)
|
||||||
|
}}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
<QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
|
||||||
|
<QTooltip>
|
||||||
|
{{
|
||||||
|
t('globals.raid', {
|
||||||
|
daysInForward: row.daysInForward,
|
||||||
|
})
|
||||||
|
}}</QTooltip
|
||||||
|
>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #column-supplierFk="{ row }">
|
<template #column-supplierFk="{ row }">
|
||||||
<span class="link" @click.stop>
|
<span class="link" @click.stop>
|
||||||
|
@ -306,26 +252,13 @@ onBeforeMount(async () => {
|
||||||
<SupplierDescriptorProxy :id="row.supplierFk" />
|
<SupplierDescriptorProxy :id="row.supplierFk" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #column-create-travelFk="{ data }">
|
<template #column-travelFk="{ row }">
|
||||||
<VnSelectTravelExtended
|
<span class="link" @click.stop>
|
||||||
:data="data"
|
{{ row.travelRef }}
|
||||||
v-model="data.travelFk"
|
<TravelDescriptorProxy :id="row.travelFk" />
|
||||||
:onFilterTravelSelected="
|
</span>
|
||||||
(data, result) => (data.travelFk = result)
|
|
||||||
"
|
|
||||||
data-cy="entry-travel-select"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
</VnSection>
|
</VnSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Inventory entry: Es inventario
|
|
||||||
Virtual entry: Es una redada
|
|
||||||
Search entries: Buscar entradas
|
|
||||||
You can search by entry reference: Puedes buscar por referencia de la entrada
|
|
||||||
Create entry: Crear entrada
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -1,36 +1,21 @@
|
||||||
entry:
|
entry:
|
||||||
lock:
|
|
||||||
title: Lock entry
|
|
||||||
message: This entry has been locked by {userName} for {time} minutes. Do you want to unlock it?
|
|
||||||
success: The entry has been locked successfully
|
|
||||||
list:
|
list:
|
||||||
newEntry: New entry
|
newEntry: New entry
|
||||||
tableVisibleColumns:
|
tableVisibleColumns:
|
||||||
isExcludedFromAvailable: Exclude from inventory
|
created: Creation
|
||||||
isOrdered: Ordered
|
|
||||||
isConfirmed: Ready to label
|
|
||||||
isReceived: Received
|
|
||||||
isRaid: Raid
|
|
||||||
landed: Date
|
|
||||||
supplierFk: Supplier
|
supplierFk: Supplier
|
||||||
reference: Ref/Alb/Guide
|
|
||||||
invoiceNumber: Invoice
|
|
||||||
agencyModeId: Agency
|
|
||||||
isBooked: Booked
|
isBooked: Booked
|
||||||
|
isConfirmed: Confirmed
|
||||||
|
isOrdered: Ordered
|
||||||
companyFk: Company
|
companyFk: Company
|
||||||
evaNotes: Notes
|
|
||||||
warehouseOutFk: Origin
|
|
||||||
warehouseInFk: Destiny
|
|
||||||
entryTypeDescription: Entry type
|
|
||||||
invoiceAmount: Import
|
|
||||||
travelFk: Travel
|
travelFk: Travel
|
||||||
dated: Dated
|
isExcludedFromAvailable: Inventory
|
||||||
|
invoiceAmount: Import
|
||||||
inventoryEntry: Inventory entry
|
inventoryEntry: Inventory entry
|
||||||
summary:
|
summary:
|
||||||
commission: Commission
|
commission: Commission
|
||||||
currency: Currency
|
currency: Currency
|
||||||
invoiceNumber: Invoice number
|
invoiceNumber: Invoice number
|
||||||
invoiceAmount: Invoice amount
|
|
||||||
ordered: Ordered
|
ordered: Ordered
|
||||||
booked: Booked
|
booked: Booked
|
||||||
excludedFromAvailable: Inventory
|
excludedFromAvailable: Inventory
|
||||||
|
@ -48,7 +33,6 @@ entry:
|
||||||
buyingValue: Buying value
|
buyingValue: Buying value
|
||||||
import: Import
|
import: Import
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
entryType: Entry type
|
|
||||||
basicData:
|
basicData:
|
||||||
travel: Travel
|
travel: Travel
|
||||||
currency: Currency
|
currency: Currency
|
||||||
|
@ -85,55 +69,17 @@ entry:
|
||||||
landing: Landing
|
landing: Landing
|
||||||
isExcludedFromAvailable: Es inventory
|
isExcludedFromAvailable: Es inventory
|
||||||
params:
|
params:
|
||||||
isExcludedFromAvailable: Exclude from inventory
|
toShipped: To
|
||||||
isOrdered: Ordered
|
fromShipped: From
|
||||||
isConfirmed: Ready to label
|
daysOnward: Days onward
|
||||||
isReceived: Received
|
daysAgo: Days ago
|
||||||
isIgnored: Ignored
|
warehouseInFk: Warehouse in
|
||||||
isRaid: Raid
|
|
||||||
landed: Date
|
|
||||||
supplierFk: Supplier
|
|
||||||
reference: Ref/Alb/Guide
|
|
||||||
invoiceNumber: Invoice
|
|
||||||
agencyModeId: Agency
|
|
||||||
isBooked: Booked
|
|
||||||
companyFk: Company
|
|
||||||
evaNotes: Notes
|
|
||||||
warehouseOutFk: Origin
|
|
||||||
warehouseInFk: Destiny
|
|
||||||
entryTypeDescription: Entry type
|
|
||||||
invoiceAmount: Import
|
|
||||||
travelFk: Travel
|
|
||||||
dated: Dated
|
|
||||||
itemFk: Item id
|
|
||||||
hex: Color
|
|
||||||
name: Item name
|
|
||||||
size: Size
|
|
||||||
stickers: Stickers
|
|
||||||
packagingFk: Packaging
|
|
||||||
weight: Kg
|
|
||||||
groupingMode: Grouping selector
|
|
||||||
grouping: Grouping
|
|
||||||
quantity: Quantity
|
|
||||||
buyingValue: Buying value
|
|
||||||
price2: Package
|
|
||||||
price3: Box
|
|
||||||
minPrice: Minumum price
|
|
||||||
hasMinPrice: Has minimum price
|
|
||||||
packingOut: Packing out
|
|
||||||
comment: Comment
|
|
||||||
subName: Supplier name
|
|
||||||
tags: Tags
|
|
||||||
company_name: Company name
|
|
||||||
itemTypeFk: Item type
|
|
||||||
workerFk: Worker id
|
|
||||||
search: Search entries
|
search: Search entries
|
||||||
searchInfo: You can search by entry reference
|
searchInfo: You can search by entry reference
|
||||||
descriptorMenu:
|
descriptorMenu:
|
||||||
showEntryReport: Show entry report
|
showEntryReport: Show entry report
|
||||||
entryFilter:
|
entryFilter:
|
||||||
params:
|
params:
|
||||||
isExcludedFromAvailable: Exclude from inventory
|
|
||||||
invoiceNumber: Invoice number
|
invoiceNumber: Invoice number
|
||||||
travelFk: Travel
|
travelFk: Travel
|
||||||
companyFk: Company
|
companyFk: Company
|
||||||
|
@ -145,16 +91,8 @@ entryFilter:
|
||||||
isBooked: Booked
|
isBooked: Booked
|
||||||
isConfirmed: Confirmed
|
isConfirmed: Confirmed
|
||||||
isOrdered: Ordered
|
isOrdered: Ordered
|
||||||
isReceived: Received
|
|
||||||
search: General search
|
search: General search
|
||||||
reference: Reference
|
reference: Reference
|
||||||
landed: Landed
|
|
||||||
id: Id
|
|
||||||
agencyModeId: Agency
|
|
||||||
evaNotes: Notes
|
|
||||||
warehouseOutFk: Origin
|
|
||||||
warehouseInFk: Destiny
|
|
||||||
entryTypeCode: Entry type
|
|
||||||
myEntries:
|
myEntries:
|
||||||
id: ID
|
id: ID
|
||||||
landed: Landed
|
landed: Landed
|
||||||
|
|
|
@ -1,36 +1,21 @@
|
||||||
entry:
|
entry:
|
||||||
lock:
|
|
||||||
title: Entrada bloqueada
|
|
||||||
message: Esta entrada ha sido bloqueada por {userName} hace {time} minutos. ¿Quieres desbloquearla?
|
|
||||||
success: La entrada ha sido bloqueada correctamente
|
|
||||||
list:
|
list:
|
||||||
newEntry: Nueva entrada
|
newEntry: Nueva entrada
|
||||||
tableVisibleColumns:
|
tableVisibleColumns:
|
||||||
isExcludedFromAvailable: Excluir del inventario
|
created: Creación
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Lista para etiquetar
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Redada
|
|
||||||
landed: Fecha
|
|
||||||
supplierFk: Proveedor
|
supplierFk: Proveedor
|
||||||
invoiceNumber: Nº Factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
agencyModeId: Agencia
|
|
||||||
isBooked: Asentado
|
isBooked: Asentado
|
||||||
|
isConfirmed: Confirmado
|
||||||
|
isOrdered: Pedida
|
||||||
companyFk: Empresa
|
companyFk: Empresa
|
||||||
travelFk: Envio
|
travelFk: Envio
|
||||||
evaNotes: Notas
|
isExcludedFromAvailable: Inventario
|
||||||
warehouseOutFk: Origen
|
|
||||||
warehouseInFk: Destino
|
|
||||||
entryTypeDescription: Tipo entrada
|
|
||||||
invoiceAmount: Importe
|
invoiceAmount: Importe
|
||||||
dated: Fecha
|
|
||||||
inventoryEntry: Es inventario
|
inventoryEntry: Es inventario
|
||||||
summary:
|
summary:
|
||||||
commission: Comisión
|
commission: Comisión
|
||||||
currency: Moneda
|
currency: Moneda
|
||||||
invoiceNumber: Núm. factura
|
invoiceNumber: Núm. factura
|
||||||
invoiceAmount: Importe
|
|
||||||
ordered: Pedida
|
ordered: Pedida
|
||||||
booked: Contabilizada
|
booked: Contabilizada
|
||||||
excludedFromAvailable: Inventario
|
excludedFromAvailable: Inventario
|
||||||
|
@ -49,13 +34,12 @@ entry:
|
||||||
buyingValue: Coste
|
buyingValue: Coste
|
||||||
import: Importe
|
import: Importe
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
entryType: Tipo entrada
|
|
||||||
basicData:
|
basicData:
|
||||||
travel: Envío
|
travel: Envío
|
||||||
currency: Moneda
|
currency: Moneda
|
||||||
observation: Observación
|
observation: Observación
|
||||||
commission: Comisión
|
commission: Comisión
|
||||||
booked: Contabilizada
|
booked: Asentado
|
||||||
excludedFromAvailable: Inventario
|
excludedFromAvailable: Inventario
|
||||||
initialTemperature: Ini °C
|
initialTemperature: Ini °C
|
||||||
finalTemperature: Fin °C
|
finalTemperature: Fin °C
|
||||||
|
@ -85,70 +69,31 @@ entry:
|
||||||
packingOut: Embalaje envíos
|
packingOut: Embalaje envíos
|
||||||
landing: Llegada
|
landing: Llegada
|
||||||
isExcludedFromAvailable: Es inventario
|
isExcludedFromAvailable: Es inventario
|
||||||
|
params:
|
||||||
|
toShipped: Hasta
|
||||||
|
fromShipped: Desde
|
||||||
|
warehouseInFk: Alm. entrada
|
||||||
|
daysOnward: Días adelante
|
||||||
|
daysAgo: Días atras
|
||||||
|
descriptorMenu:
|
||||||
|
showEntryReport: Ver informe del pedido
|
||||||
search: Buscar entradas
|
search: Buscar entradas
|
||||||
searchInfo: Puedes buscar por referencia de entrada
|
searchInfo: Puedes buscar por referencia de entrada
|
||||||
params:
|
|
||||||
isExcludedFromAvailable: Excluir del inventario
|
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Lista para etiquetar
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Redada
|
|
||||||
isIgnored: Ignorado
|
|
||||||
landed: Fecha
|
|
||||||
supplierFk: Proveedor
|
|
||||||
invoiceNumber: Nº Factura
|
|
||||||
reference: Ref/Alb/Guía
|
|
||||||
agencyModeId: Agencia
|
|
||||||
isBooked: Asentado
|
|
||||||
companyFk: Empresa
|
|
||||||
travelFk: Envio
|
|
||||||
evaNotes: Notas
|
|
||||||
warehouseOutFk: Origen
|
|
||||||
warehouseInFk: Destino
|
|
||||||
entryTypeDescription: Tipo entrada
|
|
||||||
invoiceAmount: Importe
|
|
||||||
dated: Fecha
|
|
||||||
itemFk: Id artículo
|
|
||||||
hex: Color
|
|
||||||
name: Nombre artículo
|
|
||||||
size: Medida
|
|
||||||
stickers: Etiquetas
|
|
||||||
packagingFk: Embalaje
|
|
||||||
weight: Kg
|
|
||||||
groupinMode: Selector de grouping
|
|
||||||
grouping: Grouping
|
|
||||||
quantity: Quantity
|
|
||||||
buyingValue: Precio de compra
|
|
||||||
price2: Paquete
|
|
||||||
price3: Caja
|
|
||||||
minPrice: Precio mínimo
|
|
||||||
hasMinPrice: Tiene precio mínimo
|
|
||||||
packingOut: Packing out
|
|
||||||
comment: Referencia
|
|
||||||
subName: Nombre proveedor
|
|
||||||
tags: Etiquetas
|
|
||||||
company_name: Nombre empresa
|
|
||||||
itemTypeFk: Familia
|
|
||||||
workerFk: Comprador
|
|
||||||
entryFilter:
|
entryFilter:
|
||||||
params:
|
params:
|
||||||
isExcludedFromAvailable: Inventario
|
|
||||||
isOrdered: Pedida
|
|
||||||
isConfirmed: Confirmado
|
|
||||||
isReceived: Recibida
|
|
||||||
isRaid: Raid
|
|
||||||
landed: Fecha
|
|
||||||
id: Id
|
|
||||||
supplierFk: Proveedor
|
|
||||||
invoiceNumber: Núm. factura
|
invoiceNumber: Núm. factura
|
||||||
reference: Ref/Alb/Guía
|
travelFk: Envío
|
||||||
agencyModeId: Modo agencia
|
companyFk: Empresa
|
||||||
evaNotes: Notas
|
currencyFk: Moneda
|
||||||
warehouseOutFk: Origen
|
supplierFk: Proveedor
|
||||||
warehouseInFk: Destino
|
from: Desde
|
||||||
entryTypeCode: Tipo de entrada
|
to: Hasta
|
||||||
hasToShowDeletedEntries: Mostrar entradas eliminadas
|
created: Fecha creación
|
||||||
|
isBooked: Asentado
|
||||||
|
isConfirmed: Confirmado
|
||||||
|
isOrdered: Pedida
|
||||||
|
search: Búsqueda general
|
||||||
|
reference: Referencia
|
||||||
myEntries:
|
myEntries:
|
||||||
id: ID
|
id: ID
|
||||||
landed: F. llegada
|
landed: F. llegada
|
||||||
|
|
|
@ -125,7 +125,7 @@ function deleteFile(dmsFk) {
|
||||||
<VnInput
|
<VnInput
|
||||||
clearable
|
clearable
|
||||||
clear-icon="close"
|
clear-icon="close"
|
||||||
:label="t('invoiceIn.supplierRef')"
|
:label="t('Supplier ref')"
|
||||||
v-model="data.supplierRef"
|
v-model="data.supplierRef"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
@ -149,7 +149,6 @@ function deleteFile(dmsFk) {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="id"
|
option-label="id"
|
||||||
:filter-options="['id', 'name']"
|
:filter-options="['id', 'name']"
|
||||||
data-cy="UnDeductibleVatSelect"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -311,6 +310,7 @@ function deleteFile(dmsFk) {
|
||||||
supplierFk: Supplier
|
supplierFk: Supplier
|
||||||
es:
|
es:
|
||||||
supplierFk: Proveedor
|
supplierFk: Proveedor
|
||||||
|
Supplier ref: Ref. proveedor
|
||||||
Expedition date: Fecha expedición
|
Expedition date: Fecha expedición
|
||||||
Operation date: Fecha operación
|
Operation date: Fecha operación
|
||||||
Undeductible VAT: Iva no deducible
|
Undeductible VAT: Iva no deducible
|
||||||
|
|
|
@ -90,6 +90,7 @@ async function setInvoiceCorrection(id) {
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="cardDescriptorRef"
|
ref="cardDescriptorRef"
|
||||||
|
module="InvoiceIn"
|
||||||
data-key="InvoiceIn"
|
data-key="InvoiceIn"
|
||||||
:url="`InvoiceIns/${entityId}`"
|
:url="`InvoiceIns/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
|
|
|
@ -186,7 +186,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
clickable
|
clickable
|
||||||
@click="book(entityId)"
|
@click="book(entityId)"
|
||||||
>
|
>
|
||||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</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.unbook') }}
|
{{ t('invoiceIn.descriptorMenu.toUnbook') }}
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onBeforeMount } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -12,7 +12,6 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
import { toCurrency } from 'filters/index';
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
@ -27,7 +26,7 @@ const invoiceInFormRef = ref();
|
||||||
const invoiceId = +route.params.id;
|
const invoiceId = +route.params.id;
|
||||||
const filter = { where: { invoiceInFk: invoiceId } };
|
const filter = { where: { invoiceInFk: invoiceId } };
|
||||||
const areRows = ref(false);
|
const areRows = ref(false);
|
||||||
const totals = ref();
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
name: 'duedate',
|
name: 'duedate',
|
||||||
|
@ -67,8 +66,6 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const totalAmount = computed(() => getTotal(invoiceInFormRef.value.formData, 'amount'));
|
|
||||||
|
|
||||||
const isNotEuro = (code) => code != 'EUR';
|
const isNotEuro = (code) => code != 'EUR';
|
||||||
|
|
||||||
async function insert() {
|
async function insert() {
|
||||||
|
@ -76,10 +73,6 @@ async function insert() {
|
||||||
await invoiceInFormRef.value.reload();
|
await invoiceInFormRef.value.reload();
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
totals.value = (await axios.get(`InvoiceIns/${invoiceId}/getTotals`)).data;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
@ -160,7 +153,7 @@ onBeforeMount(async () => {
|
||||||
<QTd />
|
<QTd />
|
||||||
<QTd />
|
<QTd />
|
||||||
<QTd>
|
<QTd>
|
||||||
{{ toCurrency(totalAmount) }}
|
{{ getTotal(rows, 'amount', { currency: 'default' }) }}
|
||||||
</QTd>
|
</QTd>
|
||||||
<QTd>
|
<QTd>
|
||||||
<template v-if="isNotEuro(invoiceIn.currency.code)">
|
<template v-if="isNotEuro(invoiceIn.currency.code)">
|
||||||
|
@ -242,16 +235,7 @@ onBeforeMount(async () => {
|
||||||
v-shortcut="'+'"
|
v-shortcut="'+'"
|
||||||
size="lg"
|
size="lg"
|
||||||
round
|
round
|
||||||
@click="
|
@click="!areRows ? insert() : invoiceInFormRef.insert()"
|
||||||
() => {
|
|
||||||
if (!areRows) insert();
|
|
||||||
else
|
|
||||||
invoiceInFormRef.insert({
|
|
||||||
amount: (totals.totalTaxableBase - totalAmount).toFixed(2),
|
|
||||||
invoiceInFk: invoiceId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</QPageSticky>
|
</QPageSticky>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -193,7 +193,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
<InvoiceIntoBook>
|
<InvoiceIntoBook>
|
||||||
<template #content="{ book }">
|
<template #content="{ book }">
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('Book')"
|
:label="t('To book')"
|
||||||
color="orange-11"
|
color="orange-11"
|
||||||
text-color="black"
|
text-color="black"
|
||||||
@click="book(entityId)"
|
@click="book(entityId)"
|
||||||
|
@ -224,7 +224,10 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :label="t('invoiceIn.supplierRef')" :value="entity.supplierRef" />
|
<VnLv
|
||||||
|
:label="t('invoiceIn.list.supplierRef')"
|
||||||
|
:value="entity.supplierRef"
|
||||||
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('invoiceIn.summary.currency')"
|
:label="t('invoiceIn.summary.currency')"
|
||||||
:value="entity.currency?.code"
|
:value="entity.currency?.code"
|
||||||
|
@ -354,7 +357,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
entity.totals.totalTaxableBaseForeignValue &&
|
entity.totals.totalTaxableBaseForeignValue &&
|
||||||
toCurrency(
|
toCurrency(
|
||||||
entity.totals.totalTaxableBaseForeignValue,
|
entity.totals.totalTaxableBaseForeignValue,
|
||||||
currency,
|
currency
|
||||||
)
|
)
|
||||||
}}</QTd>
|
}}</QTd>
|
||||||
</QTr>
|
</QTr>
|
||||||
|
@ -389,7 +392,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
entity.totals.totalDueDayForeignValue &&
|
entity.totals.totalDueDayForeignValue &&
|
||||||
toCurrency(
|
toCurrency(
|
||||||
entity.totals.totalDueDayForeignValue,
|
entity.totals.totalDueDayForeignValue,
|
||||||
currency,
|
currency
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</QTd>
|
</QTd>
|
||||||
|
@ -469,5 +472,5 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
Search invoice: Buscar factura recibida
|
Search invoice: Buscar factura recibida
|
||||||
You can search by invoice reference: Puedes buscar por referencia de la factura
|
You can search by invoice reference: Puedes buscar por referencia de la factura
|
||||||
Totals: Totales
|
Totals: Totales
|
||||||
Book: Contabilizar
|
To book: Contabilizar
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, nextTick } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
@ -25,6 +25,7 @@ const sageTaxTypes = ref([]);
|
||||||
const sageTransactionTypes = ref([]);
|
const sageTransactionTypes = ref([]);
|
||||||
const rowsSelected = ref([]);
|
const rowsSelected = ref([]);
|
||||||
const invoiceInFormRef = ref();
|
const invoiceInFormRef = ref();
|
||||||
|
const expenseRef = ref();
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
actionIcon: {
|
actionIcon: {
|
||||||
|
@ -96,20 +97,6 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const taxableBaseTotal = computed(() => {
|
|
||||||
return getTotal(invoiceInFormRef.value.formData, 'taxableBase');
|
|
||||||
});
|
|
||||||
|
|
||||||
const taxRateTotal = computed(() => {
|
|
||||||
return getTotal(invoiceInFormRef.value.formData, null, {
|
|
||||||
cb: taxRate,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const combinedTotal = computed(() => {
|
|
||||||
return +taxableBaseTotal.value + +taxRateTotal.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
fields: [
|
fields: [
|
||||||
'id',
|
'id',
|
||||||
|
@ -138,7 +125,7 @@ function taxRate(invoiceInTax) {
|
||||||
return ((taxTypeSage / 100) * taxableBase).toFixed(2);
|
return ((taxTypeSage / 100) * taxableBase).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function autocompleteExpense(evt, row, col, ref) {
|
function autocompleteExpense(evt, row, col) {
|
||||||
const val = evt.target.value;
|
const val = evt.target.value;
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
|
|
||||||
|
@ -147,17 +134,22 @@ function autocompleteExpense(evt, row, col, ref) {
|
||||||
({ id }) => id == useAccountShortToStandard(param),
|
({ id }) => id == useAccountShortToStandard(param),
|
||||||
);
|
);
|
||||||
|
|
||||||
ref.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
|
expenseRef.value.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCursor(ref) {
|
const taxableBaseTotal = computed(() => {
|
||||||
nextTick(() => {
|
return getTotal(invoiceInFormRef.value.formData, 'taxableBase');
|
||||||
const select = ref.vnSelectDialogRef
|
});
|
||||||
? ref.vnSelectDialogRef.vnSelectRef
|
|
||||||
: ref.vnSelectRef;
|
const taxRateTotal = computed(() => {
|
||||||
select.$el.querySelector('input').setSelectionRange(0, 0);
|
return getTotal(invoiceInFormRef.value.formData, null, {
|
||||||
|
cb: taxRate,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const combinedTotal = computed(() => {
|
||||||
|
return +taxableBaseTotal.value + +taxRateTotal.value;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
@ -195,24 +187,14 @@ function setCursor(ref) {
|
||||||
<template #body-cell-expense="{ row, col }">
|
<template #body-cell-expense="{ row, col }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<VnSelectDialog
|
<VnSelectDialog
|
||||||
:ref="`expenseRef-${row.$index}`"
|
ref="expenseRef"
|
||||||
v-model="row[col.model]"
|
v-model="row[col.model]"
|
||||||
:options="col.options"
|
:options="col.options"
|
||||||
:option-value="col.optionValue"
|
:option-value="col.optionValue"
|
||||||
:option-label="col.optionLabel"
|
:option-label="col.optionLabel"
|
||||||
:filter-options="['id', 'name']"
|
:filter-options="['id', 'name']"
|
||||||
:tooltip="t('Create a new expense')"
|
:tooltip="t('Create a new expense')"
|
||||||
@keydown.tab="
|
@keydown.tab="autocompleteExpense($event, row, col)"
|
||||||
autocompleteExpense(
|
|
||||||
$event,
|
|
||||||
row,
|
|
||||||
col,
|
|
||||||
$refs[`expenseRef-${row.$index}`],
|
|
||||||
)
|
|
||||||
"
|
|
||||||
@update:model-value="
|
|
||||||
setCursor($refs[`expenseRef-${row.$index}`])
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -228,7 +210,7 @@ function setCursor(ref) {
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-taxablebase="{ row }">
|
<template #body-cell-taxablebase="{ row }">
|
||||||
<QTd shrink>
|
<QTd>
|
||||||
<VnInputNumber
|
<VnInputNumber
|
||||||
clear-icon="close"
|
clear-icon="close"
|
||||||
v-model="row.taxableBase"
|
v-model="row.taxableBase"
|
||||||
|
@ -239,16 +221,12 @@ function setCursor(ref) {
|
||||||
<template #body-cell-sageiva="{ row, col }">
|
<template #body-cell-sageiva="{ row, col }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:ref="`sageivaRef-${row.$index}`"
|
|
||||||
v-model="row[col.model]"
|
v-model="row[col.model]"
|
||||||
:options="col.options"
|
:options="col.options"
|
||||||
:option-value="col.optionValue"
|
:option-value="col.optionValue"
|
||||||
:option-label="col.optionLabel"
|
:option-label="col.optionLabel"
|
||||||
:filter-options="['id', 'vat']"
|
:filter-options="['id', 'vat']"
|
||||||
data-cy="vat-sageiva"
|
data-cy="vat-sageiva"
|
||||||
@update:model-value="
|
|
||||||
setCursor($refs[`sageivaRef-${row.$index}`])
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -266,15 +244,11 @@ function setCursor(ref) {
|
||||||
<template #body-cell-sagetransaction="{ row, col }">
|
<template #body-cell-sagetransaction="{ row, col }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:ref="`sagetransactionRef-${row.$index}`"
|
|
||||||
v-model="row[col.model]"
|
v-model="row[col.model]"
|
||||||
:options="col.options"
|
:options="col.options"
|
||||||
:option-value="col.optionValue"
|
:option-value="col.optionValue"
|
||||||
:option-label="col.optionLabel"
|
:option-label="col.optionLabel"
|
||||||
:filter-options="['id', 'transaction']"
|
:filter-options="['id', 'transaction']"
|
||||||
@update:model-value="
|
|
||||||
setCursor($refs[`sagetransactionRef-${row.$index}`])
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -292,7 +266,7 @@ function setCursor(ref) {
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-foreignvalue="{ row }">
|
<template #body-cell-foreignvalue="{ row }">
|
||||||
<QTd shrink>
|
<QTd>
|
||||||
<VnInputNumber
|
<VnInputNumber
|
||||||
:class="{
|
:class="{
|
||||||
'no-pointer-events': !isNotEuro(currency),
|
'no-pointer-events': !isNotEuro(currency),
|
||||||
|
|
|
@ -29,7 +29,6 @@ const cols = computed(() => [
|
||||||
name: 'isBooked',
|
name: 'isBooked',
|
||||||
label: t('invoiceIn.isBooked'),
|
label: t('invoiceIn.isBooked'),
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
component: 'checkbox',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -57,7 +56,7 @@ const cols = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'supplierRef',
|
name: 'supplierRef',
|
||||||
label: t('invoiceIn.supplierRef'),
|
label: t('invoiceIn.list.supplierRef'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -178,7 +177,7 @@ const cols = computed(() => [
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('invoiceIn.supplierRef')"
|
:label="t('invoiceIn.list.supplierRef')"
|
||||||
v-model="data.supplierRef"
|
v-model="data.supplierRef"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { useQuasar } from 'quasar';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import qs from 'qs';
|
|
||||||
const { notify, dialog } = useQuasar();
|
const { notify, dialog } = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -13,51 +12,29 @@ defineExpose({ checkToBook });
|
||||||
const { store } = useArrayData();
|
const { store } = useArrayData();
|
||||||
|
|
||||||
async function checkToBook(id) {
|
async function checkToBook(id) {
|
||||||
let messages = [];
|
let directBooking = true;
|
||||||
|
|
||||||
const hasProblemWithTax = (
|
|
||||||
await axios.get('InvoiceInTaxes/count', {
|
|
||||||
params: {
|
|
||||||
where: JSON.stringify({
|
|
||||||
invoiceInFk: id,
|
|
||||||
or: [{ taxTypeSageFk: null }, { transactionTypeSageFk: null }],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
).data?.count;
|
|
||||||
|
|
||||||
if (hasProblemWithTax)
|
|
||||||
messages.push(t('The VAT and Transaction fields have not been informed'));
|
|
||||||
|
|
||||||
const { data: totals } = await axios.get(`InvoiceIns/${id}/getTotals`);
|
const { data: totals } = await axios.get(`InvoiceIns/${id}/getTotals`);
|
||||||
const taxableBaseNotEqualDueDay = totals.totalDueDay != totals.totalTaxableBase;
|
const taxableBaseNotEqualDueDay = totals.totalDueDay != totals.totalTaxableBase;
|
||||||
const vatNotEqualDueDay = totals.totalDueDay != totals.totalVat;
|
const vatNotEqualDueDay = totals.totalDueDay != totals.totalVat;
|
||||||
|
|
||||||
if (taxableBaseNotEqualDueDay && vatNotEqualDueDay)
|
if (taxableBaseNotEqualDueDay && vatNotEqualDueDay) directBooking = false;
|
||||||
messages.push(t('The sum of the taxable bases does not match the due dates'));
|
|
||||||
|
|
||||||
const dueDaysCount = (
|
const { data: dueDaysCount } = await axios.get('InvoiceInDueDays/count', {
|
||||||
await axios.get('InvoiceInDueDays/count', {
|
where: {
|
||||||
params: {
|
|
||||||
where: JSON.stringify({
|
|
||||||
invoiceInFk: id,
|
invoiceInFk: id,
|
||||||
dueDated: { gte: Date.vnNew() },
|
dueDated: { gte: Date.vnNew() },
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
).data?.count;
|
|
||||||
|
|
||||||
if (dueDaysCount) messages.push(t('Some due dates are less than or equal to today'));
|
if (dueDaysCount) directBooking = false;
|
||||||
|
|
||||||
|
if (directBooking) return toBook(id);
|
||||||
|
|
||||||
if (!messages.length) toBook(id);
|
|
||||||
else
|
|
||||||
dialog({
|
dialog({
|
||||||
component: VnConfirm,
|
component: VnConfirm,
|
||||||
componentProps: {
|
componentProps: { title: t('Are you sure you want to book this invoice?') },
|
||||||
title: t('Are you sure you want to book this invoice?'),
|
}).onOk(async () => await toBook(id));
|
||||||
message: messages.reduce((acc, msg) => `${acc}<p>${msg}</p>`, ''),
|
|
||||||
},
|
|
||||||
}).onOk(() => toBook(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toBook(id) {
|
async function toBook(id) {
|
||||||
|
@ -82,7 +59,4 @@ async function toBook(id) {
|
||||||
es:
|
es:
|
||||||
Are you sure you want to book this invoice?: ¿Estás seguro de querer asentar esta factura?
|
Are you sure you want to book this invoice?: ¿Estás seguro de querer asentar esta factura?
|
||||||
It was not able to book the invoice: No se pudo contabilizar la factura
|
It was not able to book the invoice: No se pudo contabilizar la factura
|
||||||
Some due dates are less than or equal to today: Algún vencimiento tiene una fecha menor o igual que hoy
|
|
||||||
The sum of the taxable bases does not match the due dates: La suma de las bases imponibles no coincide con la de los vencimientos
|
|
||||||
The VAT and Transaction fields have not been informed: No se han informado los campos de iva y/o transacción
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -3,10 +3,10 @@ invoiceIn:
|
||||||
searchInfo: Search incoming invoices by ID or supplier fiscal name
|
searchInfo: Search incoming invoices by ID or supplier fiscal name
|
||||||
serial: Serial
|
serial: Serial
|
||||||
isBooked: Is booked
|
isBooked: Is booked
|
||||||
supplierRef: Invoice nº
|
|
||||||
list:
|
list:
|
||||||
ref: Reference
|
ref: Reference
|
||||||
supplier: Supplier
|
supplier: Supplier
|
||||||
|
supplierRef: Supplier ref.
|
||||||
file: File
|
file: File
|
||||||
issued: Issued
|
issued: Issued
|
||||||
dueDated: Due dated
|
dueDated: Due dated
|
||||||
|
@ -19,6 +19,8 @@ invoiceIn:
|
||||||
unbook: Unbook
|
unbook: Unbook
|
||||||
delete: Delete
|
delete: Delete
|
||||||
clone: Clone
|
clone: Clone
|
||||||
|
toBook: To book
|
||||||
|
toUnbook: To unbook
|
||||||
deleteInvoice: Delete invoice
|
deleteInvoice: Delete invoice
|
||||||
invoiceDeleted: invoice deleted
|
invoiceDeleted: invoice deleted
|
||||||
cloneInvoice: Clone invoice
|
cloneInvoice: Clone invoice
|
||||||
|
@ -68,3 +70,4 @@ invoiceIn:
|
||||||
isBooked: Is booked
|
isBooked: Is booked
|
||||||
account: Ledger account
|
account: Ledger account
|
||||||
correctingFk: Rectificative
|
correctingFk: Rectificative
|
||||||
|
|
|
@ -3,10 +3,10 @@ invoiceIn:
|
||||||
searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
|
searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
|
||||||
serial: Serie
|
serial: Serie
|
||||||
isBooked: Contabilizada
|
isBooked: Contabilizada
|
||||||
supplierRef: Nº factura
|
|
||||||
list:
|
list:
|
||||||
ref: Referencia
|
ref: Referencia
|
||||||
supplier: Proveedor
|
supplier: Proveedor
|
||||||
|
supplierRef: Ref. proveedor
|
||||||
issued: F. emisión
|
issued: F. emisión
|
||||||
dueDated: F. vencimiento
|
dueDated: F. vencimiento
|
||||||
file: Fichero
|
file: Fichero
|
||||||
|
@ -15,10 +15,12 @@ invoiceIn:
|
||||||
descriptor:
|
descriptor:
|
||||||
ticketList: Listado de tickets
|
ticketList: Listado de tickets
|
||||||
descriptorMenu:
|
descriptorMenu:
|
||||||
book: Contabilizar
|
book: Asentar
|
||||||
unbook: Descontabilizar
|
unbook: Desasentar
|
||||||
delete: Eliminar
|
delete: Eliminar
|
||||||
clone: Clonar
|
clone: Clonar
|
||||||
|
toBook: Contabilizar
|
||||||
|
toUnbook: Descontabilizar
|
||||||
deleteInvoice: Eliminar factura
|
deleteInvoice: Eliminar factura
|
||||||
invoiceDeleted: Factura eliminada
|
invoiceDeleted: Factura eliminada
|
||||||
cloneInvoice: Clonar factura
|
cloneInvoice: Clonar factura
|
||||||
|
@ -66,3 +68,4 @@ invoiceIn:
|
||||||
isBooked: Contabilizada
|
isBooked: Contabilizada
|
||||||
account: Cuenta contable
|
account: Cuenta contable
|
||||||
correctingFk: Rectificativa
|
correctingFk: Rectificativa
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ function ticketFilter(invoice) {
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
|
module="InvoiceOut"
|
||||||
:url="`InvoiceOuts/${entityId}`"
|
:url="`InvoiceOuts/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
title="ref"
|
title="ref"
|
||||||
|
|
|
@ -97,19 +97,12 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'companyFk',
|
name: 'companyCode',
|
||||||
label: t('globals.company'),
|
label: t('globals.company'),
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
component: 'select',
|
component: 'select',
|
||||||
attrs: {
|
attrs: { url: 'Companies', optionLabel: 'code', optionValue: 'id' },
|
||||||
url: 'Companies',
|
columnField: { component: null },
|
||||||
optionLabel: 'code',
|
|
||||||
optionValue: 'id',
|
|
||||||
},
|
|
||||||
columnField: {
|
|
||||||
component: null,
|
|
||||||
},
|
|
||||||
format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
|
|
@ -11,7 +11,6 @@ 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 FilterItemForm from 'src/components/FilterItemForm.vue';
|
import FilterItemForm from 'src/components/FilterItemForm.vue';
|
||||||
import CreateIntrastatForm from './CreateIntrastatForm.vue';
|
import CreateIntrastatForm from './CreateIntrastatForm.vue';
|
||||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -209,20 +208,30 @@ const onIntrastatCreated = (response, formData) => {
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
<VnCheckbox
|
<div>
|
||||||
|
<QCheckbox
|
||||||
v-model="data.isFragile"
|
v-model="data.isFragile"
|
||||||
:label="t('item.basicData.isFragile')"
|
:label="t('item.basicData.isFragile')"
|
||||||
:info="t('item.basicData.isFragileTooltip')"
|
|
||||||
class="q-mr-sm"
|
class="q-mr-sm"
|
||||||
size="xs"
|
|
||||||
/>
|
/>
|
||||||
<VnCheckbox
|
<QIcon name="info" class="cursor-pointer" size="xs">
|
||||||
|
<QTooltip max-width="300px">
|
||||||
|
{{ t('item.basicData.isFragileTooltip') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<QCheckbox
|
||||||
v-model="data.isPhotoRequested"
|
v-model="data.isPhotoRequested"
|
||||||
:label="t('item.basicData.isPhotoRequested')"
|
:label="t('item.basicData.isPhotoRequested')"
|
||||||
:info="t('item.basicData.isPhotoRequestedTooltip')"
|
|
||||||
class="q-mr-sm"
|
class="q-mr-sm"
|
||||||
size="xs"
|
|
||||||
/>
|
/>
|
||||||
|
<QIcon name="info" class="cursor-pointer" size="xs">
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('item.basicData.isPhotoRequestedTooltip') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
|
|
@ -7,8 +7,8 @@ import FetchData from 'components/FetchData.vue';
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||||
import CreateGenusForm from '../components/CreateGenusForm.vue';
|
import CreateGenusForm from './CreateGenusForm.vue';
|
||||||
import CreateSpecieForm from '../components/CreateSpecieForm.vue';
|
import CreateSpecieForm from './CreateSpecieForm.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
|
@ -34,10 +34,6 @@ const $props = defineProps({
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
proxyRender: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -92,6 +88,7 @@ const updateStock = async () => {
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
data-key="Item"
|
data-key="Item"
|
||||||
|
module="Item"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
:url="`Items/${entityId}/getCard`"
|
:url="`Items/${entityId}/getCard`"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
|
@ -115,7 +112,7 @@ const updateStock = async () => {
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">
|
<span class="link">
|
||||||
{{ entity.itemType?.worker?.user?.name }}
|
{{ entity.itemType?.worker?.user?.name }}
|
||||||
<WorkerDescriptorProxy :id="entity.itemType?.worker?.id ?? NaN" />
|
<WorkerDescriptorProxy :id="entity.itemType?.worker?.id" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
|
@ -150,7 +147,7 @@ const updateStock = async () => {
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{}">
|
<template #actions="{}">
|
||||||
<QCardActions class="row justify-center" v-if="proxyRender">
|
<QCardActions class="row justify-center">
|
||||||
<QBtn
|
<QBtn
|
||||||
:to="{
|
:to="{
|
||||||
name: 'ItemDiary',
|
name: 'ItemDiary',
|
||||||
|
@ -163,16 +160,6 @@ const updateStock = async () => {
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('item.descriptor.itemDiary') }}</QTooltip>
|
<QTooltip>{{ t('item.descriptor.itemDiary') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
<QBtn
|
|
||||||
:to="{
|
|
||||||
name: 'ItemLastEntries',
|
|
||||||
}"
|
|
||||||
size="md"
|
|
||||||
icon="vn:regentry"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<QTooltip>{{ t('item.descriptor.itemLastEntries') }}</QTooltip>
|
|
||||||
</QBtn>
|
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</CardDescriptor>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import ItemSummary from './ItemSummary.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: [Number, String],
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
dated: {
|
dated: {
|
||||||
|
@ -21,8 +21,9 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPopupProxy style="max-width: 10px">
|
<QPopupProxy>
|
||||||
<ItemDescriptor
|
<ItemDescriptor
|
||||||
v-if="$props.id"
|
v-if="$props.id"
|
||||||
:id="$props.id"
|
:id="$props.id"
|
||||||
|
@ -30,7 +31,6 @@ const $props = defineProps({
|
||||||
:dated="dated"
|
:dated="dated"
|
||||||
:sale-fk="saleFk"
|
:sale-fk="saleFk"
|
||||||
:warehouse-fk="warehouseFk"
|
:warehouse-fk="warehouseFk"
|
||||||
:proxy-render="true"
|
|
||||||
/>
|
/>
|
||||||
</QPopupProxy>
|
</QPopupProxy>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -65,19 +65,10 @@ const columns = computed(() => [
|
||||||
name: 'name',
|
name: 'name',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
create: true,
|
create: true,
|
||||||
columnFilter: {
|
|
||||||
component: 'select',
|
|
||||||
attrs: {
|
|
||||||
url: 'Items',
|
|
||||||
fields: ['id', 'name', 'subName'],
|
|
||||||
optionLabel: 'name',
|
|
||||||
optionValue: 'name',
|
|
||||||
uppercase: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.groupingPrice'),
|
label: t('item.fixedPrice.groupingPrice'),
|
||||||
|
field: 'rate2',
|
||||||
name: 'rate2',
|
name: 'rate2',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
component: 'input',
|
component: 'input',
|
||||||
|
@ -85,6 +76,7 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.packingPrice'),
|
label: t('item.fixedPrice.packingPrice'),
|
||||||
|
field: 'rate3',
|
||||||
name: 'rate3',
|
name: 'rate3',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
component: 'input',
|
component: 'input',
|
||||||
|
@ -93,6 +85,7 @@ const columns = computed(() => [
|
||||||
|
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.minPrice'),
|
label: t('item.fixedPrice.minPrice'),
|
||||||
|
field: 'minPrice',
|
||||||
name: 'minPrice',
|
name: 'minPrice',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
component: 'input',
|
component: 'input',
|
||||||
|
@ -115,6 +108,7 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.fixedPrice.ended'),
|
label: t('item.fixedPrice.ended'),
|
||||||
|
field: 'ended',
|
||||||
name: 'ended',
|
name: 'ended',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
columnField: {
|
columnField: {
|
||||||
|
@ -130,6 +124,7 @@ const columns = computed(() => [
|
||||||
|
|
||||||
{
|
{
|
||||||
label: t('globals.warehouse'),
|
label: t('globals.warehouse'),
|
||||||
|
field: 'warehouseFk',
|
||||||
name: 'warehouseFk',
|
name: 'warehouseFk',
|
||||||
...defaultColumnAttrs,
|
...defaultColumnAttrs,
|
||||||
columnClass: 'shrink',
|
columnClass: 'shrink',
|
||||||
|
@ -420,6 +415,7 @@ function handleOnDataSave({ CrudModelRef }) {
|
||||||
'row-key': 'id',
|
'row-key': 'id',
|
||||||
selection: 'multiple',
|
selection: 'multiple',
|
||||||
}"
|
}"
|
||||||
|
:use-model="true"
|
||||||
v-model:selected="rowsSelected"
|
v-model:selected="rowsSelected"
|
||||||
:create-as-dialog="false"
|
:create-as-dialog="false"
|
||||||
:create="{
|
:create="{
|
||||||
|
|
|
@ -26,6 +26,7 @@ const entityId = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
|
module="ItemType"
|
||||||
:url="`ItemTypes/${entityId}`"
|
:url="`ItemTypes/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
title="code"
|
title="code"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue