7299_testToMaster #351
|
@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2418.01]
|
||||||
|
|
||||||
## [2416.01] - 2024-04-18
|
## [2416.01] - 2024-04-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "salix-front",
|
"name": "salix-front",
|
||||||
"version": "24.16.0",
|
"version": "24.18.0",
|
||||||
"description": "Salix frontend",
|
"description": "Salix frontend",
|
||||||
"productName": "Salix",
|
"productName": "Salix",
|
||||||
"author": "Verdnatura",
|
"author": "Verdnatura",
|
||||||
|
|
|
@ -78,6 +78,7 @@ defineExpose({
|
||||||
<div class="q-mt-lg row justify-end">
|
<div class="q-mt-lg row justify-end">
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('globals.save')"
|
:label="t('globals.save')"
|
||||||
|
:title="t('globals.save')"
|
||||||
type="submit"
|
type="submit"
|
||||||
color="primary"
|
color="primary"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
|
@ -85,6 +86,7 @@ defineExpose({
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('globals.cancel')"
|
:label="t('globals.cancel')"
|
||||||
|
:title="t('globals.cancel')"
|
||||||
type="reset"
|
type="reset"
|
||||||
color="primary"
|
color="primary"
|
||||||
flat
|
flat
|
||||||
|
|
|
@ -198,11 +198,13 @@ function addDefaultData(data) {
|
||||||
en:
|
en:
|
||||||
contentTypesInfo: Allowed file types {allowedContentTypes}
|
contentTypesInfo: Allowed file types {allowedContentTypes}
|
||||||
EntryDmsDescription: Reference {reference}
|
EntryDmsDescription: Reference {reference}
|
||||||
|
WorkersDescription: Working of employee id {reference}
|
||||||
SupplierDmsDescription: Reference {reference}
|
SupplierDmsDescription: Reference {reference}
|
||||||
es:
|
es:
|
||||||
Generate identifier for original file: Generar identificador para archivo original
|
Generate identifier for original file: Generar identificador para archivo original
|
||||||
contentTypesInfo: Tipos de archivo permitidos {allowedContentTypes}
|
contentTypesInfo: Tipos de archivo permitidos {allowedContentTypes}
|
||||||
EntryDmsDescription: Referencia {reference}
|
EntryDmsDescription: Referencia {reference}
|
||||||
|
WorkersDescription: Laboral del empleado {reference}
|
||||||
SupplierDmsDescription: Referencia {reference}
|
SupplierDmsDescription: Referencia {reference}
|
||||||
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -5,9 +5,11 @@ import { useRoute } from 'vue-router';
|
||||||
import { useQuasar, QCheckbox, QBtn, QInput } from 'quasar';
|
import { useQuasar, QCheckbox, QBtn, QInput } from 'quasar';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import VnDms from 'src/components/common/VnDms.vue';
|
import VnDms from 'src/components/common/VnDms.vue';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
|
import VnUserLink from '../ui/VnUserLink.vue';
|
||||||
import { downloadFile } from 'src/composables/downloadFile';
|
import { downloadFile } from 'src/composables/downloadFile';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -26,6 +28,15 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
deleteModel: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
downloadModel: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
defaultDmsCode: {
|
defaultDmsCode: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -74,7 +85,7 @@ const dmsFilter = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
order: ['dmsFk DESC'],
|
where: { [$props.filter]: route.params.id },
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
|
@ -94,12 +105,12 @@ const columns = computed(() => [
|
||||||
props: (prop) => ({
|
props: (prop) => ({
|
||||||
readonly: true,
|
readonly: true,
|
||||||
borderless: true,
|
borderless: true,
|
||||||
'model-value': prop.row.dmsType.name,
|
'model-value': prop.row.dmsType?.name,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'order',
|
field: 'hardCopyNumber',
|
||||||
label: t('globals.order'),
|
label: t('globals.order'),
|
||||||
name: 'order',
|
name: 'order',
|
||||||
component: 'span',
|
component: 'span',
|
||||||
|
@ -117,6 +128,7 @@ const columns = computed(() => [
|
||||||
label: t('globals.description'),
|
label: t('globals.description'),
|
||||||
name: 'description',
|
name: 'description',
|
||||||
component: 'span',
|
component: 'span',
|
||||||
|
props: (prop) => ({ value: prop.value?.toUpperCase() }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -136,21 +148,53 @@ const columns = computed(() => [
|
||||||
name: 'file',
|
name: 'file',
|
||||||
component: 'span',
|
component: 'span',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
field: 'worker',
|
||||||
|
label: t('globals.worker'),
|
||||||
|
name: 'worker',
|
||||||
|
component: VnUserLink,
|
||||||
|
props: (prop) => ({
|
||||||
|
name: prop.row.worker?.user?.name.toLowerCase(),
|
||||||
|
workerId: prop.row.worker?.id,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
field: 'created',
|
||||||
|
label: t('globals.created'),
|
||||||
|
name: 'created',
|
||||||
|
component: VnInputDate,
|
||||||
|
props: (prop) => ({
|
||||||
|
disable: true,
|
||||||
|
'model-value': prop.row.created,
|
||||||
|
}),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'options',
|
field: 'options',
|
||||||
name: 'options',
|
name: 'options',
|
||||||
components: [
|
components: [
|
||||||
{
|
{
|
||||||
component: QBtn,
|
component: QBtn,
|
||||||
|
name: 'download',
|
||||||
|
isDocuware: true,
|
||||||
props: () => ({
|
props: () => ({
|
||||||
icon: 'cloud_download',
|
icon: 'cloud_download',
|
||||||
flat: true,
|
flat: true,
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
}),
|
}),
|
||||||
click: (prop) => downloadFile(prop.row.id),
|
click: (prop) =>
|
||||||
|
downloadFile(
|
||||||
|
prop.row.id,
|
||||||
|
$props.downloadModel,
|
||||||
|
null,
|
||||||
|
prop.row.download
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: QBtn,
|
component: QBtn,
|
||||||
|
name: 'edit',
|
||||||
|
external: false,
|
||||||
props: () => ({
|
props: () => ({
|
||||||
icon: 'edit',
|
icon: 'edit',
|
||||||
flat: true,
|
flat: true,
|
||||||
|
@ -160,6 +204,8 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: QBtn,
|
component: QBtn,
|
||||||
|
name: 'delete',
|
||||||
|
external: false,
|
||||||
props: () => ({
|
props: () => ({
|
||||||
icon: 'delete',
|
icon: 'delete',
|
||||||
flat: true,
|
flat: true,
|
||||||
|
@ -167,12 +213,24 @@ const columns = computed(() => [
|
||||||
}),
|
}),
|
||||||
click: (prop) => deleteDms(prop.row.id),
|
click: (prop) => deleteDms(prop.row.id),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: QBtn,
|
||||||
|
name: 'open',
|
||||||
|
external: true,
|
||||||
|
props: () => ({
|
||||||
|
icon: 'open_in_new',
|
||||||
|
flat: true,
|
||||||
|
color: 'primary',
|
||||||
|
}),
|
||||||
|
click: (prop) => open(prop.row.url),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function setData(data) {
|
function setData(data) {
|
||||||
const newData = data.map((value) => value.dms);
|
const newData = data.map((value) => value.dms || value);
|
||||||
|
newData.sort((a, b) => new Date(b.created) - new Date(a.created));
|
||||||
rows.value = newData;
|
rows.value = newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +244,7 @@ function deleteDms(dmsFk) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.onOk(async () => {
|
.onOk(async () => {
|
||||||
await axios.post(`${$props.model}/${dmsFk}/removeFile`);
|
await axios.post(`${$props.deleteModel ?? $props.model}/${dmsFk}/removeFile`);
|
||||||
const index = rows.value.findIndex((row) => row.id == dmsFk);
|
const index = rows.value.findIndex((row) => row.id == dmsFk);
|
||||||
rows.value.splice(index, 1);
|
rows.value.splice(index, 1);
|
||||||
});
|
});
|
||||||
|
@ -206,84 +264,106 @@ function parseDms(data) {
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function open(url) {
|
||||||
|
window.open(url).focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldRenderButton(button, isExternal = false) {
|
||||||
|
if (button.name == 'download') return true;
|
||||||
|
return button.external === isExternal;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<VnPaginate
|
||||||
ref="dmsRef"
|
ref="dmsRef"
|
||||||
|
:data-key="$props.model"
|
||||||
:url="$props.model"
|
:url="$props.model"
|
||||||
:filter="dmsFilter"
|
:filter="dmsFilter"
|
||||||
:where="{ [$props.filter]: route.params.id }"
|
:order="['dmsFk DESC']"
|
||||||
|
:auto-load="true"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
<QTable
|
|
||||||
:columns="columns"
|
|
||||||
:rows="rows"
|
|
||||||
class="full-width q-mt-md"
|
|
||||||
hide-bottom
|
|
||||||
row-key="clientFk"
|
|
||||||
:grid="$q.screen.lt.sm"
|
|
||||||
>
|
>
|
||||||
<template #body-cell="props">
|
<template #body>
|
||||||
<QTd :props="props">
|
<QTable
|
||||||
<QTr :props="props">
|
:columns="columns"
|
||||||
<component
|
:rows="rows"
|
||||||
v-if="props.col.component"
|
class="full-width q-mt-md"
|
||||||
:is="props.col.component"
|
hide-bottom
|
||||||
v-bind="props.col.props && props.col.props(props)"
|
row-key="clientFk"
|
||||||
>
|
:grid="$q.screen.lt.sm"
|
||||||
<span
|
>
|
||||||
v-if="props.col.component == 'span'"
|
<template #body-cell="props">
|
||||||
style="white-space: wrap"
|
<QTd :props="props">
|
||||||
>{{ props.value }}</span
|
<QTr :props="props">
|
||||||
>
|
<component
|
||||||
</component>
|
v-if="props.col.component"
|
||||||
</QTr>
|
:is="props.col.component"
|
||||||
|
v-bind="props.col.props && props.col.props(props)"
|
||||||
<div class="flex justify-center" v-if="props.col.name == 'options'">
|
>
|
||||||
<div v-for="button of props.col.components" :key="button.id">
|
<span
|
||||||
<component
|
v-if="props.col.component == 'span'"
|
||||||
:is="button.component"
|
style="white-space: wrap"
|
||||||
v-bind="button.props(props)"
|
>{{ props.value }}</span
|
||||||
@click="button.click(props)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
<template #item="props">
|
|
||||||
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
|
|
||||||
<QCard
|
|
||||||
bordered
|
|
||||||
flat
|
|
||||||
@keyup.ctrl.enter.stop="claimDevelopmentForm?.saveChanges()"
|
|
||||||
>
|
|
||||||
<QSeparator />
|
|
||||||
<QList dense>
|
|
||||||
<QItem v-for="col in props.cols" :key="col.name">
|
|
||||||
<div v-if="col.name != 'options'" class="row">
|
|
||||||
<span class="labelColor">{{ col.label }}:</span>
|
|
||||||
<span>{{ col.value }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-if="col.name == 'options'" class="row">
|
|
||||||
<div
|
|
||||||
v-for="button of col.components"
|
|
||||||
:key="button.id"
|
|
||||||
class="row"
|
|
||||||
>
|
>
|
||||||
<component
|
</component>
|
||||||
:is="button.component"
|
</QTr>
|
||||||
v-bind="button.props(col)"
|
|
||||||
@click="button.click(col)"
|
<div class="row no-wrap" v-if="props.col.name == 'options'">
|
||||||
/>
|
<div v-for="button of props.col.components" :key="button.id">
|
||||||
</div>
|
<component
|
||||||
|
v-if="
|
||||||
|
shouldRenderButton(button, props.row.isDocuware)
|
||||||
|
"
|
||||||
|
:is="button.component"
|
||||||
|
v-bind="button.props(props)"
|
||||||
|
@click="button.click(props)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</QItem>
|
</div>
|
||||||
</QList>
|
</QTd>
|
||||||
</QCard>
|
</template>
|
||||||
</div>
|
<template #item="props">
|
||||||
|
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
|
||||||
|
<QCard
|
||||||
|
bordered
|
||||||
|
flat
|
||||||
|
@keyup.ctrl.enter.stop="claimDevelopmentForm?.saveChanges()"
|
||||||
|
>
|
||||||
|
<QSeparator />
|
||||||
|
<QList dense>
|
||||||
|
<QItem v-for="col in props.cols" :key="col.name">
|
||||||
|
<div v-if="col.name != 'options'" class="row">
|
||||||
|
<span class="labelColor">{{ col.label }}:</span>
|
||||||
|
<span>{{ col.value }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="col.name == 'options'" class="row">
|
||||||
|
<div
|
||||||
|
v-for="button of col.components"
|
||||||
|
:key="button.id"
|
||||||
|
class="row"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
v-if="
|
||||||
|
shouldRenderButton(
|
||||||
|
button.name,
|
||||||
|
props.row.isDocuware
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:is="button.component"
|
||||||
|
v-bind="button.props(col)"
|
||||||
|
@click="button.click(col)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</QItem>
|
||||||
|
</QList>
|
||||||
|
</QCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
</template>
|
</template>
|
||||||
</QTable>
|
</VnPaginate>
|
||||||
<QDialog v-model="formDialog.show">
|
<QDialog v-model="formDialog.show">
|
||||||
<VnDms
|
<VnDms
|
||||||
:model="updateModel ?? model"
|
:model="updateModel ?? model"
|
||||||
|
|
|
@ -61,7 +61,6 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['onFetch', 'onPaginate']);
|
const emit = defineEmits(['onFetch', 'onPaginate']);
|
||||||
defineExpose({ fetch });
|
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
sortBy: props.order,
|
sortBy: props.order,
|
||||||
|
@ -78,6 +77,7 @@ const arrayData = useArrayData(props.dataKey, {
|
||||||
userParams: props.userParams,
|
userParams: props.userParams,
|
||||||
exprBuilder: props.exprBuilder,
|
exprBuilder: props.exprBuilder,
|
||||||
});
|
});
|
||||||
|
const hasMoreData = ref();
|
||||||
const store = arrayData.store;
|
const store = arrayData.store;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -91,6 +91,10 @@ watch(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const addFilter = async (filter, params) => {
|
||||||
|
await arrayData.addFilter({ filter, params });
|
||||||
|
};
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
await arrayData.fetch({ append: false });
|
await arrayData.fetch({ append: false });
|
||||||
if (!arrayData.hasMoreData.value) {
|
if (!arrayData.hasMoreData.value) {
|
||||||
|
@ -106,11 +110,10 @@ async function paginate() {
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
await arrayData.loadMore();
|
await arrayData.loadMore();
|
||||||
|
|
||||||
if (!arrayData.hasMoreData.value) {
|
if (!arrayData.hasMoreData.value) {
|
||||||
if (store.userParamsChanged) arrayData.hasMoreData.value = true;
|
if (store.userParamsChanged) arrayData.hasMoreData.value = true;
|
||||||
store.userParamsChanged = false;
|
store.userParamsChanged = false;
|
||||||
isLoading.value = false;
|
endPagination();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,12 +123,15 @@ async function paginate() {
|
||||||
pagination.value.sortBy = sortBy;
|
pagination.value.sortBy = sortBy;
|
||||||
pagination.value.descending = descending;
|
pagination.value.descending = descending;
|
||||||
|
|
||||||
isLoading.value = false;
|
endPagination();
|
||||||
|
}
|
||||||
|
|
||||||
|
function endPagination() {
|
||||||
|
hasMoreData.value = arrayData.hasMoreData.value;
|
||||||
|
isLoading.value = false;
|
||||||
emit('onFetch', store.data);
|
emit('onFetch', store.data);
|
||||||
emit('onPaginate');
|
emit('onPaginate');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onLoad(index, done) {
|
async function onLoad(index, done) {
|
||||||
if (!store.data) {
|
if (!store.data) {
|
||||||
return done();
|
return done();
|
||||||
|
@ -140,6 +146,8 @@ async function onLoad(index, done) {
|
||||||
if (store.userParamsChanged) isDone = !arrayData.hasMoreData.value;
|
if (store.userParamsChanged) isDone = !arrayData.hasMoreData.value;
|
||||||
done(isDone);
|
done(isDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({ fetch, addFilter });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -188,6 +196,9 @@ async function onLoad(index, done) {
|
||||||
<QSpinner color="orange" size="md" />
|
<QSpinner color="orange" size="md" />
|
||||||
</div>
|
</div>
|
||||||
</QInfiniteScroll>
|
</QInfiniteScroll>
|
||||||
|
<div v-if="!isLoading && hasMoreData" class="w-full flex justify-center q-mt-md">
|
||||||
|
<QBtn color="primary" :label="t('Load more data')" @click="paginate()" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -204,4 +215,5 @@ async function onLoad(index, done) {
|
||||||
es:
|
es:
|
||||||
No data to display: Sin datos que mostrar
|
No data to display: Sin datos que mostrar
|
||||||
No results found: No se han encontrado resultados
|
No results found: No se han encontrado resultados
|
||||||
|
Load more data: Cargar más resultados
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -76,7 +76,7 @@ const removeNode = (node) => {
|
||||||
notify(t('department.departmentRemoved'), 'positive');
|
notify(t('department.departmentRemoved'), 'positive');
|
||||||
await fetchNodeLeaves(parentFk);
|
await fetchNodeLeaves(parentFk);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error removing department');
|
console.error('Error removing department');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { useSession } from 'src/composables/useSession';
|
||||||
import { getUrl } from './getUrl';
|
import { getUrl } from './getUrl';
|
||||||
|
|
||||||
const {getTokenMultimedia} = useSession();
|
const { getTokenMultimedia } = useSession();
|
||||||
const token = getTokenMultimedia();
|
const token = getTokenMultimedia();
|
||||||
|
|
||||||
export async function downloadFile(dmsId) {
|
export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile', url) {
|
||||||
let appUrl = await getUrl('', 'lilium');
|
let appUrl = await getUrl('', 'lilium');
|
||||||
appUrl = appUrl.replace('/#/', '');
|
appUrl = appUrl.replace('/#/', '');
|
||||||
window.open(`${appUrl}/api/dms/${dmsId}/downloadFile?access_token=${token}`);
|
window.open(url ?? `${appUrl}/api/${model}/${id}${urlPath}?access_token=${token}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ export function useArrayData(key, userOptions) {
|
||||||
|
|
||||||
const { limit } = filter;
|
const { limit } = filter;
|
||||||
|
|
||||||
hasMoreData.value = response.data.length === limit;
|
hasMoreData.value = response.data.length >= limit;
|
||||||
|
|
||||||
if (append) {
|
if (append) {
|
||||||
if (!store.data) store.data = [];
|
if (!store.data) store.data = [];
|
||||||
|
@ -144,6 +144,8 @@ export function useArrayData(key, userOptions) {
|
||||||
store.userParams = userParams;
|
store.userParams = userParams;
|
||||||
store.skip = 0;
|
store.skip = 0;
|
||||||
store.filter.skip = 0;
|
store.filter.skip = 0;
|
||||||
|
page.value = 1;
|
||||||
|
|
||||||
await fetch({ append: false });
|
await fetch({ append: false });
|
||||||
return { filter, params };
|
return { filter, params };
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ globals:
|
||||||
basicData: Basic data
|
basicData: Basic data
|
||||||
log: Logs
|
log: Logs
|
||||||
parkingList: Parkings list
|
parkingList: Parkings list
|
||||||
|
created: Created
|
||||||
|
worker: Worker
|
||||||
errors:
|
errors:
|
||||||
statusUnauthorized: Access denied
|
statusUnauthorized: Access denied
|
||||||
statusInternalServerError: An internal server error has ocurred
|
statusInternalServerError: An internal server error has ocurred
|
||||||
|
@ -500,6 +502,7 @@ claim:
|
||||||
commercial: Commercial
|
commercial: Commercial
|
||||||
province: Province
|
province: Province
|
||||||
zone: Zone
|
zone: Zone
|
||||||
|
customerId: client ID
|
||||||
summary:
|
summary:
|
||||||
customer: Customer
|
customer: Customer
|
||||||
assignedTo: Assigned
|
assignedTo: Assigned
|
||||||
|
@ -531,7 +534,7 @@ claim:
|
||||||
assignedTo: Assigned
|
assignedTo: Assigned
|
||||||
created: Created
|
created: Created
|
||||||
state: State
|
state: State
|
||||||
picked: Picked
|
pickup: Pick up
|
||||||
photo:
|
photo:
|
||||||
fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}'
|
fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}'
|
||||||
noData: 'There are no images/videos, click here or drag and drop the file'
|
noData: 'There are no images/videos, click here or drag and drop the file'
|
||||||
|
@ -782,6 +785,9 @@ worker:
|
||||||
workerCreate: New worker
|
workerCreate: New worker
|
||||||
department: Department
|
department: Department
|
||||||
pda: PDA
|
pda: PDA
|
||||||
|
notes: Notas
|
||||||
|
dms: My documentation
|
||||||
|
pbx: Private Branch Exchange
|
||||||
log: Log
|
log: Log
|
||||||
list:
|
list:
|
||||||
name: Name
|
name: Name
|
||||||
|
@ -1090,6 +1096,7 @@ item:
|
||||||
list: List
|
list: List
|
||||||
diary: Diary
|
diary: Diary
|
||||||
tags: Tags
|
tags: Tags
|
||||||
|
create: Create
|
||||||
descriptor:
|
descriptor:
|
||||||
item: Item
|
item: Item
|
||||||
buyer: Buyer
|
buyer: Buyer
|
||||||
|
@ -1100,6 +1107,23 @@ item:
|
||||||
available: Available
|
available: Available
|
||||||
warehouseText: 'Calculated on the warehouse of { warehouseName }'
|
warehouseText: 'Calculated on the warehouse of { warehouseName }'
|
||||||
itemDiary: Item diary
|
itemDiary: Item diary
|
||||||
|
list:
|
||||||
|
id: Identifier
|
||||||
|
grouping: Grouping
|
||||||
|
packing: Packing
|
||||||
|
description: Description
|
||||||
|
stems: Stems
|
||||||
|
category: Category
|
||||||
|
typeName: Type
|
||||||
|
intrastat: Intrastat
|
||||||
|
isActive: Active
|
||||||
|
size: Size
|
||||||
|
origin: Origin
|
||||||
|
userName: Buyer
|
||||||
|
weightByPiece: Weight/Piece
|
||||||
|
stemMultiplier: Multiplier
|
||||||
|
producer: Producer
|
||||||
|
landed: Landed
|
||||||
components:
|
components:
|
||||||
topbar: {}
|
topbar: {}
|
||||||
userPanel:
|
userPanel:
|
||||||
|
|
|
@ -88,6 +88,8 @@ globals:
|
||||||
basicData: Datos básicos
|
basicData: Datos básicos
|
||||||
log: Historial
|
log: Historial
|
||||||
parkingList: Listado de parkings
|
parkingList: Listado de parkings
|
||||||
|
created: Fecha creación
|
||||||
|
worker: Trabajador
|
||||||
errors:
|
errors:
|
||||||
statusUnauthorized: Acceso denegado
|
statusUnauthorized: Acceso denegado
|
||||||
statusInternalServerError: Ha ocurrido un error interno del servidor
|
statusInternalServerError: Ha ocurrido un error interno del servidor
|
||||||
|
@ -497,6 +499,7 @@ claim:
|
||||||
commercial: Comercial
|
commercial: Comercial
|
||||||
province: Provincia
|
province: Provincia
|
||||||
zone: Zona
|
zone: Zona
|
||||||
|
customerId: ID del cliente
|
||||||
summary:
|
summary:
|
||||||
customer: Cliente
|
customer: Cliente
|
||||||
assignedTo: Asignada a
|
assignedTo: Asignada a
|
||||||
|
@ -528,7 +531,10 @@ claim:
|
||||||
assignedTo: Asignada a
|
assignedTo: Asignada a
|
||||||
created: Creada
|
created: Creada
|
||||||
state: Estado
|
state: Estado
|
||||||
picked: Recogida
|
pickup: Recogida
|
||||||
|
null: No
|
||||||
|
agency: Agencia
|
||||||
|
delivery: Reparto
|
||||||
photo:
|
photo:
|
||||||
fileDescription: 'Reclamacion ID {claimId} del cliente {clientName} id {clientId}'
|
fileDescription: 'Reclamacion ID {claimId} del cliente {clientName} id {clientId}'
|
||||||
noData: No hay imágenes/videos haz click aquí o arrastra y suelta el archivo
|
noData: No hay imágenes/videos haz click aquí o arrastra y suelta el archivo
|
||||||
|
@ -776,6 +782,9 @@ worker:
|
||||||
workerCreate: Nuevo trabajador
|
workerCreate: Nuevo trabajador
|
||||||
department: Departamentos
|
department: Departamentos
|
||||||
pda: PDA
|
pda: PDA
|
||||||
|
notes: Notas
|
||||||
|
dms: Mi documentación
|
||||||
|
pbx: Centralita
|
||||||
log: Historial
|
log: Historial
|
||||||
list:
|
list:
|
||||||
name: Nombre
|
name: Nombre
|
||||||
|
@ -1084,6 +1093,7 @@ item:
|
||||||
list: Listado
|
list: Listado
|
||||||
diary: Histórico
|
diary: Histórico
|
||||||
tags: Etiquetas
|
tags: Etiquetas
|
||||||
|
create: Crear
|
||||||
descriptor:
|
descriptor:
|
||||||
item: Artículo
|
item: Artículo
|
||||||
buyer: Comprador
|
buyer: Comprador
|
||||||
|
@ -1094,6 +1104,23 @@ item:
|
||||||
available: Disponible
|
available: Disponible
|
||||||
warehouseText: 'Calculado sobre el almacén de { warehouseName }'
|
warehouseText: 'Calculado sobre el almacén de { warehouseName }'
|
||||||
itemDiary: Registro de compra-venta
|
itemDiary: Registro de compra-venta
|
||||||
|
list:
|
||||||
|
id: Identificador
|
||||||
|
grouping: Grouping
|
||||||
|
packing: Packing
|
||||||
|
description: Descripción
|
||||||
|
stems: Tallos
|
||||||
|
category: Reino
|
||||||
|
typeName: Tipo
|
||||||
|
intrastat: Intrastat
|
||||||
|
isActive: Activo
|
||||||
|
size: Medida
|
||||||
|
origin: Origen
|
||||||
|
weightByPiece: Peso (gramos)/tallo
|
||||||
|
userName: Comprador
|
||||||
|
stemMultiplier: Multiplicador
|
||||||
|
producer: Productor
|
||||||
|
landed: F. entrega
|
||||||
components:
|
components:
|
||||||
topbar: {}
|
topbar: {}
|
||||||
userPanel:
|
userPanel:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -177,7 +178,7 @@ function openDialog(dmsId) {
|
||||||
@on-fetch="getClaimDms"
|
@on-fetch="getClaimDms"
|
||||||
>
|
>
|
||||||
<template #header="{ entity: { claim } }">
|
<template #header="{ entity: { claim } }">
|
||||||
{{ claim.id }} - {{ claim.client.name }}
|
{{ claim.id }} - {{ claim.client.name }} ({{ claim.client.id }})
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
|
@ -214,10 +215,10 @@ function openDialog(dmsId) {
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :label="t('claim.summary.customer')">
|
<VnLv :label="t('claim.summary.customer')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<VnUserLink
|
<span class="link cursor-pointer">
|
||||||
:name="claim.client?.name"
|
{{ claim.client?.name }}
|
||||||
:worker-id="claim.client?.id"
|
<CustomerDescriptorProxy :id="claim.clientFk" />
|
||||||
/>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv
|
<VnLv
|
||||||
|
|
|
@ -63,7 +63,7 @@ const removeDepartment = () => {
|
||||||
router.push({ name: 'WorkerDepartment' });
|
router.push({ name: 'WorkerDepartment' });
|
||||||
notify('department.departmentRemoved', 'positive');
|
notify('department.departmentRemoved', 'positive');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error removing department');
|
console.error('Error removing department');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<template>Item create view</template>
|
|
@ -1 +1,577 @@
|
||||||
<template>Item list</template>
|
<script setup>
|
||||||
|
import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
|
import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||||
|
import ItemDescriptorProxy from '../Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
import ItemSummary from '../Item/Card/ItemSummary.vue';
|
||||||
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
|
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { toDateFormat } from 'src/filters/date.js';
|
||||||
|
import { useSession } from 'composables/useSession';
|
||||||
|
import { dashIfEmpty } from 'src/filters';
|
||||||
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { getTokenMultimedia } = useSession();
|
||||||
|
const token = getTokenMultimedia();
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
|
||||||
|
const paginateRef = ref(null);
|
||||||
|
const itemTypesOptions = ref([]);
|
||||||
|
const originsOptions = ref([]);
|
||||||
|
const buyersOptions = ref([]);
|
||||||
|
const intrastatOptions = ref([]);
|
||||||
|
const itemCategoriesOptions = ref([]);
|
||||||
|
const visibleColumns = ref([]);
|
||||||
|
const allColumnNames = ref([]);
|
||||||
|
|
||||||
|
const exprBuilder = (param, value) => {
|
||||||
|
switch (param) {
|
||||||
|
case 'category':
|
||||||
|
return { 'ic.name': value };
|
||||||
|
case 'buyerFk':
|
||||||
|
return { 'it.workerFk': value };
|
||||||
|
case 'grouping':
|
||||||
|
return { 'b.grouping': value };
|
||||||
|
case 'packing':
|
||||||
|
return { 'b.packing': value };
|
||||||
|
case 'origin':
|
||||||
|
return { 'ori.code': value };
|
||||||
|
case 'typeFk':
|
||||||
|
return { 'i.typeFk': value };
|
||||||
|
case 'intrastat':
|
||||||
|
return { 'intr.description': value };
|
||||||
|
case 'name':
|
||||||
|
return { 'i.name': { like: `%${value}%` } };
|
||||||
|
case 'producer':
|
||||||
|
return { 'pr.name': { like: `%${value}%` } };
|
||||||
|
case 'id':
|
||||||
|
case 'size':
|
||||||
|
case 'subname':
|
||||||
|
case 'isActive':
|
||||||
|
case 'weightByPiece':
|
||||||
|
case 'stemMultiplier':
|
||||||
|
case 'stems':
|
||||||
|
return { [`i.${param}`]: value };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = reactive({});
|
||||||
|
|
||||||
|
const applyColumnFilter = async (col) => {
|
||||||
|
try {
|
||||||
|
const paramKey = col.columnFilter?.filterParamKey || col.field;
|
||||||
|
params[paramKey] = col.columnFilter.filterValue;
|
||||||
|
await paginateRef.value.addFilter(null, params);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error applying column filter', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getInputEvents = (col) => {
|
||||||
|
return col.columnFilter.type === 'select'
|
||||||
|
? { 'update:modelValue': () => applyColumnFilter(col) }
|
||||||
|
: {
|
||||||
|
'keyup.enter': () => applyColumnFilter(col),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
name: 'picture',
|
||||||
|
align: 'left',
|
||||||
|
columnFilter: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.id'),
|
||||||
|
name: 'id',
|
||||||
|
field: 'id',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.grouping'),
|
||||||
|
field: 'grouping',
|
||||||
|
name: 'grouping',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.packing'),
|
||||||
|
field: 'packing',
|
||||||
|
name: 'packing',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('globals.description'),
|
||||||
|
field: 'name',
|
||||||
|
name: 'description',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.stems'),
|
||||||
|
field: 'stems',
|
||||||
|
name: 'stems',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.size'),
|
||||||
|
field: 'size',
|
||||||
|
name: 'size',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.typeName'),
|
||||||
|
field: 'typeName',
|
||||||
|
name: 'typeName',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnSelectFilter,
|
||||||
|
filterParamKey: 'typeFk',
|
||||||
|
type: 'select',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
options: itemTypesOptions.value,
|
||||||
|
'option-value': 'id',
|
||||||
|
'option-label': 'name',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: t('item.list.category'),
|
||||||
|
field: 'category',
|
||||||
|
name: 'category',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnSelectFilter,
|
||||||
|
type: 'select',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
options: itemCategoriesOptions.value,
|
||||||
|
'option-value': 'name',
|
||||||
|
'option-label': 'name',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: t('item.list.intrastat'),
|
||||||
|
field: 'intrastat',
|
||||||
|
name: 'intrastat',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnSelectFilter,
|
||||||
|
type: 'select',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
options: intrastatOptions.value,
|
||||||
|
'option-value': 'description',
|
||||||
|
'option-label': 'description',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.origin'),
|
||||||
|
field: 'origin',
|
||||||
|
name: 'origin',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnSelectFilter,
|
||||||
|
type: 'select',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
options: originsOptions.value,
|
||||||
|
'option-value': 'code',
|
||||||
|
'option-label': 'code',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.userName'),
|
||||||
|
field: 'userName',
|
||||||
|
name: 'userName',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnSelectFilter,
|
||||||
|
filterParamKey: 'buyerFk',
|
||||||
|
type: 'select',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
options: buyersOptions.value,
|
||||||
|
'option-value': 'id',
|
||||||
|
'option-label': 'nickname',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.weightByPiece'),
|
||||||
|
field: 'weightByPiece',
|
||||||
|
name: 'weightByPiece',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.stemMultiplier'),
|
||||||
|
field: 'stemMultiplier',
|
||||||
|
name: 'stemMultiplier',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.isActive'),
|
||||||
|
field: 'isActive',
|
||||||
|
name: 'isActive',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.producer'),
|
||||||
|
field: 'producer',
|
||||||
|
name: 'producer',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
columnFilter: {
|
||||||
|
component: VnInput,
|
||||||
|
type: 'text',
|
||||||
|
filterValue: null,
|
||||||
|
event: getInputEvents,
|
||||||
|
attrs: {
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('item.list.landed'),
|
||||||
|
field: 'landed',
|
||||||
|
name: 'landed',
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
format: (val) => dashIfEmpty(toDateFormat(val)),
|
||||||
|
columnFilter: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
name: 'actions',
|
||||||
|
align: 'left',
|
||||||
|
columnFilter: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const redirectToItemCreate = () => {
|
||||||
|
router.push({ name: 'ItemCreate' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectToItemSummary = (id) => {
|
||||||
|
router.push({ name: 'ItemSummary', params: { id } });
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneItem = async (itemFk) => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post(`Items/${itemFk}/clone`);
|
||||||
|
if (!data) return;
|
||||||
|
router.push({ name: 'ItemTags', params: { id: data.id } });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error cloning item', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
const filteredColumns = columns.value.filter(
|
||||||
|
(col) => col.name !== 'picture' && col.name !== 'actions'
|
||||||
|
);
|
||||||
|
allColumnNames.value = filteredColumns.map((col) => col.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData
|
||||||
|
url="ItemTypes"
|
||||||
|
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (itemTypesOptions = data)"
|
||||||
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="ItemCategories"
|
||||||
|
:filter="{ fields: ['name'], order: 'name ASC' }"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (itemCategoriesOptions = data)"
|
||||||
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="Intrastats"
|
||||||
|
:filter="{ fields: ['description'], order: 'description ASC' }"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (intrastatOptions = data)"
|
||||||
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="Origins"
|
||||||
|
:filter="{ fields: ['code'], order: 'code ASC' }"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (originsOptions = data)"
|
||||||
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="TicketRequests/getItemTypeWorker"
|
||||||
|
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC' }"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (buyersOptions = data)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<QToolbar class="bg-vn-dark justify-end">
|
||||||
|
<div id="st-data">
|
||||||
|
<TableVisibleColumns
|
||||||
|
:all-columns="allColumnNames"
|
||||||
|
table-code="itemsIndex"
|
||||||
|
labels-traductions-path="item.list"
|
||||||
|
@on-config-saved="visibleColumns = ['picture', ...$event, 'actions']"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<QSpace />
|
||||||
|
<div id="st-actions"></div>
|
||||||
|
</QToolbar>
|
||||||
|
<QPage class="column items-center q-pa-md">
|
||||||
|
<VnPaginate
|
||||||
|
ref="paginateRef"
|
||||||
|
data-key="ItemList"
|
||||||
|
url="Items/filter"
|
||||||
|
:order="['isActive DESC', 'name', 'id']"
|
||||||
|
:limit="12"
|
||||||
|
:expr-builder="exprBuilder"
|
||||||
|
:user-params="params"
|
||||||
|
:offset="50"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<QTable
|
||||||
|
:rows="rows"
|
||||||
|
:columns="columns"
|
||||||
|
row-key="id"
|
||||||
|
:pagination="{ rowsPerPage: 0 }"
|
||||||
|
class="full-width q-mt-md"
|
||||||
|
:visible-columns="visibleColumns"
|
||||||
|
:no-data-label="t('globals.noResults')"
|
||||||
|
@row-click="(_, row) => redirectToItemSummary(row.id)"
|
||||||
|
>
|
||||||
|
<template #top-row="{ cols }">
|
||||||
|
<QTr>
|
||||||
|
<QTd
|
||||||
|
v-for="(col, index) in cols"
|
||||||
|
:key="index"
|
||||||
|
style="max-width: 100px"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="col.columnFilter.component"
|
||||||
|
v-if="col.columnFilter"
|
||||||
|
v-model="col.columnFilter.filterValue"
|
||||||
|
v-bind="col.columnFilter.attrs"
|
||||||
|
v-on="col.columnFilter.event(col)"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
</QTd>
|
||||||
|
</QTr>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-picture="{ row }">
|
||||||
|
<QTd>
|
||||||
|
<QImg
|
||||||
|
:src="`/api/Images/catalog/50x50/${row.id}/download?access_token=${token}`"
|
||||||
|
spinner-color="primary"
|
||||||
|
:ratio="1"
|
||||||
|
height="50px"
|
||||||
|
width="50px"
|
||||||
|
class="image"
|
||||||
|
/>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-id="{ row }">
|
||||||
|
<QTd @click.stop>
|
||||||
|
<QBtn flat color="primary">
|
||||||
|
{{ row.id }}
|
||||||
|
</QBtn>
|
||||||
|
<ItemDescriptorProxy :id="row.id" />
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-userName="{ row }">
|
||||||
|
<QTd @click.stop>
|
||||||
|
<QBtn flat color="primary" dense>
|
||||||
|
{{ row.userName }}
|
||||||
|
</QBtn>
|
||||||
|
<WorkerDescriptorProxy :id="row.buyerFk" />
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-description="{ row }">
|
||||||
|
<QTd class="col">
|
||||||
|
<span>{{ row.name }} {{ row.subName }}</span>
|
||||||
|
<fetched-tags :item="row" :max-length="6" />
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-isActive="{ row }">
|
||||||
|
<QTd>
|
||||||
|
<QCheckbox :model-value="!!row.isActive" disable />
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-actions="{ row }">
|
||||||
|
<QTd>
|
||||||
|
<QIcon
|
||||||
|
@click.stop="
|
||||||
|
openConfirmationModal(
|
||||||
|
t(`All it's properties will be copied`),
|
||||||
|
t('Do you want to clone this item?'),
|
||||||
|
() => cloneItem(row.id)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
class="q-ml-sm"
|
||||||
|
color="primary"
|
||||||
|
name="vn:clone"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('Clone') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
<QIcon
|
||||||
|
@click.stop="viewSummary(row.id, ItemSummary)"
|
||||||
|
class="q-ml-md"
|
||||||
|
color="primary"
|
||||||
|
name="preview"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<QTooltip class="text-no-wrap">
|
||||||
|
{{ t('Preview') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</template>
|
||||||
|
</VnPaginate>
|
||||||
|
|
||||||
|
<QPageSticky :offset="[20, 20]">
|
||||||
|
<QBtn @click="redirectToItemCreate()" color="primary" fab icon="add" />
|
||||||
|
<QTooltip class="text-no-wrap">
|
||||||
|
{{ t('New item') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QPageSticky>
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
New item: Nuevo artículo
|
||||||
|
All it's properties will be copied: Todas sus propiedades serán copiadas
|
||||||
|
Do you want to clone this item?: ¿Desea clonar este artículo?
|
||||||
|
Clone: Clonar
|
||||||
|
Preview: Vista previa
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -61,7 +61,7 @@ const data = ref(useCardDescription());
|
||||||
const setData = (entity) => {
|
const setData = (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
data.value = useCardDescription(entity.client.name, entity.id);
|
data.value = useCardDescription(entity.client.name, entity.id);
|
||||||
state.set('ClaimDescriptor', entity);
|
state.set('OrderDescriptor', entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConfirmationValue = (isConfirmed) => {
|
const getConfirmationValue = (isConfirmed) => {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script setup>
|
||||||
|
import VnDmsList from 'src/components/common/VnDmsList.vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
const route = useRoute();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<VnDmsList
|
||||||
|
:model="`WorkerDms/${route.params.id}/filter`"
|
||||||
|
update-model="Workers"
|
||||||
|
delete-model="WorkerDms"
|
||||||
|
download-model="WorkerDms"
|
||||||
|
default-dms-code="hhrrData"
|
||||||
|
filter="worker"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'ItemMain' },
|
redirect: { name: 'ItemMain' },
|
||||||
menus: {
|
menus: {
|
||||||
main: [],
|
main: ['ItemList'],
|
||||||
card: [],
|
card: [],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -18,7 +18,7 @@ export default {
|
||||||
path: '',
|
path: '',
|
||||||
name: 'ItemMain',
|
name: 'ItemMain',
|
||||||
component: () => import('src/pages/Item/ItemMain.vue'),
|
component: () => import('src/pages/Item/ItemMain.vue'),
|
||||||
redirect: { name: 'Itemlist' },
|
redirect: { name: 'ItemList' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: 'list',
|
||||||
|
@ -29,6 +29,14 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Item/ItemList.vue'),
|
component: () => import('src/pages/Item/ItemList.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
name: 'ItemCreate',
|
||||||
|
meta: {
|
||||||
|
title: 'create',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Item/ItemCreate.vue'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default {
|
||||||
'WorkerNotificationsManager',
|
'WorkerNotificationsManager',
|
||||||
'WorkerPBX',
|
'WorkerPBX',
|
||||||
'WorkerLog',
|
'WorkerLog',
|
||||||
|
'WorkerDms',
|
||||||
],
|
],
|
||||||
departmentCard: ['BasicData'],
|
departmentCard: ['BasicData'],
|
||||||
},
|
},
|
||||||
|
@ -127,6 +128,15 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Worker/Card/WorkerPBX.vue'),
|
component: () => import('src/pages/Worker/Card/WorkerPBX.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'WorkerDms',
|
||||||
|
path: 'dms',
|
||||||
|
meta: {
|
||||||
|
title: 'dms',
|
||||||
|
icon: 'cloud_upload',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Worker/Card/WorkerDms.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'WorkerLog',
|
name: 'WorkerLog',
|
||||||
path: 'log',
|
path: 'log',
|
||||||
|
|
|
@ -7,6 +7,7 @@ import routes from 'src/router/modules';
|
||||||
|
|
||||||
export const useNavigationStore = defineStore('navigationStore', () => {
|
export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
const modules = [
|
const modules = [
|
||||||
|
'item',
|
||||||
'shelving',
|
'shelving',
|
||||||
'order',
|
'order',
|
||||||
'customer',
|
'customer',
|
||||||
|
|
|
@ -5,37 +5,40 @@ describe('WagonTypeCreate', () => {
|
||||||
cy.viewport(1920, 1080);
|
cy.viewport(1920, 1080);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit(`/#/entry/${entryId}/dms`);
|
cy.visit(`/#/entry/${entryId}/dms`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create edit and remove new dms', () => {
|
it('should create edit and remove new dms', () => {
|
||||||
cy.addRow();
|
cy.addRow();
|
||||||
cy.get('.icon-attach').click()
|
cy.get('.icon-attach').click();
|
||||||
cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', {
|
cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', {
|
||||||
force: true,
|
force: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get("tbody > tr").then((value) => {
|
cy.get('tbody > tr').then((value) => {
|
||||||
|
const u = undefined;
|
||||||
|
|
||||||
//Create and check if exist new row
|
//Create and check if exist new row
|
||||||
let newFileTd = Cypress.$(value).length;
|
let newFileTd = Cypress.$(value).length;
|
||||||
cy.get('.q-btn--standard > .q-btn__content > .block').click();
|
cy.get('.q-btn--standard > .q-btn__content > .block').click();
|
||||||
expect(value).to.have.length(newFileTd++);
|
expect(value).to.have.length(newFileTd++);
|
||||||
const newRowSelector = `tbody > :nth-child(${newFileTd})`
|
const newRowSelector = `tbody > :nth-child(${newFileTd})`;
|
||||||
cy.waitForElement(newRowSelector);
|
cy.waitForElement(newRowSelector);
|
||||||
|
cy.validateRow(newRowSelector, [u, u, u, u, 'ENTRADA ID 1']);
|
||||||
|
|
||||||
//Edit new dms
|
//Edit new dms
|
||||||
const u = undefined;
|
const newDescription = 'entry id 1 modified';
|
||||||
cy.validateRow(newRowSelector, [u,u,u,u,'ENTRADA ID 1'])
|
const textAreaSelector =
|
||||||
cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click();
|
'.q-textarea > .q-field__inner > .q-field__control > .q-field__control-container';
|
||||||
})
|
cy.get(
|
||||||
// cy.log('newFileTd', newFileTd)
|
`tbody :nth-child(${newFileTd}) > .text-right > .no-wrap > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`
|
||||||
|
).click();
|
||||||
|
|
||||||
// //Create and check if exist new row
|
cy.get(textAreaSelector).clear();
|
||||||
// cy.log('newFileTd:', newFileTd);
|
cy.get(textAreaSelector).type(newDescription);
|
||||||
// cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click()
|
cy.saveCard();
|
||||||
|
cy.reload();
|
||||||
|
|
||||||
// cy.get(`tbody :nth-child(${newFileTd}) > :nth-child(5) > .q-tr > :nth-child(1) > span`).then((value) => {
|
cy.validateRow(newRowSelector, [u, u, u, u, newDescription]);
|
||||||
// cy.log(value)
|
});
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -37,6 +37,7 @@ describe('InvoiceInVat', () => {
|
||||||
|
|
||||||
it('should throw an error if there are fields undefined', () => {
|
it('should throw an error if there are fields undefined', () => {
|
||||||
cy.get(inputBtns).eq(0).click();
|
cy.get(inputBtns).eq(0).click();
|
||||||
|
cy.get(':nth-child(1) > .q-td.q-table--col-auto-width > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .default-icon').click();
|
||||||
cy.get(dialogBtns).eq(2).click();
|
cy.get(dialogBtns).eq(2).click();
|
||||||
cy.get('.q-notification__message').should('have.text', "The code can't be empty");
|
cy.get('.q-notification__message').should('have.text', "The code can't be empty");
|
||||||
});
|
});
|
||||||
|
@ -44,7 +45,7 @@ describe('InvoiceInVat', () => {
|
||||||
it('should correctly handle expense addition', () => {
|
it('should correctly handle expense addition', () => {
|
||||||
cy.get(inputBtns).eq(0).click();
|
cy.get(inputBtns).eq(0).click();
|
||||||
|
|
||||||
cy.get(dialogInputs).eq(0).click();
|
cy.get(':nth-child(1) > .q-td.q-table--col-auto-width > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .default-icon').click();
|
||||||
cy.get(dialogInputs).eq(0).type(randomInt);
|
cy.get(dialogInputs).eq(0).type(randomInt);
|
||||||
cy.get(dialogInputs).eq(1).click();
|
cy.get(dialogInputs).eq(1).click();
|
||||||
cy.get(dialogInputs).eq(1).type('This is a dummy expense');
|
cy.get(dialogInputs).eq(1).type('This is a dummy expense');
|
||||||
|
|
|
@ -8,9 +8,9 @@ describe('WorkerList', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load workers', () => {
|
it('should load workers', () => {
|
||||||
cy.get(workerFieldNames).eq(0).should('have.text', 'JessicaJones');
|
cy.get(workerFieldNames).eq(0).should('have.text', 'jessicajones');
|
||||||
cy.get(workerFieldNames).eq(1).should('have.text', 'BruceBanner');
|
cy.get(workerFieldNames).eq(1).should('have.text', 'brucebanner');
|
||||||
cy.get(workerFieldNames).eq(2).should('have.text', 'CharlesXavier');
|
cy.get(workerFieldNames).eq(2).should('have.text', 'charlesxavier');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open the worker summary', () => {
|
it('should open the worker summary', () => {
|
||||||
|
|
|
@ -60,7 +60,6 @@ describe('WorkerNotificationsManager', () => {
|
||||||
it('should active a notification if you are their boss', () => {
|
it('should active a notification if you are their boss', () => {
|
||||||
cy.login('salesBoss');
|
cy.login('salesBoss');
|
||||||
cy.visit(`/#/worker/${salesPersonId}/notifications`);
|
cy.visit(`/#/worker/${salesPersonId}/notifications`);
|
||||||
cy.waitForElement(activeList);
|
|
||||||
cy.waitForElement(availableList);
|
cy.waitForElement(availableList);
|
||||||
|
|
||||||
cy.get(activeList)
|
cy.get(activeList)
|
||||||
|
|
|
@ -6,7 +6,8 @@ describe('WorkerSummary', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load worker summary', () => {
|
it('should load worker summary', () => {
|
||||||
cy.get('.summaryHeader > div').should('have.text', '19 - salesBoss salesBoss');
|
cy.waitForElement('.summaryHeader');
|
||||||
|
cy.get('.summaryHeader > div').should('have.text', '19 - salesboss salesboss');
|
||||||
cy.get(':nth-child(1) > :nth-child(2) > .value > span').should(
|
cy.get(':nth-child(1) > :nth-child(2) > .value > span').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'salesBossNick'
|
'salesBossNick'
|
||||||
|
|
Loading…
Reference in New Issue