Compare commits
No commits in common. "d178d7dc6a928baf53fd5556d794bf98e5c0518f" and "058ddc8e9a315b44a254c467b0b2ba450ff8a10f" have entirely different histories.
d178d7dc6a
...
058ddc8e9a
|
@ -5,8 +5,6 @@ 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.18.0",
|
"version": "24.16.0",
|
||||||
"description": "Salix frontend",
|
"description": "Salix frontend",
|
||||||
"productName": "Salix",
|
"productName": "Salix",
|
||||||
"author": "Verdnatura",
|
"author": "Verdnatura",
|
||||||
|
|
|
@ -93,11 +93,13 @@ module.exports = configure(function (/* ctx */) {
|
||||||
[
|
[
|
||||||
VueI18nPlugin({
|
VueI18nPlugin({
|
||||||
runtimeOnly: false,
|
runtimeOnly: false,
|
||||||
include: [
|
|
||||||
path.resolve(__dirname, './src/i18n/locale/**'),
|
|
||||||
path.resolve(__dirname, './src/pages/**/locale/**'),
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
// if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
|
||||||
|
// compositionOnly: false,
|
||||||
|
// you need to set i18n resource including paths !
|
||||||
|
include: path.resolve(__dirname, './src/i18n/**'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { boot } from 'quasar/wrappers';
|
import { boot } from 'quasar/wrappers';
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from 'vue-i18n';
|
||||||
import messages from 'src/i18n';
|
import messages from 'src/i18n';
|
||||||
import { locales } from 'src/i18n/handle';
|
|
||||||
|
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
locale: navigator.language || navigator.userLanguage,
|
locale: navigator.language || navigator.userLanguage,
|
||||||
|
@ -13,9 +12,8 @@ const i18n = createI18n({
|
||||||
legacy: false,
|
legacy: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default boot(async ({ app }) => {
|
export default boot(({ app }) => {
|
||||||
// Set i18n instance on app
|
// Set i18n instance on app
|
||||||
await locales();
|
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ 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"
|
||||||
|
@ -86,7 +85,6 @@ 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
|
||||||
|
|
|
@ -61,6 +61,7 @@ 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,
|
||||||
|
@ -77,7 +78,6 @@ 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,10 +91,6 @@ 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) {
|
||||||
|
@ -110,6 +106,7 @@ 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;
|
||||||
|
@ -127,7 +124,6 @@ async function paginate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function endPagination() {
|
function endPagination() {
|
||||||
hasMoreData.value = arrayData.hasMoreData.value;
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
emit('onFetch', store.data);
|
emit('onFetch', store.data);
|
||||||
emit('onPaginate');
|
emit('onPaginate');
|
||||||
|
@ -146,8 +142,6 @@ 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>
|
||||||
|
@ -196,7 +190,10 @@ defineExpose({ fetch, addFilter });
|
||||||
<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">
|
<div
|
||||||
|
v-if="!isLoading && arrayData.hasMoreData"
|
||||||
|
class="w-full flex justify-center q-mt-md"
|
||||||
|
>
|
||||||
<QBtn color="primary" :label="t('Load more data')" @click="paginate()" />
|
<QBtn color="primary" :label="t('Load more data')" @click="paginate()" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="vn-row q-gutter-md q-mb-md">
|
<div id="row" class="q-gutter-md q-mb-md">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scopped>
|
<style lang="scss" scopped>
|
||||||
.vn-row {
|
#row {
|
||||||
display: flex;
|
display: flex;
|
||||||
> * {
|
> * {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 800px) {
|
@media screen and (max-width: 800px) {
|
||||||
.vn-row {
|
#row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<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({
|
||||||
|
|
|
@ -144,8 +144,6 @@ 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 };
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
||||||
const modules = import.meta.glob(`../pages/**/locale/**.yml`);
|
|
||||||
import translations from './index';
|
|
||||||
const LOCALE_EXTENSION = '.yml';
|
|
||||||
|
|
||||||
export async function locales() {
|
|
||||||
for await (const module of Object.keys(modules)) {
|
|
||||||
const splittedFile = module.split('/');
|
|
||||||
const lang = splittedFile.pop().split(LOCALE_EXTENSION)[0];
|
|
||||||
const moduleFiles = splittedFile.join('/') + '/' + lang + LOCALE_EXTENSION;
|
|
||||||
import(moduleFiles).then((t) => {
|
|
||||||
Object.assign(translations[lang], t.default);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return translations;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default translations;
|
|
|
@ -1,15 +1,9 @@
|
||||||
const files = import.meta.glob(`./locale/*.yml`);
|
import en from './en';
|
||||||
const translations = {};
|
import es from './es';
|
||||||
|
|
||||||
for (const file in files) {
|
|
||||||
const lang = file.split('/').at(2).split('.')[0];
|
|
||||||
import(file).then((t) => {
|
|
||||||
translations[lang] = t.default;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const localeEquivalence = {
|
export const localeEquivalence = {
|
||||||
en: 'en-GB',
|
'en':'en-GB'
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
en: en,
|
||||||
|
es: es,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default translations;
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,6 @@ 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();
|
||||||
|
@ -178,7 +177,7 @@ function openDialog(dmsId) {
|
||||||
@on-fetch="getClaimDms"
|
@on-fetch="getClaimDms"
|
||||||
>
|
>
|
||||||
<template #header="{ entity: { claim } }">
|
<template #header="{ entity: { claim } }">
|
||||||
{{ claim.id }} - {{ claim.client.name }} ({{ claim.client.id }})
|
{{ claim.id }} - {{ claim.client.name }}
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
|
@ -215,10 +214,10 @@ function openDialog(dmsId) {
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :label="t('claim.summary.customer')">
|
<VnLv :label="t('claim.summary.customer')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link cursor-pointer">
|
<VnUserLink
|
||||||
{{ claim.client?.name }}
|
:name="claim.client?.name"
|
||||||
<CustomerDescriptorProxy :id="claim.clientFk" />
|
:worker-id="claim.client?.id"
|
||||||
</span>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv
|
<VnLv
|
||||||
|
|
|
@ -48,17 +48,13 @@ const zones = ref();
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput :label="t('Name')" v-model="params.name" is-outlined />
|
||||||
:label="t('customerFilter.filter.name')"
|
|
||||||
v-model="params.name"
|
|
||||||
is-outlined
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('customerFilter.filter.socialName')"
|
:label="t('Social Name')"
|
||||||
v-model="params.socialName"
|
v-model="params.socialName"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
|
@ -174,6 +170,8 @@ en:
|
||||||
params:
|
params:
|
||||||
search: Contains
|
search: Contains
|
||||||
fi: FI
|
fi: FI
|
||||||
|
name: Name
|
||||||
|
socialName: Social Name
|
||||||
salesPersonFk: Salesperson
|
salesPersonFk: Salesperson
|
||||||
provinceFk: Province
|
provinceFk: Province
|
||||||
city: City
|
city: City
|
||||||
|
@ -185,6 +183,8 @@ es:
|
||||||
params:
|
params:
|
||||||
search: Contiene
|
search: Contiene
|
||||||
fi: NIF
|
fi: NIF
|
||||||
|
name: Nombre
|
||||||
|
socialName: Razón Social
|
||||||
salesPersonFk: Comercial
|
salesPersonFk: Comercial
|
||||||
provinceFk: Provincia
|
provinceFk: Provincia
|
||||||
city: Ciudad
|
city: Ciudad
|
||||||
|
@ -193,6 +193,8 @@ es:
|
||||||
zoneFk: Zona
|
zoneFk: Zona
|
||||||
postcode: CP
|
postcode: CP
|
||||||
FI: NIF
|
FI: NIF
|
||||||
|
Name: Nombre
|
||||||
|
Social Name: Razón social
|
||||||
Salesperson: Comercial
|
Salesperson: Comercial
|
||||||
Province: Provincia
|
Province: Provincia
|
||||||
City: Ciudad
|
City: Ciudad
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
customerFilter:
|
|
||||||
filter:
|
|
||||||
name: Name
|
|
||||||
socialName: Social name
|
|
|
@ -1,4 +0,0 @@
|
||||||
customerFilter:
|
|
||||||
filter:
|
|
||||||
name: Nombre
|
|
||||||
socialName: Razón Social
|
|
|
@ -1,19 +1,19 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import CrudModel from 'components/CrudModel.vue';
|
import CrudModel from 'components/CrudModel.vue';
|
||||||
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||||
|
|
||||||
const { params } = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const entryObservationsRef = ref(null);
|
const entryObservationsRef = ref(null);
|
||||||
const entryObservationsOptions = ref([]);
|
const entryObservationsOptions = ref([]);
|
||||||
const selected = ref([]);
|
|
||||||
|
|
||||||
const sortEntryObservationOptions = (data) => {
|
const sortEntryObservationOptions = (data) => {
|
||||||
entryObservationsOptions.value = [...data].sort((a, b) =>
|
entryObservationsOptions.value = [...data].sort((a, b) =>
|
||||||
|
@ -24,29 +24,6 @@ const sortEntryObservationOptions = (data) => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (entryObservationsRef.value) entryObservationsRef.value.reload();
|
if (entryObservationsRef.value) entryObservationsRef.value.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
const columns = computed(() => [
|
|
||||||
{
|
|
||||||
name: 'observationType',
|
|
||||||
label: t('entry.notes.observationType'),
|
|
||||||
field: (row) => row.observationTypeFk,
|
|
||||||
sortable: true,
|
|
||||||
options: entryObservationsOptions.value,
|
|
||||||
required: true,
|
|
||||||
model: 'observationTypeFk',
|
|
||||||
optionValue: 'id',
|
|
||||||
optionLabel: 'description',
|
|
||||||
tabIndex: 1,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'description',
|
|
||||||
label: t('globals.description'),
|
|
||||||
field: (row) => row.description,
|
|
||||||
tabIndex: 2,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
@ -60,90 +37,65 @@ const columns = computed(() => [
|
||||||
model="EntryAccount"
|
model="EntryAccount"
|
||||||
:filter="{
|
:filter="{
|
||||||
fields: ['id', 'entryFk', 'observationTypeFk', 'description'],
|
fields: ['id', 'entryFk', 'observationTypeFk', 'description'],
|
||||||
where: { entryFk: params.id },
|
where: { entryFk: route.params.id },
|
||||||
}"
|
}"
|
||||||
ref="entryObservationsRef"
|
ref="entryObservationsRef"
|
||||||
:data-required="{ entryFk: params.id }"
|
:default-remove="false"
|
||||||
v-model:selected="selected"
|
:data-required="{ entryFk: route.params.id }"
|
||||||
>
|
>
|
||||||
<template #body="{ rows, validate }">
|
<template #body="{ rows, validate }">
|
||||||
<QTable
|
<QCard class="q-pa-md">
|
||||||
v-model:selected="selected"
|
<VnRow
|
||||||
:columns="columns"
|
v-for="(row, index) in rows"
|
||||||
:rows="rows"
|
:key="index"
|
||||||
:pagination="{ rowsPerPage: 0 }"
|
class="row q-gutter-md q-mb-md"
|
||||||
row-key="$index"
|
>
|
||||||
selection="multiple"
|
<VnSelectFilter
|
||||||
hide-pagination
|
:label="t('entry.notes.observationType')"
|
||||||
:grid="$q.screen.lt.md"
|
v-model="row.observationTypeFk"
|
||||||
table-header-class="text-left"
|
:options="entryObservationsOptions"
|
||||||
>
|
:disable="!!row.id"
|
||||||
<template #body-cell-observationType="{ row, col }">
|
option-label="description"
|
||||||
<QTd>
|
option-value="id"
|
||||||
<VnSelectFilter
|
hide-selected
|
||||||
v-model="row[col.model]"
|
/>
|
||||||
:options="col.options"
|
|
||||||
:option-value="col.optionValue"
|
<VnInput
|
||||||
:option-label="col.optionLabel"
|
:label="t('globals.description')"
|
||||||
:autofocus="col.tabIndex == 1"
|
v-model="row.description"
|
||||||
input-debounce="0"
|
:rules="validate('EntryObservation.description')"
|
||||||
hide-selected
|
/>
|
||||||
:required="true"
|
|
||||||
/>
|
<div class="row justify-center items-center">
|
||||||
</QTd>
|
<QIcon
|
||||||
</template>
|
name="delete"
|
||||||
<template #body-cell-description="{ row, col }">
|
size="sm"
|
||||||
<QTd>
|
class="cursor-pointer"
|
||||||
<VnInput
|
color="primary"
|
||||||
:label="t('globals.description')"
|
@click="entryObservationsRef.remove([row])"
|
||||||
v-model="row[col.name]"
|
>
|
||||||
:rules="validate('EntryObservation.description')"
|
<QTooltip>
|
||||||
/>
|
{{ t('Remove note') }}
|
||||||
</QTd>
|
</QTooltip>
|
||||||
</template>
|
</QIcon>
|
||||||
<template #item="props">
|
|
||||||
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
|
|
||||||
<QCard bordered flat>
|
|
||||||
<QCardSection>
|
|
||||||
<QCheckbox v-model="props.selected" dense />
|
|
||||||
</QCardSection>
|
|
||||||
<QSeparator />
|
|
||||||
<QList dense>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnSelectFilter
|
|
||||||
v-model="props.row.observationTypeFk"
|
|
||||||
:options="entryObservationsOptions"
|
|
||||||
option-value="id"
|
|
||||||
option-label="description"
|
|
||||||
input-debounce="0"
|
|
||||||
hide-selected
|
|
||||||
:required="true"
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnInput
|
|
||||||
:label="t('globals.description')"
|
|
||||||
v-model="props.row.description"
|
|
||||||
:rules="
|
|
||||||
validate('EntryObservation.description')
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</QList>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</VnRow>
|
||||||
</QTable>
|
<QIcon
|
||||||
|
name="add"
|
||||||
|
size="sm"
|
||||||
|
class="cursor-pointer"
|
||||||
|
color="primary"
|
||||||
|
@click="entryObservationsRef.insert()"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('Add note') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</QCard>
|
||||||
</template>
|
</template>
|
||||||
</CrudModel>
|
</CrudModel>
|
||||||
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
|
||||||
<QBtn fab color="primary" icon="add" @click="entryObservationsRef.insert()" />
|
|
||||||
</QPageSticky>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Add note: Añadir nota
|
Add note: Añadir nota
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { onMounted } from 'vue';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
|
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||||
|
@ -21,11 +19,6 @@ const props = defineProps({
|
||||||
const currenciesOptions = ref([]);
|
const currenciesOptions = ref([]);
|
||||||
const companiesOptions = ref([]);
|
const companiesOptions = ref([]);
|
||||||
const suppliersOptions = ref([]);
|
const suppliersOptions = ref([]);
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
onMounted(async () => {
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -65,7 +58,7 @@ onMounted(async () => {
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.search"
|
v-model="params.search"
|
||||||
:label="t('entryFilter.filter.search')"
|
:label="t('params.search')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -74,7 +67,7 @@ onMounted(async () => {
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.reference"
|
v-model="params.reference"
|
||||||
:label="t('entryFilter.filter.reference')"
|
:label="t('params.reference')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -217,7 +210,8 @@ onMounted(async () => {
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
params:
|
params:
|
||||||
|
search: General search
|
||||||
|
reference: Reference
|
||||||
invoiceNumber: Invoice number
|
invoiceNumber: Invoice number
|
||||||
travelFk: Travel
|
travelFk: Travel
|
||||||
companyFk: Company
|
companyFk: Company
|
||||||
|
@ -231,7 +225,8 @@ en:
|
||||||
isOrdered: Ordered
|
isOrdered: Ordered
|
||||||
es:
|
es:
|
||||||
params:
|
params:
|
||||||
|
search: Búsqueda general
|
||||||
|
reference: Referencia
|
||||||
invoiceNumber: Núm. factura
|
invoiceNumber: Núm. factura
|
||||||
travelFk: Envío
|
travelFk: Envío
|
||||||
companyFk: Empresa
|
companyFk: Empresa
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
entryList:
|
|
||||||
list:
|
|
||||||
inventoryEntry: 'Inventory entry'
|
|
||||||
virtualEntry: 'Virtual entry'
|
|
||||||
entryFilter:
|
|
||||||
filter:
|
|
||||||
search: 'General search'
|
|
||||||
reference: 'Reference'
|
|
|
@ -1,8 +0,0 @@
|
||||||
entryList:
|
|
||||||
list:
|
|
||||||
inventoryEntry: 'Es inventario'
|
|
||||||
virtualEntry: 'Es una redada'
|
|
||||||
entryFilter:
|
|
||||||
filter:
|
|
||||||
search: 'Búsqueda general'
|
|
||||||
reference: 'Referencia'
|
|
|
@ -1 +0,0 @@
|
||||||
<template>Item create view</template>
|
|
|
@ -1,577 +1 @@
|
||||||
<script setup>
|
<template>Item list</template>
|
||||||
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('OrderDescriptor', entity);
|
state.set('ClaimDescriptor', entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConfirmationValue = (isConfirmed) => {
|
const getConfirmationValue = (isConfirmed) => {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ const decrement = (paramsObj, key) => {
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelectFilter
|
<VnSelectFilter
|
||||||
:label="t('travelFilter.filter.agencyModeFk')"
|
:label="t('params.agencyModeFk')"
|
||||||
v-model="params.agencyModeFk"
|
v-model="params.agencyModeFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
:options="agenciesOptions"
|
:options="agenciesOptions"
|
||||||
|
@ -78,7 +79,7 @@ const decrement = (paramsObj, key) => {
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelectFilter
|
<VnSelectFilter
|
||||||
:label="t('travelFilter.filter.warehouseOutFk')"
|
:label="t('params.warehouseOutFk')"
|
||||||
v-model="params.warehouseOutFk"
|
v-model="params.warehouseOutFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
:options="warehousesOptions"
|
:options="warehousesOptions"
|
||||||
|
@ -94,7 +95,7 @@ const decrement = (paramsObj, key) => {
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelectFilter
|
<VnSelectFilter
|
||||||
:label="t('travelFilter.filter.warehouseInFk')"
|
:label="t('params.warehouseInFk')"
|
||||||
v-model="params.warehouseInFk"
|
v-model="params.warehouseInFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
:options="warehousesOptions"
|
:options="warehousesOptions"
|
||||||
|
@ -112,7 +113,7 @@ const decrement = (paramsObj, key) => {
|
||||||
<QInput
|
<QInput
|
||||||
v-model="params.scopeDays"
|
v-model="params.scopeDays"
|
||||||
type="number"
|
type="number"
|
||||||
:label="t('travelFilter.filter.scopeDays')"
|
:label="t('params.scopeDays')"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
|
@ -210,6 +211,10 @@ const decrement = (paramsObj, key) => {
|
||||||
en:
|
en:
|
||||||
params:
|
params:
|
||||||
search: Id/Reference
|
search: Id/Reference
|
||||||
|
agencyModeFk: Agency
|
||||||
|
warehouseInFk: Warehouse In
|
||||||
|
warehouseOutFk: Warehouse Out
|
||||||
|
scopeDays: Days onward
|
||||||
landedFrom: Landed from
|
landedFrom: Landed from
|
||||||
landedTo: Landed to
|
landedTo: Landed to
|
||||||
continent: Continent out
|
continent: Continent out
|
||||||
|
@ -217,6 +222,10 @@ en:
|
||||||
es:
|
es:
|
||||||
params:
|
params:
|
||||||
search: Id/Referencia
|
search: Id/Referencia
|
||||||
|
agencyModeFk: Agencia
|
||||||
|
warehouseInFk: Alm. entrada
|
||||||
|
warehouseOutFk: Alm. salida
|
||||||
|
scopeDays: Días adelante
|
||||||
landedFrom: Llegada desde
|
landedFrom: Llegada desde
|
||||||
landedTo: Llegada hasta
|
landedTo: Llegada hasta
|
||||||
continent: Cont. Salida
|
continent: Cont. Salida
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
travelFilter:
|
|
||||||
filter:
|
|
||||||
warehouseOutFk: 'Warehouse Out'
|
|
||||||
warehouseInFk: 'Warehouse In'
|
|
||||||
agencyModeFk: 'Agency'
|
|
||||||
scopeDays: 'Days onward'
|
|
|
@ -1,6 +0,0 @@
|
||||||
travelFilter:
|
|
||||||
filter:
|
|
||||||
warehouseInFk: 'Alm. entrada'
|
|
||||||
warehouseOutFk: 'Alm. salida'
|
|
||||||
agencyModeFk: 'Agencia'
|
|
||||||
scopeDays: 'Días adelante'
|
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'ItemMain' },
|
redirect: { name: 'ItemMain' },
|
||||||
menus: {
|
menus: {
|
||||||
main: ['ItemList'],
|
main: [],
|
||||||
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,14 +29,6 @@ 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'),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,6 @@ 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,40 +5,37 @@ 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 newDescription = 'entry id 1 modified';
|
const u = undefined;
|
||||||
const textAreaSelector =
|
cy.validateRow(newRowSelector, [u,u,u,u,'ENTRADA ID 1'])
|
||||||
'.q-textarea > .q-field__inner > .q-field__control > .q-field__control-container';
|
cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click();
|
||||||
cy.get(
|
})
|
||||||
`tbody :nth-child(${newFileTd}) > .text-right > .no-wrap > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`
|
// cy.log('newFileTd', newFileTd)
|
||||||
).click();
|
|
||||||
|
|
||||||
cy.get(textAreaSelector).clear();
|
// //Create and check if exist new row
|
||||||
cy.get(textAreaSelector).type(newDescription);
|
// cy.log('newFileTd:', newFileTd);
|
||||||
cy.saveCard();
|
// cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click()
|
||||||
cy.reload();
|
|
||||||
|
|
||||||
cy.validateRow(newRowSelector, [u, u, u, u, newDescription]);
|
// cy.get(`tbody :nth-child(${newFileTd}) > :nth-child(5) > .q-tr > :nth-child(1) > span`).then((value) => {
|
||||||
});
|
// cy.log(value)
|
||||||
|
// });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -37,7 +37,6 @@ 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");
|
||||||
});
|
});
|
||||||
|
@ -45,7 +44,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(':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).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,6 +60,7 @@ 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,8 +6,7 @@ describe('WorkerSummary', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load worker summary', () => {
|
it('should load worker summary', () => {
|
||||||
cy.waitForElement('.summaryHeader');
|
cy.get('.summaryHeader > div').should('have.text', '19 - salesBoss salesBoss');
|
||||||
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'
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue({
|
vue({
|
||||||
template: {
|
template: {
|
||||||
transformAssetUrls,
|
transformAssetUrls
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
quasar({
|
quasar({
|
||||||
|
|
Loading…
Reference in New Issue