#8193: Added filter in ClientNotes #1609

Open
jon wants to merge 24 commits from 8193-AddFilterInClientNotes into dev
145 changed files with 2803 additions and 1543 deletions
Showing only changes of commit 490e5cbf97 - Show all commits

4
Jenkinsfile vendored
View File

@ -115,6 +115,7 @@ pipeline {
steps {
script {
sh 'rm -f junit/e2e-*.xml'
sh 'rm -rf test/cypress/screenshots'
env.COMPOSE_TAG = PROTECTED_BRANCH.contains(env.CHANGE_TARGET) ? env.CHANGE_TARGET : 'dev'
def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs')
@ -125,13 +126,14 @@ pipeline {
sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
sh 'sh test/cypress/cypressParallel.sh 2'
sh 'sh test/cypress/cypressParallel.sh 1'
}
}
}
post {
always {
sh "docker-compose ${env.COMPOSE_PARAMS} down -v"
archiveArtifacts artifacts: 'test/cypress/screenshots/**/*', allowEmptyArchive: true
junit(
testResults: 'junit/e2e-*.xml',
allowEmptyResults: true

View File

@ -198,8 +198,7 @@ const setCategoryList = (data) => {
v-model="params.typeFk"
:options="itemTypesOptions"
dense
outlined
rounded
filled
use-input
:disable="!selectedCategoryFk"
@update:model-value="
@ -235,8 +234,7 @@ const setCategoryList = (data) => {
v-model="value.selectedTag"
:options="tagOptions"
dense
outlined
rounded
filled
:emit-value="false"
use-input
:is-clearable="false"
@ -252,8 +250,7 @@ const setCategoryList = (data) => {
option-value="value"
option-label="value"
dense
outlined
rounded
filled
emit-value
use-input
:disable="!value"
@ -265,7 +262,6 @@ const setCategoryList = (data) => {
v-model="value.value"
:label="t('components.itemsFilterPanel.value')"
:disable="!value"
is-outlined
:is-clearable="false"
@keyup.enter="applyTags(params, searchFn)"
/>

View File

@ -140,7 +140,7 @@ const $props = defineProps({
},
dataCy: {
type: String,
default: 'vn-table',
default: 'vnTable',
},
});
@ -633,6 +633,7 @@ const rowCtrlClickFunction = computed(() => {
:data-key="$attrs['data-key']"
:columns="columns"
:redirect="redirect"
v-bind="$attrs?.['table-filter']"
>
<template
v-for="(_, slotName) in $slots"
@ -684,7 +685,7 @@ const rowCtrlClickFunction = computed(() => {
@update:selected="emit('update:selected', $event)"
@selection="(details) => handleSelection(details, rows)"
:hide-selected-banner="true"
:data-cy="$props.dataCy ?? 'vnTable'"
:data-cy
>
<template #top-left v-if="!$props.withoutHeader">
<slot name="top-left"> </slot>
@ -781,6 +782,7 @@ const rowCtrlClickFunction = computed(() => {
text-overflow: ellipsis;
white-space: nowrap;
"
:data-cy="`vnTableCell_${col.name}`"
>
<slot
:name="`column-${col.name}`"
@ -895,7 +897,7 @@ const rowCtrlClickFunction = computed(() => {
{{ row[splittedColumns.title.name] }}
</span>
</QCardSection>
<!-- Fields -->
<!-- Fields -->
<QCardSection
class="q-pl-sm q-py-xs"
:class="$props.cardClass"
@ -1154,7 +1156,7 @@ es:
.grid-create {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
max-width: 100%;
grid-gap: 20px;
margin: 0 auto;

View File

@ -1,12 +1,15 @@
<script setup>
import { onBeforeMount } from 'vue';
import { useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
import { onBeforeMount, computed } from 'vue';
import { useRoute, useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import useCardSize from 'src/composables/useCardSize';
import VnSubToolbar from '../ui/VnSubToolbar.vue';
const emit = defineEmits(['onFetch']);
const props = defineProps({
id: { type: Number, required: false, default: null },
dataKey: { type: String, required: true },
url: { type: String, default: undefined },
idInWhere: { type: Boolean, default: false },
@ -16,10 +19,13 @@ const props = defineProps({
searchDataKey: { type: String, default: undefined },
searchbarProps: { type: Object, default: undefined },
redirectOnError: { type: Boolean, default: false },
visual: { type: Boolean, default: true },
});
const route = useRoute();
const stateStore = useStateStore();
const router = useRouter();
const entityId = computed(() => props.id || route?.params?.id);
const arrayData = useArrayData(props.dataKey, {
url: props.url,
userFilter: props.filter,
@ -35,7 +41,7 @@ onBeforeMount(async () => {
const route = router.currentRoute.value;
try {
await fetch(route.params.id);
await fetch(entityId.value);
} catch {
const { matched: matches } = route;
const { path } = matches.at(-1);
@ -51,8 +57,7 @@ onBeforeRouteUpdate(async (to, from) => {
router.push({ name, params: to.params });
}
}
const id = to.params.id;
if (id !== from.params.id) await fetch(id, true);
if (entityId.value !== to.params.id) await fetch(to.params.id, true);
});
async function fetch(id, append = false) {
@ -61,14 +66,17 @@ async function fetch(id, append = false) {
else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
else arrayData.store.url = props.url.replace(regex, `/${id}`);
await arrayData.fetch({ append, updateRouter: false });
emit('onFetch', arrayData.store.data);
}
function hasRouteParam(params, valueToCheck = ':addressId') {
return Object.values(params).includes(valueToCheck);
}
</script>
<template>
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="$route.path" />
</div>
<template v-if="visual">
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="$route.path" />
</div>
</template>
</template>

View File

@ -27,7 +27,11 @@ const checkboxModel = computed({
</script>
<template>
<div>
<QCheckbox v-bind="$attrs" v-model="checkboxModel" />
<QCheckbox
v-bind="$attrs"
v-model="checkboxModel"
:data-cy="$attrs['data-cy'] ?? `vnCheckbox${$attrs['label'] ?? ''}`"
/>
<QIcon
v-if="info"
v-bind="$attrs"

View File

@ -0,0 +1,166 @@
<script setup>
import VnConfirm from '../ui/VnConfirm.vue';
import VnInput from './VnInput.vue';
import VnDms from './VnDms.vue';
import axios from 'axios';
import { useQuasar } from 'quasar';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { downloadFile } from 'src/composables/downloadFile';
const { t } = useI18n();
const quasar = useQuasar();
const documentDialogRef = ref({});
const editDownloadDisabled = ref(false);
const $props = defineProps({
defaultDmsCode: {
type: String,
default: 'InvoiceIn',
},
disable: {
type: Boolean,
default: true,
},
data: {
type: Object,
default: null,
},
formRef: {
type: Object,
default: null,
},
});
function deleteFile(dmsFk) {
quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('globals.confirmDeletion'),
message: t('globals.confirmDeletionMessage'),
},
})
.onOk(async () => {
await axios.post(`dms/${dmsFk}/removeFile`);
$props.formRef.formData.dmsFk = null;
$props.formRef.formData.dms = undefined;
$props.formRef.hasChanges = true;
$props.formRef.save();
});
}
</script>
<template>
<div class="row no-wrap">
<VnInput
:label="t('Document')"
v-model="data.dmsFk"
clearable
clear-icon="close"
class="full-width"
:disable="disable"
/>
<div
v-if="data.dmsFk"
class="row no-wrap q-pa-xs q-gutter-x-xs"
data-cy="dms-buttons"
>
<QBtn
:disable="editDownloadDisabled"
@click="downloadFile(data.dmsFk)"
icon="cloud_download"
color="primary"
flat
:class="{
'no-pointer-events': editDownloadDisabled,
}"
padding="xs"
round
>
<QTooltip>{{ t('Download file') }}</QTooltip>
</QBtn>
<QBtn
:disable="editDownloadDisabled"
@click="
() => {
documentDialogRef.show = true;
documentDialogRef.dms = data.dms;
}
"
icon="edit"
color="primary"
flat
:class="{
'no-pointer-events': editDownloadDisabled,
}"
padding="xs"
round
>
<QTooltip>{{ t('Edit document') }}</QTooltip>
</QBtn>
<QBtn
:disable="editDownloadDisabled"
@click="deleteFile(data.dmsFk)"
icon="delete"
color="primary"
flat
round
:class="{
'no-pointer-events': editDownloadDisabled,
}"
padding="xs"
>
<QTooltip>{{ t('Delete file') }}</QTooltip>
</QBtn>
</div>
<QBtn
v-else
icon="add_circle"
color="primary"
flat
round
v-shortcut="'+'"
padding="xs"
@click="
() => {
documentDialogRef.show = true;
delete documentDialogRef.dms;
}
"
data-cy="dms-create"
>
<QTooltip>{{ t('Create document') }}</QTooltip>
</QBtn>
</div>
<QDialog v-model="documentDialogRef.show">
<VnDms
model="dms"
:default-dms-code="defaultDmsCode"
:form-initial-data="documentDialogRef.dms"
:url="
documentDialogRef.dms
? `Dms/${documentDialogRef.dms.id}/updateFile`
: 'Dms/uploadFile'
"
:description="documentDialogRef.supplierName"
@on-data-saved="
(_, { data }) => {
let dmsData = data;
if (Array.isArray(data)) dmsData = data[0];
formRef.formData.dmsFk = dmsData.id;
formRef.formData.dms = dmsData;
formRef.hasChanges = true;
formRef.save();
}
"
/>
</QDialog>
</template>
<i18n>
es:
Document: Documento
Download file: Descargar archivo
Edit document: Editar documento
Delete file: Eliminar archivo
Create document: Crear documento
</i18n>

View File

@ -84,7 +84,7 @@ const mixinRules = [
...($attrs.rules ?? []),
(val) => {
const maxlength = $props.maxlength;
if (maxlength && +val.length > maxlength)
if (maxlength && +val?.length > maxlength)
return t(`maxLength`, { value: maxlength });
const { min, max } = vnInputRef.value.$attrs;
if (!min) return null;

View File

@ -107,7 +107,7 @@ const manageDate = (date) => {
@click="isPopupOpen = !isPopupOpen"
@keydown="isPopupOpen = false"
hide-bottom-space
:data-cy="$attrs.dataCy ?? $attrs.label + '_inputDate'"
:data-cy="($attrs['data-cy'] ?? $attrs.label) + '_inputDate'"
>
<template #append>
<QIcon

View File

@ -10,7 +10,7 @@ import { useColor } from 'src/composables/useColor';
import { useCapitalize } from 'src/composables/useCapitalize';
import { useValidator } from 'src/composables/useValidator';
import VnAvatar from '../ui/VnAvatar.vue';
import VnJsonValue from '../common/VnJsonValue.vue';
import VnLogValue from './VnLogValue.vue';
import FetchData from '../FetchData.vue';
import VnSelect from './VnSelect.vue';
import VnUserLink from '../ui/VnUserLink.vue';
@ -560,10 +560,11 @@ watch(
value.nameI18n
}}:
</span>
<VnJsonValue
<VnLogValue
:value="
value.val.val
"
:name="value.name"
/>
</QItem>
</QCardSection>
@ -614,7 +615,10 @@ watch(
>
{{ prop.nameI18n }}:
</span>
<VnJsonValue :value="prop.val.val" />
<VnLogValue
:value="prop.val.val"
:name="prop.name"
/>
<span
v-if="
propIndex <
@ -642,8 +646,9 @@ watch(
{{ prop.nameI18n }}:
</span>
<span v-if="log.action == 'update'">
<VnJsonValue
<VnLogValue
:value="prop.old.val"
:name="prop.name"
/>
<span
v-if="prop.old.id"
@ -652,8 +657,9 @@ watch(
#{{ prop.old.id }}
</span>
<VnJsonValue
<VnLogValue
:value="prop.val.val"
:name="prop.name"
/>
<span
v-if="prop.val.id"
@ -663,8 +669,9 @@ watch(
</span>
</span>
<span v-else="prop.old.val">
<VnJsonValue
<VnLogValue
:value="prop.val.val"
:name="prop.name"
/>
<span
v-if="prop.old.id"
@ -700,6 +707,7 @@ watch(
v-model="searchInput"
class="full-width"
clearable
filled
clear-icon="close"
@keyup.enter="() => selectFilter('search')"
@focusout="() => selectFilter('search')"
@ -719,6 +727,7 @@ watch(
v-model="selectedFilters.changedModel"
option-label="locale"
option-value="value"
filled
:options="actions"
@update:model-value="selectFilter('action')"
hide-selected
@ -744,8 +753,7 @@ watch(
class="full-width"
:label="t('globals.user')"
v-model="userSelect"
option-label="name"
option-value="id"
filled
:url="`${model}Logs/${route.params.id}/editors`"
:fields="['id', 'nickname', 'name', 'image']"
sort-by="nickname"
@ -774,6 +782,7 @@ watch(
:label="t('globals.changes')"
v-model="changeInput"
class="full-width"
filled
clearable
clear-icon="close"
@keyup.enter="selectFilter('change')"
@ -810,6 +819,7 @@ watch(
@clear="selectFilter('date', 'to')"
v-model="dateFrom"
clearable
filled
clear-icon="close"
/>
</QItem>
@ -822,6 +832,7 @@ watch(
@clear="selectFilter('date', 'from')"
v-model="dateTo"
clearable
filled
clear-icon="close"
/>
</QItem>
@ -835,6 +846,7 @@ watch(
dense
flat
minimal
filled
@update:model-value="
(value) => {
dateFromDialog = false;

View File

@ -0,0 +1,22 @@
<script setup>
import { useDescriptorStore } from 'src/stores/useDescriptorStore';
import VnJsonValue from './VnJsonValue.vue';
import { computed } from 'vue';
const descriptorStore = useDescriptorStore();
const $props = defineProps({
name: { type: [String], default: undefined },
});
const descriptor = computed(() => descriptorStore.has($props.name));
</script>
<template>
<VnJsonValue v-bind="$attrs" />
<QIcon
name="launch"
class="link"
v-if="$attrs.value && descriptor"
:data-cy="'iconLaunch-' + $props.name"
/>
<component :is="descriptor" :id="$attrs.value" v-if="$attrs.value && descriptor" />
</template>

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
import { ref, toRefs, computed, watch, onMounted, useAttrs, nextTick } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'src/composables/useArrayData';
import { useRequired } from 'src/composables/useRequired';
@ -247,6 +247,7 @@ async function fetchFilter(val) {
}
async function filterHandler(val, update) {
if (isLoading.value) return update();
if (!val && lastVal.value === val) {
lastVal.value = val;
return update();
@ -294,6 +295,7 @@ async function onScroll({ to, direction, from, index }) {
await arrayData.loadMore();
setOptions(arrayData.store.data);
vnSelectRef.value.scrollTo(lastIndex);
await nextTick();
isLoading.value = false;
}
}

View File

@ -4,12 +4,15 @@ import { vi, afterEach, beforeAll, describe, expect, it } from 'vitest';
describe('VnDmsList', () => {
let vm;
const dms = {
userFk: 1,
name: 'DMS 1'
const dms = {
userFk: 1,
name: 'DMS 1',
};
beforeAll(() => {
vi.mock('src/composables/getUrl', () => ({
getUrl: vi.fn().mockResolvedValue(''),
}));
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
vm = createWrapper(VnDmsList, {
props: {
@ -18,8 +21,8 @@ describe('VnDmsList', () => {
filter: 'wd.workerFk',
updateModel: 'Workers',
deleteModel: 'WorkerDms',
downloadModel: 'WorkerDms'
}
downloadModel: 'WorkerDms',
},
}).vm;
});
@ -29,46 +32,45 @@ describe('VnDmsList', () => {
describe('setData()', () => {
const data = [
{
userFk: 1,
{
userFk: 1,
name: 'Jessica',
lastName: 'Jones',
file: '4.jpg',
created: '2021-07-28 21:00:00'
created: '2021-07-28 21:00:00',
},
{
userFk: 2,
{
userFk: 2,
name: 'Bruce',
lastName: 'Banner',
created: '2022-07-28 21:00:00',
dms: {
userFk: 2,
userFk: 2,
name: 'Bruce',
lastName: 'BannerDMS',
created: '2022-07-28 21:00:00',
file: '4.jpg',
}
},
},
{
userFk: 3,
name: 'Natasha',
lastName: 'Romanoff',
file: '4.jpg',
created: '2021-10-28 21:00:00'
}
]
created: '2021-10-28 21:00:00',
},
];
it('Should replace objects that contain the "dms" property with the value of the same and sort by creation date', () => {
vm.setData(data);
expect([vm.rows][0][0].lastName).toEqual('BannerDMS');
expect([vm.rows][0][1].lastName).toEqual('Romanoff');
});
});
describe('parseDms()', () => {
const resultDms = { ...dms, userId:1};
const resultDms = { ...dms, userId: 1 };
it('Should add properties that end with "Fk" by changing the suffix to "Id"', () => {
const parsedDms = vm.parseDms(dms);
expect(parsedDms).toEqual(resultDms);
@ -76,12 +78,12 @@ describe('VnDmsList', () => {
});
describe('showFormDialog()', () => {
const resultDms = { ...dms, userId:1};
const resultDms = { ...dms, userId: 1 };
it('should call fn parseDms() and set show true if dms is defined', () => {
vm.showFormDialog(dms);
expect(vm.formDialog.show).toEqual(true);
expect(vm.formDialog.dms).toEqual(resultDms);
});
});
});
});

View File

@ -0,0 +1,26 @@
import { describe, it, expect } from 'vitest';
import VnLogValue from 'src/components/common/VnLogValue.vue';
import { createWrapper } from 'app/test/vitest/helper';
const buildComponent = (props) => {
return createWrapper(VnLogValue, {
props,
global: {},
}).wrapper;
};
describe('VnLogValue', () => {
const id = 1;
it('renders without descriptor', async () => {
expect(getIcon('inventFk').exists()).toBe(false);
});
it('renders with descriptor', async () => {
expect(getIcon('claimFk').text()).toBe('launch');
});
function getIcon(name) {
const wrapper = buildComponent({ value: { val: id }, name });
return wrapper.find('.q-icon');
}
});

View File

@ -1,355 +1,38 @@
<script setup>
import { onBeforeMount, watch, computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useArrayData } from 'composables/useArrayData';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useState } from 'src/composables/useState';
import { useRoute, useRouter } from 'vue-router';
import { useClipboard } from 'src/composables/useClipboard';
import VnMoreOptions from './VnMoreOptions.vue';
import { ref } from 'vue';
import VnDescriptor from './VnDescriptor.vue';
const $props = defineProps({
url: {
type: String,
default: '',
},
filter: {
type: Object,
default: null,
},
title: {
type: String,
default: '',
},
subtitle: {
id: {
type: Number,
default: null,
default: false,
},
dataKey: {
type: String,
default: null,
},
summary: {
card: {
type: Object,
default: null,
},
width: {
type: String,
default: 'md-width',
},
});
const state = useState();
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { copyText } = useClipboard();
const { viewSummary } = useSummaryDialog();
let arrayData;
let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
const DESCRIPTOR_PROXY = 'DescriptorProxy';
const moduleName = ref();
const isSameModuleName = route.matched[1].meta.moduleName !== moduleName.value;
defineExpose({ getData });
onBeforeMount(async () => {
arrayData = useArrayData($props.dataKey, {
url: $props.url,
userFilter: $props.filter,
skip: 0,
oneRecord: true,
});
store = arrayData.store;
entity = computed(() => {
const data = store.data ?? {};
if (data) emit('onFetch', data);
return data;
});
// It enables to load data only once if the module is the same as the dataKey
if (!isSameDataKey.value || !route.params.id) await getData();
watch(
() => [$props.url, $props.filter],
async () => {
if (!isSameDataKey.value) await getData();
},
);
});
function getName() {
let name = $props.dataKey;
if ($props.dataKey.includes(DESCRIPTOR_PROXY)) {
name = name.split(DESCRIPTOR_PROXY)[0];
}
return name;
}
const routeName = computed(() => {
let routeName = getName();
return `${routeName}Summary`;
});
async function getData() {
store.url = $props.url;
store.filter = $props.filter ?? {};
isLoading.value = true;
try {
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
state.set($props.dataKey, data);
emit('onFetch', data);
} finally {
isLoading.value = false;
}
}
function getValueFromPath(path) {
if (!path) return;
const keys = path.toString().split('.');
let current = entity.value;
for (const key of keys) {
if (current[key] === undefined) return undefined;
else current = current[key];
}
return current;
}
function copyIdText(id) {
copyText(id, {
component: {
copyValue: id,
},
});
}
const emit = defineEmits(['onFetch']);
const iconModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.meta?.icon;
} else {
return route.matched[1].meta.icon;
}
});
const toModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.children[0]?.redirect;
} else {
return route.matched[1].path.split('/').length > 2
? route.matched[1].redirect
: route.matched[1].children[0].redirect;
}
});
const entity = ref();
</script>
<template>
<div class="descriptor">
<template v-if="entity && !isLoading">
<div class="header bg-primary q-pa-sm justify-between">
<slot name="header-extra-action">
<QBtn
round
flat
dense
size="md"
:icon="iconModule"
color="white"
class="link"
:to="toModule"
>
<QTooltip>
{{ t('globals.goToModuleIndex') }}
</QTooltip>
</QBtn>
</slot>
<QBtn
@click.stop="viewSummary(entity.id, $props.summary, $props.width)"
round
flat
dense
size="md"
icon="preview"
color="white"
class="link"
v-if="summary"
data-cy="openSummaryBtn"
>
<QTooltip>
{{ t('components.smartCard.openSummary') }}
</QTooltip>
</QBtn>
<RouterLink :to="{ name: routeName, params: { id: entity.id } }">
<QBtn
class="link"
color="white"
dense
flat
icon="launch"
round
size="md"
data-cy="goToSummaryBtn"
>
<QTooltip>
{{ t('components.cardDescriptor.summary') }}
</QTooltip>
</QBtn>
</RouterLink>
<VnMoreOptions v-if="$slots.menu">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</div>
<slot name="before" />
<div class="body q-py-sm">
<QList dense>
<QItemLabel header class="ellipsis text-h5" :lines="1">
<div class="title">
<span v-if="$props.title" :title="getValueFromPath(title)">
{{ getValueFromPath(title) ?? $props.title }}
</span>
<slot v-else name="description" :entity="entity">
<span :title="entity.name">
{{ entity.name }}
</span>
</slot>
</div>
</QItemLabel>
<QItem>
<QItemLabel class="subtitle">
#{{ getValueFromPath(subtitle) ?? entity.id }}
</QItemLabel>
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
</QItem>
</QList>
<div class="list-box q-mt-xs">
<slot name="body" :entity="entity" />
</div>
</div>
<div class="icons">
<slot name="icons" :entity="entity" />
</div>
<div class="actions justify-center" data-cy="descriptor_actions">
<slot name="actions" :entity="entity" />
</div>
<slot name="after" />
</template>
<SkeletonDescriptor v-if="!entity || isLoading" />
</div>
<QInnerLoading
:label="t('globals.pleaseWait')"
:showing="isLoading"
color="primary"
/>
</template>
<style lang="scss">
.body {
background-color: var(--vn-section-color);
.text-h5 {
font-size: 20px;
padding-top: 5px;
padding-bottom: 0px;
}
.q-item {
min-height: 20px;
.link {
margin-left: 10px;
}
}
.vn-label-value {
display: flex;
padding: 0px 16px;
.label {
color: var(--vn-label-color);
font-size: 14px;
&:not(:has(a))::after {
content: ':';
<component
:is="card"
:id
:visual="false"
v-bind="$attrs"
@on-fetch="
(data) => {
entity = data;
emit('onFetch', data);
}
}
.value {
color: var(--vn-text-color);
font-size: 14px;
margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.info {
margin-left: 5px;
}
}
}
</style>
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;
span {
color: var(--vn-text-color);
font-weight: bold;
}
}
.subtitle {
color: var(--vn-text-color);
font-size: 16px;
margin-bottom: 2px;
}
.list-box {
.q-item__label {
color: var(--vn-label-color);
padding-bottom: 0%;
}
}
.descriptor {
width: 256px;
.header {
display: flex;
align-items: center;
}
.icons {
margin: 0 10px;
display: flex;
justify-content: center;
.q-icon {
margin-right: 5px;
}
}
.actions {
margin: 0 5px;
justify-content: center !important;
}
}
</style>
<i18n>
en:
globals:
copyId: Copy ID
es:
globals:
copyId: Copiar ID
</i18n>
"
/>
<VnDescriptor v-model="entity" v-bind="$attrs">
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
</template>
</VnDescriptor>
</template>

View File

@ -0,0 +1,78 @@
<script setup>
import { onBeforeMount, watch, computed, ref } from 'vue';
import { useArrayData } from 'composables/useArrayData';
import { useState } from 'src/composables/useState';
import { useRoute } from 'vue-router';
import VnDescriptor from './VnDescriptor.vue';
const $props = defineProps({
url: {
type: String,
default: '',
},
filter: {
type: Object,
default: null,
},
dataKey: {
type: String,
default: null,
},
});
const state = useState();
const route = useRoute();
let arrayData;
let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
defineExpose({ getData });
onBeforeMount(async () => {
arrayData = useArrayData($props.dataKey, {
url: $props.url,
userFilter: $props.filter,
skip: 0,
oneRecord: true,
});
store = arrayData.store;
entity = computed(() => {
const data = store.data ?? {};
if (data) emit('onFetch', data);
return data;
});
// It enables to load data only once if the module is the same as the dataKey
if (!isSameDataKey.value || !route.params.id) await getData();
watch(
() => [$props.url, $props.filter],
async () => {
if (!isSameDataKey.value) await getData();
},
);
});
async function getData() {
store.url = $props.url;
store.filter = $props.filter ?? {};
isLoading.value = true;
try {
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
state.set($props.dataKey, data);
emit('onFetch', data);
} finally {
isLoading.value = false;
}
}
const emit = defineEmits(['onFetch']);
</script>
<template>
<VnDescriptor v-model="entity" v-bind="$attrs" :module="dataKey">
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
</template>
</VnDescriptor>
</template>

View File

@ -0,0 +1,318 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useRoute, useRouter } from 'vue-router';
import { useClipboard } from 'src/composables/useClipboard';
import VnMoreOptions from './VnMoreOptions.vue';
const entity = defineModel({ type: Object, default: null });
const $props = defineProps({
title: {
type: String,
default: '',
},
subtitle: {
type: Number,
default: null,
},
summary: {
type: Object,
default: null,
},
width: {
type: String,
default: 'md-width',
},
module: {
type: String,
default: null,
},
toModule: {
type: String,
default: null,
},
});
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { copyText } = useClipboard();
const { viewSummary } = useSummaryDialog();
const DESCRIPTOR_PROXY = 'DescriptorProxy';
const moduleName = ref();
const isSameModuleName = route.matched[1].meta.moduleName !== moduleName.value;
function getName() {
let name = $props.module;
if ($props.module.includes(DESCRIPTOR_PROXY)) {
name = name.split(DESCRIPTOR_PROXY)[0];
}
return name;
}
const routeName = computed(() => {
let routeName = getName();
return `${routeName}Summary`;
});
function getValueFromPath(path) {
if (!path) return;
const keys = path.toString().split('.');
let current = entity.value;
for (const key of keys) {
if (current[key] === undefined) return undefined;
else current = current[key];
}
return current;
}
function copyIdText(id) {
copyText(id, {
component: {
copyValue: id,
},
});
}
const emit = defineEmits(['onFetch']);
const iconModule = computed(() => {
moduleName.value = getName();
if ($props.toModule) {
return router.getRoutes().find((r) => r.name === $props.toModule.name).meta.icon;
}
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.meta?.icon;
} else {
return route.matched[1].meta.icon;
}
});
const toModule = computed(() => {
moduleName.value = getName();
if ($props.toModule) return $props.toModule;
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.redirect;
} else {
return route.matched[1].path.split('/').length > 2
? route.matched[1].redirect
: route.matched[1].children[0].redirect;
}
});
</script>
<template>
<div class="descriptor" data-cy="vnDescriptor">
<template v-if="entity && entity?.id">
<div class="header bg-primary q-pa-sm justify-between">
<slot name="header-extra-action">
<QBtn
round
flat
dense
size="md"
:icon="iconModule"
color="white"
class="link"
:to="toModule"
>
<QTooltip>
{{ t('globals.goToModuleIndex') }}
</QTooltip>
</QBtn>
</slot>
<QBtn
@click.stop="viewSummary(entity.id, summary, width)"
round
flat
dense
size="md"
icon="preview"
color="white"
class="link"
v-if="summary"
data-cy="openSummaryBtn"
>
<QTooltip>
{{ t('components.smartCard.openSummary') }}
</QTooltip>
</QBtn>
<RouterLink :to="{ name: routeName, params: { id: entity.id } }">
<QBtn
class="link"
color="white"
dense
flat
icon="launch"
round
size="md"
data-cy="goToSummaryBtn"
>
<QTooltip>
{{ t('components.vnDescriptor.summary') }}
</QTooltip>
</QBtn>
</RouterLink>
<VnMoreOptions v-if="$slots.menu">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</div>
<slot name="before" />
<div class="body q-py-sm">
<QList dense>
<QItemLabel header class="ellipsis text-h5" :lines="1">
<div class="title">
<span
v-if="title"
:title="getValueFromPath(title)"
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_title`"
>
{{ getValueFromPath(title) ?? title }}
</span>
<slot v-else name="description" :entity="entity">
<span
:title="entity.name"
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_description`"
v-text="entity.name"
/>
</slot>
</div>
</QItemLabel>
<QItem>
<QItemLabel
class="subtitle"
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_subtitle`"
>
#{{ getValueFromPath(subtitle) ?? entity.id }}
</QItemLabel>
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
</QItem>
</QList>
<div
class="list-box q-mt-xs"
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_listbox`"
>
<slot name="body" :entity="entity" />
</div>
</div>
<div class="icons">
<slot name="icons" :entity="entity" />
</div>
<div class="actions justify-center" data-cy="descriptor_actions">
<slot name="actions" :entity="entity" />
</div>
<slot name="after" />
</template>
<SkeletonDescriptor v-if="!entity" />
</div>
<QInnerLoading :label="t('globals.pleaseWait')" :showing="!entity" color="primary" />
</template>
<style lang="scss">
.body {
background-color: var(--vn-section-color);
.text-h5 {
font-size: 20px;
padding-top: 5px;
padding-bottom: 0px;
}
.q-item {
min-height: 20px;
.link {
margin-left: 10px;
}
}
.vn-label-value {
display: flex;
padding: 0px 16px;
.label {
color: var(--vn-label-color);
font-size: 14px;
&:not(:has(a))::after {
content: ':';
}
}
.value {
color: var(--vn-text-color);
font-size: 14px;
margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.info {
margin-left: 5px;
}
}
}
</style>
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;
span {
color: var(--vn-text-color);
font-weight: bold;
}
}
.subtitle {
color: var(--vn-text-color);
font-size: 16px;
margin-bottom: 2px;
}
.list-box {
.q-item__label {
color: var(--vn-label-color);
padding-bottom: 0%;
}
}
.descriptor {
width: 256px;
.header {
display: flex;
align-items: center;
}
.icons {
margin: 0 10px;
display: flex;
justify-content: center;
.q-icon {
margin-right: 5px;
}
}
.actions {
margin: 0 5px;
justify-content: center !important;
}
}
</style>
<i18n>
en:
globals:
copyId: Copy ID
es:
globals:
copyId: Copiar ID
</i18n>

View File

@ -249,7 +249,7 @@ const getLocale = (label) => {
:key="chip.label"
:removable="!unremovableParams?.includes(chip.label)"
@remove="remove(chip.label)"
data-cy="vnFilterPanelChip"
:data-cy="`vnFilterPanelChip_${chip.label}`"
>
<slot
name="tags"

View File

@ -28,7 +28,7 @@ function copyValueText() {
const val = computed(() => $props.value);
</script>
<template>
<div class="vn-label-value">
<div class="vn-label-value" :data-cy="`${$attrs['data-cy'] ?? 'vnLv'}${label ?? ''}`">
<QCheckbox
v-if="typeof value === 'boolean'"
v-model="val"

View File

@ -12,7 +12,7 @@
{{ $t('components.cardDescriptor.moreOptions') }}
</QTooltip>
<QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
<QList>
<QList data-cy="descriptor-more-opts_list">
<slot name="menu" :menu-ref="$refs.menuRef" />
</QList>
</QMenu>

View File

@ -44,6 +44,11 @@ const quasar = useQuasar();
const newNote = reactive({ text: null, observationTypeFk: null });
const observationTypes = ref([]);
const vnPaginateRef = ref();
const defaultObservationType = computed(
() => observationTypes.value.find((ot) => ot.code === 'salesPerson')?.id,
);
let originalText;
const observationTypeFk = ref([]);
const selectedFilters = ref({});
@ -120,6 +125,13 @@ function fetchData([data]) {
emit('onFetch', data);
}
const handleObservationTypes = (data) => {
observationTypes.value = data;
if (defaultObservationType.value) {
newNote.observationTypeFk = defaultObservationType.value;
}
};
const setWorkerObservations = (data) => {
const seen = new Set();
filteredWorkers.value = data;
@ -181,9 +193,9 @@ onUnmounted(() => {
<FetchData
v-if="selectType"
url="ObservationTypes"
:filter="{ fields: ['id', 'description'] }"
:filter="{ fields: ['id', 'description', 'code'] }"
jon marked this conversation as resolved Outdated
Outdated
Review

Esto no deberia estar en un componente generico, VnNotes se usa en claim, worker, etc

Esto no deberia estar en un componente generico, VnNotes se usa en claim, worker, etc
auto-load
@on-fetch="(data) => (observationTypes = data)"
@on-fetch="handleObservationTypes"
/>
<FetchData
v-if="justInput"
@ -276,6 +288,7 @@ onUnmounted(() => {
filled
size="lg"
autogrow
autofocus
@keyup.enter.stop="handleClick"
:required="isRequired"
clearable
@ -310,10 +323,7 @@ onUnmounted(() => {
class="show"
v-bind="$attrs"
:search-url="false"
@on-fetch="
newNote.text = '';
newNote.observationTypeFk = null;
"
@on-fetch="newNote.text = ''"
>
<template #body="{ rows }">
<TransitionGroup name="list" tag="div" class="column items-center full-width">

View File

@ -26,6 +26,7 @@ const id = props.entityId;
:to="{ name: routeName, params: { id: id } }"
class="header link"
:href="url"
data-cy="goToSummaryBtn"
>
<QIcon name="open_in_new" color="white" size="sm" />
</router-link>

View File

@ -6,10 +6,12 @@ const session = useSession();
const token = session.getToken();
describe('downloadFile', () => {
const baseUrl = 'http://localhost:9000';
let defaulCreateObjectURL;
beforeAll(() => {
vi.mock('src/composables/getUrl', () => ({
getUrl: vi.fn().mockResolvedValue(''),
}));
defaulCreateObjectURL = window.URL.createObjectURL;
window.URL.createObjectURL = vi.fn(() => 'blob:http://localhost:9000/blob-id');
});
@ -22,15 +24,14 @@ describe('downloadFile', () => {
headers: { 'content-disposition': 'attachment; filename="test-file.txt"' },
};
vi.spyOn(axios, 'get').mockImplementation((url) => {
if (url == 'Urls/getUrl') return Promise.resolve({ data: baseUrl });
else if (url.includes('downloadFile')) return Promise.resolve(res);
if (url.includes('downloadFile')) return Promise.resolve(res);
});
await downloadFile(1);
expect(axios.get).toHaveBeenCalledWith(
`${baseUrl}/api/dms/1/downloadFile?access_token=${token}`,
{ responseType: 'blob' }
`/api/dms/1/downloadFile?access_token=${token}`,
{ responseType: 'blob' },
);
});
});

View File

@ -7,18 +7,33 @@ const { getTokenMultimedia } = useSession();
const token = getTokenMultimedia();
export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile', url) {
const appUrl = (await getUrl('', 'lilium')).replace('/#/', '');
const appUrl = await getAppUrl();
const response = await axios.get(
url ?? `${appUrl}/api/${model}/${id}${urlPath}?access_token=${token}`,
{ responseType: 'blob' }
{ responseType: 'blob' },
);
download(response);
}
export async function downloadDocuware(url, params) {
const appUrl = await getAppUrl();
const response = await axios.get(`${appUrl}/api/` + url, {
responseType: 'blob',
params,
});
download(response);
}
function download(response) {
const contentDisposition = response.headers['content-disposition'];
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(contentDisposition);
const filename =
matches != null && matches[1]
? matches[1].replace(/['"]/g, '')
: 'downloaded-file';
const filename = matches?.[1] ? matches[1].replace(/['"]/g, '') : 'downloaded-file';
exportFile(filename, response.data);
}
async function getAppUrl() {
return (await getUrl('', 'lilium')).replace('/#/', '');
}

View File

@ -325,7 +325,6 @@ input::-webkit-inner-spin-button {
min-height: auto !important;
display: flex;
align-items: flex-end;
padding-bottom: 2px;
.q-field__native.row {
min-height: auto !important;
}

View File

@ -646,6 +646,7 @@ worker:
model: Model
serialNumber: Serial number
removePDA: Deallocate PDA
sendToTablet: Send to tablet
create:
lastName: Last name
birth: Birth
@ -816,6 +817,7 @@ travel:
search: Search travel
searchInfo: You can search by travel id or name
id: Id
awbFk: AWB
travelList:
tableVisibleColumns:
ref: Reference
@ -892,6 +894,8 @@ components:
VnLv:
copyText: '{copyValue} has been copied to the clipboard'
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
VnNotes:
clientWithoutPhone: 'The following clients do not have a phone number and the message will not be sent to them: {clientWithoutPhone}'
weekdays:
sun: Sunday
mon: Monday

View File

@ -731,6 +731,7 @@ worker:
model: Modelo
serialNumber: Número de serie
removePDA: Desasignar PDA
sendToTablet: Enviar a la tablet
create:
lastName: Apellido
birth: Fecha de nacimiento
@ -899,6 +900,7 @@ travel:
search: Buscar envío
searchInfo: Buscar envío por id o nombre
id: Id
awbFk: Guía aérea
travelList:
tableVisibleColumns:
ref: Referencia
@ -976,6 +978,8 @@ components:
VnLv:
copyText: '{copyValue} se ha copiado al portapepeles'
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
VnNotes:
clientWithoutPhone: 'Estos clientes no tienen asociado número de télefono y el sms no les será enviado: {clientWithoutPhone}'
weekdays:
sun: Domingo
mon: Lunes

View File

@ -47,7 +47,7 @@ const rolesOptions = ref([]);
:label="t('globals.name')"
v-model="params.name"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -57,7 +57,7 @@ const rolesOptions = ref([]);
:label="t('account.card.alias')"
v-model="params.nickname"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -75,8 +75,7 @@ const rolesOptions = ref([]);
use-input
hide-selected
dense
outlined
rounded
filled
:input-debounce="0"
/>
</QItemSection>

View File

@ -56,8 +56,7 @@ onBeforeMount(() => {
option-label="name"
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -72,8 +71,7 @@ onBeforeMount(() => {
option-label="name"
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -83,7 +81,7 @@ onBeforeMount(() => {
:label="t('acls.aclFilter.property')"
v-model="params.property"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -98,8 +96,7 @@ onBeforeMount(() => {
option-label="name"
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -114,8 +111,7 @@ onBeforeMount(() => {
option-label="name"
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>

View File

@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import axios from 'axios';
@ -48,11 +48,12 @@ const removeAlias = () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`MailAliases/${entityId}`"
data-key="Alias"
title="alias"
:to-module="{ name: 'AccountAlias' }"
>
<template #menu>
<QItem v-ripple clickable @click="removeAlias()">
@ -62,7 +63,7 @@ const removeAlias = () => {
<template #body="{ entity }">
<VnLv :label="t('role.description')" :value="entity.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
import VnImg from 'src/components/ui/VnImg.vue';
@ -20,7 +20,7 @@ onMounted(async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`VnUsers/preview`"
:filter="{ ...filter, where: { id: entityId } }"
@ -78,7 +78,7 @@ onMounted(async () => {
</QIcon>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -0,0 +1,14 @@
<script setup>
import AccountDescriptor from './AccountDescriptor.vue';
import AccountSummary from './AccountSummary.vue';
</script>
<template>
<QPopupProxy style="max-width: 10px">
<AccountDescriptor
v-if="$attrs.id"
v-bind="$attrs.id"
:summary="AccountSummary"
:proxy-render="true"
/>
</QPopupProxy>
</template>

View File

@ -18,7 +18,7 @@ const entityId = computed(() => $props.id || route.params.id);
data-key="Account"
ref="AccountSummary"
url="VnUsers/preview"
:filter="filter"
:filter="{ ...filter, where: { id: entityId } }"
>
<template #header="{ entity }">{{ entity.id }} - {{ entity.nickname }}</template>
<template #menu>

View File

@ -27,7 +27,7 @@ const props = defineProps({
:label="t('globals.name')"
v-model="params.name"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -37,7 +37,7 @@ const props = defineProps({
:label="t('role.description')"
v-model="params.description"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
@ -32,11 +32,12 @@ const removeRole = async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
url="VnRoles"
:filter="{ where: { id: entityId } }"
data-key="Role"
:summary="$props.summary"
:to-module="{ name: 'AccountRoles' }"
>
<template #menu>
<QItem v-ripple clickable @click="removeRole()">
@ -46,7 +47,7 @@ const removeRole = async () => {
<template #body="{ entity }">
<VnLv :label="t('role.description')" :value="entity.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -2,6 +2,7 @@
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { getDifferences, getUpdatedValues } from 'src/filters';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
import FetchData from 'components/FetchData.vue';
@ -9,12 +10,18 @@ import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnAvatar from 'src/components/ui/VnAvatar.vue';
const route = useRoute();
const { t } = useI18n();
const workersOptions = ref([]);
function onBeforeSave(formData, originalData) {
return getUpdatedValues(
Object.keys(getDifferences(formData, originalData)),
formData,
);
}
</script>
<template>
<FetchData
@ -27,6 +34,7 @@ const workersOptions = ref([]);
<FormModel
model="Claim"
:url-update="`Claims/updateClaim/${route.params.id}`"
:mapper="onBeforeSave"
auto-load
>
<template #form="{ data, validate }">

View File

@ -6,7 +6,7 @@ import { toDateHourMinSec, toPercentage } from 'src/filters';
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { getUrl } from 'src/composables/getUrl';
@ -44,7 +44,7 @@ onMounted(async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Claims/${entityId}`"
:filter="filter"
title="client.name"
@ -147,7 +147,7 @@ onMounted(async () => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -0,0 +1,14 @@
<script setup>
import ClaimDescriptor from './ClaimDescriptor.vue';
import ClaimSummary from './ClaimSummary.vue';
</script>
<template>
<QPopupProxy style="max-width: 10px">
<ClaimDescriptor
v-if="$attrs.id"
v-bind="$attrs.id"
:summary="ClaimSummary"
:proxy-render="true"
/>
</QPopupProxy>
</template>

View File

@ -33,7 +33,7 @@ const props = defineProps({
:label="t('claim.customerId')"
v-model="params.clientFk"
lazy-rules
is-outlined
filled
>
<template #prepend> <QIcon name="badge" size="xs" /></template>
</VnInput>
@ -41,12 +41,11 @@ const props = defineProps({
:label="t('Client Name')"
v-model="params.clientName"
lazy-rules
is-outlined
filled
/>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
@ -61,8 +60,7 @@ const props = defineProps({
:use-like="false"
option-filter="firstName"
dense
outlined
rounded
filled
/>
<VnSelect
:label="t('claim.state')"
@ -70,14 +68,12 @@ const props = defineProps({
:options="states"
option-label="description"
dense
outlined
rounded
filled
/>
<VnInputDate
v-model="params.created"
:label="t('claim.created')"
outlined
rounded
filled
dense
/>
<VnSelect
@ -86,8 +82,7 @@ const props = defineProps({
url="Items/withName"
:use-like="false"
sort-by="id DESC"
outlined
rounded
filled
dense
/>
<VnSelect
@ -98,15 +93,13 @@ const props = defineProps({
:use-like="false"
option-filter="firstName"
dense
outlined
rounded
filled
/>
<VnSelect
:label="t('claim.zone')"
v-model="params.zoneFk"
url="Zones"
outlined
rounded
filled
dense
/>
<QCheckbox

View File

@ -7,7 +7,7 @@ import { toCurrency, toDate } from 'src/filters';
import useCardDescription from 'src/composables/useCardDescription';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
@ -54,7 +54,7 @@ const debtWarning = computed(() => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Clients/${entityId}/getCard`"
:summary="$props.summary"
data-key="Customer"
@ -232,7 +232,7 @@ const debtWarning = computed(() => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -41,7 +41,7 @@ const exprBuilder = (param, value) => {
<template #body="{ params, searchFn }">
<QItem class="q-my-sm">
<QItemSection>
<VnInput :label="t('FI')" v-model="params.fi" is-outlined>
<VnInput :label="t('FI')" v-model="params.fi" filled>
<template #prepend>
<QIcon name="badge" size="xs" />
</template>
@ -50,7 +50,7 @@ const exprBuilder = (param, value) => {
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnInput :label="t('Name')" v-model="params.name" is-outlined />
<VnInput :label="t('Name')" v-model="params.name" filled />
</QItemSection>
</QItem>
<QItem class="q-mb-sm">
@ -58,16 +58,15 @@ const exprBuilder = (param, value) => {
<VnInput
:label="t('customer.summary.socialName')"
v-model="params.socialName"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
@ -89,8 +88,7 @@ const exprBuilder = (param, value) => {
map-options
hide-selected
dense
outlined
rounded
filled
auto-load
:input-debounce="0"
/>
@ -98,12 +96,12 @@ const exprBuilder = (param, value) => {
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnInput :label="t('City')" v-model="params.city" is-outlined />
<VnInput :label="t('City')" v-model="params.city" filled />
</QItemSection>
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnInput :label="t('Phone')" v-model="params.phone" is-outlined>
<VnInput :label="t('Phone')" v-model="params.phone" filled>
<template #prepend>
<QIcon name="phone" size="xs" />
</template>
@ -112,7 +110,7 @@ const exprBuilder = (param, value) => {
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnInput :label="t('Email')" v-model="params.email" is-outlined>
<VnInput :label="t('Email')" v-model="params.email" filled>
<template #prepend>
<QIcon name="email" size="sm" />
</template>
@ -132,19 +130,14 @@ const exprBuilder = (param, value) => {
map-options
hide-selected
dense
outlined
rounded
filled
auto-load
sortBy="name ASC"
/></QItemSection>
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnInput
:label="t('Postcode')"
v-model="params.postcode"
is-outlined
/>
<VnInput :label="t('Postcode')" v-model="params.postcode" filled />
</QItemSection>
</QItem>
</template>

View File

@ -45,8 +45,7 @@ const departments = ref();
dense
option-label="name"
option-value="id"
outlined
rounded
filled
emit-value
hide-selected
map-options
@ -67,8 +66,7 @@ const departments = ref();
map-options
option-label="name"
option-value="id"
outlined
rounded
filled
use-input
v-model="params.departmentFk"
@update:model-value="searchFn()"
@ -91,8 +89,7 @@ const departments = ref();
map-options
option-label="name"
option-value="id"
outlined
rounded
filled
use-input
v-model="params.countryFk"
@update:model-value="searchFn()"
@ -108,7 +105,7 @@ const departments = ref();
<VnInput
:label="t('P. Method')"
clearable
is-outlined
filled
v-model="params.paymentMethod"
/>
</QItemSection>
@ -119,7 +116,7 @@ const departments = ref();
<VnInput
:label="t('Balance D.')"
clearable
is-outlined
filled
v-model="params.balance"
/>
</QItemSection>
@ -137,8 +134,7 @@ const departments = ref();
map-options
option-label="name"
option-value="id"
outlined
rounded
filled
use-input
v-model="params.workerFk"
@update:model-value="searchFn()"
@ -154,7 +150,7 @@ const departments = ref();
<VnInputDate
:label="t('L. O. Date')"
clearable
is-outlined
filled
v-model="params.date"
/>
</QItemSection>
@ -165,7 +161,7 @@ const departments = ref();
<VnInput
:label="t('Credit I.')"
clearable
is-outlined
filled
v-model="params.credit"
/>
</QItemSection>
@ -175,7 +171,7 @@ const departments = ref();
<QItemSection>
<VnInputDate
:label="t('From')"
is-outlined
filled
v-model="params.defaulterSinced"
/>
</QItemSection>

View File

@ -25,7 +25,7 @@ const props = defineProps({
<template #body="{ params }">
<QItem>
<QItemSection>
<VnInput :label="t('Order ID')" v-model="params.orderFk" is-outlined>
<VnInput :label="t('Order ID')" v-model="params.orderFk" filled>
<template #prepend>
<QIcon name="vn:basket" size="xs" />
</template>
@ -34,11 +34,7 @@ const props = defineProps({
</QItem>
<QItem>
<QItemSection>
<VnInput
:label="t('Customer ID')"
v-model="params.clientFk"
is-outlined
>
<VnInput :label="t('Customer ID')" v-model="params.clientFk" filled>
<template #prepend>
<QIcon name="vn:client" size="xs" />
</template>
@ -47,19 +43,15 @@ const props = defineProps({
</QItem>
<QItem>
<QItemSection>
<VnInputNumber
:label="t('Amount')"
v-model="params.amount"
is-outlined
/>
<VnInputNumber :label="t('Amount')" v-model="params.amount" filled />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate v-model="params.from" :label="t('From')" is-outlined />
<VnInputDate v-model="params.from" :label="t('From')" filled />
</QItemSection>
<QItemSection>
<VnInputDate v-model="params.to" :label="t('To')" is-outlined />
<VnInputDate v-model="params.to" :label="t('To')" filled />
</QItemSection>
</QItem>
</template>

View File

@ -14,6 +14,8 @@ import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import VnDmsInput from 'src/components/common/VnDmsInput.vue';
const route = useRoute();
const { t } = useI18n();
@ -24,6 +26,7 @@ const user = state.getUser().fn();
const companiesOptions = ref([]);
const currenciesOptions = ref([]);
const entryRef = ref({});
onMounted(() => {
checkEntryLock(route.params.id, user.id);
@ -48,10 +51,11 @@ onMounted(() => {
auto-load
/>
<FormModel
:url-update="`Entries/${route.params.id}`"
ref="entryRef"
model="Entry"
auto-load
:url-update="`Entries/${route.params.id}`"
:clear-store-on-unmount="false"
auto-load
>
<template #form="{ data }">
<VnRow class="q-py-sm">
@ -67,11 +71,18 @@ onMounted(() => {
/>
</VnRow>
<VnRow class="q-py-sm">
<VnInput v-model="data.reference" :label="t('globals.reference')" />
<VnInputNumber
v-model="data.invoiceAmount"
:label="t('entry.summary.invoiceAmount')"
:positive="false"
<VnInput
v-model="data.reference"
:label="t('entry.list.tableVisibleColumns.reference')"
/>
<VnSelect
v-model="data.typeFk"
url="entryTypes"
:fields="['code', 'description']"
option-value="code"
optionLabel="description"
sortBy="description"
:label="t('entry.list.tableVisibleColumns.entryTypeDescription')"
/>
</VnRow>
<VnRow class="q-py-sm">
@ -113,7 +124,6 @@ onMounted(() => {
name="initialTemperature"
:label="t('entry.basicData.initialTemperature')"
:step="0.5"
:decimal-places="2"
:positive="false"
/>
<VnInputNumber
@ -121,20 +131,21 @@ onMounted(() => {
name="finalTemperature"
:label="t('entry.basicData.finalTemperature')"
:step="0.5"
:decimal-places="2"
:positive="false"
/>
<VnSelect
v-model="data.typeFk"
url="entryTypes"
:fields="['code', 'description']"
option-value="code"
optionLabel="description"
sortBy="description"
/>
</VnRow>
<VnRow class="q-py-sm">
<QInput
<VnInputNumber
v-model="data.invoiceAmount"
:label="t('entry.list.tableVisibleColumns.invoiceAmount')"
:positive="false"
@update:model-value="data.buyerFk = user.id"
/>
<VnSelectWorker v-model="data.buyerFk" hide-selected />
<VnDmsInput :data="data" :formRef="entryRef" :disable="false" />
</VnRow>
<VnRow class="q-py-sm">
<VnInputNumber
:label="t('entry.basicData.observation')"
type="textarea"
v-model="data.observation"

View File

@ -18,6 +18,7 @@ import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
import { checkEntryLock } from 'src/composables/checkEntryLock';
import VnRow from 'src/components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
const $props = defineProps({
id: {
@ -44,6 +45,8 @@ const entityId = ref($props.id ?? route.params.id);
const entryBuysRef = ref();
const footerFetchDataRef = ref();
const footer = ref({});
const dialogRef = ref(false);
const newEntryRef = ref(null);
const columns = [
{
align: 'center',
@ -250,6 +253,7 @@ const columns = [
component: 'number',
attrs: {
positive: false,
decimalPlaces: 3,
},
cellEvent: {
'update:modelValue': async (value, oldValue, row) => {
@ -497,6 +501,23 @@ async function setBuyUltimate(itemFk, data) {
});
}
async function transferBuys(rows, newEntry) {
if (!newEntry) return;
const promises = rows.map((row) => {
return axios.patch('Buys', { id: row.id, entryFk: newEntry });
});
await Promise.all(promises);
await axios.post(`Entries/${newEntry}/recalcEntryPrices`);
await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);
entryBuysRef.value.reload();
newEntryRef.value = null;
dialogRef.value = false;
}
onMounted(() => {
stateStore.rightDrawer = false;
if ($props.editableMode) checkEntryLock(entityId.value, user.id);
@ -571,6 +592,47 @@ onMounted(() => {
</QItem>
</QList>
</QBtnDropdown>
<QBtn
icon="move_group"
color="primary"
:title="t('Transfer buys')"
data-cy="transferBuys"
flat
@click="dialogRef = true"
:disable="!selectedRows.length"
/>
<QDialog v-model="dialogRef">
<QCard>
<QCardSection>
<span>{{ t('Transfer buys') }}</span>
</QCardSection>
<QCardSection>
<VnInputNumber
v-model="newEntryRef"
:label="t('Entry')"
type="number"
data-cy="entryDestinyInput"
/>
</QCardSection>
<QCardSection>
<QCardActions>
<QBtn
label="Cancel"
flat
color="primary"
@click="dialogRef = false"
/>
<QBtn
label="Transfer"
data-cy="transferBuysBtn"
flat
color="primary"
@click="transferBuys(selectedRows, newEntryRef)"
/>
</QCardActions>
</QCardSection>
</QCard>
</QDialog>
</QBtnGroup>
</Teleport>
<FetchData
@ -620,7 +682,7 @@ onMounted(() => {
},
columnGridStyle: {
'max-width': '50%',
'margin-right': '30px',
'margin-right': '5%',
flex: 1,
},
previousStyle: {
@ -652,6 +714,7 @@ onMounted(() => {
:fields="['id', 'nickname']"
option-label="nickname"
sort-by="nickname ASC"
:use-like="false"
/>
<VnSelect
:label="t('Family')"
@ -816,6 +879,8 @@ es:
Create buy: Crear compra
Invert quantity value: Invertir valor de cantidad
Check buy amount: Marcar como correcta la cantidad de compra
Transfer buys: Transferir compras
Entry: Entrada
</i18n>
<style lang="scss" scoped>
.centered-container {

View File

@ -6,7 +6,7 @@ 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 EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
import axios from 'axios';
@ -92,7 +92,7 @@ const getEntryRedirectionFilter = (entry) => {
};
function showEntryReport() {
openReport(`Entries/${entityId.value}/entry-order-pdf`);
openReport(`Entries/${entityId.value}/entry-order-pdf`, {}, true);
}
function showNotification(type, message) {
@ -145,9 +145,9 @@ async function deleteEntry() {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Entries/${entityId}`"
:filter="entryFilter"
:user-filter="entryFilter"
title="supplier.nickname"
data-key="Entry"
width="lg-width"
@ -264,7 +264,7 @@ async function deleteEntry() {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -84,7 +84,10 @@ onMounted(async () => {
:label="t('globals.company')"
:value="entry?.company?.code"
/>
<VnLv :label="t('globals.reference')" :value="entry?.reference" />
<VnLv
:label="t('entry.list.tableVisibleColumns.reference')"
:value="entry?.reference"
/>
<VnLv
:label="t('entry.summary.invoiceNumber')"
:value="entry?.invoiceNumber"
@ -159,6 +162,7 @@ onMounted(async () => {
/>
</div>
<div class="card-content">
<VnLv :label="t('travel.awbFk')" :value="entry.travel.awbFk" />
<VnCheckbox
:label="t('entry.summary.travelDelivered')"
v-model="entry.travel.isDelivered"

View File

@ -101,14 +101,14 @@ const entryFilterPanel = ref();
:label="t('params.landed')"
v-model="params.landed"
@update:model-value="searchFn()"
is-outlined
filled
data-cy="landed"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput v-model="params.id" label="Id" is-outlined />
<VnInput v-model="params.id" label="Id" filled />
</QItemSection>
</QItem>
<QItem>
@ -118,8 +118,7 @@ const entryFilterPanel = ref();
@update:model-value="searchFn()"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -128,7 +127,7 @@ const entryFilterPanel = ref();
<VnInput
v-model="params.reference"
:label="t('entry.list.tableVisibleColumns.reference')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -143,8 +142,7 @@ const entryFilterPanel = ref();
:fields="['id', 'name']"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -153,7 +151,7 @@ const entryFilterPanel = ref();
<VnInput
v-model="params.evaNotes"
:label="t('params.evaNotes')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -168,8 +166,7 @@ const entryFilterPanel = ref();
sort-by="name ASC"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -184,8 +181,7 @@ const entryFilterPanel = ref();
sort-by="name ASC"
hide-selected
dense
outlined
rounded
filled
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
@ -207,7 +203,7 @@ const entryFilterPanel = ref();
<VnInput
v-model="params.invoiceNumber"
:label="t('params.invoiceNumber')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -224,8 +220,16 @@ const entryFilterPanel = ref();
option-label="description"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
v-model="params.evaNotes"
:label="t('params.evaNotes')"
filled
/>
</QItemSection>
</QItem>

View File

@ -162,8 +162,8 @@ async function beforeSave(data, getChanges) {
}
await Promise.all(patchPromises);
const filteredChanges = changes.filter((change) => change?.isReal !== false);
data.creates = filteredChanges;
data.creates = [];
return data;
}
</script>
<template>
@ -203,7 +203,7 @@ async function beforeSave(data, getChanges) {
</VnRow>
</template>
</VnSubToolbar>
<QDialog v-model="travelDialogRef" :maximized="true" :class="['vn-row', 'wrap']">
<QDialog v-model="travelDialogRef" :class="['vn-row', 'wrap']">
<FormModelPopup
:url-update="`Travels/${travel?.id}`"
model="travel"
@ -252,12 +252,15 @@ async function beforeSave(data, getChanges) {
</span>
</template>
<template #column-footer-reserve>
<span>
<span class="q-pr-xs">
{{ round(footer.reserve) }}
</span>
</template>
<template #column-footer-bought>
<span :style="boughtStyle(footer?.bought, footer?.reserve)">
<span
:style="boughtStyle(footer?.bought, footer?.reserve)"
class="q-pr-xs"
>
{{ round(footer.bought) }}
</span>
</template>
@ -275,7 +278,7 @@ async function beforeSave(data, getChanges) {
}
.column {
min-width: 35%;
margin-top: 5%;
margin-top: 1%;
}
.text-negative {
color: $negative !important;

View File

@ -25,7 +25,7 @@ entry:
entryTypeDescription: Tipo entrada
invoiceAmount: Importe
dated: Fecha
inventoryEntry: Es inventario
inventoryEntry: Es inventario
summary:
commission: Comisión
currency: Moneda
@ -33,7 +33,8 @@ entry:
invoiceAmount: Importe
ordered: Pedida
booked: Contabilizada
excludedFromAvailable: Excluido
excludedFromAvailable: Excluir del disponible
isConfirmed: Lista para etiquetar
travelReference: Referencia
travelAgency: Agencia
travelShipped: F. envio
@ -56,7 +57,7 @@ entry:
observation: Observación
commission: Comisión
booked: Contabilizada
excludedFromAvailable: Excluido
excludedFromAvailable: Excluir del disponible
initialTemperature: Ini °C
finalTemperature: Fin °C
buys:
@ -119,9 +120,9 @@ entry:
supplierName: Proveedor
entryFilter:
params:
isExcludedFromAvailable: Excluido
isExcludedFromAvailable: Excluir del disponible
isOrdered: Pedida
isConfirmed: Confirmado
isConfirmed: Lista para etiquetar
isReceived: Recibida
isRaid: Raid
landed: Fecha

View File

@ -121,25 +121,40 @@ function deleteFile(dmsFk) {
hide-selected
:is-clearable="false"
:required="true"
data-cy="invoiceInBasicDataSupplier"
/>
<VnInput
clearable
clear-icon="close"
:label="t('invoiceIn.supplierRef')"
v-model="data.supplierRef"
data-cy="invoiceInBasicDataSupplierRef"
/>
</VnRow>
<VnRow>
<VnInputDate :label="t('Expedition date')" v-model="data.issued" />
<VnInputDate
:label="t('Expedition date')"
v-model="data.issued"
data-cy="invoiceInBasicDataIssued"
/>
<VnInputDate
:label="t('Operation date')"
v-model="data.operated"
autofocus
data-cy="invoiceInBasicDataOperated"
/>
</VnRow>
<VnRow>
<VnInputDate :label="t('Entry date')" v-model="data.bookEntried" />
<VnInputDate :label="t('Accounted date')" v-model="data.booked" />
<VnInputDate
:label="t('Entry date')"
v-model="data.bookEntried"
data-cy="invoiceInBasicDatabookEntried"
/>
<VnInputDate
:label="t('Accounted date')"
v-model="data.booked"
data-cy="invoiceInBasicDataBooked"
/>
</VnRow>
<VnRow>
<VnSelect
@ -149,7 +164,7 @@ function deleteFile(dmsFk) {
option-value="id"
option-label="id"
:filter-options="['id', 'name']"
data-cy="UnDeductibleVatSelect"
data-cy="invoiceInBasicDataDeductibleExpenseFk"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
@ -182,6 +197,7 @@ function deleteFile(dmsFk) {
padding="xs"
round
@click="downloadFile(data.dmsFk)"
data-cy="invoiceInBasicDataDmsDownload"
/>
<QBtn
:class="{
@ -197,6 +213,7 @@ function deleteFile(dmsFk) {
documentDialogRef.dms = data.dms;
}
"
data-cy="invoiceInBasicDataDmsEdit"
>
<QTooltip>{{ t('Edit document') }}</QTooltip>
</QBtn>
@ -210,6 +227,7 @@ function deleteFile(dmsFk) {
padding="xs"
round
@click="deleteFile(data.dmsFk)"
data-cy="invoiceInBasicDataDmsDelete"
/>
</div>
<QBtn
@ -224,7 +242,7 @@ function deleteFile(dmsFk) {
delete documentDialogRef.dms;
}
"
data-cy="dms-create"
data-cy="invoiceInBasicDataDmsAdd"
>
<QTooltip>{{ t('Create document') }}</QTooltip>
</QBtn>
@ -237,9 +255,9 @@ function deleteFile(dmsFk) {
:label="t('Currency')"
v-model="data.currencyFk"
:options="currencies"
option-value="id"
option-label="code"
sort-by="id"
data-cy="invoiceInBasicDataCurrencyFk"
/>
<VnSelect
@ -249,8 +267,8 @@ function deleteFile(dmsFk) {
:label="t('Company')"
v-model="data.companyFk"
:options="companies"
option-value="id"
option-label="code"
data-cy="invoiceInBasicDataCompanyFk"
/>
</VnRow>
<VnRow>
@ -260,6 +278,7 @@ function deleteFile(dmsFk) {
:options="sageWithholdings"
option-value="id"
option-label="withholding"
data-cy="invoiceInBasicDataWithholdingSageFk"
/>
</VnRow>
</template>

View File

@ -1,22 +1,16 @@
<script setup>
import { ref, computed, capitalize } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'src/composables/useArrayData';
import CrudModel from 'src/components/CrudModel.vue';
import FetchData from 'src/components/FetchData.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
const route = useRoute();
const { t } = useI18n();
const arrayData = useArrayData();
const invoiceIn = computed(() => arrayData.store.data);
const invoiceInCorrectionRef = ref();
const filter = {
include: { relation: 'invoiceIn' },
where: { correctingFk: route.params.id },
};
const columns = computed(() => [
{
name: 'origin',
@ -92,7 +86,8 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
v-if="invoiceIn"
data-key="InvoiceInCorrection"
url="InvoiceInCorrections"
:filter="filter"
:user-filter="{ include: { relation: 'invoiceIn' } }"
:filter="{ where: { correctingFk: $route.params.id } }"
auto-load
primary-key="correctingFk"
:default-remove="false"
@ -115,6 +110,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
:option-label="col.optionLabel"
:disable="row.invoiceIn.isBooked"
:filter-options="['description']"
data-cy="invoiceInCorrective_type"
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps">
@ -137,6 +133,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
:rules="[requiredFieldRule]"
:filter-options="['code', 'description']"
:disable="row.invoiceIn.isBooked"
data-cy="invoiceInCorrective_class"
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps">
@ -161,6 +158,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
:option-label="col.optionLabel"
:rules="[requiredFieldRule]"
:disable="row.invoiceIn.isBooked"
data-cy="invoiceInCorrective_reason"
/>
</QTd>
</template>

View File

@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { toCurrency, toDate } from 'src/filters';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import filter from './InvoiceInFilter.js';
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
@ -17,10 +17,6 @@ const { t } = useI18n();
const cardDescriptorRef = ref();
const entityId = computed(() => $props.id || +currentRoute.value.params.id);
const totalAmount = ref();
const config = ref();
const cplusRectificationTypes = ref([]);
const siiTypeInvoiceIns = ref([]);
const invoiceCorrectionTypes = ref([]);
const invoiceInCorrection = reactive({ correcting: [], corrected: null });
const routes = reactive({
getSupplier: (id) => {
@ -30,7 +26,7 @@ const routes = reactive({
return {
name: 'InvoiceInList',
query: {
params: JSON.stringify({ supplierFk: id }),
table: JSON.stringify({ supplierFk: id }),
},
};
},
@ -39,7 +35,7 @@ const routes = reactive({
return {
name: 'InvoiceInList',
query: {
params: JSON.stringify({ correctedFk: entityId.value }),
table: JSON.stringify({ correctedFk: entityId.value }),
},
};
}
@ -88,7 +84,7 @@ async function setInvoiceCorrection(id) {
}
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="cardDescriptorRef"
data-key="InvoiceIn"
:url="`InvoiceIns/${entityId}`"
@ -108,7 +104,7 @@ async function setInvoiceCorrection(id) {
<VnLv :label="t('invoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
<VnLv :label="t('invoiceIn.list.supplier')">
<template #value>
<span class="link">
<span class="link" data-cy="invoiceInDescriptor_supplier">
{{ entity?.supplier?.nickname }}
<SupplierDescriptorProxy :id="entity?.supplierFk" />
</span>
@ -163,7 +159,7 @@ async function setInvoiceCorrection(id) {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style lang="scss" scoped>
.q-dialog {

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, computed, toRefs, reactive } from 'vue';
import { ref, computed, toRefs, reactive, onBeforeMount } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
@ -111,10 +111,9 @@ async function cloneInvoice() {
}
const isAgricultural = () => {
if (!config.value) return false;
return (
invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
config?.value[0]?.sageWithholdingFk
invoiceIn.value?.supplier?.sageWithholdingFk ==
config.value?.sageFarmerWithholdingFk
);
};
function showPdfInvoice() {
@ -153,162 +152,183 @@ const createInvoiceInCorrection = async () => {
);
push({ path: `/invoice-in/${correctingId}/summary` });
};
onBeforeMount(async () => {
config.value = (
await axios.get('invoiceinConfigs/findOne', {
params: { fields: ['sageFarmerWithholdingFk'] },
})
).data;
});
</script>
<template>
<FetchData
url="InvoiceCorrectionTypes"
@on-fetch="(data) => (invoiceCorrectionTypes = data)"
auto-load
/>
<FetchData
url="CplusRectificationTypes"
@on-fetch="(data) => (cplusRectificationTypes = data)"
auto-load
/>
<FetchData
url="SiiTypeInvoiceIns"
:where="{ code: { like: 'R%' } }"
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
auto-load
/>
<FetchData
url="InvoiceInConfigs"
:where="{ fields: ['sageWithholdingFk'] }"
auto-load
@on-fetch="(data) => (config = data)"
/>
<InvoiceInToBook>
<template #content="{ book }">
<QItem
v-if="!invoice?.isBooked && canEditProp('toBook')"
v-ripple
clickable
@click="book(entityId)"
<template v-if="config">
<FetchData
url="InvoiceCorrectionTypes"
@on-fetch="(data) => (invoiceCorrectionTypes = data)"
auto-load
/>
<FetchData
url="CplusRectificationTypes"
@on-fetch="(data) => (cplusRectificationTypes = data)"
auto-load
/>
<FetchData
url="SiiTypeInvoiceIns"
:where="{ code: { like: 'R%' } }"
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
auto-load
/>
<InvoiceInToBook>
<template #content="{ book }">
<QItem
v-if="!invoice?.isBooked && canEditProp('toBook')"
v-ripple
clickable
@click="book(entityId)"
>
<QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
</QItem>
</template>
</InvoiceInToBook>
<QItem
v-if="invoice?.isBooked && canEditProp('toUnbook')"
v-ripple
clickable
@click="triggerMenu('unbook')"
>
<QItemSection>
{{ t('invoiceIn.descriptorMenu.unbook') }}
</QItemSection>
</QItem>
<QItem
v-if="canEditProp('deleteById')"
v-ripple
clickable
@click="triggerMenu('delete')"
>
<QItemSection>{{ t('invoiceIn.descriptorMenu.deleteInvoice') }}</QItemSection>
</QItem>
<QItem
v-if="canEditProp('clone')"
v-ripple
clickable
@click="triggerMenu('clone')"
>
<QItemSection>{{ t('invoiceIn.descriptorMenu.cloneInvoice') }}</QItemSection>
</QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
<QItemSection>{{
t('invoiceIn.descriptorMenu.showAgriculturalPdf')
}}</QItemSection>
</QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
<QItemSection
>{{ t('invoiceIn.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
>
<QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
</QItem>
</template>
</InvoiceInToBook>
<QItem
v-if="invoice?.isBooked && canEditProp('toUnbook')"
v-ripple
clickable
@click="triggerMenu('unbook')"
>
<QItemSection>
{{ t('invoiceIn.descriptorMenu.unbook') }}
</QItemSection>
</QItem>
<QItem
v-if="canEditProp('deleteById')"
v-ripple
clickable
@click="triggerMenu('delete')"
>
<QItemSection>{{ t('invoiceIn.descriptorMenu.deleteInvoice') }}</QItemSection>
</QItem>
<QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')">
<QItemSection>{{ t('invoiceIn.descriptorMenu.cloneInvoice') }}</QItemSection>
</QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
<QItemSection>{{
t('invoiceIn.descriptorMenu.showAgriculturalPdf')
}}</QItemSection>
</QItem>
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
<QItemSection
>{{ t('invoiceIn.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
</QItem>
<QItem
v-if="!invoiceInCorrection.corrected"
v-ripple
clickable
@click="triggerMenu('correct')"
data-cy="createCorrectiveItem"
>
</QItem>
<QItem
v-if="!invoiceInCorrection.corrected"
v-ripple
clickable
@click="triggerMenu('correct')"
data-cy="createCorrectiveItem"
>
<QItemSection
>{{ t('invoiceIn.descriptorMenu.createCorrective') }}...</QItemSection
<QItemSection
>{{ t('invoiceIn.descriptorMenu.createCorrective') }}...</QItemSection
>
</QItem>
<QItem
v-if="invoice.dmsFk"
v-ripple
clickable
@click="downloadFile(invoice.dmsFk)"
>
</QItem>
<QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)">
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
</QItem>
<QDialog ref="correctionDialogRef">
<QCard>
<QCardSection>
<QItem class="q-px-none">
<span class="text-primary text-h6 full-width">
{{ t('Create rectificative invoice') }}
</span>
<QBtn icon="close" flat round dense v-close-popup />
</QItem>
</QCardSection>
<QCardSection>
<QItem>
<QItemSection>
<QInput
:label="t('Original invoice')"
v-model="entityId"
readonly
/>
<VnSelect
:label="`${useCapitalize(t('globals.class'))}`"
v-model="correctionFormData.invoiceClass"
:options="siiTypeInvoiceIns"
option-value="id"
option-label="code"
:required="true"
/>
</QItemSection>
<QItemSection>
<VnSelect
:label="`${useCapitalize(t('globals.type'))}`"
v-model="correctionFormData.invoiceType"
:options="cplusRectificationTypes"
option-value="id"
option-label="description"
:required="true"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel
>{{ opt.id }} -
{{ opt.description }}</QItemLabel
>
</QItemSection>
</QItem>
<div></div>
</template>
</VnSelect>
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
</QItem>
<QDialog ref="correctionDialogRef">
<QCard data-cy="correctiveInvoiceDialog">
<QCardSection>
<QItem class="q-px-none">
<span class="text-primary text-h6 full-width">
{{ t('Create rectificative invoice') }}
</span>
<QBtn icon="close" flat round dense v-close-popup />
</QItem>
</QCardSection>
<QCardSection>
<QItem>
<QItemSection>
<QInput
:label="t('Original invoice')"
v-model="entityId"
readonly
/>
<VnSelect
:label="`${useCapitalize(t('globals.class'))}`"
v-model="correctionFormData.invoiceClass"
:options="siiTypeInvoiceIns"
option-value="id"
option-label="code"
:required="true"
data-cy="invoiceInDescriptorMenu_class"
/>
</QItemSection>
<QItemSection>
<VnSelect
:label="`${useCapitalize(t('globals.type'))}`"
v-model="correctionFormData.invoiceType"
:options="cplusRectificationTypes"
option-value="id"
option-label="description"
:required="true"
data-cy="invoiceInDescriptorMenu_type"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel
>{{ opt.id }} -
{{ opt.description }}</QItemLabel
>
</QItemSection>
</QItem>
<div></div>
</template>
</VnSelect>
<VnSelect
:label="`${useCapitalize(t('globals.reason'))}`"
v-model="correctionFormData.invoiceReason"
:options="invoiceCorrectionTypes"
option-value="id"
option-label="description"
:required="true"
/>
</QItemSection>
</QItem>
</QCardSection>
<QCardActions class="justify-end q-mr-sm">
<QBtn flat :label="t('globals.close')" color="primary" v-close-popup />
<QBtn
:label="t('globals.save')"
color="primary"
v-close-popup
@click="createInvoiceInCorrection"
:disable="isNotFilled"
/>
</QCardActions>
</QCard>
</QDialog>
<VnSelect
:label="`${useCapitalize(t('globals.reason'))}`"
v-model="correctionFormData.invoiceReason"
:options="invoiceCorrectionTypes"
option-value="id"
option-label="description"
:required="true"
data-cy="invoiceInDescriptorMenu_reason"
/>
</QItemSection>
</QItem>
</QCardSection>
<QCardActions class="justify-end q-mr-sm">
<QBtn
flat
:label="t('globals.close')"
color="primary"
v-close-popup
/>
<QBtn
:label="t('globals.save')"
color="primary"
v-close-popup
@click="createInvoiceInCorrection"
:disable="isNotFilled"
data-cy="saveCorrectiveInvoice"
/>
</QCardActions>
</QCard>
</QDialog>
</template>
</template>
<i18n>
en:
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries

View File

@ -198,6 +198,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
color="orange-11"
text-color="black"
@click="book(entityId)"
data-cy="invoiceInSummary_book"
/>
</template>
</InvoiceIntoBook>
@ -219,7 +220,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
:value="entity.supplier?.name"
>
<template #value>
<span class="link">
<span class="link" data-cy="invoiceInSummary_supplier">
{{ entity.supplier?.name }}
<SupplierDescriptorProxy :id="entity.supplierFk" />
</span>

View File

@ -202,6 +202,9 @@ function setCursor(ref) {
:option-label="col.optionLabel"
:filter-options="['id', 'name']"
:tooltip="t('Create a new expense')"
:acls="[
{ model: 'Expense', props: '*', accessType: 'WRITE' },
]"
@keydown.tab.prevent="
autocompleteExpense(
$event,

View File

@ -7,6 +7,7 @@ import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import { dateRange } from 'src/filters';
import { date } from 'quasar';
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
defineProps({ dataKey: { type: String, required: true } });
const dateFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
@ -39,17 +40,13 @@ function handleDaysAgo(params, daysAgo) {
<VnInputDate
:label="$t('globals.from')"
v-model="params.from"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
:label="$t('globals.to')"
v-model="params.to"
is-outlined
/>
<VnInputDate :label="$t('globals.to')" v-model="params.to" filled />
</QItemSection>
</QItem>
<QItem>
@ -57,7 +54,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInputNumber
:label="$t('globals.daysAgo')"
v-model="params.daysAgo"
is-outlined
filled
:step="0"
@update:model-value="(val) => handleDaysAgo(params, val)"
@remove="(val) => handleDaysAgo(params, val)"
@ -66,12 +63,7 @@ function handleDaysAgo(params, daysAgo) {
</QItem>
<QItem>
<QItemSection>
<VnSelectSupplier
v-model="params.supplierFk"
dense
outlined
rounded
/>
<VnSelectSupplier v-model="params.supplierFk" dense filled />
</QItemSection>
</QItem>
<QItem>
@ -79,7 +71,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInput
:label="getLocale('supplierRef')"
v-model="params.supplierRef"
is-outlined
filled
lazy-rules
/>
</QItemSection>
@ -89,7 +81,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInput
:label="getLocale('fi')"
v-model="params.fi"
is-outlined
filled
lazy-rules
/>
</QItemSection>
@ -99,7 +91,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInput
:label="getLocale('serial')"
v-model="params.serial"
is-outlined
filled
lazy-rules
/>
</QItemSection>
@ -109,7 +101,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInput
:label="getLocale('account')"
v-model="params.account"
is-outlined
filled
lazy-rules
/>
</QItemSection>
@ -119,7 +111,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInput
:label="getLocale('globals.params.awbCode')"
v-model="params.awbCode"
is-outlined
filled
lazy-rules
/>
</QItemSection>
@ -129,7 +121,7 @@ function handleDaysAgo(params, daysAgo) {
<VnInputNumber
:label="$t('globals.amount')"
v-model="params.amount"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -141,19 +133,19 @@ function handleDaysAgo(params, daysAgo) {
url="Companies"
option-label="code"
:fields="['id', 'code']"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QCheckbox
<VnCheckbox
:label="$t('invoiceIn.isBooked')"
v-model="params.isBooked"
@update:model-value="searchFn()"
toggle-indeterminate
/>
<QCheckbox
<VnCheckbox
:label="getLocale('params.correctingFk')"
v-model="params.correctingFk"
@update:model-value="searchFn()"

View File

@ -4,7 +4,7 @@ import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import { useArrayData } from 'src/composables/useArrayData';
import qs from 'qs';
const { notify, dialog } = useQuasar();
const { t } = useI18n();
@ -61,17 +61,15 @@ async function checkToBook(id) {
}
async function toBook(id) {
let type = 'positive';
let message = t('globals.dataSaved');
let err = false;
try {
await axios.post(`InvoiceIns/${id}/toBook`);
store.data.isBooked = true;
} catch (e) {
type = 'negative';
message = t('It was not able to book the invoice');
err = true;
throw e;
} finally {
notify({ type, message });
if (!err) notify({ type: 'positive', message: t('globals.dataSaved') });
}
}
</script>

View File

@ -25,8 +25,7 @@ const { t } = useI18n();
<VnInputNumber
v-model="params.daysAgo"
:label="t('params.daysAgo')"
outlined
rounded
filled
dense
/>
</QItemSection>
@ -36,8 +35,7 @@ const { t } = useI18n();
<VnInput
v-model="params.serial"
:label="t('params.serial')"
outlined
rounded
filled
dense
/>
</QItemSection>

View File

@ -3,7 +3,7 @@ import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
@ -34,7 +34,7 @@ function ticketFilter(invoice) {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`InvoiceOuts/${entityId}`"
:filter="filter"
@ -93,5 +93,5 @@ function ticketFilter(invoice) {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -33,17 +33,13 @@ const states = ref();
<VnInput
:label="t('globals.params.clientFk')"
v-model="params.clientFk"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
v-model="params.fi"
:label="t('globals.params.fi')"
is-outlined
/>
<VnInput v-model="params.fi" :label="t('globals.params.fi')" filled />
</QItemSection>
</QItem>
<QItem>
@ -51,7 +47,7 @@ const states = ref();
<VnInputNumber
:label="t('globals.amount')"
v-model="params.amount"
is-outlined
filled
data-cy="InvoiceOutFilterAmountBtn"
/>
</QItemSection>
@ -62,8 +58,7 @@ const states = ref();
:label="t('invoiceOut.params.min')"
dense
lazy-rules
outlined
rounded
filled
type="number"
v-model.number="params.min"
/>
@ -73,8 +68,7 @@ const states = ref();
:label="t('invoiceOut.params.max')"
dense
lazy-rules
outlined
rounded
filled
type="number"
v-model.number="params.max"
/>
@ -94,7 +88,7 @@ const states = ref();
<VnInputDate
v-model="params.created"
:label="t('invoiceOut.params.created')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -103,15 +97,14 @@ const states = ref();
<VnInputDate
v-model="params.dued"
:label="t('invoiceOut.params.dued')"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"

View File

@ -26,7 +26,7 @@ const serialTypesOptions = ref([]);
const handleInvoiceOutSerialsFetch = (data) => {
serialTypesOptions.value = Array.from(
new Set(data.map((item) => item.type).filter((type) => type))
new Set(data.map((item) => item.type).filter((type) => type)),
);
};
@ -99,8 +99,7 @@ onMounted(async () => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
data-cy="InvoiceOutGlobalClientSelect"
>
<template #option="scope">
@ -124,19 +123,18 @@ onMounted(async () => {
option-label="type"
hide-selected
dense
outlined
rounded
filled
data-cy="InvoiceOutGlobalSerialSelect"
/>
<VnInputDate
v-model="formData.invoiceDate"
:label="t('invoiceDate')"
is-outlined
filled
/>
<VnInputDate
v-model="formData.maxShipped"
:label="t('maxShipped')"
is-outlined
filled
data-cy="InvoiceOutGlobalMaxShippedDate"
/>
<VnSelect
@ -145,8 +143,7 @@ onMounted(async () => {
:options="companiesOptions"
option-label="code"
dense
outlined
rounded
filled
data-cy="InvoiceOutGlobalCompanySelect"
/>
<VnSelect
@ -154,8 +151,7 @@ onMounted(async () => {
v-model="formData.printer"
:options="printersOptions"
dense
outlined
rounded
filled
data-cy="InvoiceOutGlobalPrinterSelect"
/>
</div>
@ -166,7 +162,7 @@ onMounted(async () => {
color="primary"
class="q-mt-md full-width"
unelevated
rounded
filled
dense
/>
<QBtn
@ -175,7 +171,7 @@ onMounted(async () => {
color="primary"
class="q-mt-md full-width"
unelevated
rounded
filled
dense
@click="getStatus = 'stopping'"
/>

View File

@ -35,17 +35,13 @@ const props = defineProps({
<VnInputDate
v-model="params.from"
:label="t('globals.from')"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
v-model="params.to"
:label="t('globals.to')"
is-outlined
/>
<VnInputDate v-model="params.to" :label="t('globals.to')" filled />
</QItemSection>
</QItem>
<QItem>
@ -57,8 +53,7 @@ const props = defineProps({
option-label="code"
option-value="code"
dense
outlined
rounded
filled
@update:model-value="searchFn()"
>
<template #option="scope">
@ -84,9 +79,8 @@ const props = defineProps({
v-model="params.country"
option-label="name"
option-value="name"
outlined
dense
rounded
filled
@update:model-value="searchFn()"
>
<template #option="scope">
@ -110,9 +104,8 @@ const props = defineProps({
url="Clients"
:label="t('globals.client')"
v-model="params.clientId"
outlined
dense
rounded
filled
@update:model-value="searchFn()"
/>
</QItemSection>
@ -122,7 +115,7 @@ const props = defineProps({
<VnInputNumber
v-model="params.amount"
:label="t('globals.amount')"
is-outlined
filled
:positive="false"
/>
</QItemSection>
@ -130,9 +123,8 @@ const props = defineProps({
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"

View File

@ -3,7 +3,7 @@ import { computed, ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import EntityDescriptor from 'src/components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
@ -90,7 +90,7 @@ const updateStock = async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Item"
:summary="$props.summary"
:url="`Items/${entityId}/getCard`"
@ -162,7 +162,7 @@ const updateStock = async () => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -13,7 +13,6 @@ const props = defineProps({
required: true,
},
});
</script>
<template>
@ -28,8 +27,7 @@ const props = defineProps({
:fields="['id', 'nickname']"
option-label="nickname"
dense
outlined
rounded
filled
use-input
@update:model-value="searchFn()"
sort-by="nickname ASC"
@ -46,8 +44,7 @@ const props = defineProps({
:label="t('params.warehouseFk')"
v-model="params.warehouseFk"
dense
outlined
rounded
filled
use-input
@update:model-value="searchFn()"
/>
@ -58,7 +55,7 @@ const props = defineProps({
<VnInputDate
:label="t('params.started')"
v-model="params.started"
is-outlined
filled
@update:model-value="searchFn()"
/>
</QItemSection>
@ -68,7 +65,7 @@ const props = defineProps({
<VnInputDate
:label="t('params.ended')"
v-model="params.ended"
is-outlined
filled
@update:model-value="searchFn()"
/>
</QItemSection>

View File

@ -177,11 +177,7 @@ onMounted(async () => {
<template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnInput
v-model="params.search"
:label="t('params.search')"
is-outlined
/>
<VnInput v-model="params.search" :label="t('params.search')" filled />
</QItemSection>
</QItem>
<QItem>
@ -197,8 +193,7 @@ onMounted(async () => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -213,8 +208,7 @@ onMounted(async () => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
@ -240,8 +234,7 @@ onMounted(async () => {
option-label="nickname"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -252,8 +245,7 @@ onMounted(async () => {
@update:model-value="searchFn()"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -282,8 +274,7 @@ onMounted(async () => {
:options="tagOptions"
option-label="name"
dense
outlined
rounded
filled
:emit-value="false"
use-input
:is-clearable="false"
@ -299,8 +290,7 @@ onMounted(async () => {
option-value="value"
option-label="value"
dense
outlined
rounded
filled
emit-value
use-input
:disable="!tag"
@ -312,7 +302,7 @@ onMounted(async () => {
v-model="tag.value"
:label="t('params.value')"
:disable="!tag"
is-outlined
filled
:is-clearable="false"
@keydown.enter.prevent="applyTags(params, searchFn)"
/>
@ -351,8 +341,7 @@ onMounted(async () => {
option-label="label"
option-value="label"
dense
outlined
rounded
filled
:emit-value="false"
use-input
:is-clearable="false"
@ -377,7 +366,7 @@ onMounted(async () => {
v-model="fieldFilter.value"
:label="t('params.value')"
:disable="!fieldFilter.selectedField"
is-outlined
filled
@keydown.enter="applyFieldFilters(params, searchFn)"
/>
</QItemSection>

View File

@ -87,11 +87,7 @@ onMounted(async () => {
<template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnInput
v-model="params.search"
:label="t('params.search')"
is-outlined
/>
<VnInput v-model="params.search" :label="t('params.search')" filled />
</QItemSection>
</QItem>
<QItem>
@ -99,7 +95,7 @@ onMounted(async () => {
<VnInput
v-model="params.ticketFk"
:label="t('params.ticketFk')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -114,8 +110,7 @@ onMounted(async () => {
option-label="nickname"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -124,7 +119,7 @@ onMounted(async () => {
<VnInput
v-model="params.clientFk"
:label="t('params.clientFk')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -139,8 +134,7 @@ onMounted(async () => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -153,25 +147,16 @@ onMounted(async () => {
:params="{ departmentCodes: ['VT'] }"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
v-model="params.from"
:label="t('params.from')"
is-outlined
/>
<VnInputDate v-model="params.from" :label="t('params.from')" filled />
</QItemSection>
<QItemSection>
<VnInputDate
v-model="params.to"
:label="t('params.to')"
is-outlined
/>
<VnInputDate v-model="params.to" :label="t('params.to')" filled />
</QItemSection>
</QItem>
<QItem>
@ -180,7 +165,7 @@ onMounted(async () => {
:label="t('params.daysOnward')"
v-model="params.daysOnward"
lazy-rules
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -195,8 +180,7 @@ onMounted(async () => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import filter from './ItemTypeFilter.js';
@ -25,11 +25,12 @@ const entityId = computed(() => {
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`ItemTypes/${entityId}`"
:filter="filter"
title="code"
data-key="ItemType"
:to-module="{ name: 'ItemTypeList' }"
>
<template #body="{ entity }">
<VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
@ -45,5 +46,5 @@ const entityId = computed(() => {
:value="entity.category?.name"
/>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -77,7 +77,7 @@ const getLocale = (label) => {
<VnInput
:label="t('globals.params.clientFk')"
v-model="params.clientFk"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -86,7 +86,7 @@ const getLocale = (label) => {
<VnInput
:label="t('params.orderFk')"
v-model="params.orderFk"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -95,7 +95,7 @@ const getLocale = (label) => {
<VnInputNumber
:label="t('params.scopeDays')"
v-model="params.scopeDays"
is-outlined
filled
@update:model-value="(val) => handleScopeDays(params, val)"
@remove="(val) => handleScopeDays(params, val)"
/>
@ -106,66 +106,54 @@ const getLocale = (label) => {
<VnInput
:label="t('params.nickname')"
v-model="params.nickname"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
option-label="name"
url="Departments"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
:label="t('params.refFk')"
v-model="params.refFk"
is-outlined
/>
<VnInput :label="t('params.refFk')" v-model="params.refFk" filled />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('params.agencyModeFk')"
v-model="params.agencyModeFk"
url="AgencyModes/isActive"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.stateFk')"
v-model="params.stateFk"
url="States"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('params.groupedStates')"
v-model="params.alertLevel"
:options="groupedStates"
@ -176,9 +164,8 @@ const getLocale = (label) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.warehouseFk')"
v-model="params.warehouseFk"
:options="warehouses"
@ -188,9 +175,8 @@ const getLocale = (label) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.countryFk')"
v-model="params.countryFk"
url="Countries"
@ -200,9 +186,8 @@ const getLocale = (label) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.provinceFk')"
v-model="params.provinceFk"
url="Provinces"
@ -212,9 +197,8 @@ const getLocale = (label) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.department"
option-label="name"
@ -226,9 +210,8 @@ const getLocale = (label) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.packing')"
v-model="params.packing"
url="ItemPackingTypes"

View File

@ -57,9 +57,8 @@ const getSelectedTagValues = async (tag) => {
option-value="id"
option-label="name"
dense
outlined
class="q-mb-md"
rounded
filled
:emit-value="false"
use-input
@update:model-value="getSelectedTagValues"
@ -79,8 +78,7 @@ const getSelectedTagValues = async (tag) => {
option-value="value"
option-label="value"
dense
outlined
rounded
filled
emit-value
use-input
:disable="!value || !selectedTag"
@ -92,16 +90,14 @@ const getSelectedTagValues = async (tag) => {
v-model="value.value"
:label="t('components.itemsFilterPanel.value')"
:disable="!value"
is-outlined
class="col"
data-cy="catalogFilterValueDialogValueInput"
/>
<QBtn
icon="delete"
size="md"
outlined
dense
rounded
filled
flat
class="filter-icon col-2"
@click="tagValues.splice(index, 1)"

View File

@ -6,9 +6,11 @@ import filter from './OrderFilter.js';
<template>
<VnCard
data-key="Order"
:data-key="$attrs['data-key'] ?? 'Order'"
url="Orders"
:filter="filter"
:descriptor="OrderDescriptor"
v-bind="$attrs"
v-on="$attrs"
/>
</template>

View File

@ -221,8 +221,7 @@ function addOrder(value, field, params) {
option-value="id"
option-label="name"
dense
outlined
rounded
filled
emit-value
use-input
sort-by="name ASC"
@ -251,8 +250,7 @@ function addOrder(value, field, params) {
v-model="orderBySelected"
:options="orderByList"
dense
outlined
rounded
filled
@update:model-value="(value) => addOrder(value, 'field', params)"
/>
</QItemSection>
@ -264,8 +262,7 @@ function addOrder(value, field, params) {
v-model="orderWaySelected"
:options="orderWayList"
dense
outlined
rounded
filled
@update:model-value="(value) => addOrder(value, 'way', params)"
/>
</QItemSection>
@ -275,8 +272,7 @@ function addOrder(value, field, params) {
<VnInput
:label="t('components.itemsFilterPanel.value')"
dense
outlined
rounded
filled
:is-clearable="false"
v-model="searchByTag"
@keyup.enter="(val) => onSearchByTag(val, params)"

View File

@ -4,10 +4,10 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { toCurrency, toDate } from 'src/filters';
import { useState } from 'src/composables/useState';
import filter from './OrderFilter.js';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import OrderCard from './OrderCard.vue';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
const DEFAULT_ITEMS = 0;
@ -24,11 +24,14 @@ const route = useRoute();
const state = useState();
const { t } = useI18n();
const getTotalRef = ref();
const total = ref(0);
const entityId = computed(() => {
return $props.id || route.params.id;
});
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const setData = (entity) => {
if (!entity) return;
getTotalRef.value && getTotalRef.value.fetch();
@ -38,9 +41,6 @@ const setData = (entity) => {
const getConfirmationValue = (isConfirmed) => {
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
};
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const total = ref(0);
</script>
<template>
@ -54,12 +54,12 @@ const total = ref(0);
"
/>
<CardDescriptor
ref="descriptor"
:url="`Orders/${entityId}`"
:filter="filter"
v-bind="$attrs"
:id="entityId"
:card="OrderCard"
title="client.name"
@on-fetch="setData"
data-key="Order"
module="Order"
>
<template #body="{ entity }">
<VnLv

View File

@ -12,6 +12,11 @@ const $props = defineProps({
<template>
<QPopupProxy>
<OrderDescriptor v-if="$props.id" :id="$props.id" :summary="OrderSummary" />
<OrderDescriptor
v-if="$props.id"
:id="$props.id"
:summary="OrderSummary"
data-key="OrderDescriptor"
/>
</QPopupProxy>
</template>

View File

@ -49,8 +49,7 @@ const sourceList = ref([]);
v-model="params.clientFk"
lazy-rules
dense
outlined
rounded
filled
/>
<VnSelect
:label="t('agency')"
@ -58,13 +57,11 @@ const sourceList = ref([]);
:options="agencyList"
:input-debounce="0"
dense
outlined
rounded
filled
/>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
@ -75,21 +72,14 @@ const sourceList = ref([]);
v-model="params.from"
:label="t('fromLanded')"
dense
outlined
rounded
/>
<VnInputDate
v-model="params.to"
:label="t('toLanded')"
dense
outlined
rounded
filled
/>
<VnInputDate v-model="params.to" :label="t('toLanded')" dense filled />
<VnInput
:label="t('orderId')"
v-model="params.orderFk"
lazy-rules
is-outlined
filled
/>
<VnSelect
:label="t('application')"
@ -98,8 +88,7 @@ const sourceList = ref([]);
option-label="value"
option-value="value"
dense
outlined
rounded
filled
:input-debounce="0"
/>
<QCheckbox

View File

@ -3,7 +3,7 @@ import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
const props = defineProps({
@ -21,14 +21,15 @@ const { store } = useArrayData();
const card = computed(() => store.data);
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Agency"
:url="`Agencies/${entityId}`"
:title="card?.name"
:subtitle="props.id"
:to-module="{ name: 'RouteAgency' }"
>
<template #body="{ entity: agency }">
<VnLv :label="t('globals.name')" :value="agency.name" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -71,7 +71,7 @@ const exprBuilder = (param, value) => {
<QList dense>
<QItem class="q-my-sm">
<QItemSection>
<VnInput v-model="params.routeFk" :label="t('ID')" is-outlined />
<VnInput v-model="params.routeFk" :label="t('ID')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm" v-if="agencyList">
@ -83,8 +83,7 @@ const exprBuilder = (param, value) => {
option-value="id"
option-label="name"
dense
outlined
rounded
filled
emit-value
map-options
use-input
@ -102,8 +101,7 @@ const exprBuilder = (param, value) => {
option-value="id"
option-label="name"
dense
outlined
rounded
filled
emit-value
map-options
use-input
@ -123,8 +121,7 @@ const exprBuilder = (param, value) => {
option-value="name"
option-label="name"
dense
outlined
rounded
filled
emit-value
map-options
use-input
@ -135,20 +132,12 @@ const exprBuilder = (param, value) => {
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate
v-model="params.dated"
:label="t('Date')"
is-outlined
/>
<VnInputDate v-model="params.dated" :label="t('Date')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate
v-model="params.from"
:label="t('From')"
is-outlined
/>
<VnInputDate v-model="params.from" :label="t('From')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
@ -156,7 +145,7 @@ const exprBuilder = (param, value) => {
<VnInputDate
v-model="params.to"
:label="t('To')"
is-outlined
filled
is-clearable
/>
</QItemSection>
@ -166,23 +155,23 @@ const exprBuilder = (param, value) => {
<VnInput
v-model="params.packages"
:label="t('Packages')"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInput v-model="params.m3" :label="t('m3')" is-outlined />
<VnInput v-model="params.m3" :label="t('m3')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInput v-model="params.kmTotal" :label="t('Km')" is-outlined />
<VnInput v-model="params.kmTotal" :label="t('Km')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInput v-model="params.price" :label="t('Price')" is-outlined />
<VnInput v-model="params.price" :label="t('Price')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
@ -190,7 +179,7 @@ const exprBuilder = (param, value) => {
<VnInput
v-model="params.invoiceInFk"
:label="t('Received')"
is-outlined
filled
/>
</QItemSection>
</QItem>

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import useCardDescription from 'composables/useCardDescription';
import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDate } from 'src/filters';
@ -41,13 +41,12 @@ const getZone = async () => {
zone.value = zoneData.name;
};
const data = ref(useCardDescription());
const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
onMounted(async () => {
getZone();
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Routes/${entityId}`"
:filter="filter"
:title="null"
@ -69,7 +68,7 @@ onMounted(async () => {
<template #menu="{ entity }">
<RouteDescriptorMenu :route="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -36,8 +36,7 @@ const emit = defineEmits(['search']);
:label="t('globals.worker')"
v-model="params.workerFk"
dense
outlined
rounded
filled
:input-debounce="0"
/>
</QItemSection>
@ -52,8 +51,7 @@ const emit = defineEmits(['search']);
option-value="id"
option-label="name"
dense
outlined
rounded
filled
:input-debounce="0"
/>
</QItemSection>
@ -63,7 +61,7 @@ const emit = defineEmits(['search']);
<VnInputDate
v-model="params.from"
:label="t('globals.from')"
is-outlined
filled
:disable="Boolean(params.scopeDays)"
@update:model-value="params.scopeDays = null"
/>
@ -74,7 +72,7 @@ const emit = defineEmits(['search']);
<VnInputDate
v-model="params.to"
:label="t('globals.to')"
is-outlined
filled
:disable="Boolean(params.scopeDays)"
@update:model-value="params.scopeDays = null"
/>
@ -86,7 +84,7 @@ const emit = defineEmits(['search']);
v-model="params.scopeDays"
type="number"
:label="t('globals.daysOnward')"
is-outlined
filled
clearable
:disable="Boolean(params.from || params.to)"
@update:model-value="
@ -107,15 +105,14 @@ const emit = defineEmits(['search']);
option-label="numberPlate"
option-filter-value="numberPlate"
dense
outlined
rounded
filled
:input-debounce="0"
/>
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInput v-model="params.m3" label="m³" is-outlined clearable />
<VnInput v-model="params.m3" label="m³" filled clearable />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
@ -127,8 +124,7 @@ const emit = defineEmits(['search']);
option-value="id"
option-label="name"
dense
outlined
rounded
filled
:input-debounce="0"
/>
</QItemSection>
@ -138,7 +134,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.description"
:label="t('globals.description')"
is-outlined
filled
clearable
/>
</QItemSection>

View File

@ -28,7 +28,6 @@ const userParams = {
shipped: null,
};
const columns = computed(() => [
{
align: 'left',
@ -175,6 +174,7 @@ function downloadPdfs() {
:data-key
url="Cmrs/filter"
:columns="columns"
:order="['shipped DESC', 'cmrFk ASC']"
:user-params="userParams"
default-mode="table"
v-model:selected="selectedRows"

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDateHourMin } from 'src/filters';
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
@ -30,11 +30,12 @@ const entityId = computed(() => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Roadmaps/${entityId}`"
:filter="filter"
data-key="Roadmap"
:summary="summary"
:to-module="{ name: 'RouteRoadmap' }"
>
<template #body="{ entity }">
<VnLv :label="t('Roadmap')" :value="entity?.name" />
@ -51,7 +52,7 @@ const entityId = computed(() => {
<template #menu="{ entity }">
<RoadmapDescriptorMenu :route="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -31,12 +31,12 @@ const emit = defineEmits(['search']);
<template #body="{ params }">
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate v-model="params.from" :label="t('From')" is-outlined />
<VnInputDate v-model="params.from" :label="t('From')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
<QItemSection>
<VnInputDate v-model="params.to" :label="t('To')" is-outlined />
<VnInputDate v-model="params.to" :label="t('To')" filled />
</QItemSection>
</QItem>
<QItem class="q-my-sm">
@ -44,7 +44,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.tractorPlate"
:label="t('Tractor Plate')"
is-outlined
filled
clearable
/>
</QItemSection>
@ -54,7 +54,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.trailerPlate"
:label="t('Trailer Plate')"
is-outlined
filled
clearable
/>
</QItemSection>
@ -66,8 +66,7 @@ const emit = defineEmits(['search']);
:fields="['id', 'nickname']"
v-model="params.supplierFk"
dense
outlined
rounded
filled
emit-value
map-options
use-input
@ -81,7 +80,7 @@ const emit = defineEmits(['search']);
v-model="params.price"
:label="t('Price')"
type="number"
is-outlined
filled
clearable
/>
</QItemSection>
@ -91,7 +90,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.driverName"
:label="t('Driver name')"
is-outlined
filled
clearable
/>
</QItemSection>
@ -101,7 +100,7 @@ const emit = defineEmits(['search']);
<VnInput
v-model="params.phone"
:label="t('Phone')"
is-outlined
filled
clearable
/>
</QItemSection>

View File

@ -54,9 +54,9 @@ const columns = computed(() => [
label: t('globals.worker'),
component: markRaw(VnSelectWorker),
create: true,
cardVisible: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
columnFilter: false,
cardVisible: true,
width: '100px',
},
{
@ -74,7 +74,6 @@ const columns = computed(() => [
create: true,
columnFilter: true,
cardVisible: true,
visible: true,
},
{
name: 'vehicleFk',
@ -93,7 +92,6 @@ const columns = computed(() => [
create: true,
columnFilter: true,
cardVisible: true,
visible: true,
},
{
align: 'center',

View File

@ -30,16 +30,16 @@ const columns = computed(() => [
align: 'center',
},
{
name: 'street',
label: t('Street'),
field: (row) => row?.street,
name: 'client',
label: t('Client'),
field: (row) => row?.nickname,
sortable: false,
align: 'left',
},
{
name: 'client',
label: t('Client'),
field: (row) => row?.nickname,
name: 'street',
label: t('Street'),
field: (row) => row?.street,
sortable: false,
align: 'left',
},
@ -199,12 +199,22 @@ const confirmRemove = (ticket) => {
const openSmsDialog = async () => {
const clientsId = [];
const clientsPhone = [];
const clientWithoutPhone = [];
for (let ticket of selectedRows.value) {
clientsId.push(ticket?.clientFk);
const { data: client } = await axios.get(`Clients/${ticket?.clientFk}`);
if (!client.phone) {
clientWithoutPhone.push(ticket?.clientFk);
continue;
}
clientsPhone.push(client.phone);
}
if (clientWithoutPhone.length) {
quasar.notify({
type: 'warning',
message: t('components.VnNotes.clientWithoutPhone', { clientWithoutPhone }),
});
}
quasar.dialog({
component: SendSmsDialog,
@ -319,7 +329,7 @@ const openSmsDialog = async () => {
selection="multiple"
>
<template #body-cell-order="{ row }">
<QTd class="order-field">
<QTd class="order-field" auto-width>
<div class="flex no-wrap items-center">
<QIcon
name="low_priority"
@ -341,7 +351,7 @@ const openSmsDialog = async () => {
</QTd>
</template>
<template #body-cell-city="{ value, row }">
<QTd auto-width>
<QTd>
<span class="link" @click="goToBuscaman(row)">
{{ value }}
<QTooltip>{{ t('Open buscaman') }}</QTooltip>
@ -349,7 +359,7 @@ const openSmsDialog = async () => {
</QTd>
</template>
<template #body-cell-client="{ value, row }">
<QTd auto-width>
<QTd>
<span class="link">
{{ value }}
<CustomerDescriptorProxy :id="row?.clientFk" />

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
@ -20,10 +20,11 @@ const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Vehicles/${entityId}`"
data-key="Vehicle"
title="numberPlate"
:to-module="{ name: 'RouteVehicle' }"
>
<template #menu="{ entity }">
<QItem
@ -53,7 +54,7 @@ const entityId = computed(() => props.id || route.params.id);
<VnLv :label="$t('globals.model')" :value="entity.model" />
<VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
@ -24,7 +24,7 @@ const entityId = computed(() => {
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Shelvings/${entityId}`"
:filter="filter"
title="code"
@ -45,5 +45,5 @@ const entityId = computed(() => {
<template #menu="{ entity }">
<ShelvingDescriptorMenu :shelving="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -39,15 +39,14 @@ const emit = defineEmits(['search']);
option-label="code"
:filter-options="['id', 'code']"
dense
outlined
rounded
filled
sort-by="code ASC"
/>
</QItemSection>
</QItem>
<QItem class="q-mb-sm">
<QItemSection>
<VnSelectWorker v-model="params.userFk" outlined rounded />
<VnSelectWorker v-model="params.userFk" filled />
</QItemSection>
</QItem>
<QItem class="q-mb-md">

View File

@ -1,7 +1,7 @@
<script setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import filter from './ParkingFilter.js';
const props = defineProps({
@ -16,17 +16,17 @@ const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Parking"
:url="`Parkings/${entityId}`"
title="code"
:filter="filter"
:to-module="{ name: 'ParkingList' }"
:to-module="{ name: 'ParkingMain' }"
>
<template #body="{ entity }">
<VnLv :label="$t('globals.code')" :value="entity.code" />
<VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
<VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -36,11 +36,7 @@ const emit = defineEmits(['search']);
<template #body="{ params }">
<QItem>
<QItemSection>
<VnInput
:label="t('params.code')"
v-model="params.code"
is-outlined
/>
<VnInput :label="t('params.code')" v-model="params.code" filled />
</QItemSection>
</QItem>
<QItem>
@ -51,8 +47,7 @@ const emit = defineEmits(['search']);
option-label="description"
:label="t('params.sectorFk')"
dense
outlined
rounded
filled
:options="sectors"
use-input
input-debounce="0"

View File

@ -33,7 +33,7 @@ defineProps({
:label="t('params.from')"
v-model="params.from"
@update:model-value="searchFn()"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -47,8 +47,7 @@ defineProps({
:include="{ relation: 'accountingType' }"
sort-by="id"
dense
outlined
rounded
filled
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
@ -74,8 +73,7 @@ defineProps({
option-label="name"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>

View File

@ -25,20 +25,12 @@ defineProps({
<template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnInput
v-model="params.search"
:label="t('params.search')"
is-outlined
/>
<VnInput v-model="params.search" :label="t('params.search')" filled />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
v-model="params.itemId"
:label="t('params.itemId')"
is-outlined
/>
<VnInput v-model="params.itemId" :label="t('params.itemId')" filled />
</QItemSection>
</QItem>
<QItem>
@ -54,8 +46,7 @@ defineProps({
option-label="nickname"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -73,8 +64,7 @@ defineProps({
option-label="name"
hide-selected
dense
outlined
rounded
filled
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
@ -102,8 +92,7 @@ defineProps({
option-label="name"
hide-selected
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -113,7 +102,7 @@ defineProps({
:label="t('params.from')"
v-model="params.from"
@update:model-value="searchFn()"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -123,7 +112,7 @@ defineProps({
:label="t('params.to')"
v-model="params.to"
@update:model-value="searchFn()"
is-outlined
filled
/>
</QItemSection>
</QItem>

View File

@ -3,7 +3,7 @@ import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDateString } from 'src/filters';
@ -61,7 +61,7 @@ const getEntryQueryParams = (supplier) => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Suppliers/${entityId}`"
:filter="filter"
data-key="Supplier"
@ -136,7 +136,7 @@ const getEntryQueryParams = (supplier) => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -4,7 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDateTimeFormat } from 'src/filters/date';
@ -57,7 +57,7 @@ function getInfo() {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Tickets/${entityId}`"
:filter="filter"
data-key="Ticket"
@ -155,7 +155,7 @@ function getInfo() {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -32,7 +32,7 @@ onMounted(() => {
watch(
() => props.ticket,
() => restoreTicket
() => restoreTicket,
);
const { push, currentRoute } = useRouter();
@ -58,7 +58,7 @@ const hasDocuwareFile = ref();
const quasar = useQuasar();
const canRestoreTicket = ref(false);
const onClientSelected = async(clientId) =>{
const onClientSelected = async (clientId) => {
client.value = clientId;
await fetchClient();
await fetchAddresses();
@ -66,10 +66,10 @@ const onClientSelected = async(clientId) =>{
const onAddressSelected = (addressId) => {
address.value = addressId;
}
};
const fetchClient = async () => {
const response = await getClient(client.value)
const response = await getClient(client.value);
if (!response) return;
const [retrievedClient] = response.data;
selectedClient.value = retrievedClient;
@ -151,7 +151,7 @@ function openDeliveryNote(type = 'deliveryNote', documentType = 'pdf') {
recipientId: ticket.value.clientFk,
type: type,
},
'_blank'
'_blank',
);
}
@ -297,8 +297,8 @@ async function transferClient() {
clientFk: client.value,
addressFk: address.value,
};
await axios.patch( `Tickets/${ticketId.value}/transferClient`, params );
await axios.patch(`Tickets/${ticketId.value}/transferClient`, params);
window.location.reload();
}
@ -339,7 +339,7 @@ async function changeShippedHour(time) {
const { data } = await axios.post(
`Tickets/${ticketId.value}/updateEditableTicket`,
params
params,
);
if (data) window.location.reload();
@ -405,8 +405,7 @@ async function uploadDocuware(force) {
uploadDocuware(true);
});
const { data } = await axios.post(`Docuwares/upload`, {
fileCabinet: 'deliveryNote',
const { data } = await axios.post(`Docuwares/upload-delivery-note`, {
ticketIds: [parseInt(ticketId.value)],
});
@ -500,7 +499,7 @@ async function ticketToRestore() {
</QItem>
</template>
</VnSelect>
<VnSelect
<VnSelect
:disable="!client"
:options="addressesOptions"
:fields="['id', 'nickname']"
@ -815,7 +814,7 @@ async function ticketToRestore() {
en:
addTurn: Add turn
invoiceIds: "Invoices have been generated with the following ids: {invoiceIds}"
es:
Show Delivery Note...: Ver albarán...
Send Delivery Note...: Enviar albarán...

View File

@ -81,7 +81,7 @@ const setUserParams = (params) => {
v-model="params.days"
:label="t('negative.days')"
dense
is-outlined
filled
type="number"
@update:model-value="
(value) => {
@ -97,7 +97,7 @@ const setUserParams = (params) => {
v-model="params.id"
:label="t('negative.id')"
dense
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -107,7 +107,7 @@ const setUserParams = (params) => {
v-model="params.producer"
:label="t('negative.producer')"
dense
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -117,7 +117,7 @@ const setUserParams = (params) => {
v-model="params.origen"
:label="t('negative.origen')"
dense
is-outlined
filled
/>
</QItemSection> </QItem
><QItem>
@ -133,8 +133,7 @@ const setUserParams = (params) => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
/> </QItemSection
><QItemSection v-else>
<QSkeleton class="full-width" type="QSelect" />
@ -151,8 +150,7 @@ const setUserParams = (params) => {
option-label="name"
hide-selected
dense
outlined
rounded
filled
>
<template #option="scope">
<QItem v-bind="scope.itemProps">

View File

@ -71,7 +71,7 @@ onMounted(async () => await getItemPackingTypes());
<VnInputDate
v-model="params.dateFuture"
:label="t('params.dateFuture')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -80,7 +80,7 @@ onMounted(async () => await getItemPackingTypes());
<VnInputDate
v-model="params.dateToAdvance"
:label="t('params.dateToAdvance')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -95,8 +95,7 @@ onMounted(async () => await getItemPackingTypes());
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
:use-like="false"
>
</VnSelect>
@ -113,8 +112,7 @@ onMounted(async () => await getItemPackingTypes());
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
:use-like="false"
>
</VnSelect>
@ -125,7 +123,7 @@ onMounted(async () => await getItemPackingTypes());
<VnInputNumber
v-model="params.scopeDays"
:label="t('Days onward')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -147,8 +145,7 @@ onMounted(async () => await getItemPackingTypes());
url="Departments"
:fields="['id', 'name']"
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -162,8 +159,7 @@ onMounted(async () => await getItemPackingTypes());
option-label="name"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>

View File

@ -63,18 +63,10 @@ const getGroupedStates = (data) => {
<template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnInput
v-model="params.clientFk"
:label="t('Customer ID')"
is-outlined
/>
<VnInput v-model="params.clientFk" :label="t('Customer ID')" filled />
</QItemSection>
<QItemSection>
<VnInput
v-model="params.orderFk"
:label="t('Order ID')"
is-outlined
/>
<VnInput v-model="params.orderFk" :label="t('Order ID')" filled />
</QItemSection>
</QItem>
<QItem>
@ -82,7 +74,7 @@ const getGroupedStates = (data) => {
<VnInputDate
v-model="params.from"
:label="t('From')"
is-outlined
filled
data-cy="From_date"
/>
</QItemSection>
@ -90,7 +82,7 @@ const getGroupedStates = (data) => {
<VnInputDate
v-model="params.to"
:label="t('To')"
is-outlined
filled
data-cy="To_date"
/>
</QItemSection>
@ -98,9 +90,8 @@ const getGroupedStates = (data) => {
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
filled
:label="t('globals.params.departmentFk')"
v-model="params.departmentFk"
option-value="id"
@ -125,8 +116,7 @@ const getGroupedStates = (data) => {
map-options
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -146,19 +136,14 @@ const getGroupedStates = (data) => {
map-options
use-input
dense
outlined
rounded
filled
sort-by="name ASC"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
v-model="params.refFk"
:label="t('Invoice Ref.')"
is-outlined
/>
<VnInput v-model="params.refFk" :label="t('Invoice Ref.')" filled />
</QItemSection>
</QItem>
<QItem>
@ -166,17 +151,13 @@ const getGroupedStates = (data) => {
<VnInput
v-model="params.scopeDays"
:label="t('Days onward')"
is-outlined
filled
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
v-model="params.nickname"
:label="t('Nickname')"
is-outlined
/>
<VnInput v-model="params.nickname" :label="t('Nickname')" filled />
</QItemSection>
</QItem>
<QItem>
@ -241,8 +222,7 @@ const getGroupedStates = (data) => {
map-options
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -260,8 +240,7 @@ const getGroupedStates = (data) => {
map-options
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -281,8 +260,7 @@ const getGroupedStates = (data) => {
map-options
use-input
dense
outlined
rounded
filled
/>
</QItemSection>
</QItem>
@ -291,7 +269,7 @@ const getGroupedStates = (data) => {
<VnInput
v-model="params.collectionFk"
:label="t('Collection')"
is-outlined
filled
/>
</QItemSection>
</QItem>

View File

@ -73,7 +73,7 @@ onMounted(async () => {
<VnInputDate
v-model="params.originScopeDays"
:label="t('params.originScopeDays')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -82,7 +82,7 @@ onMounted(async () => {
<VnInputDate
v-model="params.futureScopeDays"
:label="t('params.futureScopeDays')"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -91,7 +91,7 @@ onMounted(async () => {
<VnInput
:label="t('params.litersMax')"
v-model="params.litersMax"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -100,7 +100,7 @@ onMounted(async () => {
<VnInput
:label="t('params.linesMax')"
v-model="params.linesMax"
is-outlined
filled
/>
</QItemSection>
</QItem>
@ -115,8 +115,7 @@ onMounted(async () => {
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>
@ -132,8 +131,7 @@ onMounted(async () => {
:info="t('iptInfo')"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>
@ -148,8 +146,7 @@ onMounted(async () => {
option-label="name"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>
@ -164,8 +161,7 @@ onMounted(async () => {
option-label="name"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>
@ -191,8 +187,7 @@ onMounted(async () => {
option-label="name"
@update:model-value="searchFn()"
dense
outlined
rounded
filled
>
</VnSelect>
</QItemSection>

View File

@ -340,25 +340,20 @@ async function makeInvoice(ticket) {
});
}
async function sendDocuware(ticket) {
try {
let ticketIds = ticket.map((item) => item.id);
async function sendDocuware(tickets) {
let ticketIds = tickets.map((item) => item.id);
const { data } = await axios.post(`Docuwares/upload`, {
fileCabinet: 'deliveryNote',
ticketIds,
});
const { data } = await axios.post(`Docuwares/upload-delivery-note`, {
ticketIds,
});
for (let ticket of ticketIds) {
ticket.stateFk = data.id;
ticket.state = data.name;
ticket.alertLevel = data.alertLevel;
ticket.alertLevelCode = data.code;
}
notify('globals.dataSaved', 'positive');
} catch (err) {
console.err('err: ', err);
for (let ticket of tickets) {
ticket.stateFk = data.id;
ticket.state = data.name;
ticket.alertLevel = data.alertLevel;
ticket.alertLevelCode = data.code;
}
notify('globals.dataSaved', 'positive');
}
function openBalanceDialog(ticket) {

View File

@ -36,7 +36,7 @@ const warehousesOptionsIn = ref([]);
auto-load
:filter="{ where: { isDestiny: TRUE } }"
/>
<FormModel :url-update="`Travels/${route.params.id}`" model="Travel" auto-load>
<FormModel :url-update="`Travels/${route.params.id}`" model="Travel">
<template #form="{ data }">
<VnRow>
<VnInput v-model="data.ref" :label="t('globals.reference')" />
@ -57,8 +57,8 @@ const warehousesOptionsIn = ref([]);
<VnRow>
<VnInputDate
v-model="data.availabled"
:label="t('travel.summary.availabled')"
/>
:label="t('travel.summary.availabled')"
/>
<VnInputTime
v-model="data.availabled"
:label="t('travel.summary.availabledHour')"
@ -96,6 +96,7 @@ const warehousesOptionsIn = ref([]);
</QIcon>
</template>
</VnInput>
<VnInput v-model="data.awbFk" :label="t('travel.awbFk')" />
</VnRow>
<VnRow>
<QCheckbox v-model="data.isRaid" :label="t('travel.basicData.isRaid')" />

View File

@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
@ -31,7 +31,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Travels/${entityId}`"
:title="data.title"
:subtitle="data.subtitle"
@ -79,7 +79,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

Some files were not shown because too many files have changed in this diff Show More