From 168201c755f50cefb633598e5488a88bf48068d9 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 15 Jul 2024 12:25:54 +0200
Subject: [PATCH 001/207] refs #7283 itemList table

---
 src/pages/Item/ItemList.vue | 477 +++++-------------------------------
 1 file changed, 68 insertions(+), 409 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index f1e3629cd..334ef2604 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -3,114 +3,48 @@ 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 VnSelect from 'src/components/common/VnSelect.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 ItemListFilter from './ItemListFilter.vue';
-
+import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toDateFormat } from 'src/filters/date.js';
 import { dashIfEmpty } from 'src/filters';
-import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import { useVnConfirm } from 'composables/useVnConfirm';
 import axios from 'axios';
-import RightMenu from 'src/components/common/RightMenu.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
-import VnImg from 'src/components/ui/VnImg.vue';
 
 const router = useRouter();
 const stateStore = useStateStore();
 const { t } = useI18n();
-const { viewSummary } = useSummaryDialog();
-const { openConfirmationModal } = useVnConfirm();
+const tableRef = ref();
 
-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 itemFilter = {
+    include: [
+        {
+            relation: 'trainingCourseType',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'trainingCenter',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+    ],
 };
-
-const params = reactive({ isFloramondo: false, isActive: true });
-
-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,
-            },
+        isId: true,
+        chip: {
+            condition: () => true,
         },
     },
     {
@@ -118,101 +52,41 @@ const columns = computed(() => [
         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,
-            },
-        },
+        create: 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: VnSelect,
-            filterParamKey: 'typeFk',
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                options: itemTypesOptions.value,
-                'option-value': 'id',
-                'option-label': 'name',
-                dense: true,
-            },
+        component: 'select',
+        attrs: {
+            url: 'ItemType',
+            fields: ['id', 'name'],
         },
     },
 
@@ -221,18 +95,10 @@ const columns = computed(() => [
         field: 'category',
         name: 'category',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnSelect,
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                options: itemCategoriesOptions.value,
-                'option-value': 'name',
-                'option-label': 'name',
-                dense: true,
-            },
+        component: 'select',
+        attrs: {
+            url: 'ItemCategory',
+            fields: ['id', 'name'],
         },
     },
 
@@ -241,18 +107,10 @@ const columns = computed(() => [
         field: 'intrastat',
         name: 'intrastat',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnSelect,
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                options: intrastatOptions.value,
-                'option-value': 'description',
-                'option-label': 'description',
-                dense: true,
-            },
+        component: 'select',
+        attrs: {
+            url: 'Intrastat',
+            fields: ['id', 'description'],
         },
     },
     {
@@ -260,18 +118,10 @@ const columns = computed(() => [
         field: 'origin',
         name: 'origin',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnSelect,
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                options: originsOptions.value,
-                'option-value': 'code',
-                'option-label': 'code',
-                dense: true,
-            },
+        component: 'select',
+        attrs: {
+            url: 'Origin',
+            fields: ['id', 'name'],
         },
     },
     {
@@ -279,36 +129,13 @@ const columns = computed(() => [
         field: 'userName',
         name: 'userName',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnSelect,
-            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,
-            },
-        },
+        component: 'input',
         format: (val) => dashIfEmpty(val),
     },
     {
@@ -316,16 +143,7 @@ const columns = computed(() => [
         field: 'stemMultiplier',
         name: 'stemMultiplier',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        component: 'input',
         format: (val) => dashIfEmpty(val),
     },
     {
@@ -333,40 +151,26 @@ const columns = computed(() => [
         field: 'isActive',
         name: 'isActive',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
+        component: 'checkbox',
     },
     {
         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,
-            },
+        component: 'select',
+        attrs: {
+            url: 'Producer',
+            fields: ['id', 'name'],
         },
-        format: (val) => dashIfEmpty(val),
     },
     {
         label: t('item.list.landed'),
         field: 'landed',
         name: 'landed',
         align: 'left',
-        sortable: true,
+        component: 'date',
         format: (val) => dashIfEmpty(toDateFormat(val)),
-        columnFilter: null,
-    },
-    {
-        label: '',
-        name: 'actions',
-        align: 'left',
-        columnFilter: null,
     },
 ]);
 
@@ -388,49 +192,11 @@ const cloneItem = async (itemFk) => {
     }
 };
 
-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)"
-    />
-    <VnSubToolbar>
+    <!-- <VnSubToolbar>
         <template #st-data>
             <TableVisibleColumns
                 :all-columns="allColumnNames"
@@ -439,135 +205,28 @@ onUnmounted(() => (stateStore.rightDrawer = false));
                 @on-config-saved="visibleColumns = ['picture', ...$event, 'actions']"
             />
         </template>
-    </VnSubToolbar>
-    <RightMenu>
-        <template #right-panel>
-            <ItemListFilter data-key="ItemList" />
-        </template>
-    </RightMenu>
-    <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"
-            :keep-opts="['userParams']"
-            :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>
-                            <VnImg
-                                size="50x50"
-                                :id="row.id"
-                                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>
-                            <FetchedTags :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('globals.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>
+    </VnSubToolbar> -->
+    <VnTable
+        ref="tableRef"
+        data-key="ItemList"
+        url="Items"
+        url-create="Items"
+        save-url="Items/crud"
+        :create="{
+            urlCreate: 'Items',
+            title: 'Create Item',
+            onDataSaved: () => tableRef.redirect(),
+            formInitialData: {
+                editorFk: entityId,
+            },
+        }"
+        order="id ASC"
+        :columns="columns"
+        auto-load
+        :right-search="false"
+        :is-editable="false"
+        :use-model="true"
+    />
 </template>
 
 <i18n>

From 16b5b5d9a1111f31a8c07f53272a8f6f77ae71ba Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 15 Jul 2024 13:48:59 +0200
Subject: [PATCH 002/207] refs #7283 filter

---
 src/pages/Item/ItemList.vue | 64 +++++++++++++++++++++++++++++++------
 1 file changed, 55 insertions(+), 9 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 334ef2604..4c49f068f 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -1,30 +1,39 @@
 <script setup>
 import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
+import { useRouter, useRoute } from 'vue-router';
+import VnImg from 'src/components/ui/VnImg.vue';
 
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
-import { toDateFormat } from 'src/filters/date.js';
+import { toDate } from 'src/filters';
 import { dashIfEmpty } from 'src/filters';
 import axios from 'axios';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
+const entityId = computed(() => route.params.id);
 
 const router = useRouter();
 const stateStore = useStateStore();
 const { t } = useI18n();
 const tableRef = ref();
+const route = useRoute();
 
 const itemFilter = {
     include: [
         {
-            relation: 'trainingCourseType',
+            relation: 'itemType',
             scope: {
                 fields: ['id', 'name'],
             },
         },
         {
-            relation: 'trainingCenter',
+            relation: 'intrastat',
+            scope: {
+                fields: ['id', 'description'],
+            },
+        },
+        {
+            relation: 'origin',
             scope: {
                 fields: ['id', 'name'],
             },
@@ -34,8 +43,18 @@ const itemFilter = {
 const columns = computed(() => [
     {
         label: '',
-        name: 'picture',
+        name: 'image',
         align: 'left',
+        columnField: {
+            component: VnImg,
+            attrs: (id) => {
+                return {
+                    id,
+                    width: '50px',
+                };
+            },
+        },
+        columnFilter: false,
     },
     {
         label: t('item.list.id'),
@@ -88,6 +107,10 @@ const columns = computed(() => [
             url: 'ItemType',
             fields: ['id', 'name'],
         },
+        columnField: {
+            component: null,
+        },
+        create: true,
     },
 
     {
@@ -100,6 +123,9 @@ const columns = computed(() => [
             url: 'ItemCategory',
             fields: ['id', 'name'],
         },
+        columnField: {
+            component: null,
+        },
     },
 
     {
@@ -112,6 +138,10 @@ const columns = computed(() => [
             url: 'Intrastat',
             fields: ['id', 'description'],
         },
+        columnField: {
+            component: null,
+        },
+        create: true,
     },
     {
         label: t('item.list.origin'),
@@ -123,6 +153,10 @@ const columns = computed(() => [
             url: 'Origin',
             fields: ['id', 'name'],
         },
+        columnField: {
+            component: null,
+        },
+        create: true,
     },
     {
         label: t('item.list.userName'),
@@ -136,7 +170,9 @@ const columns = computed(() => [
         name: 'weightByPiece',
         align: 'left',
         component: 'input',
-        format: (val) => dashIfEmpty(val),
+        columnField: {
+            component: null,
+        },
     },
     {
         label: t('item.list.stemMultiplier'),
@@ -144,7 +180,9 @@ const columns = computed(() => [
         name: 'stemMultiplier',
         align: 'left',
         component: 'input',
-        format: (val) => dashIfEmpty(val),
+        columnField: {
+            component: null,
+        },
     },
     {
         label: t('item.list.isActive'),
@@ -163,6 +201,9 @@ const columns = computed(() => [
             url: 'Producer',
             fields: ['id', 'name'],
         },
+        columnField: {
+            component: null,
+        },
     },
     {
         label: t('item.list.landed'),
@@ -170,7 +211,10 @@ const columns = computed(() => [
         name: 'landed',
         align: 'left',
         component: 'date',
-        format: (val) => dashIfEmpty(toDateFormat(val)),
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
     },
 ]);
 
@@ -209,9 +253,10 @@ onUnmounted(() => (stateStore.rightDrawer = false));
     <VnTable
         ref="tableRef"
         data-key="ItemList"
-        url="Items"
+        url="Items/filter"
         url-create="Items"
         save-url="Items/crud"
+        :filter="itemFilter"
         :create="{
             urlCreate: 'Items',
             title: 'Create Item',
@@ -223,6 +268,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         order="id ASC"
         :columns="columns"
         auto-load
+        redirect="Item"
         :right-search="false"
         :is-editable="false"
         :use-model="true"

From afbcd2ebda00ec2487ebc090940f83405ce54f1f Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 15 Jul 2024 14:31:33 +0200
Subject: [PATCH 003/207] refs #7283 item filters

---
 src/pages/Item/ItemList.vue     |  14 ++--
 src/pages/Item/ItemTypeList.vue | 140 ++++++++++++++++++++------------
 2 files changed, 91 insertions(+), 63 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 4c49f068f..e2c5f4bb3 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -7,9 +7,7 @@ import VnImg from 'src/components/ui/VnImg.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
-import { dashIfEmpty } from 'src/filters';
 import axios from 'axios';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const entityId = computed(() => route.params.id);
 
 const router = useRouter();
@@ -104,7 +102,7 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         attrs: {
-            url: 'ItemType',
+            url: 'ItemTypes',
             fields: ['id', 'name'],
         },
         columnField: {
@@ -112,7 +110,6 @@ const columns = computed(() => [
         },
         create: true,
     },
-
     {
         label: t('item.list.category'),
         field: 'category',
@@ -120,14 +117,13 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         attrs: {
-            url: 'ItemCategory',
+            url: 'ItemCategories',
             fields: ['id', 'name'],
         },
         columnField: {
             component: null,
         },
     },
-
     {
         label: t('item.list.intrastat'),
         field: 'intrastat',
@@ -135,7 +131,7 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         attrs: {
-            url: 'Intrastat',
+            url: 'Intrastats',
             fields: ['id', 'description'],
         },
         columnField: {
@@ -150,7 +146,7 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         attrs: {
-            url: 'Origin',
+            url: 'Origins',
             fields: ['id', 'name'],
         },
         columnField: {
@@ -198,7 +194,7 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         attrs: {
-            url: 'Producer',
+            url: 'Producers',
             fields: ['id', 'name'],
         },
         columnField: {
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 125672d60..c02f9bb43 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -1,20 +1,13 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { useRouter } from 'vue-router';
-
-import VnPaginate from 'src/components/ui/VnPaginate.vue';
-import VnLv from 'src/components/ui/VnLv.vue';
-import CardList from 'src/components/ui/CardList.vue';
-import ItemTypeSummary from 'src/pages/ItemType/Card/ItemTypeSummary.vue';
-import ItemTypeFilter from 'src/pages/ItemType/ItemTypeFilter.vue';
+import { ref, computed } from 'vue';
 import ItemTypeSearchbar from '../ItemType/ItemTypeSearchbar.vue';
-import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import RightMenu from 'src/components/common/RightMenu.vue';
+import VnTable from 'components/VnTable/VnTable.vue';
 
 const router = useRouter();
 const { t } = useI18n();
-const { viewSummary } = useSummaryDialog();
-
+const tableRef = ref();
 const redirectToItemTypeSummary = (id) => {
     router.push({ name: 'ItemTypeSummary', params: { id } });
 };
@@ -56,52 +49,91 @@ const exprBuilder = (param, value) => {
             }
     }
 };
+
+const columns = computed(() => [
+    {
+        align: 'left',
+        name: 'id',
+        label: t('id'),
+        isId: true,
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'code',
+        label: t('code'),
+        isTitle: true,
+        cardVisible: true,
+        create: true,
+    },
+    {
+        align: 'left',
+        name: 'name',
+        label: t('name'),
+        cardVisible: true,
+        create: true,
+    },
+    {
+        align: 'left',
+        name: 'worker',
+        label: t('worker'),
+        create: true,
+        component: 'select',
+        attrs: {
+            url: 'Workers',
+            fields: ['id', 'firstName'],
+        },
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'ItemCategory',
+        label: t('ItemCategory'),
+        create: true,
+        component: 'select',
+        attrs: {
+            url: 'ItemCategories',
+            fields: ['id', 'name'],
+        },
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'Temperature',
+        label: t('Temperature'),
+        create: true,
+        component: 'select',
+        attrs: {
+            url: 'Temperatures',
+            fields: ['id', 'name'],
+        },
+        cardVisible: true,
+    },
+]);
 </script>
 
 <template>
     <ItemTypeSearchbar />
-    <RightMenu>
-        <template #right-panel>
-            <ItemTypeFilter data-key="ItemTypeList" />
-        </template>
-    </RightMenu>
-    <QPage class="column items-center q-pa-md">
-        <div class="vn-card-list">
-            <VnPaginate
-                data-key="ItemTypeList"
-                url="ItemTypes"
-                :order="['name']"
-                auto-load
-                :expr-builder="exprBuilder"
-            >
-                <template #body="{ rows }">
-                    <CardList
-                        v-for="row of rows"
-                        :key="row.id"
-                        :title="row.code"
-                        @click="redirectToItemTypeSummary(row.id)"
-                        :id="row.id"
-                    >
-                        <template #list-items>
-                            <VnLv :label="t('Name')" :value="row.name" />
-                        </template>
-                        <template #actions>
-                            <QBtn
-                                :label="t('components.smartCard.openSummary')"
-                                @click.stop="viewSummary(row.id, ItemTypeSummary)"
-                                color="primary"
-                                type="submit"
-                            />
-                        </template>
-                    </CardList>
-                </template>
-            </VnPaginate>
-        </div>
-    </QPage>
-    <QPageSticky :offset="[20, 20]">
-        <QBtn fab icon="add" color="primary" @click="redirectToCreateView()" />
-        <QTooltip>
-            {{ t('New item type') }}
-        </QTooltip>
-    </QPageSticky>
+    <VnTable
+        ref="tableRef"
+        data-key="ItemTypeList"
+        :url="`ItemTypes`"
+        :url-create="`ItemTypes`"
+        save-url="ItemTypes/crud"
+        :filter="courseFilter"
+        :create="{
+            urlCreate: 'ItemTypes',
+            title: 'Create ItemTypes',
+            onDataSaved: () => tableRef.reload(),
+            formInitialData: {
+                workerFk: entityId,
+            },
+        }"
+        order="id DESC"
+        :columns="columns"
+        auto-load
+        :right-search="false"
+        :is-editable="false"
+        :use-model="true"
+    />
 </template>

From daf99f47306f2ae346e9fd023bce9e8b8c222c7b Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 15 Jul 2024 15:00:43 +0200
Subject: [PATCH 004/207] refs #7283 itemRequestList

---
 src/pages/Item/ItemRequest.vue | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index ae6638953..10cb6c2a6 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -18,6 +18,7 @@ import useNotify from 'src/composables/useNotify.js';
 import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import axios from 'axios';
 import RightMenu from 'src/components/common/RightMenu.vue';
+import { toDate } from 'src/filters';
 
 const { t } = useI18n();
 const { notify } = useNotify();
@@ -46,21 +47,28 @@ const columns = computed(() => [
         name: 'id',
         field: 'id',
         align: 'left',
-        sortable: true,
+        isId: true,
+        chip: {
+            condition: () => true,
+        },
+        cardVisible: true,
     },
     {
         label: t('item.buyRequest.shipped'),
         field: 'shipped',
         name: 'shipped',
         align: 'left',
-        sortable: true,
+        component: 'date',
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.shipped)),
     },
     {
         label: t('globals.description'),
         field: 'description',
         name: 'description',
         align: 'left',
-        sortable: true,
     },
     {
         label: t('item.buyRequest.requester'),
@@ -80,29 +88,31 @@ const columns = computed(() => [
         field: 'price',
         name: 'price',
         align: 'left',
-        sortable: true,
-        format: (val) => toCurrency(val),
+        format: (row) => toCurrency(row.price),
     },
     {
         label: t('item.buyRequest.attender'),
         field: 'attender',
         name: 'attender',
         align: 'left',
-        sortable: true,
+        attrs: {
+            url: 'Workers',
+            fields: ['id', 'firstName'],
+        },
     },
     {
         label: t('item.buyRequest.item'),
         field: 'item',
         name: 'item',
         align: 'left',
-        sortable: true,
+        component: 'input',
     },
     {
         label: t('item.buyRequest.achieved'),
         field: 'achieved',
         name: 'achieved',
         align: 'left',
-        sortable: true,
+        component: 'input',
     },
     {
         label: t('item.buyRequest.concept'),

From b7ba8eec3da2524c3fc2834dc2e4ffb64dbfc20d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 08:24:57 +0200
Subject: [PATCH 005/207] refs #7283 fix searchbar

---
 src/pages/Item/ItemList.vue | 41 +++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index e2c5f4bb3..17a62c5b9 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -3,11 +3,12 @@ import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRouter, useRoute } from 'vue-router';
 import VnImg from 'src/components/ui/VnImg.vue';
-
+import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
 import axios from 'axios';
+import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 const entityId = computed(() => route.params.id);
 
 const router = useRouter();
@@ -212,16 +213,21 @@ const columns = computed(() => [
         },
         format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
     },
+    {
+        align: 'right',
+        label: '',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('Clone item'),
+                icon: 'vn:clone',
+                action: cloneItem,
+                isPrimary: true,
+            },
+        ],
+    },
 ]);
 
-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`);
@@ -236,16 +242,11 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 </script>
 
 <template>
-    <!-- <VnSubToolbar>
-        <template #st-data>
-            <TableVisibleColumns
-                :all-columns="allColumnNames"
-                table-code="itemsIndex"
-                labels-traductions-path="item.list"
-                @on-config-saved="visibleColumns = ['picture', ...$event, 'actions']"
-            />
-        </template>
-    </VnSubToolbar> -->
+    <VnSearchbar
+        data-key="ItemList"
+        :label="t('Search Item')"
+        :info="t('You can search by id')"
+    />
     <VnTable
         ref="tableRef"
         data-key="ItemList"
@@ -265,7 +266,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         :columns="columns"
         auto-load
         redirect="Item"
-        :right-search="false"
+        :right-search="true"
         :is-editable="false"
         :use-model="true"
     />

From 85b030c7bc07fa7e2abf7e1c7e0d969c7000322d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 08:31:04 +0200
Subject: [PATCH 006/207] refs #7283 view summary

---
 src/pages/Item/ItemList.vue | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 17a62c5b9..0e444254f 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -9,8 +9,10 @@ import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
 import axios from 'axios';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
+import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 const entityId = computed(() => route.params.id);
 
+const { viewSummary } = useSummaryDialog();
 const router = useRouter();
 const stateStore = useStateStore();
 const { t } = useI18n();
@@ -224,6 +226,11 @@ const columns = computed(() => [
                 action: cloneItem,
                 isPrimary: true,
             },
+            {
+                title: t('view Summary'),
+                icon: 'preview',
+                action: (row) => viewSummary(row.id),
+            },
         ],
     },
 ]);

From cce1d891fb67b738a45d6f3d59cbcda6dd1dde5d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 08:48:50 +0200
Subject: [PATCH 007/207] refs #7283 fix viewSummary

---
 src/pages/Item/ItemList.vue | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 0e444254f..273374150 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -10,6 +10,7 @@ import { toDate } from 'src/filters';
 import axios from 'axios';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import ItemSummary from '../Item/Card/ItemSummary.vue';
 const entityId = computed(() => route.params.id);
 
 const { viewSummary } = useSummaryDialog();
@@ -229,7 +230,7 @@ const columns = computed(() => [
             {
                 title: t('view Summary'),
                 icon: 'preview',
-                action: (row) => viewSummary(row.id),
+                action: (row) => viewSummary(row.id, ItemSummary),
             },
         ],
     },

From 339f6e810bf87a9115691c69f447b43988b08e2d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 10:34:00 +0200
Subject: [PATCH 008/207] refs #7283 fix descriptorproxy

---
 src/pages/Item/ItemList.vue | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 273374150..6893d55a1 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -11,6 +11,7 @@ import axios from 'axios';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import ItemSummary from '../Item/Card/ItemSummary.vue';
+import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 const entityId = computed(() => route.params.id);
 
 const { viewSummary } = useSummaryDialog();
@@ -277,7 +278,14 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         :right-search="true"
         :is-editable="false"
         :use-model="true"
-    />
+    >
+        <template #column-userName="{ row }">
+            <span class="link" @click.stop>
+                {{ row.userName }}
+                <WorkerDescriptorProxy :id="row.buyerFk" />
+            </span>
+        </template>
+    </VnTable>
 </template>
 
 <i18n>

From f29d873ed42abad1c45d641a51aa02bc2ab02db1 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 12:15:39 +0200
Subject: [PATCH 009/207] refs #7283 fix request

---
 src/pages/Item/ItemRequest.vue | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 10cb6c2a6..e5faff6b2 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -120,13 +120,13 @@ const columns = computed(() => [
         name: 'concept',
         align: 'left',
         sortable: true,
+        component: 'input',
     },
     {
         label: t('item.buyRequest.state'),
         field: 'state',
         name: 'state',
         align: 'left',
-        sortable: true,
     },
     {
         label: '',
@@ -252,7 +252,6 @@ onBeforeMount(() => {
                     <TicketDescriptorProxy :id="row.ticketFk" />
                 </QTd>
             </template>
-
             <template #body-cell-shipped="{ row }">
                 <QTd>
                     <QBadge

From 86ae827fda7a8c45b346fdfaa490225b10039cbd Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 16 Jul 2024 13:48:32 +0200
Subject: [PATCH 010/207] refs #7283 clone

---
 src/pages/Item/ItemList.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 6893d55a1..c44438087 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -239,7 +239,7 @@ const columns = computed(() => [
 
 const cloneItem = async (itemFk) => {
     try {
-        const { data } = await axios.post(`Items/${itemFk}/clone`);
+        const { data } = await axios.post(`Items/${itemFk.id}/clone`);
         if (!data) return;
         router.push({ name: 'ItemTags', params: { id: data.id } });
     } catch (err) {

From 4d394a98a4f3d2b23bd580fcbe0a0186892e9b0c Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 22 Jul 2024 08:24:59 +0200
Subject: [PATCH 011/207] refs #7283 fix yml list basicData

---
 src/i18n/locale/en.yml                | 21 +++++++++++-
 src/i18n/locale/es.yml                | 21 +++++++++++-
 src/pages/Item/Card/ItemBasicData.vue | 47 ++++++++++++++++-----------
 src/pages/Item/ItemList.vue           |  1 -
 4 files changed, 68 insertions(+), 22 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 2f1209a3a..a3d7362b3 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -246,7 +246,6 @@ globals:
         mailForwarding: Mail forwarding
         mailAlias: Mail alias
         privileges: Privileges
-        labeler: Labeler
     created: Created
     worker: Worker
     now: Now
@@ -1194,6 +1193,26 @@ item:
         stemMultiplier: Multiplier
         producer: Producer
         landed: Landed
+    basicData:
+        type: Type
+        reference: Reference
+        relevancy: Relevancy
+        stems: Stems
+        multiplier: Multiplier
+        generic: Generic
+        intrastat: Intrastat
+        expense: Expense
+        weightByPiece: Weight/Piece
+        boxUnits: Units/Box
+        recycledPlastic: Recycled Plastic
+        nonRecycledPlastic: Non recycled plastic
+        isActive: Active
+        hasKgPrice: Price in kg
+        isFragile: Fragile
+        isFragileTooltip: Is shown at website, app that this item cannot travel (wreath, palms, ...)
+        isPhotoRequested: Do photo
+        isPhotoRequestedTooltip: This item does need a photo
+        description: Description
     fixedPrice:
         itemId: Item ID
         groupingPrice: Grouping price
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index c5c4fab66..71b2c5919 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -248,7 +248,6 @@ globals:
         components: Componentes
         pictures: Fotos
         packages: Bultos
-        labeler: Etiquetas
     created: Fecha creación
     worker: Trabajador
     now: Ahora
@@ -1175,6 +1174,26 @@ item:
         stemMultiplier: Multiplicador
         producer: Productor
         landed: F. entrega
+    basicData:
+        type: Tipo
+        reference: Referencia
+        relevancy: Relevancia
+        stems: Tallos
+        multiplier: Multiplicador
+        generic: Genérico
+        intrastat: Intrastat
+        expense: Gasto
+        weightByPiece: Peso (gramos)/tallo
+        boxUnits: Unidades/caja
+        recycledPlastic: Plastico reciclado
+        nonRecycledPlastic: Plático no reciclado
+        isActive: Activo
+        hasKgPrice: Precio en kg
+        isFragile: Frágil
+        isFragileTooltip: Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
+        isPhotoRequested: Hacer foto
+        isPhotoRequestedTooltip: Este artículo necesita una foto
+        description: Descripción
     fixedPrice:
         itemId: ID Artículo
         groupingPrice: Precio grouping
diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index eb486f551..07242635b 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -73,7 +73,7 @@ const onIntrastatCreated = (response, formData) => {
         <template #form="{ data }">
             <VnRow class="row q-gutter-md q-mb-md">
                 <VnSelect
-                    :label="t('basicData.type')"
+                    :label="t('item.basicData.type')"
                     v-model="data.typeFk"
                     :options="itemTypesOptions"
                     option-value="id"
@@ -92,17 +92,20 @@ const onIntrastatCreated = (response, formData) => {
                         </QItem>
                     </template>
                 </VnSelect>
-                <VnInput :label="t('basicData.reference')" v-model="data.comment" />
-                <VnInput :label="t('basicData.relevancy')" v-model="data.relevancy" />
+                <VnInput :label="t('item.basicData.reference')" v-model="data.comment" />
+                <VnInput
+                    :label="t('item.basicData.relevancy')"
+                    v-model="data.relevancy"
+                />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <VnInput :label="t('basicData.stems')" v-model="data.stems" />
+                <VnInput :label="t('item.basicData.stems')" v-model="data.stems" />
                 <VnInput
-                    :label="t('basicData.multiplier')"
+                    :label="t('item.basicData.multiplier')"
                     v-model="data.stemMultiplier"
                 />
                 <VnSelectDialog
-                    :label="t('basicData.generic')"
+                    :label="t('item.basicData.generic')"
                     v-model="data.genericFk"
                     :options="itemsWithNameOptions"
                     option-value="id"
@@ -129,7 +132,7 @@ const onIntrastatCreated = (response, formData) => {
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
                 <VnSelectDialog
-                    :label="t('basicData.intrastat')"
+                    :label="t('item.basicData.intrastat')"
                     v-model="data.intrastatFk"
                     :options="intrastatsOptions"
                     option-value="id"
@@ -156,7 +159,7 @@ const onIntrastatCreated = (response, formData) => {
                 </VnSelectDialog>
                 <div class="col">
                     <VnSelect
-                        :label="t('basicData.expense')"
+                        :label="t('item.basicData.expense')"
                         v-model="data.expenseFk"
                         :options="expensesOptions"
                         option-value="id"
@@ -168,61 +171,67 @@ const onIntrastatCreated = (response, formData) => {
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
                 <VnInput
-                    :label="t('basicData.weightByPiece')"
+                    :label="t('item.basicData.weightByPiece')"
                     v-model.number="data.weightByPiece"
                     :min="0"
                     type="number"
                 />
                 <VnInput
-                    :label="t('basicData.boxUnits')"
+                    :label="t('item.basicData.boxUnits')"
                     v-model.number="data.packingOut"
                     :min="0"
                     type="number"
                 />
                 <VnInput
-                    :label="t('basicData.recycledPlastic')"
+                    :label="t('item.basicData.recycledPlastic')"
                     v-model.number="data.recycledPlastic"
                     :min="0"
                     type="number"
                 />
                 <VnInput
-                    :label="t('basicData.nonRecycledPlastic')"
+                    :label="t('item.basicData.nonRecycledPlastic')"
                     v-model.number="data.nonRecycledPlastic"
                     :min="0"
                     type="number"
                 />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <QCheckbox v-model="data.isActive" :label="t('basicData.isActive')" />
-                <QCheckbox v-model="data.hasKgPrice" :label="t('basicData.hasKgPrice')" />
+                <QCheckbox
+                    v-model="data.isActive"
+                    :label="t('item.basicData.isActive')"
+                />
+                <QCheckbox
+                    v-model="data.hasKgPrice"
+                    :label="t('item.basicData.hasKgPrice')"
+                />
                 <div>
                     <QCheckbox
                         v-model="data.isFragile"
-                        :label="t('basicData.isFragile')"
+                        :label="t('item.basicData.isFragile')"
                         class="q-mr-sm"
                     />
                     <QIcon name="info" class="cursor-pointer" size="xs">
                         <QTooltip max-width="300px">
-                            {{ t('basicData.isFragileTooltip') }}
+                            {{ t('item.basicData.isFragileTooltip') }}
                         </QTooltip>
                     </QIcon>
                 </div>
                 <div>
                     <QCheckbox
                         v-model="data.isPhotoRequested"
-                        :label="t('basicData.isPhotoRequested')"
+                        :label="t('item.basicData.isPhotoRequested')"
                         class="q-mr-sm"
                     />
                     <QIcon name="info" class="cursor-pointer" size="xs">
                         <QTooltip>
-                            {{ t('basicData.isPhotoRequestedTooltip') }}
+                            {{ t('item.basicData.isPhotoRequestedTooltip') }}
                         </QTooltip>
                     </QIcon>
                 </div>
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="t('basicData.description')"
+                    :label="t('item.basicData.description')"
                     type="textarea"
                     v-model="data.description"
                     fill-input
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index c44438087..169ee93d6 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -226,7 +226,6 @@ const columns = computed(() => [
                 title: t('Clone item'),
                 icon: 'vn:clone',
                 action: cloneItem,
-                isPrimary: true,
             },
             {
                 title: t('view Summary'),

From f678c6304313cbc6d976c9df21f7f0e33c958dac Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 22 Jul 2024 13:35:41 +0200
Subject: [PATCH 012/207] refs #7283 request

---
 src/i18n/locale/en.yml         |  2 +-
 src/pages/Item/ItemList.vue    |  6 +----
 src/pages/Item/ItemRequest.vue | 40 +++++++++++++++++-----------------
 3 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index a3d7362b3..33862f766 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -1235,7 +1235,7 @@ item:
         requester: 'Requester'
         requested: 'Requested'
         price: 'Price'
-        attender: 'Atender'
+        attender: 'Attender'
         item: 'Item'
         achieved: 'Achieved'
         concept: 'Concept'
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 169ee93d6..2532a6df2 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -1,9 +1,8 @@
 <script setup>
-import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
+import { ref, computed, onUnmounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRouter, useRoute } from 'vue-router';
 import VnImg from 'src/components/ui/VnImg.vue';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
@@ -245,8 +244,6 @@ const cloneItem = async (itemFk) => {
         console.error('Error cloning item', err);
     }
 };
-
-onUnmounted(() => (stateStore.rightDrawer = false));
 </script>
 
 <template>
@@ -274,7 +271,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         :columns="columns"
         auto-load
         redirect="Item"
-        :right-search="true"
         :is-editable="false"
         :use-model="true"
     >
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index e5faff6b2..ed6f623aa 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -1,24 +1,14 @@
 <script setup>
 import { ref, computed, onMounted, onBeforeMount, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
-import FetchData from 'components/FetchData.vue';
-import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
-import ItemRequestFilter from './ItemRequestFilter.vue';
-import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
-import VnSelect from 'components/common/VnSelect.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { useArrayData } from 'composables/useArrayData';
-import { toDateFormat } from 'src/filters/date';
 import { toCurrency } from 'filters/index';
 import useNotify from 'src/composables/useNotify.js';
-import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import axios from 'axios';
-import RightMenu from 'src/components/common/RightMenu.vue';
 import { toDate } from 'src/filters';
+import VnTable from 'components/VnTable/VnTable.vue';
 
 const { t } = useI18n();
 const { notify } = useNotify();
@@ -72,16 +62,15 @@ const columns = computed(() => [
     },
     {
         label: t('item.buyRequest.requester'),
-        name: 'requester',
+        field: 'requesterName',
+        name: 'requesterFk',
         align: 'left',
-        sortable: true,
     },
     {
         label: t('item.buyRequest.requested'),
         field: 'quantity',
         name: 'requested',
         align: 'left',
-        sortable: true,
     },
     {
         label: t('item.buyRequest.price'),
@@ -95,10 +84,6 @@ const columns = computed(() => [
         field: 'attender',
         name: 'attender',
         align: 'left',
-        attrs: {
-            url: 'Workers',
-            fields: ['id', 'firstName'],
-        },
     },
     {
         label: t('item.buyRequest.item'),
@@ -218,7 +203,7 @@ onBeforeMount(() => {
 </script>
 
 <template>
-    <FetchData
+    <!-- <FetchData
         url="Workers"
         :filter="{ where: { role: 'buyer' } }"
         order="id"
@@ -350,7 +335,22 @@ onBeforeMount(() => {
                 @on-data-saved="onDenyAccept"
             />
         </QDialog>
-    </QPage>
+    </QPage> -->
+    <VnTable
+        ref="tableRef"
+        data-key="itemRequest"
+        url="ticketRequests"
+        order="id DESC"
+        :columns="columns"
+        auto-load
+    >
+        <template #column-attender="{ row }">
+            <span class="link" @click.stop>
+                {{ row.attenderFk }}
+                <WorkerDescriptorProxy :id="row.attenderFk" />
+            </span>
+        </template>
+    </VnTable>
 </template>
 
 <i18n>

From b668d07e2dc4fb453efcd1050abbc0f6fd570687 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 1 Aug 2024 13:20:33 +0200
Subject: [PATCH 013/207] refs #7283 fetchedTags

---
 src/pages/Item/ItemList.vue    | 46 +++++++++++++++++++++++-----------
 src/pages/Item/ItemRequest.vue | 17 ++++++++++---
 2 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 2532a6df2..a3b70372f 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -7,6 +7,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
 import axios from 'axios';
+import FetchedTags from 'src/components/ui/FetchedTags.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import ItemSummary from '../Item/Card/ItemSummary.vue';
@@ -43,21 +44,21 @@ const itemFilter = {
     ],
 };
 const columns = computed(() => [
-    {
-        label: '',
-        name: 'image',
-        align: 'left',
-        columnField: {
-            component: VnImg,
-            attrs: (id) => {
-                return {
-                    id,
-                    width: '50px',
-                };
-            },
-        },
-        columnFilter: false,
-    },
+    // {
+    //     label: '',
+    //     name: 'image',
+    //     align: 'left',
+    //     columnField: {
+    //         component: VnImg,
+    //         attrs: (id) => {
+    //             return {
+    //                 id,
+    //                 width: '50px',
+    //             };
+    //         },
+    //     },
+    //     columnFilter: false,
+    // },
     {
         label: t('item.list.id'),
         name: 'id',
@@ -280,9 +281,24 @@ const cloneItem = async (itemFk) => {
                 <WorkerDescriptorProxy :id="row.buyerFk" />
             </span>
         </template>
+        <template #column-description="{ row }">
+            <div class="row column full-width justify-between items-start">
+                {{ row?.name }}
+                <div v-if="row?.subName" class="subName">
+                    {{ row?.subName.toUpperCase() }}
+                </div>
+            </div>
+            <FetchedTags :item="row" :max-length="6" />
+        </template>
     </VnTable>
 </template>
 
+<style lang="scss" scoped>
+.subName {
+    text-transform: uppercase;
+    color: var(--vn-label-color);
+}
+</style>
 <i18n>
 es:
     New item: Nuevo artículo
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index ed6f623aa..0389ba864 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -13,7 +13,6 @@ import VnTable from 'components/VnTable/VnTable.vue';
 const { t } = useI18n();
 const { notify } = useNotify();
 const stateStore = useStateStore();
-const workersOptions = ref([]);
 let filterParams = ref({});
 const denyFormRef = ref(null);
 const denyRequestId = ref(null);
@@ -91,6 +90,7 @@ const columns = computed(() => [
         name: 'item',
         align: 'left',
         component: 'input',
+        visible: false,
     },
     {
         label: t('item.buyRequest.achieved'),
@@ -98,6 +98,7 @@ const columns = computed(() => [
         name: 'achieved',
         align: 'left',
         component: 'input',
+        visible: false,
     },
     {
         label: t('item.buyRequest.concept'),
@@ -106,6 +107,7 @@ const columns = computed(() => [
         align: 'left',
         sortable: true,
         component: 'input',
+        visible: false,
     },
     {
         label: t('item.buyRequest.state'),
@@ -114,10 +116,17 @@ const columns = computed(() => [
         align: 'left',
     },
     {
+        align: 'right',
         label: '',
-        name: 'action',
-        align: 'left',
-        columnFilter: null,
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('Client ticket list'),
+                icon: 'thumb_down',
+                action: onDenyAccept,
+                isPrimary: true,
+            },
+        ],
     },
 ]);
 

From fe78de0c4761772593a3e714c69894f36651e696 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 5 Aug 2024 11:49:06 +0200
Subject: [PATCH 014/207] refs #7283 fixedPrices

---
 src/pages/Item/ItemFixedPrice.vue | 325 +++++++-----------------------
 1 file changed, 70 insertions(+), 255 deletions(-)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 2ecd1f21b..41f2bac2f 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { onMounted, ref, reactive, computed, onUnmounted, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
-
+import { toDate } from 'src/filters';
 import FetchData from 'components/FetchData.vue';
 import FetchedTags from 'components/ui/FetchedTags.vue';
 import VnInput from 'src/components/common/VnInput.vue';
@@ -10,7 +10,7 @@ import VnInputDate from 'src/components/common/VnInputDate.vue';
 import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
 import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
 import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
-
+import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { dashIfEmpty } from 'src/filters';
 import { useVnConfirm } from 'composables/useVnConfirm';
@@ -27,7 +27,7 @@ const { t } = useI18n();
 const { openConfirmationModal } = useVnConfirm();
 const state = useState();
 const { notify } = useNotify();
-
+const tableRef = ref();
 const editTableCellDialogRef = ref(null);
 const user = state.getUser();
 const fixedPrices = ref([]);
@@ -111,86 +111,81 @@ const defaultColumnAttrs = {
 const columns = computed(() => [
     {
         label: t('item.fixedPrice.itemId'),
-        name: 'itemId',
-        field: 'itemFk',
-        ...defaultColumnAttrs,
-        columnFilter: {
-            ...defaultColumnFilter,
+        name: 'itemFk',
+        align: 'left',
+        isId: true,
+        chip: {
+            condition: () => true,
         },
     },
     {
         label: t('globals.description'),
-        field: 'name',
         name: 'description',
-        ...defaultColumnAttrs,
-        columnFilter: {
-            ...defaultColumnFilter,
-        },
+        align: 'left',
+        create: true,
     },
     {
         label: t('item.fixedPrice.groupingPrice'),
-        field: 'rate2',
-        name: 'groupingPrice',
-        ...defaultColumnAttrs,
-        columnFilter: {
-            ...defaultColumnFilter,
-        },
-        format: (val) => toCurrency(val),
+        name: 'rate2',
+        align: 'left',
+        create: true,
     },
     {
         label: t('item.fixedPrice.packingPrice'),
-        field: 'rate3',
-        name: 'packingPrice',
-        ...defaultColumnAttrs,
-        columnFilter: {
-            ...defaultColumnFilter,
-        },
-        format: (val) => dashIfEmpty(val),
+        name: 'rate3',
+        align: 'left',
+        create: true,
     },
 
     {
         label: t('item.fixedPrice.minPrice'),
-        field: 'minPrice',
         name: 'minPrice',
-        ...defaultColumnAttrs,
-        columnFilter: {
-            ...defaultColumnFilter,
-        },
+        align: 'left',
+        create: true,
     },
     {
         label: t('item.fixedPrice.started'),
-        field: 'started',
         name: 'started',
-        ...defaultColumnAttrs,
-        columnFilter: null,
+        align: 'left',
+        create: true,
+        format: (row) => toDate(row.started),
     },
     {
         label: t('item.fixedPrice.ended'),
-        field: 'ended',
         name: 'ended',
-        ...defaultColumnAttrs,
-        columnFilter: null,
+        align: 'left',
+        create: true,
+        format: (row) => toDate(row.ended),
     },
-
     {
         label: t('item.fixedPrice.warehouse'),
-        field: 'warehouseFk',
-        name: 'warehouse',
-        ...defaultColumnAttrs,
+        name: 'warehouseFk',
         columnFilter: {
-            component: VnSelect,
-            type: 'select',
-            filterValue: null,
-            event: getColumnInputEvents,
+            component: 'select',
             attrs: {
-                options: warehousesOptions.value,
-                'option-value': 'id',
-                'option-label': 'name',
-                dense: true,
+                url: 'Warehouses',
+                optionValue: 'id',
+                optionLabel: 'name',
             },
         },
+        component: 'select',
+        attrs: {
+            url: 'Warehouses',
+            fields: ['id', 'name'],
+        },
+        disable: false,
+    },
+    {
+        align: 'right',
+        label: '',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('Delete'),
+                icon: 'delete',
+            },
+        ],
     },
-    { name: 'deleteAction', align: 'center' },
 ]);
 
 const editTableFieldsOptions = [
@@ -364,212 +359,32 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 </script>
 
 <template>
-    <FetchData
-        url="Warehouses"
-        :filter="{ order: ['name'] }"
+    <VnTable
+        ref="tableRef"
+        data-key="ItemFixedPrices"
+        url="FixedPrices/filter"
+        :create="{
+            urlCreate: 'PriceFixed',
+            title: 'Create Item',
+            onDataSaved: () => tableRef.redirect(),
+            formInitialData: {},
+        }"
+        order="id ASC"
+        :columns="columns"
         auto-load
-        @on-fetch="(data) => onWarehousesFetched(data)"
-    />
-    <RightMenu>
-        <template #right-panel>
-            <ItemFixedPriceFilter
-                data-key="ItemFixedPrices"
-                :warehouses-options="warehousesOptions"
-            />
+        :is-editable="false"
+        :use-model="true"
+    >
+        <template #column-description="{ row }">
+            <div class="row column full-width justify-between items-start">
+                {{ row?.description }}
+                <div v-if="row?.description" class="subName">
+                    {{ row?.subName.toUpperCase() }}
+                </div>
+            </div>
+            <FetchedTags :item="row" :max-length="6" />
         </template>
-    </RightMenu>
-    <QPage class="column items-center q-pa-md">
-        <QTable
-            :rows="fixedPrices"
-            :columns="columns"
-            row-key="id"
-            selection="multiple"
-            v-model:selected="rowsSelected"
-            :pagination="{ rowsPerPage: 0 }"
-            class="full-width q-mt-md"
-            :no-data-label="t('globals.noResults')"
-        >
-            <template #top-row="{ cols }">
-                <QTr>
-                    <QTd />
-                    <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-itemId="props">
-                <QTd>
-                    <VnSelect
-                        url="Items/withName"
-                        hide-selected
-                        option-label="id"
-                        option-value="id"
-                        v-model="props.row.itemFk"
-                        v-on="getRowUpdateInputEvents(props, true, 'select')"
-                    >
-                        <template #option="scope">
-                            <QItem v-bind="scope.itemProps">
-                                <QItemSection>
-                                    <QItemLabel> #{{ scope.opt?.id }} </QItemLabel>
-                                    <QItemLabel caption>{{ scope.opt?.name }}</QItemLabel>
-                                </QItemSection>
-                            </QItem>
-                        </template>
-                    </VnSelect>
-                </QTd>
-            </template>
-            <template #body-cell-description="{ row }">
-                <QTd class="col">
-                    <span class="link">
-                        {{ row.name }}
-                    </span>
-                    <ItemDescriptorProxy :id="row.itemFk" />
-                    <FetchedTags :item="row" :max-length="6" />
-                </QTd>
-            </template>
-            <template #body-cell-groupingPrice="props">
-                <QTd class="col">
-                    <VnInput
-                        v-model.number="props.row.rate2"
-                        v-on="getRowUpdateInputEvents(props)"
-                    >
-                        <template #append>€</template>
-                    </VnInput>
-                </QTd>
-            </template>
-            <template #body-cell-packingPrice="props">
-                <QTd class="col">
-                    <VnInput
-                        v-model.number="props.row.rate3"
-                        v-on="getRowUpdateInputEvents(props)"
-                    >
-                        <template #append>€</template>
-                    </VnInput>
-                </QTd>
-            </template>
-            <template #body-cell-minPrice="props">
-                <QTd class="col">
-                    <div class="row">
-                        <QCheckbox
-                            class="col"
-                            :model-value="props.row.hasMinPrice"
-                            @update:model-value="updateMinPrice($event, props)"
-                            :false-value="0"
-                            :true-value="1"
-                            :toggle-indeterminate="false"
-                        />
-                        <VnInput
-                            class="col"
-                            :disable="!props.row.hasMinPrice"
-                            v-model.number="props.row.minPrice"
-                            v-on="getRowUpdateInputEvents(props)"
-                            type="number"
-                        />
-                    </div>
-                </QTd>
-            </template>
-            <template #body-cell-started="props">
-                <QTd class="col" style="min-width: 160px">
-                    <VnInputDate
-                        v-model="props.row.started"
-                        v-on="getRowUpdateInputEvents(props, false, 'date')"
-                        v-bind="
-                            isBigger(props.row.started)
-                                ? { 'bg-color': 'warning', 'is-outlined': true }
-                                : {}
-                        "
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-ended="props">
-                <QTd class="col" style="min-width: 150px">
-                    <VnInputDate
-                        v-model="props.row.ended"
-                        v-on="getRowUpdateInputEvents(props, false, 'date')"
-                        v-bind="
-                            isLower(props.row.ended)
-                                ? { 'bg-color': 'warning', 'is-outlined': true }
-                                : {}
-                        "
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-warehouse="props">
-                <QTd class="col">
-                    <VnSelect
-                        :options="warehousesOptions"
-                        hide-selected
-                        option-label="name"
-                        option-value="id"
-                        v-model="props.row.warehouseFk"
-                        v-on="getRowUpdateInputEvents(props, false, 'select')"
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-deleteAction="{ row, rowIndex }">
-                <QTd class="col">
-                    <QIcon
-                        name="delete"
-                        size="sm"
-                        class="cursor-pointer fill-icon-on-hover"
-                        color="primary"
-                        @click.stop="
-                            openConfirmationModal(
-                                t('This row will be removed'),
-                                t('Do you want to clone this item?'),
-                                () => removePrice(row.id, rowIndex)
-                            )
-                        "
-                    >
-                        <QTooltip class="text-no-wrap">
-                            {{ t('Delete') }}
-                        </QTooltip>
-                    </QIcon>
-                </QTd>
-            </template>
-            <template #bottom-row>
-                <QTd align="center">
-                    <QIcon
-                        @click.stop="addRow()"
-                        class="fill-icon-on-hover"
-                        color="primary"
-                        name="add_circle"
-                        size="sm"
-                    >
-                        <QTooltip>
-                            {{ t('Add fixed price') }}
-                        </QTooltip>
-                    </QIcon>
-                </QTd>
-            </template>
-        </QTable>
-        <QPageSticky v-if="rowsSelected.length" :offset="[20, 20]">
-            <QBtn @click="openEditTableCellDialog()" color="primary" fab icon="edit" />
-            <QTooltip>
-                {{ t('Edit fixed price(s)') }}
-            </QTooltip>
-        </QPageSticky>
-        <QDialog ref="editTableCellDialogRef">
-            <EditTableCellValueForm
-                edit-url="FixedPrices/editFixedPrice"
-                :rows="rowsSelected"
-                :fields-options="editTableFieldsOptions"
-                @on-data-saved="onEditCellDataSaved()"
-            />
-        </QDialog>
-    </QPage>
+    </VnTable>
 </template>
 
 <i18n>

From 6ca8ede946356c0d3b04cf57671e583f349f7f2b Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 7 Aug 2024 09:53:42 +0200
Subject: [PATCH 015/207] refs #7283 item request

---
 src/pages/Item/ItemRequest.vue  | 28 ++++++++--------------------
 src/pages/Item/ItemTypeList.vue |  3 +++
 2 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 0389ba864..8791a575f 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -33,8 +33,7 @@ watch(
 const columns = computed(() => [
     {
         label: t('item.buyRequest.ticketId'),
-        name: 'id',
-        field: 'id',
+        name: 'ticketFk',
         align: 'left',
         isId: true,
         chip: {
@@ -44,7 +43,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.buyRequest.shipped'),
-        field: 'shipped',
         name: 'shipped',
         align: 'left',
         component: 'date',
@@ -61,57 +59,46 @@ const columns = computed(() => [
     },
     {
         label: t('item.buyRequest.requester'),
-        field: 'requesterName',
-        name: 'requesterFk',
+        name: 'requesterName',
         align: 'left',
     },
     {
         label: t('item.buyRequest.requested'),
-        field: 'quantity',
-        name: 'requested',
+        name: 'saleQuantity',
         align: 'left',
     },
     {
         label: t('item.buyRequest.price'),
-        field: 'price',
         name: 'price',
         align: 'left',
         format: (row) => toCurrency(row.price),
     },
     {
         label: t('item.buyRequest.attender'),
-        field: 'attender',
-        name: 'attender',
+        name: 'attenderName',
         align: 'left',
     },
     {
         label: t('item.buyRequest.item'),
-        field: 'item',
         name: 'item',
         align: 'left',
         component: 'input',
-        visible: false,
     },
     {
         label: t('item.buyRequest.achieved'),
-        field: 'achieved',
         name: 'achieved',
         align: 'left',
         component: 'input',
-        visible: false,
     },
     {
         label: t('item.buyRequest.concept'),
-        field: 'concept',
         name: 'concept',
         align: 'left',
         sortable: true,
         component: 'input',
-        visible: false,
     },
     {
         label: t('item.buyRequest.state'),
-        field: 'state',
         name: 'state',
         align: 'left',
     },
@@ -123,7 +110,7 @@ const columns = computed(() => [
             {
                 title: t('Client ticket list'),
                 icon: 'thumb_down',
-                action: onDenyAccept,
+                action: showDenyRequestForm,
                 isPrimary: true,
             },
         ],
@@ -348,14 +335,15 @@ onBeforeMount(() => {
     <VnTable
         ref="tableRef"
         data-key="itemRequest"
-        url="ticketRequests"
+        url="ticketRequests/filter"
         order="id DESC"
         :columns="columns"
+        :is-editable="false"
         auto-load
     >
         <template #column-attender="{ row }">
             <span class="link" @click.stop>
-                {{ row.attenderFk }}
+                {{ row }}
                 <WorkerDescriptorProxy :id="row.attenderFk" />
             </span>
         </template>
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index c02f9bb43..5ebbec62b 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -84,6 +84,7 @@ const columns = computed(() => [
             fields: ['id', 'firstName'],
         },
         cardVisible: true,
+        visible: false,
     },
     {
         align: 'left',
@@ -96,6 +97,7 @@ const columns = computed(() => [
             fields: ['id', 'name'],
         },
         cardVisible: true,
+        visible: false,
     },
     {
         align: 'left',
@@ -108,6 +110,7 @@ const columns = computed(() => [
             fields: ['id', 'name'],
         },
         cardVisible: true,
+        visible: false,
     },
 ]);
 </script>

From 589ee629cfbfc3c2b79c32ecef9ff47f30d33c00 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 13 Aug 2024 12:45:30 +0200
Subject: [PATCH 016/207] refs #7283 fix conflicts

---
 src/pages/Item/ItemFixedPrice.vue | 255 +++++++++---------------------
 src/pages/Item/ItemRequest.vue    |  15 +-
 2 files changed, 89 insertions(+), 181 deletions(-)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 41f2bac2f..56ad7a17d 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -2,25 +2,15 @@
 import { onMounted, ref, reactive, computed, onUnmounted, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { toDate } from 'src/filters';
-import FetchData from 'components/FetchData.vue';
 import FetchedTags from 'components/ui/FetchedTags.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import VnInputDate from 'src/components/common/VnInputDate.vue';
-import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
-import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
-import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
-import { dashIfEmpty } from 'src/filters';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import { useState } from 'src/composables/useState';
-import { toCurrency } from 'filters/index';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import { useArrayData } from 'composables/useArrayData';
-import { isLower, isBigger } from 'src/filters/date.js';
-import RightMenu from 'src/components/common/RightMenu.vue';
 
 const stateStore = useStateStore();
 const { t } = useI18n();
@@ -75,39 +65,6 @@ watch(
     (data) => onFixedPricesFetched(data)
 );
 
-const applyColumnFilter = async (col) => {
-    try {
-        const paramKey = col.columnFilter?.filterParamKey || col.field;
-        params[paramKey] = col.columnFilter.filterValue;
-        await arrayData.addFilter({ params });
-    } catch (err) {
-        console.error('Error applying column filter', err);
-    }
-};
-
-const getColumnInputEvents = (col) => {
-    return col.columnFilter.type === 'select'
-        ? { 'update:modelValue': () => applyColumnFilter(col) }
-        : {
-              'keyup.enter': () => applyColumnFilter(col),
-          };
-};
-
-const defaultColumnFilter = {
-    component: VnInput,
-    type: 'text',
-    filterValue: null,
-    event: getColumnInputEvents,
-    attrs: {
-        dense: true,
-    },
-};
-
-const defaultColumnAttrs = {
-    align: 'left',
-    sortable: true,
-};
-
 const columns = computed(() => [
     {
         label: t('item.fixedPrice.itemId'),
@@ -127,12 +84,14 @@ const columns = computed(() => [
     {
         label: t('item.fixedPrice.groupingPrice'),
         name: 'rate2',
+        component: 'input',
         align: 'left',
         create: true,
     },
     {
         label: t('item.fixedPrice.packingPrice'),
         name: 'rate3',
+        component: 'input',
         align: 'left',
         create: true,
     },
@@ -140,6 +99,7 @@ const columns = computed(() => [
     {
         label: t('item.fixedPrice.minPrice'),
         name: 'minPrice',
+        component: 'input',
         align: 'left',
         create: true,
     },
@@ -188,70 +148,14 @@ const columns = computed(() => [
     },
 ]);
 
-const editTableFieldsOptions = [
-    {
-        field: 'rate2',
-        label: t('item.fixedPrice.groupingPrice'),
-        component: 'input',
-        attrs: {
-            type: 'number',
-        },
-    },
-    {
-        field: 'rate3',
-        label: t('item.fixedPrice.packingPrice'),
-        component: 'input',
-        attrs: {
-            type: 'number',
-        },
-    },
-    {
-        field: 'minPrice',
-        label: t('item.fixedPrice.minPrice'),
-        component: 'input',
-        attrs: {
-            type: 'number',
-        },
-    },
-    {
-        field: 'hasMinPrice',
-        label: t('item.fixedPrice.hasMinPrice'),
-        component: 'checkbox',
-        attrs: {
-            'false-value': 0,
-            'true-value': 1,
-        },
-    },
-    {
-        field: 'started',
-        label: t('item.fixedPrice.started'),
-        component: 'date',
-    },
-    {
-        field: 'ended',
-        label: t('item.fixedPrice.ended'),
-        component: 'date',
-    },
-    {
-        field: 'warehouseFk',
-        label: t('item.fixedPrice.warehouse'),
-        component: 'select',
-        attrs: {
-            options: [],
-            'option-label': 'name',
-            'option-value': 'id',
-        },
-    },
-];
-
-const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
-    return inputType === 'text'
-        ? {
-              'keyup.enter': () => upsertPrice(props, resetMinPrice),
-              blur: () => upsertPrice(props, resetMinPrice),
-          }
-        : { 'update:modelValue': () => upsertPrice(props, resetMinPrice) };
-};
+// const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
+//     return inputType === 'text'
+//         ? {
+//               'keyup.enter': () => upsertPrice(props, resetMinPrice),
+//               blur: () => upsertPrice(props, resetMinPrice),
+//           }
+//         : { 'update:modelValue': () => upsertPrice(props, resetMinPrice) };
+// };
 
 const validations = (row, rowIndex, col) => {
     const isNew = !row.id;
@@ -281,81 +185,73 @@ const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
     }
 };
 
-const addRow = () => {
-    if (!fixedPrices.value || fixedPrices.value.length === 0) {
-        fixedPrices.value = [];
+// const addRow = () => {
+//     if (!fixedPrices.value || fixedPrices.value.length === 0) {
+//         fixedPrices.value = [];
 
-        const today = Date.vnNew();
-        const millisecsInDay = 86400000;
-        const daysInWeek = 7;
-        const nextWeek = new Date(today.getTime() + daysInWeek * millisecsInDay);
+//         const today = Date.vnNew();
+//         const millisecsInDay = 86400000;
+//         const daysInWeek = 7;
+//         const nextWeek = new Date(today.getTime() + daysInWeek * millisecsInDay);
 
-        const newPrice = {
-            started: today,
-            ended: nextWeek,
-            hasMinPrice: 0,
-        };
+//         const newPrice = {
+//             started: today,
+//             ended: nextWeek,
+//             hasMinPrice: 0,
+//         };
 
-        fixedPricesOriginalData.value.push({ ...newPrice });
-        fixedPrices.value.push({ ...newPrice });
-        return;
-    }
+//         fixedPricesOriginalData.value.push({ ...newPrice });
+//         fixedPrices.value.push({ ...newPrice });
+//         return;
+//     }
 
-    const lastItemCopy = JSON.parse(
-        JSON.stringify(fixedPrices.value[fixedPrices.value.length - 1])
-    );
-    delete lastItemCopy.id;
-    fixedPricesOriginalData.value.push(lastItemCopy);
-    fixedPrices.value.push(lastItemCopy);
-};
+//     const lastItemCopy = JSON.parse(
+//         JSON.stringify(fixedPrices.value[fixedPrices.value.length - 1])
+//     );
+//     delete lastItemCopy.id;
+//     fixedPricesOriginalData.value.push(lastItemCopy);
+//     fixedPrices.value.push(lastItemCopy);
+// };
 
-const openEditTableCellDialog = () => {
-    editTableCellDialogRef.value.show();
-};
+// const openEditTableCellDialog = () => {
+//     editTableCellDialogRef.value.show();
+// };
 
-const onEditCellDataSaved = async () => {
-    rowsSelected.value = [];
-    await fetchFixedPrices();
-};
+// const onEditCellDataSaved = async () => {
+//     rowsSelected.value = [];
+//     await fetchFixedPrices();
+// };
 
-const onWarehousesFetched = (data) => {
-    warehousesOptions.value = data;
-    // Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
-    const warehouseField = editTableFieldsOptions.find(
-        (field) => field.field === 'warehouseFk'
-    );
-    warehouseField.attrs.options = data;
-};
+// const onWarehousesFetched = (data) => {
+//     warehousesOptions.value = data;
+//     // Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
+//     const warehouseField = editTableFieldsOptions.find(
+//         (field) => field.field === 'warehouseFk'
+//     );
+//     warehouseField.attrs.options = data;
+// };
 
-const removePrice = async (id, rowIndex) => {
-    try {
-        await axios.delete(`FixedPrices/${id}`);
-        fixedPrices.value.splice(rowIndex, 1);
-        fixedPricesOriginalData.value.splice(rowIndex, 1);
-        notify(t('globals.dataSaved'), 'positive');
-    } catch (err) {
-        console.error('Error removing price', err);
-    }
-};
+// const removePrice = async (id, rowIndex) => {
+//     try {
+//         await axios.delete(`FixedPrices/${id}`);
+//         fixedPrices.value.splice(rowIndex, 1);
+//         fixedPricesOriginalData.value.splice(rowIndex, 1);
+//         notify(t('globals.dataSaved'), 'positive');
+//     } catch (err) {
+//         console.error('Error removing price', err);
+//     }
+// };
 
-const updateMinPrice = async (value, props) => {
-    // El checkbox hasMinPrice se encuentra en la misma columna que el input hasMinPrice
-    // Por lo tanto le mandamos otro objeto con las mismas propiedades pero con el campo 'field' cambiado
-    props.row.hasMinPrice = value;
-    await upsertPrice({
-        row: props.row,
-        col: { field: 'hasMinPrice' },
-        rowIndex: props.rowIndex,
-    });
-};
-
-onMounted(async () => {
-    stateStore.rightDrawer = true;
-    params.warehouseFk = user.value.warehouseFk;
-    await fetchFixedPrices();
-});
-
-onUnmounted(() => (stateStore.rightDrawer = false));
+// const updateMinPrice = async (value, props) => {
+//     // El checkbox hasMinPrice se encuentra en la misma columna que el input hasMinPrice
+//     // Por lo tanto le mandamos otro objeto con las mismas propiedades pero con el campo 'field' cambiado
+//     props.row.hasMinPrice = value;
+//     await upsertPrice({
+//         row: props.row,
+//         col: { field: 'hasMinPrice' },
+//         rowIndex: props.rowIndex,
+//     });
+// };
 </script>
 
 <template>
@@ -372,13 +268,13 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         order="id ASC"
         :columns="columns"
         auto-load
-        :is-editable="false"
+        :is-editable="true"
         :use-model="true"
     >
         <template #column-description="{ row }">
             <div class="row column full-width justify-between items-start">
-                {{ row?.description }}
-                <div v-if="row?.description" class="subName">
+                {{ row?.name }}
+                <div v-if="row?.subName" class="subName">
                     {{ row?.subName.toUpperCase() }}
                 </div>
             </div>
@@ -386,7 +282,12 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         </template>
     </VnTable>
 </template>
-
+<style lang="scss" scoped>
+.subName {
+    text-transform: uppercase;
+    color: var(--vn-label-color);
+}
+</style>
 <i18n>
 es:
     Add fixed price: Añadir precio fijado
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 8791a575f..f67f7eda2 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -100,6 +100,7 @@ const columns = computed(() => [
     {
         label: t('item.buyRequest.state'),
         name: 'state',
+        action: (row) => getState(row.isOk),
         align: 'left',
     },
     {
@@ -146,7 +147,6 @@ const confirmRequest = async (request) => {
                 `TicketRequests/${request.id}/confirm`,
                 params
             );
-
             request.itemDescription = data.concept;
             request.isOk = true;
             notify(t('globals.dataSaved'), 'positive');
@@ -338,15 +338,22 @@ onBeforeMount(() => {
         url="ticketRequests/filter"
         order="id DESC"
         :columns="columns"
-        :is-editable="false"
+        :is-editable="true"
         auto-load
     >
-        <template #column-attender="{ row }">
+        <template #column-attenderName="{ row }">
             <span class="link" @click.stop>
-                {{ row }}
+                {{ row.attenderName }}
                 <WorkerDescriptorProxy :id="row.attenderFk" />
             </span>
         </template>
+
+        <template #column-requesterName="{ row }">
+            <span class="link" @click.stop>
+                {{ row.requesterName }}
+                <WorkerDescriptorProxy :id="row.requesterFk" />
+            </span>
+        </template>
     </VnTable>
 </template>
 

From 1df089cef78e6728c764d7d72cc015b573f44f66 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 14 Aug 2024 15:50:13 +0200
Subject: [PATCH 017/207] refs #7283 fix itemFixedPrice

---
 src/pages/Item/ItemFixedPrice.vue | 65 ++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 14 deletions(-)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 56ad7a17d..30eb8544e 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -1,9 +1,10 @@
 <script setup>
-import { onMounted, ref, reactive, computed, onUnmounted, watch } from 'vue';
+import { ref, reactive, computed, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { toDate } from 'src/filters';
+import { useQuasar } from 'quasar';
 import FetchedTags from 'components/ui/FetchedTags.vue';
-import VnInput from 'src/components/common/VnInput.vue';
+import { useRoute } from 'vue-router';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { useVnConfirm } from 'composables/useVnConfirm';
@@ -11,20 +12,30 @@ import { useState } from 'src/composables/useState';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import { useArrayData } from 'composables/useArrayData';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import VnConfirm from 'components/ui/VnConfirm.vue';
 
-const stateStore = useStateStore();
+const route = useRoute();
 const { t } = useI18n();
 const { openConfirmationModal } = useVnConfirm();
 const state = useState();
 const { notify } = useNotify();
 const tableRef = ref();
-const editTableCellDialogRef = ref(null);
+const quasar = useQuasar();
 const user = state.getUser();
 const fixedPrices = ref([]);
 const fixedPricesOriginalData = ref([]);
 const warehousesOptions = ref([]);
 const rowsSelected = ref([]);
 
+// function localUserData() {
+//     state.setUser(user.value);
+// }
+
+// const userLocal = localUserData();
+// console.log('localUserData', userLocal);
+
+console.log('user', user.value.warehouseFk);
 const exprBuilder = (param, value) => {
     switch (param) {
         case 'name':
@@ -80,6 +91,10 @@ const columns = computed(() => [
         name: 'description',
         align: 'left',
         create: true,
+        columnCreate: {
+            component: 'select',
+            url: 'Items',
+        },
     },
     {
         label: t('item.fixedPrice.groupingPrice'),
@@ -109,6 +124,9 @@ const columns = computed(() => [
         align: 'left',
         create: true,
         format: (row) => toDate(row.started),
+        columnCreate: {
+            component: 'date',
+        },
     },
     {
         label: t('item.fixedPrice.ended'),
@@ -116,6 +134,9 @@ const columns = computed(() => [
         align: 'left',
         create: true,
         format: (row) => toDate(row.ended),
+        columnCreate: {
+            component: 'date',
+        },
     },
     {
         label: t('item.fixedPrice.warehouse'),
@@ -148,6 +169,27 @@ const columns = computed(() => [
     },
 ]);
 
+function confirmRemove(row) {
+    quasar.dialog({
+        component: VnConfirm,
+        componentProps: {
+            title: t('confirmDeletion'),
+            message: t('confirmDeletionMessage'),
+            promise: () => remove(row),
+        },
+    });
+}
+
+async function remove(item) {
+    await axios.post('FixedPrices/filter', {
+        rows: [item.id],
+    });
+    quasar.notify({
+        message: t('globals.dataDeleted'),
+        type: 'positive',
+    });
+    tableRef.value.reload();
+}
 // const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
 //     return inputType === 'text'
 //         ? {
@@ -213,15 +255,6 @@ const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
 //     fixedPrices.value.push(lastItemCopy);
 // };
 
-// const openEditTableCellDialog = () => {
-//     editTableCellDialogRef.value.show();
-// };
-
-// const onEditCellDataSaved = async () => {
-//     rowsSelected.value = [];
-//     await fetchFixedPrices();
-// };
-
 // const onWarehousesFetched = (data) => {
 //     warehousesOptions.value = data;
 //     // Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
@@ -259,6 +292,7 @@ const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
         ref="tableRef"
         data-key="ItemFixedPrices"
         url="FixedPrices/filter"
+        :filter="{ where: { warehouseFk: user.warehouseFk } }"
         :create="{
             urlCreate: 'PriceFixed',
             title: 'Create Item',
@@ -273,7 +307,10 @@ const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
     >
         <template #column-description="{ row }">
             <div class="row column full-width justify-between items-start">
-                {{ row?.name }}
+                <span class="link" @click.stop>
+                    {{ row?.name }}
+                    <ItemDescriptorProxy class="link" :id="row.itemFk" />
+                </span>
                 <div v-if="row?.subName" class="subName">
                     {{ row?.subName.toUpperCase() }}
                 </div>

From 12a5d6cec035b72deaa3c9f316d0f329d5411081 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 19 Aug 2024 17:05:00 +0200
Subject: [PATCH 018/207] fix: refs #7283 css

---
 src/components/VnTable/VnTable.vue | 7 ++++---
 src/pages/Item/ItemRequest.vue     | 1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 6c77d44df..69c4739bf 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -486,11 +486,12 @@ defineExpose({
                                 :icon="btn.icon"
                                 class="q-px-sm"
                                 flat
-                                :class="
+                                :class="[
                                     btn.isPrimary
                                         ? 'text-primary-light'
-                                        : 'color-vn-text '
-                                "
+                                        : 'color-vn-text ',
+                                    btn.class,
+                                ]"
                                 :style="`visibility: ${
                                     (btn.show && btn.show(row)) ?? true
                                         ? 'visible'
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index f67f7eda2..65c0aaae1 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -111,6 +111,7 @@ const columns = computed(() => [
             {
                 title: t('Client ticket list'),
                 icon: 'thumb_down',
+                class: 'fill-icon',
                 action: showDenyRequestForm,
                 isPrimary: true,
             },

From bae0b4de351f43a65de5b6ef05fbdaa9cd525d7c Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 22 Aug 2024 10:38:15 +0200
Subject: [PATCH 019/207] fix: itemBotanical

---
 src/pages/Item/Card/ItemBotanical.vue | 35 +++++++++++++--------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index 416c7f78b..88d251c47 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -13,7 +13,6 @@ import CreateSpecieForm from './CreateSpecieForm.vue';
 const route = useRoute();
 const { t } = useI18n();
 
-const itemBotanicalsRef = ref(null);
 const itemGenusOptions = ref([]);
 const itemSpeciesOptions = ref([]);
 const itemBotanicals = ref([]);
@@ -31,22 +30,19 @@ const onSpecieCreated = (response, formData) => {
 const entityId = computed(() => {
     return route.params.id;
 });
-onMounted(async () => {
-    itemBotanicalsForm.itemFk = entityId.value;
-    itemBotanicals.value = await itemBotanicalsRef.value.fetch();
-    if (itemBotanicals.value.length > 0)
-        Object.assign(itemBotanicalsForm, itemBotanicals.value[0]);
-});
+// onMounted(async () => {
+//     itemBotanicalsForm.itemFk = entityId.value;
+//     // itemBotanicals.value = await itemBotanicalsRef.value.fetch();
+//     if (itemBotanicals.value.length > 0)
+//         Object.assign(itemBotanicalsForm, itemBotanicals.value[0]);
+// });
+async function handleItemBotanical(data) {
+    itemBotanicalsForm = data;
+    // if (data.length > 0) Object.assign(itemBotanicalsForm, itemBotanicals.value[0]);
+}
 </script>
 <template>
-    <FetchData
-        ref="itemBotanicalsRef"
-        url="ItemBotanicals"
-        :filter="{
-            where: { itemFk: entityId },
-        }"
-        @on-fetch="(data) => (itemBotanicals = data)"
-    />
+    <!-- <FetchData ref="itemBotanicalsRef" @on-fetch="(data) => (itemBotanicals = data)" /> -->
     <FetchData
         url="Genera"
         :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
@@ -60,11 +56,14 @@ onMounted(async () => {
         auto-load
     />
     <FormModel
+        url="ItemBotanicals"
         url-update="ItemBotanicals"
-        model="entry"
+        model="item"
         auto-load
-        :form-initial-data="itemBotanicalsForm"
-        :clear-store-on-unmount="false"
+        :filter="{
+            where: { itemFk: entityId },
+        }"
+        @on-fetch="handleItemBotanical"
     >
         <template #form="{ data }">
             <VnRow>

From 2ef56f9f9730c0cbc8c287531ad12363a9f4c447 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 27 Aug 2024 08:00:07 +0200
Subject: [PATCH 020/207] refs #7283 fixedPrice

---
 src/pages/Item/ItemFixedPrice.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 30eb8544e..05a8545c8 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -292,6 +292,7 @@ const upsertPrice = async ({ row, col, rowIndex }, resetMinPrice = false) => {
         ref="tableRef"
         data-key="ItemFixedPrices"
         url="FixedPrices/filter"
+        save-url="FixedPrices/crud"
         :filter="{ where: { warehouseFk: user.warehouseFk } }"
         :create="{
             urlCreate: 'PriceFixed',

From 6de59c64194c4aec32294575a531dda73d5d8b0d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 27 Aug 2024 14:39:21 +0200
Subject: [PATCH 021/207] refs #7283 itemRequestFixed

---
 src/pages/Item/ItemFixedPrice.vue |  1 +
 src/pages/Item/ItemList.vue       |  2 ++
 src/pages/Item/ItemRequest.vue    | 31 +++++++++++++++++++++++++++----
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 05a8545c8..7ba4984e7 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -164,6 +164,7 @@ const columns = computed(() => [
             {
                 title: t('Delete'),
                 icon: 'delete',
+                isPrimary: true,
             },
         ],
     },
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index a3b70372f..2f3d20390 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -226,11 +226,13 @@ const columns = computed(() => [
                 title: t('Clone item'),
                 icon: 'vn:clone',
                 action: cloneItem,
+                isPrimary: true,
             },
             {
                 title: t('view Summary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row.id, ItemSummary),
+                isPrimary: true,
             },
         ],
     },
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 65c0aaae1..0d641f8e2 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -9,7 +9,8 @@ import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import { toDate } from 'src/filters';
 import VnTable from 'components/VnTable/VnTable.vue';
-
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const { t } = useI18n();
 const { notify } = useNotify();
 const stateStore = useStateStore();
@@ -64,7 +65,7 @@ const columns = computed(() => [
     },
     {
         label: t('item.buyRequest.requested'),
-        name: 'saleQuantity',
+        name: 'quantity',
         align: 'left',
     },
     {
@@ -100,7 +101,7 @@ const columns = computed(() => [
     {
         label: t('item.buyRequest.state'),
         name: 'state',
-        action: (row) => getState(row.isOk),
+        format: (row) => getState(row.isOk),
         align: 'left',
     },
     {
@@ -333,11 +334,12 @@ onBeforeMount(() => {
             />
         </QDialog>
     </QPage> -->
+    <VnSubToolbar />
     <VnTable
         ref="tableRef"
         data-key="itemRequest"
         url="ticketRequests/filter"
-        order="id DESC"
+        order="shippedDate ASC, isOk ASC"
         :columns="columns"
         :is-editable="true"
         auto-load
@@ -355,6 +357,27 @@ onBeforeMount(() => {
                 <WorkerDescriptorProxy :id="row.requesterFk" />
             </span>
         </template>
+
+        <template #column-item="{ row }">
+            <span @click.stop disabled="row.isOk != null">
+                <VnInput type="number" v-model="row.item" fill-input />
+            </span>
+        </template>
+        <template #column-achieved="{ row }">
+            <span @click.stop disabled="!request.itemFk || request.isOk != null">
+                <VnInput
+                    type="number"
+                    v-model="row.achieved"
+                    fill-input
+                    @keyup.enter="changeQuantity(row)"
+                />
+            </span>
+        </template>
+        <template #column-concept="{ row }">
+            <span @click.stop disabled="row.isOk != null">
+                {{ row.itemDescription }}
+            </span>
+        </template>
     </VnTable>
 </template>
 

From cd1b5f56f711ad8a0b0c3141c085f03897f36f8c Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 28 Aug 2024 11:35:57 +0200
Subject: [PATCH 022/207] refs #7283 column-action

---
 src/pages/Item/ItemRequest.vue | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 0d641f8e2..41248afbb 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -110,7 +110,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('Client ticket list'),
+                title: t('Deny Request'),
                 icon: 'thumb_down',
                 class: 'fill-icon',
                 action: showDenyRequestForm,
@@ -378,6 +378,32 @@ onBeforeMount(() => {
                 {{ row.itemDescription }}
             </span>
         </template>
+        <template #column-action="{ row, rowIndex }">
+            <QTd>
+                <QIcon
+                    v-if="row.response?.length"
+                    name="insert_drive_file"
+                    color="primary"
+                    size="sm"
+                >
+                    <QTooltip>
+                        {{ row.response }}
+                    </QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="row.isOk == null"
+                    name="thumb_down"
+                    color="primary"
+                    size="sm"
+                    class="fill-icon"
+                    @click="showDenyRequestForm(row.id, rowIndex)"
+                >
+                    <QTooltip>
+                        {{ t('Discard') }}
+                    </QTooltip>
+                </QIcon>
+            </QTd>
+        </template>
     </VnTable>
 </template>
 

From e4aec1773b74c002913bf60f807c07ca39a873f5 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 29 Aug 2024 12:38:57 +0200
Subject: [PATCH 023/207] refs #7283 itemRequest fix deny

---
 src/pages/Item/ItemRequest.vue | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 41248afbb..0e59a16c4 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -7,6 +7,7 @@ import { useArrayData } from 'composables/useArrayData';
 import { toCurrency } from 'filters/index';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
+import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
 import { toDate } from 'src/filters';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnInput from 'src/components/common/VnInput.vue';
@@ -26,6 +27,10 @@ const arrayData = useArrayData('ItemRequests', {
 });
 const store = arrayData.store;
 
+const userParams = {
+    state: 'pending',
+};
+
 watch(
     () => store.data,
     (value) => (itemRequestsOptions.value = value)
@@ -174,7 +179,9 @@ const onDenyAccept = (_, responseData) => {
     itemRequestsOptions.value[denyRequestIndex.value].isOk = responseData.isOk;
     itemRequestsOptions.value[denyRequestIndex.value].attenderFk =
         responseData.attenderFk;
+    console.log('itemRequestsOptions: ', itemRequestsOptions.value);
     itemRequestsOptions.value[denyRequestIndex.value].response = responseData.response;
+    console.log('itemRequestsOptions.value', itemRequestsOptions.value);
     denyRequestId.value = null;
     denyRequestIndex.value = null;
 };
@@ -341,8 +348,10 @@ onBeforeMount(() => {
         url="ticketRequests/filter"
         order="shippedDate ASC, isOk ASC"
         :columns="columns"
+        :user-params="userParams"
         :is-editable="true"
         auto-load
+        :disable-option="{ card: true }"
     >
         <template #column-attenderName="{ row }">
             <span class="link" @click.stop>
@@ -378,7 +387,7 @@ onBeforeMount(() => {
                 {{ row.itemDescription }}
             </span>
         </template>
-        <template #column-action="{ row, rowIndex }">
+        <template #column-tableActions="{ row, rowIndex }">
             <QTd>
                 <QIcon
                     v-if="row.response?.length"
@@ -405,6 +414,9 @@ onBeforeMount(() => {
             </QTd>
         </template>
     </VnTable>
+    <QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale">
+        <ItemRequestDenyForm :request-id="denyRequestId" @on-data-saved="onDenyAccept" />
+    </QDialog>
 </template>
 
 <i18n>

From 388036a2eb589b6475132e630ee555147938b4a6 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 2 Sep 2024 09:19:49 +0200
Subject: [PATCH 024/207] refs #7283 itemRequest fix

---
 src/pages/Item/ItemRequest.vue | 146 ++-------------------------------
 1 file changed, 7 insertions(+), 139 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 0e59a16c4..10ed237b4 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -208,140 +208,6 @@ onBeforeMount(() => {
 </script>
 
 <template>
-    <!-- <FetchData
-        url="Workers"
-        :filter="{ where: { role: 'buyer' } }"
-        order="id"
-        @on-fetch="(data) => (workersOptions = data)"
-        auto-load
-    />
-    <VnSearchbar
-        data-key="ItemRequests"
-        url="TicketRequests/filter"
-        :label="t('globals.search')"
-        :info="t('You can search by Id or alias')"
-        :redirect="false"
-    />
-    <RightMenu>
-        <template #right-panel>
-            <ItemRequestFilter data-key="ItemRequests" />
-        </template>
-    </RightMenu>
-    <QPage class="column items-center q-pa-md">
-        <QTable
-            :rows="itemRequestsOptions"
-            :columns="columns"
-            row-key="id"
-            :pagination="{ rowsPerPage: 0 }"
-            class="full-width q-mt-md"
-            :no-data-label="t('globals.noResults')"
-        >
-            <template #body-cell-id="{ row }">
-                <QTd>
-                    <QBtn flat color="primary"> {{ row.ticketFk }}</QBtn>
-                    <TicketDescriptorProxy :id="row.ticketFk" />
-                </QTd>
-            </template>
-            <template #body-cell-shipped="{ row }">
-                <QTd>
-                    <QBadge
-                        v-if="getDateQBadgeColor(row.shipped)"
-                        :color="getDateQBadgeColor(row.shipped)"
-                        text-color="black"
-                        class="q-ma-none"
-                        dense
-                        style="font-size: 14px"
-                    >
-                        {{ toDateFormat(row.shipped) }}
-                    </QBadge>
-                    <span v-else>{{ toDateFormat(row.shipped) }}</span>
-                </QTd>
-            </template>
-            <template #body-cell-requester="{ row }">
-                <QTd>
-                    <QBtn flat dense color="primary"> {{ row.requesterName }}</QBtn>
-                    <WorkerDescriptorProxy :id="row.requesterFk" />
-                </QTd>
-            </template>
-            <template #body-cell-attender="{ row }">
-                <QTd>
-                    <VnSelect
-                        v-model="row.attenderFk"
-                        :options="workersOptions"
-                        hide-selected
-                        option-label="firstName"
-                        option-value="id"
-                        dense
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-item="{ row }">
-                <QTd>
-                    <VnInput
-                        v-model.number="row.itemFk"
-                        type="number"
-                        :disable="row.isOk != null"
-                        dense
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-achieved="{ row }">
-                <QTd>
-                    <VnInput
-                        v-model.number="row.saleQuantity"
-                        @blur="changeQuantity(row)"
-                        type="number"
-                        :disable="!row.itemFk || row.isOk != null"
-                        dense
-                    />
-                </QTd>
-            </template>
-            <template #body-cell-concept="{ row }">
-                <QTd>
-                    <QBtn flat dense color="primary"> {{ row.itemDescription }}</QBtn>
-                    <ItemDescriptorProxy :id="row.itemFk" />
-                </QTd>
-            </template>
-            <template #body-cell-state="{ row }">
-                <QTd>
-                    <span>{{ getState(row.isOk) }}</span>
-                </QTd>
-            </template>
-            <template #body-cell-action="{ row, rowIndex }">
-                <QTd>
-                    <QIcon
-                        v-if="row.response?.length"
-                        name="insert_drive_file"
-                        color="primary"
-                        size="sm"
-                    >
-                        <QTooltip>
-                            {{ row.response }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.isOk == null"
-                        name="thumb_down"
-                        color="primary"
-                        size="sm"
-                        class="fill-icon"
-                        @click="showDenyRequestForm(row.id, rowIndex)"
-                    >
-                        <QTooltip>
-                            {{ t('Discard') }}
-                        </QTooltip>
-                    </QIcon>
-                </QTd>
-            </template>
-        </QTable>
-        <QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale">
-            <ItemRequestDenyForm
-                :request-id="denyRequestId"
-                @on-data-saved="onDenyAccept"
-            />
-        </QDialog>
-    </QPage> -->
-    <VnSubToolbar />
     <VnTable
         ref="tableRef"
         data-key="itemRequest"
@@ -368,17 +234,19 @@ onBeforeMount(() => {
         </template>
 
         <template #column-item="{ row }">
-            <span @click.stop disabled="row.isOk != null">
-                <VnInput type="number" v-model="row.item" fill-input />
+            <span>
+                <VnInput v-model.number="row.itemFk" dense />
             </span>
         </template>
         <template #column-achieved="{ row }">
-            <span @click.stop disabled="!request.itemFk || request.isOk != null">
+            <span>
                 <VnInput
                     type="number"
-                    v-model="row.achieved"
-                    fill-input
+                    v-model.number="row.saleQuantity"
+                    :disable="!row.itemFk || row.isOk != null"
+                    @blur="changeQuantity(row)"
                     @keyup.enter="changeQuantity(row)"
+                    dense
                 />
             </span>
         </template>

From 3bf3e8eeaa4c93dd2c8a737d5a95fb0528abbe50 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 2 Sep 2024 11:08:50 +0200
Subject: [PATCH 025/207] refs #7283 itemRequest fix deny

---
 src/pages/Item/ItemRequest.vue | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 10ed237b4..8273c5c91 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -112,16 +112,7 @@ const columns = computed(() => [
     {
         align: 'right',
         label: '',
-        name: 'tableActions',
-        actions: [
-            {
-                title: t('Deny Request'),
-                icon: 'thumb_down',
-                class: 'fill-icon',
-                action: showDenyRequestForm,
-                isPrimary: true,
-            },
-        ],
+        name: 'denyOptions',
     },
 ]);
 
@@ -171,7 +162,9 @@ const getState = (isOk) => {
 
 const showDenyRequestForm = (requestId, rowIndex) => {
     denyRequestId.value = requestId;
+    console.log('denyRequestId.value: ', denyRequestId.value);
     denyRequestIndex.value = rowIndex;
+    console.log('denyRequestIndex.value: ', denyRequestIndex.value);
     denyFormRef.value.show();
 };
 
@@ -255,8 +248,8 @@ onBeforeMount(() => {
                 {{ row.itemDescription }}
             </span>
         </template>
-        <template #column-tableActions="{ row, rowIndex }">
-            <QTd>
+        <template #column-denyOptions="{ row, rowIndex }">
+            <QTd class="sticky no-padding">
                 <QIcon
                     v-if="row.response?.length"
                     name="insert_drive_file"

From 488dc74c1f07c9314dc14618765c7250191ae72d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 2 Sep 2024 12:14:23 +0200
Subject: [PATCH 026/207] refs #7283 itemRequest fix reload

---
 src/pages/Item/ItemRequest.vue | 24 +++---------------------
 1 file changed, 3 insertions(+), 21 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 8273c5c91..4062f8538 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed, onMounted, onBeforeMount, watch } from 'vue';
+import { ref, computed, onMounted, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 import { useStateStore } from 'stores/useStateStore';
@@ -11,7 +11,6 @@ import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
 import { toDate } from 'src/filters';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const { t } = useI18n();
 const { notify } = useNotify();
 const stateStore = useStateStore();
@@ -31,6 +30,7 @@ const userParams = {
     state: 'pending',
 };
 
+const tableRef = ref();
 watch(
     () => store.data,
     (value) => (itemRequestsOptions.value = value)
@@ -162,9 +162,7 @@ const getState = (isOk) => {
 
 const showDenyRequestForm = (requestId, rowIndex) => {
     denyRequestId.value = requestId;
-    console.log('denyRequestId.value: ', denyRequestId.value);
     denyRequestIndex.value = rowIndex;
-    console.log('denyRequestIndex.value: ', denyRequestIndex.value);
     denyFormRef.value.show();
 };
 
@@ -172,32 +170,16 @@ const onDenyAccept = (_, responseData) => {
     itemRequestsOptions.value[denyRequestIndex.value].isOk = responseData.isOk;
     itemRequestsOptions.value[denyRequestIndex.value].attenderFk =
         responseData.attenderFk;
-    console.log('itemRequestsOptions: ', itemRequestsOptions.value);
     itemRequestsOptions.value[denyRequestIndex.value].response = responseData.response;
-    console.log('itemRequestsOptions.value', itemRequestsOptions.value);
     denyRequestId.value = null;
     denyRequestIndex.value = null;
+    tableRef.value.reload();
 };
 
 onMounted(async () => {
     await arrayData.fetch({ append: false });
     stateStore.rightDrawer = true;
 });
-
-onBeforeMount(() => {
-    const today = Date.vnNew();
-    today.setHours(0, 0, 0, 0);
-
-    const nextWeek = Date.vnNew();
-    nextWeek.setHours(23, 59, 59, 59);
-    nextWeek.setDate(nextWeek.getDate() + 7);
-
-    filterParams.value = {
-        from: today,
-        to: nextWeek,
-        state: 'pending',
-    };
-});
 </script>
 
 <template>

From 04c8481b51e70f3062d7d0a997bdab2fece7c98a Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 12 Sep 2024 07:43:12 +0200
Subject: [PATCH 027/207] refs #7283 fix itemFixed

---
 src/pages/Item/ItemFixedPrice.vue | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 29b886e25..d91b5189e 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -1,6 +1,5 @@
 <script setup>
 import { onMounted, ref, reactive, onUnmounted, nextTick, computed } from 'vue';
-import { ref, reactive, computed, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import FetchedTags from 'components/ui/FetchedTags.vue';
@@ -27,15 +26,12 @@ import { QCheckbox } from 'quasar';
 
 const quasar = useQuasar();
 const stateStore = useStateStore();
-const route = useRoute();
 const { t } = useI18n();
 const { openConfirmationModal } = useVnConfirm();
 const state = useState();
 const { notify } = useNotify();
 const tableRef = ref();
 const editTableCellDialogRef = ref(null);
-const tableRef = ref();
-const quasar = useQuasar();
 const user = state.getUser();
 const fixedPrices = ref([]);
 const warehousesOptions = ref([]);
@@ -129,6 +125,7 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.started'),
+        field: 'started',
         name: 'started',
         format: ({ started }) => toDate(started),
         cardVisible: true,
@@ -144,6 +141,7 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.ended'),
+        field: 'ended',
         name: 'ended',
         ...defaultColumnAttrs,
         cardVisible: true,
@@ -157,6 +155,7 @@ const columns = computed(() => [
         columnClass: 'expand',
         format: (row) => toDate(row.ended),
     },
+
     {
         label: t('item.fixedPrice.warehouse'),
         field: 'warehouseFk',
@@ -223,18 +222,17 @@ const editTableFieldsOptions = [
         label: t('item.fixedPrice.ended'),
         component: 'date',
     },
-];
-
-function confirmRemove(row) {
-    quasar.dialog({
-        component: VnConfirm,
-        componentProps: {
-            title: t('confirmDeletion'),
-            message: t('confirmDeletionMessage'),
-            promise: () => remove(row),
+    {
+        field: 'warehouseFk',
+        label: t('item.fixedPrice.warehouse'),
+        component: 'select',
+        attrs: {
+            options: [],
+            'option-label': 'name',
+            'option-value': 'id',
         },
-    }),
-};
+    },
+];
 const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
     return inputType === 'text'
         ? {

From 039a8d1d02e1ca30a2dd6701a60b7211b3de01cd Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 12 Sep 2024 09:32:41 +0200
Subject: [PATCH 028/207] refs #7283 fix items

---
 src/i18n/locale/en.yml           |  2 ++
 src/i18n/locale/es.yml           |  2 ++
 src/pages/Item/Card/ItemCard.vue |  2 +-
 src/pages/Item/ItemList.vue      | 49 ++++++++++++--------------------
 src/pages/Item/ItemRequest.vue   |  2 +-
 5 files changed, 24 insertions(+), 33 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 6546b78c4..37d1e3726 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -1022,6 +1022,8 @@ travel:
         travelFileDescription: 'Travel id { travelId }'
         file: File
 item:
+    searchbar:
+        label: Search item
     descriptor:
         item: Item
         buyer: Buyer
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 79e66b5f7..0c0447b78 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -1007,6 +1007,8 @@ travel:
         travelFileDescription: 'Id envío { travelId }'
         file: Fichero
 item:
+    searchbar:
+        label: Buscar artículo
     descriptor:
         item: Artículo
         buyer: Comprador
diff --git a/src/pages/Item/Card/ItemCard.vue b/src/pages/Item/Card/ItemCard.vue
index 1162327c1..4cf1372cc 100644
--- a/src/pages/Item/Card/ItemCard.vue
+++ b/src/pages/Item/Card/ItemCard.vue
@@ -12,7 +12,7 @@ import ItemListFilter from '../ItemListFilter.vue';
         search-data-key="ItemList"
         :searchbar-props="{
             url: 'Items/filter',
-            label: 'searchbar.labelr',
+            label: 'item.searchbar.label',
             info: 'searchbar.info',
         }"
     />
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 2f3d20390..c31302bba 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -44,25 +44,24 @@ const itemFilter = {
     ],
 };
 const columns = computed(() => [
-    // {
-    //     label: '',
-    //     name: 'image',
-    //     align: 'left',
-    //     columnField: {
-    //         component: VnImg,
-    //         attrs: (id) => {
-    //             return {
-    //                 id,
-    //                 width: '50px',
-    //             };
-    //         },
-    //     },
-    //     columnFilter: false,
-    // },
+    {
+        label: '',
+        name: 'image',
+        align: 'left',
+        columnField: {
+            component: VnImg,
+            attrs: (id) => {
+                return {
+                    id,
+                    width: '50px',
+                };
+            },
+        },
+        columnFilter: false,
+    },
     {
         label: t('item.list.id'),
         name: 'id',
-        field: 'id',
         align: 'left',
         isId: true,
         chip: {
@@ -71,38 +70,35 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.grouping'),
-        field: 'grouping',
         name: 'grouping',
         align: 'left',
     },
     {
         label: t('item.list.packing'),
-        field: 'packing',
         name: 'packing',
         align: 'left',
     },
     {
         label: t('globals.description'),
-        field: 'name',
         name: 'description',
         align: 'left',
         create: true,
+        columnFilter: {
+            name: 'description',
+        },
     },
     {
         label: t('item.list.stems'),
-        field: 'stems',
         name: 'stems',
         align: 'left',
     },
     {
         label: t('item.list.size'),
-        field: 'size',
         name: 'size',
         align: 'left',
     },
     {
         label: t('item.list.typeName'),
-        field: 'typeName',
         name: 'typeName',
         align: 'left',
         component: 'select',
@@ -117,7 +113,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.category'),
-        field: 'category',
         name: 'category',
         align: 'left',
         component: 'select',
@@ -131,7 +126,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.intrastat'),
-        field: 'intrastat',
         name: 'intrastat',
         align: 'left',
         component: 'select',
@@ -146,7 +140,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.origin'),
-        field: 'origin',
         name: 'origin',
         align: 'left',
         component: 'select',
@@ -161,13 +154,11 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.userName'),
-        field: 'userName',
         name: 'userName',
         align: 'left',
     },
     {
         label: t('item.list.weightByPiece'),
-        field: 'weightByPiece',
         name: 'weightByPiece',
         align: 'left',
         component: 'input',
@@ -177,7 +168,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.stemMultiplier'),
-        field: 'stemMultiplier',
         name: 'stemMultiplier',
         align: 'left',
         component: 'input',
@@ -187,14 +177,12 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.isActive'),
-        field: 'isActive',
         name: 'isActive',
         align: 'left',
         component: 'checkbox',
     },
     {
         label: t('item.list.producer'),
-        field: 'producer',
         name: 'producer',
         align: 'left',
         component: 'select',
@@ -208,7 +196,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.landed'),
-        field: 'landed',
         name: 'landed',
         align: 'left',
         component: 'date',
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index be0a9c2e8..4bf45fe4c 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -188,7 +188,7 @@ onMounted(async () => {
         ref="tableRef"
         data-key="itemRequest"
         url="ticketRequests/filter"
-        order="shippedDate ASC, isOk ASC"
+        order="shipped ASC, isOk ASC"
         :columns="columns"
         :user-params="userParams"
         :is-editable="true"

From 68a2ac385f6638d0b23168f085984b2d8b40d313 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 12 Sep 2024 11:36:02 +0200
Subject: [PATCH 029/207] refs #7283 fix items images

---
 src/pages/Item/ItemList.vue | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index c31302bba..ca00a6502 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -50,9 +50,9 @@ const columns = computed(() => [
         align: 'left',
         columnField: {
             component: VnImg,
-            attrs: (id) => {
+            attrs: ({ row }) => {
                 return {
-                    id,
+                    id: row.id,
                     width: '50px',
                 };
             },
@@ -102,9 +102,11 @@ const columns = computed(() => [
         name: 'typeName',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'ItemTypes',
-            fields: ['id', 'name'],
+        columnFilter: {
+            attrs: {
+                url: 'ItemTypes',
+                fields: ['name'],
+            },
         },
         columnField: {
             component: null,

From 050d8ae208329f51e38f3e3acb79fe4c8e8a991a Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 12 Sep 2024 11:43:37 +0200
Subject: [PATCH 030/207] refs #7283 fix items error get images

---
 src/pages/Item/ItemList.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index ca00a6502..bed30725b 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -52,7 +52,7 @@ const columns = computed(() => [
             component: VnImg,
             attrs: ({ row }) => {
                 return {
-                    id: row.id,
+                    id: row?.id,
                     width: '50px',
                 };
             },

From 1916c6e4bf0b3b161b9c1ccaf6d554d5e5c2c83b Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 16 Sep 2024 14:29:39 +0200
Subject: [PATCH 031/207] refs #7283 itemFilters

---
 src/pages/Item/ItemList.vue    | 50 ++++++++++++++++++++++++----------
 src/pages/Item/ItemRequest.vue | 11 ++++++--
 2 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index bed30725b..b6668edea 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -84,7 +84,7 @@ const columns = computed(() => [
         align: 'left',
         create: true,
         columnFilter: {
-            name: 'description',
+            name: 'search',
         },
     },
     {
@@ -103,9 +103,10 @@ const columns = computed(() => [
         align: 'left',
         component: 'select',
         columnFilter: {
+            name: 'typeFk',
             attrs: {
                 url: 'ItemTypes',
-                fields: ['name'],
+                fields: ['id', 'name'],
             },
         },
         columnField: {
@@ -118,9 +119,12 @@ const columns = computed(() => [
         name: 'category',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'ItemCategories',
-            fields: ['id', 'name'],
+        columnFilter: {
+            name: 'categoryFk',
+            attrs: {
+                url: 'ItemCategories',
+                fields: ['id', 'name'],
+            },
         },
         columnField: {
             component: null,
@@ -131,9 +135,15 @@ const columns = computed(() => [
         name: 'intrastat',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'Intrastats',
-            fields: ['id', 'description'],
+        columnFilter: {
+            name: 'description',
+            attrs: {
+                url: 'Intrastats',
+                optionValue: 'description',
+                optionLabel: 'description',
+            },
+            inWhere: true,
+            alias: 'intr',
         },
         columnField: {
             component: null,
@@ -145,9 +155,15 @@ const columns = computed(() => [
         name: 'origin',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'Origins',
-            fields: ['id', 'name'],
+        columnFilter: {
+            name: 'id',
+            attrs: {
+                url: 'Origins',
+                optionValue: 'id',
+                optionLabel: 'code',
+            },
+            inWhere: true,
+            alias: 'ori',
         },
         columnField: {
             component: null,
@@ -158,6 +174,14 @@ const columns = computed(() => [
         label: t('item.list.userName'),
         name: 'userName',
         align: 'left',
+        columnFilter: {
+            name: 'workerFk',
+            attrs: {
+                url: 'Users',
+                optionValue: 'id',
+                optionLabel: 'userName',
+            },
+        },
     },
     {
         label: t('item.list.weightByPiece'),
@@ -249,8 +273,6 @@ const cloneItem = async (itemFk) => {
         data-key="ItemList"
         url="Items/filter"
         url-create="Items"
-        save-url="Items/crud"
-        :filter="itemFilter"
         :create="{
             urlCreate: 'Items',
             title: 'Create Item',
@@ -264,7 +286,7 @@ const cloneItem = async (itemFk) => {
         auto-load
         redirect="Item"
         :is-editable="false"
-        :use-model="true"
+        :filer="itemFilter"
     >
         <template #column-userName="{ row }">
             <span class="link" @click.stop>
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 4bf45fe4c..1a1d98211 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -57,45 +57,51 @@ const columns = computed(() => [
             component: null,
         },
         format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.shipped)),
+        columnClass: 'shrink',
     },
     {
         label: t('globals.description'),
         field: 'description',
         name: 'description',
         align: 'left',
+        columnClass: 'expand',
     },
     {
         label: t('item.buyRequest.requester'),
         name: 'requesterName',
-        align: 'left',
+        columnClass: 'shrink',
     },
     {
         label: t('item.buyRequest.requested'),
         name: 'quantity',
-        align: 'left',
+        columnClass: 'shrink',
     },
     {
         label: t('item.buyRequest.price'),
         name: 'price',
         align: 'left',
         format: (row) => toCurrency(row.price),
+        columnClass: 'shrink',
     },
     {
         label: t('item.buyRequest.attender'),
         name: 'attenderName',
         align: 'left',
+        columnClass: 'shrink',
     },
     {
         label: t('item.buyRequest.item'),
         name: 'item',
         align: 'left',
         component: 'input',
+        columnClass: 'expand',
     },
     {
         label: t('item.buyRequest.achieved'),
         name: 'achieved',
         align: 'left',
         component: 'input',
+        columnClass: 'shrink',
     },
     {
         label: t('item.buyRequest.concept'),
@@ -103,6 +109,7 @@ const columns = computed(() => [
         align: 'left',
         sortable: true,
         component: 'input',
+        columnClass: 'expand',
     },
     {
         label: t('item.buyRequest.state'),

From db783e15384163fdb7221afae2fc4e509e0c4c52 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 17 Sep 2024 15:03:30 +0200
Subject: [PATCH 032/207] refs #7283 item Descriptor

---
 src/composables/useArrayData.js             |   1 +
 src/pages/Item/Card/ItemDescriptor.vue      |  70 ++++++-------
 src/pages/Item/Card/ItemDescriptorImage.vue |   8 +-
 src/pages/Item/Card/ItemDiary.vue           | 110 +++++++++++---------
 4 files changed, 98 insertions(+), 91 deletions(-)

diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 651bcefb0..6671632b3 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -246,6 +246,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
     }
 
     function updateStateParams() {
+        if (!route) return;
         const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
         newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
 
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index baac0c608..a14ee1446 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -14,6 +14,7 @@ import useCardDescription from 'src/composables/useCardDescription';
 import { getUrl } from 'src/composables/getUrl';
 import axios from 'axios';
 import { dashIfEmpty } from 'src/filters';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const $props = defineProps({
     id: {
@@ -49,58 +50,49 @@ const entityId = computed(() => {
 });
 
 const regularizeStockFormDialog = ref(null);
-const available = ref(null);
-const visible = ref(null);
 const salixUrl = ref();
+const mounted = ref();
+
+const arrayDataStock = useArrayData('descriptorStock', {
+    url: `Items/${entityId.value}/getVisibleAvailable`,
+});
 
 onMounted(async () => {
-    salixUrl.value = await getUrl('');
+    salixUrl.value = await getUrl('getVisibleAvailable');
     await getItemConfigs();
-    await updateStock();
+    mounted.value = true;
 });
 
 const data = ref(useCardDescription());
 const setData = async (entity) => {
-    try {
-        if (!entity) return;
-        data.value = useCardDescription(entity.name, entity.id);
-        await updateStock();
-    } catch (err) {
-        console.error('Error item');
-    }
+    if (!entity) return;
+    data.value = useCardDescription(entity.name, entity.id);
+    await updateStock();
 };
 
 const getItemConfigs = async () => {
-    try {
-        const { data } = await axios.get('ItemConfigs/findOne');
-        if (!data) return;
-        return (warehouseConfig.value = data.warehouseFk);
-    } catch (err) {
-        console.error('Error item');
-    }
+    const { data } = await axios.get('ItemConfigs/findOne');
+    if (!data) return;
+    return (warehouseConfig.value = data.warehouseFk);
 };
 const updateStock = async () => {
-    try {
-        available.value = null;
-        visible.value = null;
+    if (!mounted.value) return;
+    await getItemConfigs();
 
-        const params = {
-            warehouseFk: $props.warehouseFk,
-            dated: $props.dated,
-        };
+    const params = {
+        warehouseFk: $props.warehouseFk ?? warehouseConfig.value,
+        dated: $props.dated,
+    };
 
-        await getItemConfigs();
-        if (!params.warehouseFk) {
-            params.warehouseFk = warehouseConfig.value;
-        }
-        const { data } = await axios.get(`Items/${entityId.value}/getVisibleAvailable`, {
-            params,
-        });
-        available.value = data.available;
-        visible.value = data.visible;
-    } catch (err) {
-        console.error('Error updating stock');
-    }
+    if (!params.warehouseFk) return;
+
+    const stock = useArrayData('descriptorStock', {
+        url: `Items/${entityId.value}/getVisibleAvailable`,
+        userParams: params,
+    });
+    const storeData = stock.store.data;
+    if (storeData?.itemFk == entityId.value) return;
+    await stock.fetch({});
 };
 
 const openRegularizeStockForm = () => {
@@ -163,8 +155,8 @@ const openCloneDialog = async () => {
         <template #before>
             <ItemDescriptorImage
                 :entity-id="entityId"
-                :visible="visible"
-                :available="available"
+                :visible="arrayDataStock.store.data?.visible"
+                :available="arrayDataStock.store.data?.available"
             />
         </template>
         <template #body="{ entity }">
diff --git a/src/pages/Item/Card/ItemDescriptorImage.vue b/src/pages/Item/Card/ItemDescriptorImage.vue
index a4ef22ce3..b035a630a 100644
--- a/src/pages/Item/Card/ItemDescriptorImage.vue
+++ b/src/pages/Item/Card/ItemDescriptorImage.vue
@@ -32,6 +32,10 @@ const editPhotoFormDialog = ref(null);
 const showEditPhotoForm = ref(false);
 const warehouseName = ref(null);
 
+onMounted(async () => {
+    getItemConfigs();
+});
+
 const toggleEditPictureForm = () => {
     showEditPhotoForm.value = !showEditPhotoForm.value;
 };
@@ -56,10 +60,6 @@ const getWarehouseName = async (warehouseFk) => {
     warehouseName.value = data.name;
 };
 
-onMounted(async () => {
-    getItemConfigs();
-});
-
 const handlePhotoUpdated = (evt = false) => {
     image.value.reload(evt);
 };
diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index 68633caa2..a36b6a246 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -17,6 +17,7 @@ import { toDateFormat } from 'src/filters/date.js';
 import { dashIfEmpty } from 'src/filters';
 import { date } from 'quasar';
 import { useState } from 'src/composables/useState';
+import { useArrayData } from 'src/composables/useArrayData';
 import axios from 'axios';
 
 const { t } = useI18n();
@@ -37,6 +38,33 @@ const warehouseFk = ref(null);
 const _showWhatsBeforeInventory = ref(false);
 const inventoriedDate = ref(null);
 
+const originTypeMap = {
+    entry: {
+        descriptor: EntryDescriptorProxy,
+        icon: 'vn:entry',
+        color: 'green',
+    },
+    ticket: {
+        descriptor: TicketDescriptorProxy,
+        icon: 'vn:ticket',
+        color: 'red',
+    },
+    order: {
+        descriptor: OrderDescriptorProxy,
+        icon: 'vn:basket',
+        color: 'yellow',
+    },
+};
+
+const entityTypeMap = {
+    client: {
+        descriptor: CustomerDescriptorProxy,
+    },
+    supplier: {
+        descriptor: SupplierDescriptorProxy,
+    },
+};
+
 const columns = computed(() => [
     {
         name: 'claim',
@@ -105,6 +133,28 @@ const showWhatsBeforeInventory = computed({
     },
 });
 
+onMounted(async () => {
+    today.value.setHours(0, 0, 0, 0);
+    if (route.query.warehouseFk) warehouseFk.value = route.query.warehouseFk;
+    else if (user.value) warehouseFk.value = user.value.warehouseFk;
+    itemsBalanceFilter.where.warehouseFk = warehouseFk.value;
+    const { data } = await axios.get('Configs/findOne');
+    inventoriedDate.value = data.inventoried;
+    await fetchItemBalances();
+    await scrollToToday();
+    await updateWarehouse(warehouseFk.value);
+});
+
+onUnmounted(() => (stateStore.rightDrawer = false));
+
+watch(
+    () => router.currentRoute.value.params.id,
+    (newId) => {
+        itemsBalanceFilter.where.itemFk = newId;
+        itemBalancesRef.value.fetch();
+    }
+);
+
 const fetchItemBalances = async () => await itemBalancesRef.value.fetch();
 
 const getBadgeAttrs = (_date) => {
@@ -131,53 +181,15 @@ const formatDateForAttribute = (dateValue) => {
     return dateValue;
 };
 
-const originTypeMap = {
-    entry: {
-        descriptor: EntryDescriptorProxy,
-        icon: 'vn:entry',
-        color: 'green',
-    },
-    ticket: {
-        descriptor: TicketDescriptorProxy,
-        icon: 'vn:ticket',
-        color: 'red',
-    },
-    order: {
-        descriptor: OrderDescriptorProxy,
-        icon: 'vn:basket',
-        color: 'yellow',
-    },
-};
-
-const entityTypeMap = {
-    client: {
-        descriptor: CustomerDescriptorProxy,
-    },
-    supplier: {
-        descriptor: SupplierDescriptorProxy,
-    },
-};
-
-onMounted(async () => {
-    today.value.setHours(0, 0, 0, 0);
-    if (route.query.warehouseFk) warehouseFk.value = route.query.warehouseFk;
-    else if (user.value) warehouseFk.value = user.value.warehouseFk;
-    itemsBalanceFilter.where.warehouseFk = warehouseFk.value;
-    const { data } = await axios.get('Configs/findOne');
-    inventoriedDate.value = data.inventoried;
-    await fetchItemBalances();
-    await scrollToToday();
-});
-
-onUnmounted(() => (stateStore.rightDrawer = false));
-
-watch(
-    () => router.currentRoute.value.params.id,
-    (newId) => {
-        itemsBalanceFilter.where.itemFk = newId;
-        itemBalancesRef.value.fetch();
-    }
-);
+async function updateWarehouse(warehouseFk) {
+    const stock = useArrayData('descriptorStock', {
+        userParams: {
+            warehouseFk,
+        },
+    });
+    await stock.fetch({});
+    stock.store.data.itemFk = route.params.id
+}
 </script>
 
 <template>
@@ -203,7 +215,9 @@ watch(
                 option-value="id"
                 dense
                 v-model="itemsBalanceFilter.where.warehouseFk"
-                @update:model-value="fetchItemBalances"
+                @update:model-value="
+                    (value) => fetchItemBalances() && updateWarehouse(value)
+                "
                 class="q-mr-lg"
             />
             <QCheckbox

From 716d018121026767ecd2e9b5b1f47dffa349a028 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Fri, 20 Sep 2024 14:20:26 +0200
Subject: [PATCH 033/207] refs #72983 fix filters

---
 src/pages/Item/ItemList.vue | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index b6668edea..48fe3280e 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -54,6 +54,7 @@ const columns = computed(() => [
                 return {
                     id: row?.id,
                     width: '50px',
+                    zoomResolution: '1600x900',
                 };
             },
         },
@@ -72,11 +73,19 @@ const columns = computed(() => [
         label: t('item.list.grouping'),
         name: 'grouping',
         align: 'left',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         label: t('item.list.packing'),
         name: 'packing',
         align: 'left',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         label: t('globals.description'),
@@ -91,11 +100,19 @@ const columns = computed(() => [
         label: t('item.list.stems'),
         name: 'stems',
         align: 'left',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         label: t('item.list.size'),
         name: 'size',
         align: 'left',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         label: t('item.list.typeName'),

From 54015fb6bfbf975a7fed3150cf82de904df56d63 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 1 Oct 2024 08:44:08 +0200
Subject: [PATCH 034/207] refs #7283 fix itemMigration

---
 src/pages/Item/ItemRequest.vue | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 1a1d98211..7fbeccbf9 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -117,6 +117,15 @@ const columns = computed(() => [
         format: (row) => getState(row.isOk),
         align: 'left',
     },
+    {
+        align: 'left',
+        name: 'daysOnward',
+        label: t('item.buyRequest.daysOnward'),
+        visible: false,
+        columnFilter: {
+            inWhere: false,
+        },
+    },
     {
         align: 'right',
         label: '',
@@ -238,6 +247,17 @@ onMounted(async () => {
                 {{ row.itemDescription }}
             </span>
         </template>
+        <template #moreFilterPanel="{ params }">
+            <VnInputNumber
+                :label="t('params.scopeDays')"
+                v-model.number="params.scopeDays"
+                @keyup.enter="(evt) => handleScopeDays(evt.target.value)"
+                @remove="handleScopeDays()"
+                class="q-px-xs q-pr-lg"
+                filled
+                dense
+            />
+        </template>
         <template #column-denyOptions="{ row, rowIndex }">
             <QTd class="sticky no-padding">
                 <QIcon

From 55ddc8644f0450091f49ce96d4ef1ad2d3988a68 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 2 Oct 2024 12:51:33 +0200
Subject: [PATCH 035/207] refs #7283 fix itemMigration list filters

---
 src/pages/Item/ItemList.vue    | 8 +++++++-
 src/pages/Item/ItemRequest.vue | 3 ++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 48fe3280e..ad2c2e238 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -208,6 +208,9 @@ const columns = computed(() => [
         columnField: {
             component: null,
         },
+        columnFilter: {
+            inWhere: true,
+        },
     },
     {
         label: t('item.list.stemMultiplier'),
@@ -217,11 +220,14 @@ const columns = computed(() => [
         columnField: {
             component: null,
         },
+        columnFilter: {
+            inWhere: true,
+        },
     },
     {
         label: t('item.list.isActive'),
         name: 'isActive',
-        align: 'left',
+        align: 'center',
         component: 'checkbox',
     },
     {
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 7fbeccbf9..0eba6f9a4 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -29,6 +29,7 @@ const store = arrayData.store;
 
 const userParams = {
     state: 'pending',
+    daysOnward: 7,
 };
 
 const tableRef = ref();
@@ -120,7 +121,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'daysOnward',
-        label: t('item.buyRequest.daysOnward'),
+        label: t('travel.travelList.tableVisibleColumns.daysOnward'),
         visible: false,
         columnFilter: {
             inWhere: false,

From 419d3d2d45b16d268da452d06fbc1aadfeb03707 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Thu, 10 Oct 2024 07:20:33 +0200
Subject: [PATCH 036/207] fix: refs #6896 fixed module problems

---
 src/components/ui/VnFilterPanel.vue          | 12 ++-
 src/components/ui/VnSearchbar.vue            |  2 +
 src/i18n/locale/en.yml                       |  2 +
 src/i18n/locale/es.yml                       |  4 +-
 src/pages/Order/Card/OrderCatalog.vue        |  6 +-
 src/pages/Order/Card/OrderCatalogFilter.vue  | 88 +++++++-------------
 src/pages/Order/Card/OrderDescriptor.vue     | 10 +--
 src/pages/Order/Card/OrderDescriptorMenu.vue |  7 +-
 src/pages/Order/Card/OrderLines.vue          |  3 +-
 src/pages/Order/Card/OrderSummary.vue        | 27 ++++++
 10 files changed, 87 insertions(+), 74 deletions(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 43d634ad9..242c4220d 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -185,6 +185,9 @@ async function remove(key) {
 }
 
 function formatValue(value) {
+    if (typeof value === 'object') {
+        return value;
+    }
     if (typeof value === 'boolean') return value ? t('Yes') : t('No');
     if (isNaN(value) && !isNaN(Date.parse(value))) return toDate(value);
 
@@ -193,6 +196,13 @@ function formatValue(value) {
 
 function sanitizer(params) {
     for (const [key, value] of Object.entries(params)) {
+        if (key == 'and') {
+            value.forEach((andValue) => {
+                params = { ...params, ...andValue };
+            });
+            delete params[key];
+        }
+
         if (value && typeof value === 'object') {
             const param = Object.values(value)[0];
             if (typeof param == 'string') params[key] = param.replaceAll('%', '');
@@ -211,7 +221,7 @@ function sanitizer(params) {
         icon="search"
         @click="search()"
     ></QBtn>
-    <QForm @submit="search" id="filterPanelForm" @keyup.enter="search()">
+    <QForm @submit="search(true)" id="filterPanelForm" @keyup.enter="search(true)">
         <QList dense>
             <QItem class="q-mt-xs">
                 <QItemSection top>
diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index dc6d4751c..fc292e980 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -9,6 +9,7 @@ import { useStateStore } from 'src/stores/useStateStore';
 const quasar = useQuasar();
 const { t } = useI18n();
 const state = useStateStore();
+const emit = defineEmits(['on-search']);
 
 const props = defineProps({
     dataKey: {
@@ -118,6 +119,7 @@ async function search() {
         delete filter.params.search;
     }
     await arrayData.applyFilter(filter);
+    emit('on-search', store.data);
 }
 </script>
 <template>
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 6235447fe..e24926092 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -705,6 +705,8 @@ order:
         quantity: Quantity
         price: Price
         amount: Amount
+        confirm: Confirm
+        confirmLines: Confirm lines
 department:
     pageTitles:
         basicData: Basic data
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 6076af5d9..648868fcb 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -679,13 +679,15 @@ order:
         vat: IVA
         state: Estado
         alias: Alias
-        items: Items
+        items: Artículos
         orderTicketList: Tickets del pedido
         details: Detalles
         item: Item
         quantity: Cantidad
         price: Precio
         amount: Monto
+        confirm: Confirmar
+        confirmLines: Confirmar lineas
 shelving:
     list:
         parking: Parking
diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index b13e8661d..110ea48af 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -86,11 +86,8 @@ function extractValueTags(items) {
         <div class="full-width">
             <VnPaginate
                 data-key="OrderCatalogList"
-                url="Orders/CatalogFilter"
-                :limit="50"
-                :user-params="catalogParams"
-                @on-fetch="extractTags"
                 :update-router="false"
+                @on-change="extractTags"
             >
                 <template #body="{ rows }">
                     <div class="catalog-list">
@@ -102,6 +99,7 @@ function extractValueTags(items) {
                             :key="row.id"
                             :item="row"
                             is-catalog
+                            class="fill-icon"
                         />
                     </div>
                 </template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 6de43e86a..9c713e77e 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -1,12 +1,11 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import axios from 'axios';
 import FetchData from 'components/FetchData.vue';
 import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
 import VnSelect from 'components/common/VnSelect.vue';
-import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
 
@@ -48,6 +47,15 @@ const orderWayList = ref([
 const orderBySelected = ref('relevancy DESC, name');
 const orderWaySelected = ref('ASC');
 
+const routeQuery = JSON.parse(route?.query.params ?? '{}');
+const params = ref({});
+
+onMounted(() => {
+    const filter = routeQuery.filter;
+    params.value = JSON.parse(filter ?? '{}')?.where ?? {};
+    if (Object.keys(params.value).length > 0) vnFilterPanelRef.value.search();
+});
+
 const createValue = (val, done) => {
     if (val.length > 2) {
         if (!tagOptions.value.includes(val)) {
@@ -61,19 +69,15 @@ const resetCategory = () => {
     typeList.value = null;
 };
 
-const clearFilter = (key) => {
-    if (key === 'categoryFk') {
+const selectCategory = (category, search) => {
+    if (!params.value?.filter) params.value.filter = { where: {} };
+    const where = params.value.filter.where;
+    if (where.categoryFk === category?.id) {
         resetCategory();
-    }
-};
-
-const selectCategory = (params, category, search) => {
-    if (params.categoryFk === category?.id) {
-        resetCategory();
-        params.categoryFk = null;
+        where.categoryFk = null;
     } else {
         selectedCategoryFk.value = category?.id;
-        params.categoryFk = category?.id;
+        where.categoryFk = category?.id;
         loadTypes(category?.id);
     }
     search();
@@ -103,17 +107,6 @@ const selectedType = computed(() => {
     return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
 });
 
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'categoryFk':
-        case 'typeFk':
-            return { [param]: value };
-        case 'search':
-            if (/^\d+$/.test(value)) return { 'i.id': value };
-            else return { 'i.name': { like: `%${value}%` } };
-    }
-}
-
 const applyTagFilter = (params, search) => {
     if (!tagValues.value?.length) {
         params.tagGroups = null;
@@ -138,15 +131,6 @@ const applyTagFilter = (params, search) => {
     tagValues.value = [{}];
 };
 
-const removeTagChip = (selection, params, search) => {
-    if (params.tagGroups) {
-        params.tagGroups = (params.tagGroups || []).filter(
-            (value) => value !== selection
-        );
-    }
-    search();
-};
-
 const setCategoryList = (data) => {
     categoryList.value = (data || [])
         .filter((category) => category.display)
@@ -178,12 +162,11 @@ function addOrder(value, field, params) {
     <VnFilterPanel
         ref="vnFilterPanelRef"
         :data-key="props.dataKey"
-        :hidden-tags="['orderFk', 'orderBy']"
-        :un-removable-params="['orderFk', 'orderBy']"
-        :expr-builder="exprBuilder"
-        :custom-tags="['tagGroups']"
-        @remove="clearFilter"
+        v-model="params"
         :redirect="false"
+        :hidden-tags="['orderFk', 'orderBy', 'filter', 'search', 'or', 'and']"
+        :un-removable-params="['orderFk', 'orderBy']"
+        :disable-submit-event="true"
     >
         <template #tags="{ tag, formatFn }">
             <strong v-if="tag.label === 'categoryFk'">
@@ -192,30 +175,17 @@ function addOrder(value, field, params) {
             <strong v-else-if="tag.label === 'typeFk'">
                 {{ t(selectedType?.name || '') }}
             </strong>
+            <div v-else-if="tag.label === 'tagGroups'" class="q-gutter-x-xs">
+                <strong v-if="JSON.parse(tag.value).tagSelection.name"
+                    >{{ JSON.parse(tag.value).tagSelection?.name }}:
+                </strong>
+                <span>{{ JSON.parse(tag.value).values[0].value }}</span>
+            </div>
             <div v-else class="q-gutter-x-xs">
                 <strong>{{ t(`params.${tag.label}`) }}: </strong>
                 <span>{{ formatFn(tag.value) }}</span>
             </div>
         </template>
-        <template #customTags="{ tags: customTags, params, searchFn }">
-            <template v-for="tag in customTags" :key="tag.label">
-                <template v-if="tag.label === 'tagGroups'">
-                    <VnFilterPanelChip
-                        v-for="chip in tag.value"
-                        :key="chip"
-                        removable
-                        @remove="removeTagChip(chip, params, searchFn)"
-                    >
-                        <strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
-                        <span>{{
-                            (JSON.parse(chip).values || [])
-                                .map((item) => item.value)
-                                .join(' | ')
-                        }}</span>
-                    </VnFilterPanelChip>
-                </template>
-            </template>
-        </template>
         <template #body="{ params, searchFn }">
             <QItem class="category-filter q-mt-md">
                 <div
@@ -226,7 +196,7 @@ function addOrder(value, field, params) {
                     <QIcon
                         :name="category.icon"
                         class="category-icon"
-                        @click="selectCategory(params, category, searchFn)"
+                        @click="selectCategory(category, searchFn)"
                     >
                         <QTooltip>
                             {{ t(category.name) }}
@@ -320,7 +290,7 @@ function addOrder(value, field, params) {
             >
                 <FetchData
                     v-if="selectedTag"
-                    :url="`Tags/${selectedTag}/filterValue`"
+                    :url="`Tags/${selectedTag.id}/filterValue`"
                     limit="30"
                     auto-load
                     @on-fetch="(data) => (tagOptions = data)"
@@ -343,7 +313,7 @@ function addOrder(value, field, params) {
                     @update:model-value="applyTagFilter(params, searchFn)"
                 />
                 <VnSelect
-                    v-else-if="selectedTag === 1"
+                    v-else-if="selectedTag.id === 1"
                     :label="t('params.value')"
                     v-model="value.value"
                     :options="tagOptions || []"
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index a035971b0..74c8d8bed 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -71,10 +71,6 @@ const getConfirmationValue = (isConfirmed) => {
 };
 
 const total = ref(null);
-
-function ticketFilter(order) {
-    return JSON.stringify({ id: order.id });
-}
 </script>
 
 <template>
@@ -126,7 +122,11 @@ function ticketFilter(order) {
                     color="primary"
                     :to="{
                         name: 'TicketList',
-                        query: { table: ticketFilter(entity) },
+                        query: {
+                            table: JSON.stringify({
+                                orderFk: entity.id,
+                            }),
+                        },
                     }"
                 >
                     <QTooltip>{{ t('order.summary.orderTicketList') }}</QTooltip>
diff --git a/src/pages/Order/Card/OrderDescriptorMenu.vue b/src/pages/Order/Card/OrderDescriptorMenu.vue
index 2695da4e5..461efa22f 100644
--- a/src/pages/Order/Card/OrderDescriptorMenu.vue
+++ b/src/pages/Order/Card/OrderDescriptorMenu.vue
@@ -23,8 +23,8 @@ function confirmRemove() {
         .dialog({
             component: VnConfirm,
             componentProps: {
-                title: t('globals.confirmDeletion'),
-                message: t('confirmDeletionMessage'),
+                title: t('You are going to delete this order'),
+                message: t('Continue anyway?'),
                 promise: remove,
             },
         })
@@ -57,5 +57,6 @@ en:
 es:
     deleteOrder: Eliminar pedido
     confirmDeletionMessage: Seguro que quieres eliminar este pedido?
-
+    You are going to delete this order: El pedido se eliminará
+    Continue anyway?: ¿Continuar de todos modos?
 </i18n>
diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index 175c956e1..0d00e04ed 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -168,7 +168,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('Delete'),
+                title: t('Remove item'),
                 icon: 'delete',
                 show: (row) => !row.order.isConfirmed,
                 action: (row) => confirmRemove(row),
@@ -397,4 +397,5 @@ es:
     confirmDeletion: Confirmar eliminación,
     confirmDeletionMessage: Seguro que quieres eliminar este artículo?
     confirm: Confirmar
+    Remove item: Eliminar artículo
 </i18n>
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index 60358f744..9bc89ad28 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -2,7 +2,10 @@
 import { computed, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
+import { useQuasar } from 'quasar';
+import axios from 'axios';
 import { dashIfEmpty, toCurrency, toDateHourMinSec } from 'src/filters';
+import { useArrayData } from 'composables/useArrayData';
 import VnLv from 'components/ui/VnLv.vue';
 import CardSummary from 'components/ui/CardSummary.vue';
 import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
@@ -21,6 +24,9 @@ const $props = defineProps({
 });
 
 const entityId = computed(() => $props.id || route.params.id);
+const summary = ref();
+const quasar = useQuasar();
+const descriptorData = useArrayData('orderData');
 const detailsColumns = ref([
     {
         name: 'item',
@@ -49,6 +55,16 @@ const detailsColumns = ref([
         field: (row) => toCurrency(row?.quantity * row?.price),
     },
 ]);
+
+async function confirmOrder() {
+    await axios.post(`Orders/${route.params.id}/confirm`);
+    quasar.notify({
+        message: t('globals.confirm'),
+        type: 'positive',
+    });
+    summary.value.fetch({});
+    descriptorData.fetch({});
+}
 </script>
 
 <template>
@@ -62,6 +78,17 @@ const detailsColumns = ref([
                 {{ t('order.summary.basket') }} #{{ entity?.id }} -
                 {{ entity?.client?.name }} ({{ entity?.clientFk }})
             </template>
+            <template #header-right>
+                <QBtn
+                    flat
+                    text-color="white"
+                    :disabled="isConfirmed"
+                    :label="t('order.summary.confirm')"
+                    @click="confirmOrder()"
+                >
+                    <QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
+                </QBtn>
+            </template>
             <template #body="{ entity }">
                 <QCard class="vn-one">
                     <VnTitle

From d7210837959ca94189a78071a8145d5509af419d Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Thu, 10 Oct 2024 08:43:33 +0200
Subject: [PATCH 037/207] fix: filter panel

---
 src/components/ui/VnFilterPanel.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 242c4220d..f042c6481 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -221,7 +221,7 @@ function sanitizer(params) {
         icon="search"
         @click="search()"
     ></QBtn>
-    <QForm @submit="search(true)" id="filterPanelForm" @keyup.enter="search(true)">
+    <QForm @submit="search()" id="filterPanelForm" @keyup.enter="search(true)">
         <QList dense>
             <QItem class="q-mt-xs">
                 <QItemSection top>

From f16707756e99cd64e798e6190bf03845b82520a5 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 9 Oct 2024 00:40:21 +0200
Subject: [PATCH 038/207] fix: change type vnput

---
 src/pages/Ticket/Card/TicketCreateRequest.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/Ticket/Card/TicketCreateRequest.vue b/src/pages/Ticket/Card/TicketCreateRequest.vue
index ffe009516..d6e757afe 100644
--- a/src/pages/Ticket/Card/TicketCreateRequest.vue
+++ b/src/pages/Ticket/Card/TicketCreateRequest.vue
@@ -56,6 +56,7 @@ const attendersOptions = ref([]);
                     v-model="data.price"
                     :label="t('purchaseRequest.price')"
                     type="number"
+                    step="0.01"
                     min="0"
                 />
             </VnRow>

From 3d5d2673452f4aa1e584fa333f12bcfc83e1f52f Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 10 Oct 2024 09:29:12 +0200
Subject: [PATCH 039/207] revert: commit

---
 src/components/ui/VnFilterPanel.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index f042c6481..66e9df5f5 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -221,7 +221,7 @@ function sanitizer(params) {
         icon="search"
         @click="search()"
     ></QBtn>
-    <QForm @submit="search()" id="filterPanelForm" @keyup.enter="search(true)">
+    <QForm @submit="search" id="filterPanelForm" @keyup.enter.prevent="search(true)">
         <QList dense>
             <QItem class="q-mt-xs">
                 <QItemSection top>

From 787ce2fc48d28728fcc27aa1df73705d02508188 Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Mon, 14 Oct 2024 09:33:00 +0200
Subject: [PATCH 040/207] feat: refs #7006 itemTypeLog added

---
 src/pages/ItemType/Card/ItemTypeBasicData.vue |  1 +
 src/pages/ItemType/Card/ItemTypeLog.vue       |  7 +++++++
 src/pages/ItemType/locale/en.yml              |  1 +
 src/pages/ItemType/locale/es.yml              |  1 +
 src/router/modules/itemType.js                | 11 ++++++++++-
 5 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 src/pages/ItemType/Card/ItemTypeLog.vue

diff --git a/src/pages/ItemType/Card/ItemTypeBasicData.vue b/src/pages/ItemType/Card/ItemTypeBasicData.vue
index 51e24272d..deaf4a5fe 100644
--- a/src/pages/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/ItemType/Card/ItemTypeBasicData.vue
@@ -73,6 +73,7 @@ const temperaturesOptions = ref([]);
                     option-label="name"
                     hide-selected
                 />
+                <VnInput v-model="data.life" :label="t('shared.life')" />
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/ItemType/Card/ItemTypeLog.vue b/src/pages/ItemType/Card/ItemTypeLog.vue
new file mode 100644
index 000000000..b3f7a6597
--- /dev/null
+++ b/src/pages/ItemType/Card/ItemTypeLog.vue
@@ -0,0 +1,7 @@
+<script setup>
+import VnLog from 'src/components/common/VnLog.vue';
+</script>
+
+<template>
+    <VnLog model="ItemType" url="/ItemTypeLogs"></VnLog>
+</template>
diff --git a/src/pages/ItemType/locale/en.yml b/src/pages/ItemType/locale/en.yml
index 7889418ea..4b203bd68 100644
--- a/src/pages/ItemType/locale/en.yml
+++ b/src/pages/ItemType/locale/en.yml
@@ -4,6 +4,7 @@ shared:
     worker: Worker
     category: Category
     temperature: Temperature
+    life: Life
 summary:
     id: id
     life: Life
diff --git a/src/pages/ItemType/locale/es.yml b/src/pages/ItemType/locale/es.yml
index 9a94dceb6..43699c332 100644
--- a/src/pages/ItemType/locale/es.yml
+++ b/src/pages/ItemType/locale/es.yml
@@ -4,6 +4,7 @@ shared:
     worker: Trabajador
     category: Reino
     temperature: Temperatura
+    life: Vida
 summary:
     id: id
     code: Código
diff --git a/src/router/modules/itemType.js b/src/router/modules/itemType.js
index 8064c41ff..0fd3797e6 100644
--- a/src/router/modules/itemType.js
+++ b/src/router/modules/itemType.js
@@ -12,7 +12,7 @@ export default {
     redirect: { name: 'ItemTypeList' },
     menus: {
         main: [],
-        card: ['ItemTypeBasicData'],
+        card: ['ItemTypeBasicData', 'ItemTypeLog'],
     },
     children: [
         {
@@ -40,6 +40,15 @@ export default {
                     component: () =>
                         import('src/pages/ItemType/Card/ItemTypeBasicData.vue'),
                 },
+                {
+                    path: 'log',
+                    name: 'ItemTypeLog',
+                    meta: {
+                        title: 'log',
+                        icon: 'vn:History',
+                    },
+                    component: () => import('src/pages/ItemType/Card/ItemTypeLog.vue'),
+                },
             ],
         },
     ],

From f2cb0111eb6a5ceb1232da91f5190b5610c2e81d Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 16 Oct 2024 14:45:33 +0200
Subject: [PATCH 041/207] fix: refs #7283 fix image

---
 src/pages/Item/ItemList.vue | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index ad2c2e238..6c7b7eaed 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -1,10 +1,9 @@
 <script setup>
-import { ref, computed, onUnmounted } from 'vue';
+import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRouter, useRoute } from 'vue-router';
 import VnImg from 'src/components/ui/VnImg.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
-import { useStateStore } from 'stores/useStateStore';
 import { toDate } from 'src/filters';
 import axios from 'axios';
 import FetchedTags from 'src/components/ui/FetchedTags.vue';
@@ -16,7 +15,6 @@ const entityId = computed(() => route.params.id);
 
 const { viewSummary } = useSummaryDialog();
 const router = useRouter();
-const stateStore = useStateStore();
 const { t } = useI18n();
 const tableRef = ref();
 const route = useRoute();
@@ -53,8 +51,8 @@ const columns = computed(() => [
             attrs: ({ row }) => {
                 return {
                     id: row?.id,
-                    width: '50px',
                     zoomResolution: '1600x900',
+                    zoom: true,
                 };
             },
         },
@@ -116,9 +114,13 @@ const columns = computed(() => [
     },
     {
         label: t('item.list.typeName'),
-        name: 'typeName',
+        name: 'typeFk',
         align: 'left',
         component: 'select',
+        attrs: {
+            url: 'ItemTypes',
+            fields: ['id', 'name'],
+        },
         columnFilter: {
             name: 'typeFk',
             attrs: {
@@ -152,6 +154,11 @@ const columns = computed(() => [
         name: 'intrastat',
         align: 'left',
         component: 'select',
+        attrs: {
+            url: 'Intrastats',
+            optionValue: 'description',
+            optionLabel: 'description',
+        },
         columnFilter: {
             name: 'description',
             attrs: {
@@ -159,7 +166,6 @@ const columns = computed(() => [
                 optionValue: 'description',
                 optionLabel: 'description',
             },
-            inWhere: true,
             alias: 'intr',
         },
         columnField: {
@@ -172,6 +178,11 @@ const columns = computed(() => [
         name: 'origin',
         align: 'left',
         component: 'select',
+        attrs: {
+            url: 'Origins',
+            optionValue: 'id',
+            optionLabel: 'code',
+        },
         columnFilter: {
             name: 'id',
             attrs: {

From 16ef5d372296ef2a5609ea319edb162c30337dc5 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 17 Oct 2024 08:30:45 +0200
Subject: [PATCH 042/207] fix: refs #7306 clean warning

---
 src/pages/Customer/Card/CustomerUnpaid.vue | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerUnpaid.vue b/src/pages/Customer/Card/CustomerUnpaid.vue
index ad00cbf59..6fa5b7f01 100644
--- a/src/pages/Customer/Card/CustomerUnpaid.vue
+++ b/src/pages/Customer/Card/CustomerUnpaid.vue
@@ -2,10 +2,9 @@
 import { computed, onBeforeMount, ref, watch, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
-
 import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-
+import VnRow from 'components/ui/VnRow.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify';
 import { useStateStore } from 'stores/useStateStore';

From 608e6c717ab6748238446eb8c06f700a09790a01 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 17 Oct 2024 09:34:48 +0200
Subject: [PATCH 043/207] fix: refs #7310 clean warning

---
 src/pages/Travel/Card/TravelThermographs.vue | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index 6d83581ee..e4a060889 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -19,7 +19,7 @@ const router = useRouter();
 const { t } = useI18n();
 const { notify } = useNotify();
 
-const thermographPaginateRef = ref(null);
+const thermographPaginateRef = ref();
 const warehouses = ref([]);
 
 const thermographFilter = {
@@ -137,7 +137,6 @@ const removeThermograph = async (id) => {
         data-key="TravelThermographs"
         url="TravelThermographs"
         :filter="thermographFilter"
-        :params="{ travelFk: id }"
         auto-load
     >
         <template #body="{ rows }">

From 58e88f605c8f4138c835c13c671eec195e65b1bd Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 18 Oct 2024 08:04:52 +0200
Subject: [PATCH 044/207] refactor: refs #7132 delete duplicate translations'
 keys

---
 .../InvoiceIn/Card/InvoiceInDescriptor.vue    |  6 +-
 src/pages/InvoiceIn/Card/InvoiceInSummary.vue | 10 +--
 src/pages/InvoiceIn/InvoiceInCreate.vue       |  2 +-
 src/pages/InvoiceIn/InvoiceInList.vue         |  4 +-
 src/pages/InvoiceIn/locale/en.yml             |  7 --
 src/pages/InvoiceIn/locale/es.yml             |  6 --
 src/pages/InvoiceOut/locale/es.yml            | 21 +++---
 src/pages/Item/Card/CreateIntrastatForm.vue   |  2 +-
 src/pages/Item/Card/ItemDiary.vue             |  2 +-
 src/pages/Item/Card/ItemLastEntries.vue       |  8 +--
 src/pages/Item/Card/ItemTags.vue              |  2 +-
 src/pages/Item/locale/en.yml                  |  7 --
 src/pages/Item/locale/es.yml                  |  7 --
 src/pages/ItemType/locale/es.yml              |  5 --
 src/pages/Monitor/MonitorOrders.vue           |  4 +-
 src/pages/Monitor/Ticket/MonitorTickets.vue   |  6 +-
 src/pages/Monitor/locale/en.yml               |  5 --
 src/pages/Monitor/locale/es.yml               |  5 --
 .../Card/BasicData/TicketBasicDataForm.vue    | 18 ++---
 src/pages/Ticket/Card/ExpeditionNewTicket.vue |  2 +-
 src/pages/Ticket/Card/TicketComponents.vue    | 24 +++----
 src/pages/Ticket/Card/TicketCreateRequest.vue |  9 +--
 .../Ticket/Card/TicketCreateServiceType.vue   |  2 +-
 .../Ticket/Card/TicketCreateTracking.vue      |  4 +-
 src/pages/Ticket/Card/TicketExpedition.vue    |  6 +-
 src/pages/Ticket/Card/TicketNotes.vue         |  2 +-
 src/pages/Ticket/Card/TicketPackage.vue       |  2 +-
 .../Ticket/Card/TicketPurchaseRequest.vue     | 21 +++---
 src/pages/Ticket/Card/TicketSale.vue          | 16 ++---
 src/pages/Ticket/Card/TicketSaleTracking.vue  | 20 +++---
 src/pages/Ticket/Card/TicketService.vue       |  6 +-
 src/pages/Ticket/Card/TicketTracking.vue      |  6 +-
 src/pages/Ticket/Card/TicketTransfer.vue      | 14 ++--
 src/pages/Ticket/Card/TicketVolume.vue        |  6 +-
 src/pages/Ticket/TicketAdvance.vue            |  2 +-
 src/pages/Ticket/TicketFuture.vue             | 24 +++----
 src/pages/Ticket/TicketWeekly.vue             |  6 +-
 src/pages/Ticket/locale/en.yml                | 65 -------------------
 src/pages/Ticket/locale/es.yml                | 64 ------------------
 src/pages/Zone/Card/ZoneCreateWarehouse.vue   |  2 +-
 src/pages/Zone/Card/ZoneDescriptor.vue        | 10 +--
 .../Zone/Card/ZoneEventExclusionForm.vue      |  4 +-
 .../Zone/Card/ZoneEventInclusionForm.vue      | 16 ++---
 src/pages/Zone/Card/ZoneEventsPanel.vue       | 14 ++--
 src/pages/Zone/Card/ZoneLocations.vue         |  2 +-
 src/pages/Zone/Card/ZoneSummary.vue           | 14 ++--
 src/pages/Zone/Card/ZoneWarehouses.vue        |  6 +-
 src/pages/Zone/ZoneClosingTable.vue           | 12 ++--
 src/pages/Zone/ZoneCreate.vue                 | 14 ++--
 src/pages/Zone/ZoneDeliveryPanel.vue          |  4 +-
 src/pages/Zone/ZoneFilterPanel.vue            |  6 +-
 src/pages/Zone/ZoneList.vue                   |  4 +-
 src/pages/Zone/ZoneUpcoming.vue               |  4 +-
 src/pages/Zone/locale/en.yml                  | 50 ++------------
 src/pages/Zone/locale/es.yml                  | 53 ++-------------
 55 files changed, 189 insertions(+), 454 deletions(-)

diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index 9bc4856a8..92f3fffca 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -355,10 +355,10 @@ const createInvoiceInCorrection = async () => {
             </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('invoiceIn.card.issued')" :value="toDate(entity.issued)" />
+            <VnLv :label="t('invoiceIn.list.issued')" :value="toDate(entity.issued)" />
             <VnLv :label="t('invoiceIn.summary.booked')" :value="toDate(entity.booked)" />
-            <VnLv :label="t('invoiceIn.card.amount')" :value="toCurrency(totalAmount)" />
-            <VnLv :label="t('invoiceIn.summary.supplier')">
+            <VnLv :label="t('invoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
+            <VnLv :label="t('invoiceIn.list.supplier')">
                 <template #value>
                     <span class="link">
                         {{ entity?.supplier?.nickname }}
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index 801a04342..08fc11f69 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -95,7 +95,7 @@ const dueDayColumns = ref([
     },
     {
         name: 'amount',
-        label: 'invoiceIn.summary.amount',
+        label: 'invoiceIn.list.amount',
         field: (row) => row.amount,
         format: (value) => toCurrency(value),
         sortable: true,
@@ -123,7 +123,7 @@ const intrastatColumns = ref([
     },
     {
         name: 'amount',
-        label: 'invoiceIn.summary.amount',
+        label: 'invoiceIn.list.amount',
         field: (row) => toCurrency(row.amount),
         sortable: true,
         align: 'left',
@@ -210,7 +210,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     />
                 </QCardSection>
                 <VnLv
-                    :label="t('invoiceIn.summary.supplier')"
+                    :label="t('invoiceIn.list.supplier')"
                     :value="entity.supplier?.name"
                 >
                     <template #value>
@@ -221,7 +221,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     </template>
                 </VnLv>
                 <VnLv
-                    :label="t('invoiceIn.summary.supplierRef')"
+                    :label="t('invoiceIn.list.supplierRef')"
                     :value="entity.supplierRef"
                 />
                 <VnLv
@@ -271,7 +271,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     :value="entity.expenseDeductible?.name"
                 />
                 <VnLv
-                    :label="t('invoiceIn.summary.company')"
+                    :label="t('invoiceIn.card.company')"
                     :value="entity.company?.code"
                 />
                 <VnLv :label="t('invoiceIn.isBooked')" :value="invoiceIn?.isBooked" />
diff --git a/src/pages/InvoiceIn/InvoiceInCreate.vue b/src/pages/InvoiceIn/InvoiceInCreate.vue
index e6863beb1..c809e032b 100644
--- a/src/pages/InvoiceIn/InvoiceInCreate.vue
+++ b/src/pages/InvoiceIn/InvoiceInCreate.vue
@@ -83,7 +83,7 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
                         </template>
                     </VnSelect>
                     <VnInput
-                        :label="t('invoiceIn.summary.supplierRef')"
+                        :label="t('invoiceIn.list.supplierRef')"
                         v-model="data.supplierRef"
                     />
                 </VnRow>
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index 265f95b0e..d64876858 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -50,7 +50,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'serial',
-        label: t('invoiceIn.list.serial'),
+        label: t('invoiceIn.serial'),
     },
     {
         align: 'left',
@@ -151,7 +151,7 @@ const cols = computed(() => [
                 </template>
             </VnSelect>
             <VnInput
-                :label="t('invoiceIn.summary.supplierRef')"
+                :label="t('invoiceIn.list.supplierRef')"
                 v-model="data.supplierRef"
             />
             <VnSelect
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index b09340c81..b39511f29 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -5,14 +5,11 @@ invoiceIn:
         ref: Reference
         supplier: Supplier
         supplierRef: Supplier ref.
-        serial: Serial
         file: File
         issued: Issued
         awb: AWB
         amount: Amount
     card:
-        issued: Issued
-        amount: Amount
         client: Client
         company: Company
         customerCard: Customer card
@@ -21,8 +18,6 @@ invoiceIn:
         dueDay: Due day
         intrastat: Intrastat
     summary:
-        supplier: Supplier
-        supplierRef: Supplier ref.
         currency: Currency
         issued: Expedition date
         operated: Operation date
@@ -30,7 +25,6 @@ invoiceIn:
         bookedDate: Booked date
         sage: Sage withholding
         vat: Undeductible VAT
-        company: Company
         expense: Expense
         taxableBase: Taxable base
         rate: Rate
@@ -38,7 +32,6 @@ invoiceIn:
         sageTransaction: Sage transaction
         dueDay: Date
         bank: Bank
-        amount: Amount
         foreignValue: Foreign value
         dueTotal: Due day
         noMatch: Do not match
diff --git a/src/pages/InvoiceIn/locale/es.yml b/src/pages/InvoiceIn/locale/es.yml
index 31d41fc97..5f483dd08 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -11,8 +11,6 @@ invoiceIn:
         awb: AWB
         amount: Importe
     card:
-        issued: Fecha emisión
-        amount: Importe
         client: Cliente
         company: Empresa
         customerCard: Ficha del cliente
@@ -20,8 +18,6 @@ invoiceIn:
         vat: Iva
         dueDay: Fecha de vencimiento
     summary:
-        supplier: Proveedor
-        supplierRef: Ref. proveedor
         currency: Divisa
         docNumber: Número documento
         issued: Fecha de expedición
@@ -30,14 +26,12 @@ invoiceIn:
         bookedDate: Fecha contable
         sage: Retención sage
         vat: Iva no deducible
-        company: Empresa
         expense: Gasto
         taxableBase: Base imp.
         rate: Tasa
         sageTransaction: Sage transación
         dueDay: Fecha
         bank: Caja
-        amount: Importe
         foreignValue: Divisa
         dueTotal: Vencimiento
         code: Código
diff --git a/src/pages/InvoiceOut/locale/es.yml b/src/pages/InvoiceOut/locale/es.yml
index a05125630..192f5b26f 100644
--- a/src/pages/InvoiceOut/locale/es.yml
+++ b/src/pages/InvoiceOut/locale/es.yml
@@ -9,9 +9,6 @@ invoiceOutList:
         id: ID
         ref: Referencia
         issued: Fecha emisión
-        customer: Cliente
-        company: Empresa
-        amount: Importe
         created: F. creación
         dueDate: F. máxima
         invoiceOutSerial: Serial
@@ -20,12 +17,12 @@ invoiceOutList:
 DownloadPdf: Descargar PDF
 InvoiceOutSummary: Resumen
 negativeBases:
-        country: País
-        clientId: ID del cliente
-        client: Cliente
-        base: Base
-        ticketId: Ticket
-        active: Activo
-        hasToInvoice: Debe facturar
-        verifiedData: Datos verificados
-        commercial: Comercial
\ No newline at end of file
+    country: País
+    clientId: ID del cliente
+    client: Cliente
+    base: Base
+    ticketId: Ticket
+    active: Activo
+    hasToInvoice: Debe facturar
+    verifiedData: Datos verificados
+    commercial: Comercial
diff --git a/src/pages/Item/Card/CreateIntrastatForm.vue b/src/pages/Item/Card/CreateIntrastatForm.vue
index 5fe254759..443615d7e 100644
--- a/src/pages/Item/Card/CreateIntrastatForm.vue
+++ b/src/pages/Item/Card/CreateIntrastatForm.vue
@@ -42,7 +42,7 @@ onMounted(async () => {
                     :required="true"
                 />
                 <VnInput
-                    :label="t('createIntrastatForm.description')"
+                    :label="t('itemBasicData.description')"
                     v-model="data.description"
                     :required="true"
                 />
diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index 68633caa2..a59bfa367 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -62,7 +62,7 @@ const columns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('itemDiary.reference'),
+        label: t('itemBasicData.reference'),
         field: 'reference',
         name: 'reference',
         align: 'left',
diff --git a/src/pages/Item/Card/ItemLastEntries.vue b/src/pages/Item/Card/ItemLastEntries.vue
index b211790ca..5c0251ea8 100644
--- a/src/pages/Item/Card/ItemLastEntries.vue
+++ b/src/pages/Item/Card/ItemLastEntries.vue
@@ -59,7 +59,7 @@ const columns = computed(() => [
         align: 'center',
     },
     {
-        label: t('lastEntries.warehouse'),
+        label: t('itemDiary.warehouse'),
         name: 'warehouse',
         field: 'warehouse',
         align: 'left',
@@ -94,7 +94,7 @@ const columns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('lastEntries.packing'),
+        label: t('shelvings.packing'),
         name: 'packing',
         align: 'center',
     },
@@ -104,7 +104,7 @@ const columns = computed(() => [
         align: 'center',
     },
     {
-        label: t('lastEntries.stems'),
+        label: t('itemBasicData.stems'),
         name: 'stems',
         field: 'stems',
         align: 'center',
@@ -188,7 +188,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
     <VnSubToolbar>
         <template #st-data>
             <VnInputDate
-                :label="t('lastEntries.since')"
+                :label="t('itemDiary.since')"
                 dense
                 v-model="from"
                 class="q-mr-lg"
diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index 6f31d0cf8..de34cb9fe 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -147,7 +147,7 @@ const insertTag = (rows) => {
                                 :is-clearable="false"
                             />
                             <VnInput
-                                :label="t('itemTags.relevancy')"
+                                :label="t('itemBasicData.relevancy')"
                                 type="number"
                                 v-model="row.priority"
                                 :required="true"
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index c32ee493c..647a01810 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -16,7 +16,6 @@ itemDiary:
     date: Date
     origin: Origin
     state: State
-    reference: Reference
     entity: Entity
     in: In
     out: Out
@@ -48,22 +47,17 @@ itemBasicData:
 createIntrastatForm:
     title: New intrastat
     identifier: Identifier
-    description: Description
 tax:
     country: Country
     class: Class
 lastEntries:
-    since: Since
     to: To
     ig: Ig
-    warehouse: Warehouse
     landed: Landed
     entry: Entry
     pvp: PVP
     label: Label
-    packing: Packing
     grouping: Grouping
-    stems: Stems
     quantity: Quantity
     cost: Cost
     kg: Kg.
@@ -77,7 +71,6 @@ itemTags:
     addTag: Add tag
     tag: Tag
     value: Value
-    relevancy: Relevancy
 searchbar:
     label: Search item
     info: Search by item id
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index d32cb7885..80eab8f26 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -16,7 +16,6 @@ itemDiary:
     date: Fecha
     origin: Origen
     state: Estado
-    reference: Referencia
     entity: Entidad
     in: Entrada
     out: Salida
@@ -48,22 +47,17 @@ itemBasicData:
 createIntrastatForm:
     title: Nuevo intrastat
     identifier: Identificador
-    description: Descripción
 tax:
     country: País
     class: Clase
 lastEntries:
-    since: Desde
     to: Hasta
     ig: Ig
-    warehouse: Almacén
     landed: F. Entrega
     entry: Entrada
     pvp: PVP
     label: Etiquetas
-    packing: Packing
     grouping: Grouping
-    stems: Tallos
     quantity: Cantidad
     cost: Coste
     kg: Kg.
@@ -77,7 +71,6 @@ itemTags:
     addTag: Añadir etiqueta
     tag: Etiqueta
     value: Valor
-    relevancy: Relevancia
 searchbar:
     label: Buscar artículo
     info: Buscar por id de artículo
diff --git a/src/pages/ItemType/locale/es.yml b/src/pages/ItemType/locale/es.yml
index 9a94dceb6..5a32d09a5 100644
--- a/src/pages/ItemType/locale/es.yml
+++ b/src/pages/ItemType/locale/es.yml
@@ -6,11 +6,6 @@ shared:
     temperature: Temperatura
 summary:
     id: id
-    code: Código
-    name: Nombre
-    worker: Trabajador
-    category: Reino
-    temperature: Temperatura
     life: Vida
     promo: Promoción
     itemPackingType: Tipo de embalaje
diff --git a/src/pages/Monitor/MonitorOrders.vue b/src/pages/Monitor/MonitorOrders.vue
index fac601735..326fae0ee 100644
--- a/src/pages/Monitor/MonitorOrders.vue
+++ b/src/pages/Monitor/MonitorOrders.vue
@@ -44,7 +44,7 @@ const columns = computed(() => [
         format: (row) => toDateTimeFormat(row.date_make),
     },
     {
-        label: t('salesOrdersTable.client'),
+        label: t('salesClientsTable.client'),
         name: 'clientFk',
         align: 'left',
         columnFilter: {
@@ -63,7 +63,7 @@ const columns = computed(() => [
         columnFilter: false,
     },
     {
-        label: t('salesOrdersTable.salesPerson'),
+        label: t('salesClientsTable.salesPerson'),
         name: 'salesPersonFk',
         align: 'left',
         optionFilter: 'firstName',
diff --git a/src/pages/Monitor/Ticket/MonitorTickets.vue b/src/pages/Monitor/Ticket/MonitorTickets.vue
index d24230c64..406bf5f29 100644
--- a/src/pages/Monitor/Ticket/MonitorTickets.vue
+++ b/src/pages/Monitor/Ticket/MonitorTickets.vue
@@ -77,7 +77,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('salesTicketsTable.client'),
+        label: t('salesClientsTable.client'),
         name: 'clientFk',
         align: 'left',
         field: 'nickname',
@@ -91,7 +91,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('salesTicketsTable.salesPerson'),
+        label: t('salesClientsTable.salesPerson'),
         name: 'salesPersonFk',
         field: 'userName',
         align: 'left',
@@ -108,7 +108,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('salesTicketsTable.date'),
+        label: t('salesClientsTable.date'),
         name: 'shippedDate',
         align: 'left',
         columnFilter: {
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index b8082f02a..2f839e5f5 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -13,8 +13,6 @@ salesOrdersTable:
     delete: Delete
     dateSend: Send date
     dateMake: Make date
-    client: Client
-    salesPerson: Salesperson
     deleteConfirmMessage: All the selected elements will be deleted. Are you sure you want to continue?
     agency: Agency
     import: Import
@@ -29,9 +27,6 @@ salesTicketsTable:
     componentLack: Component lack
     tooLittle: Ticket too little
     identifier: Identifier
-    client: Client
-    salesPerson: Salesperson
-    date: Date
     theoretical: Theoretical
     practical: Practical
     province: Province
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index 4ee5b90a9..5b7f4f551 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -13,8 +13,6 @@ salesOrdersTable:
     delete: Eliminar
     dateSend: Fecha de envío
     dateMake: Fecha de realización
-    client: Cliente
-    salesPerson: Comercial
     deleteConfirmMessage: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
     agency: Agencia
     import: Importe
@@ -29,9 +27,6 @@ salesTicketsTable:
     componentLack: Faltan componentes
     tooLittle: Ticket demasiado pequeño
     identifier: Identificador
-    client: Cliente
-    salesPerson: Comercial
-    date: Fecha
     theoretical: Teórica
     practical: Práctica
     province: Provincia
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index fdc75abda..90c579c4c 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -297,7 +297,7 @@ onMounted(() => onFormModelInit());
     <QForm>
         <VnRow>
             <VnSelect
-                :label="t('basicData.client')"
+                :label="t('ticketList.client')"
                 v-model="clientId"
                 option-value="id"
                 option-label="name"
@@ -320,7 +320,7 @@ onMounted(() => onFormModelInit());
                 </template>
             </VnSelect>
             <VnSelect
-                :label="t('basicData.warehouse')"
+                :label="t('ticketList.warehouse')"
                 v-model="warehouseId"
                 option-value="id"
                 option-label="name"
@@ -328,7 +328,7 @@ onMounted(() => onFormModelInit());
                 hide-selected
                 map-options
                 :required="true"
-                :rules="validate('basicData.warehouse')"
+                :rules="validate('ticketList.warehouse')"
             />
         </VnRow>
         <VnRow>
@@ -394,7 +394,7 @@ onMounted(() => onFormModelInit());
         </VnRow>
         <VnRow class="row q-gutter-md q-mb-md no-wrap">
             <VnSelect
-                :label="t('basicData.company')"
+                :label="t('ticketList.company')"
                 v-model="formData.companyFk"
                 option-value="id"
                 option-label="code"
@@ -402,7 +402,7 @@ onMounted(() => onFormModelInit());
                 hide-selected
                 map-options
                 :required="true"
-                :rules="validate('basicData.company')"
+                :rules="validate('ticketList.company')"
             />
             <VnSelect
                 :label="t('basicData.agency')"
@@ -416,7 +416,7 @@ onMounted(() => onFormModelInit());
                 :rules="validate('basicData.agency')"
             />
             <VnSelect
-                :label="t('basicData.zone')"
+                :label="t('ticketList.zone')"
                 v-model="zoneId"
                 option-value="id"
                 option-label="name"
@@ -428,7 +428,7 @@ onMounted(() => onFormModelInit());
                 map-options
                 :required="true"
                 @focus="zonesFetchRef.fetch()"
-                :rules="validate('basicData.zone')"
+                :rules="validate('ticketList.zone')"
             >
                 <template #option="scope">
                     <QItem v-bind="scope.itemProps">
@@ -445,10 +445,10 @@ onMounted(() => onFormModelInit());
         </VnRow>
         <VnRow>
             <VnInputDate
-                :label="t('basicData.shipped')"
+                :label="t('ticketList.shipped')"
                 v-model="formData.shipped"
                 :required="true"
-                :rules="validate('basicData.shipped')"
+                :rules="validate('ticketList.shipped')"
             />
             <VnInputTime
                 :label="t('basicData.shippedHour')"
diff --git a/src/pages/Ticket/Card/ExpeditionNewTicket.vue b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
index 9183ae405..4a6ca966d 100644
--- a/src/pages/Ticket/Card/ExpeditionNewTicket.vue
+++ b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
@@ -66,7 +66,7 @@ const createTicket = async () => {
         <template #form-inputs="{ data }">
             <VnRow>
                 <VnInputDate
-                    :label="t('expedition.landed')"
+                    :label="t('basicData.landed')"
                     v-model="data.landed"
                     :model-value="date"
                 />
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 0bccdaacd..a9573443b 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -72,7 +72,7 @@ const salesFilter = computed(() => ({
 
 const columns = computed(() => [
     {
-        label: t('ticketComponents.item'),
+        label: t('basicData.item'),
         name: 'item',
         align: 'left',
     },
@@ -92,13 +92,13 @@ const columns = computed(() => [
         columnFilter: false,
     },
     {
-        label: t('ticketComponents.description'),
+        label: t('basicData.description'),
         name: 'description',
         align: 'left',
         columnClass: 'expand',
     },
     {
-        label: t('ticketComponents.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         field: 'quantity',
         align: 'left',
@@ -116,12 +116,12 @@ const columns = computed(() => [
         align: 'left',
     },
     {
-        label: t('ticketComponents.import'),
+        label: t('advanceTickets.import'),
         name: 'import',
         align: 'left',
     },
     {
-        label: t('ticketComponents.total'),
+        label: t('basicData.total'),
         name: 'total',
         align: 'left',
     },
@@ -196,7 +196,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         <QCard class="q-pa-sm color-vn-text" bordered flat style="border-color: black">
             <QCardSection horizontal>
                 <span class="text-weight-bold text-subtitle1 text-center full-width">
-                    {{ t('ticketComponents.total') }}
+                    {{ t('basicData.total') }}
                 </span>
             </QCardSection>
             <QCardSection horizontal>
@@ -238,9 +238,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
                 </span>
             </QCardSection>
             <QCardSection horizontal>
-                <span class="q-mr-xs color-vn-label">
-                    {{ t('ticketComponents.price') }}:
-                </span>
+                <span class="q-mr-xs color-vn-label"> {{ t('basicData.price') }}: </span>
                 <span>{{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}</span>
             </QCardSection>
             <QCardSection horizontal>
@@ -250,18 +248,14 @@ onUnmounted(() => (stateStore.rightDrawer = false));
                 <span>{{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}</span>
             </QCardSection>
             <QCardSection horizontal>
-                <span class="q-mr-xs color-vn-label">
-                    {{ t('ticketComponents.zone') }}:
-                </span>
+                <span class="q-mr-xs color-vn-label"> {{ t('ticketList.zone') }}: </span>
                 <span class="link">
                     {{ dashIfEmpty(ticketData?.zone?.name) }}
                     <ZoneDescriptorProxy :id="ticketData?.zone?.id" />
                 </span>
             </QCardSection>
             <QCardSection v-if="ticketData?.zone?.isVolumetric" horizontal>
-                <span class="q-mr-xs color-vn-label">
-                    {{ t('ticketComponents.volume') }}:
-                </span>
+                <span class="q-mr-xs color-vn-label"> {{ t('volume.volume') }}: </span>
                 <span>{{ ticketVolume }}</span>
             </QCardSection>
             <QCardSection horizontal>
diff --git a/src/pages/Ticket/Card/TicketCreateRequest.vue b/src/pages/Ticket/Card/TicketCreateRequest.vue
index ffe009516..539780a6a 100644
--- a/src/pages/Ticket/Card/TicketCreateRequest.vue
+++ b/src/pages/Ticket/Card/TicketCreateRequest.vue
@@ -32,10 +32,7 @@ const attendersOptions = ref([]);
     >
         <template #form-inputs="{ data }">
             <VnRow>
-                <VnInput
-                    v-model="data.description"
-                    :label="t('purchaseRequest.description')"
-                />
+                <VnInput v-model="data.description" :label="t('basicData.description')" />
                 <VnSelect
                     :label="t('purchaseRequest.atender')"
                     v-model="data.attenderFk"
@@ -48,13 +45,13 @@ const attendersOptions = ref([]);
             <VnRow>
                 <VnInput
                     v-model="data.quantity"
-                    :label="t('purchaseRequest.quantity')"
+                    :label="t('basicData.quantity')"
                     type="number"
                     min="1"
                 />
                 <VnInput
                     v-model="data.price"
-                    :label="t('purchaseRequest.price')"
+                    :label="t('basicData.price')"
                     type="number"
                     min="0"
                 />
diff --git a/src/pages/Ticket/Card/TicketCreateServiceType.vue b/src/pages/Ticket/Card/TicketCreateServiceType.vue
index 067d7dee8..2f5857e86 100644
--- a/src/pages/Ticket/Card/TicketCreateServiceType.vue
+++ b/src/pages/Ticket/Card/TicketCreateServiceType.vue
@@ -34,7 +34,7 @@ onMounted(async () => {
             <VnRow>
                 <VnInput
                     ref="nameInputRef"
-                    :label="t('service.description')"
+                    :label="t('basicData.description')"
                     v-model="data.name"
                     :required="true"
                 />
diff --git a/src/pages/Ticket/Card/TicketCreateTracking.vue b/src/pages/Ticket/Card/TicketCreateTracking.vue
index d692f550d..3ea762c6c 100644
--- a/src/pages/Ticket/Card/TicketCreateTracking.vue
+++ b/src/pages/Ticket/Card/TicketCreateTracking.vue
@@ -39,7 +39,7 @@ const onStateFkChange = (formData) => (formData.userFk = user.value.id);
             <VnRow>
                 <VnSelect
                     v-model="data.stateFk"
-                    :label="t('tracking.state')"
+                    :label="t('ticketList.state')"
                     :options="statesOptions"
                     @update:model-value="onStateFkChange(data)"
                     hide-selected
@@ -47,7 +47,7 @@ const onStateFkChange = (formData) => (formData.userFk = user.value.id);
                     option-value="id"
                 />
                 <VnSelect
-                    :label="t('tracking.worker')"
+                    :label="t('expedition.worker')"
                     v-model="data.userFk"
                     url="Workers/search"
                     fields=" ['id', 'name']"
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index 4becb3db3..fc408272d 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -81,7 +81,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('expedition.item'),
+        label: t('basicData.item'),
         name: 'packagingItemFk',
         align: 'left',
         cardVisible: true,
@@ -131,7 +131,7 @@ const columns = computed(() => [
         format: (row) => toDateTimeFormat(row.created),
     },
     {
-        label: t('expedition.state'),
+        label: t('ticketList.state'),
         name: 'state',
         align: 'left',
         cardVisible: true,
@@ -153,7 +153,7 @@ const columns = computed(() => [
 
 const logTableColumns = computed(() => [
     {
-        label: t('expedition.state'),
+        label: t('ticketList.state'),
         name: 'state',
         field: 'state',
         align: 'center',
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index b5302d15f..12f7ba2c6 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -88,7 +88,7 @@ async function handleSave() {
                             :disable="!!row.id"
                         />
                         <VnInput
-                            :label="t('ticketNotes.description')"
+                            :label="t('basicData.description')"
                             v-model="row.description"
                             class="col"
                             @keyup.enter="handleSave"
diff --git a/src/pages/Ticket/Card/TicketPackage.vue b/src/pages/Ticket/Card/TicketPackage.vue
index c0418bcf6..04d6020f3 100644
--- a/src/pages/Ticket/Card/TicketPackage.vue
+++ b/src/pages/Ticket/Card/TicketPackage.vue
@@ -93,7 +93,7 @@ watch(
                             </template>
                         </VnSelect>
                         <VnInput
-                            :label="t('package.quantity')"
+                            :label="t('basicData.quantity')"
                             v-model.number="row.quantity"
                             class="col"
                             type="number"
diff --git a/src/pages/Ticket/Card/TicketPurchaseRequest.vue b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
index d0af9efd0..7715e9e21 100644
--- a/src/pages/Ticket/Card/TicketPurchaseRequest.vue
+++ b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
@@ -81,7 +81,7 @@ const crudModelFilter = reactive({
 const columns = computed(() => [
     {
         align: 'left',
-        label: t('purchaseRequest.id'),
+        label: t('ticketList.id'),
         name: 'id',
         chip: {
             condition: () => true,
@@ -90,13 +90,13 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('purchaseRequest.description'),
+        label: t('basicData.description'),
         name: 'description',
         columnClass: 'expand',
     },
     {
         align: 'left',
-        label: t('purchaseRequest.created'),
+        label: t('expedition.created'),
         name: 'created',
         format: (row) => toDateFormat(row.created),
         cardVisible: true,
@@ -117,12 +117,12 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('purchaseRequest.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
     },
     {
         align: 'left',
-        label: t('purchaseRequest.price'),
+        label: t('basicData.price'),
         name: 'price',
     },
     {
@@ -133,7 +133,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('purchaseRequest.state'),
+        label: t('ticketList.state'),
         name: 'isOk',
         cardVisible: true,
     },
@@ -248,10 +248,7 @@ onMounted(() => (stateStore.rightDrawer = false));
         </template>
 
         <template #more-create-dialog="{ data }">
-            <VnInput
-                v-model="data.description"
-                :label="t('purchaseRequest.description')"
-            />
+            <VnInput v-model="data.description" :label="t('basicData.description')" />
             <VnSelect
                 :label="t('purchaseRequest.atender')"
                 v-model="data.attenderFk"
@@ -262,13 +259,13 @@ onMounted(() => (stateStore.rightDrawer = false));
             />
             <VnInput
                 v-model="data.quantity"
-                :label="t('purchaseRequest.quantity')"
+                :label="t('basicData.quantity')"
                 type="number"
                 min="1"
             />
             <VnInput
                 v-model="data.price"
-                :label="t('purchaseRequest.price')"
+                :label="t('basicData.price')"
                 type="number"
                 min="0"
             />
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 43af8d528..d49007e9d 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -90,25 +90,25 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('ticketSale.id'),
+        label: t('ticketList.id'),
         name: 'itemFk',
     },
     {
         align: 'left',
-        label: t('ticketSale.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         format: (row) => toCurrency(row.quantity),
     },
     {
         align: 'left',
-        label: t('ticketSale.item'),
+        label: t('basicData.item'),
         name: 'item',
         format: (row) => row?.item?.name,
         columnClass: 'expand',
     },
     {
         align: 'left',
-        label: t('ticketSale.price'),
+        label: t('basicData.price'),
         name: 'price',
         format: (row) => toCurrency(row.price),
     },
@@ -120,7 +120,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('ticketSale.amount'),
+        label: t('ticketList.amount'),
         name: 'amount',
         format: (row) => parseInt(row.amount * row.quantity),
     },
@@ -516,7 +516,7 @@ watch(
                 <QBtnDropdown
                     ref="stateBtnDropdownRef"
                     color="primary"
-                    :label="t('ticketSale.state')"
+                    :label="t('ticketList.state')"
                     :disable="!isTicketEditable"
                 >
                     <VnSelect
@@ -587,7 +587,7 @@ watch(
                 }}</span>
             </QCardSection>
             <QCardSection class="justify-end text-weight-bold text-subtitle1" horizontal>
-                <span class="q-mr-xs color-vn-label"> {{ t('ticketSale.total') }}: </span>
+                <span class="q-mr-xs color-vn-label"> {{ t('basicData.total') }}: </span>
                 <span>{{ toCurrency(store.data?.totalWithVat) }}</span>
             </QCardSection>
         </div></QDrawer
@@ -753,7 +753,7 @@ watch(
                 >
                     <VnInput
                         v-model.number="edit.price"
-                        :label="t('ticketSale.price')"
+                        :label="t('basicData.price')"
                         type="number"
                     />
                 </TicketEditManaProxy>
diff --git a/src/pages/Ticket/Card/TicketSaleTracking.vue b/src/pages/Ticket/Card/TicketSaleTracking.vue
index e7830bf37..4d1b82bec 100644
--- a/src/pages/Ticket/Card/TicketSaleTracking.vue
+++ b/src/pages/Ticket/Card/TicketSaleTracking.vue
@@ -42,19 +42,19 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.item'),
+        label: t('basicData.item'),
         name: 'item',
         align: 'left',
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.description'),
+        label: t('basicData.description'),
         name: 'description',
         align: 'left',
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         field: 'quantity',
         align: 'left',
@@ -78,7 +78,7 @@ const columns = computed(() => [
 
 const logTableColumns = computed(() => [
     {
-        label: t('ticketSaleTracking.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         field: 'quantity',
         align: 'left',
@@ -92,20 +92,20 @@ const logTableColumns = computed(() => [
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.worker'),
+        label: t('expedition.worker'),
         name: 'worker',
         align: 'left',
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.state'),
+        label: t('ticketList.state'),
         name: 'state',
         field: 'state',
         align: 'left',
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.created'),
+        label: t('expedition.created'),
         name: 'created',
         field: 'created',
         align: 'left',
@@ -116,13 +116,13 @@ const logTableColumns = computed(() => [
 
 const shelvingsTableColumns = computed(() => [
     {
-        label: t('ticketSaleTracking.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         align: 'left',
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.worker'),
+        label: t('expedition.worker'),
         name: 'worker',
         align: 'left',
         sortable: true,
@@ -140,7 +140,7 @@ const shelvingsTableColumns = computed(() => [
         sortable: true,
     },
     {
-        label: t('ticketSaleTracking.created'),
+        label: t('expedition.created'),
         name: 'created',
         field: 'created',
         align: 'left',
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 45a870f7f..285890e08 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -85,21 +85,21 @@ const getDefaultTaxClass = async () => {
 const columns = computed(() => [
     {
         name: 'description',
-        label: t('service.description'),
+        label: t('basicData.description'),
         field: (row) => row.ticketServiceTypeFk,
         sortable: true,
         align: 'left',
     },
     {
         name: 'quantity',
-        label: t('service.quantity'),
+        label: t('basicData.quantity'),
         field: (row) => row.quantity,
         sortable: true,
         align: 'left',
     },
     {
         name: 'price',
-        label: t('service.price'),
+        label: t('basicData.price'),
         field: (row) => row.price,
         sortable: true,
         align: 'left',
diff --git a/src/pages/Ticket/Card/TicketTracking.vue b/src/pages/Ticket/Card/TicketTracking.vue
index 00b517765..f5ed03b0d 100644
--- a/src/pages/Ticket/Card/TicketTracking.vue
+++ b/src/pages/Ticket/Card/TicketTracking.vue
@@ -52,19 +52,19 @@ const paginateFilter = reactive({
 
 const columns = computed(() => [
     {
-        label: t('tracking.state'),
+        label: t('ticketList.state'),
         name: 'state',
         field: 'state',
         align: 'left',
         format: (val) => val.name,
     },
     {
-        label: t('tracking.worker'),
+        label: t('expedition.worker'),
         name: 'worker',
         align: 'left',
     },
     {
-        label: t('tracking.created'),
+        label: t('expedition.created'),
         name: 'created',
         field: 'created',
         align: 'left',
diff --git a/src/pages/Ticket/Card/TicketTransfer.vue b/src/pages/Ticket/Card/TicketTransfer.vue
index e1a011a84..d7aff3ef7 100644
--- a/src/pages/Ticket/Card/TicketTransfer.vue
+++ b/src/pages/Ticket/Card/TicketTransfer.vue
@@ -33,19 +33,19 @@ const _transfer = ref();
 
 const transferLinesColumns = computed(() => [
     {
-        label: t('ticketSale.id'),
+        label: t('ticketList.id'),
         name: 'itemFk',
         field: 'itemFk',
         align: 'left',
     },
     {
-        label: t('ticketSale.item'),
+        label: t('basicData.item'),
         name: 'item',
         field: 'concept',
         align: 'left',
     },
     {
-        label: t('ticketSale.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         field: 'quantity',
         align: 'left',
@@ -54,26 +54,26 @@ const transferLinesColumns = computed(() => [
 
 const destinationTicketColumns = computed(() => [
     {
-        label: t('ticketSale.id'),
+        label: t('ticketList.id'),
         name: 'id',
         field: 'id',
         align: 'left',
     },
     {
-        label: t('ticketSale.shipped'),
+        label: t('ticketList.shipped'),
         name: 'item',
         field: 'shipped',
         align: 'left',
         format: (val) => toDateFormat(val),
     },
     {
-        label: t('ticketSale.agency'),
+        label: t('basicData.agency'),
         name: 'agency',
         field: 'agencyName',
         align: 'left',
     },
     {
-        label: t('ticketSale.address'),
+        label: t('basicData.address'),
         name: 'address',
         field: 'address',
         align: 'left',
diff --git a/src/pages/Ticket/Card/TicketVolume.vue b/src/pages/Ticket/Card/TicketVolume.vue
index 2cf7ffc42..15b79dad7 100644
--- a/src/pages/Ticket/Card/TicketVolume.vue
+++ b/src/pages/Ticket/Card/TicketVolume.vue
@@ -39,7 +39,7 @@ const packingTypeVolume = ref([]);
 const columns = computed(() => [
     {
         align: 'left',
-        label: t('volume.item'),
+        label: t('basicData.item'),
         name: 'itemFk',
         chip: {
             condition: () => true,
@@ -48,7 +48,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('volume.description'),
+        label: t('basicData.description'),
         name: 'concept',
         columnClass: 'expand',
         cardVisible: true,
@@ -62,7 +62,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('volume.quantity'),
+        label: t('basicData.quantity'),
         name: 'quantity',
         cardVisible: true,
     },
diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue
index 43b500dc0..1fc45f713 100644
--- a/src/pages/Ticket/TicketAdvance.vue
+++ b/src/pages/Ticket/TicketAdvance.vue
@@ -127,7 +127,7 @@ const ticketColumns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('advanceTickets.state'),
+        label: t('ticketList.state'),
         name: 'state',
         align: 'left',
         sortable: true,
diff --git a/src/pages/Ticket/TicketFuture.vue b/src/pages/Ticket/TicketFuture.vue
index 2078d0595..35c0f6eb2 100644
--- a/src/pages/Ticket/TicketFuture.vue
+++ b/src/pages/Ticket/TicketFuture.vue
@@ -95,7 +95,7 @@ const ticketColumns = computed(() => [
         columnFilter: null,
     },
     {
-        label: t('futureTickets.ticketId'),
+        label: t('advanceTickets.ticketId'),
         name: 'ticketId',
         align: 'center',
         sortable: true,
@@ -118,7 +118,7 @@ const ticketColumns = computed(() => [
         columnFilter: null,
     },
     {
-        label: t('futureTickets.ipt'),
+        label: t('advanceTickets.ipt'),
         name: 'ipt',
         field: 'ipt',
         align: 'left',
@@ -139,14 +139,14 @@ const ticketColumns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('futureTickets.state'),
+        label: t('ticketList.state'),
         name: 'state',
         align: 'left',
         sortable: true,
         columnFilter: null,
     },
     {
-        label: t('futureTickets.liters'),
+        label: t('advanceTickets.liters'),
         name: 'liters',
         field: 'liters',
         align: 'left',
@@ -162,7 +162,7 @@ const ticketColumns = computed(() => [
         },
     },
     {
-        label: t('futureTickets.import'),
+        label: t('advanceTickets.import'),
         field: 'import',
         name: 'import',
         align: 'left',
@@ -186,7 +186,7 @@ const ticketColumns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('futureTickets.futureId'),
+        label: t('advanceTickets.futureId'),
         name: 'futureId',
         align: 'left',
         sortable: true,
@@ -211,7 +211,7 @@ const ticketColumns = computed(() => [
     },
 
     {
-        label: t('futureTickets.futureIpt'),
+        label: t('advanceTickets.futureIpt'),
         name: 'futureIpt',
         field: 'futureIpt',
         align: 'left',
@@ -232,7 +232,7 @@ const ticketColumns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('futureTickets.futureState'),
+        label: t('advanceTickets.futureState'),
         name: 'futureState',
         align: 'right',
         sortable: true,
@@ -259,7 +259,7 @@ const moveTicketsFuture = async () => {
 
         let params = { tickets: ticketsToMove };
         await axios.post('Tickets/merge', params);
-        notify(t('futureTickets.moveTicketSuccess'), 'positive');
+        notify(t('advanceTickets.moveTicketSuccess'), 'positive');
         selectedTickets.value = [];
         arrayData.fetch({ append: false });
     } catch (error) {
@@ -333,14 +333,14 @@ onMounted(async () => {
                         colspan="8"
                         translate
                     >
-                        {{ t('futureTickets.origin') }}
+                        {{ t('advanceTickets.origin') }}
                     </QTh>
                     <QTh
                         class="horizontal-separator text-uppercase color-vn-label"
                         colspan="4"
                         translate
                     >
-                        {{ t('futureTickets.destination') }}
+                        {{ t('advanceTickets.destination') }}
                     </QTh>
                 </QTr>
                 <QTr>
@@ -409,7 +409,7 @@ onMounted(async () => {
                         size="xs"
                     >
                         <QTooltip>
-                            {{ t('futureTickets.noVisible') }}
+                            {{ t('ticketSale.noVisible') }}
                         </QTooltip>
                     </QIcon>
                     <QIcon
diff --git a/src/pages/Ticket/TicketWeekly.vue b/src/pages/Ticket/TicketWeekly.vue
index d68d18c24..05477d2fb 100644
--- a/src/pages/Ticket/TicketWeekly.vue
+++ b/src/pages/Ticket/TicketWeekly.vue
@@ -47,7 +47,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'clientFk',
-        label: t('weeklyTickets.client'),
+        label: t('ticketList.client'),
         isTitle: true,
         cardVisible: true,
         component: 'select',
@@ -79,7 +79,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('weeklyTickets.agency'),
+        label: t('basicData.agency'),
         name: 'agencyModeFk',
         cardVisible: true,
         columnFilter: {
@@ -95,7 +95,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'warehouseFk',
-        label: t('weeklyTickets.warehouse'),
+        label: t('ticketList.warehouse'),
         cardVisible: true,
         columnFilter: {
             component: 'select',
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index 829ea7a91..41c393a42 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -2,16 +2,12 @@ card:
     search: Search tickets
     searchInfo: You can search by ticket id or alias
 volume:
-    item: Item
-    description: Description
     packingType: Packing Type
-    quantity: Quantity
     volumeQuantity: m³ per quantity
     type: Type
     volume: Volume
 ticketNotes:
     observationType: Observation type
-    description: Description
     removeNote: Remove note
     addNote: Add note
     observationTypes:
@@ -25,29 +21,18 @@ ticketNotes:
         DropOff: Drop Off
         Sustitución: Sustitution
 ticketSale:
-    id: Id
     visible: Visible
     available: Available
-    quantity: Quantity
-    item: Item
-    price: Price
     discount: Disc
-    amount: Amount
     packaging: Packaging
     subtotal: Subtotal
     tax: VAT
-    total: Total
     history: History
     claim: Claim
     reserved: Reserved
-    noVisible: Not visible
     hasComponentLack: Component lack
     ok: Ok
-    state: State
     more: More
-    shipped: Shipped
-    agency: Agency
-    address: Address
 advanceTickets:
     preparation: Preparation
     origin: Origin
@@ -56,7 +41,6 @@ advanceTickets:
     destinationAgency: 'Destination agency: {agency}'
     ticketId: ID
     ipt: IPT
-    state: State
     liters: Liters
     lines: Lines
     import: Import
@@ -81,17 +65,9 @@ advanceTickets:
     searchInfo: Search advance tickets by ID or client ID
 futureTickets:
     problems: Problems
-    ticketId: ID
     shipped: Date
-    ipt: IPT
-    state: State
-    liters: Liters
-    import: Import
     availableLines: Available lines
-    futureId: ID
     futureShipped: Date
-    futureIpt: IPT
-    futureState: State
     noVerified: No verified data
     noVisible: Not visible
     purchaseRequest: Purchase request
@@ -99,11 +75,8 @@ futureTickets:
     componentLack: Component lack
     rounding: Rounding
     risk: Risk
-    origin: Origin
-    destination: Destination
     moveTicketTitle: Move tickets
     moveTicketDialogSubtitle: 'Do you want to move {selectedTickets} tickets to the future?'
-    moveTicketSuccess: Tickets moved successfully!
     searchInfo: Search future tickets by date
     futureTicket: Future tickets
     FREE: Free
@@ -113,17 +86,14 @@ futureTickets:
     DELIVERED: Delivered
 expedition:
     id: Expedition
-    item: Item
     name: Name
     packageType: Package type
     counter: Counter
     externalId: external Id
     created: Created
-    state: State
     historyAction: Status log
     newTicketWithRoute: New ticket with route
     newTicketWithoutRoute: New ticket without route
-    landed: Landed
     routeId: Route id
     deleteExpedition: Delete expedition
     expeditionRemoved: Expedition removed
@@ -138,17 +108,12 @@ basicData:
     next: Next
     back: Back
     finalize: Finalize
-    client: Client
-    warehouse: Warehouse
     address: Address
     inactive: (Inactive)
     noDeliveryZoneAvailable: No delivery zone available for this landing date
     editAddress: Edit address
     alias: Alias
-    company: Company
     agency: Agency
-    zone: Zone
-    shipped: Shipped
     landed: Landed
     shippedHour: Shipped hour
     priceDifference: Price difference
@@ -171,37 +136,22 @@ basicData:
     chooseAnOption: Choose an option
     unroutedTicket: The ticket has been unrouted
 purchaseRequest:
-    id: Id
-    description: Description
-    created: Created
     requester: Requester
     atender: Atender
-    quantity: Quantity
-    price: Price
     saleFk: Item id
-    state: State
     newRequest: New request
 weeklyTickets:
     id: Ticket ID
-    client: Client
     shipment: Shipment
-    agency: Agency
-    warehouse: Warehouse
     salesperson: Salesperson
     search: Search weekly tickets
     searchInfo: Search weekly tickets by id or client id
 ticketSaleTracking:
     isChecked: Is checked
-    item: Item
-    description: Description
-    quantity: Quantity
     parking: Parking
     historyAction: Log states
     shelvingAction: Shelvings sale
     original: Original
-    worker: Worker
-    state: State
-    created: Created
     shelving: Shelving
     saleGroupDetail: sale group detail
     previousSelected: previous selected
@@ -210,40 +160,25 @@ ticketSaleTracking:
     checked: checked
 service:
     pay: Pay
-    description: Description
-    quantity: Quantity
-    price: Price
     removeService: Remove service
     newService: New service type
     addService: Add service
     quantityInfo: To create services with negative amounts mark the service on the source ticket and press the pay button.
     createRefundSuccess: 'The following refund ticket have been created: { ticketId }'
 ticketComponents:
-    item: Item
-    description: Description
-    quantity: Quantity
     serie: Serie
     components: Components
-    import: Import
-    total: Total
     baseToCommission: Base to commission
     totalWithoutVat: Total without VAT
     zoneBreakdown: Zone breakdown
-    price: Price
     bonus: Bonus
-    zone: Zone
-    volume: Volume
     theoricalCost: Theorical cost
     totalPrice: Total price
     packages: Packages
 tracking:
-    state: State
-    worker: Worker
-    created: Created
     addState: Add state
 package:
     package: Package
-    quantity: Quantity
     added: Added
     addPackage: Add package
     removePackage: Remove package
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index b372e48ef..2f7e2add8 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -1,32 +1,22 @@
 service:
     pay: Abonar
-    description: Descripción
-    quantity: Cantidad
-    price: Precio
     removeService: Quitar servicio
     newService: Nuevo tipo de servicio
     addService: Añadir servicio
     quantityInfo: Para crear sevicios con cantidades negativas marcar servicio en el ticket origen y apretar el boton abonar.
     createRefundSuccess: 'Se ha creado siguiente ticket de abono: { ticketId }'
 tracking:
-    state: Estado
-    worker: Trabajador
-    created: Fecha creación
     addState: Añadir estado
 card:
     search: Buscar tickets
     searchInfo: Buscar tickets por identificador o alias
 volume:
-    item: Artículo
-    description: Descripción
     packingType: Encajado
-    quantity: Cantidad
     volumeQuantity: m³ por cantidad
     type: Tipo
     volume: Volumen
 ticketNotes:
     observationType: Tipo de observación
-    description: Descripción
     removeNote: Quitar nota
     addNote: Añadir nota
     observationTypes:
@@ -42,31 +32,20 @@ ticketNotes:
         Accepted: Aceptado
         Denied: Denegado
 purchaseRequest:
-    Id: Id
-    description: Descripción
-    created: Fecha creación
     requester: Solicitante
     atender: Comprador
-    quantity: Cantidad
-    price: Precio
     saleFk: Id artículo
-    state: Estado
     newRequest: Crear petición
 basicData:
     next: Siguiente
     back: Anterior
     finalize: Finalizar
-    client: Cliente
-    warehouse: Almacén
     address: Consignatario
     inactive: (Inactivo)
     noDeliveryZoneAvailable: No hay una zona de reparto disponible para la fecha de envío seleccionada
     editAddress: Editar dirección
     alias: Alias
-    company: Empresa
     agency: Agencia
-    zone: Zona
-    shipped: F. Envío
     landed: F. Entrega
     shippedHour: Hora de envío
     priceDifference: Diferencia de precio
@@ -90,10 +69,7 @@ basicData:
     unroutedTicket: El ticket ha sido desenrutado
 weeklyTickets:
     id: ID Ticket
-    client: Cliente
     shipment: Salida
-    agency: Agencia
-    warehouse: Almacén
     salesperson: Comercial
     search: Buscar por tickets programados
     searchInfo: Buscar tickets programados por el identificador o el identificador del cliente
@@ -105,7 +81,6 @@ advanceTickets:
     destinationAgency: 'Agencia destino: {agency}'
     ticketId: ID
     ipt: IPT
-    state: Estado
     liters: Litros
     lines: Líneas
     import: Importe
@@ -130,29 +105,17 @@ advanceTickets:
     searchInfo: Buscar tickets adelantados por el identificador o el identificador del cliente
 futureTickets:
     problems: Problemas
-    ticketId: ID
     shipped: Fecha
-    ipt: IPT
-    state: Estado
-    liters: Litros
-    import: Importe
     availableLines: Líneas disponibles
-    futureId: ID
     futureShipped: Fecha
-    futureIpt: IPT
-    futureState: Estado
     noVerified: Sin datos comprobados
-    noVisible: No visible
     purchaseRequest: Petición de compra
     clientFrozen: Cliente congelado
     risk: Riesgo
     componentLack: Faltan componentes
     rounding: Redondeo
-    origin: Origen
-    destination: Destino
     moveTicketTitle: Mover tickets
     moveTicketDialogSubtitle: '¿Desea mover {selectedTickets} tickets hacia el futuro?'
-    moveTicketSuccess: Tickets movidos correctamente
     searchInfo: Buscar tickets por fecha
     futureTicket: Tickets a futuro
     FREE: Libre
@@ -161,60 +124,40 @@ futureTickets:
     PACKED: Encajado
     DELIVERED: Servido
 ticketSale:
-    id: Id
     visible: Visible
     available: Disponible
-    quantity: Cantidad
-    item: Artículo
-    price: Precio
     discount: Dto
-    amount: Importe
     packaging: Encajado
     subtotal: Subtotal
     tax: IVA
-    total: Total
     history: Historial
     claim: Reclamación
     reserved: Reservado
     noVisible: No visible
     hasComponentLack: Faltan componentes
     ok: Ok
-    state: Estado
     more: Más
-    shipped: F. Envío
-    agency: Agencia
     address: Consignatario
 ticketComponents:
-    item: Artículo
-    description: Descripción
-    quantity: Cantidad
     serie: Serie
     components: Componentes
-    import: Importe
-    total: Total
     baseToCommission: Base comisionable
     totalWithoutVat: Total sin IVA
     zoneBreakdown: Desglose zona
-    price: Precio
     bonus: Bonificación
-    zone: Zona
-    volume: Volúmen
     theoricalCost: Porte teórico
     totalPrice: Precio total
     packages: Bultos
 expedition:
     id: Expedición
-    item: Artículo
     name: Nombre
     packageType: Embalaje
     counter: Contador
     externalId: ID externo
     created: Fecha creación
-    state: Estado
     historyAction: Historial de estados
     newTicketWithRoute: Nuevo ticket con ruta
     newTicketWithoutRoute: Nuevo ticket sin ruta
-    landed: F. entrega
     routeId: Id ruta
     deleteExpedition: Eliminar expedición
     expeditionRemoved: Expedición eliminada
@@ -227,22 +170,15 @@ expedition:
     removeExpedition: Eliminar expedición
 package:
     package: Embalaje
-    quantity: Cantidad
     added: Añadido
     addPackage: Añadir embalaje
     removePackage: Quitar embalaje
 ticketSaleTracking:
     isChecked: Comprobado
-    item: Artículo
-    description: Descripción
-    quantity: Cantidad
     parking: Parking
     historyAction: Historial estados
     shelvingAction: Carros línea
     original: Original
-    worker: Trabajador
-    state: Estado
-    created: Fecha creación
     shelving: Matrícula
     saleGroupDetail: detalle grupo líneas
     previousSelected: previa seleccionado
diff --git a/src/pages/Zone/Card/ZoneCreateWarehouse.vue b/src/pages/Zone/Card/ZoneCreateWarehouse.vue
index 86c4dcc72..a46ec2e6c 100644
--- a/src/pages/Zone/Card/ZoneCreateWarehouse.vue
+++ b/src/pages/Zone/Card/ZoneCreateWarehouse.vue
@@ -32,7 +32,7 @@ const warehousesOptions = ref([]);
             <VnRow>
                 <div class="col">
                     <VnSelect
-                        :label="t('warehouses.warehouse')"
+                        :label="t('list.warehouse')"
                         v-model="ZoneWarehouseFormData.warehouseFk"
                         :options="warehousesOptions"
                         option-value="id"
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index 04fb22ba5..f991818fb 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -57,11 +57,11 @@ const setData = (entity) => {
             <ZoneDescriptorMenuItems :zone="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('summary.agency')" :value="entity.agencyMode.name" />
-            <VnLv :label="t('summary.closeHour')" :value="toTimeFormat(entity.hour)" />
-            <VnLv :label="t('summary.travelingDays')" :value="entity.travelingDays" />
-            <VnLv :label="t('summary.price')" :value="toCurrency(entity.price)" />
-            <VnLv :label="t('summary.bonus')" :value="toCurrency(entity.bonus)" />
+            <VnLv :label="t('list.agency')" :value="entity.agencyMode.name" />
+            <VnLv :label="t('zone.closing')" :value="toTimeFormat(entity.hour)" />
+            <VnLv :label="t('zone.travelingDays')" :value="entity.travelingDays" />
+            <VnLv :label="t('list.price')" :value="toCurrency(entity.price)" />
+            <VnLv :label="t('zone.bonus')" :value="toCurrency(entity.bonus)" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Zone/Card/ZoneEventExclusionForm.vue b/src/pages/Zone/Card/ZoneEventExclusionForm.vue
index 215c12f46..72c02a5cd 100644
--- a/src/pages/Zone/Card/ZoneEventExclusionForm.vue
+++ b/src/pages/Zone/Card/ZoneEventExclusionForm.vue
@@ -186,8 +186,8 @@ onMounted(() => {
                 class="q-mr-sm"
                 @click="
                     openConfirmationModal(
-                        t('eventsPanel.deleteTitle'),
-                        t('eventsPanel.deleteSubtitle'),
+                        t('zone.deleteTitle'),
+                        t('zone.deleteSubtitle'),
                         () => deleteEvent()
                     )
                 "
diff --git a/src/pages/Zone/Card/ZoneEventInclusionForm.vue b/src/pages/Zone/Card/ZoneEventInclusionForm.vue
index 66e41607f..8b1645426 100644
--- a/src/pages/Zone/Card/ZoneEventInclusionForm.vue
+++ b/src/pages/Zone/Card/ZoneEventInclusionForm.vue
@@ -153,7 +153,7 @@ onMounted(() => {
                 <div class="col flex justify-center">
                     <VnInputDate
                         v-if="inclusionType === 'day'"
-                        :label="t('eventsInclusionForm.day')"
+                        :label="t('eventsExclusionForm.day')"
                         v-model="eventInclusionFormData.dated"
                         class="full-width"
                     />
@@ -176,11 +176,11 @@ onMounted(() => {
             <VnRow>
                 <VnInputTime
                     v-model="eventInclusionFormData.hour"
-                    :label="t('eventsInclusionForm.closing')"
+                    :label="t('zone.closing')"
                 />
                 <VnInput
                     v-model="eventInclusionFormData.travelingDays"
-                    :label="t('eventsInclusionForm.travelingDays')"
+                    :label="t('zone.travelingDays')"
                     type="number"
                     min="0"
                 />
@@ -188,13 +188,13 @@ onMounted(() => {
             <VnRow>
                 <VnInput
                     v-model="eventInclusionFormData.price"
-                    :label="t('eventsInclusionForm.price')"
+                    :label="t('list.price')"
                     type="number"
                     min="0"
                 />
                 <VnInput
                     v-model="eventInclusionFormData.bonus"
-                    :label="t('eventsInclusionForm.bonus')"
+                    :label="t('zone.bonus')"
                     type="number"
                     min="0"
                 />
@@ -202,7 +202,7 @@ onMounted(() => {
             <VnRow>
                 <VnInput
                     v-model="eventInclusionFormData.m3Max"
-                    :label="t('eventsInclusionForm.m3Max')"
+                    :label="t('zone.m3Max')"
                     type="number"
                     min="0"
                 />
@@ -224,8 +224,8 @@ onMounted(() => {
                 class="q-mr-sm"
                 @click="
                     openConfirmationModal(
-                        t('eventsPanel.deleteTitle'),
-                        t('eventsPanel.deleteSubtitle'),
+                        t('zone.deleteTitle'),
+                        t('zone.deleteSubtitle'),
                         () => deleteEvent()
                     )
                 "
diff --git a/src/pages/Zone/Card/ZoneEventsPanel.vue b/src/pages/Zone/Card/ZoneEventsPanel.vue
index 2cfa98246..55bc27ebe 100644
--- a/src/pages/Zone/Card/ZoneEventsPanel.vue
+++ b/src/pages/Zone/Card/ZoneEventsPanel.vue
@@ -150,31 +150,31 @@ onMounted(async () => {
                         </span>
                     </div>
                     <span class="color-vn-label">
-                        {{ t('eventsPanel.closing') }}:
+                        {{ t('zone.closing') }}:
                         <span class="color-vn-text q-ml-xs">
                             {{ dashIfEmpty(toTimeFormat(event.hour)) }}
                         </span>
                     </span>
                     <span class="color-vn-label">
-                        {{ t('eventsPanel.travelingDays') }}:
+                        {{ t('zone.travelingDays') }}:
                         <span class="color-vn-text">
                             {{ dashIfEmpty(event.travelingDays) }}
                         </span>
                     </span>
                     <span class="color-vn-label">
-                        {{ t('eventsPanel.price') }}:
+                        {{ t('list.price') }}:
                         <span class="color-vn-text">
                             {{ dashOrCurrency(event.price)() }}</span
                         >
                     </span>
                     <span class="color-vn-label">
-                        {{ t('eventsPanel.bonus') }}:
+                        {{ t('zone.bonus') }}:
                         <span class="color-vn-text">
                             {{ dashOrCurrency(event.bonus)() }}</span
                         >
                     </span>
                     <span class="color-vn-label">
-                        {{ t('eventsPanel.m3Max') }}:
+                        {{ t('zone.m3Max') }}:
                         <span class="color-vn-text"> {{ dashIfEmpty(event.m3Max) }}</span>
                     </span>
                 </QItemSection>
@@ -187,8 +187,8 @@ onMounted(async () => {
                         color="primary"
                         @click.stop="
                             openConfirmationModal(
-                                t('eventsPanel.deleteTitle'),
-                                t('eventsPanel.deleteSubtitle'),
+                                t('zone.deleteTitle'),
+                                t('zone.deleteSubtitle'),
                                 () => deleteEvent(event.id)
                             )
                         "
diff --git a/src/pages/Zone/Card/ZoneLocations.vue b/src/pages/Zone/Card/ZoneLocations.vue
index f357e9e5b..321748f00 100644
--- a/src/pages/Zone/Card/ZoneLocations.vue
+++ b/src/pages/Zone/Card/ZoneLocations.vue
@@ -23,7 +23,7 @@ const onSelected = async (val, node) => {
 <template>
     <QPage class="column items-center q-pa-md">
         <QCard class="full-width q-pa-md" style="max-width: 800px">
-            <ZoneLocationsTree :root-label="t('zoneLocations.locations')">
+            <ZoneLocationsTree :root-label="t('zone.pageTitles.locations')">
                 <template #content="{ node }">
                     <span v-if="!node.id">{{ node.name }}</span>
                     <QCheckbox
diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
index d46282c10..384ee1fe9 100644
--- a/src/pages/Zone/Card/ZoneSummary.vue
+++ b/src/pages/Zone/Card/ZoneSummary.vue
@@ -40,7 +40,7 @@ const filter = computed(() => {
 
 const columns = computed(() => [
     {
-        label: t('summary.name'),
+        label: t('list.name'),
         name: 'name',
         field: 'warehouse',
         align: 'left',
@@ -82,22 +82,22 @@ onMounted(async () => {
         <template #body="{ entity: zone }">
             <QCard class="vn-one">
                 <VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
-                <VnLv :label="t('summary.agency')" :value="zone.agencyMode?.name" />
-                <VnLv :label="t('summary.price')" :value="toCurrency(zone.price)" />
-                <VnLv :label="t('summary.bonus')" :value="toCurrency(zone.bonus)" />
+                <VnLv :label="t('list.agency')" :value="zone.agencyMode?.name" />
+                <VnLv :label="t('list.price')" :value="toCurrency(zone.price)" />
+                <VnLv :label="t('zone.bonus')" :value="toCurrency(zone.bonus)" />
             </QCard>
             <QCard class="vn-one">
                 <VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
                 <VnLv :label="t('summary.closeHour')" :value="toTimeFormat(zone.hour)" />
-                <VnLv :label="t('summary.travelingDays')" :value="zone.travelingDays" />
+                <VnLv :label="t('zone.travelingDays')" :value="zone.travelingDays" />
                 <QCheckbox
-                    :label="t('summary.volumetric')"
+                    :label="t('zone.volumetric')"
                     v-model="zone.isVolumetric"
                     :disable="true"
                 />
             </QCard>
             <QCard class="full-width">
-                <VnTitle :url="zoneUrl + `warehouses`" :text="t('summary.warehouse')" />
+                <VnTitle :url="zoneUrl + `warehouses`" :text="t('list.warehouse')" />
                 <QTable
                     :columns="columns"
                     :rows="warehouses"
diff --git a/src/pages/Zone/Card/ZoneWarehouses.vue b/src/pages/Zone/Card/ZoneWarehouses.vue
index 6b2933224..e61aae9ec 100644
--- a/src/pages/Zone/Card/ZoneWarehouses.vue
+++ b/src/pages/Zone/Card/ZoneWarehouses.vue
@@ -90,14 +90,14 @@ const openCreateWarehouseForm = () => createWarehouseDialogRef.value.show();
                                         color="primary"
                                         @click="
                                             openConfirmationModal(
-                                                t('warehouses.deleteTitle'),
-                                                t('warehouses.deleteSubtitle'),
+                                                t('zone.deleteTitle'),
+                                                t('zone.deleteSubtitle'),
                                                 () => deleteWarehouse(row, rows, rowIndex)
                                             )
                                         "
                                     >
                                         <QTooltip>
-                                            {{ t('warehouses.delete') }}
+                                            {{ t('eventsPanel.delete') }}
                                         </QTooltip>
                                     </QIcon>
                                 </QTd>
diff --git a/src/pages/Zone/ZoneClosingTable.vue b/src/pages/Zone/ZoneClosingTable.vue
index ce0c91af7..049f82271 100644
--- a/src/pages/Zone/ZoneClosingTable.vue
+++ b/src/pages/Zone/ZoneClosingTable.vue
@@ -23,28 +23,28 @@ defineProps({
 
 const columns = computed(() => [
     {
-        label: t('zoneClosingTable.id'),
+        label: t('list.id'),
         name: 'id',
         field: 'id',
         sortable: true,
         align: 'left',
     },
     {
-        label: t('zoneClosingTable.name'),
+        label: t('list.name'),
         name: 'name',
         field: 'name',
         sortable: true,
         align: 'left',
     },
     {
-        label: t('zoneClosingTable.agency'),
+        label: t('list.agency'),
         name: 'agency',
         field: 'agencyModeName',
         sortable: true,
         align: 'left',
     },
     {
-        label: t('zoneClosingTable.closing'),
+        label: t('zone.closing'),
         name: 'close',
         field: 'hour',
         sortable: true,
@@ -52,7 +52,7 @@ const columns = computed(() => [
         format: (val) => toTimeFormat(val),
     },
     {
-        label: t('zoneClosingTable.price'),
+        label: t('list.price'),
         name: 'price',
         field: 'price',
         sortable: true,
@@ -73,7 +73,7 @@ const redirectToZoneSummary = (id) => {
 <template>
     <div>
         <div class="header">
-            <span>{{ t('zoneClosingTable.zones') }}</span>
+            <span>{{ t('zone.pageTitles.zones') }}</span>
         </div>
         <QTable
             :rows="rows"
diff --git a/src/pages/Zone/ZoneCreate.vue b/src/pages/Zone/ZoneCreate.vue
index 7d7fa24a3..6db83c51d 100644
--- a/src/pages/Zone/ZoneCreate.vue
+++ b/src/pages/Zone/ZoneCreate.vue
@@ -54,13 +54,13 @@ const redirectToZoneLocations = (_, { id }) => {
                 <VnRow>
                     <VnInput
                         v-model="data.name"
-                        :label="t('create.name')"
+                        :label="t('list.name')"
                         :required="true"
                     />
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('create.warehouse')"
+                        :label="t('list.warehouse')"
                         :options="warehousesOptions"
                         hide-selected
                         option-label="name"
@@ -68,7 +68,7 @@ const redirectToZoneLocations = (_, { id }) => {
                         v-model="data.warehouseFk"
                     />
                     <VnSelect
-                        :label="t('create.agency')"
+                        :label="t('list.agency')"
                         :options="agencyOptions"
                         hide-selected
                         option-label="name"
@@ -80,7 +80,7 @@ const redirectToZoneLocations = (_, { id }) => {
                 <VnRow>
                     <VnInput
                         v-model="data.travelingDays"
-                        :label="t('create.travelingDays')"
+                        :label="t('zone.travelingDays')"
                         type="number"
                         min="0"
                     />
@@ -90,20 +90,20 @@ const redirectToZoneLocations = (_, { id }) => {
                 <VnRow>
                     <VnInput
                         v-model="data.price"
-                        :label="t('create.price')"
+                        :label="t('list.price')"
                         type="number"
                         min="0"
                     />
                     <VnInput
                         v-model="data.bonus"
-                        :label="t('create.bonus')"
+                        :label="t('zone.bonus')"
                         type="number"
                         min="0"
                     />
                 </VnRow>
                 <VnRow>
                     <QCheckbox
-                        :label="t('create.volumetric')"
+                        :label="t('zone.volumetric')"
                         v-model="data.isVolumetric"
                         :toggle-indeterminate="false"
                     />
diff --git a/src/pages/Zone/ZoneDeliveryPanel.vue b/src/pages/Zone/ZoneDeliveryPanel.vue
index 423095d6e..a2d215ed6 100644
--- a/src/pages/Zone/ZoneDeliveryPanel.vue
+++ b/src/pages/Zone/ZoneDeliveryPanel.vue
@@ -117,7 +117,7 @@ watch(
             <VnSelect
                 data-key="delivery"
                 v-if="deliveryMethodFk == 'delivery'"
-                :label="t('deliveryPanel.agency')"
+                :label="t('list.agency')"
                 v-model="formData.agencyModeFk"
                 url="AgencyModes/isActive"
                 :fields="['id', 'name']"
@@ -132,7 +132,7 @@ watch(
             />
             <VnSelect
                 v-else
-                :label="t('deliveryPanel.warehouse')"
+                :label="t('list.warehouse')"
                 v-model="formData.agencyModeFk"
                 url="AgencyModes/isActive"
                 :fields="['id', 'name']"
diff --git a/src/pages/Zone/ZoneFilterPanel.vue b/src/pages/Zone/ZoneFilterPanel.vue
index 25c55d75c..efe710360 100644
--- a/src/pages/Zone/ZoneFilterPanel.vue
+++ b/src/pages/Zone/ZoneFilterPanel.vue
@@ -38,11 +38,7 @@ const agencies = ref([]);
         <template #body="{ params, searchFn }">
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        :label="t('filterPanel.name')"
-                        v-model="params.name"
-                        is-outlined
-                    />
+                    <VnInput :label="t('list.name')" v-model="params.name" is-outlined />
                 </QItemSection>
             </QItem>
             <QItem>
diff --git a/src/pages/Zone/ZoneList.vue b/src/pages/Zone/ZoneList.vue
index d160ea6b5..060b266ab 100644
--- a/src/pages/Zone/ZoneList.vue
+++ b/src/pages/Zone/ZoneList.vue
@@ -174,13 +174,13 @@ onMounted(() => (stateStore.rightDrawer = true));
             />
             <VnInput
                 v-model="data.bonus"
-                :label="t('list.bonus')"
+                :label="t('zone.bonus')"
                 min="0"
                 type="number"
             />
             <VnInput
                 v-model="data.travelingDays"
-                :label="t('list.travelingDays')"
+                :label="t('zone.travelingDays')"
                 type="number"
                 min="0"
             />
diff --git a/src/pages/Zone/ZoneUpcoming.vue b/src/pages/Zone/ZoneUpcoming.vue
index ecf82bf4f..c74ae6078 100644
--- a/src/pages/Zone/ZoneUpcoming.vue
+++ b/src/pages/Zone/ZoneUpcoming.vue
@@ -22,13 +22,13 @@ const columns = computed(() => [
         align: 'left',
     },
     {
-        label: t('upcomingDeliveries.closing'),
+        label: t('zone.closing'),
         name: 'closing',
         field: 'hour',
         align: 'left',
     },
     {
-        label: t('upcomingDeliveries.id'),
+        label: t('list.id'),
         name: 'id',
         field: 'zoneFk',
         align: 'left',
diff --git a/src/pages/Zone/locale/en.yml b/src/pages/Zone/locale/en.yml
index 2608c071c..bf7d8f0de 100644
--- a/src/pages/Zone/locale/en.yml
+++ b/src/pages/Zone/locale/en.yml
@@ -8,6 +8,13 @@ zone:
         upcomingDeliveries: Upcoming deliveries
         warehouses: Warehouses
         calendar: Calendar
+    m3Max: Max m³
+    deleteTitle: This item will be deleted
+    deleteSubtitle: Are you sure you want to continue?
+    volumetric: Volumetric
+    bonus: Bonus
+    closing: Closing
+    travelingDays: Traveling days
 list:
     clone: Clone
     id: Id
@@ -22,74 +29,38 @@ list:
     searchInfo: Search zone by id or name
     confirmCloneTitle: All it's properties will be copied
     confirmCloneSubtitle: Do you want to clone this zone?
-    travelingDays: Traveling days
     warehouse: Warehouse
-    bonus: Bonus
-    isVolumetric: Volumetric
     createZone: Create zone
     zoneSummary: Summary
 create:
     name: Name
-    warehouse: Warehouse
-    agency: Agency
-    travelingDays: Traveling days
     closingHour: Closing hour
-    price: Price
-    bonus: Bonus
-    volumetric: Volumetric
     itemMaxSize: Max m³
     inflation: Inflation
 summary:
-    agency: Agency
-    price: Price
     basicData: Basic data
-    bonus: Bonus
     closeHour: Close hour
-    travelingDays: Traveling days
-    volumetric: Volumetric
-    warehouse: Warehouse
-    name: Name
 filterPanel:
-    name: Name
     agencyModeFk: Agency
-zoneLocations:
-    locations: Locations
 deliveryPanel:
     pickup: Pick up
     delivery: Delivery
     postcode: Postcode
-    agency: Agency
-    warehouse: Warehouse
     query: Query
     noEventsWarning: No service for the specified zone
 zoneClosingTable:
-    id: Id
-    name: Name
-    agency: Agency
-    closing: Closing
-    price: Price
     preview: Preview
-    zones: Zones
 warehouses:
-    delete: Delete
     deleteTitle: This item will be deleted
     deleteSubtitle: Are you sure you want to continue?
-    warehouse: Warehouse
     add: Add
 eventsPanel:
     editMode: Edit mode
     include: Include
     exclude: Exclude
     events: Events
-    closing: Closing
-    travelingDays: Traveling days
-    price: Price
-    bonus: Bonus
-    m3Max: Max m³
     everyday: Everyday
     delete: Delete
-    deleteTitle: This item will be deleted
-    deleteSubtitle: Are you sure you want to continue?
 eventsExclusionForm:
     addExclusion: Add exclusion
     editExclusion: Edit exclusion
@@ -103,15 +74,8 @@ eventsInclusionForm:
     oneDay: One day
     indefinitely: Indefinitely
     rangeOfDates: Range of dates
-    day: Day
-    closing: Closing
-    travelingDays: Traveling days
-    price: Price
-    bonus: Bonus
-    m3Max: Max m³
     from: From
     to: To
 upcomingDeliveries:
     province: Province
     closing: Closing
-    id: Id
diff --git a/src/pages/Zone/locale/es.yml b/src/pages/Zone/locale/es.yml
index 7ecfb580d..91541bea3 100644
--- a/src/pages/Zone/locale/es.yml
+++ b/src/pages/Zone/locale/es.yml
@@ -8,6 +8,13 @@ zone:
         upcomingDeliveries: Próximos repartos
         warehouses: Almacenes
         calendar: Calendario
+    m3Max: Medida máxima
+    deleteTitle: Este elemento será eliminado
+    deleteSubtitle: ¿Seguro que quieres continuar?
+    volumetric: Volumétrico
+    bonus: Bonificación
+    closing: Cierre
+    travelingDays: Días de viaje
 list:
     clone: Clonar
     id: Id
@@ -22,76 +29,38 @@ list:
     searchInfo: Buscar zonas por identificador o nombre
     confirmCloneTitle: Todas sus propiedades serán copiadas
     confirmCloneSubtitle: ¿Seguro que quieres clonar esta zona?
-    travelingDays: Días de viaje
     warehouse: Almacén
-    bonus: Bonus
     isVolumetric: Volumétrico
     createZone: Crear zona
     zoneSummary: Resumen
 create:
-    name: Nombre
-    warehouse: Almacén
-    agency: Agencia
-    travelingDays: Días de viaje
     closingHour: Hora de cierre
-    price: Precio
-    bonus: Bonificación
-    volumetric: Volumétrico
     itemMaxSize: Medida máxima
     inflation: Inflación
 summary:
-    agency: Agencia
-    price: Precio
     basicData: Datos básicos
-    bonus: Bonificación
     closeHour: Hora de cierre
-    travelingDays: Días de viaje
-    volumetric: Volumétrico
-    warehouse: Almacén
-    name: Nombre
 filterPanel:
-    name: Nombre
     agencyModeFk: Agencia
-zoneLocations:
-    locations: Localizaciones
 deliveryPanel:
     pickup: Recogida
     delivery: Entrega
     postcode: Código postal
-    agency: Agencia
-    warehouse: Almacén
     query: Consultar
     noEventsWarning: No hay servicio para la zona especificada
 zoneClosingTable:
-    id: Id
-    name: Nombre
-    agency: Agencia
-    closing: Cierre
     preview: Vista previa
-    price: Precio
-    zones: Zonas
 Search zones: Buscar zonas
 You can search by zone reference: Puedes buscar por referencia de la zona
 warehouses:
-    delete: Eliminar
-    deleteTitle: Este elemento será eliminado
-    deleteSubtitle: ¿Seguro que quieres continuar?
-    warehouse: Almacén
     add: Añadir
 eventsPanel:
     editMode: Modo edición
     include: Incluir
     exclude: Excluir
     events: Eventos
-    closing: Cierre
-    travelingDays: Días de viaje
-    price: Precio
-    bonus: Bonificación
-    m3Max: Medida máxima
     everyday: Todos los días
     delete: Eliminar
-    deleteTitle: Este elemento será eliminado
-    deleteSubtitle: ¿Seguro que quieres continuar?
 eventsExclusionForm:
     addExclusion: Añadir exclusión
     editExclusion: Editar exclusión
@@ -105,15 +74,7 @@ eventsInclusionForm:
     oneDay: Un día
     indefinitely: Indefinido
     rangeOfDates: Rango de fechas
-    day: Día
-    closing: Cierre
-    travelingDays: Días de viaje
-    price: Precio
-    bonus: Bonificación
-    m3Max: Medida máxima
     from: Desde
     to: Hasta
 upcomingDeliveries:
     province: Provincia
-    closing: Cierre
-    id: Id

From 8eef9c0009a47fcf9ac5d29b3c3299ce8725adfc Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 18 Oct 2024 09:21:18 +0200
Subject: [PATCH 045/207] refactor: refs #7132 customer's module translations

---
 src/pages/Customer/Card/CustomerBasicData.vue | 14 +++----
 .../Customer/Card/CustomerDescriptor.vue      | 18 ++++++---
 src/pages/Customer/Card/CustomerSummary.vue   |  6 +--
 src/pages/Customer/CustomerFilter.vue         |  4 +-
 src/pages/Customer/CustomerList.vue           | 22 +++++------
 src/pages/Customer/locale/en.yml              | 39 -------------------
 src/pages/Customer/locale/es.yml              | 38 ------------------
 7 files changed, 35 insertions(+), 106 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue
index d31669b43..a77d2f865 100644
--- a/src/pages/Customer/Card/CustomerBasicData.vue
+++ b/src/pages/Customer/Card/CustomerBasicData.vue
@@ -55,7 +55,7 @@ const exprBuilder = (param, value) => {
                 />
                 <VnSelect
                     :input-debounce="0"
-                    :label="t('customer.basicData.businessType')"
+                    :label="t('customer.summary.businessType')"
                     :options="businessTypes"
                     :rules="validate('client.businessTypeFk')"
                     emit-value
@@ -67,13 +67,13 @@ const exprBuilder = (param, value) => {
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="t('customer.basicData.contact')"
+                    :label="t('customer.summary.contact')"
                     :rules="validate('client.contact')"
                     clearable
                     v-model="data.contact"
                 />
                 <VnInput
-                    :label="t('customer.basicData.email')"
+                    :label="t('globals.params.email')"
                     :rules="validate('client.email')"
                     clearable
                     type="email"
@@ -90,13 +90,13 @@ const exprBuilder = (param, value) => {
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="t('customer.basicData.phone')"
+                    :label="t('customer.extendedList.tableVisibleColumns.phone')"
                     :rules="validate('client.phone')"
                     clearable
                     v-model="data.phone"
                 />
                 <VnInput
-                    :label="t('customer.basicData.mobile')"
+                    :label="t('customer.summary.mobile')"
                     :rules="validate('client.mobile')"
                     clearable
                     v-model="data.mobile"
@@ -106,7 +106,7 @@ const exprBuilder = (param, value) => {
                 <VnSelect
                     url="Workers/search"
                     v-model="data.salesPersonFk"
-                    :label="t('customer.basicData.salesPerson')"
+                    :label="t('customer.summary.salesPerson')"
                     :params="{
                         departmentCodes: ['VT', 'shopping'],
                     }"
@@ -144,7 +144,7 @@ const exprBuilder = (param, value) => {
                     option-value="id"
                     option-label="name"
                     emit-value
-                    :label="t('customer.basicData.contactChannel')"
+                    :label="t('customer.summary.contactChannel')"
                     map-options
                     :rules="validate('client.contactChannelFk')"
                     :input-debounce="0"
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index 43103bd68..b73354386 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -53,11 +53,17 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
             <CustomerDescriptorMenu :customer="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('customer.card.payMethod')" :value="entity.payMethod.name" />
-
-            <VnLv :label="t('customer.card.credit')" :value="toCurrency(entity.credit)" />
             <VnLv
-                :label="t('customer.card.securedCredit')"
+                :label="t('customer.summary.payMethod')"
+                :value="entity.payMethod.name"
+            />
+
+            <VnLv
+                :label="t('customer.summary.credit')"
+                :value="toCurrency(entity.credit)"
+            />
+            <VnLv
+                :label="t('customer.summary.securedCredit')"
                 :value="toCurrency(entity.creditInsurance)"
             />
 
@@ -66,7 +72,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 :value="toCurrency(entity.debt)"
                 :info="t('customer.summary.riskInfo')"
             />
-            <VnLv :label="t('customer.card.salesPerson')">
+            <VnLv :label="t('customer.summary.salesPerson')">
                 <template #value>
                     <VnUserLink
                         v-if="entity.salesPersonUser"
@@ -77,7 +83,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 </template>
             </VnLv>
             <VnLv
-                :label="t('customer.card.businessTypeFk')"
+                :label="t('customer.extendedList.tableVisibleColumns.businessTypeFk')"
                 :value="entity.businessType.description"
             />
         </template>
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 8b5f0f2c2..047c46016 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -79,7 +79,7 @@ const sumRisk = ({ clientRisks }) => {
                 <VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
                 <VnLv :value="entity.phone">
                     <template #label>
-                        {{ t('customer.summary.phone') }}
+                        {{ t('customer.extendedList.tableVisibleColumns.phone') }}
                         <VnLinkPhone :phone-number="entity.phone" />
                     </template>
                 </VnLv>
@@ -89,7 +89,7 @@ const sumRisk = ({ clientRisks }) => {
                         <VnLinkPhone :phone-number="entity.mobile" />
                     </template>
                 </VnLv>
-                <VnLv :label="t('customer.summary.email')" :value="entity.email" copy />
+                <VnLv :label="t('globals.params.email')" :value="entity.email" copy />
                 <VnLv
                     :label="t('customer.summary.salesPerson')"
                     :value="entity?.salesPersonUser?.name"
@@ -201,7 +201,7 @@ const sumRisk = ({ clientRisks }) => {
                     :value="entity.defaultAddress.city"
                 />
                 <VnLv
-                    :label="t('customer.summary.addressStreet')"
+                    :label="t('customer.summary.street')"
                     :value="entity.defaultAddress.street"
                 />
             </QCard>
diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index 6c50cc9df..ae3a42514 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -34,7 +34,7 @@ defineProps({
             <QItem class="q-mb-sm">
                 <QItemSection>
                     <VnInput
-                        :label="t('customerFilter.filter.name')"
+                        :label="t('globals.name')"
                         v-model="params.name"
                         is-outlined
                     />
@@ -43,7 +43,7 @@ defineProps({
             <QItem class="q-mb-sm">
                 <QItemSection>
                     <VnInput
-                        :label="t('customerFilter.filter.socialName')"
+                        :label="t('customer.summary.socialName')"
                         v-model="params.socialName"
                         is-outlined
                     />
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 63f5149e8..0cf984f20 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -78,7 +78,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.credit'),
+        label: t('customer.summary.credit'),
         name: 'credit',
         columnFilter: {
             component: 'number',
@@ -116,7 +116,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.mobile'),
+        label: t('customer.summary.mobile'),
         name: 'mobile',
         cardVisible: true,
         columnFilter: {
@@ -163,17 +163,17 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.city'),
+        label: t('customer.summary.city'),
         name: 'city',
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.postcode'),
+        label: t('customer.summary.postcode'),
         name: 'postcode',
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.email'),
+        label: t('globals.params.email'),
         name: 'email',
         cardVisible: true,
     },
@@ -208,7 +208,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.payMethodFk'),
+        label: t('customer.summary.payMethodFk'),
         name: 'payMethodFk',
         columnFilter: {
             component: 'select',
@@ -251,7 +251,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.isActive'),
+        label: t('customer.summary.isActive'),
         name: 'isActive',
         chip: {
             color: null,
@@ -280,7 +280,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.isEqualizated'),
+        label: t('customer.summary.isEqualizated'),
         name: 'isEqualizated',
         create: true,
         columnFilter: {
@@ -326,7 +326,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.hasLcr'),
+        label: t('customer.summary.hasLcr'),
         name: 'hasLcr',
         columnFilter: {
             inWhere: true,
@@ -334,7 +334,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('customer.extendedList.tableVisibleColumns.hasCoreVnl'),
+        label: t('customer.summary.hasCoreVnl'),
         name: 'hasCoreVnl',
         columnFilter: {
             inWhere: true,
@@ -425,7 +425,7 @@ function handleLocation(data, location) {
             <VnSelect
                 url="Workers/search"
                 v-model="data.salesPersonFk"
-                :label="t('customer.basicData.salesPerson')"
+                :label="t('customer.summary.salesPerson')"
                 :params="{
                     departmentCodes: ['VT', 'shopping'],
                 }"
diff --git a/src/pages/Customer/locale/en.yml b/src/pages/Customer/locale/en.yml
index 545c3f274..07ec53964 100644
--- a/src/pages/Customer/locale/en.yml
+++ b/src/pages/Customer/locale/en.yml
@@ -1,21 +1,5 @@
-customerFilter:
-    filter:
-        name: Name
-        socialName: Social name
 customer:
-    list:
-        phone: Phone
-        email: Email
-        customerOrders: Display customer orders
-        moreOptions: More options
     card:
-        customerList: Customer list
-        customerId: Claim ID
-        salesPerson: Sales person
-        credit: Credit
-        risk: Risk
-        securedCredit: Secured credit
-        payMethod: Pay method
         debt: Debt
         isFrozen: Customer frozen
         hasDebt: Customer has debt
@@ -23,9 +7,7 @@ customer:
         notChecked: Customer no checked
         webAccountInactive: Web account inactive
         noWebAccess: Web access is disabled
-        businessType: Business type
         passwordRequirements: 'The password must have at least { length } length characters, {nAlpha} alphabetic characters, {nUpper} capital letters, {nDigits} digits and {nPunct} symbols (Ex: $%&.)\n'
-        businessTypeFk: Business type
     summary:
         basicData: Basic data
         fiscalAddress: Fiscal address
@@ -37,9 +19,7 @@ customer:
         customerId: Customer ID
         name: Name
         contact: Contact
-        phone: Phone
         mobile: Mobile
-        email: Email
         salesPerson: Sales person
         contactChannel: Contact channel
         socialName: Social name
@@ -63,7 +43,6 @@ customer:
         hasB2BVnl: Has B2B VNL
         addressName: Address name
         addressCity: City
-        addressStreet: Street
         username: Username
         webAccess: Web access
         totalGreuge: Total greuge
@@ -92,45 +71,27 @@ customer:
         goToLines: Go to lines
     basicData:
         socialName: Fiscal name
-        businessType: Business type
-        contact: Contact
         youCanSaveMultipleEmails: You can save multiple emails
-        email: Email
-        phone: Phone
-        mobile: Mobile
-        salesPerson: Sales person
-        contactChannel: Contact channel
         previousClient: Previous client
     extendedList:
         tableVisibleColumns:
             id: Identifier
-            name: Name
             socialName: Social name
             fi: Tax number
             salesPersonFk: Salesperson
-            credit: Credit
             creditInsurance: Credit insurance
             phone: Phone
-            mobile: Mobile
             street: Street
             countryFk: Country
             provinceFk: Province
-            city: City
-            postcode: Postcode
-            email: Email
             created: Created
             businessTypeFk: Business type
-            payMethodFk: Billing data
             sageTaxTypeFk: Sage tax type
             sageTransactionTypeFk: Sage tr. type
-            isActive: Active
             isVies: Vies
             isTaxDataChecked: Verified data
-            isEqualizated: Is equalizated
             isFreezed: Freezed
             hasToInvoice: Invoice
             hasToInvoiceByAddress: Invoice by address
             isToBeMailed: Mailing
-            hasLcr: Received LCR
-            hasCoreVnl: VNL core received
             hasSepaVnl: VNL B2B received
diff --git a/src/pages/Customer/locale/es.yml b/src/pages/Customer/locale/es.yml
index 451784425..36a266497 100644
--- a/src/pages/Customer/locale/es.yml
+++ b/src/pages/Customer/locale/es.yml
@@ -1,22 +1,7 @@
 Search customer: Buscar cliente
 You can search by customer id or name: Puedes buscar por id o nombre del cliente
-customerFilter:
-    filter:
-        name: Nombre
-        socialName: Razón Social
 customer:
-    list:
-        phone: Teléfono
-        email: Email
-        customerOrders: Mostrar órdenes del cliente
-        moreOptions: Más opciones
     card:
-        customerId: ID cliente
-        salesPerson: Comercial
-        credit: Crédito
-        risk: Riesgo
-        securedCredit: Crédito asegurado
-        payMethod: Método de pago
         debt: Riesgo
         isFrozen: Cliente congelado
         hasDebt: Cliente con riesgo
@@ -24,9 +9,7 @@ customer:
         notChecked: Cliente no comprobado
         webAccountInactive: Sin acceso web
         noWebAccess: El acceso web está desactivado
-        businessType: Tipo de negocio
         passwordRequirements: 'La contraseña debe tener al menos { length } caracteres de longitud, {nAlpha} caracteres alfabéticos, {nUpper} letras mayúsculas, {nDigits} dígitos y {nPunct} símbolos (Ej: $%&.)'
-        businessTypeFk: Tipo de negocio
     summary:
         basicData: Datos básicos
         fiscalAddress: Dirección fiscal
@@ -38,9 +21,7 @@ customer:
         customerId: ID cliente
         name: Nombre
         contact: Contacto
-        phone: Teléfono
         mobile: Móvil
-        email: Email
         salesPerson: Comercial
         contactChannel: Canal de contacto
         socialName: Razón social
@@ -64,7 +45,6 @@ customer:
         hasB2BVnl: Recibido B2B VNL
         addressName: Nombre de la dirección
         addressCity: Ciudad
-        addressStreet: Calle
         username: Usuario
         webAccess: Acceso web
         totalGreuge: Greuge total
@@ -93,45 +73,27 @@ customer:
         goToLines: Ir a líneas
     basicData:
         socialName: Nombre fiscal
-        businessType: Tipo de negocio
-        contact: Contacto
         youCanSaveMultipleEmails: Puede guardar varios correos electrónicos encadenándolos mediante comas sin espacios{','} ejemplo{':'} user{'@'}dominio{'.'}com, user2{'@'}dominio{'.'}com siendo el primer correo electrónico el principal
-        email: Email
-        phone: Teléfono
-        mobile: Móvil
-        salesPerson: Comercial
-        contactChannel: Canal de contacto
         previousClient: Cliente anterior
     extendedList:
         tableVisibleColumns:
             id: Identificador
-            name: Nombre
             socialName: Razón social
             fi: NIF / CIF
             salesPersonFk: Comercial
-            credit: Crédito
             creditInsurance: Crédito asegurado
             phone: Teléfono
-            mobile: Móvil
             street: Dirección fiscal
             countryFk: País
             provinceFk: Provincia
-            city: Población
-            postcode: Código postal
-            email: Email
             created: Fecha creación
             businessTypeFk: Tipo de negocio
-            payMethodFk: Forma de pago
             sageTaxTypeFk: Tipo de impuesto Sage
             sageTransactionTypeFk: Tipo tr. sage
-            isActive: Activo
             isVies: Vies
             isTaxDataChecked: Datos comprobados
-            isEqualizated: Recargo de equivalencias
             isFreezed: Congelado
             hasToInvoice: Factura
             hasToInvoiceByAddress: Factura por consigna
             isToBeMailed: Env. emails
-            hasLcr: Recibido LCR
-            hasCoreVnl: Recibido core VNL
             hasSepaVnl: Recibido B2B VNL

From 0e77d4b68f9f62d2516337179bb6ab5e7d98d33e Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 18 Oct 2024 10:40:40 +0200
Subject: [PATCH 046/207] refactor: refs #7132 account's module translations

---
 src/pages/Account/AccountCreate.vue           |  8 +--
 src/pages/Account/AccountFilter.vue           |  2 +-
 src/pages/Account/AccountLdap.vue             |  8 +--
 src/pages/Account/AccountSamba.vue            |  6 +--
 src/pages/Account/Alias/AliasCreateForm.vue   |  7 +--
 .../Account/Alias/Card/AliasBasicData.vue     |  4 +-
 .../Account/Alias/Card/AliasDescriptor.vue    |  2 +-
 src/pages/Account/Alias/Card/AliasSummary.vue |  4 +-
 src/pages/Account/Card/AccountBasicData.vue   |  2 +-
 src/pages/Account/Role/AccountRolesFilter.vue |  2 +-
 src/pages/Account/Role/Card/RoleBasicData.vue |  7 +--
 .../Account/Role/Card/RoleDescriptor.vue      |  2 +-
 src/pages/Account/Role/Card/RoleForm.vue      |  7 +--
 src/pages/Account/Role/Card/RoleSummary.vue   |  6 +--
 src/pages/Account/locale/en.yml               | 49 ++----------------
 src/pages/Account/locale/es.yml               | 50 ++-----------------
 16 files changed, 35 insertions(+), 131 deletions(-)

diff --git a/src/pages/Account/AccountCreate.vue b/src/pages/Account/AccountCreate.vue
index e584a1acd..6b7c049c8 100644
--- a/src/pages/Account/AccountCreate.vue
+++ b/src/pages/Account/AccountCreate.vue
@@ -37,7 +37,7 @@ const redirectToAccountBasicData = (_, { id }) => {
             <div class="column q-gutter-sm">
                 <VnInput
                     v-model="data.name"
-                    :label="t('account.create.name')"
+                    :label="t('globals.name')"
                     :rules="validate('VnUser.name')"
                 />
                 <VnInput
@@ -47,12 +47,12 @@ const redirectToAccountBasicData = (_, { id }) => {
                 />
                 <VnInput
                     v-model="data.email"
-                    :label="t('account.create.email')"
+                    :label="t('globals.params.email')"
                     type="email"
                     :rules="validate('VnUser.email')"
                 />
                 <VnSelect
-                    :label="t('account.create.role')"
+                    :label="t('account.card.role')"
                     v-model="data.roleFk"
                     :options="rolesOptions"
                     option-value="id"
@@ -63,7 +63,7 @@ const redirectToAccountBasicData = (_, { id }) => {
                 />
                 <VnInput
                     v-model="data.password"
-                    :label="t('account.create.password')"
+                    :label="t('ldap.password')"
                     type="password"
                     :rules="validate('VnUser.password')"
                 />
diff --git a/src/pages/Account/AccountFilter.vue b/src/pages/Account/AccountFilter.vue
index 1775aa06b..22c167d43 100644
--- a/src/pages/Account/AccountFilter.vue
+++ b/src/pages/Account/AccountFilter.vue
@@ -44,7 +44,7 @@ const rolesOptions = ref([]);
             <QItem class="q-my-sm">
                 <QItemSection>
                     <VnInput
-                        :label="t('account.card.name')"
+                        :label="t('globals.name')"
                         v-model="params.name"
                         lazy-rules
                         is-outlined
diff --git a/src/pages/Account/AccountLdap.vue b/src/pages/Account/AccountLdap.vue
index 7b8433e73..84d8f1cde 100644
--- a/src/pages/Account/AccountLdap.vue
+++ b/src/pages/Account/AccountLdap.vue
@@ -102,11 +102,11 @@ onMounted(async () => await getInitialLdapConfig());
                 <QBtn
                     class="q-ml-none"
                     color="primary"
-                    :label="t('ldap.testConnection')"
+                    :label="t('account.card.testConnection')"
                     @click="onTestConection()"
                 >
                     <QTooltip>
-                        {{ t('ldap.testConnection') }}
+                        {{ t('account.card.testConnection') }}
                     </QTooltip>
                 </QBtn>
             </template>
@@ -114,7 +114,7 @@ onMounted(async () => await getInitialLdapConfig());
                 <VnRow class="row q-gutter-md">
                     <div class="col">
                         <QCheckbox
-                            :label="t('ldap.enableSync')"
+                            :label="t('account.card.enableSync')"
                             v-model="data.hasData"
                             @update:model-value="($event) => (hasData = $event)"
                             :toggle-indeterminate="false"
@@ -146,7 +146,7 @@ onMounted(async () => await getInitialLdapConfig());
                     />
                     <VnInput :label="t('ldap.userDN')" clearable v-model="data.userDn" />
                     <VnInput
-                        :label="t('ldap.groupDN')"
+                        :label="t('account.card.groupDN')"
                         clearable
                         v-model="data.groupDn"
                     />
diff --git a/src/pages/Account/AccountSamba.vue b/src/pages/Account/AccountSamba.vue
index 7af9f4364..15b886f27 100644
--- a/src/pages/Account/AccountSamba.vue
+++ b/src/pages/Account/AccountSamba.vue
@@ -110,12 +110,12 @@ onMounted(async () => await getInitialSambaConfig());
                 <QBtn
                     class="q-ml-none"
                     color="primary"
-                    :label="t('samba.testConnection')"
+                    :label="t('account.card.testConnection')"
                     :disable="formModel.hasChanges"
                     @click="onTestConection()"
                 >
                     <QTooltip>
-                        {{ t('samba.testConnection') }}
+                        {{ t('account.card.testConnection') }}
                     </QTooltip>
                 </QBtn>
             </template>
@@ -123,7 +123,7 @@ onMounted(async () => await getInitialSambaConfig());
                 <VnRow class="row q-gutter-md">
                     <div class="col">
                         <QCheckbox
-                            :label="t('samba.enableSync')"
+                            :label="t('account.card.enableSync')"
                             v-model="data.hasData"
                             @update:model-value="($event) => (hasData = $event)"
                             :toggle-indeterminate="false"
diff --git a/src/pages/Account/Alias/AliasCreateForm.vue b/src/pages/Account/Alias/AliasCreateForm.vue
index b21099555..e401b6d54 100644
--- a/src/pages/Account/Alias/AliasCreateForm.vue
+++ b/src/pages/Account/Alias/AliasCreateForm.vue
@@ -36,15 +36,12 @@ const onDataSaved = ({ id }) => {
         <template #form-inputs="{ data }">
             <VnRow>
                 <div class="col">
-                    <VnInput v-model="data.alias" :label="t('mailAlias.name')" />
+                    <VnInput v-model="data.alias" :label="t('globals.name')" />
                 </div>
             </VnRow>
             <VnRow>
                 <div class="col">
-                    <VnInput
-                        v-model="data.description"
-                        :label="t('mailAlias.description')"
-                    />
+                    <VnInput v-model="data.description" :label="t('role.description')" />
                 </div>
             </VnRow>
         </template>
diff --git a/src/pages/Account/Alias/Card/AliasBasicData.vue b/src/pages/Account/Alias/Card/AliasBasicData.vue
index ba940cda5..c78dfb4df 100644
--- a/src/pages/Account/Alias/Card/AliasBasicData.vue
+++ b/src/pages/Account/Alias/Card/AliasBasicData.vue
@@ -11,8 +11,8 @@ const { t } = useI18n();
     <FormModel model="Alias">
         <template #form="{ data }">
             <div class="column q-gutter-y-md">
-                <VnInput v-model="data.alias" :label="t('mailAlias.name')" />
-                <VnInput v-model="data.description" :label="t('mailAlias.description')" />
+                <VnInput v-model="data.alias" :label="t('globals.name')" />
+                <VnInput v-model="data.description" :label="t('role.description')" />
                 <QCheckbox :label="t('mailAlias.isPublic')" v-model="data.isPublic" />
             </div>
         </template>
diff --git a/src/pages/Account/Alias/Card/AliasDescriptor.vue b/src/pages/Account/Alias/Card/AliasDescriptor.vue
index 963f84547..713cecf75 100644
--- a/src/pages/Account/Alias/Card/AliasDescriptor.vue
+++ b/src/pages/Account/Alias/Card/AliasDescriptor.vue
@@ -71,7 +71,7 @@ const removeAlias = () => {
             </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('mailAlias.description')" :value="entity.description" />
+            <VnLv :label="t('role.description')" :value="entity.description" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Account/Alias/Card/AliasSummary.vue b/src/pages/Account/Alias/Card/AliasSummary.vue
index b2dc1f0fc..1f76fe7c2 100644
--- a/src/pages/Account/Alias/Card/AliasSummary.vue
+++ b/src/pages/Account/Alias/Card/AliasSummary.vue
@@ -42,8 +42,8 @@ const entityId = computed(() => $props.id || route.params.id);
                         <QIcon name="open_in_new" />
                     </router-link>
                 </QCardSection>
-                <VnLv :label="t('mailAlias.id')" :value="alias.id" />
-                <VnLv :label="t('mailAlias.description')" :value="alias.description" />
+                <VnLv :label="t('role.id')" :value="alias.id" />
+                <VnLv :label="t('role.description')" :value="alias.description" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Card/AccountBasicData.vue b/src/pages/Account/Card/AccountBasicData.vue
index f1cdaf9df..e6c9da6fe 100644
--- a/src/pages/Account/Card/AccountBasicData.vue
+++ b/src/pages/Account/Card/AccountBasicData.vue
@@ -36,7 +36,7 @@ watch(
             <div class="q-gutter-y-sm">
                 <VnInput v-model="data.name" :label="t('account.card.nickname')" />
                 <VnInput v-model="data.nickname" :label="t('account.card.alias')" />
-                <VnInput v-model="data.email" :label="t('account.card.email')" />
+                <VnInput v-model="data.email" :label="t('globals.params.email')" />
                 <VnSelect
                     url="Languages"
                     v-model="data.lang"
diff --git a/src/pages/Account/Role/AccountRolesFilter.vue b/src/pages/Account/Role/AccountRolesFilter.vue
index 8340b965d..ff4411897 100644
--- a/src/pages/Account/Role/AccountRolesFilter.vue
+++ b/src/pages/Account/Role/AccountRolesFilter.vue
@@ -29,7 +29,7 @@ const props = defineProps({
             <QItem class="q-my-sm">
                 <QItemSection>
                     <VnInput
-                        :label="t('role.name')"
+                        :label="t('globals.name')"
                         v-model="params.name"
                         lazy-rules
                         is-outlined
diff --git a/src/pages/Account/Role/Card/RoleBasicData.vue b/src/pages/Account/Role/Card/RoleBasicData.vue
index 56f4f0c27..1de9ff387 100644
--- a/src/pages/Account/Role/Card/RoleBasicData.vue
+++ b/src/pages/Account/Role/Card/RoleBasicData.vue
@@ -12,15 +12,12 @@ const { t } = useI18n();
         <template #form="{ data }">
             <VnRow>
                 <div class="col">
-                    <VnInput v-model="data.name" :label="t('role.card.name')" />
+                    <VnInput v-model="data.name" :label="t('globals.name')" />
                 </div>
             </VnRow>
             <VnRow>
                 <div class="col">
-                    <VnInput
-                        v-model="data.description"
-                        :label="t('role.card.description')"
-                    />
+                    <VnInput v-model="data.description" :label="t('role.description')" />
                 </div>
             </VnRow>
         </template>
diff --git a/src/pages/Account/Role/Card/RoleDescriptor.vue b/src/pages/Account/Role/Card/RoleDescriptor.vue
index e4af3ed13..af018565a 100644
--- a/src/pages/Account/Role/Card/RoleDescriptor.vue
+++ b/src/pages/Account/Role/Card/RoleDescriptor.vue
@@ -58,7 +58,7 @@ const removeRole = async () => {
             </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('role.card.description')" :value="entity.description" />
+            <VnLv :label="t('role.description')" :value="entity.description" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Account/Role/Card/RoleForm.vue b/src/pages/Account/Role/Card/RoleForm.vue
index 382639beb..09a098085 100644
--- a/src/pages/Account/Role/Card/RoleForm.vue
+++ b/src/pages/Account/Role/Card/RoleForm.vue
@@ -22,15 +22,12 @@ const { t } = useI18n();
         <template #form-inputs="{ data }">
             <VnRow>
                 <div class="col">
-                    <VnInput v-model="data.name" :label="t('role.card.name')" />
+                    <VnInput v-model="data.name" :label="t('globals.name')" />
                 </div>
             </VnRow>
             <VnRow>
                 <div class="col">
-                    <VnInput
-                        v-model="data.description"
-                        :label="t('role.card.description')"
-                    />
+                    <VnInput v-model="data.description" :label="t('role.description')" />
                 </div>
             </VnRow>
         </template>
diff --git a/src/pages/Account/Role/Card/RoleSummary.vue b/src/pages/Account/Role/Card/RoleSummary.vue
index 76c72e947..fef85f919 100644
--- a/src/pages/Account/Role/Card/RoleSummary.vue
+++ b/src/pages/Account/Role/Card/RoleSummary.vue
@@ -44,9 +44,9 @@ const filter = {
                         <QIcon name="open_in_new" />
                     </a>
                 </QCardSection>
-                <VnLv :label="t('role.card.id')" :value="role.id" />
-                <VnLv :label="t('role.card.name')" :value="role.name" />
-                <VnLv :label="t('role.card.description')" :value="role.description" />
+                <VnLv :label="t('role.id')" :value="role.id" />
+                <VnLv :label="t('globals.name')" :value="role.name" />
+                <VnLv :label="t('role.description')" :value="role.description" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/locale/en.yml b/src/pages/Account/locale/en.yml
index fe8707eb8..f2f563923 100644
--- a/src/pages/Account/locale/en.yml
+++ b/src/pages/Account/locale/en.yml
@@ -1,32 +1,15 @@
 account:
-    pageTitles:
-        users: Users
-        list: Users
-        roles: Roles
-        alias: Mail aliasses
-        accounts: Accounts
-        ldap: LDAP
-        samba: Samba
-        acls: ACLs
-        connections: Connections
-        inheritedRoles: Inherited Roles
-        subRoles: Sub Roles
-        newRole: New role
-        privileges: Privileges
-        mailAlias: Mail Alias
-        mailForwarding: Mail Forwarding
-        accountCreate: New user
-        aliasUsers: Users
     card:
-        name: Name
         nickname: User
         role: Role
-        email: Email
         alias: Alias
         lang: Language
         roleFk: Role
         newUser: New user
         ticketTracking: Ticket tracking
+        enableSync: Habilitar sincronización
+        groupDN: DN grupos
+        testConnection: Probar conexión
         privileges:
             delegate: Can delegate privileges
         enabled: Account enabled!
@@ -74,11 +57,7 @@ account:
     search: Search user
     searchInfo: You can search by id, name or nickname
     create:
-        name: Name
         nickname: Nickname
-        email: Email
-        role: Role
-        password: Password
         active: Active
     mailForwarding:
         forwardingMail: Forward email
@@ -86,50 +65,30 @@ account:
         enableMailForwarding: Enable mail forwarding
         mailInputInfo: All emails will be forwarded to the specified address.
 role:
-    pageTitles:
-        inheritedRoles: Inherited Roles
-        subRoles: Sub Roles
-    card:
-        description: Description
-        id: Id
-        name: Name
     newRole: New role
     searchRoles: Search role
     searchInfo: Search role by id or name
-    name: Name
     description: Description
     id: Id
 mailAlias:
-    pageTitles:
-        aliasUsers: Users
     search: Search mail alias
     searchInfo: Search alias by id or name
-    alias: Alias
-    description: Description
-    id: Id
     newAlias: New alias
-    name: Name
     isPublic: Public
 ldap:
-    enableSync: Enable synchronization
     server: Server
     rdn: RDN
     userDN: User DN
     filter: Filter
-    groupDN: Group DN
-    testConnection: Test connection
     success: LDAP connection established!
     password: Password
 samba:
-    enableSync: Enable synchronization
     domainController: Domain controller
     domainAD: AD domain
     userAD: AD user
-    groupDN: Group DN
     passwordAD: AD password
     domainPart: User DN (without domain part)
     verifyCertificate: Verify certificate
-    testConnection: Test connection
     success: Samba connection established!
 accounts:
     homedir: Homedir base
@@ -147,8 +106,6 @@ connections:
     created: Created
     killSession: Kill session
 acls:
-    role: Role
-    accessType: Access type
     permissions: Permission
     search: Search acls
     searchInfo: Search acls by model name
diff --git a/src/pages/Account/locale/es.yml b/src/pages/Account/locale/es.yml
index 112ffe9cc..ba559f2c3 100644
--- a/src/pages/Account/locale/es.yml
+++ b/src/pages/Account/locale/es.yml
@@ -1,27 +1,7 @@
 account:
-    pageTitles:
-        users: Usuarios
-        list: Usuarios
-        roles: Roles
-        alias: Alias de correo
-        accounts: Cuentas
-        ldap: LDAP
-        samba: Samba
-        acls: ACLs
-        connections: Conexiones
-        inheritedRoles: Roles heredados
-        newRole: Nuevo rol
-        subRoles: Subroles
-        privileges: Privilegios
-        mailAlias: Alias de correo
-        mailForwarding: Reenvío de correo
-        accountCreate: Nuevo usuario
-        aliasUsers: Usuarios
     card:
         nickname: Usuario
-        name: Nombre
         role: Rol
-        email: Mail
         alias: Alias
         lang: Idioma
         roleFk: Rol
@@ -33,6 +13,9 @@ account:
         deactivated: ¡Usuario desactivado!
         newUser: Nuevo usuario
         twoFactor: Doble factor
+        enableSync: Habilitar sincronización
+        groupDN: DN grupos
+        testConnection: Probar conexión
         privileges:
             delegate: Puede delegar privilegios
         actions:
@@ -73,11 +56,7 @@ account:
     search: Buscar usuario
     searchInfo: Puedes buscar por id, nombre o usuario
     create:
-        name: Nombre
         nickname: Nombre mostrado
-        email: Email
-        role: Rol
-        password: Contraseña
         active: Activo
     mailForwarding:
         forwardingMail: Dirección de reenvío
@@ -85,51 +64,30 @@ account:
         enableMailForwarding: Habilitar redirección de correo
         mailInputInfo: Todos los correos serán reenviados a la dirección especificada, no se mantendrá copia de los mismos en el buzón del usuario.
 role:
-    pageTitles:
-        inheritedRoles: Roles heredados
-        subRoles: Subroles
-        newRole: Nuevo rol
-    card:
-        description: Descripción
-        id: Id
-        name: Nombre
     newRole: Nuevo rol
     searchRoles: Buscar roles
     searchInfo: Buscar rol por id o nombre
-    name: Nombre
     description: Descripción
     id: Id
 mailAlias:
-    pageTitles:
-        aliasUsers: Usuarios
     search: Buscar alias de correo
     searchInfo: Buscar alias por id o nombre
-    alias: Alias
-    description: Descripción
-    id: Id
     newAlias: Nuevo alias
-    name: Nombre
     isPublic: Público
 ldap:
     password: Contraseña
-    enableSync: Habilitar sincronización
     server: Servidor
     rdn: RDN
     userDN: DN usuarios
     filter: Filtro
-    groupDN: DN grupos
-    testConnection: Probar conexión
     success: ¡Conexión con LDAP establecida!
 samba:
-    enableSync: Habilitar sincronización
     domainController: Controlador de dominio
     domainAD: Dominio AD
-    groupDN: DN grupos
     userAD: Usuario AD
     passwordAD: Contraseña AD
     domainPart: DN usuarios (sin la parte del dominio)
     verifyCertificate: Verificar certificado
-    testConnection: Probar conexión
     success: ¡Conexión con Samba establecida!
 accounts:
     homedir: Directorio base para carpetas de usuario
@@ -147,8 +105,6 @@ connections:
     created: Creado
     killSession: Matar sesión
 acls:
-    role: Rol
-    accessType: Tipo de acceso
     permissions: Permiso
     search: Buscar acls
     searchInfo: Buscar acls por nombre

From 89cb9aacec0ebbca0b539fbfa69586e65ed45f15 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 18 Oct 2024 12:54:21 +0200
Subject: [PATCH 047/207] refactor: refs #7132 1st wave of changes in global
 translations files

---
 src/components/FilterTravelForm.vue           |  4 +-
 src/components/common/VnDms.vue               |  2 +-
 src/i18n/locale/en.yml                        | 71 +------------------
 src/i18n/locale/es.yml                        | 68 ------------------
 .../Department/Card/DepartmentBasicData.vue   |  4 +-
 .../Department/Card/DepartmentSummary.vue     |  6 +-
 src/pages/Entry/Card/EntryBasicData.vue       |  5 +-
 src/pages/Entry/Card/EntryBuys.vue            |  5 +-
 src/pages/Entry/Card/EntryBuysImport.vue      |  7 +-
 src/pages/Entry/Card/EntrySummary.vue         |  6 +-
 src/pages/Entry/EntryLatestBuys.vue           |  8 +--
 src/pages/Entry/EntryList.vue                 |  2 +-
 .../InvoiceOut/Card/InvoiceOutSummary.vue     |  2 +-
 .../InvoiceOutNegativeBasesFilter.vue         |  6 +-
 src/pages/Item/Card/ItemSummary.vue           |  4 +-
 src/pages/Item/ItemRequest.vue                |  2 +-
 src/pages/Order/Card/OrderSummary.vue         |  6 +-
 .../Shelving/Card/ShelvingDescriptor.vue      |  2 +-
 src/pages/Shelving/Card/ShelvingForm.vue      |  2 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |  2 +-
 .../Supplier/Card/SupplierConsumption.vue     |  6 +-
 src/pages/Supplier/Card/SupplierSummary.vue   |  2 +-
 src/pages/Ticket/Card/TicketDescriptor.vue    |  4 +-
 src/pages/Ticket/Card/TicketSummary.vue       | 17 ++---
 src/pages/Travel/Card/TravelBasicData.vue     |  7 +-
 src/pages/Travel/Card/TravelSummary.vue       |  2 +-
 src/pages/Travel/Card/TravelThermographs.vue  |  2 +-
 .../Travel/Card/TravelThermographsForm.vue    |  4 +-
 src/pages/Travel/TravelList.vue               |  2 +-
 src/pages/Wagon/WagonCreate.vue               |  6 +-
 src/pages/Wagon/WagonList.vue                 |  2 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |  2 +-
 src/pages/Worker/Card/WorkerFormation.vue     |  2 +-
 src/pages/Worker/Card/WorkerMedical.vue       |  4 +-
 src/pages/Worker/Card/WorkerSummary.vue       |  4 +-
 35 files changed, 61 insertions(+), 219 deletions(-)

diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue
index c84772d9b..841a55bba 100644
--- a/src/components/FilterTravelForm.vue
+++ b/src/components/FilterTravelForm.vue
@@ -70,7 +70,7 @@ const tableColumns = computed(() => [
             warehousesOptions.value.find((warehouse) => warehouse.id === val).name,
     },
     {
-        label: t('entry.basicData.shipped'),
+        label: t('globals.shipped'),
         name: 'shipped',
         field: 'shipped',
         align: 'left',
@@ -170,7 +170,7 @@ const selectTravel = ({ id }) => {
                     v-model="travelFilterParams.warehouseInFk"
                 />
                 <VnInputDate
-                    :label="t('entry.basicData.shipped')"
+                    :label="t('globals.shipped')"
                     v-model="travelFilterParams.shipped"
                 />
                 <VnInputDate
diff --git a/src/components/common/VnDms.vue b/src/components/common/VnDms.vue
index 920b7f137..d2b40d7d6 100644
--- a/src/components/common/VnDms.vue
+++ b/src/components/common/VnDms.vue
@@ -158,7 +158,7 @@ function addDefaultData(data) {
                 />
                 <QFile
                     ref="inputFileRef"
-                    :label="t('entry.buys.file')"
+                    :label="t('globals.file')"
                     v-model="dms.files"
                     :multiple="false"
                     :accept="allowedContentTypes"
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index b73395df2..f4d258585 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -300,8 +300,6 @@ globals:
         salesPersonFk: Sales person
         warehouseFk: Warehouse
         provinceFk: Province
-        from: From
-        To: To
         stateFk: State
         departmentFk: Department
         email: Email
@@ -328,8 +326,7 @@ login:
     loginError: Invalid username or password
     fieldRequired: This field is required
     twoFactorRequired: Two-factor verification required
-twoFactor:
-    code: Code
+twoFactorRequired:
     validate: Validate
     insert: Enter the verification code
     explanation: >-
@@ -357,7 +354,6 @@ entry:
         ordered: Ordered
         tableVisibleColumns:
             id: Id
-            reference: Reference
             created: Creation
             supplierFk: Supplier
             isBooked: Booked
@@ -372,7 +368,6 @@ entry:
         commission: Commission
         currency: Currency
         company: Company
-        reference: Reference
         invoiceNumber: Invoice number
         ordered: Ordered
         confirmed: Confirmed
@@ -388,10 +383,8 @@ entry:
         travelWarehouseIn: Warehouse In
         travelReceived: Received
         buys: Buys
-        quantity: Quantity
         stickers: Stickers
         package: Package
-        weight: Weight
         packing: Packing
         grouping: Grouping
         buyingValue: Buying value
@@ -401,7 +394,6 @@ entry:
     basicData:
         supplier: Supplier
         travel: Travel
-        reference: Reference
         invoiceNumber: Invoice number
         company: Company
         currency: Currency
@@ -415,13 +407,11 @@ entry:
         agency: Agency
         warehouseOut: Warehouse Out
         warehouseIn: Warehouse In
-        shipped: Shipped
         landed: Landed
         id: ID
     buys:
         groupingPrice: Grouping price
         packingPrice: Packing price
-        reference: Reference
         observations: Observations
         item: Item
         size: Size
@@ -429,7 +419,6 @@ entry:
         grouping: Grouping
         buyingValue: Buying value
         packagingFk: Box
-        file: File
         name: Name
         producer: Producer
         type: Type
@@ -448,7 +437,6 @@ entry:
             itemFk: Item ID
             packing: Packing
             grouping: Grouping
-            quantity: Quantity
             size: Size
             tags: Tags
             type: Type
@@ -461,14 +449,12 @@ entry:
             buyingValue: Buying value
             freightValue: Freight value
             comissionValue: Commission value
-            description: Description
             packageValue: Package value
             isIgnored: Is ignored
             price2: Grouping
             price3: Packing
             minPrice: Min
             ektFk: Ekt
-            weight: Weight
             packagingFk: Package
             packingOut: Package out
             landing: Landing
@@ -476,17 +462,10 @@ entry:
             isRaid: Raid
 ticket:
     pageTitles:
-        tickets: Tickets
         list: List
-        ticketCreate: New ticket
         summary: Summary
-        basicData: Basic Data
-        boxing: Boxing
-        sms: Sms
-        notes: Notes
         sale: Sale
         dms: File management
-        volume: Volume
         observation: Notes
         ticketAdvance: Advance tickets
         futureTickets: Future tickets
@@ -495,17 +474,13 @@ ticket:
     list:
         nickname: Nickname
         state: State
-        shipped: Shipped
         landed: Landed
-        salesPerson: Sales person
         total: Total
     card:
         ticketId: Ticket ID
         state: State
         customerId: Customer ID
-        salesPerson: Sales person
         agency: Agency
-        shipped: Shipped
         warehouse: Warehouse
         customerCard: Customer card
         alias: Alias
@@ -521,7 +496,6 @@ ticket:
         notFound: No videos available
     summary:
         state: State
-        salesPerson: Sales person
         agency: Agency
         zone: Zone
         warehouse: Warehouse
@@ -543,7 +517,6 @@ ticket:
         item: Item
         visible: Visible
         available: Available
-        quantity: Quantity
         price: Price
         discount: Discount
         packing: Packing
@@ -559,12 +532,10 @@ ticket:
         requester: Requester
         atender: Atender
         request: Request
-        weight: Weight
         goTo: Go to
         summaryAmount: Summary
         purchaseRequest: Purchase request
         service: Service
-        description: Description
         attender: Attender
         ok: Ok
     create:
@@ -584,7 +555,6 @@ invoiceOut:
         company: Company
         dued: Due date
         shortDued: Due date
-        amount: Amount
     card:
         issued: Issued
         client: Client
@@ -604,7 +574,6 @@ invoiceOut:
         tickets: Tickets
         ticketId: Ticket id
         nickname: Alias
-        shipped: Shipped
         totalWithVat: Amount
     globalInvoices:
         errors:
@@ -625,13 +594,10 @@ invoiceOut:
             percentageText: '{getPercentage}% {getAddressNumber} of {getNAddresses}'
             pdfsNumberText: '{nPdfs} of {totalPdfs} PDFs'
     negativeBases:
-        from: From
-        to: To
         company: Company
         country: Country
         clientId: Client Id
         client: Client
-        amount: Amount
         base: Base
         ticketId: Ticket Id
         active: Active
@@ -646,13 +612,11 @@ shelving:
         priority: Priority
         newShelving: New Shelving
     summary:
-        code: Code
         parking: Parking
         priority: Priority
         worker: Worker
         recyclable: Recyclable
     basicData:
-        code: Code
         parking: Parking
         priority: Priority
         recyclable: Recyclable
@@ -694,7 +658,6 @@ order:
         phone: Phone
         createdFrom: Created From
         address: Address
-        notes: Notes
         subtotal: Subtotal
         total: Total
         vat: VAT
@@ -702,18 +665,14 @@ order:
         alias: Alias
         items: Items
         orderTicketList: Order Ticket List
-        details: Details
         item: Item
-        quantity: Quantity
         price: Price
         amount: Amount
 department:
     pageTitles:
-        basicData: Basic data
         department: Department
         summary: Summary
     name: Name
-    code: Code
     chat: Chat
     bossDepartment: Boss Department
     email: Email
@@ -728,20 +687,16 @@ worker:
     pageTitles:
         workers: Workers
         list: List
-        basicData: Basic data
         summary: Summary
-        notifications: Notifications
         workerCreate: New worker
         department: Department
         pda: PDA
-        notes: Notas
         dms: My documentation
         pbx: Private Branch Exchange
         log: Log
         calendar: Calendar
         timeControl: Time control
         locker: Locker
-        balance: Balance
         medical: Medical
     list:
         name: Name
@@ -754,7 +709,6 @@ worker:
         newWorker: New worker
     card:
         workerId: Worker ID
-        user: User
         name: Name
         email: Email
         phone: Phone
@@ -762,9 +716,7 @@ worker:
         active: Active
         warehouse: Warehouse
         agency: Agency
-        salesPerson: Sales person
     summary:
-        basicData: Basic data
         boss: Boss
         phoneExtension: Phone extension
         entPhone: Enterprise phone
@@ -820,16 +772,13 @@ worker:
             endDate: End date
             center: Training center
             invoice: Invoice
-            amount: Amount
             remark: Remark
             hasDiploma: Has diploma
     medical:
         tableVisibleColumns:
-            date: Date
             time: Hour
             center: Formation Center
             invoice: Invoice
-            amount: Amount
             isFit: Fit
             remark: Observations
     imageNotFound: Image not found
@@ -865,7 +814,6 @@ wagon:
         removeItem: Wagon removed successfully
     create:
         plate: Plate
-        volume: Volume
         type: Type
         label: Label
     warnings:
@@ -898,7 +846,6 @@ supplier:
             country: Country
     summary:
         responsible: Responsible
-        notes: Notes
         verified: Verified
         isActive: Is active
         billingData: Billing data
@@ -978,15 +925,12 @@ supplier:
         addRow: Add row
     consumption:
         entry: Entry
-        date: Date
-        reference: Reference
 travel:
     travelList:
         tableVisibleColumns:
             id: Id
             ref: Reference
             agency: Agency
-            shipped: Shipped
             landed: Landed
             shipHour: Shipment Hour
             landHour: Landing Hour
@@ -1017,29 +961,23 @@ travel:
         landedFrom: Landed from
         landedTo: Landed to
         continent: Continent out
-        totalEntries: Total entries
     basicData:
-        reference: Reference
         agency: Agency
-        shipped: Shipped
         landed: Landed
         warehouseOut: Warehouse Out
         warehouseIn: Warehouse In
         delivered: Delivered
         received: Received
     thermographs:
-        code: Code
         temperature: Temperature
         state: State
         destination: Destination
         created: Created
         thermograph: Thermograph
-        reference: Reference
         type: Type
         company: Company
         warehouse: Warehouse
         travelFileDescription: 'Travel id { travelId }'
-        file: File
 item:
     descriptor:
         item: Item
@@ -1056,7 +994,6 @@ item:
         id: Identifier
         grouping: Grouping
         packing: Packing
-        description: Description
         stems: Stems
         category: Category
         typeName: Type
@@ -1087,7 +1024,6 @@ item:
         origin: Origin
     buyRequest:
         ticketId: 'Ticket ID'
-        shipped: 'Shipped'
         requester: 'Requester'
         requested: 'Requested'
         price: 'Price'
@@ -1097,9 +1033,7 @@ item:
         concept: 'Concept'
         state: 'State'
     summary:
-        basicData: 'Basic data'
         otherData: 'Other data'
-        description: 'Description'
         tax: 'Tax'
         tags: 'Tags'
         botanical: 'Botanical'
@@ -1143,7 +1077,6 @@ components:
         salesPersonFk: Buyer
         supplierFk: Supplier
         from: From
-        to: To
         active: Is active
         visible: Is visible
         floramondo: Is floramondo
@@ -1151,7 +1084,6 @@ components:
     userPanel:
         copyToken: Token copied to clipboard
         settings: Settings
-        logOut: Log Out
         localWarehouse: Local warehouse
         localBank: Local bank
         localCompany: Local company
@@ -1159,7 +1091,6 @@ components:
         userCompany: User company
     smartCard:
         downloadFile: Download file
-        clone: Clone
         openCard: View
         openSummary: Summary
     cardDescriptor:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 2552c9549..a8d582c30 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -304,8 +304,6 @@ globals:
         salesPersonFk: Comercial
         warehouseFk: Almacén
         provinceFk: Provincia
-        from: Desde
-        To: Hasta
         stateFk: Estado
         departmentFk: Departamento
         email: Correo
@@ -333,7 +331,6 @@ login:
     fieldRequired: Este campo es obligatorio
     twoFactorRequired: Verificación de doble factor requerida
 twoFactor:
-    code: Código
     validate: Validar
     insert: Introduce el código de verificación
     explanation: Por favor introduce el código de verificación que te hemos enviado a tu email en los próximos 5 minutos
@@ -359,7 +356,6 @@ entry:
         ordered: Pedida
         tableVisibleColumns:
             id: Id
-            reference: Referencia
             created: Creación
             supplierFk: Proveedor
             isBooked: Asentado
@@ -374,7 +370,6 @@ entry:
         commission: Comisión
         currency: Moneda
         company: Empresa
-        reference: Referencia
         invoiceNumber: Núm. factura
         ordered: Pedida
         confirmed: Confirmada
@@ -390,10 +385,8 @@ entry:
         travelWarehouseIn: Alm. entrada
         travelReceived: Recibida
         buys: Compras
-        quantity: Cantidad
         stickers: Etiquetas
         package: Embalaje
-        weight: Peso
         packing: Packing
         grouping: Grouping
         buyingValue: Coste
@@ -403,7 +396,6 @@ entry:
     basicData:
         supplier: Proveedor
         travel: Envío
-        reference: Referencia
         invoiceNumber: Núm. factura
         company: Empresa
         currency: Moneda
@@ -417,13 +409,11 @@ entry:
         agency: Agencia
         warehouseOut: Alm. salida
         warehouseIn: Alm. entrada
-        shipped: F. envío
         landed: F. entrega
         id: ID
     buys:
         groupingPrice: Precio grouping
         packingPrice: Precio packing
-        reference: Referencia
         observations: Observaciónes
         item: Artículo
         size: Medida
@@ -431,7 +421,6 @@ entry:
         grouping: Grouping
         buyingValue: Coste
         packagingFk: Embalaje
-        file: Fichero
         name: Nombre
         producer: Productor
         type: Tipo
@@ -450,7 +439,6 @@ entry:
             itemFk: Id Artículo
             packing: packing
             grouping: Grouping
-            quantity: Cantidad
             size: Medida
             tags: Etiquetas
             type: Tipo
@@ -463,14 +451,12 @@ entry:
             buyingValue: Coste
             freightValue: Porte
             comissionValue: Comisión
-            description: Descripción
             packageValue: Embalaje
             isIgnored: Ignorado
             price2: Grouping
             price3: Packing
             minPrice: Min
             ektFk: Ekt
-            weight: Peso
             packagingFk: Embalaje
             packingOut: Embalaje envíos
             landing: Llegada
@@ -478,17 +464,9 @@ entry:
             isRaid: Redada
 ticket:
     pageTitles:
-        tickets: Tickets
         list: Listado
-        ticketCreate: Nuevo ticket
         summary: Resumen
-        basicData: Datos básicos
-        boxing: Encajado
-        sms: Sms
-        notes: Notas
-        sale: Lineas del pedido
         dms: Gestión documental
-        volume: Volumen
         observation: Notas
         ticketAdvance: Adelantar tickets
         futureTickets: Tickets a futuro
@@ -500,21 +478,16 @@ ticket:
         tracking: Estados
         components: Componentes
         pictures: Fotos
-        packages: Embalajes
     list:
         nickname: Alias
         state: Estado
-        shipped: Enviado
         landed: Entregado
-        salesPerson: Comercial
         total: Total
     card:
         ticketId: ID ticket
         state: Estado
         customerId: ID cliente
-        salesPerson: Comercial
         agency: Agencia
-        shipped: Enviado
         warehouse: Almacén
         customerCard: Ficha del cliente
         alias: Alias
@@ -530,7 +503,6 @@ ticket:
         notFound: No hay vídeos disponibles
     summary:
         state: Estado
-        salesPerson: Comercial
         agency: Agencia
         zone: Zona
         warehouse: Almacén
@@ -552,7 +524,6 @@ ticket:
         item: Artículo
         visible: Visible
         available: Disponible
-        quantity: Cantidad
         price: Precio
         discount: Descuento
         packing: Encajado
@@ -568,12 +539,10 @@ ticket:
         requester: Solicitante
         atender: Comprador
         request: Petición de compra
-        weight: Peso
         goTo: Ir a
         summaryAmount: Resumen
         purchaseRequest: Petición de compra
         service: Servicio
-        description: Descripción
         attender: Consignatario
     create:
         client: Cliente
@@ -592,7 +561,6 @@ invoiceOut:
         company: Empresa
         dued: Fecha vencimineto
         shortDued: F. vencimiento
-        amount: Importe
     card:
         issued: Fecha emisión
         client: Cliente
@@ -613,7 +581,6 @@ invoiceOut:
         tickets: Tickets
         ticketId: Id ticket
         nickname: Alias
-        shipped: F. envío
         totalWithVat: Importe
     globalInvoices:
         errors:
@@ -638,7 +605,6 @@ invoiceOut:
         country: País
         clientId: Id cliente
         client: Cliente
-        amount: Importe
         base: Base
         ticketId: Id ticket
         active: Activo
@@ -675,7 +641,6 @@ order:
         phone: Teléfono
         createdFrom: Creado desde
         address: Dirección
-        notes: Notas
         subtotal: Subtotal
         total: Total
         vat: IVA
@@ -683,9 +648,7 @@ order:
         alias: Alias
         items: Items
         orderTicketList: Tickets del pedido
-        details: Detalles
         item: Item
-        quantity: Cantidad
         price: Precio
         amount: Monto
 shelving:
@@ -694,13 +657,11 @@ shelving:
         priority: Prioridad
         newShelving: Nuevo Carro
     summary:
-        code: Código
         parking: Parking
         priority: Prioridad
         worker: Trabajador
         recyclable: Reciclable
     basicData:
-        code: Código
         parking: Parking
         priority: Prioridad
         recyclable: Reciclable
@@ -715,11 +676,9 @@ parking:
         label: Buscar parking...
 department:
     pageTitles:
-        basicData: Basic data
         department: Departamentos
         summary: Resumen
     name: Nombre
-    code: Código
     chat: Chat
     bossDepartment: Jefe de departamento
     email: Email
@@ -734,20 +693,16 @@ worker:
     pageTitles:
         workers: Trabajadores
         list: Listado
-        basicData: Datos básicos
         summary: Resumen
-        notifications: Notificaciones
         workerCreate: Nuevo trabajador
         department: Departamentos
         pda: PDA
-        notes: Notas
         dms: Mi documentación
         pbx: Centralita
         log: Historial
         calendar: Calendario
         timeControl: Control de horario
         locker: Taquilla
-        balance: Balance
         formation: Formación
         medical: Mutua
     list:
@@ -761,7 +716,6 @@ worker:
         newWorker: Nuevo trabajador
     card:
         workerId: ID Trabajador
-        user: Usuario
         name: Nombre
         email: Correo personal
         phone: Teléfono
@@ -769,9 +723,7 @@ worker:
         active: Activo
         warehouse: Almacén
         agency: Empresa
-        salesPerson: Comercial
     summary:
-        basicData: Datos básicos
         boss: Jefe
         phoneExtension: Extensión de teléfono
         entPhone: Teléfono de empresa
@@ -818,16 +770,13 @@ worker:
             endDate: Fecha Fin
             center: Centro Formación
             invoice: Factura
-            amount: Importe
             remark: Bonficado
             hasDiploma: Diploma
     medical:
         tableVisibleColumns:
-            date: Fecha
             time: Hora
             center: Centro de Formación
             invoice: Factura
-            amount: Importe
             isFit: Apto
             remark: Observaciones
     imageNotFound: No se ha encontrado la imagen
@@ -863,7 +812,6 @@ wagon:
         removeItem: Vagón borrado correctamente
     create:
         plate: Matrícula
-        volume: Volumen
         type: Tipo
         label: Etiqueta
     warnings:
@@ -895,7 +843,6 @@ supplier:
             country: País
     summary:
         responsible: Responsable
-        notes: Notas
         verified: Verificado
         isActive: Está activo
         billingData: Forma de pago
@@ -975,15 +922,12 @@ supplier:
         addRow: Añadir fila
     consumption:
         entry: Entrada
-        date: Fecha
-        reference: Referencia
 travel:
     travelList:
         tableVisibleColumns:
             id: Id
             ref: Referencia
             agency: Agencia
-            shipped: F.envío
             shipHour: Hora de envío
             landHour: Hora de llegada
             landed: F.entrega
@@ -1014,29 +958,23 @@ travel:
         landedFrom: Llegada desde
         landedTo: Llegada hasta
         continent: Cont. Salida
-        totalEntries: Ent. totales
     basicData:
-        reference: Referencia
         agency: Agencia
-        shipped: F. Envío
         landed: F. entrega
         warehouseOut: Alm. salida
         warehouseIn: Alm. entrada
         delivered: Enviada
         received: Recibida
     thermographs:
-        code: Código
         temperature: Temperatura
         state: Estado
         destination: Destino
         created: Fecha creación
         thermograph: Termógrafo
-        reference: Referencia
         type: Tipo
         company: Empresa
         warehouse: Almacén
         travelFileDescription: 'Id envío { travelId }'
-        file: Fichero
 item:
     descriptor:
         item: Artículo
@@ -1053,7 +991,6 @@ item:
         id: Identificador
         grouping: Grouping
         packing: Packing
-        description: Descripción
         stems: Tallos
         category: Reino
         typeName: Tipo
@@ -1083,9 +1020,7 @@ item:
         intrastat: Intrastat
         origin: Origen
     summary:
-        basicData: 'Datos básicos'
         otherData: 'Otros datos'
-        description: 'Descripción'
         tax: 'IVA'
         tags: 'Etiquetas'
         botanical: 'Botánico'
@@ -1114,7 +1049,6 @@ item:
         specie: 'Specie'
     buyRequest:
         ticketId: 'ID Ticket'
-        shipped: 'F. envío'
         requester: 'Solicitante'
         requested: 'Solicitado'
         price: 'Precio'
@@ -1146,7 +1080,6 @@ components:
     userPanel:
         copyToken: Token copiado al portapapeles
         settings: Configuración
-        logOut: Cerrar sesión
         localWarehouse: Almacén local
         localBank: Banco local
         localCompany: Empresa local
@@ -1154,7 +1087,6 @@ components:
         userCompany: Empresa del usuario
     smartCard:
         downloadFile: Descargar archivo
-        clone: Clonar
         openCard: Ficha
         openSummary: Detalles
         viewSummary: Vista previa
diff --git a/src/pages/Department/Card/DepartmentBasicData.vue b/src/pages/Department/Card/DepartmentBasicData.vue
index 141bb4159..384881792 100644
--- a/src/pages/Department/Card/DepartmentBasicData.vue
+++ b/src/pages/Department/Card/DepartmentBasicData.vue
@@ -28,8 +28,8 @@ const { t } = useI18n();
                 />
                 <VnInput
                     v-model="data.code"
-                    :label="t('department.code')"
-                    :rules="validate('department.code')"
+                    :label="t('globals.code')"
+                    :rules="validate('globals.code')"
                     clearable
                 />
             </VnRow>
diff --git a/src/pages/Department/Card/DepartmentSummary.vue b/src/pages/Department/Card/DepartmentSummary.vue
index ecbb39ed0..05a9e073e 100644
--- a/src/pages/Department/Card/DepartmentSummary.vue
+++ b/src/pages/Department/Card/DepartmentSummary.vue
@@ -50,11 +50,7 @@ onMounted(async () => {
                             :value="department.name"
                             dash
                         />
-                        <VnLv
-                            :label="t('department.code')"
-                            :value="department.code"
-                            dash
-                        />
+                        <VnLv :label="t('globals.code')" :value="department.code" dash />
                         <VnLv
                             :label="t('department.chat')"
                             :value="department.chatName"
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index b81b1db22..2a00bfd74 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -108,10 +108,7 @@ const onFilterTravelSelected = (formData, id) => {
                 </VnSelectDialog>
             </VnRow>
             <VnRow>
-                <VnInput
-                    v-model="data.reference"
-                    :label="t('entry.basicData.reference')"
-                />
+                <VnInput v-model="data.reference" :label="t('globals.reference')" />
             </VnRow>
             <VnRow>
                 <VnInput
diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue
index ff89faada..35972b85a 100644
--- a/src/pages/Entry/Card/EntryBuys.vue
+++ b/src/pages/Entry/Card/EntryBuys.vue
@@ -5,7 +5,6 @@ import { useI18n } from 'vue-i18n';
 import { QBtn } from 'quasar';
 
 import VnPaginate from 'src/components/ui/VnPaginate.vue';
-import FetchData from 'src/components/FetchData.vue';
 import VnSelect from 'components/common/VnSelect.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import FetchedTags from 'components/ui/FetchedTags.vue';
@@ -163,7 +162,7 @@ const entriesTableColumns = computed(() => {
             align: 'left',
         },
         {
-            label: t('entry.summary.quantity'),
+            label: t('globals.quantity'),
             field: 'quantity',
             name: 'quantity',
             align: 'left',
@@ -187,7 +186,7 @@ const entriesTableColumns = computed(() => {
             align: 'left',
         },
         {
-            label: t('entry.summary.weight'),
+            label: t('globals.weight'),
             field: 'weight',
             name: 'weight',
             align: 'left',
diff --git a/src/pages/Entry/Card/EntryBuysImport.vue b/src/pages/Entry/Card/EntryBuysImport.vue
index 8431e1096..36ca3b797 100644
--- a/src/pages/Entry/Card/EntryBuysImport.vue
+++ b/src/pages/Entry/Card/EntryBuysImport.vue
@@ -200,7 +200,7 @@ const redirectToBuysView = () => {
             <VnRow>
                 <QFile
                     ref="inputFileRef"
-                    :label="t('entry.buys.file')"
+                    :label="t('globals.file')"
                     v-model="importData.file"
                     :multiple="false"
                     accept=".json"
@@ -220,10 +220,7 @@ const redirectToBuysView = () => {
             </VnRow>
             <div v-if="importData.file">
                 <VnRow>
-                    <VnInput
-                        :label="t('entry.buys.reference')"
-                        v-model="importData.ref"
-                    />
+                    <VnInput :label="t('globals.reference')" v-model="importData.ref" />
                 </VnRow>
                 <VnRow>
                     <VnInput
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index 58a5c2e1b..0ed2e8a67 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -83,7 +83,7 @@ const tableColumnComponents = {
 const entriesTableColumns = computed(() => {
     return [
         {
-            label: t('entry.summary.quantity'),
+            label: t('globals.quantity'),
             field: 'quantity',
             name: 'quantity',
             align: 'left',
@@ -101,7 +101,7 @@ const entriesTableColumns = computed(() => {
             align: 'left',
         },
         {
-            label: t('entry.summary.weight'),
+            label: t('globals.weight'),
             field: 'weight',
             name: 'weight',
             align: 'left',
@@ -190,7 +190,7 @@ const fetchEntryBuys = async () => {
                     :value="entry.currency?.name"
                 />
                 <VnLv :label="t('entry.summary.company')" :value="entry.company.code" />
-                <VnLv :label="t('entry.summary.reference')" :value="entry.reference" />
+                <VnLv :label="t('globals.reference')" :value="entry.reference" />
                 <VnLv
                     :label="t('entry.summary.invoiceNumber')"
                     :value="entry.invoiceNumber"
diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue
index 61c430b23..756948182 100644
--- a/src/pages/Entry/EntryLatestBuys.vue
+++ b/src/pages/Entry/EntryLatestBuys.vue
@@ -47,12 +47,12 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.quantity'),
+        label: t('globals.quantity'),
         name: 'quantity',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.description'),
+        label: t('globals.description'),
         name: 'description',
     },
     {
@@ -82,7 +82,7 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.weightByPiece'),
+        label: t('globals.weightByPiece'),
         name: 'weightByPiece',
     },
     {
@@ -147,7 +147,7 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.weight'),
+        label: t('globals.weight'),
         name: 'weight',
     },
     {
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 6f7ff1935..e44e3891e 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -50,7 +50,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.reference'),
+        label: t('globals.reference'),
         name: 'reference',
         isTitle: true,
         component: 'input',
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
index e9d5a2f1f..83b1bf8a4 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
@@ -86,7 +86,7 @@ const ticketsColumns = ref([
     },
     {
         name: 'landed',
-        label: t('invoiceOut.summary.shipped'),
+        label: t('globals.shipped'),
         field: (row) => row.shipped,
         format: (value) => toDate(value),
         sortable: true,
diff --git a/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue b/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
index 94eab2aab..cf4c27e65 100644
--- a/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
+++ b/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
@@ -33,7 +33,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInputDate
                         v-model="params.from"
-                        :label="t('invoiceOut.negativeBases.from')"
+                        :label="t('globals.from')"
                         is-outlined
                     />
                 </QItemSection>
@@ -42,7 +42,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInputDate
                         v-model="params.to"
-                        :label="t('invoiceOut.negativeBases.to')"
+                        :label="t('globals.to')"
                         is-outlined
                     />
                 </QItemSection>
@@ -88,7 +88,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInputNumber
                         v-model="params.amount"
-                        :label="t('invoiceOut.negativeBases.amount')"
+                        :label="t('globals.amount')"
                         is-outlined
                     />
                 </QItemSection>
diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index 7b6015c30..dd2c0649b 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -55,7 +55,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
             <QCard class="vn-one">
                 <VnTitle
                     :url="getUrl(entityId, 'basic-data')"
-                    :text="t('item.summary.basicData')"
+                    :text="t('globals.summary.basicData')"
                 />
                 <VnLv :label="t('item.summary.name')" :value="item.name" />
                 <VnLv :label="t('item.summary.completeName')" :value="item.longName" />
@@ -126,7 +126,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
             <QCard class="vn-one" v-if="item.description">
                 <VnTitle
                     :url="getUrl(entityId, 'basic-data')"
-                    :text="t('item.summary.description')"
+                    :text="t('globals.description')"
                 />
                 <p v-text="item.description" />
             </QCard>
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 8a41bbe04..7dd961a35 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -47,7 +47,7 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('item.buyRequest.shipped'),
+        label: t('globals.shipped'),
         field: 'shipped',
         name: 'shipped',
         align: 'left',
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index 60358f744..ceacbc75b 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -35,7 +35,7 @@ const detailsColumns = ref([
     },
     {
         name: 'quantity',
-        label: t('order.summary.quantity'),
+        label: t('globals.quantity'),
         field: (row) => row?.quantity,
     },
     {
@@ -161,13 +161,13 @@ const detailsColumns = ref([
                     </VnLv>
                 </QCard>
                 <QCard>
-                    <VnTitle :text="t('order.summary.details')" />
+                    <VnTitle :text="t('globals.details')" />
                     <QTable :columns="detailsColumns" :rows="entity?.rows" flat>
                         <template #header="props">
                             <QTr :props="props">
                                 <QTh auto-width>{{ t('order.summary.item') }}</QTh>
                                 <QTh>{{ t('globals.description') }}</QTh>
-                                <QTh auto-width>{{ t('order.summary.quantity') }}</QTh>
+                                <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                                 <QTh auto-width>{{ t('order.summary.price') }}</QTh>
                                 <QTh auto-width>{{ t('order.summary.amount') }}</QTh>
                             </QTr>
diff --git a/src/pages/Shelving/Card/ShelvingDescriptor.vue b/src/pages/Shelving/Card/ShelvingDescriptor.vue
index 6beca6d88..30e807d20 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptor.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptor.vue
@@ -53,7 +53,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
         @on-fetch="setData"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('shelving.summary.code')" :value="entity.code" />
+            <VnLv :label="t('globals.code')" :value="entity.code" />
             <VnLv :label="t('shelving.summary.parking')" :value="entity.parking?.code" />
             <VnLv v-if="entity.worker" :label="t('shelving.summary.worker')">
                 <template #value>
diff --git a/src/pages/Shelving/Card/ShelvingForm.vue b/src/pages/Shelving/Card/ShelvingForm.vue
index dc0234c22..f69d427b0 100644
--- a/src/pages/Shelving/Card/ShelvingForm.vue
+++ b/src/pages/Shelving/Card/ShelvingForm.vue
@@ -58,7 +58,7 @@ const onSave = (shelving, newShelving) => {
             <VnRow>
                 <VnInput
                     v-model="data.code"
-                    :label="t('shelving.basicData.code')"
+                    :label="t('globals.code')"
                     :rules="validate('Shelving.code')"
                 />
                 <VnSelect
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index 94175b0c1..a196b1992 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -54,7 +54,7 @@ const filter = {
                         {{ t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </RouterLink>
-                    <VnLv :label="t('shelving.summary.code')" :value="entity.code" />
+                    <VnLv :label="t('globals.code')" :value="entity.code" />
                     <VnLv
                         :label="t('shelving.summary.parking')"
                         :value="entity.parking?.code"
diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue
index 8fa6a1e5c..fe1cec260 100644
--- a/src/pages/Supplier/Card/SupplierConsumption.vue
+++ b/src/pages/Supplier/Card/SupplierConsumption.vue
@@ -190,13 +190,11 @@ onMounted(async () => {
                         <span>{{ row.id }}</span>
                     </QTd>
                     <QTd no-hover>
-                        <span class="label">{{ t('supplier.consumption.date') }}: </span>
+                        <span class="label">{{ t('globals.date') }}: </span>
                         <span>{{ toDate(row.shipped) }}</span></QTd
                     >
                     <QTd colspan="6" no-hover>
-                        <span class="label"
-                            >{{ t('supplier.consumption.reference') }}:
-                        </span>
+                        <span class="label">{{ t('globals.reference') }}: </span>
                         <span>{{ row.invoiceNumber }}</span>
                     </QTd>
                 </QTr>
diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue
index 5791db1eb..6ffb95344 100644
--- a/src/pages/Supplier/Card/SupplierSummary.vue
+++ b/src/pages/Supplier/Card/SupplierSummary.vue
@@ -60,7 +60,7 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
                         />
                     </template>
                 </VnLv>
-                <VnLv :label="t('supplier.summary.notes')" class="q-mb-xs">
+                <VnLv :label="t('globals.notes')" class="q-mb-xs">
                     <template #value>
                         <span> {{ dashIfEmpty(supplier.note) }} </span>
                     </template>
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index 70fd9ab1e..af9021e36 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -135,7 +135,7 @@ function ticketFilter(ticket) {
                     </QBadge>
                 </template>
             </VnLv>
-            <VnLv :label="t('ticket.summary.salesPerson')">
+            <VnLv :label="t('globals.salesPerson')">
                 <template #value>
                     <VnUserLink
                         :name="entity.client?.salesPersonUser?.name"
@@ -144,7 +144,7 @@ function ticketFilter(ticket) {
                 </template>
             </VnLv>
             <VnLv
-                :label="t('ticket.card.shipped')"
+                :label="t('globals.shipped')"
                 :value="toDateTimeFormat(entity.shipped)"
             />
             <VnLv
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index af96c2724..ac2ae0509 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -142,7 +142,7 @@ function toTicketUrl(section) {
                         </QBadge>
                     </template>
                 </VnLv>
-                <VnLv :label="t('ticket.summary.salesPerson')">
+                <VnLv :label="t('globals.salesPerson')">
                     <template #value>
                         <VnUserLink
                             :name="entity.client?.salesPersonUser?.name"
@@ -200,10 +200,7 @@ function toTicketUrl(section) {
                         </span>
                     </template>
                 </VnLv>
-                <VnLv
-                    :label="t('ticket.summary.weight')"
-                    :value="dashIfEmpty(entity.weight)"
-                />
+                <VnLv :label="t('globals.weight')" :value="dashIfEmpty(entity.weight)" />
             </QCard>
             <QCard class="vn-one" style="flex: 2 1">
                 <VnTitle
@@ -313,7 +310,7 @@ function toTicketUrl(section) {
                             <QTh auto-width>{{ t('ticket.summary.item') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.visible') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.available') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
+                            <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                             <QTh auto-width>{{ t('globals.description') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.discount') }}</QTh>
@@ -476,7 +473,7 @@ function toTicketUrl(section) {
                         <QTr class="tr-header" :props="props">
                             <QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.package') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
+                            <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                         </QTr>
                     </template>
                     <template #body="props">
@@ -496,7 +493,7 @@ function toTicketUrl(section) {
                 <QTable :rows="ticket.services" flat style="text-align: center">
                     <template #header="props">
                         <QTr class="tr-header" :props="props">
-                            <QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
+                            <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                             <QTh auto-width>{{ t('globals.description') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.taxClass') }}</QTh>
@@ -524,11 +521,11 @@ function toTicketUrl(section) {
                 <QTable :rows="ticket.requests" flat style="text-align: center">
                     <template #header="props">
                         <QTr class="tr-header" :props="props">
-                            <QTh auto-width>{{ t('ticket.summary.description') }}</QTh>
+                            <QTh auto-width>{{ t('globals.description') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.requester') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.attender') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
+                            <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.item') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.ok') }}</QTh>
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index a3620a6ba..ca9caf82d 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -29,7 +29,7 @@ const agenciesOptions = ref([]);
     >
         <template #form="{ data }">
             <VnRow>
-                <VnInput v-model="data.ref" :label="t('travel.basicData.reference')" />
+                <VnInput v-model="data.ref" :label="t('globals.reference')" />
                 <VnSelect
                     :label="t('travel.basicData.agency')"
                     v-model="data.agencyModeFk"
@@ -41,10 +41,7 @@ const agenciesOptions = ref([]);
                 />
             </VnRow>
             <VnRow>
-                <VnInputDate
-                    v-model="data.shipped"
-                    :label="t('travel.basicData.shipped')"
-                />
+                <VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
                 <VnInputDate
                     v-model="data.landed"
                     :label="t('travel.basicData.landed')"
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 4be198493..d48ed2847 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -110,7 +110,7 @@ const entriesTableColumns = computed(() => {
 const thermographsTableColumns = computed(() => {
     return [
         {
-            label: t('travel.thermographs.code'),
+            label: t('globals.code'),
             field: 'thermographFk',
             name: 'thermographFk',
             align: 'left',
diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index e308243e3..96544a8ca 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -36,7 +36,7 @@ const thermographFilter = {
 const TableColumns = computed(() => {
     return [
         {
-            label: t('travel.thermographs.code'),
+            label: t('globals.code'),
             field: 'thermographFk',
             name: 'thermographFk',
             align: 'left',
diff --git a/src/pages/Travel/Card/TravelThermographsForm.vue b/src/pages/Travel/Card/TravelThermographsForm.vue
index 5e3ecdc3e..b70e93dfc 100644
--- a/src/pages/Travel/Card/TravelThermographsForm.vue
+++ b/src/pages/Travel/Card/TravelThermographsForm.vue
@@ -222,7 +222,7 @@ const onThermographCreated = async (data) => {
                 <VnRow>
                     <VnInput
                         v-model="thermographForm.reference"
-                        :label="t('travel.thermographs.reference')"
+                        :label="t('globals.reference')"
                     />
                     <VnSelect
                         :label="t('travel.thermographs.type')"
@@ -279,7 +279,7 @@ const onThermographCreated = async (data) => {
                 <VnRow>
                     <QFile
                         ref="inputFileRef"
-                        :label="t('travel.thermographs.file')"
+                        :label="t('globals.file')"
                         multiple
                         :accept="allowedContentTypes"
                         v-model="thermographForm.files"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index a8c0e69cb..7ea2b3f7a 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -100,7 +100,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'shipped',
-        label: t('travel.travelList.tableVisibleColumns.shipped'),
+        label: t('globals.shipped'),
         component: 'date',
         columnField: {
             component: null,
diff --git a/src/pages/Wagon/WagonCreate.vue b/src/pages/Wagon/WagonCreate.vue
index 411c36632..2ec0f4d55 100644
--- a/src/pages/Wagon/WagonCreate.vue
+++ b/src/pages/Wagon/WagonCreate.vue
@@ -111,12 +111,10 @@ function filterType(val, update) {
                     <QInput
                         filled
                         v-model="wagon.volume"
-                        :label="t('wagon.create.volume')"
+                        :label="t('wagon.list.volume')"
                         type="number"
                         min="0"
-                        :rules="[
-                            (val) => !!val || t('wagon.warnings.volumeNotEmpty'),
-                        ]"
+                        :rules="[(val) => !!val || t('wagon.warnings.volumeNotEmpty')]"
                     />
                     <QSelect
                         filled
diff --git a/src/pages/Wagon/WagonList.vue b/src/pages/Wagon/WagonList.vue
index 02e3b6d16..61679b933 100644
--- a/src/pages/Wagon/WagonList.vue
+++ b/src/pages/Wagon/WagonList.vue
@@ -129,7 +129,7 @@ async function remove(row) {
                 <VnInput
                     filled
                     v-model="data.volume"
-                    :label="t('wagon.create.volume')"
+                    :label="t('wagon.list.volume')"
                     type="number"
                     min="0"
                     :rules="[(val) => !!val || t('wagon.warnings.volumeNotEmpty')]"
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 1cb42bbfb..491105e09 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -138,7 +138,7 @@ const handlePhotoUpdated = (evt = false) => {
             </div>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('worker.card.user')" :value="entity.user?.name" />
+            <VnLv :label="t('globals.user')" :value="entity.user?.name" />
             <VnLv
                 :label="t('worker.card.email')"
                 :value="entity.user?.emailUser?.email"
diff --git a/src/pages/Worker/Card/WorkerFormation.vue b/src/pages/Worker/Card/WorkerFormation.vue
index c11dd019e..1f5b54c4a 100644
--- a/src/pages/Worker/Card/WorkerFormation.vue
+++ b/src/pages/Worker/Card/WorkerFormation.vue
@@ -77,7 +77,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'amount',
-        label: t('worker.formation.tableVisibleColumns.amount'),
+        label: t('globals.amount'),
         component: 'input',
         field: 'amount',
         create: true,
diff --git a/src/pages/Worker/Card/WorkerMedical.vue b/src/pages/Worker/Card/WorkerMedical.vue
index fab1416c9..bb8c8da58 100644
--- a/src/pages/Worker/Card/WorkerMedical.vue
+++ b/src/pages/Worker/Card/WorkerMedical.vue
@@ -12,7 +12,7 @@ const columns = [
     {
         align: 'left',
         name: 'date',
-        label: t('worker.medical.tableVisibleColumns.date'),
+        label: t('globals.date'),
         create: true,
         component: 'date',
     },
@@ -47,7 +47,7 @@ const columns = [
     {
         align: 'left',
         name: 'amount',
-        label: t('worker.medical.tableVisibleColumns.amount'),
+        label: t('globals.amount'),
         create: true,
         component: 'input',
     },
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index ed34e771d..3f562a77b 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -52,7 +52,7 @@ onBeforeMount(async () => {
         </template>
         <template #body="{ entity: worker }">
             <QCard class="vn-one">
-                <VnTitle :url="basicDataUrl" :text="t('worker.summary.basicData')" />
+                <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
                 <VnLv :label="t('worker.card.name')" :value="worker.user?.nickname" />
                 <VnLv :label="t('worker.list.department')">
                     <template #value>
@@ -91,7 +91,7 @@ onBeforeMount(async () => {
                 </VnLv>
             </QCard>
             <QCard class="vn-one" v-if="advancedSummary">
-                <VnTitle :url="basicDataUrl" :text="t('worker.summary.basicData')" />
+                <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
                 <VnLv
                     :label="t('worker.summary.fiDueDate')"
                     :value="toDate(worker.fiDueDate)"

From 11bf70d76ce3aa42d7c5ae2d94e4ebeb0a281082 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 18 Oct 2024 14:12:23 +0200
Subject: [PATCH 048/207] fix: category and tags filters

---
 src/components/ui/VnSearchbar.vue           |   4 +-
 src/pages/Order/Card/OrderCatalogFilter.vue | 111 +++++++++++++++-----
 2 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index fc292e980..569e0ed18 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -9,7 +9,7 @@ import { useStateStore } from 'src/stores/useStateStore';
 const quasar = useQuasar();
 const { t } = useI18n();
 const state = useStateStore();
-const emit = defineEmits(['on-search']);
+const emit = defineEmits(['onSearch']);
 
 const props = defineProps({
     dataKey: {
@@ -119,7 +119,7 @@ async function search() {
         delete filter.params.search;
     }
     await arrayData.applyFilter(filter);
-    emit('on-search', store.data);
+    emit('onSearch', store.data);
 }
 </script>
 <template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 9c713e77e..850212a62 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -1,12 +1,12 @@
 <script setup>
-import { computed, ref, onMounted } from 'vue';
+import { computed, ref, onMounted, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import axios from 'axios';
 import FetchData from 'components/FetchData.vue';
 import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
 import VnSelect from 'components/common/VnSelect.vue';
-import VnInput from 'src/components/common/VnInput.vue';
+// import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
 
 const { t } = useI18n();
@@ -48,12 +48,15 @@ const orderBySelected = ref('relevancy DESC, name');
 const orderWaySelected = ref('ASC');
 
 const routeQuery = JSON.parse(route?.query.params ?? '{}');
-const params = ref({});
+const paramsSearch = ref({});
 
 onMounted(() => {
-    const filter = routeQuery.filter;
-    params.value = JSON.parse(filter ?? '{}')?.where ?? {};
-    if (Object.keys(params.value).length > 0) vnFilterPanelRef.value.search();
+    paramsSearch.value = JSON.parse(routeQuery.filter ?? '{}')?.where ?? {};
+    if (Object.keys(paramsSearch.value).length > 0) vnFilterPanelRef.value.search();
+    if (routeQuery.categoryFk && routeQuery.typeFk) {
+        selectedCategoryFk.value = routeQuery.categoryFk;
+        selectedTypeFk.value = routeQuery.typeFk;
+    }
 });
 
 const createValue = (val, done) => {
@@ -70,12 +73,18 @@ const resetCategory = () => {
 };
 
 const selectCategory = (category, search) => {
-    if (!params.value?.filter) params.value.filter = { where: {} };
-    const where = params.value.filter.where;
+    if (!paramsSearch.value?.filter) paramsSearch.value.filter = { where: {} };
+    const where = paramsSearch.value.filter.where;
     if (where.categoryFk === category?.id) {
         resetCategory();
         where.categoryFk = null;
     } else {
+        if (where.categoryFk && where.categoryFk !== category?.id) {
+            paramsSearch.value.typeFk = null;
+            selectedTypeFk.value = null;
+            typeList.value = [];
+        }
+
         selectedCategoryFk.value = category?.id;
         where.categoryFk = category?.id;
         loadTypes(category?.id);
@@ -90,6 +99,10 @@ const loadTypes = async (categoryFk = selectedCategoryFk.value) => {
     typeList.value = data;
 };
 
+watch(selectedTypeFk, (newValue) => {
+    paramsSearch.value.typeFk = newValue;
+});
+
 const selectedCategory = computed(() =>
     (categoryList.value || []).find(
         (category) => category?.id === selectedCategoryFk.value
@@ -107,25 +120,55 @@ const selectedType = computed(() => {
     return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
 });
 
+// const applyTagFilter = (params, search) => {
+
+//     if (params.tagGroups) params.tagGroups = null;
+//     if (!tagValues.value?.length) {
+//         params.tagGroups = null;
+//         search();
+//         return;
+//     }
+//     if (!params.tagGroups) {
+//         params.tagGroups = [];
+//     }
+//     params.tagGroups.push(
+//         JSON.stringify({
+//             values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
+//             tagSelection: {
+//                 ...selectedTag.value,
+//                 orgShowField: selectedTag?.value?.name,
+//             },
+//             tagFk: selectedTag?.value?.tagFk,
+//         })
+//     );
+//     search();
+//     selectedTag.value = null;
+//     tagValues.value = [{}];
+// };
+
 const applyTagFilter = (params, search) => {
     if (!tagValues.value?.length) {
         params.tagGroups = null;
         search();
         return;
     }
+
     if (!params.tagGroups) {
         params.tagGroups = [];
+    } else if (typeof params.tagGroups === 'string') {
+        params.tagGroups = [params.tagGroups];
     }
-    params.tagGroups.push(
-        JSON.stringify({
-            values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
-            tagSelection: {
-                ...selectedTag.value,
-                orgShowField: selectedTag?.value?.name,
-            },
-            tagFk: selectedTag?.value?.tagFk,
-        })
-    );
+
+    const newTagGroup = JSON.stringify({
+        values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
+        tagSelection: {
+            ...selectedTag.value,
+            orgShowField: selectedTag?.value?.name,
+        },
+        tagFk: selectedTag?.value?.tagFk,
+    });
+    params.tagGroups.push(newTagGroup);
+
     search();
     selectedTag.value = null;
     tagValues.value = [{}];
@@ -155,6 +198,22 @@ function addOrder(value, field, params) {
     params.orderBy = JSON.stringify(orderBy);
     vnFilterPanelRef.value.search();
 }
+
+const data = ref([]);
+
+function getTagData(value) {
+    if (Array.isArray(value) && value.length >= 1) {
+        const parsedTags = value.map((obj) => JSON.parse(obj));
+
+        if (parsedTags.length === 1) {
+            data.value = parsedTags[0];
+        } else {
+            data.value = parsedTags;
+        }
+    } else {
+        data.value = JSON.parse(value);
+    }
+}
 </script>
 
 <template>
@@ -162,13 +221,14 @@ function addOrder(value, field, params) {
     <VnFilterPanel
         ref="vnFilterPanelRef"
         :data-key="props.dataKey"
-        v-model="params"
+        v-model="paramsSearch"
         :redirect="false"
         :hidden-tags="['orderFk', 'orderBy', 'filter', 'search', 'or', 'and']"
-        :un-removable-params="['orderFk', 'orderBy']"
+        :unremovable-params="['orderFk', 'orderBy']"
         :disable-submit-event="true"
     >
         <template #tags="{ tag, formatFn }">
+            {{ console.log('tag.label: ', tag.label) }}
             <strong v-if="tag.label === 'categoryFk'">
                 {{ t(selectedCategory?.name || '') }}
             </strong>
@@ -176,10 +236,11 @@ function addOrder(value, field, params) {
                 {{ t(selectedType?.name || '') }}
             </strong>
             <div v-else-if="tag.label === 'tagGroups'" class="q-gutter-x-xs">
-                <strong v-if="JSON.parse(tag.value).tagSelection.name"
-                    >{{ JSON.parse(tag.value).tagSelection?.name }}:
-                </strong>
-                <span>{{ JSON.parse(tag.value).values[0].value }}</span>
+                {{ getTagData(tag.value) }}
+                <strong> {{ data.tagSelection?.name }}: </strong>
+                <span>
+                    {{ console.log('data', data.values) }}
+                </span>
             </div>
             <div v-else class="q-gutter-x-xs">
                 <strong>{{ t(`params.${tag.label}`) }}: </strong>
@@ -328,7 +389,7 @@ function addOrder(value, field, params) {
                     @new-value="createValue"
                     @update:model-value="applyTagFilter(params, searchFn)"
                 />
-                <VnInput
+                <QInput
                     v-else
                     :label="t('params.value')"
                     v-model="value.value"

From e5cd9d4b8f40dae59f976dd8afe0da24b6690ea3 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 21 Oct 2024 12:56:09 +0200
Subject: [PATCH 049/207] refactor: refs #7132 global translations files
 changed

---
 src/components/FilterItemForm.vue             |  14 +-
 src/components/FilterTravelForm.vue           |  16 +-
 src/components/ItemsFilterPanel.vue           |   2 +-
 src/i18n/locale/en.yml                        | 311 +++--------------
 src/i18n/locale/es.yml                        | 314 +++---------------
 .../Department/Card/DepartmentBasicData.vue   |   8 +-
 .../Department/Card/DepartmentSummary.vue     |   6 +-
 src/pages/Entry/Card/EntryBasicData.vue       |  22 +-
 src/pages/Entry/Card/EntryBuys.vue            |   6 +-
 src/pages/Entry/Card/EntryBuysImport.vue      |   8 +-
 src/pages/Entry/Card/EntryDescriptor.vue      |   7 +-
 src/pages/Entry/Card/EntrySummary.vue         |   8 +-
 src/pages/Entry/EntryBuysTableDialog.vue      |   2 +-
 src/pages/Entry/EntryLatestBuys.vue           |  20 +-
 src/pages/Entry/EntryList.vue                 |   2 +-
 .../InvoiceOut/Card/InvoiceOutDescriptor.vue  |   4 +-
 .../InvoiceOut/Card/InvoiceOutSummary.vue     |  16 +-
 src/pages/InvoiceOut/InvoiceOutGlobal.vue     |   2 +-
 .../InvoiceOutNegativeBasesFilter.vue         |   6 +-
 src/pages/Item/Card/ItemDescriptor.vue        |   7 +-
 src/pages/Item/Card/ItemDescriptorImage.vue   |   4 +-
 src/pages/Item/Card/ItemSummary.vue           |  10 +-
 src/pages/Item/ItemCreate.vue                 |  13 +-
 src/pages/Item/ItemFixedPrice.vue             |   4 +-
 src/pages/Item/ItemList.vue                   |  14 +-
 src/pages/Item/ItemRequest.vue                |   8 +-
 src/pages/Order/Card/OrderBasicData.vue       |   2 +-
 src/pages/Order/Card/OrderCreateDialog.vue    |   3 +-
 src/pages/Order/Card/OrderDescriptor.vue      |  10 +-
 src/pages/Order/Card/OrderSummary.vue         |  24 +-
 .../Shelving/Card/ShelvingDescriptor.vue      |   4 +-
 src/pages/Shelving/Card/ShelvingForm.vue      |   6 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |   9 +-
 src/pages/Supplier/Card/SupplierAddresses.vue |   9 +-
 .../Supplier/Card/SupplierAddressesCreate.vue |  20 +-
 src/pages/Supplier/Card/SupplierBasicData.vue |   2 +-
 .../Supplier/Card/SupplierBillingData.vue     |   2 +-
 src/pages/Supplier/Card/SupplierContacts.vue  |  17 +-
 .../Supplier/Card/SupplierDescriptor.vue      |   2 +-
 .../Supplier/Card/SupplierFiscalData.vue      |   8 +-
 src/pages/Supplier/Card/SupplierSummary.vue   |  11 +-
 src/pages/Supplier/SupplierList.vue           |  12 +-
 src/pages/Ticket/Card/TicketBoxing.vue        |   4 +-
 src/pages/Ticket/Card/TicketDescriptor.vue    |   8 +-
 src/pages/Ticket/Card/TicketSummary.vue       |  39 +--
 src/pages/Ticket/TicketCreate.vue             |   8 +-
 src/pages/Ticket/TicketCreateDialog.vue       |   8 +-
 src/pages/Ticket/TicketList.vue               |   6 +-
 src/pages/Travel/Card/TravelBasicData.vue     |  15 +-
 src/pages/Travel/Card/TravelDescriptor.vue    |   4 +-
 src/pages/Travel/Card/TravelSummary.vue       |  10 +-
 src/pages/Travel/Card/TravelThermographs.vue  |   4 +-
 .../Travel/Card/TravelThermographsForm.vue    |   8 +-
 src/pages/Travel/ExtraCommunity.vue           |   4 +-
 src/pages/Travel/TravelCreate.vue             |   4 +-
 src/pages/Travel/TravelList.vue               |  10 +-
 src/pages/Wagon/Type/WagonTypeEdit.vue        |   2 +-
 src/pages/Wagon/WagonCreate.vue               |   4 +-
 src/pages/Wagon/WagonList.vue                 |   6 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |   4 +-
 src/pages/Worker/Card/WorkerSummary.vue       |   6 +-
 src/pages/Worker/WorkerCreate.vue             |  10 +-
 src/pages/Worker/WorkerList.vue               |   8 +-
 63 files changed, 322 insertions(+), 825 deletions(-)

diff --git a/src/components/FilterItemForm.vue b/src/components/FilterItemForm.vue
index 1cf36deeb..d1ceff4ce 100644
--- a/src/components/FilterItemForm.vue
+++ b/src/components/FilterItemForm.vue
@@ -50,25 +50,25 @@ const loading = ref(false);
 
 const tableColumns = computed(() => [
     {
-        label: t('entry.buys.id'),
+        label: t('globals.id'),
         name: 'id',
         field: 'id',
         align: 'left',
     },
     {
-        label: t('entry.buys.name'),
+        label: t('globals.name'),
         name: 'name',
         field: 'name',
         align: 'left',
     },
     {
-        label: t('entry.buys.size'),
+        label: t('globals.size'),
         name: 'size',
         field: 'size',
         align: 'left',
     },
     {
-        label: t('entry.buys.producer'),
+        label: t('globals.producer'),
         name: 'producerName',
         field: 'producer',
         align: 'left',
@@ -152,10 +152,10 @@ const selectItem = ({ id }) => {
             </span>
             <h1 class="title">{{ t('Filter item') }}</h1>
             <VnRow>
-                <VnInput :label="t('entry.buys.name')" v-model="itemFilterParams.name" />
+                <VnInput :label="t('globals.name')" v-model="itemFilterParams.name" />
                 <VnInput :label="t('entry.buys.size')" v-model="itemFilterParams.size" />
                 <VnSelect
-                    :label="t('entry.buys.producer')"
+                    :label="t('globals.producer')"
                     :options="producersOptions"
                     hide-selected
                     option-label="name"
@@ -163,7 +163,7 @@ const selectItem = ({ id }) => {
                     v-model="itemFilterParams.producerFk"
                 />
                 <VnSelect
-                    :label="t('entry.buys.type')"
+                    :label="t('globals.type')"
                     :options="ItemTypesOptions"
                     hide-selected
                     option-label="name"
diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue
index 841a55bba..a471552f2 100644
--- a/src/components/FilterTravelForm.vue
+++ b/src/components/FilterTravelForm.vue
@@ -48,13 +48,13 @@ const loading = ref(false);
 
 const tableColumns = computed(() => [
     {
-        label: t('entry.basicData.id'),
+        label: t('globals.id'),
         name: 'id',
         field: 'id',
         align: 'left',
     },
     {
-        label: t('entry.basicData.warehouseOut'),
+        label: t('globals.warehouseOut'),
         name: 'warehouseOutFk',
         field: 'warehouseOutFk',
         align: 'left',
@@ -62,7 +62,7 @@ const tableColumns = computed(() => [
             warehousesOptions.value.find((warehouse) => warehouse.id === val).name,
     },
     {
-        label: t('entry.basicData.warehouseIn'),
+        label: t('globals.warehouseIn'),
         name: 'warehouseInFk',
         field: 'warehouseInFk',
         align: 'left',
@@ -77,7 +77,7 @@ const tableColumns = computed(() => [
         format: (val) => toDate(val),
     },
     {
-        label: t('entry.basicData.landed'),
+        label: t('globals.landed'),
         name: 'landed',
         field: 'landed',
         align: 'left',
@@ -146,7 +146,7 @@ const selectTravel = ({ id }) => {
             <h1 class="title">{{ t('Filter travels') }}</h1>
             <VnRow>
                 <VnSelect
-                    :label="t('entry.basicData.agency')"
+                    :label="t('globals.agency')"
                     :options="agenciesOptions"
                     hide-selected
                     option-label="name"
@@ -154,7 +154,7 @@ const selectTravel = ({ id }) => {
                     v-model="travelFilterParams.agencyModeFk"
                 />
                 <VnSelect
-                    :label="t('entry.basicData.warehouseOut')"
+                    :label="t('globals.warehouseOut')"
                     :options="warehousesOptions"
                     hide-selected
                     option-label="name"
@@ -162,7 +162,7 @@ const selectTravel = ({ id }) => {
                     v-model="travelFilterParams.warehouseOutFk"
                 />
                 <VnSelect
-                    :label="t('entry.basicData.warehouseIn')"
+                    :label="t('globals.warehouseIn')"
                     :options="warehousesOptions"
                     hide-selected
                     option-label="name"
@@ -174,7 +174,7 @@ const selectTravel = ({ id }) => {
                     v-model="travelFilterParams.shipped"
                 />
                 <VnInputDate
-                    :label="t('entry.basicData.landed')"
+                    :label="t('globals.landed')"
                     v-model="travelFilterParams.landed"
                 />
             </VnRow>
diff --git a/src/components/ItemsFilterPanel.vue b/src/components/ItemsFilterPanel.vue
index e89d32da4..938dceb4d 100644
--- a/src/components/ItemsFilterPanel.vue
+++ b/src/components/ItemsFilterPanel.vue
@@ -248,7 +248,7 @@ const removeTag = (index, params, search) => {
             >
                 <QItemSection class="col">
                     <VnSelect
-                        :label="t('components.itemsFilterPanel.tag')"
+                        :label="t('globals.tag')"
                         v-model="value.selectedTag"
                         :options="tagOptions"
                         option-label="name"
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index f4d258585..aa6e3ba2c 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -59,7 +59,7 @@ globals:
     downloadCSVSuccess: CSV downloaded successfully
     reference: Reference
     agency: Agency
-    wareHouseOut: Warehouse Out
+    warehouseOut: Warehouse Out
     wareHouseIn: Warehouse In
     landed: Landed
     shipped: Shipped
@@ -106,6 +106,26 @@ globals:
     weight: Weight
     error: Ups! Something went wrong
     recalc: Recalculate
+    alias: Alias
+    vat: VAT
+    intrastat: Intrastat
+    tags: Tags
+    size: Size
+    producer: Producer
+    origin: Origin
+    state: State
+    subtotal: Subtotal
+    visible: Visible
+    price: Price
+    client: Client
+    country: Country
+    phone: Phone
+    mobile: Mobile
+    postcode: Postcode
+    street: Street
+    tag: Tag
+    ticketId: Ticket ID
+    confirmed: Confirmed
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -295,7 +315,6 @@ globals:
     maxTemperature: Max
     minTemperature: Min
     params:
-        id: ID
         clientFk: Client id
         salesPersonFk: Sales person
         warehouseFk: Warehouse
@@ -346,14 +365,7 @@ resetPassword:
 entry:
     list:
         newEntry: New entry
-        landed: Landed
-        invoiceNumber: Invoice number
-        supplier: Supplier
-        booked: Booked
-        confirmed: Confirmed
-        ordered: Ordered
         tableVisibleColumns:
-            id: Id
             created: Creation
             supplierFk: Supplier
             isBooked: Booked
@@ -362,25 +374,20 @@ entry:
             companyFk: Company
             travelFk: Travel
             isExcludedFromAvailable: Inventory
-            isRaid: Raid
             invoiceAmount: Import
     summary:
         commission: Commission
         currency: Currency
-        company: Company
         invoiceNumber: Invoice number
         ordered: Ordered
-        confirmed: Confirmed
         booked: Booked
         raid: Raid
         excludedFromAvailable: Inventory
         travelReference: Reference
         travelAgency: Agency
         travelShipped: Shipped
-        travelWarehouseOut: Warehouse Out
         travelDelivered: Delivered
         travelLanded: Landed
-        travelWarehouseIn: Warehouse In
         travelReceived: Received
         buys: Buys
         stickers: Stickers
@@ -390,63 +397,29 @@ entry:
         buyingValue: Buying value
         import: Import
         pvp: PVP
-        item: Item
     basicData:
-        supplier: Supplier
         travel: Travel
-        invoiceNumber: Invoice number
-        company: Company
         currency: Currency
         commission: Commission
         observation: Observation
-        ordered: Ordered
-        confirmed: Confirmed
         booked: Booked
         raid: Raid
         excludedFromAvailable: Inventory
-        agency: Agency
-        warehouseOut: Warehouse Out
-        warehouseIn: Warehouse In
-        landed: Landed
-        id: ID
     buys:
-        groupingPrice: Grouping price
-        packingPrice: Packing price
         observations: Observations
-        item: Item
-        size: Size
-        packing: Packing
-        grouping: Grouping
-        buyingValue: Buying value
         packagingFk: Box
-        name: Name
-        producer: Producer
-        type: Type
         color: Color
-        id: ID
         printedStickers: Printed stickers
     notes:
         observationType: Observation type
-    descriptor:
-        agency: Agency
-        landed: Landed
-        warehouseOut: Warehouse Out
     latestBuys:
         tableVisibleColumns:
             image: Picture
             itemFk: Item ID
-            packing: Packing
-            grouping: Grouping
-            size: Size
-            tags: Tags
-            type: Type
-            intrastat: Intrastat
-            origin: Origin
             weightByPiece: Weight/Piece
             isActive: Active
             family: Family
             entryFk: Entry
-            buyingValue: Buying value
             freightValue: Freight value
             comissionValue: Commission value
             packageValue: Package value
@@ -455,7 +428,6 @@ entry:
             price3: Packing
             minPrice: Min
             ektFk: Ekt
-            packagingFk: Package
             packingOut: Package out
             landing: Landing
             isExcludedFromAvailable: Es inventory
@@ -471,60 +443,38 @@ ticket:
         futureTickets: Future tickets
         purchaseRequest: Purchase request
         weeklyTickets: Weekly tickets
-    list:
-        nickname: Nickname
-        state: State
-        landed: Landed
-        total: Total
     card:
-        ticketId: Ticket ID
-        state: State
         customerId: Customer ID
-        agency: Agency
-        warehouse: Warehouse
         customerCard: Customer card
-        alias: Alias
         ticketList: Ticket List
         newOrder: New Order
     boxing:
         expedition: Expedition
-        item: Item
         created: Created
-        worker: Worker
         selectTime: 'Select time:'
         selectVideo: 'Select video:'
         notFound: No videos available
     summary:
-        state: State
-        agency: Agency
         zone: Zone
-        warehouse: Warehouse
         collection: Collection
         route: Route
         invoice: Invoice
         shipped: Shipped
-        landed: Landed
         consigneePhone: Consignee phone
         consigneeMobile: Consignee mobile
         consigneeAddress: Consignee address
         clientPhone: Client phone
         clientMobile: Client mobile
         consignee: Consignee
-        subtotal: Subtotal
-        vat: VAT
         total: Total
         saleLines: Line items
-        item: Item
-        visible: Visible
         available: Available
-        price: Price
         discount: Discount
         packing: Packing
         hasComponentLack: Component lack
         itemShortage: Not visible
         claim: Claim
         reserved: Reserved
-        created: Created
         package: Package
         taxClass: Tax class
         services: Services
@@ -539,41 +489,20 @@ ticket:
         attender: Attender
         ok: Ok
     create:
-        client: Client
         address: Address
-        landed: Landed
-        warehouse: Warehouse
-        agency: Agency
 invoiceOut:
-    list:
-        ref: Reference
-        issued: Issued
-        shortIssued: Issued
-        client: Client
-        created: Created
-        shortCreated: Created
-        company: Company
-        dued: Due date
-        shortDued: Due date
     card:
         issued: Issued
-        client: Client
-        company: Company
         customerCard: Customer card
     summary:
         issued: Issued
-        created: Created
         dued: Due
         booked: Booked
-        company: Company
         taxBreakdown: Tax breakdown
-        type: Type
         taxableBase: Taxable base
         rate: Rate
         fee: Fee
         tickets: Tickets
-        ticketId: Ticket id
-        nickname: Alias
         totalWithVat: Amount
     globalInvoices:
         errors:
@@ -587,19 +516,14 @@ invoiceOut:
             noTicketsToInvoice: There are not tickets to invoice
             criticalInvoiceError: 'Critical invoicing error, process stopped'
         table:
-            client: Client
             addressId: Address id
             streetAddress: Street
         statusCard:
             percentageText: '{getPercentage}% {getAddressNumber} of {getNAddresses}'
             pdfsNumberText: '{nPdfs} of {totalPdfs} PDFs'
     negativeBases:
-        company: Company
-        country: Country
         clientId: Client Id
-        client: Client
         base: Base
-        ticketId: Ticket Id
         active: Active
         hasToInvoice: Has to Invoice
         verifiedData: Verified Data
@@ -612,13 +536,6 @@ shelving:
         priority: Priority
         newShelving: New Shelving
     summary:
-        parking: Parking
-        priority: Priority
-        worker: Worker
-        recyclable: Recyclable
-    basicData:
-        parking: Parking
-        priority: Priority
         recyclable: Recyclable
 parking:
     pickingOrder: Picking order
@@ -633,49 +550,28 @@ parking:
 order:
     field:
         salesPersonFk: Sales Person
-        clientFk: Client
-        isConfirmed: Confirmed
-        created: Created
-        landed: Landed
-        hour: Hour
-        agency: Agency
-        total: Total
     form:
         clientFk: Client
         addressFk: Address
-        landed: Landed
         agencyModeFk: Agency
     list:
         newOrder: New Order
     summary:
         basket: Basket
-        nickname: Nickname
-        company: Company
-        confirmed: Confirmed
         notConfirmed: Not confirmed
         created: Created
-        landed: Landed
-        phone: Phone
         createdFrom: Created From
         address: Address
-        subtotal: Subtotal
         total: Total
-        vat: VAT
-        state: State
-        alias: Alias
         items: Items
         orderTicketList: Order Ticket List
-        item: Item
-        price: Price
         amount: Amount
 department:
     pageTitles:
         department: Department
         summary: Summary
-    name: Name
     chat: Chat
     bossDepartment: Boss Department
-    email: Email
     selfConsumptionCustomer: Self-consumption customer
     telework: Telework
     notifyOnErrors: Notify on errors
@@ -699,23 +595,9 @@ worker:
         locker: Locker
         medical: Medical
     list:
-        name: Name
-        email: Email
-        phone: Phone
-        mobile: Mobile
-        active: Active
         department: Department
         schedule: Schedule
         newWorker: New worker
-    card:
-        workerId: Worker ID
-        name: Name
-        email: Email
-        phone: Phone
-        mobile: Mobile
-        active: Active
-        warehouse: Warehouse
-        agency: Agency
     summary:
         boss: Boss
         phoneExtension: Phone extension
@@ -748,19 +630,12 @@ worker:
         serialNumber: Serial number
         removePDA: Deallocate PDA
     create:
-        name: Name
         lastName: Last name
         birth: Birth
         fi: Fi
         code: Worker code
-        phone: Phone
-        postcode: Postcode
-        province: Province
-        city: City
-        street: Street
         webUser: Web user
         personalEmail: Personal email
-        company: Company
         boss: Boss
         payMethods: Pay method
         iban: IBAN
@@ -801,7 +676,6 @@ wagon:
         wagonCounter: Trolley counter
         wagonTray: Tray List
     type:
-        name: Name
         submit: Submit
         reset: Reset
         trayColor: Tray color
@@ -809,12 +683,10 @@ wagon:
     list:
         plate: Plate
         volume: Volume
-        type: Type
         remove: Remove
         removeItem: Wagon removed successfully
     create:
         plate: Plate
-        type: Type
         label: Label
     warnings:
         noData: No data available
@@ -831,25 +703,17 @@ wagon:
 supplier:
     list:
         payMethod: Pay method
-        payDeadline: Pay deadline
-        payDay: Pay day
         account: Account
         newSupplier: New supplier
         tableVisibleColumns:
-            id: Id
-            name: Name
             nif: NIF/CIF
-            nickname: Alias
             account: Account
-            payMethod: Pay Method
             payDay: Pay Day
-            country: Country
     summary:
         responsible: Responsible
         verified: Verified
         isActive: Is active
         billingData: Billing data
-        payMethod: Pay method
         payDeadline: Pay deadline
         payDay: Pay day
         account: Account
@@ -862,15 +726,10 @@ supplier:
         fiscalAddress: Fiscal address
         socialName: Social name
         taxNumber: Tax number
-        street: Street
         city: City
-        postCode: Postcode
-        province: Province
-        country: Country
     create:
         supplierName: Supplier name
     basicData:
-        alias: Alias
         workerFk: Responsible
         isSerious: Verified
         isActive: Active
@@ -884,36 +743,18 @@ supplier:
         sageWithholdingFk: Sage withholding
         sageTransactionTypeFk: Sage transaction type
         supplierActivityFk: Supplier activity
-        healthRegister: Health register
-        street: Street
-        postcode: Postcode
-        city: City *
-        provinceFk: Province
-        country: Country
         isTrucker: Trucker
         isVies: Vies
     billingData:
         payMethodFk: Billing data
         payDemFk: Payment deadline
-        payDay: Pay day
     accounts:
         iban: Iban
         bankEntity: Bank entity
         beneficiary: Beneficiary
     contacts:
-        name: Name
-        phone: Phone
-        mobile: Mobile
         email: Email
         observation: Notes
-    addresses:
-        street: Street
-        postcode: Postcode
-        phone: Phone
-        name: Name
-        city: City
-        province: Province
-        mobile: Mobile
     agencyTerms:
         agencyFk: Agency
         minimumM3: Minimum M3
@@ -928,19 +769,13 @@ supplier:
 travel:
     travelList:
         tableVisibleColumns:
-            id: Id
             ref: Reference
-            agency: Agency
-            landed: Landed
             shipHour: Shipment Hour
             landHour: Landing Hour
-            warehouseIn: Warehouse in
-            warehouseOut: Warehouse out
             totalEntries: Total entries
             totalEntriesTooltip: Total entries
             daysOnward: Landed days onwards
     summary:
-        confirmed: Confirmed
         entryId: Entry Id
         freight: Freight
         package: Package
@@ -953,59 +788,28 @@ travel:
         AddEntry: Add entry
         thermographs: Thermographs
         hb: HB
-    variables:
-        search: Id/Reference
-        agencyModeFk: Agency
-        warehouseInFk: ' Warehouse In'
-        warehouseOutFk: Warehouse Out
-        landedFrom: Landed from
-        landedTo: Landed to
-        continent: Continent out
-    basicData:
-        agency: Agency
-        landed: Landed
-        warehouseOut: Warehouse Out
-        warehouseIn: Warehouse In
-        delivered: Delivered
-        received: Received
     thermographs:
         temperature: Temperature
-        state: State
         destination: Destination
-        created: Created
         thermograph: Thermograph
-        type: Type
-        company: Company
-        warehouse: Warehouse
         travelFileDescription: 'Travel id { travelId }'
 item:
     descriptor:
-        item: Item
         buyer: Buyer
         color: Color
         category: Category
-        stems: Stems
-        visible: Visible
         available: Available
         warehouseText: 'Calculated on the warehouse of { warehouseName }'
         itemDiary: Item diary
-        producer: Producer
     list:
         id: Identifier
-        grouping: Grouping
-        packing: Packing
         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
     fixedPrice:
         itemFk: Item ID
         groupingPrice: Grouping price
@@ -1014,71 +818,52 @@ item:
         minPrice: Min price
         started: Started
         ended: Ended
-        warehouse: Warehouse
     create:
-        name: Name
-        tag: Tag
         priority: Priority
-        type: Type
-        intrastat: Intrastat
-        origin: Origin
     buyRequest:
-        ticketId: 'Ticket ID'
-        requester: 'Requester'
-        requested: 'Requested'
-        price: 'Price'
-        attender: 'Atender'
-        item: 'Item'
-        achieved: 'Achieved'
-        concept: 'Concept'
-        state: 'State'
+        requester: Requester
+        requested: Requested
+        attender: Atender
+        achieved: Achieved
+        concept: Concept
     summary:
-        otherData: 'Other data'
-        tax: 'Tax'
-        tags: 'Tags'
-        botanical: 'Botanical'
-        barcode: 'Barcode'
-        name: 'Nombre'
-        completeName: 'Nombre completo'
-        family: 'Familia'
-        size: 'Medida'
-        origin: 'Origen'
-        stems: 'Tallos'
-        multiplier: 'Multiplicador'
-        buyer: 'Comprador'
-        doPhoto: 'Do photo'
-        intrastatCode: 'Código intrastat'
-        intrastat: 'Intrastat'
-        ref: 'Referencia'
-        relevance: 'Relevancia'
-        weight: 'Peso (gramos)/tallo'
-        units: 'Unidades/caja'
-        expense: 'Gasto'
-        generic: 'Genérico'
-        recycledPlastic: 'Plástico reciclado'
-        nonRecycledPlastic: 'Plástico no reciclado'
-        minSalesQuantity: 'Cantidad mínima de venta'
-        genus: 'Genus'
-        specie: 'Specie'
+        otherData: Other data
+        tax: Tax
+        botanical: Botanical
+        barcode: Barcode
+        completeName: Complete name
+        family: Familiy
+        stems: Stems
+        multiplier: Multiplier
+        buyer: Buyer
+        doPhoto: Do photo
+        intrastatCode: Intrastat code
+        ref: Reference
+        relevance: Relevance
+        weight: Weight (gram)/stem
+        units: Units/box
+        expense: Expense
+        generic: Generic
+        recycledPlastic: Recycled plastic
+        nonRecycledPlastic: Non recycled plastic
+        minSalesQuantity: Min sales quantity
+        genus: Genus
+        specie: Specie
 components:
     topbar: {}
     itemsFilterPanel:
         typeFk: Type
-        tag: Tag
         value: Value
         # ItemFixedPriceFilter
         buyerFk: Buyer
-        warehouseFk: Warehouse
         started: From
         ended: To
         mine: For me
         hasMinPrice: Minimum price
         # LatestBuysFilter
         salesPersonFk: Buyer
-        supplierFk: Supplier
         from: From
         active: Is active
-        visible: Is visible
         floramondo: Is floramondo
         showBadDates: Show future items
     userPanel:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index a8d582c30..92507db40 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -58,8 +58,8 @@ globals:
     downloadCSVSuccess: Descarga de CSV exitosa
     reference: Referencia
     agency: Agencia
-    wareHouseOut: Alm. salida
-    wareHouseIn: Alm. entrada
+    warehouseOut: Alm. salida
+    warehouseIn: Alm. entrada
     landed: F. entrega
     shipped: F. envío
     totalEntries: Ent. totales
@@ -108,6 +108,26 @@ globals:
     weight: Peso
     error: ¡Ups! Algo salió mal
     recalc: Recalcular
+    alias: Alias
+    vat: IVA
+    intrastat: Intrastat
+    tags: Etiquetas
+    size: Medida
+    producer: Productor
+    origin: Origen
+    state: Estado
+    subtotal: Subtotal
+    visible: Visible
+    price: Precio
+    client: Cliente
+    country: País
+    phone: Teléfono
+    mobile: Móvil
+    postcode: Código postal
+    street: Dirección
+    tag: Etiqueta
+    ticketId: ID ticket
+    confirmed: Confirmado
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -299,7 +319,6 @@ globals:
     maxTemperature: Máx
     minTemperature: Mín
     params:
-        id: Id
         clientFk: Id cliente
         salesPersonFk: Comercial
         warehouseFk: Almacén
@@ -348,14 +367,7 @@ resetPassword:
 entry:
     list:
         newEntry: Nueva entrada
-        landed: F. entrega
-        invoiceNumber: Núm. factura
-        supplier: Proveedor
-        booked: Asentado
-        confirmed: Confirmado
-        ordered: Pedida
         tableVisibleColumns:
-            id: Id
             created: Creación
             supplierFk: Proveedor
             isBooked: Asentado
@@ -364,15 +376,12 @@ entry:
             companyFk: Empresa
             travelFk: Envio
             isExcludedFromAvailable: Inventario
-            isRaid: Redada
             invoiceAmount: Importe
     summary:
         commission: Comisión
         currency: Moneda
-        company: Empresa
         invoiceNumber: Núm. factura
         ordered: Pedida
-        confirmed: Confirmada
         booked: Contabilizada
         raid: Redada
         excludedFromAvailable: Inventario
@@ -382,7 +391,6 @@ entry:
         travelWarehouseOut: Alm. salida
         travelDelivered: Enviada
         travelLanded: F. entrega
-        travelWarehouseIn: Alm. entrada
         travelReceived: Recibida
         buys: Compras
         stickers: Etiquetas
@@ -392,63 +400,29 @@ entry:
         buyingValue: Coste
         import: Importe
         pvp: PVP
-        item: Artículo
     basicData:
-        supplier: Proveedor
         travel: Envío
-        invoiceNumber: Núm. factura
-        company: Empresa
         currency: Moneda
         observation: Observación
         commission: Comisión
-        ordered: Pedida
-        confirmed: Confirmado
         booked: Asentado
         raid: Redada
         excludedFromAvailable: Inventario
-        agency: Agencia
-        warehouseOut: Alm. salida
-        warehouseIn: Alm. entrada
-        landed: F. entrega
-        id: ID
     buys:
-        groupingPrice: Precio grouping
-        packingPrice: Precio packing
         observations: Observaciónes
-        item: Artículo
-        size: Medida
-        packing: Packing
-        grouping: Grouping
-        buyingValue: Coste
         packagingFk: Embalaje
-        name: Nombre
-        producer: Productor
-        type: Tipo
         color: Color
-        id: ID
         printedStickers: Etiquetas impresas
     notes:
         observationType: Tipo de observación
-    descriptor:
-        agency: Agencia
-        landed: F. entrega
-        warehouseOut: Alm. salida
     latestBuys:
         tableVisibleColumns:
             image: Foto
             itemFk: Id Artículo
-            packing: packing
-            grouping: Grouping
-            size: Medida
-            tags: Etiquetas
-            type: Tipo
-            intrastat: Intrastat
-            origin: Origen
             weightByPiece: Peso (gramos)/tallo
             isActive: Activo
             family: Familia
             entryFk: Entrada
-            buyingValue: Coste
             freightValue: Porte
             comissionValue: Comisión
             packageValue: Embalaje
@@ -457,7 +431,6 @@ entry:
             price3: Packing
             minPrice: Min
             ektFk: Ekt
-            packagingFk: Embalaje
             packingOut: Embalaje envíos
             landing: Llegada
             isExcludedFromAvailable: Es inventario
@@ -478,60 +451,38 @@ ticket:
         tracking: Estados
         components: Componentes
         pictures: Fotos
-    list:
-        nickname: Alias
-        state: Estado
-        landed: Entregado
-        total: Total
     card:
-        ticketId: ID ticket
-        state: Estado
         customerId: ID cliente
-        agency: Agencia
-        warehouse: Almacén
         customerCard: Ficha del cliente
-        alias: Alias
         ticketList: Listado de tickets
         newOrder: Nuevo pedido
     boxing:
         expedition: Expedición
-        item: Artículo
         created: Creado
-        worker: Trabajador
         selectTime: 'Seleccionar hora:'
         selectVideo: 'Seleccionar vídeo:'
         notFound: No hay vídeos disponibles
     summary:
-        state: Estado
-        agency: Agencia
         zone: Zona
-        warehouse: Almacén
         collection: Colección
         route: Ruta
         invoice: Factura
         shipped: Enviado
-        landed: Entregado
         consigneePhone: Tel. consignatario
         consigneeMobile: Móv. consignatario
         consigneeAddress: Dir. consignatario
         clientPhone: Tel. cliente
         clientMobile: Móv. cliente
         consignee: Consignatario
-        subtotal: Subtotal
-        vat: IVA
         total: Total
         saleLines: Líneas del pedido
-        item: Artículo
-        visible: Visible
         available: Disponible
-        price: Precio
         discount: Descuento
         packing: Encajado
         hasComponentLack: Faltan componentes
         itemShortage: No visible
         claim: Reclamación
         reserved: Reservado
-        created: Fecha creación
         package: Embalaje
         taxClass: Tipo IVA
         services: Servicios
@@ -545,42 +496,21 @@ ticket:
         service: Servicio
         attender: Consignatario
     create:
-        client: Cliente
         address: Dirección
-        landed: F. entrega
-        warehouse: Almacén
-        agency: Agencia
 invoiceOut:
-    list:
-        ref: Referencia
-        issued: Fecha emisión
-        shortIssued: F. emisión
-        client: Cliente
-        created: Fecha creación
-        shortCreated: F. creación
-        company: Empresa
-        dued: Fecha vencimineto
-        shortDued: F. vencimiento
     card:
         issued: Fecha emisión
-        client: Cliente
-        company: Empresa
         customerCard: Ficha del cliente
         ticketList: Listado de tickets
     summary:
         issued: Fecha
-        created: Fecha creación
         dued: Vencimiento
         booked: Contabilizada
-        company: Empresa
         taxBreakdown: Desglose impositivo
-        type: Tipo
         taxableBase: Base imp.
         rate: Tarifa
         fee: Cuota
         tickets: Tickets
-        ticketId: Id ticket
-        nickname: Alias
         totalWithVat: Importe
     globalInvoices:
         errors:
@@ -594,19 +524,14 @@ invoiceOut:
             noTicketsToInvoice: No existen tickets para facturar
             criticalInvoiceError: Error crítico en la facturación proceso detenido
         table:
-            client: Cliente
             addressId: Id dirección
             streetAddress: Dirección fiscal
         statusCard:
             percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
             pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
     negativeBases:
-        company: Empresa
-        country: País
         clientId: Id cliente
-        client: Cliente
         base: Base
-        ticketId: Id ticket
         active: Activo
         hasToInvoice: Facturar
         verifiedData: Datos comprobados
@@ -616,40 +541,21 @@ invoiceOut:
 order:
     field:
         salesPersonFk: Comercial
-        clientFk: Cliente
-        isConfirmed: Confirmada
-        created: Creado
-        landed: F. entrega
-        hour: Hora
-        agency: Agencia
-        total: Total
     form:
         clientFk: Cliente
         addressFk: Dirección
-        landed: F. entrega
         agencyModeFk: Agencia
     list:
         newOrder: Nuevo Pedido
     summary:
         basket: Cesta
-        nickname: Alias
-        company: Empresa
-        confirmed: Confirmada
         notConfirmed: No confirmada
         created: Creado
-        landed: F. entrega
-        phone: Teléfono
         createdFrom: Creado desde
         address: Dirección
-        subtotal: Subtotal
         total: Total
-        vat: IVA
-        state: Estado
-        alias: Alias
         items: Items
         orderTicketList: Tickets del pedido
-        item: Item
-        price: Precio
         amount: Monto
 shelving:
     list:
@@ -657,13 +563,6 @@ shelving:
         priority: Prioridad
         newShelving: Nuevo Carro
     summary:
-        parking: Parking
-        priority: Prioridad
-        worker: Trabajador
-        recyclable: Reciclable
-    basicData:
-        parking: Parking
-        priority: Prioridad
         recyclable: Reciclable
 parking:
     pickingOrder: Orden de recogida
@@ -678,10 +577,8 @@ department:
     pageTitles:
         department: Departamentos
         summary: Resumen
-    name: Nombre
     chat: Chat
     bossDepartment: Jefe de departamento
-    email: Email
     selfConsumptionCustomer: Cliente autoconsumo
     telework: Teletrabaja
     notifyOnErrors: Notificar errores
@@ -706,23 +603,9 @@ worker:
         formation: Formación
         medical: Mutua
     list:
-        name: Nombre
-        email: Email
-        phone: Teléfono
-        mobile: Móvil
-        active: Activo
         department: Departamento
         schedule: Horario
         newWorker: Nuevo trabajador
-    card:
-        workerId: ID Trabajador
-        name: Nombre
-        email: Correo personal
-        phone: Teléfono
-        mobile: Móvil
-        active: Activo
-        warehouse: Almacén
-        agency: Empresa
     summary:
         boss: Jefe
         phoneExtension: Extensión de teléfono
@@ -746,19 +629,12 @@ worker:
         serialNumber: Número de serie
         removePDA: Desasignar PDA
     create:
-        name: Nombre
         lastName: Apellido
         birth: Fecha de nacimiento
         fi: DNI/NIF/NIE
         code: Código de trabajador
-        phone: Teléfono
-        postcode: Código postal
-        province: Provincia
-        city: Población
-        street: Dirección
         webUser: Usuario Web
         personalEmail: Correo personal
-        company: Empresa
         boss: Jefe
         payMethods: Método de pago
         iban: IBAN
@@ -799,7 +675,6 @@ wagon:
         wagonCounter: Contador de carros
         wagonTray: Listado bandejas
     type:
-        name: Nombre
         submit: Guardar
         reset: Deshacer cambios
         trayColor: Color de la bandeja
@@ -807,12 +682,9 @@ wagon:
     list:
         plate: Matrícula
         volume: Volumen
-        type: Tipo
         remove: Borrar
         removeItem: Vagón borrado correctamente
     create:
-        plate: Matrícula
-        type: Tipo
         label: Etiqueta
     warnings:
         noData: Sin datos disponibles
@@ -828,25 +700,16 @@ wagon:
 supplier:
     list:
         payMethod: Método de pago
-        payDeadline: Plazo de pago
-        payDay: Día de pago
         account: Cuenta
         newSupplier: Nuevo proveedor
         tableVisibleColumns:
-            id: Id
-            name: Nombre
             nif: NIF/CIF
-            nickname: Alias
             account: Cuenta
-            payMethod: Método de pago
-            payDay: Dia de pago
-            country: País
     summary:
         responsible: Responsable
         verified: Verificado
         isActive: Está activo
         billingData: Forma de pago
-        payMethod: Método de pago
         payDeadline: Plazo de pago
         payDay: Día de pago
         account: Cuenta
@@ -859,15 +722,11 @@ supplier:
         fiscalAddress: Dirección fiscal
         socialName: Razón social
         taxNumber: NIF/CIF
-        street: Dirección
         city: Población
-        postCode: Código postal
         province: Provincia
-        country: País
     create:
         supplierName: Nombre del proveedor
     basicData:
-        alias: Alias
         workerFk: Responsable
         isSerious: Verificado
         isActive: Activo
@@ -881,36 +740,17 @@ supplier:
         sageWithholdingFk: Retención sage
         sageTransactionTypeFk: Tipo de transacción sage
         supplierActivityFk: Actividad proveedor
-        healthRegister: Pasaporte sanitario
-        street: Calle
-        postcode: Código postal
-        city: Población *
-        provinceFk: Provincia
-        country: País
         isTrucker: Transportista
         isVies: Vies
     billingData:
         payMethodFk: Forma de pago
         payDemFk: Plazo de pago
-        payDay: Día de pago
     accounts:
         iban: Iban
         bankEntity: Entidad bancaria
         beneficiary: Beneficiario
     contacts:
-        name: Nombre
-        phone: Teléfono
-        mobile: Móvil
-        email: Email
         observation: Notas
-    addresses:
-        street: Dirección
-        postcode: Código postal
-        phone: Teléfono
-        name: Nombre
-        city: Población
-        province: Provincia
-        mobile: Móvil
     agencyTerms:
         agencyFk: Agencia
         minimumM3: M3 mínimos
@@ -925,19 +765,13 @@ supplier:
 travel:
     travelList:
         tableVisibleColumns:
-            id: Id
             ref: Referencia
-            agency: Agencia
             shipHour: Hora de envío
             landHour: Hora de llegada
-            landed: F.entrega
-            warehouseIn: Alm.salida
-            warehouseOut: Alm.entrada
             totalEntries: ∑
             totalEntriesTooltip: Entradas totales
             daysOnward: Días de llegada en adelante
     summary:
-        confirmed: Confirmado
         entryId: Id entrada
         freight: Porte
         package: Embalaje
@@ -950,59 +784,28 @@ travel:
         AddEntry: Añadir entrada
         thermographs: Termógrafos
         hb: HB
-    variables:
-        search: Id/Referencia
-        agencyModeFk: Agencia
-        warehouseInFk: Alm. entrada
-        warehouseOutFk: ' Alm. salida'
-        landedFrom: Llegada desde
-        landedTo: Llegada hasta
-        continent: Cont. Salida
-    basicData:
-        agency: Agencia
-        landed: F. entrega
-        warehouseOut: Alm. salida
-        warehouseIn: Alm. entrada
-        delivered: Enviada
-        received: Recibida
     thermographs:
         temperature: Temperatura
-        state: Estado
         destination: Destino
-        created: Fecha creación
         thermograph: Termógrafo
-        type: Tipo
-        company: Empresa
-        warehouse: Almacén
         travelFileDescription: 'Id envío { travelId }'
 item:
     descriptor:
-        item: Artículo
         buyer: Comprador
         color: Color
         category: Categoría
-        stems: Tallos
-        visible: Visible
         available: Disponible
         warehouseText: 'Calculado sobre el almacén de { warehouseName }'
         itemDiary: Registro de compra-venta
-        producer: Productor
     list:
         id: Identificador
-        grouping: Grouping
-        packing: Packing
         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
     fixedPrice:
         itemFk: ID Artículo
         groupingPrice: Precio grouping
@@ -1011,70 +814,51 @@ item:
         minPrice: Precio min
         started: Inicio
         ended: Fin
-        warehouse: Almacén
     create:
-        name: Nombre
-        tag: Etiqueta
         priority: Prioridad
-        type: Tipo
-        intrastat: Intrastat
-        origin: Origen
     summary:
-        otherData: 'Otros datos'
-        tax: 'IVA'
-        tags: 'Etiquetas'
-        botanical: 'Botánico'
-        barcode: 'Código de barras'
-        name: 'Nombre'
-        completeName: 'Nombre completo'
-        family: 'Familia'
-        size: 'Medida'
-        origin: 'Origen'
-        stems: 'Tallos'
-        multiplier: 'Multiplicador'
-        buyer: 'Comprador'
-        doPhoto: 'Hacer foto'
-        intrastatCode: 'Código intrastat'
-        intrastat: 'Intrastat'
-        ref: 'Referencia'
-        relevance: 'Relevancia'
-        weight: 'Peso (gramos)/tallo'
-        units: 'Unidades/caja'
-        expense: 'Gasto'
-        generic: 'Genérico'
-        recycledPlastic: 'Plástico reciclado'
-        nonRecycledPlastic: 'Plástico no reciclado'
-        minSalesQuantity: 'Cantidad mínima de venta'
-        genus: 'Genus'
-        specie: 'Specie'
+        otherData: Otros datos
+        tax: IVA
+        botanical: Botánico
+        barcode: Código de barras
+        completeName: Nombre completo
+        family: Familia
+        stems: Tallos
+        multiplier: Multiplicador
+        buyer: Comprador
+        doPhoto: Hacer foto
+        intrastatCode: Código intrastat
+        ref: Referencia
+        relevance: Relevancia
+        weight: Peso (gramos)/tallo
+        units: Unidades/caja
+        expense: Gasto
+        generic: Genérico
+        recycledPlastic: Plástico reciclado
+        nonRecycledPlastic: Plástico no reciclado
+        minSalesQuantity: Cantidad mínima de venta
+        genus: Genus
+        specie: Specie
     buyRequest:
-        ticketId: 'ID Ticket'
-        requester: 'Solicitante'
-        requested: 'Solicitado'
-        price: 'Precio'
-        attender: 'Comprador'
-        item: 'Artículo'
-        achieved: 'Conseguido'
-        concept: 'Concepto'
-        state: 'Estado'
+        requester: Solicitante
+        requested: Solicitado
+        attender: Comprador
+        achieved: Conseguido
+        concept: Concepto
 components:
     topbar: {}
     itemsFilterPanel:
         typeFk: Tipo
-        tag: Etiqueta
         value: Valor
         # ItemFixedPriceFilter
         buyerFk: Comprador
-        warehouseFk: Almacén
         started: Desde
         ended: Hasta
         mine: Para mi
         hasMinPrice: Precio mínimo
         # LatestBuysFilter
         salesPersonFk: Comprador
-        supplierFk: Proveedor
         active: Activo
-        visible: Visible
         floramondo: Floramondo
         showBadDates: Ver items a futuro
     userPanel:
diff --git a/src/pages/Department/Card/DepartmentBasicData.vue b/src/pages/Department/Card/DepartmentBasicData.vue
index 384881792..07bccd971 100644
--- a/src/pages/Department/Card/DepartmentBasicData.vue
+++ b/src/pages/Department/Card/DepartmentBasicData.vue
@@ -20,9 +20,9 @@ const { t } = useI18n();
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
-                    :label="t('department.name')"
+                    :label="t('globals.name')"
                     v-model="data.name"
-                    :rules="validate('department.name')"
+                    :rules="validate('globals.name')"
                     clearable
                     autofocus
                 />
@@ -42,8 +42,8 @@ const { t } = useI18n();
                 />
                 <VnInput
                     v-model="data.notificationEmail"
-                    :label="t('department.email')"
-                    :rules="validate('department.email')"
+                    :label="t('globals.params.email')"
+                    :rules="validate('globals.params.email')"
                     clearable
                 />
             </VnRow>
diff --git a/src/pages/Department/Card/DepartmentSummary.vue b/src/pages/Department/Card/DepartmentSummary.vue
index 05a9e073e..623eab94a 100644
--- a/src/pages/Department/Card/DepartmentSummary.vue
+++ b/src/pages/Department/Card/DepartmentSummary.vue
@@ -45,11 +45,7 @@ onMounted(async () => {
                 />
                 <div class="full-width row wrap justify-between content-between">
                     <div class="column" style="min-width: 50%">
-                        <VnLv
-                            :label="t('department.name')"
-                            :value="department.name"
-                            dash
-                        />
+                        <VnLv :label="t('globals.name')" :value="department.name" dash />
                         <VnLv :label="t('globals.code')" :value="department.code" dash />
                         <VnLv
                             :label="t('department.chat')"
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index 2a00bfd74..64ef60956 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -53,7 +53,7 @@ const onFilterTravelSelected = (formData, id) => {
         <template #form="{ data }">
             <VnRow>
                 <VnSelect
-                    :label="t('entry.basicData.supplier')"
+                    :label="t('globals.supplier')"
                     v-model="data.supplierFk"
                     url="Suppliers"
                     option-value="id"
@@ -113,10 +113,10 @@ const onFilterTravelSelected = (formData, id) => {
             <VnRow>
                 <VnInput
                     v-model="data.invoiceNumber"
-                    :label="t('entry.basicData.invoiceNumber')"
+                    :label="t('entry.summary.invoiceNumber')"
                 />
                 <VnSelect
-                    :label="t('entry.basicData.company')"
+                    :label="t('globals.company')"
                     v-model="data.companyFk"
                     :options="companiesOptions"
                     option-value="id"
@@ -128,14 +128,14 @@ const onFilterTravelSelected = (formData, id) => {
             </VnRow>
             <VnRow>
                 <VnSelect
-                    :label="t('entry.basicData.currency')"
+                    :label="t('entry.summary.currency')"
                     v-model="data.currencyFk"
                     :options="currenciesOptions"
                     option-value="id"
                     option-label="code"
                 />
                 <QInput
-                    :label="t('entry.basicData.commission')"
+                    :label="t('entry.summary.commission')"
                     v-model="data.commission"
                     type="number"
                     autofocus
@@ -153,17 +153,11 @@ const onFilterTravelSelected = (formData, id) => {
                 />
             </VnRow>
             <VnRow>
-                <QCheckbox
-                    v-model="data.isOrdered"
-                    :label="t('entry.basicData.ordered')"
-                />
-                <QCheckbox
-                    v-model="data.isConfirmed"
-                    :label="t('entry.basicData.confirmed')"
-                />
+                <QCheckbox v-model="data.isOrdered" :label="t('entry.summary.ordered')" />
+                <QCheckbox v-model="data.isConfirmed" :label="t('globals.confirmed')" />
                 <QCheckbox
                     v-model="data.isExcludedFromAvailable"
-                    :label="t('entry.basicData.excludedFromAvailable')"
+                    :label="t('entry.summary.excludedFromAvailable')"
                 />
                 <QCheckbox v-model="data.isRaid" :label="t('entry.basicData.raid')" />
                 <QCheckbox
diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue
index 35972b85a..98ce884cf 100644
--- a/src/pages/Entry/Card/EntryBuys.vue
+++ b/src/pages/Entry/Card/EntryBuys.vue
@@ -156,7 +156,7 @@ const tableColumnComponents = computed(() => ({
 const entriesTableColumns = computed(() => {
     return [
         {
-            label: t('entry.summary.item'),
+            label: t('globals.item'),
             field: 'itemFk',
             name: 'item',
             align: 'left',
@@ -211,13 +211,13 @@ const entriesTableColumns = computed(() => {
             format: (value) => toCurrency(value),
         },
         {
-            label: t('entry.buys.groupingPrice'),
+            label: t('item.fixedPrice.groupingPrice'),
             field: 'price2',
             name: 'price2',
             align: 'left',
         },
         {
-            label: t('entry.buys.packingPrice'),
+            label: t('item.fixedPrice.packingPrice'),
             field: 'price3',
             name: 'price3',
             align: 'left',
diff --git a/src/pages/Entry/Card/EntryBuysImport.vue b/src/pages/Entry/Card/EntryBuysImport.vue
index 36ca3b797..c03b7756f 100644
--- a/src/pages/Entry/Card/EntryBuysImport.vue
+++ b/src/pages/Entry/Card/EntryBuysImport.vue
@@ -35,7 +35,7 @@ const packagingsOptions = ref([]);
 
 const columns = computed(() => [
     {
-        label: t('entry.buys.item'),
+        label: t('globals.item'),
         name: 'item',
         field: 'itemFk',
         options: lastItemBuysOptions.value,
@@ -56,19 +56,19 @@ const columns = computed(() => [
         align: 'left',
     },
     {
-        label: t('entry.buys.packing'),
+        label: t('entry.summary.packing'),
         name: 'packing',
         field: 'packing',
         align: 'left',
     },
     {
-        label: t('entry.buys.grouping'),
+        label: t('entry.summary.grouping'),
         name: 'grouping',
         field: 'grouping',
         align: 'left',
     },
     {
-        label: t('entry.buys.buyingValue'),
+        label: t('entry.summary.buyingValue'),
         name: 'buyingValue',
         field: 'buyingValue',
         align: 'left',
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index b22d6ba53..fa75e820d 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -122,14 +122,11 @@ watch;
             </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv
-                :label="t('entry.descriptor.agency')"
-                :value="entity.travel?.agency?.name"
-            />
+            <VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
             <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
             <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
             <VnLv
-                :label="t('entry.descriptor.warehouseOut')"
+                :label="t('globals.warehouseOut')"
                 :value="entity.travel?.warehouseOut?.name"
             />
         </template>
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index 0ed2e8a67..9fe9ae265 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -189,7 +189,7 @@ const fetchEntryBuys = async () => {
                     :label="t('entry.summary.currency')"
                     :value="entry.currency?.name"
                 />
-                <VnLv :label="t('entry.summary.company')" :value="entry.company.code" />
+                <VnLv :label="t('globals.company')" :value="entry.company.code" />
                 <VnLv :label="t('globals.reference')" :value="entry.reference" />
                 <VnLv
                     :label="t('entry.summary.invoiceNumber')"
@@ -218,7 +218,7 @@ const fetchEntryBuys = async () => {
                 />
                 <VnLv :label="t('shipped')" :value="toDate(entry.travel.shipped)" />
                 <VnLv
-                    :label="t('entry.summary.travelWarehouseOut')"
+                    :label="t('globals.warehouseOut')"
                     :value="entry.travel.warehouseOut?.name"
                 />
                 <QCheckbox
@@ -228,7 +228,7 @@ const fetchEntryBuys = async () => {
                 />
                 <VnLv :label="t('landed')" :value="toDate(entry.travel.landed)" />
                 <VnLv
-                    :label="t('entry.summary.travelWarehouseIn')"
+                    :label="t('globals.warehouseIn')"
                     :value="entry.travel.warehouseIn?.name"
                 />
                 <QCheckbox
@@ -251,7 +251,7 @@ const fetchEntryBuys = async () => {
                     :disable="true"
                 />
                 <QCheckbox
-                    :label="t('entry.summary.confirmed')"
+                    :label="t('globals.confirmed')"
                     v-model="entry.isConfirmed"
                     :disable="true"
                 />
diff --git a/src/pages/Entry/EntryBuysTableDialog.vue b/src/pages/Entry/EntryBuysTableDialog.vue
index 0f9be6298..960c936ee 100644
--- a/src/pages/Entry/EntryBuysTableDialog.vue
+++ b/src/pages/Entry/EntryBuysTableDialog.vue
@@ -35,7 +35,7 @@ const entriesTableColumns = computed(() => [
     {
         align: 'left',
         name: 'item',
-        label: t('entry.summary.item'),
+        label: t('globals.item'),
         field: (row) => row.item.name,
     },
     {
diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue
index 756948182..9e1492bb6 100644
--- a/src/pages/Entry/EntryLatestBuys.vue
+++ b/src/pages/Entry/EntryLatestBuys.vue
@@ -37,12 +37,12 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.packing'),
+        label: t('entry.summary.packing'),
         name: 'packing',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.grouping'),
+        label: t('entry.summary.grouping'),
         name: 'grouping',
     },
     {
@@ -57,27 +57,27 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.size'),
+        label: t('globals.size'),
         name: 'size',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.tags'),
+        label: t('globals.tags'),
         name: 'tags',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.type'),
+        label: t('globals.type'),
         name: 'type',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.intrastat'),
+        label: t('globals.intrastat'),
         name: 'intrastat',
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.origin'),
+        label: t('globals.origin'),
         name: 'origin',
     },
     {
@@ -102,7 +102,7 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.buyingValue'),
+        label: t('entry.summary.buyingValue'),
         name: 'buyingValue',
     },
     {
@@ -117,7 +117,7 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.packageValue'),
+        label: t('entry.buys.packageValue'),
         name: 'packageValue',
     },
     {
@@ -152,7 +152,7 @@ const columns = [
     },
     {
         align: 'left',
-        label: t('entry.latestBuys.tableVisibleColumns.packagingFk'),
+        label: t('entry.buys.packagingFk'),
         name: 'packagingFk',
     },
     {
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index e44e3891e..2bfea2a4d 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -43,7 +43,7 @@ const entryFilter = {
 const columns = computed(() => [
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.id'),
+        label: t('globals.id'),
         name: 'id',
         isTitle: true,
         cardVisible: true,
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
index 5e4be407e..2b60948dd 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
@@ -69,7 +69,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
         <template #body="{ entity }">
             <VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" />
             <VnLv :label="t('globals.amount')" :value="toCurrency(entity.amount)" />
-            <VnLv v-if="entity.client" :label="t('invoiceOut.card.client')">
+            <VnLv v-if="entity.client" :label="t('globals.client')">
                 <template #value>
                     <span class="link">
                         {{ entity.client.name }}
@@ -79,7 +79,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
             </VnLv>
             <VnLv
                 v-if="entity.company"
-                :label="t('invoiceOut.card.company')"
+                :label="t('globals.company')"
                 :value="entity.company.code"
             />
         </template>
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
index 83b1bf8a4..027f08109 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
@@ -42,7 +42,7 @@ function fetch() {
 const taxColumns = ref([
     {
         name: 'item',
-        label: 'invoiceOut.summary.type',
+        label: 'globals.type',
         field: (row) => row.name,
         sortable: true,
     },
@@ -72,14 +72,14 @@ const taxColumns = ref([
 const ticketsColumns = ref([
     {
         name: 'item',
-        label: t('invoiceOut.summary.ticketId'),
+        label: t('globals.ticketId'),
         field: (row) => row.id,
         sortable: true,
         align: 'left',
     },
     {
         name: 'quantity',
-        label: t('invoiceOut.summary.nickname'),
+        label: t('globals.alias'),
         field: (row) => row.nickname,
         sortable: true,
         align: 'left',
@@ -124,18 +124,12 @@ const ticketsColumns = ref([
                     :label="t('invoiceOut.summary.dued')"
                     :value="toDate(invoiceOut.dued)"
                 />
-                <VnLv
-                    :label="t('invoiceOut.summary.created')"
-                    :value="toDate(invoiceOut.created)"
-                />
+                <VnLv :label="t('globals.created')" :value="toDate(invoiceOut.created)" />
                 <VnLv
                     :label="t('invoiceOut.summary.booked')"
                     :value="toDate(invoiceOut.booked)"
                 />
-                <VnLv
-                    :label="t('invoiceOut.summary.company')"
-                    :value="invoiceOut.company.code"
-                />
+                <VnLv :label="t('globals.company')" :value="invoiceOut.company.code" />
             </QCard>
             <QCard class="vn-three">
                 <VnTitle :text="t('invoiceOut.summary.taxBreakdown')" />
diff --git a/src/pages/InvoiceOut/InvoiceOutGlobal.vue b/src/pages/InvoiceOut/InvoiceOutGlobal.vue
index 5f2eb3c02..7f6bf41d3 100644
--- a/src/pages/InvoiceOut/InvoiceOutGlobal.vue
+++ b/src/pages/InvoiceOut/InvoiceOutGlobal.vue
@@ -59,7 +59,7 @@ const columns = computed(() => [
         field: 'clientId',
     },
     {
-        label: t('invoiceOut.globalInvoices.table.client'),
+        label: t('globals.client'),
         field: 'clientName',
         name: 'clientName',
         align: 'left',
diff --git a/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue b/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
index cf4c27e65..8c8c01e9c 100644
--- a/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
+++ b/src/pages/InvoiceOut/InvoiceOutNegativeBasesFilter.vue
@@ -51,7 +51,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInput
                         v-model="params.company"
-                        :label="t('invoiceOut.negativeBases.company')"
+                        :label="t('globals.company')"
                         is-outlined
                     />
                 </QItemSection>
@@ -60,7 +60,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInput
                         v-model="params.country"
-                        :label="t('invoiceOut.negativeBases.country')"
+                        :label="t('globals.country')"
                         is-outlined
                     />
                 </QItemSection>
@@ -79,7 +79,7 @@ const props = defineProps({
                 <QItemSection>
                     <VnInput
                         v-model="params.clientSocialName"
-                        :label="t('invoiceOut.negativeBases.client')"
+                        :label="t('globals.client')"
                         is-outlined
                     />
                 </QItemSection>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index ef844824f..805ba6e11 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -173,10 +173,7 @@ const openCloneDialog = async () => {
                     </span>
                 </template>
             </VnLv>
-            <VnLv
-                :label="t('item.descriptor.producer')"
-                :value="dashIfEmpty(entity.subName)"
-            />
+            <VnLv :label="t('globals.producer')" :value="dashIfEmpty(entity.subName)" />
             <VnLv
                 v-if="entity.value5"
                 :label="t('item.descriptor.color')"
@@ -190,7 +187,7 @@ const openCloneDialog = async () => {
             />
             <VnLv
                 v-if="entity.value7"
-                :label="t('item.descriptor.stems')"
+                :label="t('item.list.stems')"
                 :value="entity.value7"
             />
         </template>
diff --git a/src/pages/Item/Card/ItemDescriptorImage.vue b/src/pages/Item/Card/ItemDescriptorImage.vue
index a4ef22ce3..063c77c65 100644
--- a/src/pages/Item/Card/ItemDescriptorImage.vue
+++ b/src/pages/Item/Card/ItemDescriptorImage.vue
@@ -75,7 +75,7 @@ const handlePhotoUpdated = (evt = false) => {
                             <QIcon name="vn:item" />
                         </div>
                         <div class="text-grey-5" style="opacity: 0.4">
-                            {{ t('item.descriptor.item') }}
+                            {{ t('globals.item') }}
                         </div>
                     </div>
                 </div>
@@ -107,7 +107,7 @@ const handlePhotoUpdated = (evt = false) => {
     >
         <div class="col column items-center">
             <span class="text-uppercase color-vn-white" style="font-size: 11px">
-                {{ t('item.descriptor.visible') }}
+                {{ t('globals.visible') }}
             </span>
             <span class="text-weight-bold text-h5 color-vn-white">{{ visible }}</span>
         </div>
diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index dd2c0649b..4570b2319 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -57,11 +57,11 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                     :url="getUrl(entityId, 'basic-data')"
                     :text="t('globals.summary.basicData')"
                 />
-                <VnLv :label="t('item.summary.name')" :value="item.name" />
+                <VnLv :label="t('globals.name')" :value="item.name" />
                 <VnLv :label="t('item.summary.completeName')" :value="item.longName" />
                 <VnLv :label="t('item.summary.family')" :value="item.itemType.name" />
-                <VnLv :label="t('item.summary.size')" :value="item.size" />
-                <VnLv :label="t('item.summary.origin')" :value="item.origin.name" />
+                <VnLv :label="t('globals.size')" :value="item.size" />
+                <VnLv :label="t('globals.origin')" :value="item.origin.name" />
                 <VnLv :label="t('item.summary.stems')" :value="item.stems" />
                 <VnLv
                     :label="t('item.summary.multiplier')"
@@ -96,7 +96,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                     :value="item.intrastat.id"
                 />
                 <VnLv
-                    :label="t('item.summary.intrastat')"
+                    :label="t('globals.intrastat')"
                     :value="item.intrastat.description"
                 />
                 <VnLv :label="t('item.summary.ref')" :value="item.comment" />
@@ -115,7 +115,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                 />
             </QCard>
             <QCard class="vn-one">
-                <VnTitle :url="getUrl(entityId, 'tags')" :text="t('item.summary.tags')" />
+                <VnTitle :url="getUrl(entityId, 'tags')" :text="t('globals.tags')" />
                 <VnLv
                     v-for="(tag, index) in tags"
                     :key="index"
diff --git a/src/pages/Item/ItemCreate.vue b/src/pages/Item/ItemCreate.vue
index 6b6234b70..d69153820 100644
--- a/src/pages/Item/ItemCreate.vue
+++ b/src/pages/Item/ItemCreate.vue
@@ -86,12 +86,9 @@ onBeforeMount(async () => {
         >
             <template #form="{ data }">
                 <VnRow>
-                    <VnInput
-                        v-model="data.provisionalName"
-                        :label="t('item.create.name')"
-                    />
+                    <VnInput v-model="data.provisionalName" :label="t('globals.name')" />
                     <VnSelect
-                        :label="t('item.create.tag')"
+                        :label="t('globals.tag')"
                         v-model="data.tag"
                         :options="tagsOptions"
                         option-value="id"
@@ -109,7 +106,7 @@ onBeforeMount(async () => {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('item.create.type')"
+                        :label="t('globals.type')"
                         v-model="data.typeFk"
                         :options="itemTypesOptions"
                         option-label="name"
@@ -133,7 +130,7 @@ onBeforeMount(async () => {
                         </template>
                     </VnSelect>
                     <VnSelect
-                        :label="t('item.create.intrastat')"
+                        :label="t('globals.intrastat')"
                         v-model="data.intrastatFk"
                         :options="intrastatsOptions"
                         option-label="description"
@@ -156,7 +153,7 @@ onBeforeMount(async () => {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('item.create.origin')"
+                        :label="t('globals.origin')"
                         v-model="data.originFk"
                         :options="originsOptions"
                         option-value="id"
diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 7d4d6b896..4205d8344 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -132,7 +132,7 @@ const columns = computed(() => [
     },
 
     {
-        label: t('item.fixedPrice.warehouse'),
+        label: t('globals.warehouse'),
         field: 'warehouseFk',
         name: 'warehouseFk',
         ...defaultColumnAttrs,
@@ -192,7 +192,7 @@ const editTableFieldsOptions = [
     },
     {
         field: 'warehouseFk',
-        label: t('item.fixedPrice.warehouse'),
+        label: t('globals.warehouse'),
         component: 'select',
         attrs: {
             options: [],
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index ae4c9531c..2ad9c92d0 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -114,7 +114,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('item.list.grouping'),
+        label: t('entry.summary.grouping'),
         field: 'grouping',
         name: 'grouping',
         align: 'left',
@@ -131,7 +131,7 @@ const columns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('item.list.packing'),
+        label: t('entry.summary.packing'),
         field: 'packing',
         name: 'packing',
         align: 'left',
@@ -180,7 +180,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('item.list.size'),
+        label: t('globals.size'),
         field: 'size',
         name: 'size',
         align: 'left',
@@ -237,7 +237,7 @@ const columns = computed(() => [
     },
 
     {
-        label: t('item.list.intrastat'),
+        label: t('globals.intrastat'),
         field: 'intrastat',
         name: 'intrastat',
         align: 'left',
@@ -256,7 +256,7 @@ const columns = computed(() => [
         },
     },
     {
-        label: t('item.list.origin'),
+        label: t('globals.origin'),
         field: 'origin',
         name: 'origin',
         align: 'left',
@@ -337,7 +337,7 @@ const columns = computed(() => [
         columnFilter: null,
     },
     {
-        label: t('item.list.producer'),
+        label: t('globals.producer'),
         field: 'producer',
         name: 'producer',
         align: 'left',
@@ -354,7 +354,7 @@ const columns = computed(() => [
         format: (val) => dashIfEmpty(val),
     },
     {
-        label: t('item.list.landed'),
+        label: t('globals.landed'),
         field: 'landed',
         name: 'landed',
         align: 'left',
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 7dd961a35..be378893e 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -40,7 +40,7 @@ watch(
 
 const columns = computed(() => [
     {
-        label: t('item.buyRequest.ticketId'),
+        label: t('globals.ticketId'),
         name: 'id',
         field: 'id',
         align: 'left',
@@ -74,7 +74,7 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('item.buyRequest.price'),
+        label: t('globals.price'),
         field: 'price',
         name: 'price',
         align: 'left',
@@ -89,7 +89,7 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('item.buyRequest.item'),
+        label: t('globals.item'),
         field: 'item',
         name: 'item',
         align: 'left',
@@ -110,7 +110,7 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('item.buyRequest.state'),
+        label: t('globals.state'),
         field: 'state',
         name: 'state',
         align: 'left',
diff --git a/src/pages/Order/Card/OrderBasicData.vue b/src/pages/Order/Card/OrderBasicData.vue
index 4bc9e2e43..dc8d1a429 100644
--- a/src/pages/Order/Card/OrderBasicData.vue
+++ b/src/pages/Order/Card/OrderBasicData.vue
@@ -162,7 +162,7 @@ const onClientChange = async (clientId) => {
                 <VnRow>
                     <VnInputDate
                         placeholder="dd-mm-aaa"
-                        :label="t('order.form.landed')"
+                        :label="t('globals.landed')"
                         v-model="data.landed"
                         @update:model-value="
                             () => fetchAgencyList(data.landed, data.addressFk)
diff --git a/src/pages/Order/Card/OrderCreateDialog.vue b/src/pages/Order/Card/OrderCreateDialog.vue
index bcc62aa43..b9b232115 100644
--- a/src/pages/Order/Card/OrderCreateDialog.vue
+++ b/src/pages/Order/Card/OrderCreateDialog.vue
@@ -10,7 +10,6 @@ import VnSelect from 'components/common/VnSelect.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
 import { useDialogPluginComponent } from 'quasar';
 import { reactive } from 'vue';
-import FetchData from 'components/FetchData.vue';
 
 const { t } = useI18n();
 const state = useState();
@@ -186,7 +185,7 @@ onMounted(async () => {
             <VnRow class="row q-gutter-md q-mb-md">
                 <VnInputDate
                     placeholder="dd-mm-aaa"
-                    :label="t('order.form.landed')"
+                    :label="t('globals.landed')"
                     v-model="data.landed"
                     @update:model-value="
                         () => fetchAgencyList(data.landed, data.addressId)
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index a035971b0..0bd645e42 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -67,7 +67,7 @@ const setData = (entity) => {
 };
 
 const getConfirmationValue = (isConfirmed) => {
-    return t(isConfirmed ? 'order.summary.confirmed' : 'order.summary.notConfirmed');
+    return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
 };
 
 const total = ref(null);
@@ -98,7 +98,7 @@ function ticketFilter(order) {
         </template>
         <template #body="{ entity }">
             <VnLv
-                :label="t('order.summary.state')"
+                :label="t('globals.state')"
                 :value="getConfirmationValue(entity.isConfirmed)"
             />
             <VnLv :label="t('order.field.salesPersonFk')">
@@ -109,9 +109,9 @@ function ticketFilter(order) {
                     </span>
                 </template>
             </VnLv>
-            <VnLv :label="t('order.summary.landed')" :value="toDate(entity?.landed)" />
-            <VnLv :label="t('order.field.agency')" :value="entity?.agencyMode?.name" />
-            <VnLv :label="t('order.summary.alias')" :value="entity?.address?.nickname" />
+            <VnLv :label="t('globals.landed')" :value="toDate(entity?.landed)" />
+            <VnLv :label="t('globals.agency')" :value="entity?.agencyMode?.name" />
+            <VnLv :label="t('globals.alias')" :value="entity?.address?.nickname" />
             <VnLv
                 :label="t('order.summary.items')"
                 :value="(entity?.rows?.length || DEFAULT_ITEMS).toString()"
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index ceacbc75b..9e9c371bf 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -24,7 +24,7 @@ const entityId = computed(() => $props.id || route.params.id);
 const detailsColumns = ref([
     {
         name: 'item',
-        label: t('order.summary.item'),
+        label: t('globals.item'),
         field: (row) => row?.item?.id,
         sortable: true,
     },
@@ -40,7 +40,7 @@ const detailsColumns = ref([
     },
     {
         name: 'price',
-        label: t('order.summary.price'),
+        label: t('globals.price'),
         field: (row) => toCurrency(row?.price),
     },
     {
@@ -69,7 +69,7 @@ const detailsColumns = ref([
                         :text="t('globals.pageTitles.basicData')"
                     />
                     <VnLv label="ID" :value="entity.id" />
-                    <VnLv :label="t('order.summary.nickname')" dash>
+                    <VnLv :label="t('globals.alias')" dash>
                         <template #value>
                             <span class="link">
                                 {{ dashIfEmpty(entity?.address?.nickname) }}
@@ -78,11 +78,11 @@ const detailsColumns = ref([
                         </template>
                     </VnLv>
                     <VnLv
-                        :label="t('order.summary.company')"
+                        :label="t('globals.company')"
                         :value="entity?.address?.companyFk"
                     />
                     <VnLv
-                        :label="t('order.summary.confirmed')"
+                        :label="t('globals.confirmed')"
                         :value="Boolean(entity?.isConfirmed)"
                     />
                 </QCard>
@@ -96,14 +96,14 @@ const detailsColumns = ref([
                         :value="toDateHourMinSec(entity?.created)"
                     />
                     <VnLv
-                        :label="t('order.summary.confirmed')"
+                        :label="t('globals.confirmed')"
                         :value="toDateHourMinSec(entity?.confirmed)"
                     />
                     <VnLv
-                        :label="t('order.summary.landed')"
+                        :label="t('globals.landed')"
                         :value="toDateHourMinSec(entity?.landed)"
                     />
-                    <VnLv :label="t('order.summary.phone')">
+                    <VnLv :label="t('globals.phone')">
                         <template #value>
                             {{ dashIfEmpty(entity?.address?.phone) }}
                             <a
@@ -135,7 +135,7 @@ const detailsColumns = ref([
                     <VnTitle :text="t('order.summary.total')" />
                     <VnLv>
                         <template #label>
-                            <span class="text-h6">{{ t('order.summary.subtotal') }}</span>
+                            <span class="text-h6">{{ t('globals.subtotal') }}</span>
                         </template>
                         <template #value>
                             <span class="text-h6">{{
@@ -145,7 +145,7 @@ const detailsColumns = ref([
                     </VnLv>
                     <VnLv>
                         <template #label>
-                            <span class="text-h6">{{ t('order.summary.vat') }}</span>
+                            <span class="text-h6">{{ t('globals.vat') }}</span>
                         </template>
                         <template #value>
                             <span class="text-h6">{{ toCurrency(entity?.VAT) }}</span>
@@ -165,10 +165,10 @@ const detailsColumns = ref([
                     <QTable :columns="detailsColumns" :rows="entity?.rows" flat>
                         <template #header="props">
                             <QTr :props="props">
-                                <QTh auto-width>{{ t('order.summary.item') }}</QTh>
+                                <QTh auto-width>{{ t('globals.item') }}</QTh>
                                 <QTh>{{ t('globals.description') }}</QTh>
                                 <QTh auto-width>{{ t('globals.quantity') }}</QTh>
-                                <QTh auto-width>{{ t('order.summary.price') }}</QTh>
+                                <QTh auto-width>{{ t('globals.price') }}</QTh>
                                 <QTh auto-width>{{ t('order.summary.amount') }}</QTh>
                             </QTr>
                         </template>
diff --git a/src/pages/Shelving/Card/ShelvingDescriptor.vue b/src/pages/Shelving/Card/ShelvingDescriptor.vue
index 30e807d20..b1ff4a8ae 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptor.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptor.vue
@@ -54,8 +54,8 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
     >
         <template #body="{ entity }">
             <VnLv :label="t('globals.code')" :value="entity.code" />
-            <VnLv :label="t('shelving.summary.parking')" :value="entity.parking?.code" />
-            <VnLv v-if="entity.worker" :label="t('shelving.summary.worker')">
+            <VnLv :label="t('shelving.list.parking')" :value="entity.parking?.code" />
+            <VnLv v-if="entity.worker" :label="t('globals.worker')">
                 <template #value>
                     <VnUserLink
                         :name="entity.worker?.user?.nickname"
diff --git a/src/pages/Shelving/Card/ShelvingForm.vue b/src/pages/Shelving/Card/ShelvingForm.vue
index f69d427b0..3bbd94a0a 100644
--- a/src/pages/Shelving/Card/ShelvingForm.vue
+++ b/src/pages/Shelving/Card/ShelvingForm.vue
@@ -68,7 +68,7 @@ const onSave = (shelving, newShelving) => {
                     option-label="code"
                     :filter-options="['id', 'code']"
                     :fields="['id', 'code']"
-                    :label="t('shelving.basicData.parking')"
+                    :label="t('shelving.list.parking')"
                     :rules="validate('Shelving.parkingFk')"
                 />
             </VnRow>
@@ -76,12 +76,12 @@ const onSave = (shelving, newShelving) => {
                 <VnInput
                     v-model="data.priority"
                     type="number"
-                    :label="t('shelving.basicData.priority')"
+                    :label="t('shelving.list.priority')"
                     :rules="validate('Shelving.priority')"
                 />
                 <QCheckbox
                     v-model="data.isRecyclable"
-                    :label="t('shelving.basicData.recyclable')"
+                    :label="t('shelving.summary.recyclable')"
                     :rules="validate('Shelving.isRecyclable')"
                 />
             </VnRow>
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index a196b1992..db7ac34f5 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -56,14 +56,11 @@ const filter = {
                     </RouterLink>
                     <VnLv :label="t('globals.code')" :value="entity.code" />
                     <VnLv
-                        :label="t('shelving.summary.parking')"
+                        :label="t('shelving.list.parking')"
                         :value="entity.parking?.code"
                     />
-                    <VnLv
-                        :label="t('shelving.summary.priority')"
-                        :value="entity.priority"
-                    />
-                    <VnLv v-if="entity.worker" :label="t('shelving.summary.worker')">
+                    <VnLv :label="t('shelving.list.priority')" :value="entity.priority" />
+                    <VnLv v-if="entity.worker" :label="t('globals.worker')">
                         <template #value>
                             <VnUserLink
                                 :name="entity.worker?.user?.nickname"
diff --git a/src/pages/Supplier/Card/SupplierAddresses.vue b/src/pages/Supplier/Card/SupplierAddresses.vue
index f46a3be19..f1e95b8de 100644
--- a/src/pages/Supplier/Card/SupplierAddresses.vue
+++ b/src/pages/Supplier/Card/SupplierAddresses.vue
@@ -69,16 +69,13 @@ const redirectToUpdateView = (addressData) => {
                         @click="redirectToUpdateView(row)"
                     >
                         <template #list-items>
+                            <VnLv :label="t('globals.street')" :value="row.street" />
                             <VnLv
-                                :label="t('supplier.addresses.street')"
-                                :value="row.street"
-                            />
-                            <VnLv
-                                :label="t('supplier.addresses.postcode')"
+                                :label="t('globals.postcode')"
                                 :value="`${row.postalCode} - ${row.city}, ${row.province.name}`"
                             />
                             <VnLv
-                                :label="t('supplier.addresses.phone')"
+                                :label="t('globals.phone')"
                                 :value="`${row.phone}, ${row.mobile}`"
                             />
                         </template>
diff --git a/src/pages/Supplier/Card/SupplierAddressesCreate.vue b/src/pages/Supplier/Card/SupplierAddressesCreate.vue
index 0feceb74a..7a078f03b 100644
--- a/src/pages/Supplier/Card/SupplierAddressesCreate.vue
+++ b/src/pages/Supplier/Card/SupplierAddressesCreate.vue
@@ -72,14 +72,8 @@ function handleLocation(data, location) {
         >
             <template #form="{ data, validate }">
                 <VnRow>
-                    <VnInput
-                        v-model="data.nickname"
-                        :label="t('supplier.addresses.name')"
-                    />
-                    <VnInput
-                        v-model="data.street"
-                        :label="t('supplier.addresses.street')"
-                    />
+                    <VnInput v-model="data.nickname" :label="t('globals.name')" />
+                    <VnInput v-model="data.street" :label="t('globals.street')" />
                 </VnRow>
                 <VnRow>
                     <VnLocation
@@ -101,14 +95,8 @@ function handleLocation(data, location) {
                     </VnLocation>
                 </VnRow>
                 <VnRow>
-                    <VnInput
-                        v-model="data.phone"
-                        :label="t('supplier.addresses.phone')"
-                    />
-                    <VnInput
-                        v-model="data.mobile"
-                        :label="t('supplier.addresses.mobile')"
-                    />
+                    <VnInput v-model="data.phone" :label="t('globals.phone')" />
+                    <VnInput v-model="data.mobile" :label="t('globals.mobile')" />
                 </VnRow>
             </template>
         </FormModel>
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index 52964557d..101007756 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -24,7 +24,7 @@ const workersOptions = ref([]);
             <VnRow>
                 <VnInput
                     v-model="data.nickname"
-                    :label="t('supplier.basicData.alias')"
+                    :label="t('globals.alias')"
                     :rules="validate('supplier.nickname')"
                     clearable
                 />
diff --git a/src/pages/Supplier/Card/SupplierBillingData.vue b/src/pages/Supplier/Card/SupplierBillingData.vue
index 7200bbba6..05c9858d9 100644
--- a/src/pages/Supplier/Card/SupplierBillingData.vue
+++ b/src/pages/Supplier/Card/SupplierBillingData.vue
@@ -58,7 +58,7 @@ const formatPayDems = (data) => {
             </VnRow>
             <VnRow>
                 <QInput
-                    :label="t('supplier.billingData.payDay')"
+                    :label="t('supplier.summary.payDay')"
                     type="number"
                     v-model="data.payDay"
                 />
diff --git a/src/pages/Supplier/Card/SupplierContacts.vue b/src/pages/Supplier/Card/SupplierContacts.vue
index 3f2063784..6781c8d34 100644
--- a/src/pages/Supplier/Card/SupplierContacts.vue
+++ b/src/pages/Supplier/Card/SupplierContacts.vue
@@ -44,21 +44,12 @@ const insertRow = () => {
                     <VnRow class="row q-gutter-md">
                         <VnInput
                             input-name-focusable
-                            :label="t('supplier.contacts.name')"
+                            :label="t('globals.name')"
                             v-model="row.name"
                         />
-                        <VnInput
-                            :label="t('supplier.contacts.phone')"
-                            v-model="row.phone"
-                        />
-                        <VnInput
-                            :label="t('supplier.contacts.mobile')"
-                            v-model="row.mobile"
-                        />
-                        <VnInput
-                            :label="t('supplier.contacts.email')"
-                            v-model="row.email"
-                        />
+                        <VnInput :label="t('globals.phone')" v-model="row.phone" />
+                        <VnInput :label="t('globals.mobile')" v-model="row.mobile" />
+                        <VnInput :label="t('globals.params.email')" v-model="row.email" />
                     </VnRow>
                     <VnRow class="row q-gutter-md">
                         <QInput
diff --git a/src/pages/Supplier/Card/SupplierDescriptor.vue b/src/pages/Supplier/Card/SupplierDescriptor.vue
index 5754031b3..0fbe03c99 100644
--- a/src/pages/Supplier/Card/SupplierDescriptor.vue
+++ b/src/pages/Supplier/Card/SupplierDescriptor.vue
@@ -116,7 +116,7 @@ const getEntryQueryParams = (supplier) => {
             <VnLv :label="t('supplier.summary.taxNumber')" :value="entity.nif" />
             <VnLv label="Alias" :value="entity.nickname" />
             <VnLv
-                :label="t('supplier.summary.payMethod')"
+                :label="t('supplier.list.payMethod')"
                 :value="entity?.payMethod?.name"
             />
             <VnLv
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index 169c4d796..547842960 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -147,16 +147,12 @@ function handleLocation(data, location) {
                 />
                 <VnInput
                     v-model="data.healthRegister"
-                    :label="t('supplier.fiscalData.healthRegister')"
+                    :label="t('supplier.summary.healthRegister')"
                     clearable
                 />
             </VnRow>
             <VnRow>
-                <VnInput
-                    v-model="data.street"
-                    :label="t('supplier.fiscalData.street')"
-                    clearable
-                />
+                <VnInput v-model="data.street" :label="t('globals.street')" clearable />
             </VnRow>
             <VnRow>
                 <VnLocation
diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue
index 6ffb95344..dbb4c47e1 100644
--- a/src/pages/Supplier/Card/SupplierSummary.vue
+++ b/src/pages/Supplier/Card/SupplierSummary.vue
@@ -82,7 +82,7 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
                     :text="t('supplier.summary.billingData')"
                 />
                 <VnLv
-                    :label="t('supplier.summary.payMethod')"
+                    :label="t('supplier.list.payMethod')"
                     :value="supplier.payMethod?.name"
                     dash
                 />
@@ -131,19 +131,16 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
                 />
                 <VnLv :label="t('supplier.summary.socialName')" :value="supplier.name" />
                 <VnLv :label="t('supplier.summary.taxNumber')" :value="supplier.nif" />
-                <VnLv :label="t('supplier.summary.street')" :value="supplier.street" />
+                <VnLv :label="t('globals.street')" :value="supplier.street" />
                 <VnLv :label="t('supplier.summary.city')" :value="supplier.city" />
-                <VnLv
-                    :label="t('supplier.summary.postCode')"
-                    :value="supplier.postCode"
-                />
+                <VnLv :label="t('globals.postCode')" :value="supplier.postCode" />
                 <VnLv
                     :label="t('supplier.summary.province')"
                     :value="supplier.province?.name"
                     dash
                 />
                 <VnLv
-                    :label="t('supplier.summary.country')"
+                    :label="t('globals.country')"
                     :value="supplier.country?.name"
                     dash
                 />
diff --git a/src/pages/Supplier/SupplierList.vue b/src/pages/Supplier/SupplierList.vue
index ea79947a4..69f826201 100644
--- a/src/pages/Supplier/SupplierList.vue
+++ b/src/pages/Supplier/SupplierList.vue
@@ -12,13 +12,13 @@ const tableRef = ref();
 const columns = computed(() => [
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.id'),
+        label: t('globals.id'),
         name: 'id',
         isTitle: true,
     },
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.name'),
+        label: t('globals.name'),
         name: 'socialName',
         create: true,
         columnFilter: {
@@ -35,7 +35,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.nickname'),
+        label: t('globals.alias'),
         name: 'alias',
         columnFilter: {
             name: 'search',
@@ -51,7 +51,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.payMethod'),
+        label: t('supplier.list.payMethod'),
         name: 'payMethod',
         columnFilter: {
             inWhere: true,
@@ -70,7 +70,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.payDay'),
+        label: t('supplier.summary.payDay'),
         name: 'payDay',
         columnFilter: {
             inWhere: true,
@@ -79,7 +79,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('supplier.list.tableVisibleColumns.country'),
+        label: t('globals.country'),
         name: 'country',
         columnFilter: {
             component: 'select',
diff --git a/src/pages/Ticket/Card/TicketBoxing.vue b/src/pages/Ticket/Card/TicketBoxing.vue
index bff95c0e2..1a7287396 100644
--- a/src/pages/Ticket/Card/TicketBoxing.vue
+++ b/src/pages/Ticket/Card/TicketBoxing.vue
@@ -136,13 +136,13 @@ async function getVideoList(expeditionId, timed) {
                         <QItemLabel class="text-h6">#{{ expedition.id }}</QItemLabel>
                     </QItemSection>
                     <QItemSection>
-                        <QItemLabel caption>{{ t('ticket.boxing.created') }}</QItemLabel>
+                        <QItemLabel caption>{{ t('globals.created') }}</QItemLabel>
                         <QItemLabel>
                             {{
                                 date.formatDate(expedition.created, 'YYYY-MM-DD HH:mm:ss')
                             }}
                         </QItemLabel>
-                        <QItemLabel caption>{{ t('ticket.boxing.item') }}</QItemLabel>
+                        <QItemLabel caption>{{ t('globals.item') }}</QItemLabel>
                         <QItemLabel>{{ expedition.packagingItemFk }}</QItemLabel>
                         <QItemLabel caption>{{ t('ticket.boxing.worker') }}</QItemLabel>
                         <QItemLabel>{{ expedition.userName }}</QItemLabel>
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index af9021e36..f8ffb43ed 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -125,7 +125,7 @@ function ticketFilter(ticket) {
                     </span>
                 </template>
             </VnLv>
-            <VnLv v-if="entity.ticketState" :label="t('ticket.card.state')">
+            <VnLv v-if="entity.ticketState" :label="t('globals.state')">
                 <template #value>
                     <QBadge
                         text-color="black"
@@ -149,11 +149,11 @@ function ticketFilter(ticket) {
             />
             <VnLv
                 v-if="entity.agencyMode"
-                :label="t('ticket.card.agency')"
+                :label="t('globals.agency')"
                 :value="entity.agencyMode.name"
             />
-            <VnLv :label="t('ticket.card.warehouse')" :value="entity.warehouse?.name" />
-            <VnLv :label="t('ticket.card.alias')" :value="entity.nickname" />
+            <VnLv :label="t('globals.warehouse')" :value="entity.warehouse?.name" />
+            <VnLv :label="t('globals.alias')" :value="entity.nickname" />
         </template>
         <template #icons="{ entity }">
             <QCardActions class="q-gutter-x-xs">
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index ac2ae0509..45769daa5 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -132,7 +132,7 @@ function toTicketUrl(section) {
                     :url="toTicketUrl('basic-data')"
                     :text="t('globals.summary.basicData')"
                 />
-                <VnLv v-if="entity.ticketState" :label="t('ticket.summary.state')">
+                <VnLv v-if="entity.ticketState" :label="t('globals.state')">
                     <template #value>
                         <QBadge
                             text-color="black"
@@ -150,10 +150,7 @@ function toTicketUrl(section) {
                         />
                     </template>
                 </VnLv>
-                <VnLv
-                    :label="t('ticket.summary.agency')"
-                    :value="entity.agencyMode?.name"
-                />
+                <VnLv :label="t('globals.agency')" :value="entity.agencyMode?.name" />
                 <VnLv :label="t('ticket.summary.zone')">
                     <template #value>
                         <span class="link" @click.stop>
@@ -162,10 +159,7 @@ function toTicketUrl(section) {
                         </span>
                     </template>
                 </VnLv>
-                <VnLv
-                    :label="t('ticket.summary.warehouse')"
-                    :value="entity.warehouse?.name"
-                />
+                <VnLv :label="t('globals.warehouse')" :value="entity.warehouse?.name" />
                 <VnLv
                     v-if="ticket?.ticketCollections?.length > 0"
                     :label="t('ticket.summary.collection')"
@@ -211,10 +205,7 @@ function toTicketUrl(section) {
                     :label="t('ticket.summary.shipped')"
                     :value="toDate(entity.shipped)"
                 />
-                <VnLv
-                    :label="t('ticket.summary.landed')"
-                    :value="toDate(entity.landed)"
-                />
+                <VnLv :label="t('globals.landed')" :value="toDate(entity.landed)" />
                 <VnLv :label="t('globals.packages')" :value="entity.packages" />
                 <VnLv :value="entity.address.phone">
                     <template #label>
@@ -281,11 +272,11 @@ function toTicketUrl(section) {
                 <VnTitle :text="t('ticket.summary.summaryAmount')" />
                 <div class="bodyCard">
                     <VnLv
-                        :label="t('ticket.summary.subtotal')"
+                        :label="t('globals.subtotal')"
                         :value="toCurrency(entity.totalWithoutVat)"
                     />
                     <VnLv
-                        :label="t('ticket.summary.vat')"
+                        :label="t('globals.vat')"
                         :value="toCurrency(entity.totalWithVat - entity.totalWithoutVat)"
                     />
                     <VnLv
@@ -307,12 +298,12 @@ function toTicketUrl(section) {
                     <template #header="props">
                         <QTr class="tr-header" :props="props">
                             <QTh auto-width></QTh>
-                            <QTh auto-width>{{ t('ticket.summary.item') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.visible') }}</QTh>
+                            <QTh auto-width>{{ t('globals.item') }}</QTh>
+                            <QTh auto-width>{{ t('globals.visible') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.available') }}</QTh>
                             <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                             <QTh auto-width>{{ t('globals.description') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
+                            <QTh auto-width>{{ t('globals.price') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.discount') }}</QTh>
                             <QTh auto-width>{{ t('globals.amount') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.packing') }}</QTh>
@@ -364,7 +355,7 @@ function toTicketUrl(section) {
                                     size="xs"
                                 >
                                     <QTooltip>
-                                        {{ t('ticket.summary.visible') }}:
+                                        {{ t('globals.visible') }}:
                                         {{ props.row.visible }}
                                     </QTooltip>
                                 </QIcon>
@@ -471,7 +462,7 @@ function toTicketUrl(section) {
                 <QTable :rows="ticket.packagings" flat style="text-align: center">
                     <template #header="props">
                         <QTr class="tr-header" :props="props">
-                            <QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
+                            <QTh auto-width>{{ t('globals.created') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.package') }}</QTh>
                             <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                         </QTr>
@@ -495,7 +486,7 @@ function toTicketUrl(section) {
                         <QTr class="tr-header" :props="props">
                             <QTh auto-width>{{ t('globals.quantity') }}</QTh>
                             <QTh auto-width>{{ t('globals.description') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
+                            <QTh auto-width>{{ t('globals.price') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.taxClass') }}</QTh>
                             <QTh auto-width>{{ t('globals.amount') }}</QTh>
                         </QTr>
@@ -522,12 +513,12 @@ function toTicketUrl(section) {
                     <template #header="props">
                         <QTr class="tr-header" :props="props">
                             <QTh auto-width>{{ t('globals.description') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
+                            <QTh auto-width>{{ t('globals.created') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.requester') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.attender') }}</QTh>
                             <QTh auto-width>{{ t('globals.quantity') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
-                            <QTh auto-width>{{ t('ticket.summary.item') }}</QTh>
+                            <QTh auto-width>{{ t('globals.price') }}</QTh>
+                            <QTh auto-width>{{ t('globals.item') }}</QTh>
                             <QTh auto-width>{{ t('ticket.summary.ok') }}</QTh>
                         </QTr>
                     </template>
diff --git a/src/pages/Ticket/TicketCreate.vue b/src/pages/Ticket/TicketCreate.vue
index 3cc486122..1c6a76e6e 100644
--- a/src/pages/Ticket/TicketCreate.vue
+++ b/src/pages/Ticket/TicketCreate.vue
@@ -134,7 +134,7 @@ const redirectToTicketList = (_, { id }) => {
                 <VnRow>
                     <div class="col">
                         <VnSelect
-                            :label="t('ticket.create.client')"
+                            :label="t('globals.client')"
                             v-model="data.clientId"
                             :options="clientOptions"
                             option-value="id"
@@ -188,7 +188,7 @@ const redirectToTicketList = (_, { id }) => {
                     <div class="col">
                         <VnInputDate
                             placeholder="dd-mm-aaa"
-                            :label="t('ticket.create.landed')"
+                            :label="t('globals.landed')"
                             v-model="data.landed"
                             @update:model-value="() => fetchAvailableAgencies(data)"
                         />
@@ -197,7 +197,7 @@ const redirectToTicketList = (_, { id }) => {
                 <VnRow>
                     <div class="col">
                         <VnSelect
-                            :label="t('ticket.create.warehouse')"
+                            :label="t('globals.warehouse')"
                             v-model="data.warehouseId"
                             :options="warehousesOptions"
                             option-value="id"
@@ -210,7 +210,7 @@ const redirectToTicketList = (_, { id }) => {
                 <VnRow>
                     <div class="col">
                         <VnSelect
-                            :label="t('ticket.create.agency')"
+                            :label="t('globals.agency')"
                             v-model="data.agencyModeId"
                             :options="agenciesOptions"
                             option-value="agencyModeFk"
diff --git a/src/pages/Ticket/TicketCreateDialog.vue b/src/pages/Ticket/TicketCreateDialog.vue
index 4138884bf..ba25a5744 100644
--- a/src/pages/Ticket/TicketCreateDialog.vue
+++ b/src/pages/Ticket/TicketCreateDialog.vue
@@ -128,7 +128,7 @@ const redirectToTicketList = (_, { id }) => {
             <VnRow>
                 <div class="col">
                     <VnSelect
-                        :label="t('ticket.create.client')"
+                        :label="t('globals.client')"
                         v-model="data.clientId"
                         url="Clients"
                         :fields="['id', 'name', 'defaultAddressFk']"
@@ -184,7 +184,7 @@ const redirectToTicketList = (_, { id }) => {
                 <div class="col">
                     <VnInputDate
                         placeholder="dd-mm-aaa"
-                        :label="t('ticket.create.landed')"
+                        :label="t('globals.landed')"
                         v-model="data.landed"
                         @update:model-value="() => fetchAvailableAgencies(data)"
                     />
@@ -193,7 +193,7 @@ const redirectToTicketList = (_, { id }) => {
             <VnRow>
                 <div class="col">
                     <VnSelect
-                        :label="t('ticket.create.warehouse')"
+                        :label="t('globals.warehouse')"
                         v-model="data.warehouseId"
                         :options="warehousesOptions"
                         option-value="id"
@@ -206,7 +206,7 @@ const redirectToTicketList = (_, { id }) => {
             <VnRow>
                 <div class="col">
                     <VnSelect
-                        :label="t('ticket.create.agency')"
+                        :label="t('globals.agency')"
                         v-model="data.agencyModeId"
                         :options="agenciesOptions"
                         option-value="agencyModeFk"
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index ad97e75c1..d50dc5a1b 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -661,7 +661,7 @@ function setReference(data) {
                 <div class="col">
                     <VnInputDate
                         placeholder="dd-mm-aaa"
-                        :label="t('ticket.create.landed')"
+                        :label="t('globals.landed')"
                         v-model="data.landed"
                         @update:model-value="() => fetchAvailableAgencies(data)"
                     />
@@ -672,7 +672,7 @@ function setReference(data) {
                     <VnSelect
                         url="Warehouses"
                         :sort-by="['name']"
-                        :label="t('ticket.create.warehouse')"
+                        :label="t('globals.warehouse')"
                         v-model="data.warehouseId"
                         :options="warehousesOptions"
                         option-value="id"
@@ -685,7 +685,7 @@ function setReference(data) {
             <VnRow>
                 <div class="col">
                     <VnSelect
-                        :label="t('ticket.create.agency')"
+                        :label="t('globals.agency')"
                         v-model="data.agencyModeId"
                         :options="agenciesOptions"
                         option-value="agencyModeFk"
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index ca9caf82d..a3d776795 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -31,7 +31,7 @@ const agenciesOptions = ref([]);
             <VnRow>
                 <VnInput v-model="data.ref" :label="t('globals.reference')" />
                 <VnSelect
-                    :label="t('travel.basicData.agency')"
+                    :label="t('globals.agency')"
                     v-model="data.agencyModeFk"
                     :options="agenciesOptions"
                     option-value="id"
@@ -42,14 +42,11 @@ const agenciesOptions = ref([]);
             </VnRow>
             <VnRow>
                 <VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
-                <VnInputDate
-                    v-model="data.landed"
-                    :label="t('travel.basicData.landed')"
-                />
+                <VnInputDate v-model="data.landed" :label="t('globals.landed')" />
             </VnRow>
             <VnRow>
                 <VnSelect
-                    :label="t('travel.basicData.warehouseOut')"
+                    :label="t('globals.warehouseOut')"
                     v-model="data.warehouseOutFk"
                     :options="agenciesOptions"
                     option-value="id"
@@ -58,7 +55,7 @@ const agenciesOptions = ref([]);
                     hide-selected
                 />
                 <VnSelect
-                    :label="t('travel.basicData.warehouseIn')"
+                    :label="t('globals.warehouseIn')"
                     v-model="data.warehouseInFk"
                     :options="agenciesOptions"
                     option-value="id"
@@ -72,11 +69,11 @@ const agenciesOptions = ref([]);
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('travel.basicData.delivered')"
+                    :label="t('travel.summary.delivered')"
                     v-model="data.isDelivered"
                 />
                 <QCheckbox
-                    :label="t('travel.basicData.received')"
+                    :label="t('travel.summary.received')"
                     v-model="data.isReceived"
                 />
             </VnRow>
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index bda29903b..ba8d7f947 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -71,8 +71,8 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
             <TravelDescriptorMenuItems :travel="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('globals.wareHouseIn')" :value="entity.warehouseIn.name" />
-            <VnLv :label="t('globals.wareHouseOut')" :value="entity.warehouseOut.name" />
+            <VnLv :label="t('globals.warehouseIn')" :value="entity.warehouseIn.name" />
+            <VnLv :label="t('globals.warehouseOut')" :value="entity.warehouseOut.name" />
             <VnLv :label="t('globals.shipped')" :value="toDate(entity.shipped)" />
             <VnLv :label="t('globals.landed')" :value="toDate(entity.landed)" />
             <VnLv :label="t('globals.totalEntries')" :value="entity.totalEntries" />
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index d48ed2847..b8e3c3407 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -33,7 +33,7 @@ const warehouses = ref([]);
 const entriesTableColumns = computed(() => {
     return [
         {
-            label: t('travel.summary.confirmed'),
+            label: t('globals.confirmed'),
             field: 'isConfirmed',
             name: 'isConfirmed',
             align: 'left',
@@ -136,7 +136,7 @@ const thermographsTableColumns = computed(() => {
             format: (val) => (val ? `${val}°` : ''),
         },
         {
-            label: t('travel.thermographs.state'),
+            label: t('globals.state'),
             field: 'result',
             name: 'result',
             align: 'left',
@@ -150,7 +150,7 @@ const thermographsTableColumns = computed(() => {
                 warehouses.value.find((warehouse) => warehouse.id === val)?.name,
         },
         {
-            label: t('travel.thermographs.created'),
+            label: t('globals.created'),
             field: 'created',
             name: 'created',
             align: 'left',
@@ -265,7 +265,7 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 </QCardSection>
                 <VnLv :label="t('globals.shipped')" :value="toDate(travel.shipped)" />
                 <VnLv
-                    :label="t('globals.wareHouseOut')"
+                    :label="t('globals.warehouseOut')"
                     :value="travel.warehouseOut?.name"
                 />
                 <QCheckbox
@@ -283,7 +283,7 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 </QCardSection>
                 <VnLv :label="t('globals.landed')" :value="toDate(travel.landed)" />
                 <VnLv
-                    :label="t('globals.wareHouseIn')"
+                    :label="t('globals.warehouseIn')"
                     :value="travel.warehouseIn?.name"
                 />
                 <QCheckbox
diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index 96544a8ca..0ac8ab5a7 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -62,7 +62,7 @@ const TableColumns = computed(() => {
             format: (val) => (val ? `${val}°` : ''),
         },
         {
-            label: t('travel.thermographs.state'),
+            label: t('globals.state'),
             field: 'result',
             name: 'result',
             align: 'left',
@@ -76,7 +76,7 @@ const TableColumns = computed(() => {
                 warehouses.value.find((warehouse) => warehouse.id === val)?.name,
         },
         {
-            label: t('travel.thermographs.created'),
+            label: t('globals.created'),
             field: 'created',
             name: 'created',
             align: 'left',
diff --git a/src/pages/Travel/Card/TravelThermographsForm.vue b/src/pages/Travel/Card/TravelThermographsForm.vue
index b70e93dfc..4d7b77edf 100644
--- a/src/pages/Travel/Card/TravelThermographsForm.vue
+++ b/src/pages/Travel/Card/TravelThermographsForm.vue
@@ -216,7 +216,7 @@ const onThermographCreated = async (data) => {
                     </VnSelectDialog>
                     <VnInput
                         v-model="thermographForm.state"
-                        :label="t('travel.thermographs.state')"
+                        :label="t('globals.state')"
                     />
                 </VnRow>
                 <VnRow>
@@ -225,7 +225,7 @@ const onThermographCreated = async (data) => {
                         :label="t('globals.reference')"
                     />
                     <VnSelect
-                        :label="t('travel.thermographs.type')"
+                        :label="t('globals.type')"
                         v-model="thermographForm.dmsTypeId"
                         :options="dmsTypesOptions"
                         option-value="id"
@@ -234,14 +234,14 @@ const onThermographCreated = async (data) => {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('travel.thermographs.company')"
+                        :label="t('globals.company')"
                         v-model="thermographForm.companyId"
                         :options="companiesOptions"
                         option-value="id"
                         option-label="code"
                     />
                     <VnSelect
-                        :label="t('travel.thermographs.warehouse')"
+                        :label="t('globals.warehouse')"
                         v-model="thermographForm.warehouseId"
                         :options="warehousesOptions"
                         option-value="id"
diff --git a/src/pages/Travel/ExtraCommunity.vue b/src/pages/Travel/ExtraCommunity.vue
index 4dc7eb052..d45fae5a6 100644
--- a/src/pages/Travel/ExtraCommunity.vue
+++ b/src/pages/Travel/ExtraCommunity.vue
@@ -220,7 +220,7 @@ const columns = computed(() => [
         sortable: true,
     },
     {
-        label: t('globals.wareHouseOut'),
+        label: t('globals.warehouseOut'),
         field: 'warehouseOutName',
         name: 'warehouseOutName',
         align: 'left',
@@ -237,7 +237,7 @@ const columns = computed(() => [
         format: (value) => toDate(value),
     },
     {
-        label: t('globals.wareHouseIn'),
+        label: t('globals.wareHhuseIn'),
         field: 'warehouseInName',
         name: 'warehouseInName',
         align: 'left',
diff --git a/src/pages/Travel/TravelCreate.vue b/src/pages/Travel/TravelCreate.vue
index 6fb3274e4..72c34aad8 100644
--- a/src/pages/Travel/TravelCreate.vue
+++ b/src/pages/Travel/TravelCreate.vue
@@ -74,7 +74,7 @@ const redirectToTravelBasicData = (_, { id }) => {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('globals.wareHouseOut')"
+                        :label="t('globals.warehouseOut')"
                         v-model="data.warehouseOutFk"
                         :options="warehousesOptions"
                         option-value="id"
@@ -82,7 +82,7 @@ const redirectToTravelBasicData = (_, { id }) => {
                         hide-selected
                     />
                     <VnSelect
-                        :label="t('globals.wareHouseIn')"
+                        :label="t('globals.warehouseIn')"
                         v-model="data.warehouseInFk"
                         :options="warehousesOptions"
                         option-value="id"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index 7ea2b3f7a..63d3bf956 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -48,7 +48,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'id',
-        label: t('travel.travelList.tableVisibleColumns.id'),
+        label: t('globals.id'),
         isId: true,
         cardVisible: true,
     },
@@ -66,7 +66,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'agencyModeFk',
-        label: t('travel.travelList.tableVisibleColumns.agency'),
+        label: t('globals.agency'),
         component: 'select',
         attrs: {
             url: 'agencyModes',
@@ -82,7 +82,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'warehouseInFk',
-        label: t('travel.travelList.tableVisibleColumns.warehouseIn'),
+        label: t('globals.warehouseIn'),
         component: 'select',
         attrs: {
             url: 'warehouses',
@@ -118,7 +118,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'warehouseOutFk',
-        label: t('travel.travelList.tableVisibleColumns.warehouseOut'),
+        label: t('globals.warehouseOut'),
         component: 'select',
         attrs: {
             url: 'warehouses',
@@ -134,7 +134,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'landed',
-        label: t('travel.travelList.tableVisibleColumns.landed'),
+        label: t('globals.landed'),
         component: 'date',
         columnField: {
             component: null,
diff --git a/src/pages/Wagon/Type/WagonTypeEdit.vue b/src/pages/Wagon/Type/WagonTypeEdit.vue
index eb8205d72..3de115fc0 100644
--- a/src/pages/Wagon/Type/WagonTypeEdit.vue
+++ b/src/pages/Wagon/Type/WagonTypeEdit.vue
@@ -95,7 +95,7 @@ watch(
                     <VnInput
                         filled
                         v-model="data.name"
-                        :label="t('wagon.type.name')"
+                        :label="t('globals.name')"
                         :rules="[(val) => !!val || t('wagon.warnings.nameNotEmpty')]"
                     />
                     <QCheckbox
diff --git a/src/pages/Wagon/WagonCreate.vue b/src/pages/Wagon/WagonCreate.vue
index 2ec0f4d55..ac2aab6ce 100644
--- a/src/pages/Wagon/WagonCreate.vue
+++ b/src/pages/Wagon/WagonCreate.vue
@@ -103,7 +103,7 @@ function filterType(val, update) {
                     <VnInput
                         filled
                         v-model="wagon.plate"
-                        :label="t('wagon.create.plate')"
+                        :label="t('wagon.list.plate')"
                         :rules="[(val) => !!val || t('wagon.warnings.plateNotEmpty')]"
                     />
                 </div>
@@ -127,7 +127,7 @@ function filterType(val, update) {
                         option-value="id"
                         emit-value
                         map-options
-                        :label="t('wagon.create.type')"
+                        :label="t('globals.type')"
                         :options="filteredWagonTypes"
                         :rules="[(val) => !!val || t('wagon.warnings.typeNotEmpty')]"
                         @filter="filterType"
diff --git a/src/pages/Wagon/WagonList.vue b/src/pages/Wagon/WagonList.vue
index 61679b933..893b058ea 100644
--- a/src/pages/Wagon/WagonList.vue
+++ b/src/pages/Wagon/WagonList.vue
@@ -46,7 +46,7 @@ const columns = computed(() => [
     {
         align: 'left',
         name: 'name',
-        label: t('wagon.list.type'),
+        label: t('globals.type'),
         cardVisible: true,
         format: (row) => row?.type?.name,
     },
@@ -123,7 +123,7 @@ async function remove(row) {
                 <VnInput
                     filled
                     v-model="data.plate"
-                    :label="t('wagon.create.plate')"
+                    :label="t('wagon.list.plate')"
                     :rules="[(val) => !!val || t('wagon.warnings.plateNotEmpty')]"
                 />
                 <VnInput
@@ -146,7 +146,7 @@ async function remove(row) {
                     option-value="id"
                     emit-value
                     map-options
-                    :label="t('wagon.create.type')"
+                    :label="t('globals.type')"
                     :options="filteredWagonTypes"
                     :rules="[(val) => !!val || t('wagon.warnings.typeNotEmpty')]"
                     @filter="filterType"
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 491105e09..8cb688ec8 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -140,7 +140,7 @@ const handlePhotoUpdated = (evt = false) => {
         <template #body="{ entity }">
             <VnLv :label="t('globals.user')" :value="entity.user?.name" />
             <VnLv
-                :label="t('worker.card.email')"
+                :label="t('globals.params.email')"
                 :value="entity.user?.emailUser?.email"
                 copy
             />
@@ -150,7 +150,7 @@ const handlePhotoUpdated = (evt = false) => {
             />
             <VnLv :value="entity.phone">
                 <template #label>
-                    {{ t('worker.card.phone') }}
+                    {{ t('globals.phone') }}
                     <VnLinkPhone :phone-number="entity.phone" />
                 </template>
             </VnLv>
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 3f562a77b..dcb9aa6d5 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -53,7 +53,7 @@ onBeforeMount(async () => {
         <template #body="{ entity: worker }">
             <QCard class="vn-one">
                 <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
-                <VnLv :label="t('worker.card.name')" :value="worker.user?.nickname" />
+                <VnLv :label="t('globals.name')" :value="worker.user?.nickname" />
                 <VnLv :label="t('worker.list.department')">
                     <template #value>
                         <span class="link" v-text="worker.department?.department?.name" />
@@ -119,9 +119,9 @@ onBeforeMount(async () => {
             </QCard>
             <QCard class="vn-one">
                 <VnTitle :text="t('worker.summary.userData')" />
-                <VnLv :label="t('worker.card.name')" :value="worker?.user?.nickname" />
+                <VnLv :label="t('globals.name')" :value="worker?.user?.nickname" />
                 <VnLv
-                    :label="t('worker.list.email')"
+                    :label="t('globals.params.email')"
                     :value="worker.user?.emailUser?.email"
                     copy
                 />
diff --git a/src/pages/Worker/WorkerCreate.vue b/src/pages/Worker/WorkerCreate.vue
index b51209879..5676837dd 100644
--- a/src/pages/Worker/WorkerCreate.vue
+++ b/src/pages/Worker/WorkerCreate.vue
@@ -111,7 +111,7 @@ async function autofillBic(worker) {
                 <VnRow>
                     <VnInput
                         v-model="data.firstName"
-                        :label="t('worker.create.name')"
+                        :label="t('globals.name')"
                         :rules="validate('Worker.firstName')"
                         @update:model-value="generateCodeUser(data)"
                     />
@@ -141,7 +141,7 @@ async function autofillBic(worker) {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('worker.create.company')"
+                        :label="t('globals.company')"
                         v-model="data.companyFk"
                         :options="companiesOptions"
                         option-value="id"
@@ -150,7 +150,7 @@ async function autofillBic(worker) {
                         :rules="validate('Worker.company')"
                     />
                     <VnSelect
-                        :label="t('worker.create.boss')"
+                        :label="t('worker.summary.boss')"
                         v-model="data.bossFk"
                         url="Workers/search"
                         option-value="id"
@@ -185,7 +185,7 @@ async function autofillBic(worker) {
                     />
                     <VnInput
                         v-model="data.phone"
-                        :label="t('worker.create.phone')"
+                        :label="t('globals.phone')"
                         :rules="validate('Worker.phone')"
                         :disable="formData.isFreelance"
                     />
@@ -201,7 +201,7 @@ async function autofillBic(worker) {
                 </VnRow>
                 <VnRow>
                     <VnInput
-                        :label="t('worker.create.street')"
+                        :label="t('globals.street')"
                         v-model="data.street"
                         :rules="validate('Worker.street')"
                         :disable="formData.isFreelance"
diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue
index 7a3f760bc..a2ce43b77 100644
--- a/src/pages/Worker/WorkerList.vue
+++ b/src/pages/Worker/WorkerList.vue
@@ -233,7 +233,7 @@ async function autofillBic(worker) {
                     <VnInput
                         next
                         v-model="data.firstName"
-                        :label="t('worker.create.name')"
+                        :label="t('globals.name')"
                         @update:model-value="generateCodeUser(data)"
                     />
                     <VnInput
@@ -253,7 +253,7 @@ async function autofillBic(worker) {
                 </VnRow>
                 <VnRow>
                     <VnSelect
-                        :label="t('worker.create.company')"
+                        :label="t('globals.company')"
                         v-model="data.companyFk"
                         :options="companiesOptions"
                         option-value="id"
@@ -261,7 +261,7 @@ async function autofillBic(worker) {
                         hide-selected
                     />
                     <VnSelect
-                        :label="t('worker.create.boss')"
+                        :label="t('worker.summary.boss')"
                         v-model="data.bossFk"
                         url="Workers/search"
                         option-value="id"
@@ -290,7 +290,7 @@ async function autofillBic(worker) {
                     />
                     <VnInput
                         v-model="data.phone"
-                        :label="t('worker.create.phone')"
+                        :label="t('globals.phone')"
                         :disable="data.isFreelance"
                     />
                 </VnRow>

From df3b4e7a186afeaa329055e94be04fb7ef76944d Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 21 Oct 2024 13:07:07 +0200
Subject: [PATCH 050/207] refactor: refs #7132 deleted useless code

---
 src/pages/Ticket/TicketAdvance.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue
index 1fc45f713..98792760b 100644
--- a/src/pages/Ticket/TicketAdvance.vue
+++ b/src/pages/Ticket/TicketAdvance.vue
@@ -551,7 +551,6 @@ onMounted(async () => {
             style="max-width: 99%"
         >
             <template #header="props">
-                {{ userParams.scopeDays }}
                 <QTr :props="props">
                     <QTh
                         class="horizontal-separator text-uppercase color-vn-label"

From 52981953f7e9efbc1a8875c321376e02a50c3b33 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Oct 2024 13:23:45 +0200
Subject: [PATCH 051/207] feat(): refs #8039 canceledError not notify

---
 src/boot/axios.js  | 5 +++--
 src/boot/quasar.js | 3 ++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/boot/axios.js b/src/boot/axios.js
index 3bd80f487..d3e981adb 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -3,6 +3,7 @@ import { useSession } from 'src/composables/useSession';
 import { Router } from 'src/router';
 import useNotify from 'src/composables/useNotify.js';
 import { useStateQueryStore } from 'src/stores/useStateQueryStore';
+import { CanceledError } from 'axios';
 
 const session = useSession();
 const { notify } = useNotify();
@@ -42,7 +43,7 @@ const onResponseError = (error) => {
     let message = '';
 
     const response = error.response;
-    const responseData = response && response.data;
+    const responseData = response?.data;
     const responseError = responseData && response.data.error;
     if (responseError) {
         message = responseError.message;
@@ -78,7 +79,7 @@ const onResponseError = (error) => {
         return Promise.reject(error);
     }
 
-    notify(message, 'negative');
+    if (!(error instanceof CanceledError)) notify(message, 'negative');
 
     return Promise.reject(error);
 };
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 5db6edd24..41a7990c7 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -3,6 +3,7 @@ import qFormMixin from './qformMixin';
 import mainShortcutMixin from './mainShortcutMixin';
 import keyShortcut from './keyShortcut';
 import useNotify from 'src/composables/useNotify.js';
+import { CanceledError } from 'axios';
 const { notify } = useNotify();
 
 export default boot(({ app }) => {
@@ -11,6 +12,6 @@ export default boot(({ app }) => {
     app.directive('shortcut', keyShortcut);
     app.config.errorHandler = function (err) {
         console.error(err);
-        notify('globals.error', 'negative', 'error');
+        if (!(err instanceof CanceledError)) notify('globals.error', 'negative', 'error');
     };
 });

From 9780fe596fa0af4212f308a3150d1066a3275517 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Oct 2024 13:33:12 +0200
Subject: [PATCH 052/207] feat: refs #8039 notify error unify

---
 src/boot/axios.js  | 34 +---------------------------------
 src/boot/quasar.js | 37 ++++++++++++++++++++++++++++++++++---
 2 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/src/boot/axios.js b/src/boot/axios.js
index d3e981adb..b084b835d 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -40,37 +40,7 @@ const onResponse = (response) => {
 const onResponseError = (error) => {
     stateQuery.remove(error.config);
 
-    let message = '';
-
-    const response = error.response;
-    const responseData = response?.data;
-    const responseError = responseData && response.data.error;
-    if (responseError) {
-        message = responseError.message;
-    }
-
-    switch (response?.status) {
-        case 422:
-            if (error.name == 'ValidationError')
-                message +=
-                    ' "' +
-                    responseError.details.context +
-                    '.' +
-                    Object.keys(responseError.details.codes).join(',') +
-                    '"';
-            break;
-        case 500:
-            message = 'errors.statusInternalServerError';
-            break;
-        case 502:
-            message = 'errors.statusBadGateway';
-            break;
-        case 504:
-            message = 'errors.statusGatewayTimeout';
-            break;
-    }
-
-    if (session.isLoggedIn() && response?.status === 401) {
+    if (session.isLoggedIn() && error.response?.status === 401) {
         session.destroy(false);
         const hash = window.location.hash;
         const url = hash.slice(1);
@@ -79,8 +49,6 @@ const onResponseError = (error) => {
         return Promise.reject(error);
     }
 
-    if (!(error instanceof CanceledError)) notify(message, 'negative');
-
     return Promise.reject(error);
 };
 
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 41a7990c7..bf5175ee6 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -10,8 +10,39 @@ export default boot(({ app }) => {
     app.mixin(qFormMixin);
     app.mixin(mainShortcutMixin);
     app.directive('shortcut', keyShortcut);
-    app.config.errorHandler = function (err) {
-        console.error(err);
-        if (!(err instanceof CanceledError)) notify('globals.error', 'negative', 'error');
+    app.config.errorHandler = (error) => {
+        let message;
+        const response = error.response;
+        const responseData = response?.data;
+        const responseError = responseData && response.data.error;
+        if (responseError) {
+            message = responseError.message;
+        }
+
+        switch (response?.status) {
+            case 422:
+                if (error.name == 'ValidationError')
+                    message +=
+                        ' "' +
+                        responseError.details.context +
+                        '.' +
+                        Object.keys(responseError.details.codes).join(',') +
+                        '"';
+                break;
+            case 500:
+                message = 'errors.statusInternalServerError';
+                break;
+            case 502:
+                message = 'errors.statusBadGateway';
+                break;
+            case 504:
+                message = 'errors.statusGatewayTimeout';
+                break;
+        }
+
+        console.error(error);
+        if (error instanceof CanceledError) return;
+
+        notify(message ?? 'globals.error', 'negative', 'error');
     };
 });

From c69f7af3906e5d88f321350813ec42cc692bd6f4 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Oct 2024 13:38:35 +0200
Subject: [PATCH 053/207] test: refs #8039 axios not notify

---
 test/vitest/__tests__/boot/axios.spec.js | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js
index 7a802b4d2..19d396ec5 100644
--- a/test/vitest/__tests__/boot/axios.spec.js
+++ b/test/vitest/__tests__/boot/axios.spec.js
@@ -36,8 +36,6 @@ describe('Axios boot', () => {
 
     describe('onResponseError()', async () => {
         it('should call to the Notify plugin with a message error for an status code "500"', async () => {
-            Notify.create = vi.fn();
-
             const error = {
                 response: {
                     status: 500,
@@ -45,19 +43,10 @@ describe('Axios boot', () => {
             };
 
             const result = onResponseError(error);
-
             expect(result).rejects.toEqual(expect.objectContaining(error));
-            expect(Notify.create).toHaveBeenCalledWith(
-                expect.objectContaining({
-                    message: 'An internal server error has ocurred',
-                    type: 'negative',
-                })
-            );
         });
 
         it('should call to the Notify plugin with a message from the response property', async () => {
-            Notify.create = vi.fn();
-
             const error = {
                 response: {
                     status: 401,
@@ -70,14 +59,7 @@ describe('Axios boot', () => {
             };
 
             const result = onResponseError(error);
-
             expect(result).rejects.toEqual(expect.objectContaining(error));
-            expect(Notify.create).toHaveBeenCalledWith(
-                expect.objectContaining({
-                    message: 'Invalid user or password',
-                    type: 'negative',
-                })
-            );
         });
     });
 });

From 29a7f3b2fed499111e620941fd17baa55611a388 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 21 Oct 2024 13:48:43 +0200
Subject: [PATCH 054/207] fix: refs #7283 #7283 ItemDiary subToolbar

---
 src/pages/Item/Card/ItemDiary.vue | 67 ++++++++++++++++---------------
 1 file changed, 34 insertions(+), 33 deletions(-)

diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index a36b6a246..23dc6214e 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -188,7 +188,7 @@ async function updateWarehouse(warehouseFk) {
         },
     });
     await stock.fetch({});
-    stock.store.data.itemFk = route.params.id
+    stock.store.data.itemFk = route.params.id;
 }
 </script>
 
@@ -205,38 +205,39 @@ async function updateWarehouse(warehouseFk) {
         auto-load
         @on-fetch="(data) => (warehousesOptions = data)"
     />
-    <QToolbar class="justify-end">
-        <div id="st-data" class="row">
-            <VnSelect
-                :label="t('itemDiary.warehouse')"
-                :options="warehousesOptions"
-                hide-selected
-                option-label="name"
-                option-value="id"
-                dense
-                v-model="itemsBalanceFilter.where.warehouseFk"
-                @update:model-value="
-                    (value) => fetchItemBalances() && updateWarehouse(value)
-                "
-                class="q-mr-lg"
-            />
-            <QCheckbox
-                :label="t('itemDiary.showBefore')"
-                v-model="showWhatsBeforeInventory"
-                @update:model-value="fetchItemBalances"
-                class="q-mr-lg"
-            />
-            <VnInputDate
-                v-if="showWhatsBeforeInventory"
-                :label="t('itemDiary.since')"
-                dense
-                v-model="itemsBalanceFilter.where.date"
-                @update:model-value="fetchItemBalances"
-            />
-        </div>
-        <QSpace />
-        <div id="st-actions"></div>
-    </QToolbar>
+    <template v-if="stateStore.isHeaderMounted()">
+        <Teleport to="#st-data">
+            <div class="row">
+                <VnSelect
+                    :label="t('itemDiary.warehouse')"
+                    :options="warehousesOptions"
+                    hide-selected
+                    option-label="name"
+                    option-value="id"
+                    dense
+                    v-model="itemsBalanceFilter.where.warehouseFk"
+                    @update:model-value="
+                        (value) => fetchItemBalances() && updateWarehouse(value)
+                    "
+                    class="q-mr-lg"
+                />
+                <QCheckbox
+                    :label="t('itemDiary.showBefore')"
+                    v-model="showWhatsBeforeInventory"
+                    @update:model-value="fetchItemBalances"
+                    class="q-mr-lg"
+                />
+                <VnInputDate
+                    v-if="showWhatsBeforeInventory"
+                    :label="t('itemDiary.since')"
+                    dense
+                    v-model="itemsBalanceFilter.where.date"
+                    @update:model-value="fetchItemBalances"
+                />
+            </div>
+        </Teleport>
+        <Teleport to="#st-actions"> </Teleport>
+    </template>
     <QPage class="column items-center q-pa-md">
         <QTable
             :rows="itemBalances"

From f4a7e20c574ab8603d6f4b2dabd222556a9a31ea Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 21 Oct 2024 14:31:31 +0200
Subject: [PATCH 055/207] test: refs #6943 #6943 add comands to solve tests

---
 .../integration/client/clientBalance.spec.js  |  2 +-
 .../integration/client/clientCredits.spec.js  |  2 +-
 .../integration/client/clientList.spec.js     |  6 +--
 .../client/clientRecoveries.spec.js           |  2 +-
 .../clientCreditOpinion.spec.js               |  2 +-
 .../client/others/clientConsumption.spec.js   |  2 +-
 .../client/others/clientMandates.spec.js      |  2 +-
 .../client/others/clientSamples.spec.js       |  2 +-
 .../client/others/clientWebPayments.spec.js   |  4 +-
 test/cypress/support/commands.js              | 42 +++++++++++++++++++
 10 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/test/cypress/integration/client/clientBalance.spec.js b/test/cypress/integration/client/clientBalance.spec.js
index 4a666bdb1..dfba56b16 100644
--- a/test/cypress/integration/client/clientBalance.spec.js
+++ b/test/cypress/integration/client/clientBalance.spec.js
@@ -8,6 +8,6 @@ describe('Client balance', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/clientCredits.spec.js b/test/cypress/integration/client/clientCredits.spec.js
index f81bf987d..5f303b40d 100644
--- a/test/cypress/integration/client/clientCredits.spec.js
+++ b/test/cypress/integration/client/clientCredits.spec.js
@@ -8,6 +8,6 @@ describe('Client credits', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 93e53b9f6..909bd3933 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -44,7 +44,7 @@ describe('Client list', () => {
         });
     });
 
-    it('Client founded create ticket', () => {
+    it.skip('Client founded create ticket', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
         cy.clickButtonsDescriptor(2);
@@ -52,10 +52,10 @@ describe('Client list', () => {
         cy.waitForElement('.q-form');
         cy.checkValueForm(1, search);
     });
-    it('Client founded create order', () => {
+    it.skip('Client founded create order', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
-        cy.clickButtonsDescriptor(4);
+        cy.clickButtonsDescriptor(3);
         cy.waitForElement('#formModel');
         cy.waitForElement('.q-form');
         cy.checkValueForm(2, search);
diff --git a/test/cypress/integration/client/clientRecoveries.spec.js b/test/cypress/integration/client/clientRecoveries.spec.js
index a4e220008..ea6f14407 100644
--- a/test/cypress/integration/client/clientRecoveries.spec.js
+++ b/test/cypress/integration/client/clientRecoveries.spec.js
@@ -8,6 +8,6 @@ describe('Client recoveries', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js
index 7d9c0fa77..c32215f01 100644
--- a/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js
+++ b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js
@@ -8,6 +8,6 @@ describe('Client credit opinion', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/others/clientConsumption.spec.js b/test/cypress/integration/client/others/clientConsumption.spec.js
index 179a37707..bbc11998e 100644
--- a/test/cypress/integration/client/others/clientConsumption.spec.js
+++ b/test/cypress/integration/client/others/clientConsumption.spec.js
@@ -8,6 +8,6 @@ describe('Client consumption', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/others/clientMandates.spec.js b/test/cypress/integration/client/others/clientMandates.spec.js
index aaeb7f930..055eda2d0 100644
--- a/test/cypress/integration/client/others/clientMandates.spec.js
+++ b/test/cypress/integration/client/others/clientMandates.spec.js
@@ -8,6 +8,6 @@ describe('Client mandates', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/others/clientSamples.spec.js b/test/cypress/integration/client/others/clientSamples.spec.js
index 03b7238f4..a50120402 100644
--- a/test/cypress/integration/client/others/clientSamples.spec.js
+++ b/test/cypress/integration/client/others/clientSamples.spec.js
@@ -8,6 +8,6 @@ describe('Client samples', () => {
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/integration/client/others/clientWebPayments.spec.js b/test/cypress/integration/client/others/clientWebPayments.spec.js
index 5f7087d21..f35b12612 100644
--- a/test/cypress/integration/client/others/clientWebPayments.spec.js
+++ b/test/cypress/integration/client/others/clientWebPayments.spec.js
@@ -3,11 +3,11 @@ describe('Client web payments', () => {
     beforeEach(() => {
         cy.viewport(1280, 720);
         cy.login('developer');
-        cy.visit('#/customer/1101/others/web-payments', {
+        cy.visit('#/customer/1101/others/web-payment', {
             timeout: 5000,
         });
     });
     it('Should load layout', () => {
-        cy.get('.q-card').should('be.visible');
+        cy.get('.q-page').should('be.visible');
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 83f45b721..9106a64cd 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -245,6 +245,13 @@ Cypress.Commands.add('validateContent', (selector, expectedValue) => {
     cy.get(selector).should('have.text', expectedValue);
 });
 
+Cypress.Commands.add('openActionDescriptor', (opt) => {
+    cy.openActionsDescriptor();
+    const listItem = '[role="menu"] .q-list .q-item';
+    cy.contains(listItem, opt).click();
+    1;
+});
+
 Cypress.Commands.add('openActionsDescriptor', () => {
     cy.get('.header > :nth-child(3) > .q-btn__content > .q-icon').click();
 });
@@ -254,3 +261,38 @@ Cypress.Commands.add('openUserPanel', () => {
         '.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
     ).click();
 });
+
+Cypress.Commands.add('clickButtonsDescriptor', (id) => {
+    cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
+        .invoke('removeAttr', 'target')
+        .click();
+});
+
+Cypress.Commands.add('openActions', (row) => {
+    cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
+});
+
+Cypress.Commands.add('checkNotification', (type) => {
+    const values = {
+        created: 'Data created',
+        updated: 'Data saved',
+        deleted: 'Data deleted',
+    };
+    cy.get('.q-notification__message').should('have.text', values[type]);
+});
+
+Cypress.Commands.add('checkValueForm', (id, search) => {
+    cy.get(
+        `.grid-create > :nth-child(${id}) > .q-field__inner>.q-field__control> .q-field__control-container>.q-field__native >.q-field__input`
+    ).should('have.value', search);
+});
+
+Cypress.Commands.add('checkValueSelectForm', (id, search) => {
+    cy.get(
+        `.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container>.q-field__native>.q-field__input`
+    ).should('have.value', search);
+});
+
+Cypress.Commands.add('searchByLabel', (label, value) => {
+    cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
+});

From f3a62091893009b75b4ef3a701f7db1b43f151e1 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 22 Oct 2024 12:00:11 +0200
Subject: [PATCH 056/207] fix: refs #7283 #7283 bugs

---
 src/pages/Item/Card/ItemDescriptorImage.vue |  4 +-
 src/pages/Item/ItemList.vue                 | 55 ++++++++++++++++-----
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/src/pages/Item/Card/ItemDescriptorImage.vue b/src/pages/Item/Card/ItemDescriptorImage.vue
index b035a630a..3cd51758b 100644
--- a/src/pages/Item/Card/ItemDescriptorImage.vue
+++ b/src/pages/Item/Card/ItemDescriptorImage.vue
@@ -134,10 +134,10 @@ es:
     Regularize stock: Regularizar stock
     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?
-    warehouseText: Calculated on the warehouse of { warehouseName }
+    warehouseText: Calculado sobre el almacén de { warehouseName }
 
 en:
-    warehouseText: Calculado sobre el almacén de { warehouseName }
+    warehouseText: Calculated on the warehouse of { warehouseName }
 </i18n>
 
 <style lang="scss" scoped>
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 6c7b7eaed..92c9d188b 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -11,6 +11,9 @@ import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import ItemSummary from '../Item/Card/ItemSummary.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
+import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
+import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import { useQuasar } from 'quasar';
 const entityId = computed(() => route.params.id);
 
 const { viewSummary } = useSummaryDialog();
@@ -18,6 +21,7 @@ const router = useRouter();
 const { t } = useI18n();
 const tableRef = ref();
 const route = useRoute();
+const quasar = useQuasar();
 
 const itemFilter = {
     include: [
@@ -53,10 +57,12 @@ const columns = computed(() => [
                     id: row?.id,
                     zoomResolution: '1600x900',
                     zoom: true,
+                    class: 'rounded',
                 };
             },
         },
         columnFilter: false,
+        cardVisible: true,
     },
     {
         label: t('item.list.id'),
@@ -66,6 +72,7 @@ const columns = computed(() => [
         chip: {
             condition: () => true,
         },
+        cardVisible: true,
     },
     {
         label: t('item.list.grouping'),
@@ -93,6 +100,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'search',
         },
+        cardVisible: true,
     },
     {
         label: t('item.list.stems'),
@@ -102,6 +110,7 @@ const columns = computed(() => [
             component: 'number',
             inWhere: true,
         },
+        cardVisible: true,
     },
     {
         label: t('item.list.size'),
@@ -111,6 +120,7 @@ const columns = computed(() => [
             component: 'number',
             inWhere: true,
         },
+        cardVisible: true,
     },
     {
         label: t('item.list.typeName'),
@@ -172,6 +182,7 @@ const columns = computed(() => [
             component: null,
         },
         create: true,
+        cardVisible: true,
     },
     {
         label: t('item.list.origin'),
@@ -197,6 +208,7 @@ const columns = computed(() => [
             component: null,
         },
         create: true,
+        cardVisible: true,
     },
     {
         label: t('item.list.userName'),
@@ -270,13 +282,14 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('Clone item'),
+                title: t('globals.clone'),
+
                 icon: 'vn:clone',
-                action: cloneItem,
+                action: openCloneDialog,
                 isPrimary: true,
             },
             {
-                title: t('view Summary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row.id, ItemSummary),
                 isPrimary: true,
@@ -285,21 +298,34 @@ const columns = computed(() => [
     },
 ]);
 
-const cloneItem = async (itemFk) => {
+const cloneItem = async () => {
     try {
-        const { data } = await axios.post(`Items/${itemFk.id}/clone`);
-        if (!data) return;
+        const { data } = await axios.post(`Items/${entityId.value}/clone`);
         router.push({ name: 'ItemTags', params: { id: data.id } });
     } catch (err) {
-        console.error('Error cloning item', err);
+        console.error('Error cloning item');
     }
 };
+
+const openCloneDialog = async () => {
+    quasar
+        .dialog({
+            component: VnConfirm,
+            componentProps: {
+                title: t('All its properties will be copied'),
+                message: t('Do you want to clone this item?'),
+            },
+        })
+        .onOk(async () => {
+            await cloneItem();
+        });
+};
 </script>
 
 <template>
     <VnSearchbar
         data-key="ItemList"
-        :label="t('Search Item')"
+        :label="t('item.searchbar.label')"
         :info="t('You can search by id')"
     />
     <VnTable
@@ -309,19 +335,25 @@ const cloneItem = async (itemFk) => {
         url-create="Items"
         :create="{
             urlCreate: 'Items',
-            title: 'Create Item',
+            title: t('Create Item'),
             onDataSaved: () => tableRef.redirect(),
             formInitialData: {
                 editorFk: entityId,
             },
         }"
-        order="id ASC"
+        :order="['isActive DESC', 'name', 'id']"
         :columns="columns"
         auto-load
         redirect="Item"
         :is-editable="false"
         :filer="itemFilter"
     >
+        <template #column-id="{ row }">
+            <span class="link" @click.stop>
+                {{ row.id }}
+                <ItemDescriptorProxy :id="row.id" />
+            </span>
+        </template>
         <template #column-userName="{ row }">
             <span class="link" @click.stop>
                 {{ row.userName }}
@@ -349,7 +381,8 @@ const cloneItem = async (itemFk) => {
 <i18n>
 es:
     New item: Nuevo artículo
-    All it's properties will be copied: Todas sus propiedades serán copiadas
+    All its properties will be copied: Todas sus propiedades serán copiadas
     Do you want to clone this item?: ¿Desea clonar este artículo?
     Preview: Vista previa
+    Regularize stock: Regularizar stock
 </i18n>

From 1346a2e7fd52f8811ac0b2efbd0c03676becca1f Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 22 Oct 2024 12:05:44 +0200
Subject: [PATCH 057/207] fix: tag chips

---
 src/pages/Order/Card/OrderCatalogFilter.vue | 113 +++++++++-----------
 1 file changed, 50 insertions(+), 63 deletions(-)

diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 850212a62..0fe8c4d64 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -6,8 +6,8 @@ import axios from 'axios';
 import FetchData from 'components/FetchData.vue';
 import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
 import VnSelect from 'components/common/VnSelect.vue';
-// import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
+import VnFilterPanelChip from 'src/components/ui/VnFilterPanelChip.vue';
 
 const { t } = useI18n();
 
@@ -49,6 +49,7 @@ const orderWaySelected = ref('ASC');
 
 const routeQuery = JSON.parse(route?.query.params ?? '{}');
 const paramsSearch = ref({});
+const tagData = ref([]);
 
 onMounted(() => {
     paramsSearch.value = JSON.parse(routeQuery.filter ?? '{}')?.where ?? {};
@@ -120,32 +121,6 @@ const selectedType = computed(() => {
     return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
 });
 
-// const applyTagFilter = (params, search) => {
-
-//     if (params.tagGroups) params.tagGroups = null;
-//     if (!tagValues.value?.length) {
-//         params.tagGroups = null;
-//         search();
-//         return;
-//     }
-//     if (!params.tagGroups) {
-//         params.tagGroups = [];
-//     }
-//     params.tagGroups.push(
-//         JSON.stringify({
-//             values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
-//             tagSelection: {
-//                 ...selectedTag.value,
-//                 orgShowField: selectedTag?.value?.name,
-//             },
-//             tagFk: selectedTag?.value?.tagFk,
-//         })
-//     );
-//     search();
-//     selectedTag.value = null;
-//     tagValues.value = [{}];
-// };
-
 const applyTagFilter = (params, search) => {
     if (!tagValues.value?.length) {
         params.tagGroups = null;
@@ -153,27 +128,46 @@ const applyTagFilter = (params, search) => {
         return;
     }
 
-    if (!params.tagGroups) {
+    if (!params.tagGroups || typeof params.tagGroups === 'string') {
         params.tagGroups = [];
-    } else if (typeof params.tagGroups === 'string') {
-        params.tagGroups = [params.tagGroups];
     }
 
-    const newTagGroup = JSON.stringify({
-        values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
-        tagSelection: {
-            ...selectedTag.value,
-            orgShowField: selectedTag?.value?.name,
-        },
-        tagFk: selectedTag?.value?.tagFk,
-    });
-    params.tagGroups.push(newTagGroup);
+    params.tagGroups.push(
+        JSON.stringify({
+            values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
+            tagSelection: {
+                ...selectedTag.value,
+                orgShowField: selectedTag?.value?.name,
+            },
+            tagFk: selectedTag?.value?.tagFk,
+        })
+    );
 
+    tagData.value.push(JSON.parse(params.tagGroups[params.tagGroups.length - 1]));
     search();
     selectedTag.value = null;
     tagValues.value = [{}];
 };
 
+const removeTagChip = (selection, params, search) => {
+    if (typeof params.tagGroups === 'string') {
+        try {
+            params.tagGroups = JSON.parse(params.tagGroups);
+        } catch (error) {
+            console.error('Error parsing tagGroups:', error);
+            params.tagGroups = [];
+        }
+    }
+    console.log('params.tagGroups: ', params.tagGroups);
+    console.log('selection: ', selection);
+
+    if (Array.isArray(params.tagGroups)) {
+        params.tagGroups = params.tagGroups.filter((value) => value !== selection);
+    }
+
+    search();
+};
+
 const setCategoryList = (data) => {
     categoryList.value = (data || [])
         .filter((category) => category.display)
@@ -198,22 +192,6 @@ function addOrder(value, field, params) {
     params.orderBy = JSON.stringify(orderBy);
     vnFilterPanelRef.value.search();
 }
-
-const data = ref([]);
-
-function getTagData(value) {
-    if (Array.isArray(value) && value.length >= 1) {
-        const parsedTags = value.map((obj) => JSON.parse(obj));
-
-        if (parsedTags.length === 1) {
-            data.value = parsedTags[0];
-        } else {
-            data.value = parsedTags;
-        }
-    } else {
-        data.value = JSON.parse(value);
-    }
-}
 </script>
 
 <template>
@@ -224,29 +202,37 @@ function getTagData(value) {
         v-model="paramsSearch"
         :redirect="false"
         :hidden-tags="['orderFk', 'orderBy', 'filter', 'search', 'or', 'and']"
+        :custom-tags="['tagGroups']"
         :unremovable-params="['orderFk', 'orderBy']"
         :disable-submit-event="true"
     >
         <template #tags="{ tag, formatFn }">
-            {{ console.log('tag.label: ', tag.label) }}
             <strong v-if="tag.label === 'categoryFk'">
                 {{ t(selectedCategory?.name || '') }}
             </strong>
             <strong v-else-if="tag.label === 'typeFk'">
                 {{ t(selectedType?.name || '') }}
             </strong>
-            <div v-else-if="tag.label === 'tagGroups'" class="q-gutter-x-xs">
-                {{ getTagData(tag.value) }}
-                <strong> {{ data.tagSelection?.name }}: </strong>
-                <span>
-                    {{ console.log('data', data.values) }}
-                </span>
-            </div>
             <div v-else class="q-gutter-x-xs">
                 <strong>{{ t(`params.${tag.label}`) }}: </strong>
                 <span>{{ formatFn(tag.value) }}</span>
             </div>
         </template>
+        <template #customTags="{ tags: customTags, params, searchFn }">
+            <template v-for="tag in customTags" :key="tag.label">
+                <template v-if="tag.label === 'tagGroups'">
+                    <VnFilterPanelChip
+                        v-for="chip in tagData"
+                        :key="chip"
+                        removable
+                        @remove="removeTagChip(chip, params, searchFn)"
+                    >
+                        <strong>{{ chip.tagSelection?.name }}: </strong>
+                        <span>{{ chip.values[0].value }}</span>
+                    </VnFilterPanelChip>
+                </template>
+            </template>
+        </template>
         <template #body="{ params, searchFn }">
             <QItem class="category-filter q-mt-md">
                 <div
@@ -410,6 +396,7 @@ function getTagData(value) {
                     icon="add_circle"
                     shortcut="+"
                     flat
+                    size="md"
                     class="filter-icon"
                     @click="tagValues.push({})"
                 />

From d6b8d41b6c4cf5144018754d8bc7cdee1e73f5ba Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 22 Oct 2024 12:09:19 +0200
Subject: [PATCH 058/207] fix: refs #7283 #7283 ItemSummary bugs

---
 src/pages/Item/Card/ItemSummary.vue | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index 7b6015c30..071203038 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -135,7 +135,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                 <VnLv
                     v-for="(tax, index) in item.taxes"
                     :key="index"
-                    :label="tax.country.country"
+                    :label="tax.country.name"
                     :value="tax.taxClass.description"
                 />
             </QCard>
@@ -155,7 +155,8 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                     :url="getUrl(entityId, 'barcode')"
                     :text="t('item.summary.barcode')"
                 />
-                <p
+                <div
+                    class="text-bold"
                     v-for="(barcode, index) in item.itemBarcode"
                     :key="index"
                     v-text="barcode.code"

From fff3310658db3eb3a80d8a259e94ac57a02a3d48 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 22 Oct 2024 12:09:32 +0200
Subject: [PATCH 059/207] fix: refs #7283 tooltips !Item

---
 src/pages/Account/AccountList.vue       | 2 +-
 src/pages/Account/Role/AccountRoles.vue | 2 +-
 src/pages/Route/RouteAutonomous.vue     | 2 +-
 src/pages/Route/RouteExtendedList.vue   | 2 +-
 src/pages/Ticket/TicketList.vue         | 2 +-
 src/pages/Zone/ZoneList.vue             | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue
index 72c445fa9..9e7f1b10a 100644
--- a/src/pages/Account/AccountList.vue
+++ b/src/pages/Account/AccountList.vue
@@ -74,7 +74,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('View Summary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row.id, AccountSummary),
                 isPrimary: true,
diff --git a/src/pages/Account/Role/AccountRoles.vue b/src/pages/Account/Role/AccountRoles.vue
index ea175d913..5398485e3 100644
--- a/src/pages/Account/Role/AccountRoles.vue
+++ b/src/pages/Account/Role/AccountRoles.vue
@@ -54,7 +54,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('View Summary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row.id, RoleSummary),
                 isPrimary: true,
diff --git a/src/pages/Route/RouteAutonomous.vue b/src/pages/Route/RouteAutonomous.vue
index 5ad349942..4a691dbef 100644
--- a/src/pages/Route/RouteAutonomous.vue
+++ b/src/pages/Route/RouteAutonomous.vue
@@ -126,7 +126,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('Preview'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 isPrimary: true,
                 action: (row) => viewSummary(row?.routeFk, RouteSummary),
diff --git a/src/pages/Route/RouteExtendedList.vue b/src/pages/Route/RouteExtendedList.vue
index 51da4ec12..dbf646935 100644
--- a/src/pages/Route/RouteExtendedList.vue
+++ b/src/pages/Route/RouteExtendedList.vue
@@ -204,7 +204,7 @@ const columns = computed(() => [
                 isPrimary: true,
             },
             {
-                title: t('route.components.smartCard.viewSummary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row?.id, RouteSummary),
                 isPrimary: true,
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index ad97e75c1..272d3a666 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -202,7 +202,7 @@ const columns = computed(() => [
                 action: (row) => redirectToLines(row.id),
             },
             {
-                title: t('ticketList.summary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 isPrimary: true,
                 action: (row) => viewSummary(row.id, TicketSummary),
diff --git a/src/pages/Zone/ZoneList.vue b/src/pages/Zone/ZoneList.vue
index d160ea6b5..89f2dd42c 100644
--- a/src/pages/Zone/ZoneList.vue
+++ b/src/pages/Zone/ZoneList.vue
@@ -103,7 +103,7 @@ const columns = computed(() => [
         name: 'tableActions',
         actions: [
             {
-                title: t('list.zoneSummary'),
+                title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
                 action: (row) => viewSummary(row.id, ZoneSummary),
                 isPrimary: true,

From 49c0d64c07e27e2c469499d85dacba8a611184e3 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 22 Oct 2024 12:13:43 +0200
Subject: [PATCH 060/207] fix: refs #7283 #7283 ItemSummary bugs

---
 src/pages/Item/Card/ItemSummary.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index 071203038..6ad09ac64 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -119,7 +119,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
                 <VnLv
                     v-for="(tag, index) in tags"
                     :key="index"
-                    :label="`${tag.priority} ${tag.tag.name}`"
+                    :label="`${tag.priority} ${tag.tag.name}:`"
                     :value="tag.value"
                 />
             </QCard>

From 9db1c4f721a3a0d5f3f3a103060a65b78bca4fa4 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 12:29:33 +0200
Subject: [PATCH 061/207] fix: refs #8039 bad tests

---
 src/components/FormModel.vue                     | 3 ---
 test/cypress/integration/outLogin/logout.spec.js | 7 ++++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 05f947cf3..9ac2d38a5 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -217,9 +217,6 @@ async function save() {
         updateAndEmit('onDataSaved', formData.value, response?.data);
         if ($props.reload) await arrayData.fetch({});
         hasChanges.value = false;
-    } catch (err) {
-        console.error(err);
-        notify('errors.writeRequest', 'negative');
     } finally {
         isLoading.value = false;
     }
diff --git a/test/cypress/integration/outLogin/logout.spec.js b/test/cypress/integration/outLogin/logout.spec.js
index 423189908..8d4e90aac 100644
--- a/test/cypress/integration/outLogin/logout.spec.js
+++ b/test/cypress/integration/outLogin/logout.spec.js
@@ -13,7 +13,7 @@ describe('Logout', () => {
     });
     describe('not user', () => {
         beforeEach(() => {
-            cy.intercept('GET', '**/VnUsers/acl', {
+            cy.intercept('GET', '**DefaultViewConfigs**', {
                 statusCode: 401,
                 body: {
                     error: {
@@ -24,10 +24,11 @@ describe('Logout', () => {
                     },
                 },
                 statusMessage: 'AUTHORIZATION_REQUIRED',
-            }).as('someRoute');
+            });
         });
+
         it('when token not exists', () => {
-            cy.reload();
+            cy.get('.q-list > [href="#/item"]').click();
             cy.get('.q-notification__message').should(
                 'have.text',
                 'Authorization Required'

From d25cdbf34e808838eec6cddbc0f3347af84c60f0 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 22 Oct 2024 12:43:58 +0200
Subject: [PATCH 062/207] test: refs #6943 #6943 use command correctly

---
 test/cypress/integration/client/clientList.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 909bd3933..1b41e55cd 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -50,7 +50,7 @@ describe('Client list', () => {
         cy.clickButtonsDescriptor(2);
         cy.waitForElement('#formModel');
         cy.waitForElement('.q-form');
-        cy.checkValueForm(1, search);
+        cy.checkValueSelectForm(1, search);
     });
     it.skip('Client founded create order', () => {
         const search = 'Jessica Jones';

From a732ec05fbe6ba834d46c8eaf3d348c9dbcc0b01 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 13:21:16 +0200
Subject: [PATCH 063/207] test: refs #8039 add hasNotify and, refactor:
 agencyWorkCenter test

---
 src/components/FormModelPopup.vue             |  2 ++
 .../route/agency/agencyWorkCenter.spec.js     | 33 +++++++------------
 test/cypress/support/commands.js              | 11 +++++++
 3 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index 118c8f5f4..d91f07535 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -61,6 +61,7 @@ defineExpose({
                     :loading="isLoading"
                     @click="emit('onDataCanceled')"
                     v-close-popup
+                    data-cy="FormModelPopup_cancel"
                 />
                 <QBtn
                     :label="t('globals.save')"
@@ -70,6 +71,7 @@ defineExpose({
                     class="q-ml-sm"
                     :disabled="isLoading"
                     :loading="isLoading"
+                    data-cy="FormModelPopup_save"
                 />
             </div>
         </template>
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 353c5805b..6a3cab664 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -7,31 +7,20 @@ describe('AgencyWorkCenter', () => {
     const createButton = '.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon';
     const workCenterCombobox = 'input[role="combobox"]';
 
-    it('assign workCenter', () => {
+    it('check workCenter crud', () => {
+        // create
         cy.get(createButton).click();
         cy.get(workCenterCombobox).type('workCenterOne{enter}');
-        cy.get('.q-notification__message').should('have.text', 'Data created');
-    });
+        cy.hasNotify('Data created');
 
-    it('delete workCenter', () => {
+        // expect error when duplicate
+        cy.get(createButton).click();
+        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.hasNotify('This workCenter is already assigned to this agency');
+        cy.get('[data-cy="FormModelPopup_cancel"]').click();
+
+        // delete
         cy.get('.q-item__section--side > .q-btn > .q-btn__content > .q-icon').click();
-        cy.get('.q-notification__message').should(
-            'have.text',
-            'WorkCenter removed successfully'
-        );
-    });
-
-    it('error on duplicate workCenter', () => {
-        cy.get(createButton).click();
-        cy.get(workCenterCombobox).type('workCenterOne{enter}');
-        cy.get('.q-notification__message').should('have.text', 'Data created');
-        cy.get(createButton).click();
-        cy.get(
-            '.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'
-        ).type('workCenterOne{enter}');
-
-        cy.get(
-            ':nth-child(2) > .q-notification__wrapper > .q-notification__content > .q-notification__message'
-        ).should('have.text', 'This workCenter is already assigned to this agency');
+        cy.hasNotify('WorkCenter removed successfully');
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 83f45b721..c7b36cd3a 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -254,3 +254,14 @@ Cypress.Commands.add('openUserPanel', () => {
         '.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
     ).click();
 });
+
+Cypress.Commands.add('hasNotify', (text) => {
+    //last
+    cy.get('.q-notification')
+        .should('be.visible')
+        .last()
+        .then(($lastNotification) => {
+            if (!Cypress.$($lastNotification).text().includes(text))
+                throw new Error(`Notification not found: "${text}"`);
+        });
+});

From 2d81cffb3329bb874f32e41b3fe38c2eef6eb55e Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 13:34:20 +0200
Subject: [PATCH 064/207] feat: refs #8039 show duplicate request in local

---
 src/boot/quasar.js | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index bf5175ee6..7845719fe 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -4,6 +4,7 @@ import mainShortcutMixin from './mainShortcutMixin';
 import keyShortcut from './keyShortcut';
 import useNotify from 'src/composables/useNotify.js';
 import { CanceledError } from 'axios';
+
 const { notify } = useNotify();
 
 export default boot(({ app }) => {
@@ -41,7 +42,11 @@ export default boot(({ app }) => {
         }
 
         console.error(error);
-        if (error instanceof CanceledError) return;
+        if (error instanceof CanceledError) {
+            const env = process.env.NODE_ENV;
+            if (env && env !== 'development') return;
+            message = 'Duplicate request';
+        }
 
         notify(message ?? 'globals.error', 'negative', 'error');
     };

From 0c9c01b6e9f2ea6fa3674301039eed2f6501e65d Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 13:53:01 +0200
Subject: [PATCH 065/207] test: refs #8039 fix ZoneWarehouse e2e

---
 src/pages/Zone/Card/ZoneWarehouses.vue           | 16 ++++------------
 .../worker/workerNotificationsManager.spec.js    |  5 +----
 2 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/pages/Zone/Card/ZoneWarehouses.vue b/src/pages/Zone/Card/ZoneWarehouses.vue
index 6b2933224..98e446797 100644
--- a/src/pages/Zone/Card/ZoneWarehouses.vue
+++ b/src/pages/Zone/Card/ZoneWarehouses.vue
@@ -34,21 +34,13 @@ const columns = computed(() => [
 ]);
 
 const deleteWarehouse = async (row) => {
-    try {
-        await axios.delete(`${urlPath.value}/${row.id}`);
-        fetchWarehouses();
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.delete(`${urlPath.value}/${row.id}`);
+    fetchWarehouses();
 };
 
 const createZoneWarehouse = async (ZoneWarehouseFormData) => {
-    try {
-        await axios.post(urlPath.value, ZoneWarehouseFormData);
-        fetchWarehouses();
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.post(urlPath.value, ZoneWarehouseFormData);
+    fetchWarehouses();
 };
 
 watch(
diff --git a/test/cypress/integration/worker/workerNotificationsManager.spec.js b/test/cypress/integration/worker/workerNotificationsManager.spec.js
index ac452c4ff..367287a5a 100644
--- a/test/cypress/integration/worker/workerNotificationsManager.spec.js
+++ b/test/cypress/integration/worker/workerNotificationsManager.spec.js
@@ -17,10 +17,7 @@ describe('WorkerNotificationsManager', () => {
         cy.login('developer');
         cy.visit(`/#/worker/${salesPersonId}/notifications`);
         cy.get(firstAvailableNotification).click();
-        cy.notificationHas(
-            '.q-notification__message',
-            'The notification subscription of this worker cant be modified'
-        );
+        cy.hasNotify('The notification subscription of this worker cant be modified');
     });
 
     it('should active a notification that is yours', () => {

From cd00a3c67f0fe72a4437f3a2eae3e7eae5266ebf Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 13:55:35 +0200
Subject: [PATCH 066/207] test: refs #8039 fix WorkerNotification e2e

---
 src/pages/Worker/Card/WorkerNotificationsManager.vue | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/pages/Worker/Card/WorkerNotificationsManager.vue b/src/pages/Worker/Card/WorkerNotificationsManager.vue
index 731e073cd..53571fb93 100644
--- a/src/pages/Worker/Card/WorkerNotificationsManager.vue
+++ b/src/pages/Worker/Card/WorkerNotificationsManager.vue
@@ -44,8 +44,9 @@ async function toggleNotification(notification) {
                 `worker.notificationsManager.${notification.active ? '' : 'un'}subscribed`
             ),
         });
-    } catch {
+    } catch (e) {
         notification.active = !notification.active;
+        throw e;
     }
 }
 

From dd2dc86eea3d035aa6ee6845a1dd0047fb653db0 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 14:05:15 +0200
Subject: [PATCH 067/207] fix: refs #8039 o not handle unnecessary errors

---
 src/pages/Account/Alias/Card/AliasUsers.vue   |  10 +-
 src/pages/Account/Card/AccountMailAlias.vue   |  20 +--
 src/pages/Account/Role/Card/SubRoles.vue      |  26 +--
 .../Card/BasicData/TicketBasicDataForm.vue    |  28 +--
 .../Card/BasicData/TicketBasicDataView.vue    |  85 ++++-----
 src/pages/Ticket/Card/ExpeditionNewTicket.vue |  32 ++--
 src/pages/Ticket/Card/TicketComponents.vue    |  26 +--
 src/pages/Ticket/Card/TicketExpedition.vue    |  58 +++----
 .../Ticket/Card/TicketSaleMoreActions.vue     |  12 +-
 src/pages/Ticket/Card/TicketSaleTracking.vue  | 164 +++++++-----------
 src/pages/Ticket/Card/TicketService.vue       |  52 +++---
 src/pages/Ticket/Card/TicketVolume.vue        |  22 +--
 src/pages/Ticket/TicketAdvanceFilter.vue      |  24 ++-
 src/pages/Ticket/TicketFutureFilter.vue       |  40 ++---
 14 files changed, 228 insertions(+), 371 deletions(-)

diff --git a/src/pages/Account/Alias/Card/AliasUsers.vue b/src/pages/Account/Alias/Card/AliasUsers.vue
index 4a9c449e4..4aad68f1a 100644
--- a/src/pages/Account/Alias/Card/AliasUsers.vue
+++ b/src/pages/Account/Alias/Card/AliasUsers.vue
@@ -46,13 +46,9 @@ const columns = computed(() => [
 ]);
 
 const deleteAlias = async (row) => {
-    try {
-        await axios.delete(`${urlPath.value}/${row.id}`);
-        notify(t('User removed'), 'positive');
-        fetchAliases();
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.delete(`${urlPath.value}/${row.id}`);
+    notify(t('User removed'), 'positive');
+    fetchAliases();
 };
 
 watch(
diff --git a/src/pages/Account/Card/AccountMailAlias.vue b/src/pages/Account/Card/AccountMailAlias.vue
index 15d03c665..8d3bd3b67 100644
--- a/src/pages/Account/Card/AccountMailAlias.vue
+++ b/src/pages/Account/Card/AccountMailAlias.vue
@@ -61,23 +61,15 @@ const fetchAccountExistence = async () => {
 };
 
 const deleteMailAlias = async (row) => {
-    try {
-        await axios.delete(`${urlPath}/${row.id}`);
-        fetchMailAliases();
-        notify(t('Unsubscribed from alias!'), 'positive');
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.delete(`${urlPath}/${row.id}`);
+    fetchMailAliases();
+    notify(t('Unsubscribed from alias!'), 'positive');
 };
 
 const createMailAlias = async (mailAliasFormData) => {
-    try {
-        await axios.post(urlPath, mailAliasFormData);
-        notify(t('Subscribed to alias!'), 'positive');
-        fetchMailAliases();
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.post(urlPath, mailAliasFormData);
+    notify(t('Subscribed to alias!'), 'positive');
+    fetchMailAliases();
 };
 
 const fetchMailAliases = async () => {
diff --git a/src/pages/Account/Role/Card/SubRoles.vue b/src/pages/Account/Role/Card/SubRoles.vue
index d17f96dd8..6cac94667 100644
--- a/src/pages/Account/Role/Card/SubRoles.vue
+++ b/src/pages/Account/Role/Card/SubRoles.vue
@@ -46,29 +46,15 @@ const columns = computed(() => [
 ]);
 
 const deleteSubRole = async (row) => {
-    try {
-        await axios.delete(`${urlPath.value}/${row.id}`);
-        fetchSubRoles();
-        notify(
-            t('Role removed. Changes will take a while to fully propagate.'),
-            'positive'
-        );
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.delete(`${urlPath.value}/${row.id}`);
+    fetchSubRoles();
+    notify(t('Role removed. Changes will take a while to fully propagate.'), 'positive');
 };
 
 const createSubRole = async (subRoleFormData) => {
-    try {
-        await axios.post(urlPath.value, subRoleFormData);
-        notify(
-            t('Role added! Changes will take a while to fully propagate.'),
-            'positive'
-        );
-        fetchSubRoles();
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.post(urlPath.value, subRoleFormData);
+    notify(t('Role added! Changes will take a while to fully propagate.'), 'positive');
+    fetchSubRoles();
 };
 
 watch(
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index f5ce8a0f3..f6c20c514 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -112,32 +112,20 @@ const getShipped = async (params) => {
 };
 
 const onChangeZone = async (zoneId) => {
-    try {
-        formData.value.agencyModeFk = null;
-        const { data } = await axios.get(`Zones/${zoneId}`);
-        formData.value.agencyModeFk = data.agencyModeFk;
-    } catch (error) {
-        console.error(error);
-    }
+    formData.value.agencyModeFk = null;
+    const { data } = await axios.get(`Zones/${zoneId}`);
+    formData.value.agencyModeFk = data.agencyModeFk;
 };
 
 const onChangeAddress = async (addressId) => {
-    try {
-        formData.value.nickname = null;
-        const { data } = await axios.get(`Addresses/${addressId}`);
-        formData.value.nickname = data.nickname;
-    } catch (error) {
-        console.error(error);
-    }
+    formData.value.nickname = null;
+    const { data } = await axios.get(`Addresses/${addressId}`);
+    formData.value.nickname = data.nickname;
 };
 
 const getClientDefaultAddress = async (clientId) => {
-    try {
-        const { data } = await axios.get(`Clients/${clientId}`);
-        if (data) addressId.value = data.defaultAddressFk;
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.get(`Clients/${clientId}`);
+    if (data) addressId.value = data.defaultAddressFk;
 };
 
 const clientAddressesList = async (value) => {
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index 92640f898..fb7881403 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -70,60 +70,51 @@ const isFormInvalid = () => {
 };
 
 const getPriceDifference = async () => {
-    try {
-        const params = {
-            landed: formData.value.landed,
-            addressId: formData.value.addressFk,
-            agencyModeId: formData.value.agencyModeFk,
-            zoneId: formData.value.zoneFk,
-            warehouseId: formData.value.warehouseFk,
-            shipped: formData.value.shipped,
-        };
-        const { data } = await axios.post(
-            `tickets/${formData.value.id}/priceDifference`,
-            params
-        );
-        formData.value.sale = data;
-    } catch (error) {
-        console.error(error);
-    }
+    const params = {
+        landed: formData.value.landed,
+        addressId: formData.value.addressFk,
+        agencyModeId: formData.value.agencyModeFk,
+        zoneId: formData.value.zoneFk,
+        warehouseId: formData.value.warehouseFk,
+        shipped: formData.value.shipped,
+    };
+    const { data } = await axios.post(
+        `tickets/${formData.value.id}/priceDifference`,
+        params
+    );
+    formData.value.sale = data;
 };
 
 const submit = async () => {
-    try {
-        if (!formData.value.option)
-            return notify(t('basicData.chooseAnOption'), 'negative');
+    if (!formData.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
 
-        const params = {
-            clientFk: formData.value.clientFk,
-            nickname: formData.value.nickname,
-            agencyModeFk: formData.value.agencyModeFk,
-            addressFk: formData.value.addressFk,
-            zoneFk: formData.value.zoneFk,
-            warehouseFk: formData.value.warehouseFk,
-            companyFk: formData.value.companyFk,
-            shipped: formData.value.shipped,
-            landed: formData.value.landed,
-            isDeleted: formData.value.isDeleted,
-            option: formData.value.option,
-            isWithoutNegatives: formData.value.withoutNegatives,
-            withWarningAccept: formData.value.withWarningAccept,
-            keepPrice: false,
-        };
+    const params = {
+        clientFk: formData.value.clientFk,
+        nickname: formData.value.nickname,
+        agencyModeFk: formData.value.agencyModeFk,
+        addressFk: formData.value.addressFk,
+        zoneFk: formData.value.zoneFk,
+        warehouseFk: formData.value.warehouseFk,
+        companyFk: formData.value.companyFk,
+        shipped: formData.value.shipped,
+        landed: formData.value.landed,
+        isDeleted: formData.value.isDeleted,
+        option: formData.value.option,
+        isWithoutNegatives: formData.value.withoutNegatives,
+        withWarningAccept: formData.value.withWarningAccept,
+        keepPrice: false,
+    };
 
-        const { data } = await axios.post(
-            `tickets/${formData.value.id}/componentUpdate`,
-            params
-        );
+    const { data } = await axios.post(
+        `tickets/${formData.value.id}/componentUpdate`,
+        params
+    );
 
-        if (!data) return;
+    if (!data) return;
 
-        const ticketToMove = data.id;
-        notify(t('basicData.unroutedTicket'), 'positive');
-        router.push({ name: 'TicketSummary', params: { id: ticketToMove } });
-    } catch (error) {
-        console.error(error);
-    }
+    const ticketToMove = data.id;
+    notify(t('basicData.unroutedTicket'), 'positive');
+    router.push({ name: 'TicketSummary', params: { id: ticketToMove } });
 };
 
 const submitWithNegatives = async () => {
diff --git a/src/pages/Ticket/Card/ExpeditionNewTicket.vue b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
index 9183ae405..c288f6cc2 100644
--- a/src/pages/Ticket/Card/ExpeditionNewTicket.vue
+++ b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
@@ -34,26 +34,20 @@ const newTicketFormData = reactive({});
 const date = new Date();
 
 const createTicket = async () => {
-    try {
-        const expeditionIds = $props.selectedExpeditions.map(
-            (expedition) => expedition.id
-        );
-        const params = {
-            clientId: $props.ticket.clientFk,
-            landed: newTicketFormData.landed,
-            warehouseId: $props.ticket.warehouseFk,
-            addressId: $props.ticket.addressFk,
-            agencyModeId: $props.ticket.agencyModeFk,
-            routeId: newTicketFormData.routeFk,
-            expeditionIds: expeditionIds,
-        };
+    const expeditionIds = $props.selectedExpeditions.map((expedition) => expedition.id);
+    const params = {
+        clientId: $props.ticket.clientFk,
+        landed: newTicketFormData.landed,
+        warehouseId: $props.ticket.warehouseFk,
+        addressId: $props.ticket.addressFk,
+        agencyModeId: $props.ticket.agencyModeFk,
+        routeId: newTicketFormData.routeFk,
+        expeditionIds: expeditionIds,
+    };
 
-        const { data } = await axios.post('Expeditions/moveExpeditions', params);
-        notify(t('globals.dataSaved'), 'positive');
-        router.push({ name: 'TicketSummary', params: { id: data.id } });
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.post('Expeditions/moveExpeditions', params);
+    notify(t('globals.dataSaved'), 'positive');
+    router.push({ name: 'TicketSummary', params: { id: data.id } });
 };
 </script>
 
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 0bccdaacd..b5b3c430c 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -150,31 +150,19 @@ const getTotal = computed(() => {
 });
 
 const getComponentsSum = async () => {
-    try {
-        const { data } = await axios.get(`Tickets/${route.params.id}/getComponentsSum`);
-        componentsList.value = data;
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.get(`Tickets/${route.params.id}/getComponentsSum`);
+    componentsList.value = data;
 };
 
 const getTheoricalCost = async () => {
-    try {
-        const { data } = await axios.get(`Tickets/${route.params.id}/freightCost`);
-        theoricalCost.value = data;
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.get(`Tickets/${route.params.id}/freightCost`);
+    theoricalCost.value = data;
 };
 
 const getTicketVolume = async () => {
-    try {
-        if (!ticketData.value) return;
-        const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`);
-        ticketVolume.value = data[0].volume;
-    } catch (error) {
-        console.error(error);
-    }
+    if (!ticketData.value) return;
+    const { data } = await axios.get(`Tickets/${ticketData.value.id}/getVolume`);
+    ticketVolume.value = data[0].volume;
 };
 
 onMounted(() => {
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index 4becb3db3..b4a2ca732 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -187,18 +187,12 @@ const showNewTicketDialog = (withRoute = false) => {
 };
 
 const deleteExpedition = async () => {
-    try {
-        const expeditionIds = selectedExpeditions.value.map(
-            (expedition) => expedition.id
-        );
-        const params = { expeditionIds };
-        await axios.post('Expeditions/deleteExpeditions', params);
-        await refetchExpeditions();
-        selectedExpeditions.value = [];
-        notify(t('expedition.expeditionRemoved'), 'positive');
-    } catch (error) {
-        console.error(error);
-    }
+    const expeditionIds = selectedExpeditions.value.map((expedition) => expedition.id);
+    const params = { expeditionIds };
+    await axios.post('Expeditions/deleteExpeditions', params);
+    await refetchExpeditions();
+    selectedExpeditions.value = [];
+    notify(t('expedition.expeditionRemoved'), 'positive');
 };
 
 const showLog = async (expedition) => {
@@ -207,29 +201,25 @@ const showLog = async (expedition) => {
 };
 
 const getExpeditionState = async (expedition) => {
-    try {
-        const filter = {
-            where: { expeditionFk: expedition.id },
-            order: ['created DESC'],
+    const filter = {
+        where: { expeditionFk: expedition.id },
+        order: ['created DESC'],
+    };
+
+    const { data: expeditionStates } = await axios.get(`ExpeditionStates/filter`, {
+        params: { filter: JSON.stringify(filter) },
+    });
+    const { data: scannedStates } = await axios.get(`ExpeditionStates`, {
+        params: { filter: JSON.stringify(filter), fields: ['id', 'isScanned'] },
+    });
+
+    expeditionsLogsData.value = expeditionStates.map((state) => {
+        const scannedState = scannedStates.find((s) => s.id === state.id);
+        return {
+            ...state,
+            isScanned: scannedState ? scannedState.isScanned : false,
         };
-
-        const { data: expeditionStates } = await axios.get(`ExpeditionStates/filter`, {
-            params: { filter: JSON.stringify(filter) },
-        });
-        const { data: scannedStates } = await axios.get(`ExpeditionStates`, {
-            params: { filter: JSON.stringify(filter), fields: ['id', 'isScanned'] },
-        });
-
-        expeditionsLogsData.value = expeditionStates.map((state) => {
-            const scannedState = scannedStates.find((s) => s.id === state.id);
-            return {
-                ...state,
-                isScanned: scannedState ? scannedState.isScanned : false,
-            };
-        });
-    } catch (error) {
-        console.error(error);
-    }
+    });
 };
 
 onMounted(async () => {
diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 2ec519d2d..588f78a7b 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -165,14 +165,10 @@ const createRefund = async (withWarehouse) => {
         negative: true,
     };
 
-    try {
-        const { data } = await axios.post('Tickets/cloneAll', params);
-        const [refundTicket] = data;
-        notify(t('refundTicketCreated', { ticketId: refundTicket.id }), 'positive');
-        push({ name: 'TicketSale', params: { id: refundTicket.id } });
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.post('Tickets/cloneAll', params);
+    const [refundTicket] = data;
+    notify(t('refundTicketCreated', { ticketId: refundTicket.id }), 'positive');
+    push({ name: 'TicketSale', params: { id: refundTicket.id } });
 };
 </script>
 
diff --git a/src/pages/Ticket/Card/TicketSaleTracking.vue b/src/pages/Ticket/Card/TicketSaleTracking.vue
index e7830bf37..1083393c4 100644
--- a/src/pages/Ticket/Card/TicketSaleTracking.vue
+++ b/src/pages/Ticket/Card/TicketSaleTracking.vue
@@ -150,18 +150,14 @@ const shelvingsTableColumns = computed(() => [
 ]);
 
 const getSaleTrackings = async (sale) => {
-    try {
-        const filter = {
-            where: { saleFk: sale.saleFk },
-            order: ['itemFk DESC'],
-        };
-        const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
-            params: { filter: JSON.stringify(filter) },
-        });
-        saleTrackings.value = data;
-    } catch (error) {
-        console.error(error);
-    }
+    const filter = {
+        where: { saleFk: sale.saleFk },
+        order: ['itemFk DESC'],
+    };
+    const { data } = await axios.get(`SaleTrackings/listSaleTracking`, {
+        params: { filter: JSON.stringify(filter) },
+    });
+    saleTrackings.value = data;
 };
 
 const showLog = async (sale) => {
@@ -170,17 +166,13 @@ const showLog = async (sale) => {
 };
 
 const getItemShelvingSales = async (sale) => {
-    try {
-        const filter = {
-            where: { saleFk: sale.saleFk },
-        };
-        const { data } = await axios.get(`ItemShelvingSales/filter`, {
-            params: { filter: JSON.stringify(filter) },
-        });
-        itemShelvingsSales.value = data;
-    } catch (error) {
-        console.error(error);
-    }
+    const filter = {
+        where: { saleFk: sale.saleFk },
+    };
+    const { data } = await axios.get(`ItemShelvingSales/filter`, {
+        params: { filter: JSON.stringify(filter) },
+    });
+    itemShelvingsSales.value = data;
 };
 
 const showShelving = async (sale) => {
@@ -189,36 +181,28 @@ const showShelving = async (sale) => {
 };
 
 const updateQuantity = async (sale) => {
-    try {
-        if (oldQuantity.value === sale.quantity) return;
-        const params = {
-            quantity: sale.quantity,
-        };
-        await axios.patch(`ItemShelvingSales/${sale.id}`, params);
-        oldQuantity.value = null;
-    } catch (error) {
-        console.error(error);
-    }
+    if (oldQuantity.value === sale.quantity) return;
+    const params = {
+        quantity: sale.quantity,
+    };
+    await axios.patch(`ItemShelvingSales/${sale.id}`, params);
+    oldQuantity.value = null;
 };
 
 const updateParking = async (sale) => {
-    try {
-        const filter = {
-            fields: ['id'],
-            where: {
-                code: sale.shelvingFk,
-            },
-        };
-        const { data } = await axios.get(`Shelvings/findOne`, {
-            params: { filter: JSON.stringify(filter) },
-        });
-        const params = {
-            parkingFk: sale.parkingFk,
-        };
-        await axios.patch(`Shelvings/${data.id}`, params);
-    } catch (error) {
-        console.error(error);
-    }
+    const filter = {
+        fields: ['id'],
+        where: {
+            code: sale.shelvingFk,
+        },
+    };
+    const { data } = await axios.get(`Shelvings/findOne`, {
+        params: { filter: JSON.stringify(filter) },
+    });
+    const params = {
+        parkingFk: sale.parkingFk,
+    };
+    await axios.patch(`Shelvings/${data.id}`, params);
 };
 
 const updateShelving = async (sale) => {
@@ -241,61 +225,41 @@ const updateShelving = async (sale) => {
 };
 
 const saleTrackingNew = async (sale, stateCode, isChecked) => {
-    try {
-        const params = {
-            saleFk: sale.saleFk,
-            isChecked,
-            quantity: sale.quantity,
-            stateCode,
-        };
-        await axios.post(`SaleTrackings/new`, params);
-        notify(t('globals.dataSaved'), 'positive');
-    } catch (error) {
-        console.error(error);
-    }
+    const params = {
+        saleFk: sale.saleFk,
+        isChecked,
+        quantity: sale.quantity,
+        stateCode,
+    };
+    await axios.post(`SaleTrackings/new`, params);
+    notify(t('globals.dataSaved'), 'positive');
 };
 
 const saleTrackingDel = async ({ saleFk }, stateCode) => {
-    try {
-        const params = {
-            saleFk,
-            stateCodes: [stateCode],
-        };
-        await axios.post(`SaleTrackings/delete`, params);
-        notify(t('globals.dataSaved'), 'positive');
-    } catch (error) {
-        console.error(error);
-    }
+    const params = {
+        saleFk,
+        stateCodes: [stateCode],
+    };
+    await axios.post(`SaleTrackings/delete`, params);
+    notify(t('globals.dataSaved'), 'positive');
 };
 
 const clickSaleGroupDetail = async (sale) => {
-    try {
-        if (!sale.saleGroupDetailFk) return;
+    if (!sale.saleGroupDetailFk) return;
 
-        await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
-        sale.hasSaleGroupDetail = false;
-        notify(t('globals.dataSaved'), 'positive');
-    } catch (error) {
-        console.error(error);
-    }
+    await axios.delete(`SaleGroupDetails/${sale.saleGroupDetailFk}`);
+    sale.hasSaleGroupDetail = false;
+    notify(t('globals.dataSaved'), 'positive');
 };
 
 const clickPreviousSelected = (sale) => {
-    try {
-        qCheckBoxController(sale, 'isPreviousSelected');
-        if (!sale.isPreviousSelected) sale.isPrevious = false;
-    } catch (error) {
-        console.error(error);
-    }
+    qCheckBoxController(sale, 'isPreviousSelected');
+    if (!sale.isPreviousSelected) sale.isPrevious = false;
 };
 
 const clickPrevious = (sale) => {
-    try {
-        qCheckBoxController(sale, 'isPrevious');
-        if (sale.isPrevious) sale.isPreviousSelected = true;
-    } catch (error) {
-        console.error(error);
-    }
+    qCheckBoxController(sale, 'isPrevious');
+    if (sale.isPrevious) sale.isPreviousSelected = true;
 };
 
 const qCheckBoxController = (sale, action) => {
@@ -306,16 +270,12 @@ const qCheckBoxController = (sale, action) => {
         isPreviousSelected: 'PREVIOUS_PREPARATION',
     };
     const stateCode = STATE_CODES[action];
-    try {
-        if (!sale[action]) {
-            saleTrackingNew(sale, stateCode, true);
-            sale[action] = true;
-        } else {
-            saleTrackingDel(sale, stateCode);
-            sale[action] = false;
-        }
-    } catch (error) {
-        console.error(error);
+    if (!sale[action]) {
+        saleTrackingNew(sale, stateCode, true);
+        sale[action] = true;
+    } else {
+        saleTrackingDel(sale, stateCode);
+        sale[action] = false;
     }
 };
 </script>
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 45a870f7f..47c28a422 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -46,40 +46,32 @@ watch(
 onMounted(async () => await getDefaultTaxClass());
 
 const createRefund = async () => {
-    try {
-        if (!selected.value.length) return;
+    if (!selected.value.length) return;
 
-        const params = {
-            servicesIds: selected.value.map((s) => +s.id),
-            withWarehouse: false,
-            negative: true,
-        };
-        const { data } = await axios.post('Sales/clone', params);
-        const [refundTicket] = data;
-        notify(
-            t('service.createRefundSuccess', {
-                ticketId: refundTicket.id,
-            }),
-            'positive'
-        );
-        router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
-    } catch (error) {
-        console.error(error);
-    }
+    const params = {
+        servicesIds: selected.value.map((s) => +s.id),
+        withWarehouse: false,
+        negative: true,
+    };
+    const { data } = await axios.post('Sales/clone', params);
+    const [refundTicket] = data;
+    notify(
+        t('service.createRefundSuccess', {
+            ticketId: refundTicket.id,
+        }),
+        'positive'
+    );
+    router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
 };
 
 const getDefaultTaxClass = async () => {
-    try {
-        let filter = {
-            where: { code: 'G' },
-        };
-        const { data } = await axios.get('TaxClasses/findOne', {
-            params: { filter: JSON.stringify(filter) },
-        });
-        defaultTaxClass.value = data;
-    } catch (error) {
-        console.error(error);
-    }
+    let filter = {
+        where: { code: 'G' },
+    };
+    const { data } = await axios.get('TaxClasses/findOne', {
+        params: { filter: JSON.stringify(filter) },
+    });
+    defaultTaxClass.value = data;
 };
 
 const columns = computed(() => [
diff --git a/src/pages/Ticket/Card/TicketVolume.vue b/src/pages/Ticket/Card/TicketVolume.vue
index 2cf7ffc42..edfe489d9 100644
--- a/src/pages/Ticket/Card/TicketVolume.vue
+++ b/src/pages/Ticket/Card/TicketVolume.vue
@@ -75,22 +75,18 @@ const columns = computed(() => [
 ]);
 
 const applyVolumes = async (salesData) => {
-    try {
-        if (!salesData.length) return;
+    if (!salesData.length) return;
 
-        sales.value = salesData;
-        const ticket = sales.value[0].ticketFk;
-        const { data } = await axios.get(`Tickets/${ticket}/getVolume`);
-        const volumes = new Map(data.saleVolume.map((volume) => [volume.saleFk, volume]));
+    sales.value = salesData;
+    const ticket = sales.value[0].ticketFk;
+    const { data } = await axios.get(`Tickets/${ticket}/getVolume`);
+    const volumes = new Map(data.saleVolume.map((volume) => [volume.saleFk, volume]));
 
-        sales.value.forEach((sale) => {
-            sale.saleVolume = volumes.get(sale.id);
-        });
+    sales.value.forEach((sale) => {
+        sale.saleVolume = volumes.get(sale.id);
+    });
 
-        packingTypeVolume.value = data.packingTypeVolume;
-    } catch (error) {
-        console.error(error);
-    }
+    packingTypeVolume.value = data.packingTypeVolume;
 };
 
 onMounted(() => (stateStore.rightDrawer = true));
diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue
index b25ebdea6..27cacd80a 100644
--- a/src/pages/Ticket/TicketAdvanceFilter.vue
+++ b/src/pages/Ticket/TicketAdvanceFilter.vue
@@ -27,20 +27,16 @@ const warehousesOptions = ref([]);
 const itemPackingTypes = ref([]);
 
 const getItemPackingTypes = async () => {
-    try {
-        const filter = {
-            where: { isActive: true },
-        };
-        const { data } = await axios.get('ItemPackingTypes', {
-            params: { filter: JSON.stringify(filter) },
-        });
-        itemPackingTypes.value = data.map((ipt) => ({
-            description: t(ipt.description),
-            code: ipt.code,
-        }));
-    } catch (error) {
-        console.error(error);
-    }
+    const filter = {
+        where: { isActive: true },
+    };
+    const { data } = await axios.get('ItemPackingTypes', {
+        params: { filter: JSON.stringify(filter) },
+    });
+    itemPackingTypes.value = data.map((ipt) => ({
+        description: t(ipt.description),
+        code: ipt.code,
+    }));
 };
 
 onMounted(async () => await getItemPackingTypes());
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index 6345f62b3..ffe967272 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -24,33 +24,25 @@ const itemPackingTypes = ref([]);
 const stateOptions = ref([]);
 
 const getItemPackingTypes = async () => {
-    try {
-        const filter = {
-            where: { isActive: true },
-        };
-        const { data } = await axios.get('ItemPackingTypes', {
-            params: { filter: JSON.stringify(filter) },
-        });
-        itemPackingTypes.value = data.map((ipt) => ({
-            description: t(ipt.description),
-            code: ipt.code,
-        }));
-    } catch (error) {
-        console.error(error);
-    }
+    const filter = {
+        where: { isActive: true },
+    };
+    const { data } = await axios.get('ItemPackingTypes', {
+        params: { filter: JSON.stringify(filter) },
+    });
+    itemPackingTypes.value = data.map((ipt) => ({
+        description: t(ipt.description),
+        code: ipt.code,
+    }));
 };
 
 const getGroupedStates = async () => {
-    try {
-        const { data } = await axios.get('AlertLevels');
-        stateOptions.value = data.map((state) => ({
-            id: state.id,
-            name: t(`futureTickets.${state.code}`),
-            code: state.code,
-        }));
-    } catch (error) {
-        console.error(error);
-    }
+    const { data } = await axios.get('AlertLevels');
+    stateOptions.value = data.map((state) => ({
+        id: state.id,
+        name: t(`futureTickets.${state.code}`),
+        code: state.code,
+    }));
 };
 
 onMounted(async () => {

From ee31bc8262d511bc659316d7046b5f9d0228034d Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Oct 2024 14:07:27 +0200
Subject: [PATCH 068/207] chore: refs #8039 not required

---
 src/boot/axios.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/boot/axios.js b/src/boot/axios.js
index b084b835d..aee38e887 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -3,7 +3,6 @@ import { useSession } from 'src/composables/useSession';
 import { Router } from 'src/router';
 import useNotify from 'src/composables/useNotify.js';
 import { useStateQueryStore } from 'src/stores/useStateQueryStore';
-import { CanceledError } from 'axios';
 
 const session = useSession();
 const { notify } = useNotify();

From ae56c06628010c4197c0b5fa9f858df99711800f Mon Sep 17 00:00:00 2001
From: jgallego <jgallego@verdnatura.es>
Date: Wed, 23 Oct 2024 07:45:00 +0200
Subject: [PATCH 069/207] feat: refs #7349 usa back con permisos

---
 src/pages/Item/ItemRequest.vue                | 23 ++++++++++++++----
 src/pages/Item/ItemTypeCreate.vue             | 24 ++++++++++++++-----
 src/pages/ItemType/Card/ItemTypeBasicData.vue | 22 +++++++++++++----
 3 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 82c3b48e0..25082697d 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -258,15 +258,28 @@ onBeforeMount(() => {
             <template #body-cell-attender="{ row }">
                 <QTd>
                     <VnSelect
+                        url="Workers/search"
                         v-model="row.attenderFk"
-                        :where="{ role: 'buyer' }"
-                        sort-by="id"
-                        url="Workers"
+                        :params="{ departmentCodes: ['shopping'] }"
+                        :fields="['id', 'nickname']"
+                        sort-by="nickname ASC"
                         hide-selected
-                        option-label="firstName"
+                        option-label="nickname"
                         option-value="id"
                         dense
-                    />
+                    >
+                        <template #option="scope">
+                            <QItem v-bind="scope.itemProps">
+                                <QItemSection>
+                                    <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                    <QItemLabel caption
+                                        >{{ scope.opt?.nickname }},
+                                        {{ scope.opt?.code }}</QItemLabel
+                                    >
+                                </QItemSection>
+                            </QItem>
+                        </template>
+                    </VnSelect>
                 </QTd>
             </template>
             <template #body-cell-item="{ row }">
diff --git a/src/pages/Item/ItemTypeCreate.vue b/src/pages/Item/ItemTypeCreate.vue
index 290a40389..60c037510 100644
--- a/src/pages/Item/ItemTypeCreate.vue
+++ b/src/pages/Item/ItemTypeCreate.vue
@@ -52,15 +52,27 @@ const redirectToItemTypeBasicData = (_, { id }) => {
                 </VnRow>
                 <VnRow>
                     <VnSelect
+                        url="Workers/search"
                         v-model="data.workerFk"
-                        :label="t('itemType.shared.worker')"
-                        url="Workers"
-                        sort-by="firstName ASC"
-                        :fields="['id', 'firstName']"
+                        :label="t('shared.worker')"
+                        sort-by="nickname ASC"
+                        :fields="['id', 'nickname']"
+                        :params="{ departmentCodes: ['shopping'] }"
+                        option-label="nickname"
                         option-value="id"
-                        option-label="firstName"
                         hide-selected
-                    />
+                        ><template #option="scope">
+                            <QItem v-bind="scope.itemProps">
+                                <QItemSection>
+                                    <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                    <QItemLabel caption
+                                        >{{ scope.opt?.nickname }},
+                                        {{ scope.opt?.code }}</QItemLabel
+                                    >
+                                </QItemSection>
+                            </QItem>
+                        </template>
+                    </VnSelect>
                     <VnSelect
                         v-model="data.categoryFk"
                         :label="t('itemType.shared.category')"
diff --git a/src/pages/ItemType/Card/ItemTypeBasicData.vue b/src/pages/ItemType/Card/ItemTypeBasicData.vue
index d35fbb17d..1d4a5cf94 100644
--- a/src/pages/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/ItemType/Card/ItemTypeBasicData.vue
@@ -41,15 +41,27 @@ const temperaturesOptions = ref([]);
             </VnRow>
             <VnRow>
                 <VnSelect
+                    url="Workers/search"
                     v-model="data.workerFk"
                     :label="t('shared.worker')"
-                    url="Workers"
-                    sort-by="firstName ASC"
-                    :fields="['id', 'firstName']"
+                    sort-by="nickname ASC"
+                    :fields="['id', 'nickname']"
+                    :params="{ departmentCodes: ['shopping'] }"
+                    option-label="nickname"
                     option-value="id"
-                    option-label="firstName"
                     hide-selected
-                />
+                    ><template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                <QItemLabel caption
+                                    >{{ scope.opt?.nickname }},
+                                    {{ scope.opt?.code }}</QItemLabel
+                                >
+                            </QItemSection>
+                        </QItem>
+                    </template></VnSelect
+                >
                 <VnSelect
                     v-model="data.categoryFk"
                     :label="t('shared.category')"

From 1bf1844c8f9edf13b8c0a6f414510a184e70edf0 Mon Sep 17 00:00:00 2001
From: jgallego <jgallego@verdnatura.es>
Date: Wed, 23 Oct 2024 07:46:52 +0200
Subject: [PATCH 070/207] fix: refs #7349 dependencia no usada

---
 src/components/VnSelectProvince.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/VnSelectProvince.vue b/src/components/VnSelectProvince.vue
index 606799e50..9fcbef11e 100644
--- a/src/components/VnSelectProvince.vue
+++ b/src/components/VnSelectProvince.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, watch } from 'vue';
+import { ref } from 'vue';
 import { useValidator } from 'src/composables/useValidator';
 import { useI18n } from 'vue-i18n';
 

From b40af0ce7bb73660464db2b2b945261920528ece Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 23 Oct 2024 09:49:48 +0200
Subject: [PATCH 071/207] fix: refs #7283 fix pr

---
 src/pages/Item/Card/ItemBasicData.vue  |  8 ++-
 src/pages/Item/Card/ItemBotanical.vue  |  7 ---
 src/pages/Item/Card/ItemDescriptor.vue | 13 ++++
 src/pages/Item/Card/ItemTax.vue        |  4 +-
 src/pages/Item/ItemRequest.vue         | 34 ++++++++++-
 src/pages/Item/ItemTypeList.vue        | 85 +++++++++-----------------
 6 files changed, 84 insertions(+), 67 deletions(-)

diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index 6b6d89c6d..1b0342668 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -85,13 +85,19 @@ const onIntrastatCreated = (response, formData) => {
                 <VnInput :label="t('item.basicData.reference')" v-model="data.comment" />
                 <VnInput
                     :label="t('item.basicData.relevancy')"
+                    type="number"
                     v-model="data.relevancy"
                 />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <VnInput :label="t('item.basicData.stems')" v-model="data.stems" />
+                <VnInput
+                    :label="t('item.basicData.stems')"
+                    type="number"
+                    v-model="data.stems"
+                />
                 <VnInput
                     :label="t('item.basicData.multiplier')"
+                    type="number"
                     v-model="data.stemMultiplier"
                 />
                 <VnSelectDialog
diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index 5f7f3a5e4..1aa6faed1 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -20,15 +20,8 @@ let itemBotanicalsForm = reactive({ itemFk: null });
 const entityId = computed(() => {
     return route.params.id;
 });
-// onMounted(async () => {
-//     itemBotanicalsForm.itemFk = entityId.value;
-//     // itemBotanicals.value = await itemBotanicalsRef.value.fetch();
-//     if (itemBotanicals.value.length > 0)
-//         Object.assign(itemBotanicalsForm, itemBotanicals.value[0]);
-// });
 async function handleItemBotanical(data) {
     itemBotanicalsForm = data;
-    // if (data.length > 0) Object.assign(itemBotanicalsForm, itemBotanicals.value[0]);
 }
 </script>
 <template>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index 09d6a8a4f..aa9795a74 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -189,6 +189,18 @@ const openCloneDialog = async () => {
                 :value="entity.value7"
             />
         </template>
+        <template #icons="{ entity }">
+            <QCardActions v-if="entity" class="q-gutter-x-md">
+                <QIcon
+                    v-if="!entity.isActive"
+                    name="vn:unavailable"
+                    color="primary"
+                    size="xs"
+                >
+                    <QTooltip>{{ t('Inactive article') }}</QTooltip>
+                </QIcon>
+            </QCardActions>
+        </template>
         <template #actions="{}">
             <QCardActions class="row justify-center">
                 <QBtn
@@ -213,6 +225,7 @@ es:
     Regularize stock: Regularizar stock
     All its properties will be copied: Todas sus propiedades serán copiadas
     Do you want to clone this item?: ¿Desea clonar este artículo?
+    Inactive article: Artículo inactivo
 </i18n>
 
 <style lang="scss" scoped>
diff --git a/src/pages/Item/Card/ItemTax.vue b/src/pages/Item/Card/ItemTax.vue
index 489a2c7b2..9050db42e 100644
--- a/src/pages/Item/Card/ItemTax.vue
+++ b/src/pages/Item/Card/ItemTax.vue
@@ -22,7 +22,7 @@ const taxesFilter = {
         {
             relation: 'country',
             scope: {
-                fields: ['country'],
+                fields: ['name'],
             },
         },
     ],
@@ -73,7 +73,7 @@ const submitTaxes = async (data) => {
                 >
                     <VnInput
                         :label="t('tax.country')"
-                        v-model="row.country.country"
+                        v-model="row.country.name"
                         disable
                     />
                     <VnSelect
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 0eba6f9a4..ea265e706 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -5,7 +5,7 @@ import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.v
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { useArrayData } from 'composables/useArrayData';
-import { toCurrency } from 'filters/index';
+import { dashIfEmpty, toCurrency } from 'filters/index';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
@@ -134,6 +134,20 @@ const columns = computed(() => [
     },
 ]);
 
+const getBadgeColor = (date) => {
+    const today = Date.vnNew();
+    today.setHours(0, 0, 0, 0);
+
+    const orderLanded = new Date(date);
+    orderLanded.setHours(0, 0, 0, 0);
+
+    const difference = today - orderLanded;
+
+    if (difference == 0) return 'warning';
+    if (difference < 0) return 'success';
+    if (difference > 0) return 'alert';
+};
+
 const changeQuantity = async (request) => {
     try {
         if (request.saleFk) {
@@ -212,6 +226,24 @@ onMounted(async () => {
         auto-load
         :disable-option="{ card: true }"
     >
+        <template #column-ticketFk="{ row }">
+            <span class="link">
+                {{ row.ticketFk }}
+                <TicketDescriptorProxy :id="row.ticketFk" />
+            </span>
+        </template>
+        <template #column-shipped="{ row }">
+            <QTd>
+                <QBadge
+                    :color="getBadgeColor(row.shipped)"
+                    text-color="black"
+                    class="q-pa-sm"
+                    style="font-size: 14px"
+                >
+                    {{ toDate(row.shipped) }}
+                </QBadge>
+            </QTd>
+        </template>
         <template #column-attenderName="{ row }">
             <span class="link" @click.stop>
                 {{ row.attenderName }}
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 5ebbec62b..9981a0d68 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -1,54 +1,14 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
+import { useRoute } from 'vue-router';
 import { ref, computed } from 'vue';
 import ItemTypeSearchbar from '../ItemType/ItemTypeSearchbar.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 
-const router = useRouter();
+const route = useRoute();
 const { t } = useI18n();
 const tableRef = ref();
-const redirectToItemTypeSummary = (id) => {
-    router.push({ name: 'ItemTypeSummary', params: { id } });
-};
-
-const redirectToCreateView = () => {
-    router.push({ name: 'ItemTypeCreate' });
-};
-
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'name':
-            return {
-                name: { like: `%${value}%` },
-            };
-        case 'code':
-            return {
-                code: { like: `%${value}%` },
-            };
-        case 'search':
-            if (value) {
-                if (!isNaN(value)) {
-                    return { id: value };
-                } else {
-                    return {
-                        or: [
-                            {
-                                name: {
-                                    like: `%${value}%`,
-                                },
-                            },
-                            {
-                                code: {
-                                    like: `%${value}%`,
-                                },
-                            },
-                        ],
-                    };
-                }
-            }
-    }
-};
+const entityId = computed(() => route.params.id);
 
 const columns = computed(() => [
     {
@@ -75,20 +35,21 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        name: 'worker',
+        name: 'workerFk',
         label: t('worker'),
         create: true,
         component: 'select',
         attrs: {
             url: 'Workers',
-            fields: ['id', 'firstName'],
+            optionLabel: 'firstName',
+            optionValue: 'id',
         },
-        cardVisible: true,
+        cardVisible: false,
         visible: false,
     },
     {
         align: 'left',
-        name: 'ItemCategory',
+        name: 'categoryFk',
         label: t('ItemCategory'),
         create: true,
         component: 'select',
@@ -96,7 +57,7 @@ const columns = computed(() => [
             url: 'ItemCategories',
             fields: ['id', 'name'],
         },
-        cardVisible: true,
+        cardVisible: false,
         visible: false,
     },
     {
@@ -109,7 +70,7 @@ const columns = computed(() => [
             url: 'Temperatures',
             fields: ['id', 'name'],
         },
-        cardVisible: true,
+        cardVisible: false,
         visible: false,
     },
 ]);
@@ -121,18 +82,13 @@ const columns = computed(() => [
         ref="tableRef"
         data-key="ItemTypeList"
         :url="`ItemTypes`"
-        :url-create="`ItemTypes`"
-        save-url="ItemTypes/crud"
-        :filter="courseFilter"
         :create="{
             urlCreate: 'ItemTypes',
             title: 'Create ItemTypes',
             onDataSaved: () => tableRef.reload(),
-            formInitialData: {
-                workerFk: entityId,
-            },
+            formInitialData: {},
         }"
-        order="id DESC"
+        order="code ASC"
         :columns="columns"
         auto-load
         :right-search="false"
@@ -140,3 +96,20 @@ const columns = computed(() => [
         :use-model="true"
     />
 </template>
+
+<i18n>
+    es:
+        id: Id
+        code: Código
+        name: Nombre
+        worker: Encargado
+        ItemCategory: Categoría
+        Temperature: Temperatura
+        Create ItemTypes: Crear familia
+    en:
+        code: Code
+        name: Name
+        worker: Worker
+        ItemCategory: ItemCategory
+        Temperature: Temperature
+</i18n>

From b69ef48a44ba04dfc7c5012a59c3cf97dcfd2baf Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Wed, 23 Oct 2024 12:21:34 +0200
Subject: [PATCH 072/207] refactor: refs #7132 deleted pageTitles repeated

---
 src/i18n/locale/en.yml | 43 ------------------------------------
 src/i18n/locale/es.yml | 49 ------------------------------------------
 2 files changed, 92 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 9049a44a9..d7456ce8f 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -354,9 +354,6 @@ twoFactorRequired:
     explanation: >-
         Please, enter the verification code that we have sent to your email in the
         next 5 minutes
-verifyEmail:
-    pageTitles:
-        verifyEmail: Email verification
 recoverPassword:
     userOrEmail: User or recovery email
     explanation: >-
@@ -436,16 +433,6 @@ entry:
             isExcludedFromAvailable: Es inventory
             isRaid: Raid
 ticket:
-    pageTitles:
-        list: List
-        summary: Summary
-        sale: Sale
-        dms: File management
-        observation: Notes
-        ticketAdvance: Advance tickets
-        futureTickets: Future tickets
-        purchaseRequest: Purchase request
-        weeklyTickets: Weekly tickets
     card:
         customerId: Customer ID
         customerCard: Customer card
@@ -544,8 +531,6 @@ parking:
     sector: Sector
     row: Row
     column: Column
-    pageTitles:
-        parking: Parking
     searchBar:
         info: You can search by parking code
         label: Search parking...
@@ -569,9 +554,6 @@ order:
         orderTicketList: Order Ticket List
         amount: Amount
 department:
-    pageTitles:
-        department: Department
-        summary: Summary
     chat: Chat
     bossDepartment: Boss Department
     selfConsumptionCustomer: Self-consumption customer
@@ -582,21 +564,6 @@ department:
     hasToSendMail: Send check-ins by email
     departmentRemoved: Department removed
 worker:
-    pageTitles:
-        workers: Workers
-        list: List
-        summary: Summary
-        workerCreate: New worker
-        department: Department
-        pda: PDA
-        dms: My documentation
-        pbx: Private Branch Exchange
-        log: Log
-        calendar: Calendar
-        timeControl: Time control
-        locker: Locker
-        medical: Medical
-        operator: Operator
     list:
         department: Department
         schedule: Schedule
@@ -680,16 +647,6 @@ worker:
         isOnReservationMode: Reservation mode
         machine: Machine
 wagon:
-    pageTitles:
-        wagons: Wagons
-        wagonsList: Wagons List
-        wagonCreate: Create wagon
-        wagonEdit: Edit wagon
-        typesList: Types List
-        typeCreate: Create type
-        typeEdit: Edit type
-        wagonCounter: Trolley counter
-        wagonTray: Tray List
     type:
         submit: Submit
         reset: Reset
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 69f4f6b0c..71f820d8f 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -356,9 +356,6 @@ twoFactor:
     validate: Validar
     insert: Introduce el código de verificación
     explanation: Por favor introduce el código de verificación que te hemos enviado a tu email en los próximos 5 minutos
-verifyEmail:
-    pageTitles:
-        verifyEmail: Verificación de correo
 recoverPassword:
     userOrEmail: Usuario o correo de recuperación
     explanation: >-
@@ -439,21 +436,6 @@ entry:
             isExcludedFromAvailable: Es inventario
             isRaid: Redada
 ticket:
-    pageTitles:
-        list: Listado
-        summary: Resumen
-        dms: Gestión documental
-        observation: Notas
-        ticketAdvance: Adelantar tickets
-        futureTickets: Tickets a futuro
-        expedition: Expedición
-        purchaseRequest: Petición de compra
-        weeklyTickets: Tickets programados
-        saleTracking: Líneas preparadas
-        services: Servicios
-        tracking: Estados
-        components: Componentes
-        pictures: Fotos
     card:
         customerId: ID cliente
         customerCard: Ficha del cliente
@@ -570,15 +552,10 @@ parking:
     pickingOrder: Orden de recogida
     row: Fila
     column: Columna
-    pageTitles:
-        parking: Parking
     searchBar:
         info: Puedes buscar por código de parking
         label: Buscar parking...
 department:
-    pageTitles:
-        department: Departamentos
-        summary: Resumen
     chat: Chat
     bossDepartment: Jefe de departamento
     selfConsumptionCustomer: Cliente autoconsumo
@@ -589,22 +566,6 @@ department:
     hasToSendMail: Enviar fichadas por mail
     departmentRemoved: Departamento eliminado
 worker:
-    pageTitles:
-        workers: Trabajadores
-        list: Listado
-        summary: Resumen
-        workerCreate: Nuevo trabajador
-        department: Departamentos
-        pda: PDA
-        dms: Mi documentación
-        pbx: Centralita
-        log: Historial
-        calendar: Calendario
-        timeControl: Control de horario
-        locker: Taquilla
-        formation: Formación
-        medical: Mutua
-        operator: Operario
     list:
         department: Departamento
         schedule: Horario
@@ -680,16 +641,6 @@ worker:
         machine: Máquina
 
 wagon:
-    pageTitles:
-        wagons: Vagones
-        wagonsList: Listado vagones
-        wagonCreate: Crear tipo
-        wagonEdit: Editar tipo
-        typesList: Listado tipos
-        typeCreate: Crear tipo
-        typeEdit: Editar tipo
-        wagonCounter: Contador de carros
-        wagonTray: Listado bandejas
     type:
         submit: Guardar
         reset: Deshacer cambios

From d8b80cfa6d31087bee361d9b48a999b3f199e59a Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Wed, 23 Oct 2024 12:30:04 +0200
Subject: [PATCH 073/207] fix: refs #7283 fix pr

---
 src/pages/Item/Card/ItemBotanical.vue  | 5 +----
 src/pages/Item/Card/ItemDescriptor.vue | 2 --
 2 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index 1aa6faed1..c4b561772 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -20,9 +20,6 @@ let itemBotanicalsForm = reactive({ itemFk: null });
 const entityId = computed(() => {
     return route.params.id;
 });
-async function handleItemBotanical(data) {
-    itemBotanicalsForm = data;
-}
 </script>
 <template>
     <FetchData
@@ -41,7 +38,7 @@ async function handleItemBotanical(data) {
         :filter="{
             where: { itemFk: entityId },
         }"
-        @on-fetch="handleItemBotanical"
+        @on-fetch="(data) => (itemBotanicalsForm = data)"
     >
         <template #form="{ data }">
             <VnRow>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index aa9795a74..635dd17c8 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -50,7 +50,6 @@ const entityId = computed(() => {
 });
 
 const regularizeStockFormDialog = ref(null);
-const salixUrl = ref();
 const mounted = ref();
 
 const arrayDataStock = useArrayData('descriptorStock', {
@@ -58,7 +57,6 @@ const arrayDataStock = useArrayData('descriptorStock', {
 });
 
 onMounted(async () => {
-    salixUrl.value = await getUrl('getVisibleAvailable');
     await getItemConfigs();
     mounted.value = true;
 });

From 37b3affdbfc2c406b72116ac89657218e38f7adc Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Wed, 23 Oct 2024 13:02:28 +0200
Subject: [PATCH 074/207] refactor: revert catalog changes

---
 src/components/ui/VnFilterPanel.vue         |  12 +--
 src/components/ui/VnSearchbar.vue           |   2 -
 src/pages/Order/Card/OrderCatalog.vue       |   5 +-
 src/pages/Order/Card/OrderCatalogFilter.vue | 108 ++++++++------------
 4 files changed, 50 insertions(+), 77 deletions(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 66e9df5f5..43d634ad9 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -185,9 +185,6 @@ async function remove(key) {
 }
 
 function formatValue(value) {
-    if (typeof value === 'object') {
-        return value;
-    }
     if (typeof value === 'boolean') return value ? t('Yes') : t('No');
     if (isNaN(value) && !isNaN(Date.parse(value))) return toDate(value);
 
@@ -196,13 +193,6 @@ function formatValue(value) {
 
 function sanitizer(params) {
     for (const [key, value] of Object.entries(params)) {
-        if (key == 'and') {
-            value.forEach((andValue) => {
-                params = { ...params, ...andValue };
-            });
-            delete params[key];
-        }
-
         if (value && typeof value === 'object') {
             const param = Object.values(value)[0];
             if (typeof param == 'string') params[key] = param.replaceAll('%', '');
@@ -221,7 +211,7 @@ function sanitizer(params) {
         icon="search"
         @click="search()"
     ></QBtn>
-    <QForm @submit="search" id="filterPanelForm" @keyup.enter.prevent="search(true)">
+    <QForm @submit="search" id="filterPanelForm" @keyup.enter="search()">
         <QList dense>
             <QItem class="q-mt-xs">
                 <QItemSection top>
diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index 569e0ed18..dc6d4751c 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -9,7 +9,6 @@ import { useStateStore } from 'src/stores/useStateStore';
 const quasar = useQuasar();
 const { t } = useI18n();
 const state = useStateStore();
-const emit = defineEmits(['onSearch']);
 
 const props = defineProps({
     dataKey: {
@@ -119,7 +118,6 @@ async function search() {
         delete filter.params.search;
     }
     await arrayData.applyFilter(filter);
-    emit('onSearch', store.data);
 }
 </script>
 <template>
diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index 110ea48af..f9bcca94c 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -86,8 +86,11 @@ function extractValueTags(items) {
         <div class="full-width">
             <VnPaginate
                 data-key="OrderCatalogList"
+                url="Orders/CatalogFilter"
+                :limit="50"
+                :user-params="catalogParams"
+                @on-fetch="extractTags"
                 :update-router="false"
-                @on-change="extractTags"
             >
                 <template #body="{ rows }">
                     <div class="catalog-list">
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 0fe8c4d64..6de43e86a 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -1,13 +1,14 @@
 <script setup>
-import { computed, ref, onMounted, watch } from 'vue';
+import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import axios from 'axios';
 import FetchData from 'components/FetchData.vue';
 import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
 import VnSelect from 'components/common/VnSelect.vue';
+import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
+import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
-import VnFilterPanelChip from 'src/components/ui/VnFilterPanelChip.vue';
 
 const { t } = useI18n();
 
@@ -47,19 +48,6 @@ const orderWayList = ref([
 const orderBySelected = ref('relevancy DESC, name');
 const orderWaySelected = ref('ASC');
 
-const routeQuery = JSON.parse(route?.query.params ?? '{}');
-const paramsSearch = ref({});
-const tagData = ref([]);
-
-onMounted(() => {
-    paramsSearch.value = JSON.parse(routeQuery.filter ?? '{}')?.where ?? {};
-    if (Object.keys(paramsSearch.value).length > 0) vnFilterPanelRef.value.search();
-    if (routeQuery.categoryFk && routeQuery.typeFk) {
-        selectedCategoryFk.value = routeQuery.categoryFk;
-        selectedTypeFk.value = routeQuery.typeFk;
-    }
-});
-
 const createValue = (val, done) => {
     if (val.length > 2) {
         if (!tagOptions.value.includes(val)) {
@@ -73,21 +61,19 @@ const resetCategory = () => {
     typeList.value = null;
 };
 
-const selectCategory = (category, search) => {
-    if (!paramsSearch.value?.filter) paramsSearch.value.filter = { where: {} };
-    const where = paramsSearch.value.filter.where;
-    if (where.categoryFk === category?.id) {
+const clearFilter = (key) => {
+    if (key === 'categoryFk') {
         resetCategory();
-        where.categoryFk = null;
-    } else {
-        if (where.categoryFk && where.categoryFk !== category?.id) {
-            paramsSearch.value.typeFk = null;
-            selectedTypeFk.value = null;
-            typeList.value = [];
-        }
+    }
+};
 
+const selectCategory = (params, category, search) => {
+    if (params.categoryFk === category?.id) {
+        resetCategory();
+        params.categoryFk = null;
+    } else {
         selectedCategoryFk.value = category?.id;
-        where.categoryFk = category?.id;
+        params.categoryFk = category?.id;
         loadTypes(category?.id);
     }
     search();
@@ -100,10 +86,6 @@ const loadTypes = async (categoryFk = selectedCategoryFk.value) => {
     typeList.value = data;
 };
 
-watch(selectedTypeFk, (newValue) => {
-    paramsSearch.value.typeFk = newValue;
-});
-
 const selectedCategory = computed(() =>
     (categoryList.value || []).find(
         (category) => category?.id === selectedCategoryFk.value
@@ -121,17 +103,26 @@ const selectedType = computed(() => {
     return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
 });
 
+function exprBuilder(param, value) {
+    switch (param) {
+        case 'categoryFk':
+        case 'typeFk':
+            return { [param]: value };
+        case 'search':
+            if (/^\d+$/.test(value)) return { 'i.id': value };
+            else return { 'i.name': { like: `%${value}%` } };
+    }
+}
+
 const applyTagFilter = (params, search) => {
     if (!tagValues.value?.length) {
         params.tagGroups = null;
         search();
         return;
     }
-
-    if (!params.tagGroups || typeof params.tagGroups === 'string') {
+    if (!params.tagGroups) {
         params.tagGroups = [];
     }
-
     params.tagGroups.push(
         JSON.stringify({
             values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
@@ -142,29 +133,17 @@ const applyTagFilter = (params, search) => {
             tagFk: selectedTag?.value?.tagFk,
         })
     );
-
-    tagData.value.push(JSON.parse(params.tagGroups[params.tagGroups.length - 1]));
     search();
     selectedTag.value = null;
     tagValues.value = [{}];
 };
 
 const removeTagChip = (selection, params, search) => {
-    if (typeof params.tagGroups === 'string') {
-        try {
-            params.tagGroups = JSON.parse(params.tagGroups);
-        } catch (error) {
-            console.error('Error parsing tagGroups:', error);
-            params.tagGroups = [];
-        }
+    if (params.tagGroups) {
+        params.tagGroups = (params.tagGroups || []).filter(
+            (value) => value !== selection
+        );
     }
-    console.log('params.tagGroups: ', params.tagGroups);
-    console.log('selection: ', selection);
-
-    if (Array.isArray(params.tagGroups)) {
-        params.tagGroups = params.tagGroups.filter((value) => value !== selection);
-    }
-
     search();
 };
 
@@ -199,12 +178,12 @@ function addOrder(value, field, params) {
     <VnFilterPanel
         ref="vnFilterPanelRef"
         :data-key="props.dataKey"
-        v-model="paramsSearch"
-        :redirect="false"
-        :hidden-tags="['orderFk', 'orderBy', 'filter', 'search', 'or', 'and']"
+        :hidden-tags="['orderFk', 'orderBy']"
+        :un-removable-params="['orderFk', 'orderBy']"
+        :expr-builder="exprBuilder"
         :custom-tags="['tagGroups']"
-        :unremovable-params="['orderFk', 'orderBy']"
-        :disable-submit-event="true"
+        @remove="clearFilter"
+        :redirect="false"
     >
         <template #tags="{ tag, formatFn }">
             <strong v-if="tag.label === 'categoryFk'">
@@ -222,13 +201,17 @@ function addOrder(value, field, params) {
             <template v-for="tag in customTags" :key="tag.label">
                 <template v-if="tag.label === 'tagGroups'">
                     <VnFilterPanelChip
-                        v-for="chip in tagData"
+                        v-for="chip in tag.value"
                         :key="chip"
                         removable
                         @remove="removeTagChip(chip, params, searchFn)"
                     >
-                        <strong>{{ chip.tagSelection?.name }}: </strong>
-                        <span>{{ chip.values[0].value }}</span>
+                        <strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
+                        <span>{{
+                            (JSON.parse(chip).values || [])
+                                .map((item) => item.value)
+                                .join(' | ')
+                        }}</span>
                     </VnFilterPanelChip>
                 </template>
             </template>
@@ -243,7 +226,7 @@ function addOrder(value, field, params) {
                     <QIcon
                         :name="category.icon"
                         class="category-icon"
-                        @click="selectCategory(category, searchFn)"
+                        @click="selectCategory(params, category, searchFn)"
                     >
                         <QTooltip>
                             {{ t(category.name) }}
@@ -337,7 +320,7 @@ function addOrder(value, field, params) {
             >
                 <FetchData
                     v-if="selectedTag"
-                    :url="`Tags/${selectedTag.id}/filterValue`"
+                    :url="`Tags/${selectedTag}/filterValue`"
                     limit="30"
                     auto-load
                     @on-fetch="(data) => (tagOptions = data)"
@@ -360,7 +343,7 @@ function addOrder(value, field, params) {
                     @update:model-value="applyTagFilter(params, searchFn)"
                 />
                 <VnSelect
-                    v-else-if="selectedTag.id === 1"
+                    v-else-if="selectedTag === 1"
                     :label="t('params.value')"
                     v-model="value.value"
                     :options="tagOptions || []"
@@ -375,7 +358,7 @@ function addOrder(value, field, params) {
                     @new-value="createValue"
                     @update:model-value="applyTagFilter(params, searchFn)"
                 />
-                <QInput
+                <VnInput
                     v-else
                     :label="t('params.value')"
                     v-model="value.value"
@@ -396,7 +379,6 @@ function addOrder(value, field, params) {
                     icon="add_circle"
                     shortcut="+"
                     flat
-                    size="md"
                     class="filter-icon"
                     @click="tagValues.push({})"
                 />

From 1c8eabe2936e8a109a3580d3b3552b51d5f1712e Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 24 Oct 2024 00:39:35 +0200
Subject: [PATCH 075/207] perf: refs #7283 #7283 declare composable inst4ead
 code duplicated

---
 src/pages/Item/Card/ItemDescriptor.vue  | 34 +++-------------------
 src/pages/Item/ItemList.vue             | 34 +++-------------------
 src/pages/Item/composables/cloneItem.js | 38 +++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 60 deletions(-)
 create mode 100644 src/pages/Item/composables/cloneItem.js

diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index 635dd17c8..6fbc5a4bd 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -1,20 +1,18 @@
 <script setup>
 import { computed, ref, onMounted } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
+import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { useQuasar } from 'quasar';
 
 import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import VnConfirm from 'components/ui/VnConfirm.vue';
 import RegularizeStockForm from 'components/RegularizeStockForm.vue';
 import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
 import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
-import { getUrl } from 'src/composables/getUrl';
 import { dashIfEmpty } from 'src/filters';
 import { useArrayData } from 'src/composables/useArrayData';
+import { cloneItem } from 'src/pages/Item/composables/cloneItem';
 
 const $props = defineProps({
     id: {
@@ -40,9 +38,8 @@ const $props = defineProps({
     },
 });
 
-const quasar = useQuasar();
+const { openCloneDialog } = cloneItem();
 const route = useRoute();
-const router = useRouter();
 const { t } = useI18n();
 const warehouseConfig = ref(null);
 const entityId = computed(() => {
@@ -96,29 +93,6 @@ const updateStock = async () => {
 const openRegularizeStockForm = () => {
     regularizeStockFormDialog.value.show();
 };
-
-const cloneItem = async () => {
-    try {
-        const { data } = await axios.post(`Items/${entityId.value}/clone`);
-        router.push({ name: 'ItemTags', params: { id: data.id } });
-    } catch (err) {
-        console.error('Error cloning item');
-    }
-};
-
-const openCloneDialog = async () => {
-    quasar
-        .dialog({
-            component: VnConfirm,
-            componentProps: {
-                title: t('All its properties will be copied'),
-                message: t('Do you want to clone this item?'),
-            },
-        })
-        .onOk(async () => {
-            await cloneItem();
-        });
-};
 </script>
 
 <template>
@@ -144,7 +118,7 @@ const openCloneDialog = async () => {
                     </QDialog>
                 </QItemSection>
             </QItem>
-            <QItem v-ripple clickable @click="openCloneDialog()">
+            <QItem v-ripple clickable @click="openCloneDialog(entityId)">
                 <QItemSection>
                     {{ t('globals.clone') }}
                 </QItemSection>
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 92c9d188b..30b86bc11 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -1,27 +1,24 @@
 <script setup>
 import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRouter, useRoute } from 'vue-router';
+import { useRoute } from 'vue-router';
 import VnImg from 'src/components/ui/VnImg.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import { toDate } from 'src/filters';
-import axios from 'axios';
 import FetchedTags from 'src/components/ui/FetchedTags.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import ItemSummary from '../Item/Card/ItemSummary.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
-import VnConfirm from 'src/components/ui/VnConfirm.vue';
-import { useQuasar } from 'quasar';
-const entityId = computed(() => route.params.id);
+import { cloneItem } from 'src/pages/Item/composables/cloneItem';
 
+const entityId = computed(() => route.params.id);
+const { openCloneDialog } = cloneItem();
 const { viewSummary } = useSummaryDialog();
-const router = useRouter();
 const { t } = useI18n();
 const tableRef = ref();
 const route = useRoute();
-const quasar = useQuasar();
 
 const itemFilter = {
     include: [
@@ -297,29 +294,6 @@ const columns = computed(() => [
         ],
     },
 ]);
-
-const cloneItem = async () => {
-    try {
-        const { data } = await axios.post(`Items/${entityId.value}/clone`);
-        router.push({ name: 'ItemTags', params: { id: data.id } });
-    } catch (err) {
-        console.error('Error cloning item');
-    }
-};
-
-const openCloneDialog = async () => {
-    quasar
-        .dialog({
-            component: VnConfirm,
-            componentProps: {
-                title: t('All its properties will be copied'),
-                message: t('Do you want to clone this item?'),
-            },
-        })
-        .onOk(async () => {
-            await cloneItem();
-        });
-};
 </script>
 
 <template>
diff --git a/src/pages/Item/composables/cloneItem.js b/src/pages/Item/composables/cloneItem.js
new file mode 100644
index 000000000..f1114c779
--- /dev/null
+++ b/src/pages/Item/composables/cloneItem.js
@@ -0,0 +1,38 @@
+import axios from 'axios';
+import { computed, ref, onMounted } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import { useQuasar } from 'quasar';
+import VnConfirm from 'components/ui/VnConfirm.vue';
+
+export function cloneItem() {
+    const { t } = useI18n();
+
+    const quasar = useQuasar();
+    const route = useRoute();
+    const router = useRouter();
+    const cloneItem = async (entityId) => {
+        const { id } = entityId;
+        try {
+            const { data } = await axios.post(`Items/${id ?? entityId}/clone`);
+            router.push({ name: 'ItemTags', params: { id: data.id } });
+        } catch (err) {
+            console.error('Error cloning item');
+        }
+    };
+
+    const openCloneDialog = async (entityId) => {
+        quasar
+            .dialog({
+                component: VnConfirm,
+                componentProps: {
+                    title: t('All its properties will be copied'),
+                    message: t('Do you want to clone this item?'),
+                },
+            })
+            .onOk(async () => {
+                await cloneItem(entityId);
+            });
+    };
+    return { openCloneDialog };
+}

From 56ef811584970ae0c53f04f35604be941cd5a3ef Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 24 Oct 2024 07:47:26 +0200
Subject: [PATCH 076/207] fix: refs #7283 order translation

---
 src/pages/Item/ItemTypeList.vue |  4 +--
 src/router/modules/item.js      | 45 +++++++++++++++++----------------
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 9981a0d68..d9f7bba85 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -84,11 +84,11 @@ const columns = computed(() => [
         :url="`ItemTypes`"
         :create="{
             urlCreate: 'ItemTypes',
-            title: 'Create ItemTypes',
+            title: t('Create ItemTypes'),
             onDataSaved: () => tableRef.reload(),
             formInitialData: {},
         }"
-        order="code ASC"
+        order="name ASC"
         :columns="columns"
         auto-load
         :right-search="false"
diff --git a/src/router/modules/item.js b/src/router/modules/item.js
index 48e19dd54..2838c3be7 100644
--- a/src/router/modules/item.js
+++ b/src/router/modules/item.js
@@ -48,6 +48,28 @@ export default {
                     },
                     component: () => import('src/pages/Item/ItemList.vue'),
                 },
+                {
+                    path: 'request',
+                    name: 'ItemRequest',
+                    meta: {
+                        title: 'buyRequest',
+                        icon: 'vn:buyrequest',
+                    },
+                    component: () => import('src/pages/Item/ItemRequest.vue'),
+                },
+                {
+                    path: 'waste-breakdown',
+                    name: 'WasteBreakdown',
+                    meta: {
+                        title: 'wasteBreakdown',
+                        icon: 'vn:claims',
+                    },
+                    beforeEnter: (to, from, next) => {
+                        next({ name: 'ItemList' });
+                        window.location.href =
+                            'https://grafana.verdnatura.es/d/TTNXQAxVk';
+                    },
+                },
                 {
                     path: 'fixed-price',
                     name: 'ItemFixedPrice',
@@ -65,19 +87,7 @@ export default {
                     },
                     component: () => import('src/pages/Item/ItemCreate.vue'),
                 },
-                {
-                    path: 'waste-breakdown',
-                    name: 'WasteBreakdown',
-                    meta: {
-                        title: 'wasteBreakdown',
-                        icon: 'vn:claims',
-                    },
-                    beforeEnter: (to, from, next) => {
-                        next({ name: 'ItemList' });
-                        window.location.href =
-                            'https://grafana.verdnatura.es/d/TTNXQAxVk';
-                    },
-                },
+
                 {
                     path: 'item-type-list',
                     name: 'ItemTypeList',
@@ -95,15 +105,6 @@ export default {
                     },
                     component: () => import('src/pages/Item/ItemTypeCreate.vue'),
                 },
-                {
-                    path: 'request',
-                    name: 'ItemRequest',
-                    meta: {
-                        title: 'buyRequest',
-                        icon: 'vn:buyrequest',
-                    },
-                    component: () => import('src/pages/Item/ItemRequest.vue'),
-                },
             ],
         },
         {

From 87d2e0a39b1ee2d12e8468a0ca802168d32273f8 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 24 Oct 2024 10:36:48 +0200
Subject: [PATCH 077/207] perf: refs #7283 #7283 handle composable i18n

---
 src/i18n/locale/es.yml                  | 108 -----------------------
 src/pages/Item/Card/ItemDescriptor.vue  |   2 -
 src/pages/Item/ItemList.vue             |   2 -
 src/pages/Item/composables/cloneItem.js |   8 +-
 src/pages/Item/locale/en.yml            | 112 ++++++++++++++++++++++++
 src/pages/Item/locale/es.yml            | 112 ++++++++++++++++++++++++
 6 files changed, 227 insertions(+), 117 deletions(-)

diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 7c368b7b7..bd414a793 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -1053,114 +1053,6 @@ travel:
         warehouse: Almacén
         travelFileDescription: 'Id envío { travelId }'
         file: Fichero
-item:
-    searchbar:
-        label: Buscar artículo
-    descriptor:
-        item: Artículo
-        buyer: Comprador
-        color: Color
-        category: Categoría
-        stems: Tallos
-        visible: Visible
-        available: Disponible
-        warehouseText: 'Calculado sobre el almacén de { warehouseName }'
-        itemDiary: Registro de compra-venta
-        producer: Productor
-    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
-    basicData:
-        type: Tipo
-        reference: Referencia
-        relevancy: Relevancia
-        stems: Tallos
-        multiplier: Multiplicador
-        generic: Genérico
-        intrastat: Intrastat
-        expense: Gasto
-        weightByPiece: Peso (gramos)/tallo
-        boxUnits: Unidades/caja
-        recycledPlastic: Plastico reciclado
-        nonRecycledPlastic: Plático no reciclado
-        isActive: Activo
-        hasKgPrice: Precio en kg
-        isFragile: Frágil
-        isFragileTooltip: Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
-        isPhotoRequested: Hacer foto
-        isPhotoRequestedTooltip: Este artículo necesita una foto
-        description: Descripción
-    fixedPrice:
-        itemFk: ID Artículo
-        groupingPrice: Precio grouping
-        packingPrice: Precio packing
-        hasMinPrice: Tiene precio mínimo
-        minPrice: Precio min
-        started: Inicio
-        ended: Fin
-        warehouse: Almacén
-    create:
-        name: Nombre
-        tag: Etiqueta
-        priority: Prioridad
-        type: Tipo
-        intrastat: Intrastat
-        origin: Origen
-    summary:
-        basicData: 'Datos básicos'
-        otherData: 'Otros datos'
-        description: 'Descripción'
-        tax: 'IVA'
-        tags: 'Etiquetas'
-        botanical: 'Botánico'
-        barcode: 'Código de barras'
-        name: 'Nombre'
-        completeName: 'Nombre completo'
-        family: 'Familia'
-        size: 'Medida'
-        origin: 'Origen'
-        stems: 'Tallos'
-        multiplier: 'Multiplicador'
-        buyer: 'Comprador'
-        doPhoto: 'Hacer foto'
-        intrastatCode: 'Código intrastat'
-        intrastat: 'Intrastat'
-        ref: 'Referencia'
-        relevance: 'Relevancia'
-        weight: 'Peso (gramos)/tallo'
-        units: 'Unidades/caja'
-        expense: 'Gasto'
-        generic: 'Genérico'
-        recycledPlastic: 'Plástico reciclado'
-        nonRecycledPlastic: 'Plástico no reciclado'
-        minSalesQuantity: 'Cantidad mínima de venta'
-        genus: 'Genus'
-        specie: 'Specie'
-    buyRequest:
-        ticketId: 'ID Ticket'
-        shipped: 'F. envío'
-        requester: 'Solicitante'
-        requested: 'Solicitado'
-        price: 'Precio'
-        attender: 'Comprador'
-        item: 'Artículo'
-        achieved: 'Conseguido'
-        concept: 'Concepto'
-        state: 'Estado'
 components:
     topbar: {}
     itemsFilterPanel:
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index 6fbc5a4bd..243d4c7cb 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -195,8 +195,6 @@ const openRegularizeStockForm = () => {
 <i18n>
 es:
     Regularize stock: Regularizar stock
-    All its properties will be copied: Todas sus propiedades serán copiadas
-    Do you want to clone this item?: ¿Desea clonar este artículo?
     Inactive article: Artículo inactivo
 </i18n>
 
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 30b86bc11..cca5560fe 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -355,8 +355,6 @@ const columns = computed(() => [
 <i18n>
 es:
     New item: Nuevo artículo
-    All its properties will be copied: Todas sus propiedades serán copiadas
-    Do you want to clone this item?: ¿Desea clonar este artículo?
     Preview: Vista previa
     Regularize stock: Regularizar stock
 </i18n>
diff --git a/src/pages/Item/composables/cloneItem.js b/src/pages/Item/composables/cloneItem.js
index f1114c779..2421c0808 100644
--- a/src/pages/Item/composables/cloneItem.js
+++ b/src/pages/Item/composables/cloneItem.js
@@ -1,6 +1,5 @@
 import axios from 'axios';
-import { computed, ref, onMounted } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
+import { useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
 import VnConfirm from 'components/ui/VnConfirm.vue';
@@ -9,7 +8,6 @@ export function cloneItem() {
     const { t } = useI18n();
 
     const quasar = useQuasar();
-    const route = useRoute();
     const router = useRouter();
     const cloneItem = async (entityId) => {
         const { id } = entityId;
@@ -26,8 +24,8 @@ export function cloneItem() {
             .dialog({
                 component: VnConfirm,
                 componentProps: {
-                    title: t('All its properties will be copied'),
-                    message: t('Do you want to clone this item?'),
+                    title: t('item.descriptor.clone.title'),
+                    message: t('item.descriptor.clone.subTitle'),
                 },
             })
             .onOk(async () => {
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index c32ee493c..034e39a17 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -88,3 +88,115 @@ itemType:
         worker: Worker
         category: Category
         temperature: Temperature
+item:
+    searchbar:
+        label: Search item
+    descriptor:
+        item: Item
+        buyer: Buyer
+        color: Color
+        category: Category
+        stems: Stems
+        visible: Visible
+        available: Available
+        warehouseText: 'Calculated on the warehouse of { warehouseName }'
+        itemDiary: Item diary
+        producer: Producer
+        clone:
+            title: All its properties will be copied
+            subTitle: Do you want to clone this item?
+
+    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
+    basicData:
+        type: Type
+        reference: Reference
+        relevancy: Relevancy
+        stems: Stems
+        multiplier: Multiplier
+        generic: Generic
+        intrastat: Intrastat
+        expense: Expense
+        weightByPiece: Weight/Piece
+        boxUnits: Units/Box
+        recycledPlastic: Recycled Plastic
+        nonRecycledPlastic: Non recycled plastic
+        isActive: Active
+        hasKgPrice: Price in kg
+        isFragile: Fragile
+        isFragileTooltip: Is shown at website, app that this item cannot travel (wreath, palms, ...)
+        isPhotoRequested: Do photo
+        isPhotoRequestedTooltip: This item does need a photo
+        description: Description
+    fixedPrice:
+        itemFk: Item ID
+        groupingPrice: Grouping price
+        packingPrice: Packing price
+        hasMinPrice: Has min price
+        minPrice: Min price
+        started: Started
+        ended: Ended
+        warehouse: Warehouse
+    create:
+        name: Name
+        tag: Tag
+        priority: Priority
+        type: Type
+        intrastat: Intrastat
+        origin: Origin
+    buyRequest:
+        ticketId: 'Ticket ID'
+        shipped: 'Shipped'
+        requester: 'Requester'
+        requested: 'Requested'
+        price: 'Price'
+        attender: 'Attender'
+        item: 'Item'
+        achieved: 'Achieved'
+        concept: 'Concept'
+        state: 'State'
+    summary:
+        basicData: 'Basic data'
+        otherData: 'Other data'
+        description: 'Description'
+        tax: 'Tax'
+        tags: 'Tags'
+        botanical: 'Botanical'
+        barcode: 'Barcode'
+        name: 'Nombre'
+        completeName: 'Nombre completo'
+        family: 'Familia'
+        size: 'Medida'
+        origin: 'Origen'
+        stems: 'Tallos'
+        multiplier: 'Multiplicador'
+        buyer: 'Comprador'
+        doPhoto: 'Do photo'
+        intrastatCode: 'Código intrastat'
+        intrastat: 'Intrastat'
+        ref: 'Referencia'
+        relevance: 'Relevancia'
+        weight: 'Peso (gramos)/tallo'
+        units: 'Unidades/caja'
+        expense: 'Gasto'
+        generic: 'Genérico'
+        recycledPlastic: 'Plástico reciclado'
+        nonRecycledPlastic: 'Plástico no reciclado'
+        minSalesQuantity: 'Cantidad mínima de venta'
+        genus: 'Genus'
+        specie: 'Specie'
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index d32cb7885..917bd7e5f 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -88,3 +88,115 @@ itemType:
         worker: Trabajador
         category: Reino
         temperature: Temperatura
+item:
+    searchbar:
+        label: Buscar artículo
+    descriptor:
+        item: Artículo
+        buyer: Comprador
+        color: Color
+        category: Categoría
+        stems: Tallos
+        visible: Visible
+        available: Disponible
+        warehouseText: 'Calculado sobre el almacén de { warehouseName }'
+        itemDiary: Registro de compra-venta
+        producer: Productor
+        clone:
+            title: Todas sus propiedades serán copiadas
+            subTitle: ¿Desea clonar este artículo?
+
+    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
+    basicData:
+        type: Tipo
+        reference: Referencia
+        relevancy: Relevancia
+        stems: Tallos
+        multiplier: Multiplicador
+        generic: Genérico
+        intrastat: Intrastat
+        expense: Gasto
+        weightByPiece: Peso (gramos)/tallo
+        boxUnits: Unidades/caja
+        recycledPlastic: Plastico reciclado
+        nonRecycledPlastic: Plático no reciclado
+        isActive: Activo
+        hasKgPrice: Precio en kg
+        isFragile: Frágil
+        isFragileTooltip: Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
+        isPhotoRequested: Hacer foto
+        isPhotoRequestedTooltip: Este artículo necesita una foto
+        description: Descripción
+    fixedPrice:
+        itemFk: ID Artículo
+        groupingPrice: Precio grouping
+        packingPrice: Precio packing
+        hasMinPrice: Tiene precio mínimo
+        minPrice: Precio min
+        started: Inicio
+        ended: Fin
+        warehouse: Almacén
+    create:
+        name: Nombre
+        tag: Etiqueta
+        priority: Prioridad
+        type: Tipo
+        intrastat: Intrastat
+        origin: Origen
+    summary:
+        basicData: 'Datos básicos'
+        otherData: 'Otros datos'
+        description: 'Descripción'
+        tax: 'IVA'
+        tags: 'Etiquetas'
+        botanical: 'Botánico'
+        barcode: 'Código de barras'
+        name: 'Nombre'
+        completeName: 'Nombre completo'
+        family: 'Familia'
+        size: 'Medida'
+        origin: 'Origen'
+        stems: 'Tallos'
+        multiplier: 'Multiplicador'
+        buyer: 'Comprador'
+        doPhoto: 'Hacer foto'
+        intrastatCode: 'Código intrastat'
+        intrastat: 'Intrastat'
+        ref: 'Referencia'
+        relevance: 'Relevancia'
+        weight: 'Peso (gramos)/tallo'
+        units: 'Unidades/caja'
+        expense: 'Gasto'
+        generic: 'Genérico'
+        recycledPlastic: 'Plástico reciclado'
+        nonRecycledPlastic: 'Plástico no reciclado'
+        minSalesQuantity: 'Cantidad mínima de venta'
+        genus: 'Genus'
+        specie: 'Specie'
+    buyRequest:
+        ticketId: 'ID Ticket'
+        shipped: 'F. envío'
+        requester: 'Solicitante'
+        requested: 'Solicitado'
+        price: 'Precio'
+        attender: 'Comprador'
+        item: 'Artículo'
+        achieved: 'Conseguido'
+        concept: 'Concepto'
+        state: 'Estado'

From 2d8789312b41049ae833bc9f05320af1256e3af8 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 24 Oct 2024 11:34:55 +0200
Subject: [PATCH 078/207] test: refs #6943 #6943 remove skip tests

---
 .../integration/client/clientList.spec.js      | 17 -----------------
 test/cypress/support/commands.js               | 18 ------------------
 2 files changed, 35 deletions(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 1b41e55cd..f150fc190 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -43,21 +43,4 @@ describe('Client list', () => {
             cy.url().should('include', `/customer/${id}/summary`);
         });
     });
-
-    it.skip('Client founded create ticket', () => {
-        const search = 'Jessica Jones';
-        cy.searchByLabel('Name', search);
-        cy.clickButtonsDescriptor(2);
-        cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form');
-        cy.checkValueSelectForm(1, search);
-    });
-    it.skip('Client founded create order', () => {
-        const search = 'Jessica Jones';
-        cy.searchByLabel('Name', search);
-        cy.clickButtonsDescriptor(3);
-        cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form');
-        cy.checkValueForm(2, search);
-    });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 9106a64cd..33dfa85df 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -262,12 +262,6 @@ Cypress.Commands.add('openUserPanel', () => {
     ).click();
 });
 
-Cypress.Commands.add('clickButtonsDescriptor', (id) => {
-    cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
-        .invoke('removeAttr', 'target')
-        .click();
-});
-
 Cypress.Commands.add('openActions', (row) => {
     cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
 });
@@ -281,18 +275,6 @@ Cypress.Commands.add('checkNotification', (type) => {
     cy.get('.q-notification__message').should('have.text', values[type]);
 });
 
-Cypress.Commands.add('checkValueForm', (id, search) => {
-    cy.get(
-        `.grid-create > :nth-child(${id}) > .q-field__inner>.q-field__control> .q-field__control-container>.q-field__native >.q-field__input`
-    ).should('have.value', search);
-});
-
-Cypress.Commands.add('checkValueSelectForm', (id, search) => {
-    cy.get(
-        `.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container>.q-field__native>.q-field__input`
-    ).should('have.value', search);
-});
-
 Cypress.Commands.add('searchByLabel', (label, value) => {
     cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
 });

From 3f640c650b12152f3a086464d3b0140a5bc6198d Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 24 Oct 2024 12:32:15 +0200
Subject: [PATCH 079/207] perf: refs #7283 #7283 handle i18n

---
 src/i18n/locale/en.yml       | 108 -----------------------------------
 src/pages/Item/locale/en.yml |   1 -
 src/pages/Item/locale/es.yml |   1 -
 3 files changed, 110 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index b19363c12..c1748c8ff 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -1055,114 +1055,6 @@ travel:
         warehouse: Warehouse
         travelFileDescription: 'Travel id { travelId }'
         file: File
-item:
-    searchbar:
-        label: Search item
-    descriptor:
-        item: Item
-        buyer: Buyer
-        color: Color
-        category: Category
-        stems: Stems
-        visible: Visible
-        available: Available
-        warehouseText: 'Calculated on the warehouse of { warehouseName }'
-        itemDiary: Item diary
-        producer: Producer
-    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
-    basicData:
-        type: Type
-        reference: Reference
-        relevancy: Relevancy
-        stems: Stems
-        multiplier: Multiplier
-        generic: Generic
-        intrastat: Intrastat
-        expense: Expense
-        weightByPiece: Weight/Piece
-        boxUnits: Units/Box
-        recycledPlastic: Recycled Plastic
-        nonRecycledPlastic: Non recycled plastic
-        isActive: Active
-        hasKgPrice: Price in kg
-        isFragile: Fragile
-        isFragileTooltip: Is shown at website, app that this item cannot travel (wreath, palms, ...)
-        isPhotoRequested: Do photo
-        isPhotoRequestedTooltip: This item does need a photo
-        description: Description
-    fixedPrice:
-        itemFk: Item ID
-        groupingPrice: Grouping price
-        packingPrice: Packing price
-        hasMinPrice: Has min price
-        minPrice: Min price
-        started: Started
-        ended: Ended
-        warehouse: Warehouse
-    create:
-        name: Name
-        tag: Tag
-        priority: Priority
-        type: Type
-        intrastat: Intrastat
-        origin: Origin
-    buyRequest:
-        ticketId: 'Ticket ID'
-        shipped: 'Shipped'
-        requester: 'Requester'
-        requested: 'Requested'
-        price: 'Price'
-        attender: 'Attender'
-        item: 'Item'
-        achieved: 'Achieved'
-        concept: 'Concept'
-        state: 'State'
-    summary:
-        basicData: 'Basic data'
-        otherData: 'Other data'
-        description: 'Description'
-        tax: 'Tax'
-        tags: 'Tags'
-        botanical: 'Botanical'
-        barcode: 'Barcode'
-        name: 'Nombre'
-        completeName: 'Nombre completo'
-        family: 'Familia'
-        size: 'Medida'
-        origin: 'Origen'
-        stems: 'Tallos'
-        multiplier: 'Multiplicador'
-        buyer: 'Comprador'
-        doPhoto: 'Do photo'
-        intrastatCode: 'Código intrastat'
-        intrastat: 'Intrastat'
-        ref: 'Referencia'
-        relevance: 'Relevancia'
-        weight: 'Peso (gramos)/tallo'
-        units: 'Unidades/caja'
-        expense: 'Gasto'
-        generic: 'Genérico'
-        recycledPlastic: 'Plástico reciclado'
-        nonRecycledPlastic: 'Plástico no reciclado'
-        minSalesQuantity: 'Cantidad mínima de venta'
-        genus: 'Genus'
-        specie: 'Specie'
 components:
     topbar: {}
     itemsFilterPanel:
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index 034e39a17..53310cbd0 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -105,7 +105,6 @@ item:
         clone:
             title: All its properties will be copied
             subTitle: Do you want to clone this item?
-
     list:
         id: Identifier
         grouping: Grouping
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index 917bd7e5f..1ade9b955 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -105,7 +105,6 @@ item:
         clone:
             title: Todas sus propiedades serán copiadas
             subTitle: ¿Desea clonar este artículo?
-
     list:
         id: Identificador
         grouping: Grouping

From 64f36c7d4b7a8210df9af7e087660094c0a28c2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= <carlosap@verdnatura.es>
Date: Thu, 24 Oct 2024 12:35:11 +0200
Subject: [PATCH 080/207] feat: refs #8087 Traspasar redadas a travels

---
 src/i18n/locale/en.yml                    | 5 +----
 src/i18n/locale/es.yml                    | 5 +----
 src/pages/Entry/Card/EntryBasicData.vue   | 6 ------
 src/pages/Entry/Card/EntryDescriptor.vue  | 4 ++--
 src/pages/Entry/Card/EntrySummary.vue     | 5 -----
 src/pages/Entry/EntryList.vue             | 4 ++--
 src/pages/Travel/Card/TravelBasicData.vue | 4 ++++
 src/pages/Travel/Card/TravelSummary.vue   | 4 ++++
 8 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index aa8df17e2..d1ea5ceb9 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -106,6 +106,7 @@ globals:
     weight: Weight
     error: Ups! Something went wrong
     recalc: Recalculate
+    daysInForward: Forward days
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -369,7 +370,6 @@ entry:
             companyFk: Company
             travelFk: Travel
             isExcludedFromAvailable: Inventory
-            isRaid: Raid
             invoiceAmount: Import
     summary:
         commission: Commission
@@ -380,7 +380,6 @@ entry:
         ordered: Ordered
         confirmed: Confirmed
         booked: Booked
-        raid: Raid
         excludedFromAvailable: Inventory
         travelReference: Reference
         travelAgency: Agency
@@ -413,7 +412,6 @@ entry:
         ordered: Ordered
         confirmed: Confirmed
         booked: Booked
-        raid: Raid
         excludedFromAvailable: Inventory
         agency: Agency
         warehouseOut: Warehouse Out
@@ -476,7 +474,6 @@ entry:
             packingOut: Package out
             landing: Landing
             isExcludedFromAvailable: Es inventory
-            isRaid: Raid
 ticket:
     pageTitles:
         tickets: Tickets
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 575e2c6c7..18e580893 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -108,6 +108,7 @@ globals:
     weight: Peso
     error: ¡Ups! Algo salió mal
     recalc: Recalcular
+    daysInForward: Días en el futuro
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -371,7 +372,6 @@ entry:
             companyFk: Empresa
             travelFk: Envio
             isExcludedFromAvailable: Inventario
-            isRaid: Redada
             invoiceAmount: Importe
     summary:
         commission: Comisión
@@ -382,7 +382,6 @@ entry:
         ordered: Pedida
         confirmed: Confirmada
         booked: Contabilizada
-        raid: Redada
         excludedFromAvailable: Inventario
         travelReference: Referencia
         travelAgency: Agencia
@@ -415,7 +414,6 @@ entry:
         ordered: Pedida
         confirmed: Confirmado
         booked: Asentado
-        raid: Redada
         excludedFromAvailable: Inventario
         agency: Agencia
         warehouseOut: Alm. salida
@@ -478,7 +476,6 @@ entry:
             packingOut: Embalaje envíos
             landing: Llegada
             isExcludedFromAvailable: Es inventario
-            isRaid: Redada
 ticket:
     pageTitles:
         tickets: Tickets
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index b81b1db22..d60ed8645 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -168,12 +168,6 @@ const onFilterTravelSelected = (formData, id) => {
                     v-model="data.isExcludedFromAvailable"
                     :label="t('entry.basicData.excludedFromAvailable')"
                 />
-                <QCheckbox v-model="data.isRaid" :label="t('entry.basicData.raid')" />
-                <QCheckbox
-                    v-if="isAdministrative()"
-                    v-model="data.isBooked"
-                    :label="t('entry.basicData.booked')"
-                />
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index b22d6ba53..d85e5e1a0 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -32,7 +32,6 @@ const entryFilter = {
         {
             relation: 'travel',
             scope: {
-                fields: ['id', 'landed', 'shipped', 'agencyModeFk', 'warehouseOutFk'],
                 include: [
                     {
                         relation: 'agency',
@@ -143,8 +142,9 @@ watch;
                 >
                     <QTooltip>{{ t('Inventory entry') }}</QTooltip>
                 </QIcon>
+                {{ console.log('currentEntry', currentEntry) }}
                 <QIcon
-                    v-if="currentEntry?.isRaid"
+                    v-if="currentEntry?.travel?.daysInForward"
                     name="vn:net"
                     color="primary"
                     size="xs"
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index c2f1e6b57..62e13551a 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -259,11 +259,6 @@ const fetchEntryBuys = async () => {
                     v-model="entry.isBooked"
                     :disable="true"
                 />
-                <QCheckbox
-                    :label="t('entry.summary.raid')"
-                    v-model="entry.isRaid"
-                    :disable="true"
-                />
                 <QCheckbox
                     :label="t('entry.summary.excludedFromAvailable')"
                     v-model="entry.isExcludedFromAvailable"
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 6f7ff1935..00b6c8626 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -168,8 +168,8 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isRaid'),
-        name: 'isRaid',
+        label: t('entry.list.tableVisibleColumns.daysInForward'),
+        name: 'daysInForward',
         chip: {
             color: null,
             condition: (value) => value,
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index a3620a6ba..aaf8abb91 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -72,6 +72,10 @@ const agenciesOptions = ref([]);
             </VnRow>
             <VnRow>
                 <VnInput v-model="data.m3" label="m3" />
+                <VnInput
+                    :label="t('globals.daysInForward')"
+                    v-model="data.daysInForward"
+                />
             </VnRow>
             <VnRow>
                 <QCheckbox
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 4be198493..59059b0db 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -303,6 +303,10 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 <VnLv :label="t('globals.reference')" :value="travel.ref" />
                 <VnLv label="m³" :value="travel.m3" />
                 <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
+                <VnLv
+                    :label="t('globals.daysInForward')"
+                    :value="travel?.daysInForward"
+                />
             </QCard>
             <QCard class="full-width">
                 <VnTitle :text="t('travel.summary.entries')" />

From 671d9fd6fb0f6686ade7b54bfe9e36b6d8a11a8c Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 24 Oct 2024 13:38:13 +0200
Subject: [PATCH 081/207] fix: refs #7283 itemtype fix

---
 src/pages/Item/ItemTypeList.vue | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index d9f7bba85..2c1153016 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -1,14 +1,14 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
-import { useRoute } from 'vue-router';
 import { ref, computed } from 'vue';
 import ItemTypeSearchbar from '../ItemType/ItemTypeSearchbar.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
+import FetchData from 'components/FetchData.vue';
 
-const route = useRoute();
 const { t } = useI18n();
 const tableRef = ref();
-const entityId = computed(() => route.params.id);
+const workerOptions = ref([]);
+const ItemCategoriesOptions = ref([]);
 
 const columns = computed(() => [
     {
@@ -40,7 +40,7 @@ const columns = computed(() => [
         create: true,
         component: 'select',
         attrs: {
-            url: 'Workers',
+            options: workerOptions.value,
             optionLabel: 'firstName',
             optionValue: 'id',
         },
@@ -54,8 +54,9 @@ const columns = computed(() => [
         create: true,
         component: 'select',
         attrs: {
-            url: 'ItemCategories',
+            options: ItemCategoriesOptions.value,
             fields: ['id', 'name'],
+            order: 'name ASC',
         },
         cardVisible: false,
         visible: false,
@@ -77,6 +78,18 @@ const columns = computed(() => [
 </script>
 
 <template>
+    <FetchData
+        url="Workers"
+        :filter="{ fields: ['id', 'firstName'], order: ['firstName ASC'] }"
+        @on-fetch="(data) => (workerOptions = data)"
+        auto-load
+    />
+    <FetchData
+        url="ItemCategories"
+        :filter="{ fields: ['id', 'name'], order: ['name ASC'] }"
+        @on-fetch="(data) => (ItemCategoriesOptions = data)"
+        auto-load
+    />
     <ItemTypeSearchbar />
     <VnTable
         ref="tableRef"
@@ -102,8 +115,8 @@ const columns = computed(() => [
         id: Id
         code: Código
         name: Nombre
-        worker: Encargado
-        ItemCategory: Categoría
+        worker: Trabajador
+        ItemCategory: Reino
         Temperature: Temperatura
         Create ItemTypes: Crear familia
     en:

From c2043902f8f77a6f4957b82d7f7576f540bf8f1e Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Thu, 24 Oct 2024 14:08:11 +0200
Subject: [PATCH 082/207] fix: refs #7283 fix required

---
 src/pages/Item/ItemRequestDenyForm.vue | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pages/Item/ItemRequestDenyForm.vue b/src/pages/Item/ItemRequestDenyForm.vue
index be70fb799..c9a4cbe9c 100644
--- a/src/pages/Item/ItemRequestDenyForm.vue
+++ b/src/pages/Item/ItemRequestDenyForm.vue
@@ -10,6 +10,7 @@ defineProps({
     requestId: {
         type: Number,
         default: null,
+        required: true,
     },
 });
 
@@ -43,6 +44,7 @@ onMounted(async () => {
                         type="textarea"
                         v-model="data.observation"
                         fill-input
+                        :required="true"
                         autogrow
                     />
                 </div>

From 855979d22d3397182210a661717880e7bb04ab2d Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 24 Oct 2024 14:59:14 +0200
Subject: [PATCH 083/207] perf: refs #7283 #7283 i18n params

---
 src/pages/Item/ItemRequest.vue |  1 +
 src/pages/Item/locale/en.yml   | 13 +++++++++++++
 src/pages/Item/locale/es.yml   | 15 +++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index ea265e706..450031a0e 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -225,6 +225,7 @@ onMounted(async () => {
         :is-editable="true"
         auto-load
         :disable-option="{ card: true }"
+        chip-locale="item.params"
     >
         <template #column-ticketFk="{ row }">
             <span class="link">
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index 53310cbd0..e99853760 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -89,6 +89,19 @@ itemType:
         category: Category
         temperature: Temperature
 item:
+    params:
+        daysOnward: Days onward
+        search: General search
+        ticketFk: Ticket id
+        attenderFk: Atender
+        clientFk: Client id
+        warehouseFk: Warehouse
+        requesterFk: Salesperson
+        from: From
+        to: To
+        mine: For me
+        state: State
+        myTeam: My team
     searchbar:
         label: Search item
     descriptor:
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index 1ade9b955..56c6ec317 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -88,7 +88,22 @@ itemType:
         worker: Trabajador
         category: Reino
         temperature: Temperatura
+params:
+    state: asfsdf
 item:
+    params:
+        daysOnward: Días adelante
+        search: Búsqueda general
+        ticketFk: Id ticket
+        attenderFk: Comprador
+        clientFk: Id cliente
+        warehouseFk: Almacén
+        requesterFk: Comercial
+        from: Desde
+        to: Hasta
+        mine: Para mi
+        state: Estado
+        myTeam: Mi equipo
     searchbar:
         label: Buscar artículo
     descriptor:

From 92e147355fea8b083948f544daf608fc8db8734c Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 24 Oct 2024 15:13:05 +0200
Subject: [PATCH 084/207] fix: better performance

---
 src/components/VnTable/VnTable.vue  |  7 ++++---
 src/pages/Account/AccountAcls.vue   | 28 +++++++++++++++++++++++++---
 src/pages/Account/AccountFilter.vue |  1 +
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 908157610..c1680bf13 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -151,8 +151,8 @@ const tableModes = [
     },
 ];
 onBeforeMount(() => {
-    setUserParams(route.query[$props.searchUrl]);
-    hasParams.value = params.value && Object.keys(params.value).length !== 0;
+    const urlParams = route.query[$props.searchUrl];
+    hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
 });
 
 onMounted(() => {
@@ -185,7 +185,8 @@ watch(
 
 watch(
     () => route.query[$props.searchUrl],
-    (val) => setUserParams(val)
+    (val) => setUserParams(val),
+    { immediate: true, deep: true }
 );
 
 const isTableMode = computed(() => mode.value == TABLE_MODE);
diff --git a/src/pages/Account/AccountAcls.vue b/src/pages/Account/AccountAcls.vue
index dd93a0cb5..63cdac9c7 100644
--- a/src/pages/Account/AccountAcls.vue
+++ b/src/pages/Account/AccountAcls.vue
@@ -9,6 +9,8 @@ import { useQuasar } from 'quasar';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnSearchbar from 'components/ui/VnSearchbar.vue';
 import VnConfirm from 'components/ui/VnConfirm.vue';
+import FetchData from 'src/components/FetchData.vue';
+import { useValidator } from 'src/composables/useValidator';
 
 defineProps({
     id: {
@@ -23,11 +25,18 @@ const stateStore = useStateStore();
 const quasar = useQuasar();
 
 const tableRef = ref();
-
+const roles = ref();
+const validationsStore = useValidator();
+const { models } = validationsStore;
 const exprBuilder = (param, value) => {
     switch (param) {
         case 'search':
-            return { model: { like: `%${value}%` } };
+            return {
+                or: [
+                    { model: { like: `%${value}%` } },
+                    { property: { like: `%${value}%` } },
+                ],
+            };
         default:
             return { [param]: value };
     }
@@ -47,6 +56,13 @@ const columns = computed(() => [
         label: t('model'),
         cardVisible: true,
         create: true,
+        columnCreate: {
+            label: t('model'),
+            component: 'select',
+            attrs: {
+                options: Object.keys(models),
+            },
+        },
     },
     {
         align: 'left',
@@ -55,9 +71,10 @@ const columns = computed(() => [
         cardVisible: true,
         component: 'select',
         attrs: {
-            url: 'VnRoles',
+            options: roles,
             optionLabel: 'name',
             optionValue: 'name',
+            inputDebounce: 0,
         },
         create: true,
     },
@@ -130,6 +147,11 @@ const deleteAcl = async ({ id }) => {
     />
     <QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
     </QDrawer>
+    <FetchData
+        url="VnRoles?fields=['name']"
+        auto-load
+        @on-fetch="(data) => (roles = data)"
+    />
     <VnTable
         ref="tableRef"
         data-key="AccountAcls"
diff --git a/src/pages/Account/AccountFilter.vue b/src/pages/Account/AccountFilter.vue
index 1775aa06b..3c8378d93 100644
--- a/src/pages/Account/AccountFilter.vue
+++ b/src/pages/Account/AccountFilter.vue
@@ -33,6 +33,7 @@ const rolesOptions = ref([]);
         :search-button="true"
         :hidden-tags="['search']"
         :redirect="false"
+        search-url="table"
     >
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">

From 12c236276d1d321ae657a2a005630df210917af6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= <carlosap@verdnatura.es>
Date: Thu, 24 Oct 2024 19:32:20 +0200
Subject: [PATCH 085/207] feat: refs #8087 Traspasar redadas a travels

---
 src/i18n/locale/en.yml                     |  3 +-
 src/i18n/locale/es.yml                     |  3 +-
 src/pages/Entry/Card/EntryDescriptor.vue   | 19 +++++-----
 src/pages/Entry/EntryList.vue              | 43 ++++++++++++----------
 src/pages/Entry/locale/en.yml              |  1 -
 src/pages/Entry/locale/es.yml              |  1 -
 src/pages/Travel/Card/TravelBasicData.vue  | 17 ++++++++-
 src/pages/Travel/Card/TravelDescriptor.vue | 17 +++++++++
 src/pages/Travel/Card/TravelSummary.vue    |  2 +-
 src/pages/Travel/TravelList.vue            | 15 ++++++++
 10 files changed, 86 insertions(+), 35 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index d1ea5ceb9..928553293 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -106,7 +106,6 @@ globals:
     weight: Weight
     error: Ups! Something went wrong
     recalc: Recalculate
-    daysInForward: Forward days
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -313,6 +312,7 @@ globals:
     changePass: Change password
     deleteConfirmTitle: Delete selected elements
     changeState: Change state
+    raid: 'Raid {daysInForward} days'
 errors:
     statusUnauthorized: Access denied
     statusInternalServerError: An internal server error has ocurred
@@ -1039,6 +1039,7 @@ travel:
         warehouseIn: Warehouse In
         delivered: Delivered
         received: Received
+        daysInForward: Days in forward
     thermographs:
         code: Code
         temperature: Temperature
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 18e580893..52bc821d1 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -108,7 +108,6 @@ globals:
     weight: Peso
     error: ¡Ups! Algo salió mal
     recalc: Recalcular
-    daysInForward: Días en el futuro
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -317,6 +316,7 @@ globals:
     changePass: Cambiar contraseña
     deleteConfirmTitle: Eliminar los elementos seleccionados
     changeState: Cambiar estado
+    raid: 'Redada {daysInForward} días'
 errors:
     statusUnauthorized: Acceso denegado
     statusInternalServerError: Ha ocurrido un error interno del servidor
@@ -1037,6 +1037,7 @@ travel:
         warehouseIn: Alm. entrada
         delivered: Enviada
         received: Recibida
+        daysInForward: Días redada
     thermographs:
         code: Código
         temperature: Temperatura
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index d85e5e1a0..bbfc73138 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -7,7 +7,6 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import useCardDescription from 'src/composables/useCardDescription';
 
-import { useState } from 'src/composables/useState';
 import { toDate } from 'src/filters';
 import { usePrintService } from 'composables/usePrintService';
 import { getUrl } from 'src/composables/getUrl';
@@ -23,7 +22,6 @@ const $props = defineProps({
 const route = useRoute();
 const { t } = useI18n();
 const { openReport } = usePrintService();
-const state = useState();
 const entryDescriptorRef = ref(null);
 const url = ref();
 
@@ -74,8 +72,6 @@ const data = ref(useCardDescription());
 const setData = (entity) =>
     (data.value = useCardDescription(entity.supplier?.nickname, entity.id));
 
-const currentEntry = computed(() => state.get('entry'));
-
 const getEntryRedirectionFilter = (entry) => {
     let entryTravel = entry && entry.travel;
 
@@ -132,24 +128,29 @@ watch;
                 :value="entity.travel?.warehouseOut?.name"
             />
         </template>
-        <template #icons>
+        <template #icons="{ entity }">
             <QCardActions class="q-gutter-x-md">
                 <QIcon
-                    v-if="currentEntry?.isExcludedFromAvailable"
+                    v-if="entity?.isExcludedFromAvailable"
                     name="vn:inventory"
                     color="primary"
                     size="xs"
                 >
                     <QTooltip>{{ t('Inventory entry') }}</QTooltip>
                 </QIcon>
-                {{ console.log('currentEntry', currentEntry) }}
                 <QIcon
-                    v-if="currentEntry?.travel?.daysInForward"
+                    v-if="entity?.travel?.daysInForward"
                     name="vn:net"
                     color="primary"
                     size="xs"
                 >
-                    <QTooltip>{{ t('Virtual entry') }}</QTooltip>
+                    <QTooltip>
+                        {{
+                            t('globals.raid', {
+                                daysInForward: entity?.travel?.daysInForward,
+                            })
+                        }}</QTooltip
+                    >
                 </QIcon>
             </QCardActions>
         </template>
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 00b6c8626..518d72d82 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -41,6 +41,10 @@ const entryFilter = {
 };
 
 const columns = computed(() => [
+    {
+        name: 'status',
+        hidden: true,
+    },
     {
         align: 'left',
         label: t('entry.list.tableVisibleColumns.id'),
@@ -154,27 +158,8 @@ const columns = computed(() => [
         cardVisible: true,
     },
     {
-        align: 'left',
         label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
         name: 'isExcludedFromAvailable',
-        chip: {
-            color: null,
-            condition: (value) => value,
-            icon: 'vn:inventory',
-        },
-        columnFilter: {
-            inWhere: true,
-        },
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.daysInForward'),
-        name: 'daysInForward',
-        chip: {
-            color: null,
-            condition: (value) => value,
-            icon: 'vn:net',
-        },
         columnFilter: {
             inWhere: true,
         },
@@ -225,6 +210,26 @@ onMounted(async () => {
         auto-load
         :right-search="false"
     >
+        <template #column-status="{ row }">
+            <div class="row q-gutter-xs">
+                <QIcon
+                    v-if="!!row.isExcludedFromAvailable"
+                    name="vn:inventory"
+                    color="primary"
+                >
+                    <QTooltip>{{
+                        t('entry.list.tableVisibleColumns.isExcludedFromAvailable')
+                    }}</QTooltip>
+                </QIcon>
+                <QIcon v-if="!!row.daysInForward" name="vn:net" color="primary">
+                    <QTooltip>
+                        {{
+                            t('globals.raid', { daysInForward: row.daysInForward })
+                        }}</QTooltip
+                    >
+                </QIcon>
+            </div>
+        </template>
         <template #column-supplierFk="{ row }">
             <span class="link" @click.stop>
                 {{ row.supplierName }}
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index f9dbd0589..cd5113d84 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -1,7 +1,6 @@
 entryList:
     list:
         inventoryEntry: Inventory entry
-        virtualEntry: Virtual entry
 entryFilter:
     filter:
         search: General search
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index feeea1fc9..3007c5d44 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -4,7 +4,6 @@ You can search by entry reference: Puedes buscar por referencia de la entrada
 entryList:
     list:
         inventoryEntry: Es inventario
-        virtualEntry: Es una redada
 entryFilter:
     filter:
         search: Búsqueda general
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index aaf8abb91..d6245e655 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -73,9 +73,15 @@ const agenciesOptions = ref([]);
             <VnRow>
                 <VnInput v-model="data.m3" label="m3" />
                 <VnInput
-                    :label="t('globals.daysInForward')"
+                    :label="t('travel.basicData.daysInForward')"
                     v-model="data.daysInForward"
-                />
+                >
+                    <template #append>
+                        <QIcon name="info" class="cursor-info">
+                            <QTooltip>{{ t('raidDays') }}</QTooltip>
+                        </QIcon>
+                    </template>
+                </VnInput>
             </VnRow>
             <VnRow>
                 <QCheckbox
@@ -90,3 +96,10 @@ const agenciesOptions = ref([]);
         </template>
     </FormModel>
 </template>
+
+<i18n>
+es:
+    raidDays: Al rellenarlo, generamos una redada. Indica los días que un travel se moverá automáticamente en el tiempo
+en:
+    raidDays: When filling, a raid is generated. Enter the number of days the travel will automatically forward in time
+</i18n>
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index bda29903b..6025ad045 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -32,6 +32,7 @@ const filter = {
         'warehouseOutFk',
         'cargoSupplierFk',
         'agencyModeFk',
+        'daysInForward',
     ],
     include: [
         {
@@ -77,6 +78,22 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
             <VnLv :label="t('globals.landed')" :value="toDate(entity.landed)" />
             <VnLv :label="t('globals.totalEntries')" :value="entity.totalEntries" />
         </template>
+        <template #icons="{ entity }">
+            <QCardActions class="q-gutter-x-md">
+                <QIcon
+                    v-if="entity.daysInForward"
+                    name="vn:net"
+                    color="primary"
+                    size="xs"
+                >
+                    <QTooltip>
+                        {{
+                            t('globals.raid', { daysInForward: entity.daysInForward })
+                        }}</QTooltip
+                    >
+                </QIcon>
+            </QCardActions>
+        </template>
         <template #actions="{ entity }">
             <QCardActions>
                 <QBtn
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 59059b0db..7dc267671 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -304,7 +304,7 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 <VnLv label="m³" :value="travel.m3" />
                 <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
                 <VnLv
-                    :label="t('globals.daysInForward')"
+                    :label="t('travel.basicData.daysInForward')"
                     :value="travel?.daysInForward"
                 />
             </QCard>
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index a8c0e69cb..199746bb7 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -45,6 +45,10 @@ const redirectCreateEntryView = (travelData) => {
 };
 
 const columns = computed(() => [
+    {
+        name: 'status',
+        hidden: true,
+    },
     {
         align: 'left',
         name: 'id',
@@ -221,6 +225,17 @@ const columns = computed(() => [
         :is-editable="false"
         :use-model="true"
     >
+        <template #column-status="{ row }">
+            <div class="row">
+                <QIcon v-if="!!row.daysInForward" name="vn:net" color="primary">
+                    <QTooltip>
+                        {{
+                            t('globals.raid', { daysInForward: row.daysInForward })
+                        }}</QTooltip
+                    >
+                </QIcon>
+            </div>
+        </template>
         <template #column-shipped="{ row }">
             <QBadge
                 text-color="black"

From e8d2a40dafbc8ccec24957715bf6cfea82e4bc25 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Fri, 25 Oct 2024 08:11:31 +0200
Subject: [PATCH 086/207] fix: entryFilters

---
 src/pages/Entry/EntryLatestBuys.vue | 65 ++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue
index 61c430b23..119808176 100644
--- a/src/pages/Entry/EntryLatestBuys.vue
+++ b/src/pages/Entry/EntryLatestBuys.vue
@@ -23,7 +23,6 @@ const columns = [
                 return {
                     id: row.id,
                     size: '50x50',
-                    width: '50px',
                 };
             },
         },
@@ -34,21 +33,37 @@ const columns = [
         label: t('entry.latestBuys.tableVisibleColumns.itemFk'),
         name: 'itemFk',
         isTitle: true,
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.packing'),
         name: 'packing',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.grouping'),
         name: 'grouping',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.quantity'),
         name: 'quantity',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
@@ -59,6 +74,10 @@ const columns = [
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.size'),
         name: 'size',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
@@ -84,6 +103,10 @@ const columns = [
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.weightByPiece'),
         name: 'weightByPiece',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
@@ -99,26 +122,46 @@ const columns = [
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.entryFk'),
         name: 'entryFk',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.buyingValue'),
         name: 'buyingValue',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.freightValue'),
         name: 'freightValue',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.comissionValue'),
         name: 'comissionValue',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.packageValue'),
         name: 'packageValue',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
@@ -129,16 +172,28 @@ const columns = [
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.price2'),
         name: 'price2',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.price3'),
         name: 'price3',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.minPrice'),
         name: 'minPrice',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
@@ -149,11 +204,19 @@ const columns = [
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.weight'),
         name: 'weight',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',
         label: t('entry.latestBuys.tableVisibleColumns.packagingFk'),
         name: 'packagingFk',
+        columnFilter: {
+            component: 'number',
+            inWhere: true,
+        },
     },
     {
         align: 'left',

From 4c1e4aedd2099bd08526c2a51d7d9308627a01dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= <carlosap@verdnatura.es>
Date: Fri, 25 Oct 2024 10:03:09 +0200
Subject: [PATCH 087/207] feat: refs #8087 Traspasar redadas a travels

---
 src/pages/Entry/Card/EntryBasicData.vue  | 6 ++++++
 src/pages/Entry/Card/EntryDescriptor.vue | 8 ++++++++
 src/pages/Entry/EntryList.vue            | 2 +-
 src/pages/Travel/TravelList.vue          | 2 +-
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index d60ed8645..b81b1db22 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -168,6 +168,12 @@ const onFilterTravelSelected = (formData, id) => {
                     v-model="data.isExcludedFromAvailable"
                     :label="t('entry.basicData.excludedFromAvailable')"
                 />
+                <QCheckbox v-model="data.isRaid" :label="t('entry.basicData.raid')" />
+                <QCheckbox
+                    v-if="isAdministrative()"
+                    v-model="data.isBooked"
+                    :label="t('entry.basicData.booked')"
+                />
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index bbfc73138..d66185aa9 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -30,6 +30,14 @@ const entryFilter = {
         {
             relation: 'travel',
             scope: {
+                fields: [
+                    'id',
+                    'landed',
+                    'shipped',
+                    'agencyModeFk',
+                    'warehouseOutFk',
+                    'daysInForward',
+                ],
                 include: [
                     {
                         relation: 'agency',
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 518d72d82..e9179c239 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -43,7 +43,7 @@ const entryFilter = {
 const columns = computed(() => [
     {
         name: 'status',
-        hidden: true,
+        columnFilter: false,
     },
     {
         align: 'left',
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index 199746bb7..334640bff 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -47,7 +47,7 @@ const redirectCreateEntryView = (travelData) => {
 const columns = computed(() => [
     {
         name: 'status',
-        hidden: true,
+        columnFilter: false,
     },
     {
         align: 'left',

From 9e57c5e4527b8ffade7be3d0a02889d0c2550346 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= <carlosap@verdnatura.es>
Date: Fri, 25 Oct 2024 10:13:09 +0200
Subject: [PATCH 088/207] feat: refs #8087 Traspasar redadas a travels

---
 src/pages/Entry/Card/EntryBasicData.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index b81b1db22..3288616fb 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -168,7 +168,6 @@ const onFilterTravelSelected = (formData, id) => {
                     v-model="data.isExcludedFromAvailable"
                     :label="t('entry.basicData.excludedFromAvailable')"
                 />
-                <QCheckbox v-model="data.isRaid" :label="t('entry.basicData.raid')" />
                 <QCheckbox
                     v-if="isAdministrative()"
                     v-model="data.isBooked"

From ff559384aad8a7d59a9ebfcb7263ffd93cc40c60 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 25 Oct 2024 10:33:59 +0200
Subject: [PATCH 089/207] perf: refs #6943 #6943 merge command

---
 .../route/agency/agencyWorkCenter.spec.js     |  6 +++---
 .../worker/workerNotificationsManager.spec.js |  4 +++-
 test/cypress/support/commands.js              | 20 ++++++++-----------
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 6a3cab664..311c0130c 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -11,16 +11,16 @@ describe('AgencyWorkCenter', () => {
         // create
         cy.get(createButton).click();
         cy.get(workCenterCombobox).type('workCenterOne{enter}');
-        cy.hasNotify('Data created');
+        cy.checkNotification('created');
 
         // expect error when duplicate
         cy.get(createButton).click();
         cy.get('[data-cy="FormModelPopup_save"]').click();
-        cy.hasNotify('This workCenter is already assigned to this agency');
+        cy.checkNotification('This workCenter is already assigned to this agency');
         cy.get('[data-cy="FormModelPopup_cancel"]').click();
 
         // delete
         cy.get('.q-item__section--side > .q-btn > .q-btn__content > .q-icon').click();
-        cy.hasNotify('WorkCenter removed successfully');
+        cy.checkNotification('WorkCenter removed successfully');
     });
 });
diff --git a/test/cypress/integration/worker/workerNotificationsManager.spec.js b/test/cypress/integration/worker/workerNotificationsManager.spec.js
index 367287a5a..f121b3894 100644
--- a/test/cypress/integration/worker/workerNotificationsManager.spec.js
+++ b/test/cypress/integration/worker/workerNotificationsManager.spec.js
@@ -17,7 +17,9 @@ describe('WorkerNotificationsManager', () => {
         cy.login('developer');
         cy.visit(`/#/worker/${salesPersonId}/notifications`);
         cy.get(firstAvailableNotification).click();
-        cy.hasNotify('The notification subscription of this worker cant be modified');
+        cy.checkNotification(
+            'The notification subscription of this worker cant be modified'
+        );
     });
 
     it('should active a notification that is yours', () => {
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index dcfb54a3e..7d5a44f78 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -274,21 +274,13 @@ Cypress.Commands.add('openActions', (row) => {
     cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
 });
 
-Cypress.Commands.add('checkNotification', (type) => {
-    const values = {
+Cypress.Commands.add('checkNotification', (tag) => {
+    const defaultTags = {
         created: 'Data created',
         updated: 'Data saved',
         deleted: 'Data deleted',
-    };
-    cy.get('.q-notification__message').should('have.text', values[type]);
-});
-
-Cypress.Commands.add('searchByLabel', (label, value) => {
-    cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
-});
-
-Cypress.Commands.add('hasNotify', (text) => {
-    //last
+    }; //last
+    const text = defaultTags[tag] ?? tag;
     cy.get('.q-notification')
         .should('be.visible')
         .last()
@@ -297,3 +289,7 @@ Cypress.Commands.add('hasNotify', (text) => {
                 throw new Error(`Notification not found: "${text}"`);
         });
 });
+
+Cypress.Commands.add('searchByLabel', (label, value) => {
+    cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
+});

From 02f682ac0b5d153c43339812b41fab0605c861c3 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 25 Oct 2024 10:53:19 +0200
Subject: [PATCH 090/207] perf: refs #6943 #6943 merge command

---
 test/cypress/integration/client/clientList.spec.js        | 2 +-
 .../integration/route/agency/agencyWorkCenter.spec.js     | 2 +-
 test/cypress/support/commands.js                          | 8 +-------
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index f150fc190..22bca15ac 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -28,7 +28,7 @@ describe('Client list', () => {
 
         cy.get('.q-mt-lg > .q-btn--standard').click();
 
-        cy.checkNotification('created');
+        cy.checkNotification('Data created');
         cy.url().should('include', '/summary');
     });
     it('Client list search client', () => {
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 311c0130c..fdfcd4286 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -11,7 +11,7 @@ describe('AgencyWorkCenter', () => {
         // create
         cy.get(createButton).click();
         cy.get(workCenterCombobox).type('workCenterOne{enter}');
-        cy.checkNotification('created');
+        cy.checkNotification('Data created');
 
         // expect error when duplicate
         cy.get(createButton).click();
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 7d5a44f78..c9b1a748e 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -274,13 +274,7 @@ Cypress.Commands.add('openActions', (row) => {
     cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
 });
 
-Cypress.Commands.add('checkNotification', (tag) => {
-    const defaultTags = {
-        created: 'Data created',
-        updated: 'Data saved',
-        deleted: 'Data deleted',
-    }; //last
-    const text = defaultTags[tag] ?? tag;
+Cypress.Commands.add('checkNotification', (text) => {
     cy.get('.q-notification')
         .should('be.visible')
         .last()

From bb51a9e6870af70d95a0b70c6e63e49c1633b749 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Fri, 25 Oct 2024 11:38:00 +0200
Subject: [PATCH 091/207] fix: refs #7943 use summary

---
 src/pages/Worker/Card/WorkerCard.vue    | 2 +-
 src/pages/Worker/Card/WorkerSummary.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Worker/Card/WorkerCard.vue b/src/pages/Worker/Card/WorkerCard.vue
index 5f9fa0f8e..428731a5c 100644
--- a/src/pages/Worker/Card/WorkerCard.vue
+++ b/src/pages/Worker/Card/WorkerCard.vue
@@ -6,7 +6,7 @@ import WorkerFilter from '../WorkerFilter.vue';
 <template>
     <VnCard
         data-key="Worker"
-        base-url="Workers"
+        custom-url="Workers/summary"
         :descriptor="WorkerDescriptor"
         :filter-panel="WorkerFilter"
         search-data-key="WorkerList"
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index ed34e771d..4a78afb52 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -45,7 +45,7 @@ onBeforeMount(async () => {
         ref="summary"
         :url="`Workers/summary`"
         :filter="{ where: { id: entityId } }"
-        data-key="WorkerSummary"
+        data-key="Worker"
     >
         <template #header="{ entity }">
             <div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>

From cdb73f7a17588b70d628af92d349ece882aa336b Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Fri, 25 Oct 2024 11:50:20 +0200
Subject: [PATCH 092/207] fix: refs #7943 use correct data-key

---
 src/pages/Worker/WorkerList.vue | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue
index 7a3f760bc..022cecdc6 100644
--- a/src/pages/Worker/WorkerList.vue
+++ b/src/pages/Worker/WorkerList.vue
@@ -169,7 +169,7 @@ async function autofillBic(worker) {
 </script>
 <template>
     <VnSearchbar
-        data-key="Worker"
+        data-key="WorkerList"
         :label="t('Search worker')"
         :info="t('You can search by worker id or name')"
     />
@@ -191,13 +191,13 @@ async function autofillBic(worker) {
     />
     <RightMenu>
         <template #right-panel>
-            <WorkerFilter data-key="Worker" />
+            <WorkerFilter data-key="WorkerList" />
         </template>
     </RightMenu>
     <VnTable
         v-if="defaultPayMethod"
         ref="tableRef"
-        data-key="Worker"
+        data-key="WorkerList"
         url="Workers/filter"
         :create="{
             urlCreate: 'Workers/new',

From 8edba36a7401bad871b994d2e6f2a870c8ed92d0 Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Fri, 25 Oct 2024 13:46:36 +0200
Subject: [PATCH 093/207] feat: refs #7006 itemType basic data new inputs

---
 src/pages/ItemType/Card/ItemTypeBasicData.vue | 36 ++++++++++++++++++-
 src/pages/ItemType/locale/en.yml              |  3 ++
 src/pages/ItemType/locale/es.yml              |  3 ++
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/src/pages/ItemType/Card/ItemTypeBasicData.vue b/src/pages/ItemType/Card/ItemTypeBasicData.vue
index f4013e126..e447f565b 100644
--- a/src/pages/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/ItemType/Card/ItemTypeBasicData.vue
@@ -8,12 +8,14 @@ import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import VnAvatar from 'src/components/ui/VnAvatar.vue';
 
 const route = useRoute();
 const { t } = useI18n();
 
 const categoriesOptions = ref([]);
 const temperaturesOptions = ref([]);
+const itemPackingTypesOptions = ref([]);
 </script>
 <template>
     <FetchData
@@ -28,6 +30,16 @@ const temperaturesOptions = ref([]);
         :filter="{ order: 'name ASC', fields: ['code', 'name'] }"
         auto-load
     />
+    <FetchData
+        url="ItemPackingTypes"
+        @on-fetch="(data) => (itemPackingTypesOptions = data)"
+        :filter="{
+            where: { isActive: true },
+            order: 'description ASC',
+            fields: ['code', 'description'],
+        }"
+        auto-load
+    />
     <FormModel
         :url="`ItemTypes/${route.params.id}`"
         :url-update="`ItemTypes/${route.params.id}`"
@@ -50,7 +62,15 @@ const temperaturesOptions = ref([]);
                     option-label="nickname"
                     option-value="id"
                     hide-selected
-                    ><template #option="scope">
+                >
+                    <template #prepend>
+                        <VnAvatar
+                            :worker-id="data.workerFk"
+                            color="primary"
+                            :title="title"
+                        />
+                    </template>
+                    <template #option="scope">
                         <QItem v-bind="scope.itemProps">
                             <QItemSection>
                                 <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
@@ -82,6 +102,20 @@ const temperaturesOptions = ref([]);
                 />
                 <VnInput v-model="data.life" :label="t('shared.life')" />
             </VnRow>
+            <VnRow>
+                <VnSelect
+                    v-model="data.itemPackingTypeFk"
+                    :label="t('shared.itemPackingType')"
+                    :options="itemPackingTypesOptions"
+                    option-value="code"
+                    option-label="description"
+                    hide-selected
+                />
+                <VnInput v-model="data.maxRefs" :label="t('shared.maxRefs')" />
+            </VnRow>
+            <VnRow>
+                <QCheckbox v-model="data.isFragile" :label="t('shared.fragile')" />
+            </VnRow>
         </template>
     </FormModel>
 </template>
diff --git a/src/pages/ItemType/locale/en.yml b/src/pages/ItemType/locale/en.yml
index 4b203bd68..575d5e402 100644
--- a/src/pages/ItemType/locale/en.yml
+++ b/src/pages/ItemType/locale/en.yml
@@ -5,6 +5,9 @@ shared:
     category: Category
     temperature: Temperature
     life: Life
+    itemPackingType: Item packing type
+    maxRefs: Maximum references
+    fragile: Fragile
 summary:
     id: id
     life: Life
diff --git a/src/pages/ItemType/locale/es.yml b/src/pages/ItemType/locale/es.yml
index 43699c332..09ee5a1f7 100644
--- a/src/pages/ItemType/locale/es.yml
+++ b/src/pages/ItemType/locale/es.yml
@@ -5,6 +5,9 @@ shared:
     category: Reino
     temperature: Temperatura
     life: Vida
+    itemPackingType: Tipo de embalaje
+    maxRefs: Referencias máximas
+    fragile: Frágil
 summary:
     id: id
     code: Código

From 211da859bd20cdab9a041bc821ea60b7fb073ae2 Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Fri, 25 Oct 2024 08:57:16 -0300
Subject: [PATCH 094/207] fix: catalog view category and type filter

---
 src/components/ui/VnFilterPanel.vue         | 33 +++++++++++++++++--
 src/filters/getParamWhere.js                | 12 +++++--
 src/pages/Order/Card/OrderCatalog.vue       | 35 +++++++++++++++++----
 src/pages/Order/Card/OrderCatalogFilter.vue | 26 +++++++++++----
 4 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 43d634ad9..5bdaf150c 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -57,7 +57,6 @@ const $props = defineProps({
     },
 });
 
-defineExpose({ search, sanitizer });
 const emit = defineEmits([
     'update:modelValue',
     'refresh',
@@ -170,9 +169,30 @@ const tagsList = computed(() => {
     return tagList;
 });
 
+const formatTags = (tags) => {
+    const formattedTags = [];
+    tags.forEach((tag) => {
+        if (tag.label === 'and') {
+            tag.value.forEach((item) => {
+                for (const key in item) {
+                    formattedTags.push({ label: key, value: item[key] });
+                }
+            });
+        } else {
+            formattedTags.push(tag);
+        }
+    });
+    return formattedTags;
+};
+
 const tags = computed(() => {
-    return tagsList.value.filter((tag) => !($props.customTags || []).includes(tag.label));
+    const filteredTags = tagsList.value.filter(
+        (tag) => !($props.customTags || []).includes(tag.label)
+    );
+    console.log('formatTags: ', formatTags(filteredTags));
+    return formatTags(filteredTags);
 });
+
 const customTags = computed(() =>
     tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
 );
@@ -193,13 +213,20 @@ function formatValue(value) {
 
 function sanitizer(params) {
     for (const [key, value] of Object.entries(params)) {
-        if (value && typeof value === 'object') {
+        if (key === 'and' && Array.isArray(value)) {
+            value.forEach((item) => {
+                Object.assign(params, item);
+            });
+            delete params[key];
+        } else if (value && typeof value === 'object') {
             const param = Object.values(value)[0];
             if (typeof param == 'string') params[key] = param.replaceAll('%', '');
         }
     }
     return params;
 }
+
+defineExpose({ search, sanitizer, userParams });
 </script>
 
 <template>
diff --git a/src/filters/getParamWhere.js b/src/filters/getParamWhere.js
index 48cd9c479..22dd69af1 100644
--- a/src/filters/getParamWhere.js
+++ b/src/filters/getParamWhere.js
@@ -10,11 +10,19 @@ function parseJSON(str, fallback) {
 export default function (route, param) {
     // catch route query params
     const params = parseJSON(route?.query?.params, {});
-
     // extract and parse filter from params
     const { filter: filterStr = '{}' } = params;
+
     const where = parseJSON(filterStr, {})?.where;
-    if (where && where[param] !== undefined) {
+
+    if (where && !param) {
+        return where;
+    } else if (where && where.and) {
+        const foundParam = where.and.find((p) => p[param]);
+        if (foundParam) {
+            return foundParam[param];
+        }
+    } else if (where && where[param]) {
         return where[param];
     }
     return null;
diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index f9bcca94c..9fee29d7d 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -1,13 +1,14 @@
 <script setup>
 import { useStateStore } from 'stores/useStateStore';
 import { useRoute, useRouter } from 'vue-router';
-import { onMounted, onUnmounted, ref } from 'vue';
+import { onBeforeMount, onMounted, onUnmounted, ref, computed } from 'vue';
 import axios from 'axios';
 import { useI18n } from 'vue-i18n';
 import VnPaginate from 'components/ui/VnPaginate.vue';
 import CatalogItem from 'components/ui/CatalogItem.vue';
 import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
+import getParamWhere from 'src/filters/getParamWhere';
 
 const route = useRoute();
 const router = useRouter();
@@ -15,17 +16,36 @@ const stateStore = useStateStore();
 const { t } = useI18n();
 const tags = ref([]);
 
+let catalogParams = {
+    orderFk: route.params.id,
+    orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
+};
+
+onBeforeMount(() => {
+    const whereParams = getParamWhere(route);
+    if (whereParams) {
+        const formattedWhereParams = {};
+        if (whereParams.and) {
+            whereParams.and.forEach((item) => {
+                Object.assign(formattedWhereParams, item);
+            });
+        } else {
+            Object.assign(formattedWhereParams, whereParams);
+        }
+
+        catalogParams = {
+            ...catalogParams,
+            ...formattedWhereParams,
+        };
+    }
+});
+
 onMounted(() => {
     stateStore.rightDrawer = true;
     checkOrderConfirmation();
 });
 onUnmounted(() => (stateStore.rightDrawer = false));
 
-const catalogParams = {
-    orderFk: route.params.id,
-    orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
-};
-
 async function checkOrderConfirmation() {
     const response = await axios.get(`Orders/${route.params.id}`);
     if (response.data.isConfirmed === 1) {
@@ -61,6 +81,7 @@ function extractValueTags(items) {
     );
     tagValue.value = resultValueTags;
 }
+const autoLoad = computed(() => !!catalogParams.categoryFk);
 </script>
 
 <template>
@@ -79,6 +100,7 @@ function extractValueTags(items) {
                 data-key="OrderCatalogList"
                 :tag-value="tagValue"
                 :tags="tags"
+                :initial-catalog-params="catalogParams"
             />
         </QScrollArea>
     </QDrawer>
@@ -91,6 +113,7 @@ function extractValueTags(items) {
                 :user-params="catalogParams"
                 @on-fetch="extractTags"
                 :update-router="false"
+                :auto-load="autoLoad"
             >
                 <template #body="{ rows }">
                     <div class="catalog-list">
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 6de43e86a..cc3f45391 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import axios from 'axios';
@@ -26,9 +26,13 @@ const props = defineProps({
         type: Array,
         required: true,
     },
+    initialCatalogParams: {
+        type: Object,
+        default: () => ({}),
+    },
 });
 const categoryList = ref(null);
-const selectedCategoryFk = ref(getParamWhere(route, 'categoryFk'));
+const selectedCategoryFk = ref(null);
 const typeList = ref([]);
 const selectedTypeFk = ref(null);
 const selectedTag = ref(null);
@@ -74,6 +78,8 @@ const selectCategory = (params, category, search) => {
     } else {
         selectedCategoryFk.value = category?.id;
         params.categoryFk = category?.id;
+        params.typeFk = null;
+        selectedTypeFk.value = null;
         loadTypes(category?.id);
     }
     search();
@@ -86,11 +92,11 @@ const loadTypes = async (categoryFk = selectedCategoryFk.value) => {
     typeList.value = data;
 };
 
-const selectedCategory = computed(() =>
-    (categoryList.value || []).find(
+const selectedCategory = computed(() => {
+    return (categoryList.value || []).find(
         (category) => category?.id === selectedCategoryFk.value
-    )
-);
+    );
+});
 function filterFn(val, update) {
     update(() => {
         const needle = val.toLowerCase();
@@ -171,6 +177,11 @@ function addOrder(value, field, params) {
     params.orderBy = JSON.stringify(orderBy);
     vnFilterPanelRef.value.search();
 }
+
+onMounted(() => {
+    selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
+    selectedTypeFk.value = getParamWhere(route, 'typeFk');
+});
 </script>
 
 <template>
@@ -206,6 +217,8 @@ function addOrder(value, field, params) {
                         removable
                         @remove="removeTagChip(chip, params, searchFn)"
                     >
+                        <pre>{{ chip }}</pre>
+
                         <strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
                         <span>{{
                             (JSON.parse(chip).values || [])
@@ -384,6 +397,7 @@ function addOrder(value, field, params) {
                 />
             </QItem>
             <QSeparator />
+            <pre>{{ params }}</pre>
         </template>
     </VnFilterPanel>
 </template>

From 494fc66c06377838c2d23d6f6cf945c91c753f67 Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Fri, 25 Oct 2024 14:14:51 +0200
Subject: [PATCH 095/207] feat: refs #7006 itemType basic data new inputs

---
 src/pages/Item/ItemTypeList.vue               | 15 ++++-----------
 src/pages/ItemType/Card/ItemTypeBasicData.vue |  1 -
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 2c1153016..13dd56a42 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -7,7 +7,6 @@ import FetchData from 'components/FetchData.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-const workerOptions = ref([]);
 const ItemCategoriesOptions = ref([]);
 
 const columns = computed(() => [
@@ -40,12 +39,12 @@ const columns = computed(() => [
         create: true,
         component: 'select',
         attrs: {
-            options: workerOptions.value,
-            optionLabel: 'firstName',
+            url: 'Workers/search',
+            optionLabel: 'nickname',
             optionValue: 'id',
         },
-        cardVisible: false,
-        visible: false,
+        cardVisible: true,
+        visible: true,
     },
     {
         align: 'left',
@@ -78,12 +77,6 @@ const columns = computed(() => [
 </script>
 
 <template>
-    <FetchData
-        url="Workers"
-        :filter="{ fields: ['id', 'firstName'], order: ['firstName ASC'] }"
-        @on-fetch="(data) => (workerOptions = data)"
-        auto-load
-    />
     <FetchData
         url="ItemCategories"
         :filter="{ fields: ['id', 'name'], order: ['name ASC'] }"
diff --git a/src/pages/ItemType/Card/ItemTypeBasicData.vue b/src/pages/ItemType/Card/ItemTypeBasicData.vue
index e447f565b..1a4a7c9f3 100644
--- a/src/pages/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/ItemType/Card/ItemTypeBasicData.vue
@@ -58,7 +58,6 @@ const itemPackingTypesOptions = ref([]);
                     :label="t('shared.worker')"
                     sort-by="nickname ASC"
                     :fields="['id', 'nickname']"
-                    :params="{ departmentCodes: ['shopping'] }"
                     option-label="nickname"
                     option-value="id"
                     hide-selected

From 1da86900e653a072bbe898f2d75997a5851c59be Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Sun, 27 Oct 2024 13:43:38 +0100
Subject: [PATCH 096/207] fix: refs #7524 e2e & worker module

---
 src/components/ui/VnRow.vue                   |  3 --
 src/composables/useAdvancedSummary.js         | 11 ++++++
 src/pages/Ticket/Card/TicketExpedition.vue    |  1 +
 src/pages/Ticket/TicketAdvance.vue            |  1 -
 src/pages/Worker/Card/WorkerBasicData.vue     | 36 +++++++++----------
 src/pages/Worker/Card/WorkerLocker.vue        |  3 +-
 src/pages/Worker/Card/WorkerSummary.vue       | 32 ++++++++---------
 src/router/modules/worker.js                  |  7 ++++
 .../ticket/ticketExpedition.spec.js           | 12 +++----
 .../integration/worker/workerList.spec.js     |  2 +-
 .../integration/worker/workerLocker.spec.js   | 11 +++---
 test/cypress/support/commands.js              |  2 +-
 12 files changed, 63 insertions(+), 58 deletions(-)
 create mode 100644 src/composables/useAdvancedSummary.js

diff --git a/src/components/ui/VnRow.vue b/src/components/ui/VnRow.vue
index 16bcfab7d..40dabf610 100644
--- a/src/components/ui/VnRow.vue
+++ b/src/components/ui/VnRow.vue
@@ -1,6 +1,3 @@
-<script setup>
-defineProps({ wrap: { type: Boolean, default: false } });
-</script>
 <template>
     <div class="vn-row q-gutter-md q-mb-md">
         <slot />
diff --git a/src/composables/useAdvancedSummary.js b/src/composables/useAdvancedSummary.js
new file mode 100644
index 000000000..98b998d2a
--- /dev/null
+++ b/src/composables/useAdvancedSummary.js
@@ -0,0 +1,11 @@
+import axios from 'axios';
+import { useRole } from './useRole';
+
+export async function useAdvancedSummary(model, id, roles = ['hr']) {
+    if (useRole().hasAny(roles)) {
+        const { data } = await axios.get(`${model}/advancedSummary`, {
+            params: { filter: { where: { id } } },
+        });
+        return Array.isArray(data) ? data[0] : data;
+    }
+}
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index 8041ad069..d682d0408 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -211,6 +211,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
         <template #st-actions>
             <QBtnGroup push class="q-gutter-x-sm" flat>
                 <VnBtnSelect
+                    data-cy="change-state"
                     :disable="!hasSelectedRows"
                     color="primary"
                     :label="t('globals.changeState')"
diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue
index 7db2b54b3..bdd980c07 100644
--- a/src/pages/Ticket/TicketAdvance.vue
+++ b/src/pages/Ticket/TicketAdvance.vue
@@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n';
 import FetchData from 'components/FetchData.vue';
 import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
-import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import VnProgress from 'src/components/common/VnProgressModal.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 import TicketAdvanceFilter from './TicketAdvanceFilter.vue';
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
index d131fea3e..6a13e3f39 100644
--- a/src/pages/Worker/Card/WorkerBasicData.vue
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref } from 'vue';
+import { ref, onBeforeMount } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
@@ -8,32 +8,22 @@ import FormModel from 'src/components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 
-const route = useRoute();
 const { t } = useI18n();
-
 const educationLevels = ref([]);
 const countries = ref([]);
 const maritalStatus = [
     { code: 'M', name: t('Married') },
     { code: 'S', name: t('Single') },
 ];
+const advancedSummary = ref({});
 
-const workerFilter = {
-    include: [
-        {
-            relation: 'user',
-            scope: {
-                fields: ['name', 'emailVerified'],
-                include: { relation: 'emailUser', scope: { fields: ['email'] } },
-            },
-        },
-        { relation: 'sip', scope: { fields: ['extension', 'secret'] } },
-        { relation: 'department', scope: { include: { relation: 'department' } } },
-    ],
-};
+onBeforeMount(async () => {
+    advancedSummary.value =
+        (await useAdvancedSummary('Workers', +useRoute().params.id)) ?? {};
+});
 </script>
-
 <template>
     <FetchData
         :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
@@ -48,10 +38,16 @@ const workerFilter = {
         auto-load
     />
     <FormModel
-        :filter="workerFilter"
-        :url="`Workers/${route.params.id}`"
+        :filter="{ where: { id: +$route.params.id } }"
+        url="Workers/summary"
+        :url-update="`Workers/${$route.params.id}`"
         auto-load
         model="Worker"
+        @on-fetch="
+            async (data) => {
+                Object.assign(data, advancedSummary);
+            }
+        "
     >
         <template #form="{ data }">
             <VnRow>
@@ -134,7 +130,7 @@ const workerFilter = {
                 <VnInput v-model="data.fi" :label="t('fi')" />
                 <VnInputDate :label="t('birth')" v-model="data.birth" />
             </VnRow>
-            <VnRow>
+            <VnRow wrap>
                 <QCheckbox
                     size="sm"
                     :label="t('isFreelance')"
diff --git a/src/pages/Worker/Card/WorkerLocker.vue b/src/pages/Worker/Card/WorkerLocker.vue
index 4a19e472c..015bced35 100644
--- a/src/pages/Worker/Card/WorkerLocker.vue
+++ b/src/pages/Worker/Card/WorkerLocker.vue
@@ -18,7 +18,7 @@ const { store } = useArrayData('Worker');
 const entityId = computed(() => useRoute().params.id);
 const filter = computed(() => ({
     where: {
-        gender: store.data?.sex,
+        gender: store.data?.[0]?.sex,
         or: [{ workerFk: null }, { workerFk: entityId.value }],
     },
 }));
@@ -51,6 +51,7 @@ const init = async (data) => {
     >
         <template #form="{ data }">
             <VnSelect
+                data-cy="locker"
                 :label="t('Locker')"
                 v-model="data.id"
                 :options="lockers"
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 4a78afb52..0a0694fdf 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -2,7 +2,6 @@
 import { ref, onBeforeMount, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import axios from 'axios';
 import { dashIfEmpty, toDate } from 'src/filters';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
@@ -11,7 +10,7 @@ import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
 import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
-import { useRole } from 'src/composables/useRole';
+import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -25,18 +24,11 @@ const $props = defineProps({
 
 const entityId = computed(() => $props.id || route.params.id);
 const basicDataUrl = ref(null);
-const isHr = computed(() => useRole().hasAny(['hr']));
 const advancedSummary = ref();
 
 onBeforeMount(async () => {
-    if (isHr.value) {
-        advancedSummary.value = (
-            await axios.get('Workers/advancedSummary', {
-                params: { filter: { where: { id: entityId.value } } },
-            })
-        ).data[0];
-        basicDataUrl.value = `#/worker/${entityId.value}/basic-data`;
-    }
+    advancedSummary.value = await useAdvancedSummary('Workers', entityId.value);
+    basicDataUrl.value = `#/worker/${entityId.value}/basic-data`;
 });
 </script>
 
@@ -101,21 +93,27 @@ onBeforeMount(async () => {
                     :label="t('worker.summary.seniority')"
                     :value="toDate(worker.seniority)"
                 />
-                <VnLv :label="t('worker.summary.fi')" :value="worker.fi" />
-                <VnLv :label="t('worker.summary.birth')" :value="toDate(worker.birth)" />
+                <VnLv :label="t('worker.summary.fi')" :value="advancedSummary.fi" />
+                <VnLv
+                    :label="t('worker.summary.birth')"
+                    :value="toDate(advancedSummary.birth)"
+                />
                 <VnLv
                     :label="t('worker.summary.isFreelance')"
-                    :value="worker.isFreelance"
+                    :value="advancedSummary.isFreelance"
                 />
                 <VnLv
                     :label="t('worker.summary.isSsDiscounted')"
-                    :value="worker.isSsDiscounted"
+                    :value="advancedSummary.isSsDiscounted"
                 />
                 <VnLv
                     :label="t('worker.summary.hasMachineryAuthorized')"
-                    :value="worker.hasMachineryAuthorized"
+                    :value="advancedSummary.hasMachineryAuthorized"
+                />
+                <VnLv
+                    :label="t('worker.summary.isDisable')"
+                    :value="advancedSummary.isDisable"
                 />
-                <VnLv :label="t('worker.summary.isDisable')" :value="worker.isDisable" />
             </QCard>
             <QCard class="vn-one">
                 <VnTitle :text="t('worker.summary.userData')" />
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index c2a9e668f..d1feff23d 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -87,6 +87,13 @@ export default {
                     meta: {
                         title: 'basicData',
                         icon: 'vn:settings',
+                        acls: [
+                            {
+                                model: 'Worker',
+                                props: 'updateAttributes',
+                                accessType: 'WRITE',
+                            },
+                        ],
                     },
                     component: () => import('src/pages/Worker/Card/WorkerBasicData.vue'),
                 },
diff --git a/test/cypress/integration/ticket/ticketExpedition.spec.js b/test/cypress/integration/ticket/ticketExpedition.spec.js
index 5eb2c1a2a..d4afd401f 100644
--- a/test/cypress/integration/ticket/ticketExpedition.spec.js
+++ b/test/cypress/integration/ticket/ticketExpedition.spec.js
@@ -11,15 +11,13 @@ describe('Ticket expedtion', () => {
 
     it('should change the state', () => {
         cy.visit('#/ticket/1/expedition');
-        cy.intercept('GET', /\/api\/Expeditions\/filter/).as('expeditions');
-        cy.intercept('POST', /\/api\/Expeditions\/crud/).as('crud');
-
-        cy.wait('@expeditions');
+        cy.intercept('GET', /\/api\/Expeditions\/filter/).as('show');
+        cy.intercept('POST', /\/api\/ExpeditionStates\/addExpeditionState/).as('add');
 
+        cy.wait('@show');
         cy.selectRows([1, 2]);
-        cy.get('#subToolbar [aria-controls]:nth-child(1)').click();
-        cy.get('.q-menu .q-item').contains('Perdida').click();
-        cy.wait('@crud');
+        cy.selectOption('[data-cy="change-state"]', 'Perdida');
+        cy.wait('@add');
 
         cy.get(`${tableContent} tr:nth-child(-n+2) ${stateTd}`).each(($el) => {
             cy.wrap($el).contains('Perdida');
diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js
index 8a8bea443..c1c37fd32 100644
--- a/test/cypress/integration/worker/workerList.spec.js
+++ b/test/cypress/integration/worker/workerList.spec.js
@@ -11,7 +11,7 @@ describe('WorkerList', () => {
     it('should open the worker summary', () => {
         cy.get(inputName).type('jessica{enter}');
         cy.get(searchBtn).click();
-        cy.intercept('GET', /\/api\/Workers\/\d+/).as('worker');
+        cy.intercept('GET', /\/api\/Workers\/summary+/).as('worker');
         cy.wait('@worker').then(() =>
             cy.get(descriptorTitle).should('include.text', 'Jessica')
         );
diff --git a/test/cypress/integration/worker/workerLocker.spec.js b/test/cypress/integration/worker/workerLocker.spec.js
index 8a169dfb2..c222414fd 100644
--- a/test/cypress/integration/worker/workerLocker.spec.js
+++ b/test/cypress/integration/worker/workerLocker.spec.js
@@ -1,8 +1,7 @@
 describe('WorkerLocker', () => {
     const productionId = 49;
-    const lockerCode = '2F';
-    const input = '.q-card input';
-    const thirdOpt = '[role="listbox"] .q-item:nth-child(1)';
+    const lockerCode = '4F';
+    const lockerSelect = '[data-cy="locker"]';
     beforeEach(() => {
         cy.viewport(1280, 720);
         cy.login('productionBoss');
@@ -10,10 +9,8 @@ describe('WorkerLocker', () => {
     });
 
     it('should allocates a locker', () => {
-        cy.get(input).click();
-        cy.waitForElement('[role="listbox"]');
-        cy.get(thirdOpt).click();
+        cy.selectOption(lockerSelect, lockerCode);
         cy.saveCard();
-        cy.get(input).invoke('val').should('eq', lockerCode);
+        cy.get(lockerSelect).invoke('val').should('eq', lockerCode);
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index c9b1a748e..76bdefd27 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -82,7 +82,7 @@ Cypress.Commands.add('getValue', (selector) => {
 // Fill Inputs
 Cypress.Commands.add('selectOption', (selector, option) => {
     cy.waitForElement(selector);
-    cy.get(selector).find('.q-select__dropdown-icon').click();
+    cy.get(selector).click();
     cy.get('.q-menu .q-item').contains(option).click();
 });
 

From 0cc0e82aaaba838cbcd6c7ced6d52347af7438d0 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Sun, 27 Oct 2024 14:48:44 +0100
Subject: [PATCH 097/207] feat: refs #8078 add shortcut multi selection

---
 src/components/VnTable/VnTable.vue | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index c1680bf13..74a96e0e3 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -331,6 +331,16 @@ function handleScroll() {
     const isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) <= 40;
     if (isAtBottom) CrudModelRef.value.vnPaginateRef.paginate();
 }
+
+function handleSelection({ evt, added, rows: selectedRows }, rows) {
+    if (evt?.shiftKey && added) {
+        const rowIndex = selectedRows[0].$index;
+        for (const row of rows) {
+            if (row.$index > rowIndex) break;
+            selected.value.push(row);
+        }
+    }
+}
 </script>
 <template>
     <QDrawer
@@ -431,6 +441,7 @@ function handleScroll() {
                 @virtual-scroll="handleScroll"
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
                 @update:selected="emit('update:selected', $event)"
+                @selection="(details) => handleSelection(details, rows)"
             >
                 <template #top-left v-if="!$props.withoutHeader">
                     <slot name="top-left"></slot>

From c93f152060a9cb37360e35069e39a32ebbeca1c1 Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Sun, 27 Oct 2024 15:27:53 -0300
Subject: [PATCH 098/207] fix: order catalog fixes

---
 src/pages/Order/Card/OrderCatalog.vue       |  22 ++-
 src/pages/Order/Card/OrderCatalogFilter.vue | 164 +++++++++-----------
 2 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index 9fee29d7d..a266fc3d4 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { useStateStore } from 'stores/useStateStore';
 import { useRoute, useRouter } from 'vue-router';
-import { onBeforeMount, onMounted, onUnmounted, ref, computed } from 'vue';
+import { onBeforeMount, onMounted, onUnmounted, ref, computed, watch } from 'vue';
 import axios from 'axios';
 import { useI18n } from 'vue-i18n';
 import VnPaginate from 'components/ui/VnPaginate.vue';
@@ -9,11 +9,15 @@ import CatalogItem from 'components/ui/CatalogItem.vue';
 import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import getParamWhere from 'src/filters/getParamWhere';
+import { useArrayData } from 'composables/useArrayData';
 
 const route = useRoute();
 const router = useRouter();
 const stateStore = useStateStore();
 const { t } = useI18n();
+const arrayData = useArrayData('OrderCatalogList');
+const store = arrayData.store;
+const showFilter = ref(null);
 const tags = ref([]);
 
 let catalogParams = {
@@ -37,6 +41,8 @@ onBeforeMount(() => {
             ...catalogParams,
             ...formattedWhereParams,
         };
+    } else {
+        showFilter.value = true;
     }
 });
 
@@ -44,6 +50,7 @@ onMounted(() => {
     stateStore.rightDrawer = true;
     checkOrderConfirmation();
 });
+
 onUnmounted(() => (stateStore.rightDrawer = false));
 
 async function checkOrderConfirmation() {
@@ -54,6 +61,7 @@ async function checkOrderConfirmation() {
 }
 
 function extractTags(items) {
+    if (!items || !items.length) return;
     const resultTags = [];
     (items || []).forEach((item) => {
         (item.tags || []).forEach((tag) => {
@@ -82,6 +90,14 @@ function extractValueTags(items) {
     tagValue.value = resultValueTags;
 }
 const autoLoad = computed(() => !!catalogParams.categoryFk);
+
+watch(
+    () => store.data,
+    (val) => {
+        extractTags(val);
+    },
+    { immediate: true }
+);
 </script>
 
 <template>
@@ -95,7 +111,7 @@ const autoLoad = computed(() => !!catalogParams.categoryFk);
         :info="t('You can search items by name or id')"
     />
     <QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
-        <QScrollArea class="fit text-grey-8">
+        <QScrollArea v-if="showFilter" class="fit text-grey-8">
             <OrderCatalogFilter
                 data-key="OrderCatalogList"
                 :tag-value="tagValue"
@@ -111,7 +127,7 @@ const autoLoad = computed(() => !!catalogParams.categoryFk);
                 url="Orders/CatalogFilter"
                 :limit="50"
                 :user-params="catalogParams"
-                @on-fetch="extractTags"
+                @on-fetch="showFilter = true"
                 :update-router="false"
                 :auto-load="autoLoad"
             >
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index cc3f45391..5612399d7 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -26,11 +26,8 @@ const props = defineProps({
         type: Array,
         required: true,
     },
-    initialCatalogParams: {
-        type: Object,
-        default: () => ({}),
-    },
 });
+
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
@@ -52,14 +49,6 @@ const orderWayList = ref([
 const orderBySelected = ref('relevancy DESC, name');
 const orderWaySelected = ref('ASC');
 
-const createValue = (val, done) => {
-    if (val.length > 2) {
-        if (!tagOptions.value.includes(val)) {
-            done(tagOptions.value, 'add-unique');
-        }
-        tagValues.value.push({ value: val });
-    }
-};
 const resetCategory = () => {
     selectedCategoryFk.value = null;
     typeList.value = null;
@@ -97,14 +86,7 @@ const selectedCategory = computed(() => {
         (category) => category?.id === selectedCategoryFk.value
     );
 });
-function filterFn(val, update) {
-    update(() => {
-        const needle = val.toLowerCase();
-        tagOptions.value = props.tagValue.filter(
-            (v) => v.toLowerCase().indexOf(needle) > -1
-        );
-    });
-}
+
 const selectedType = computed(() => {
     return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
 });
@@ -120,36 +102,36 @@ function exprBuilder(param, value) {
     }
 }
 
-const applyTagFilter = (params, search) => {
+const applyTags = (params, search) => {
     if (!tagValues.value?.length) {
         params.tagGroups = null;
         search();
         return;
     }
-    if (!params.tagGroups) {
-        params.tagGroups = [];
-    }
-    params.tagGroups.push(
-        JSON.stringify({
-            values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
-            tagSelection: {
-                ...selectedTag.value,
-                orgShowField: selectedTag?.value?.name,
-            },
-            tagFk: selectedTag?.value?.tagFk,
-        })
-    );
+
+    const tagGroups = {
+        values: [...tagValues.value],
+        tagFk: selectedTag?.value?.id,
+        tagSelection: {
+            name: selectedTag?.value?.name,
+        },
+    };
+
+    params.tagGroups = tagGroups;
     search();
-    selectedTag.value = null;
-    tagValues.value = [{}];
 };
 
-const removeTagChip = (selection, params, search) => {
-    if (params.tagGroups) {
-        params.tagGroups = (params.tagGroups || []).filter(
-            (value) => value !== selection
-        );
+const removeTagGroupParam = (params, search, valIndex = null) => {
+    if (!params.tagGroups) return;
+
+    if (!valIndex) {
+        params.tagGroups = null;
+        tagValues.value = [{}];
+    } else {
+        (tagValues.value || []).splice(valIndex, 1);
+        params.tagGroups.values.splice(valIndex, 1);
     }
+
     search();
 };
 
@@ -178,9 +160,37 @@ function addOrder(value, field, params) {
     vnFilterPanelRef.value.search();
 }
 
+const getSelectedTagValues = async (tag) => {
+    try {
+        if (!tag?.id) return;
+        const filter = {
+            fields: ['value'],
+            order: 'value ASC',
+            limit: 30,
+        };
+
+        const url = `Tags/${tag?.id}/filterValue`;
+        console.log('url', url);
+        const params = { filter: JSON.stringify(filter) };
+        const { data } = await axios.get(url, {
+            params,
+        });
+        tagOptions.value = data;
+    } catch (err) {
+        console.error('Error getting selected tag values');
+    }
+};
+
 onMounted(() => {
     selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
     selectedTypeFk.value = getParamWhere(route, 'typeFk');
+    if (route.query.params && JSON.parse(route.query.params).tagGroups) {
+        const tagGroups = JSON.parse(route.query.params).tagGroups;
+        tagValues.value = [...tagGroups.values];
+        selectedTag.value = (props.tags || []).find(
+            (tag) => tag.name === tagGroups.tagSelection.name
+        );
+    }
 });
 </script>
 
@@ -212,19 +222,19 @@ onMounted(() => {
             <template v-for="tag in customTags" :key="tag.label">
                 <template v-if="tag.label === 'tagGroups'">
                     <VnFilterPanelChip
-                        v-for="chip in tag.value"
-                        :key="chip"
                         removable
-                        @remove="removeTagChip(chip, params, searchFn)"
+                        @remove="removeTagGroupParam(params, searchFn)"
                     >
-                        <pre>{{ chip }}</pre>
-
-                        <strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
-                        <span>{{
-                            (JSON.parse(chip).values || [])
-                                .map((item) => item.value)
-                                .join(' | ')
-                        }}</span>
+                        <strong class="q-mr-xs">
+                            {{ tag.value?.tagSelection?.name }}:
+                        </strong>
+                        <span>
+                            {{
+                                (tag.value?.values || [])
+                                    .map((item) => `"${item.value}"`)
+                                    .join(', ')
+                            }}
+                        </span>
                     </VnFilterPanelChip>
                 </template>
             </template>
@@ -323,6 +333,7 @@ onMounted(() => {
                         rounded
                         :emit-value="false"
                         use-input
+                        @update:model-value="($event) => getSelectedTagValues($event)"
                     />
                 </QItemSection>
             </QItem>
@@ -331,16 +342,9 @@ onMounted(() => {
                 :key="value"
                 class="q-mt-md filter-value"
             >
-                <FetchData
-                    v-if="selectedTag"
-                    :url="`Tags/${selectedTag}/filterValue`"
-                    limit="30"
-                    auto-load
-                    @on-fetch="(data) => (tagOptions = data)"
-                />
                 <VnSelect
-                    v-if="!selectedTag"
-                    :label="t('params.value')"
+                    v-if="!selectedTag?.isFree && tagOptions"
+                    :label="t('components.itemsFilterPanel.value')"
                     v-model="value.value"
                     :options="tagOptions || []"
                     option-value="value"
@@ -350,41 +354,23 @@ onMounted(() => {
                     rounded
                     emit-value
                     use-input
-                    class="filter-input"
-                    @new-value="createValue"
-                    @filter="filterFn"
-                    @update:model-value="applyTagFilter(params, searchFn)"
-                />
-                <VnSelect
-                    v-else-if="selectedTag === 1"
-                    :label="t('params.value')"
-                    v-model="value.value"
-                    :options="tagOptions || []"
-                    option-value="value"
-                    option-label="value"
-                    dense
-                    outlined
-                    rounded
-                    emit-value
-                    use-input
-                    class="filter-input"
-                    @new-value="createValue"
-                    @update:model-value="applyTagFilter(params, searchFn)"
+                    :disable="!value"
+                    :is-clearable="false"
+                    @update:model-value="applyTags(params, searchFn)"
                 />
                 <VnInput
                     v-else
-                    :label="t('params.value')"
                     v-model="value.value"
-                    dense
-                    outlined
-                    rounded
-                    class="filter-input"
-                    @keyup.enter="applyTagFilter(params, searchFn)"
+                    :label="t('components.itemsFilterPanel.value')"
+                    :disable="!value"
+                    is-outlined
+                    :is-clearable="false"
+                    @keyup.enter="applyTags(params, searchFn)"
                 />
                 <QIcon
                     name="delete"
                     class="filter-icon"
-                    @click="(tagValues || []).splice(index, 1)"
+                    @click="removeTagGroupParam(params, searchFn, index)"
                 />
             </QItem>
             <QItem class="q-mt-lg">
@@ -393,11 +379,11 @@ onMounted(() => {
                     shortcut="+"
                     flat
                     class="filter-icon"
+                    size="md"
                     @click="tagValues.push({})"
                 />
             </QItem>
             <QSeparator />
-            <pre>{{ params }}</pre>
         </template>
     </VnFilterPanel>
 </template>

From ca6547e174b12865105cd819ccb3f1ccedf47803 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 07:48:11 +0100
Subject: [PATCH 099/207] feat: refs #7970 notify changes

---
 src/components/ui/VnConfirm.vue      | 23 ++++++---
 src/pages/Ticket/Card/TicketSale.vue | 76 ++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 10 deletions(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index 4fa374b62..0fbc55cfb 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -30,10 +30,10 @@ const props = defineProps({
     },
 });
 
-defineEmits(['confirm', ...useDialogPluginComponent.emits]);
-defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
+defineEmits([...useDialogPluginComponent.emits]);
 
-const { dialogRef, onDialogOK } = useDialogPluginComponent();
+const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
+    useDialogPluginComponent();
 
 const title = props.title || t('Confirm');
 const message =
@@ -53,9 +53,13 @@ async function confirm() {
     }
     onDialogOK(props.data);
 }
+
+function cancel() {
+    onDialogCancel();
+}
 </script>
 <template>
-    <QDialog ref="dialogRef">
+    <QDialog ref="dialogRef" @hide="onDialogHide">
         <QCard class="q-pa-sm">
             <QCardSection class="row items-center q-pb-none">
                 <QAvatar
@@ -67,7 +71,14 @@ async function confirm() {
                 />
                 <span class="text-h6">{{ title }}</span>
                 <QSpace />
-                <QBtn icon="close" :disable="isLoading" flat round dense v-close-popup />
+                <QBtn
+                    icon="close"
+                    :disable="isLoading"
+                    flat
+                    round
+                    dense
+                    @click="cancel()"
+                />
             </QCardSection>
             <QCardSection class="q-pb-none">
                 <span v-if="message !== false" v-html="message" />
@@ -81,7 +92,7 @@ async function confirm() {
                     color="primary"
                     :disable="isLoading"
                     flat
-                    v-close-popup
+                    @click="cancel()"
                 />
                 <QBtn
                     :label="t('globals.confirm')"
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index c786c67e3..3426db880 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -2,6 +2,7 @@
 import { onMounted, ref, computed, onUnmounted, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRouter, useRoute } from 'vue-router';
+import { useQuasar } from 'quasar';
 
 import FetchData from 'components/FetchData.vue';
 import FetchedTags from 'components/ui/FetchedTags.vue';
@@ -23,6 +24,7 @@ import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import VnUsesMana from 'src/components/ui/VnUsesMana.vue';
+import VnConfirm from 'src/components/ui/VnConfirm.vue';
 
 const route = useRoute();
 const router = useRouter();
@@ -32,7 +34,7 @@ const { notify } = useNotify();
 const { openConfirmationModal } = useVnConfirm();
 const editPriceProxyRef = ref(null);
 const stateBtnDropdownRef = ref(null);
-
+const quasar = useQuasar();
 const arrayData = useArrayData('ticketData');
 const { store } = arrayData;
 const selectedRows = ref([]);
@@ -51,6 +53,7 @@ const transfer = ref({
     sales: [],
 });
 const tableRef = ref([]);
+const canProceed = ref();
 
 watch(
     () => route.params.id,
@@ -214,7 +217,9 @@ const addSale = async (sale) => {
     }
 };
 
-const changeQuantity = (sale) => {
+const changeQuantity = async (sale) => {
+    canProceed.value = await isSalePrepared(sale);
+    if (!canProceed.value) return;
     if (
         !sale.itemFk ||
         sale.quantity == null ||
@@ -226,6 +231,8 @@ const changeQuantity = (sale) => {
 };
 
 const updateConcept = async (sale) => {
+    canProceed.value = await isSalePrepared(sale);
+    if (!canProceed.value) return;
     try {
         const data = { newConcept: sale.concept };
         await axios.post(`Sales/${sale.id}/updateConcept`, data);
@@ -286,6 +293,8 @@ const onOpenEditDiscountPopover = async (sale) => {
 };
 
 const updatePrice = async (sale) => {
+    canProceed.value = await isSalePrepared(sale);
+    if (!canProceed.value) return;
     try {
         const newPrice = edit.value.price;
         if (newPrice != null && newPrice != sale.price) {
@@ -300,12 +309,18 @@ const updatePrice = async (sale) => {
     }
 };
 
-const changeDiscount = (sale) => {
+const changeDiscount = async (sale) => {
+    canProceed.value = await isSalePrepared(sale);
+    if (!canProceed.value) return;
     const newDiscount = edit.value.discount;
     if (newDiscount != null && newDiscount != sale.discount) updateDiscount([sale]);
 };
 
 const updateDiscount = async (sales, newDiscount = null) => {
+    for (const sale of sales) {
+        const canProceed = await isSalePrepared(sale);
+        if (!canProceed) return;
+    }
     const saleIds = sales.map((sale) => sale.id);
     const _newDiscount = newDiscount || edit.value.discount;
     const params = {
@@ -433,7 +448,9 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 const items = ref([]);
 const newRow = ref({});
 
-const updateItem = (row) => {
+const updateItem = async (row) => {
+    canProceed.value = await isSalePrepared(row);
+    if (!canProceed.value) return;
     const selectedItem = items.value.find((item) => item.id === row.itemFk);
     if (selectedItem) {
         row.item = selectedItem;
@@ -476,6 +493,55 @@ const endNewRow = (row) => {
     }
 };
 
+async function isSalePrepared(item) {
+    const filter = {
+        params: {
+            where: { ticketFk: route.params.id },
+            order: ['concept ASC', 'quantity DESC'],
+        },
+    };
+    const { data } = await axios.get(`SaleTrackings/${route.params.id}/filter`, {
+        params: {
+            filter: JSON.stringify(filter),
+        },
+    });
+
+    const matchingSale = data.find((sale) => sale.itemFk === item.itemFk);
+    if (!matchingSale) {
+        return true;
+    }
+
+    if (
+        matchingSale.hasSaleGroupDetail ||
+        matchingSale.isControled ||
+        matchingSale.isPrepared ||
+        matchingSale.isPrevious ||
+        matchingSale.isPreviousSelected
+    ) {
+        try {
+            await new Promise((resolve, reject) => {
+                quasar
+                    .dialog({
+                        component: VnConfirm,
+                        componentProps: {
+                            title: t('Item prepared'),
+                            message: t(
+                                'This item is already prepared. Do you want to continue?'
+                            ),
+                            data: item,
+                        },
+                    })
+                    .onOk(() => resolve(true))
+                    .onCancel(() => reject(new Error('cancelled')));
+            });
+        } catch (error) {
+            tableRef.value.reload();
+            return false;
+        }
+    }
+    return true;
+}
+
 watch(
     () => newRow.value.itemFk,
     (newItemFk) => {
@@ -820,4 +886,6 @@ es:
     You are going to delete lines of the ticket: Vas a eliminar lineas del ticket
     Add item: Añadir artículo
     Transfer lines: Transferir líneas
+    Item prepared: Artículo preparado
+    This item is already prepared. Do you want to continue?: Este artículo ya esta preparado. Desea continuar?
 </i18n>

From cca255507a593dce4f57fb949f2170dfb2187dd2 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 28 Oct 2024 09:57:25 +0100
Subject: [PATCH 100/207] fix: itemType redirection and fix filters

---
 src/components/common/VnComponent.vue         |  2 +-
 src/components/ui/VnFilterPanel.vue           |  2 +-
 .../ItemType/Card/ItemTypeBasicData.vue       |  0
 .../{ => Item}/ItemType/Card/ItemTypeCard.vue |  4 +-
 .../ItemType/Card/ItemTypeDescriptor.vue      |  0
 .../{ => Item}/ItemType/Card/ItemTypeLog.vue  |  0
 .../ItemType/Card/ItemTypeSummary.vue         |  0
 .../{ => Item}/ItemType/ItemTypeFilter.vue    | 35 +++++++
 .../{ => Item}/ItemType/ItemTypeSearchbar.vue |  1 +
 src/pages/{ => Item}/ItemType/locale/en.yml   |  0
 src/pages/{ => Item}/ItemType/locale/es.yml   |  0
 src/pages/Item/ItemTypeCreate.vue             | 98 -------------------
 src/pages/Item/ItemTypeList.vue               | 58 +++++++++--
 .../Ticket/Card/TicketDescriptorMenu.vue      |  1 -
 src/router/modules/item.js                    |  8 --
 src/router/modules/itemType.js                |  9 +-
 16 files changed, 93 insertions(+), 125 deletions(-)
 rename src/pages/{ => Item}/ItemType/Card/ItemTypeBasicData.vue (100%)
 rename src/pages/{ => Item}/ItemType/Card/ItemTypeCard.vue (75%)
 rename src/pages/{ => Item}/ItemType/Card/ItemTypeDescriptor.vue (100%)
 rename src/pages/{ => Item}/ItemType/Card/ItemTypeLog.vue (100%)
 rename src/pages/{ => Item}/ItemType/Card/ItemTypeSummary.vue (100%)
 rename src/pages/{ => Item}/ItemType/ItemTypeFilter.vue (57%)
 rename src/pages/{ => Item}/ItemType/ItemTypeSearchbar.vue (94%)
 rename src/pages/{ => Item}/ItemType/locale/en.yml (100%)
 rename src/pages/{ => Item}/ItemType/locale/es.yml (100%)
 delete mode 100644 src/pages/Item/ItemTypeCreate.vue

diff --git a/src/components/common/VnComponent.vue b/src/components/common/VnComponent.vue
index bd25c787c..580bcf348 100644
--- a/src/components/common/VnComponent.vue
+++ b/src/components/common/VnComponent.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed, defineModel } from 'vue';
+import { computed } from 'vue';
 
 const model = defineModel(undefined, { required: true });
 const $props = defineProps({
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 43d634ad9..e902214b2 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -37,7 +37,7 @@ const $props = defineProps({
     },
     hiddenTags: {
         type: Array,
-        default: () => ['filter', 'search', 'or', 'and'],
+        default: () => ['filter', 'or', 'and'],
     },
     customTags: {
         type: Array,
diff --git a/src/pages/ItemType/Card/ItemTypeBasicData.vue b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
similarity index 100%
rename from src/pages/ItemType/Card/ItemTypeBasicData.vue
rename to src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
diff --git a/src/pages/ItemType/Card/ItemTypeCard.vue b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
similarity index 75%
rename from src/pages/ItemType/Card/ItemTypeCard.vue
rename to src/pages/Item/ItemType/Card/ItemTypeCard.vue
index 9daec7921..0a2706a07 100644
--- a/src/pages/ItemType/Card/ItemTypeCard.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
@@ -1,7 +1,7 @@
 <script setup>
 import VnCard from 'components/common/VnCard.vue';
-import ItemTypeDescriptor from 'src/pages/ItemType/Card/ItemTypeDescriptor.vue';
-import ItemTypeFilter from 'src/pages/ItemType/ItemTypeFilter.vue';
+import ItemTypeDescriptor from 'src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue';
+import ItemTypeFilter from 'src/pages/Item/ItemType/ItemTypeFilter.vue';
 import ItemTypeSearchbar from '../ItemTypeSearchbar.vue';
 </script>
 <template>
diff --git a/src/pages/ItemType/Card/ItemTypeDescriptor.vue b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
similarity index 100%
rename from src/pages/ItemType/Card/ItemTypeDescriptor.vue
rename to src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
diff --git a/src/pages/ItemType/Card/ItemTypeLog.vue b/src/pages/Item/ItemType/Card/ItemTypeLog.vue
similarity index 100%
rename from src/pages/ItemType/Card/ItemTypeLog.vue
rename to src/pages/Item/ItemType/Card/ItemTypeLog.vue
diff --git a/src/pages/ItemType/Card/ItemTypeSummary.vue b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
similarity index 100%
rename from src/pages/ItemType/Card/ItemTypeSummary.vue
rename to src/pages/Item/ItemType/Card/ItemTypeSummary.vue
diff --git a/src/pages/ItemType/ItemTypeFilter.vue b/src/pages/Item/ItemType/ItemTypeFilter.vue
similarity index 57%
rename from src/pages/ItemType/ItemTypeFilter.vue
rename to src/pages/Item/ItemType/ItemTypeFilter.vue
index 2a86795c2..f6fb73098 100644
--- a/src/pages/ItemType/ItemTypeFilter.vue
+++ b/src/pages/Item/ItemType/ItemTypeFilter.vue
@@ -12,6 +12,39 @@ const props = defineProps({
 });
 
 const emit = defineEmits(['search']);
+const exprBuilder = (param, value) => {
+    switch (param) {
+        case 'name':
+            return {
+                name: { like: `%${value}%` },
+            };
+        case 'code':
+            return {
+                code: { like: `%${value}%` },
+            };
+        case 'search':
+            if (value) {
+                if (!isNaN(value)) {
+                    return { id: value };
+                } else {
+                    return {
+                        or: [
+                            {
+                                name: {
+                                    like: `%${value}%`,
+                                },
+                            },
+                            {
+                                code: {
+                                    like: `%${value}%`,
+                                },
+                            },
+                        ],
+                    };
+                }
+            }
+    }
+};
 </script>
 
 <template>
@@ -19,6 +52,8 @@ const emit = defineEmits(['search']);
         :data-key="props.dataKey"
         :search-button="true"
         @search="emit('search')"
+        search-url="table"
+        :expr-builder="exprBuilder"
     >
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">
diff --git a/src/pages/ItemType/ItemTypeSearchbar.vue b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
similarity index 94%
rename from src/pages/ItemType/ItemTypeSearchbar.vue
rename to src/pages/Item/ItemType/ItemTypeSearchbar.vue
index 749033d43..87903a517 100644
--- a/src/pages/ItemType/ItemTypeSearchbar.vue
+++ b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
@@ -10,6 +10,7 @@ const { t } = useI18n();
         url="ItemTypes"
         :label="t('Search item type')"
         :info="t('Search itemType by id, name or code')"
+        search-url="table"
     />
 </template>
 <i18n>
diff --git a/src/pages/ItemType/locale/en.yml b/src/pages/Item/ItemType/locale/en.yml
similarity index 100%
rename from src/pages/ItemType/locale/en.yml
rename to src/pages/Item/ItemType/locale/en.yml
diff --git a/src/pages/ItemType/locale/es.yml b/src/pages/Item/ItemType/locale/es.yml
similarity index 100%
rename from src/pages/ItemType/locale/es.yml
rename to src/pages/Item/ItemType/locale/es.yml
diff --git a/src/pages/Item/ItemTypeCreate.vue b/src/pages/Item/ItemTypeCreate.vue
deleted file mode 100644
index 60c037510..000000000
--- a/src/pages/Item/ItemTypeCreate.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-<script setup>
-import { reactive, ref } from 'vue';
-import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
-
-import FetchData from 'components/FetchData.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import FormModel from 'components/FormModel.vue';
-import VnRow from 'components/ui/VnRow.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
-
-const { t } = useI18n();
-const router = useRouter();
-
-const newItemTypeForm = reactive({});
-
-const categoriesOptions = ref([]);
-const temperaturesOptions = ref([]);
-
-const redirectToItemTypeBasicData = (_, { id }) => {
-    router.push({ name: 'ItemTypeBasicData', params: { id } });
-};
-</script>
-
-<template>
-    <FetchData
-        url="ItemCategories"
-        @on-fetch="(data) => (categoriesOptions = data)"
-        :filter="{ order: 'name ASC', fields: ['id', 'name'] }"
-        auto-load
-    />
-    <FetchData
-        url="Temperatures"
-        @on-fetch="(data) => (temperaturesOptions = data)"
-        :filter="{ order: 'name ASC', fields: ['code', 'name'] }"
-        auto-load
-    />
-    <QPage>
-        <VnSubToolbar />
-        <FormModel
-            url-create="ItemTypes"
-            model="itemTypeCreate"
-            :form-initial-data="newItemTypeForm"
-            observe-form-changes
-            @on-data-saved="redirectToItemTypeBasicData"
-        >
-            <template #form="{ data }">
-                <VnRow>
-                    <VnInput v-model="data.code" :label="t('itemType.shared.code')" />
-                    <VnInput v-model="data.name" :label="t('itemType.shared.name')" />
-                </VnRow>
-                <VnRow>
-                    <VnSelect
-                        url="Workers/search"
-                        v-model="data.workerFk"
-                        :label="t('shared.worker')"
-                        sort-by="nickname ASC"
-                        :fields="['id', 'nickname']"
-                        :params="{ departmentCodes: ['shopping'] }"
-                        option-label="nickname"
-                        option-value="id"
-                        hide-selected
-                        ><template #option="scope">
-                            <QItem v-bind="scope.itemProps">
-                                <QItemSection>
-                                    <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
-                                    <QItemLabel caption
-                                        >{{ scope.opt?.nickname }},
-                                        {{ scope.opt?.code }}</QItemLabel
-                                    >
-                                </QItemSection>
-                            </QItem>
-                        </template>
-                    </VnSelect>
-                    <VnSelect
-                        v-model="data.categoryFk"
-                        :label="t('itemType.shared.category')"
-                        :options="categoriesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                    />
-                </VnRow>
-                <VnRow>
-                    <VnSelect
-                        v-model="data.temperatureFk"
-                        :label="t('itemType.shared.temperature')"
-                        :options="temperaturesOptions"
-                        option-value="code"
-                        option-label="name"
-                        hide-selected
-                    />
-                </VnRow>
-            </template>
-        </FormModel>
-    </QPage>
-</template>
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 13dd56a42..149de482d 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -1,13 +1,16 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { ref, computed } from 'vue';
-import ItemTypeSearchbar from '../ItemType/ItemTypeSearchbar.vue';
+import ItemTypeSearchbar from 'src/pages/Item/ItemType/ItemTypeSearchbar.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import FetchData from 'components/FetchData.vue';
+import RightMenu from 'src/components/common/RightMenu.vue';
+import ItemTypeFilter from './ItemType/ItemTypeFilter.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-const ItemCategoriesOptions = ref([]);
+const itemCategoriesOptions = ref([]);
+const temperatureOptions = ref([]);
 
 const columns = computed(() => [
     {
@@ -34,7 +37,6 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        name: 'workerFk',
         label: t('worker'),
         create: true,
         component: 'select',
@@ -45,6 +47,19 @@ const columns = computed(() => [
         },
         cardVisible: true,
         visible: true,
+        columnField: {
+            component: 'userLink',
+            attrs: ({ row }) => {
+                return {
+                    workerId: row?.worker?.id,
+                    name: row.worker?.user?.name,
+                    defaultName: true,
+                };
+            },
+        },
+        columnFilter: {
+            name: 'workerFk',
+        },
     },
     {
         align: 'left',
@@ -53,9 +68,7 @@ const columns = computed(() => [
         create: true,
         component: 'select',
         attrs: {
-            options: ItemCategoriesOptions.value,
-            fields: ['id', 'name'],
-            order: 'name ASC',
+            options: itemCategoriesOptions.value,
         },
         cardVisible: false,
         visible: false,
@@ -67,8 +80,7 @@ const columns = computed(() => [
         create: true,
         component: 'select',
         attrs: {
-            url: 'Temperatures',
-            fields: ['id', 'name'],
+            options: temperatureOptions.value,
         },
         cardVisible: false,
         visible: false,
@@ -80,26 +92,52 @@ const columns = computed(() => [
     <FetchData
         url="ItemCategories"
         :filter="{ fields: ['id', 'name'], order: ['name ASC'] }"
-        @on-fetch="(data) => (ItemCategoriesOptions = data)"
+        @on-fetch="(data) => (itemCategoriesOptions = data)"
         auto-load
     />
+    <FetchData
+        url="Temperatures"
+        :filter="{ fields: ['id', 'name'], order: ['name ASC'] }"
+        @on-fetch="(data) => (temperatureOptions = data)"
+        auto-load
+    />
+    <RightMenu>
+        <template #right-panel>
+            <ItemTypeFilter data-key="ItemTypeList" />
+        </template>
+    </RightMenu>
     <ItemTypeSearchbar />
     <VnTable
         ref="tableRef"
         data-key="ItemTypeList"
-        :url="`ItemTypes`"
+        url="ItemTypes"
         :create="{
             urlCreate: 'ItemTypes',
             title: t('Create ItemTypes'),
             onDataSaved: () => tableRef.reload(),
             formInitialData: {},
         }"
+        :user-filter="{
+            include: {
+                relation: 'worker',
+                scope: {
+                    fields: ['id'],
+                    include: {
+                        relation: 'user',
+                        scope: {
+                            fields: ['id', 'name'],
+                        },
+                    },
+                },
+            },
+        }"
         order="name ASC"
         :columns="columns"
         auto-load
         :right-search="false"
         :is-editable="false"
         :use-model="true"
+        redirect="item/item-type"
     />
 </template>
 
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 834fced87..bf4a1efb4 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -348,7 +348,6 @@ async function hasDocuware() {
 }
 
 async function uploadDocuware(force) {
-    console.log('force: ', force);
     if (!force)
         return quasar
             .dialog({
diff --git a/src/router/modules/item.js b/src/router/modules/item.js
index 2838c3be7..0f810434c 100644
--- a/src/router/modules/item.js
+++ b/src/router/modules/item.js
@@ -97,14 +97,6 @@ export default {
                     },
                     component: () => import('src/pages/Item/ItemTypeList.vue'),
                 },
-                {
-                    path: 'item-type-list/create',
-                    name: 'ItemTypeCreate',
-                    meta: {
-                        title: 'itemTypeCreate',
-                    },
-                    component: () => import('src/pages/Item/ItemTypeCreate.vue'),
-                },
             ],
         },
         {
diff --git a/src/router/modules/itemType.js b/src/router/modules/itemType.js
index 0fd3797e6..1ceecd4cc 100644
--- a/src/router/modules/itemType.js
+++ b/src/router/modules/itemType.js
@@ -18,7 +18,7 @@ export default {
         {
             name: 'ItemTypeCard',
             path: ':id',
-            component: () => import('src/pages/ItemType/Card/ItemTypeCard.vue'),
+            component: () => import('src/pages/Item/ItemType/Card/ItemTypeCard.vue'),
             redirect: { name: 'ItemTypeSummary' },
             children: [
                 {
@@ -28,7 +28,7 @@ export default {
                         title: 'summary',
                     },
                     component: () =>
-                        import('src/pages/ItemType/Card/ItemTypeSummary.vue'),
+                        import('src/pages/Item/ItemType/Card/ItemTypeSummary.vue'),
                 },
                 {
                     name: 'ItemTypeBasicData',
@@ -38,7 +38,7 @@ export default {
                         icon: 'vn:settings',
                     },
                     component: () =>
-                        import('src/pages/ItemType/Card/ItemTypeBasicData.vue'),
+                        import('src/pages/Item/ItemType/Card/ItemTypeBasicData.vue'),
                 },
                 {
                     path: 'log',
@@ -47,7 +47,8 @@ export default {
                         title: 'log',
                         icon: 'vn:History',
                     },
-                    component: () => import('src/pages/ItemType/Card/ItemTypeLog.vue'),
+                    component: () =>
+                        import('src/pages/Item/ItemType/Card/ItemTypeLog.vue'),
                 },
             ],
         },

From bc8a87b267921f339843e6639de268a55a482938 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 28 Oct 2024 09:58:07 +0100
Subject: [PATCH 101/207] chore: typo

---
 src/components/ui/VnFilterPanel.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index e902214b2..43d634ad9 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -37,7 +37,7 @@ const $props = defineProps({
     },
     hiddenTags: {
         type: Array,
-        default: () => ['filter', 'or', 'and'],
+        default: () => ['filter', 'search', 'or', 'and'],
     },
     customTags: {
         type: Array,

From df1c123444e577336fed9c5b1c17d093ecf37d68 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 10:39:45 +0100
Subject: [PATCH 102/207] feat: refs #7193 modified parking to use the scope
 and corrected small errors

---
 src/i18n/locale/en.yml                       | 3 +--
 src/i18n/locale/es.yml                       | 3 +--
 src/pages/Parking/Card/ParkingCard.vue       | 6 ------
 src/pages/Parking/Card/ParkingDescriptor.vue | 1 +
 src/pages/Parking/ParkingList.vue            | 4 +---
 5 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index c1748c8ff..24fda7aff 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -278,6 +278,7 @@ globals:
         RouteExtendedList: Router
         wasteRecalc: Waste recaclulate
         operator: Operator
+        parking: Parking
     supplier: Supplier
     created: Created
     worker: Worker
@@ -663,8 +664,6 @@ parking:
     sector: Sector
     row: Row
     column: Column
-    pageTitles:
-        parking: Parking
     searchBar:
         info: You can search by parking code
         label: Search parking...
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index bd414a793..1571f7b92 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -282,6 +282,7 @@ globals:
         medical: Mutua
         wasteRecalc: Recalcular mermas
         operator: Operario
+        parking: Parking
     supplier: Proveedor
     created: Fecha creación
     worker: Trabajador
@@ -710,8 +711,6 @@ parking:
     pickingOrder: Orden de recogida
     row: Fila
     column: Columna
-    pageTitles:
-        parking: Parking
     searchBar:
         info: Puedes buscar por código de parking
         label: Buscar parking...
diff --git a/src/pages/Parking/Card/ParkingCard.vue b/src/pages/Parking/Card/ParkingCard.vue
index ad37eb630..337106986 100644
--- a/src/pages/Parking/Card/ParkingCard.vue
+++ b/src/pages/Parking/Card/ParkingCard.vue
@@ -2,17 +2,11 @@
 import VnCard from 'components/common/VnCard.vue';
 import ParkingDescriptor from 'pages/Parking/Card/ParkingDescriptor.vue';
 import ParkingFilter from 'pages/Parking/ParkingFilter.vue';
-
-const filter = {
-    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
-    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
-};
 </script>
 <template>
     <VnCard
         data-key="Parking"
         base-url="Parkings"
-        :filter="filter"
         :descriptor="ParkingDescriptor"
         :filter-panel="ParkingFilter"
         search-data-key="ParkingList"
diff --git a/src/pages/Parking/Card/ParkingDescriptor.vue b/src/pages/Parking/Card/ParkingDescriptor.vue
index b57bfb0cc..d36ea16fc 100644
--- a/src/pages/Parking/Card/ParkingDescriptor.vue
+++ b/src/pages/Parking/Card/ParkingDescriptor.vue
@@ -29,6 +29,7 @@ const filter = {
         :url="`Parkings/${entityId}`"
         title="code"
         :filter="filter"
+        :to-module="{ name: 'ParkingList' }"
     >
         <template #body="{ entity }">
             <VnLv :label="t('globals.code')" :value="entity.code" />
diff --git a/src/pages/Parking/ParkingList.vue b/src/pages/Parking/ParkingList.vue
index b6f4e8146..109613383 100644
--- a/src/pages/Parking/ParkingList.vue
+++ b/src/pages/Parking/ParkingList.vue
@@ -22,7 +22,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 
 const filter = {
     fields: ['id', 'sectorFk', 'code', 'pickingOrder'],
-    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
 };
 
 function exprBuilder(param, value) {
@@ -55,10 +54,9 @@ function exprBuilder(param, value) {
             <VnPaginate
                 data-key="ParkingList"
                 url="Parkings"
-                :filter="filter"
+                :user-filter="filter"
                 :expr-builder="exprBuilder"
                 :limit="20"
-                auto-load
                 order="code"
             >
                 <template #body="{ rows }">

From 2cde8501327333e6f259f8e7d1bea88e1d5be1a9 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 11:37:32 +0100
Subject: [PATCH 103/207] fix: refs #7193 fixed e2e test

---
 test/cypress/integration/parking/parkingList.spec.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/cypress/integration/parking/parkingList.spec.js b/test/cypress/integration/parking/parkingList.spec.js
index b78a660d1..f1efaa375 100644
--- a/test/cypress/integration/parking/parkingList.spec.js
+++ b/test/cypress/integration/parking/parkingList.spec.js
@@ -1,5 +1,6 @@
 /// <reference types="cypress" />
 describe('ParkingList', () => {
+    const searchbar = '#searchbar input';
     const firstCard = '.q-card:nth-child(1)';
     const firstChipId =
         ':nth-child(1) > :nth-child(1) > .justify-between > .flex > .q-chip > .q-chip__content';
@@ -14,6 +15,7 @@ describe('ParkingList', () => {
     });
 
     it('should redirect on clicking a parking', () => {
+        cy.get(searchbar).type('{enter}');
         cy.get(firstChipId)
             .invoke('text')
             .then((content) => {
@@ -24,6 +26,7 @@ describe('ParkingList', () => {
     });
 
     it('should open the details', () => {
+        cy.get(searchbar).type('{enter}');
         cy.get(firstDetailBtn).click();
         cy.get(summaryHeader).contains('Basic data');
     });

From 9347bb1ef5384aee2e84f73afa3d3b48b449b500 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 11:44:49 +0100
Subject: [PATCH 104/207] refactor: refs #7970 refactored VnConfirm to emit
 events

---
 src/components/ui/VnConfirm.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index 0fbc55cfb..c5d2b43f5 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -30,7 +30,7 @@ const props = defineProps({
     },
 });
 
-defineEmits([...useDialogPluginComponent.emits]);
+defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
 
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();

From 17b1921af6603db83744efc8095c6dbc4eb34141 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 12:21:26 +0100
Subject: [PATCH 105/207] feat: added composable to confirm orders

---
 src/composables/confirmOrder.js       | 22 +++++++++++++++++++++
 src/pages/Order/Card/OrderLines.vue   | 28 +++++++++++++--------------
 src/pages/Order/Card/OrderSummary.vue | 21 +++++++++-----------
 3 files changed, 44 insertions(+), 27 deletions(-)
 create mode 100644 src/composables/confirmOrder.js

diff --git a/src/composables/confirmOrder.js b/src/composables/confirmOrder.js
new file mode 100644
index 000000000..33e05a1d7
--- /dev/null
+++ b/src/composables/confirmOrder.js
@@ -0,0 +1,22 @@
+import axios from 'axios';
+import { useQuasar } from 'quasar';
+import { useI18n } from 'vue-i18n';
+
+export function confirmOrder() {
+    const quasar = useQuasar();
+    const { t } = useI18n();
+
+    async function confirm(route) {
+        const { data } = await axios.post(`Orders/${route}/confirm`);
+        if (data) {
+            quasar.notify({
+                message: t('globals.confirm'),
+                type: 'positive',
+            });
+            return data;
+        }
+        return null;
+    }
+
+    return { confirm };
+}
diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index ee883b73a..90586dc15 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -6,6 +6,7 @@ import { useQuasar } from 'quasar';
 import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import { useArrayData } from 'composables/useArrayData';
+import { confirmOrder } from 'composables/confirmOrder';
 import { toCurrency, toDate } from 'src/filters';
 
 import VnConfirm from 'components/ui/VnConfirm.vue';
@@ -31,7 +32,7 @@ const orderSummary = ref({
 });
 const getTotalRef = ref();
 const getVATRef = ref();
-
+const { confirm } = confirmOrder();
 const lineFilter = ref({
     include: [
         {
@@ -204,20 +205,17 @@ async function remove(item) {
     getVATRef.value.fetch();
 }
 
-async function confirmOrder() {
-    await axios.post(`Orders/${route.params.id}/confirm`);
-    quasar.notify({
-        message: t('globals.confirm'),
-        type: 'positive',
-    });
-    router.push({
-        name: 'TicketList',
-        query: {
-            table: JSON.stringify({ clientFk: descriptorData.store.data.clientFk }),
-        },
-    });
+async function handleConfirm() {
+    const result = await confirm(route.params.id);
+    if (result) {
+        router.push({
+            name: 'TicketList',
+            query: {
+                table: JSON.stringify({ clientFk: descriptorData.store.data.clientFk }),
+            },
+        });
+    }
 }
-
 watch(
     () => router.currentRoute.value.params.id,
     () => {
@@ -314,7 +312,7 @@ watch(
         </template>
     </VnTable>
     <QPageSticky :offset="[20, 20]" v-if="!order?.isConfirmed" style="z-index: 2">
-        <QBtn fab icon="check" color="primary" @click="confirmOrder()" />
+        <QBtn fab icon="check" color="primary" @click="handleConfirm()" />
         <QTooltip>
             {{ t('confirm') }}
         </QTooltip>
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index 9bc89ad28..3669fe8d8 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -2,10 +2,9 @@
 import { computed, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { useQuasar } from 'quasar';
-import axios from 'axios';
 import { dashIfEmpty, toCurrency, toDateHourMinSec } from 'src/filters';
 import { useArrayData } from 'composables/useArrayData';
+import { confirmOrder } from 'composables/confirmOrder';
 import VnLv from 'components/ui/VnLv.vue';
 import CardSummary from 'components/ui/CardSummary.vue';
 import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
@@ -25,8 +24,8 @@ const $props = defineProps({
 
 const entityId = computed(() => $props.id || route.params.id);
 const summary = ref();
-const quasar = useQuasar();
 const descriptorData = useArrayData('orderData');
+const { confirm } = confirmOrder();
 const detailsColumns = ref([
     {
         name: 'item',
@@ -56,14 +55,12 @@ const detailsColumns = ref([
     },
 ]);
 
-async function confirmOrder() {
-    await axios.post(`Orders/${route.params.id}/confirm`);
-    quasar.notify({
-        message: t('globals.confirm'),
-        type: 'positive',
-    });
-    summary.value.fetch({});
-    descriptorData.fetch({});
+async function handleConfirm() {
+    const result = await confirm(route.params.id);
+    if (result) {
+        summary.value.fetch({});
+        descriptorData.fetch({});
+    }
 }
 </script>
 
@@ -84,7 +81,7 @@ async function confirmOrder() {
                     text-color="white"
                     :disabled="isConfirmed"
                     :label="t('order.summary.confirm')"
-                    @click="confirmOrder()"
+                    @click="handleConfirm()"
                 >
                     <QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
                 </QBtn>

From 3d4ca2bc672a2375a14df8c2f2918b137839ffef Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 12:45:13 +0100
Subject: [PATCH 106/207] refactor: refs #7970 added emit

---
 src/components/ui/VnConfirm.vue | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index c5d2b43f5..ec9d0f48b 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -30,7 +30,7 @@ const props = defineProps({
     },
 });
 
-defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
+const emit = defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
 
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();
@@ -55,6 +55,7 @@ async function confirm() {
 }
 
 function cancel() {
+    emit('cancel');
     onDialogCancel();
 }
 </script>

From cab5a165d2acb6c4e5d92859e5ed96611029d938 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 28 Oct 2024 12:59:25 +0100
Subject: [PATCH 107/207] refactor: changed confirmOrder directory

---
 src/{ => pages/Order}/composables/confirmOrder.js | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename src/{ => pages/Order}/composables/confirmOrder.js (100%)

diff --git a/src/composables/confirmOrder.js b/src/pages/Order/composables/confirmOrder.js
similarity index 100%
rename from src/composables/confirmOrder.js
rename to src/pages/Order/composables/confirmOrder.js

From f2803a63136a9478e492d112d4f6f1b6d16b5c73 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 28 Oct 2024 13:08:19 +0100
Subject: [PATCH 108/207] fix: refs #7283 item filters

---
 src/pages/Item/ItemList.vue    | 35 +++++++++++++++++++++-------------
 src/pages/Item/ItemRequest.vue | 24 +++++++++++++++++++++++
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index cca5560fe..c9422a0fe 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -40,6 +40,12 @@ const itemFilter = {
                 fields: ['id', 'name'],
             },
         },
+        {
+            relation: 'production',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
     ],
 };
 const columns = computed(() => [
@@ -161,19 +167,13 @@ const columns = computed(() => [
         name: 'intrastat',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'Intrastats',
-            optionValue: 'description',
-            optionLabel: 'description',
-        },
         columnFilter: {
-            name: 'description',
+            name: 'intrastat',
             attrs: {
                 url: 'Intrastats',
                 optionValue: 'description',
                 optionLabel: 'description',
             },
-            alias: 'intr',
         },
         columnField: {
             component: null,
@@ -211,14 +211,19 @@ const columns = computed(() => [
         label: t('item.list.userName'),
         name: 'userName',
         align: 'left',
+        component: 'select',
         columnFilter: {
             name: 'workerFk',
             attrs: {
-                url: 'Users',
+                url: 'VnUsers',
                 optionValue: 'id',
-                optionLabel: 'userName',
+                optionLabel: 'nickname',
             },
         },
+
+        columnField: {
+            component: null,
+        },
     },
     {
         label: t('item.list.weightByPiece'),
@@ -255,9 +260,13 @@ const columns = computed(() => [
         name: 'producer',
         align: 'left',
         component: 'select',
-        attrs: {
-            url: 'Producers',
-            fields: ['id', 'name'],
+        columnFilter: {
+            name: 'producerFk',
+            attrs: {
+                url: 'Producers',
+                optionValue: 'id',
+                optionLabel: 'name',
+            },
         },
         columnField: {
             component: null,
@@ -331,7 +340,7 @@ const columns = computed(() => [
         <template #column-userName="{ row }">
             <span class="link" @click.stop>
                 {{ row.userName }}
-                <WorkerDescriptorProxy :id="row.buyerFk" />
+                <WorkerDescriptorProxy :id="row.workerFk" />
             </span>
         </template>
         <template #column-description="{ row }">
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 450031a0e..7a737dd71 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -70,6 +70,18 @@ const columns = computed(() => [
     {
         label: t('item.buyRequest.requester'),
         name: 'requesterName',
+        component: 'select',
+        columnFilter: {
+            name: 'requesterFk',
+            attrs: {
+                url: 'VnUsers',
+                optionValue: 'id',
+                optionLabel: 'nickname',
+            },
+        },
+        columnField: {
+            component: null,
+        },
         columnClass: 'shrink',
     },
     {
@@ -88,6 +100,18 @@ const columns = computed(() => [
         label: t('item.buyRequest.attender'),
         name: 'attenderName',
         align: 'left',
+        component: 'select',
+        columnFilter: {
+            name: 'attenderFk',
+            attrs: {
+                url: 'VnUsers',
+                optionValue: 'id',
+                optionLabel: 'nickname',
+            },
+        },
+        columnField: {
+            component: null,
+        },
         columnClass: 'shrink',
     },
     {

From 965c2f7b20bce7ce702fddb758654b810d94e121 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 28 Oct 2024 13:16:51 +0100
Subject: [PATCH 109/207] fix: refs #7283 preview

---
 src/pages/Item/ItemList.vue    | 2 +-
 src/pages/Item/ItemRequest.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index c9422a0fe..a6873d10c 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -215,7 +215,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'workerFk',
             attrs: {
-                url: 'VnUsers',
+                url: 'VnUsers/preview',
                 optionValue: 'id',
                 optionLabel: 'nickname',
             },
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 7a737dd71..4122b0c12 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -104,7 +104,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'attenderFk',
             attrs: {
-                url: 'VnUsers',
+                url: 'VnUsers/preview',
                 optionValue: 'id',
                 optionLabel: 'nickname',
             },

From d252f6d2a3deb600cc0290a5892c26b614decc76 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 28 Oct 2024 13:22:33 +0100
Subject: [PATCH 110/207] fix: refs #7283 fix preview

---
 src/pages/Item/ItemRequest.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 4122b0c12..36da0368b 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -74,7 +74,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'requesterFk',
             attrs: {
-                url: 'VnUsers',
+                url: 'VnUsers/preview',
                 optionValue: 'id',
                 optionLabel: 'nickname',
             },

From a1105f2ef19b15eb3cc54891b737d4495b20b8a9 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 13:24:46 +0100
Subject: [PATCH 111/207] feat: refs #7524 add front test

---
 .../pages/Tickets/TicketAdvance.spec.js       | 116 ++++++++++++++++++
 test/vitest/helper.js                         |   2 +
 2 files changed, 118 insertions(+)
 create mode 100644 test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js

diff --git a/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
new file mode 100644
index 000000000..6fae2788e
--- /dev/null
+++ b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
@@ -0,0 +1,116 @@
+import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest';
+import { createWrapper, axios } from 'app/test/vitest/helper';
+import TicketAdvance from 'pages/Ticket/TicketAdvance.vue';
+import { Notify } from 'quasar';
+
+describe('TicketAdvance', () => {
+    let wrapper;
+    let vm;
+
+    beforeAll(() => {
+        vi.spyOn(axios, 'get').mockImplementation(() => ({ data: [] }));
+        wrapper = createWrapper(TicketAdvance);
+        vm = wrapper.vm;
+        // vm.vnTableRef.value = { reload: vi.fn(), params: {} };
+    });
+    beforeEach(() => {
+        Notify.create = vi.fn();
+    });
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
+
+    describe('requestComponentUpdate()', () => {
+        const mockTicket = {
+            futureId: 1,
+            futureClientFk: 1,
+            nickname: 'test',
+            futureAddressFk: 1,
+            futureAgencyModeFk: 1,
+            futureWarehouseFk: 1,
+            futureCompanyFk: 1,
+            landed: '2023-01-01',
+            zoneFk: 1,
+        };
+        const mockParams = {
+            clientFk: 1,
+            nickname: 'test',
+            agencyModeFk: 1,
+            addressFk: 1,
+            zoneFk: 1,
+            warehouseFk: 1,
+            companyFk: 1,
+            landed: '2023-01-01',
+            isDeleted: false,
+            isWithoutNegatives: false,
+            newTicket: undefined,
+            keepPrice: true,
+        };
+        const queryResult = 'tickets/1/componentUpdate';
+
+        it('should return query and params when ticket has no landed', async () => {
+            const mockLanded = { landed: '2023-01-01', zoneFk: 1 };
+            vi.spyOn(vm, 'getLanded').mockResolvedValue(mockLanded);
+
+            const { query, params } = await vm.requestComponentUpdate(mockTicket, false);
+
+            expect(query).toBe(queryResult);
+            expect(params).toEqual(mockParams);
+        });
+
+        it('should return query and params when ticket has landed', async () => {
+            const { query, params } = await vm.requestComponentUpdate(mockTicket, false);
+
+            expect(query).toBe(queryResult);
+            expect(params).toEqual(mockParams);
+        });
+    });
+
+    describe('moveTicketsAdvance()', () => {
+        it('should move tickets and notify success', async () => {
+            const tickets = [
+                {
+                    id: 1,
+                    futureId: 2,
+                    futureShipped: '2023-01-01',
+                    shipped: '2023-01-02',
+                    workerFk: 1,
+                },
+                {
+                    id: 2,
+                    futureId: 3,
+                    futureShipped: '2023-01-01',
+                    shipped: '2023-01-02',
+                    workerFk: 1,
+                },
+            ];
+            vm.selectedTickets.value = tickets;
+            vi.spyOn(axios, 'post').mockResolvedValue({});
+            await vm.moveTicketsAdvance();
+
+            expect(axios.post).toHaveBeenCalledOnce('Tickets/merge', {
+                tickets: [
+                    {
+                        originId: 2,
+                        destinationId: 1,
+                        originShipped: '2023-01-01',
+                        destinationShipped: '2023-01-02',
+                        workerFk: 1,
+                    },
+                    {
+                        originId: 3,
+                        destinationId: 2,
+                        originShipped: '2023-01-01',
+                        destinationShipped: '2023-01-02',
+                        workerFk: 1,
+                    },
+                ],
+            });
+            expect(Notify.create).toHaveBeenCalledWith({
+                type: 'positive',
+                message: 'advanceTickets.moveTicketSuccess',
+            });
+            expect(vm.selectedTickets).toEqual([]);
+        });
+    });
+});
diff --git a/test/vitest/helper.js b/test/vitest/helper.js
index e201535ec..4bfae5dc8 100644
--- a/test/vitest/helper.js
+++ b/test/vitest/helper.js
@@ -70,8 +70,10 @@ class FormDataMock {
         vi.fn();
     }
 }
+
 global.FormData = FormDataMock;
 global.URL = class URL {};
+global.Date.vnNew = () => new Date(Date.UTC(2001, 0, 1, 11));
 
 export function createWrapper(component, options) {
     const defaultOptions = {

From 15977357d9c4c3e76d79cd5798ee78a222e367ff Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Mon, 28 Oct 2024 14:11:34 +0100
Subject: [PATCH 112/207] refactor: refs #7266 Changed method name

---
 src/pages/Entry/EntryBuysTableDialog.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Entry/EntryBuysTableDialog.vue b/src/pages/Entry/EntryBuysTableDialog.vue
index 0f9be6298..23a6a0021 100644
--- a/src/pages/Entry/EntryBuysTableDialog.vue
+++ b/src/pages/Entry/EntryBuysTableDialog.vue
@@ -121,7 +121,7 @@ const entriesTableColumns = computed(() => [
                                         :loading="isLoading"
                                         @click="
                                             openReport(
-                                                `Entries/${props.row.id}/buy-label`
+                                                `Entries/${props.row.id}/buy-label-supplier`
                                             )
                                         "
                                         unelevated

From 934b32092bb27eebcbbd298674bb5e5f7e832515 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 14:21:03 +0100
Subject: [PATCH 113/207] chore: refs #7524 fix test

---
 .../pages/Tickets/TicketAdvance.spec.js       | 22 +++++++++++--------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
index 6fae2788e..ab1a47544 100644
--- a/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
+++ b/test/vitest/__tests__/pages/Tickets/TicketAdvance.spec.js
@@ -2,6 +2,7 @@ import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vite
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import TicketAdvance from 'pages/Ticket/TicketAdvance.vue';
 import { Notify } from 'quasar';
+import { nextTick } from 'vue';
 
 describe('TicketAdvance', () => {
     let wrapper;
@@ -11,7 +12,8 @@ describe('TicketAdvance', () => {
         vi.spyOn(axios, 'get').mockImplementation(() => ({ data: [] }));
         wrapper = createWrapper(TicketAdvance);
         vm = wrapper.vm;
-        // vm.vnTableRef.value = { reload: vi.fn(), params: {} };
+        vi.spyOn(vm.vnTableRef, 'reload').mockImplementation(() => vi.fn());
+        vm.vnTableRef.value = { params: {} };
     });
     beforeEach(() => {
         Notify.create = vi.fn();
@@ -29,7 +31,7 @@ describe('TicketAdvance', () => {
             futureAgencyModeFk: 1,
             futureWarehouseFk: 1,
             futureCompanyFk: 1,
-            landed: '2023-01-01',
+            landed: '2023-01-02',
             zoneFk: 1,
         };
         const mockParams = {
@@ -40,7 +42,8 @@ describe('TicketAdvance', () => {
             zoneFk: 1,
             warehouseFk: 1,
             companyFk: 1,
-            landed: '2023-01-01',
+            landed: '2023-01-02',
+            shipped: '2023-01-01',
             isDeleted: false,
             isWithoutNegatives: false,
             newTicket: undefined,
@@ -49,7 +52,10 @@ describe('TicketAdvance', () => {
         const queryResult = 'tickets/1/componentUpdate';
 
         it('should return query and params when ticket has no landed', async () => {
-            const mockLanded = { landed: '2023-01-01', zoneFk: 1 };
+            vm.vnTableRef.params.dateToAdvance = '2023-01-01';
+            await nextTick();
+
+            const mockLanded = { landed: '2023-01-02', zoneFk: 1 };
             vi.spyOn(vm, 'getLanded').mockResolvedValue(mockLanded);
 
             const { query, params } = await vm.requestComponentUpdate(mockTicket, false);
@@ -84,7 +90,7 @@ describe('TicketAdvance', () => {
                     workerFk: 1,
                 },
             ];
-            vm.selectedTickets.value = tickets;
+            vm.selectedTickets = tickets;
             vi.spyOn(axios, 'post').mockResolvedValue({});
             await vm.moveTicketsAdvance();
 
@@ -106,10 +112,8 @@ describe('TicketAdvance', () => {
                     },
                 ],
             });
-            expect(Notify.create).toHaveBeenCalledWith({
-                type: 'positive',
-                message: 'advanceTickets.moveTicketSuccess',
-            });
+            expect(vm.vnTableRef.reload).toHaveBeenCalled();
+            expect(Notify.create).toHaveBeenCalled();
             expect(vm.selectedTickets).toEqual([]);
         });
     });

From d5639471cf358c89c9dfb28b3f3b9eb11b2d4a23 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 15:40:36 +0100
Subject: [PATCH 114/207] feat: refs #8078 add tests

---
 .../__tests__/components/VnTable.spec.js      | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 test/vitest/__tests__/components/VnTable.spec.js

diff --git a/test/vitest/__tests__/components/VnTable.spec.js b/test/vitest/__tests__/components/VnTable.spec.js
new file mode 100644
index 000000000..d11c2b6c3
--- /dev/null
+++ b/test/vitest/__tests__/components/VnTable.spec.js
@@ -0,0 +1,47 @@
+import { describe, expect, it, beforeAll, beforeEach } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+
+describe('VnTable', () => {
+    let wrapper;
+    let vm;
+
+    beforeAll(() => {
+        wrapper = createWrapper(VnTable, {
+            propsData: {
+                columns: [],
+            },
+        });
+        vm = wrapper.vm;
+    });
+
+    beforeEach(() => (vm.selected = []));
+
+    describe('handleSelection()', () => {
+        const rows = [{ $index: 0 }, { $index: 1 }, { $index: 2 }];
+        const selectedRows = [{ $index: 1 }];
+        it('should add rows to selected when shift key is pressed and rows are added', () => {
+            vm.handleSelection(
+                { evt: { shiftKey: true }, added: true, rows: selectedRows },
+                rows
+            );
+            expect(vm.selected).toEqual([{ $index: 0 }, { $index: 1 }]);
+        });
+
+        it('should not add rows to selected when shift key is not pressed', () => {
+            vm.handleSelection(
+                { evt: { shiftKey: false }, added: true, rows: selectedRows },
+                rows
+            );
+            expect(vm.selected).toEqual([]);
+        });
+
+        it('should not add rows to selected when rows are not added', () => {
+            vm.handleSelection(
+                { evt: { shiftKey: true }, added: false, rows: selectedRows },
+                rows
+            );
+            expect(vm.selected).toEqual([]);
+        });
+    });
+});

From 7e3e194b465f0ba3abfa4a57aa762f58f63d24c1 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 16:19:13 +0100
Subject: [PATCH 115/207] fix: refs #8078 e2e #7970

---
 src/components/ui/VnConfirm.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index ec9d0f48b..89726c891 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -31,9 +31,9 @@ const props = defineProps({
 });
 
 const emit = defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
-
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();
+defineExpose({ dialogRef });
 
 const title = props.title || t('Confirm');
 const message =

From 57488503aa1c9494586f6bf3c1b6b7860e7ccf6b Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 16:19:24 +0100
Subject: [PATCH 116/207] fix: refs #8078 e2e #7970

---
 src/pages/Ticket/Card/TicketDescriptorMenu.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index bf4a1efb4..8efd0f1e1 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -659,7 +659,7 @@ async function uploadDocuware(force) {
             </QList>
         </QMenu>
     </QItem>
-    <QItem @click="$refs.weightDialog.show()" v-ripple clickable>
+    <QItem @click="$refs.weightDialog.dialogRef.show()" v-ripple clickable>
         <QItemSection avatar>
             <QIcon name="weight" />
         </QItemSection>

From 1e16e3312e3e22d0c6170195acd9c3e4670e5b5a Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 28 Oct 2024 16:21:00 +0100
Subject: [PATCH 117/207] fix: refs #8078 improve cy command

---
 src/components/ui/CardDescriptor.vue                     | 1 +
 test/cypress/integration/ticket/ticketDescriptor.spec.js | 4 ++++
 test/cypress/support/commands.js                         | 2 +-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index 7f35f0a28..83af77442 100644
--- a/src/components/ui/CardDescriptor.vue
+++ b/src/components/ui/CardDescriptor.vue
@@ -167,6 +167,7 @@ const toModule = computed(() =>
                     icon="more_vert"
                     round
                     size="md"
+                    data-cy="descriptor-more-opts"
                 >
                     <QTooltip>
                         {{ t('components.cardDescriptor.moreOptions') }}
diff --git a/test/cypress/integration/ticket/ticketDescriptor.spec.js b/test/cypress/integration/ticket/ticketDescriptor.spec.js
index 0ba2723a2..cd9f288f5 100644
--- a/test/cypress/integration/ticket/ticketDescriptor.spec.js
+++ b/test/cypress/integration/ticket/ticketDescriptor.spec.js
@@ -14,6 +14,8 @@ describe('Ticket descriptor', () => {
 
     it('should clone the ticket without warehouse', () => {
         cy.visit('/#/ticket/1/summary');
+        cy.intercept('GET', /\/api\/Tickets\/\d/).as('ticket');
+        cy.wait('@ticket');
         cy.openActionsDescriptor();
         cy.contains(listItem, toCloneOpt).click();
         cy.clickConfirm();
@@ -28,6 +30,8 @@ describe('Ticket descriptor', () => {
 
     it('should set the weight of the ticket', () => {
         cy.visit('/#/ticket/10/summary');
+        cy.intercept('GET', /\/api\/Tickets\/\d/).as('ticket');
+        cy.wait('@ticket');
         cy.openActionsDescriptor();
         cy.contains(listItem, setWeightOpt).click();
         cy.intercept('POST', /\/api\/Tickets\/\d+\/setWeight/).as('weight');
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 76bdefd27..1e9ca93b5 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -261,7 +261,7 @@ Cypress.Commands.add('openActionDescriptor', (opt) => {
 });
 
 Cypress.Commands.add('openActionsDescriptor', () => {
-    cy.get('.header > :nth-child(3) > .q-btn__content > .q-icon').click();
+    cy.get('[data-cy="descriptor-more-opts"]').click();
 });
 
 Cypress.Commands.add('openUserPanel', () => {

From 0de4dfd4f8bcf5f55a56a48c5a89fa8f702745e9 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 02:15:02 +0100
Subject: [PATCH 118/207] feat: apply changes for customerModule

---
 src/components/ui/VnLinkMail.vue              |  16 +++
 src/pages/Customer/Card/CustomerAddress.vue   |   2 +-
 src/pages/Customer/Card/CustomerBalance.vue   | 120 +++++++++++-------
 src/pages/Customer/Card/CustomerCredits.vue   |   4 +-
 .../Customer/Card/CustomerDescriptor.vue      |  38 +++++-
 .../Customer/Card/CustomerDescriptorMenu.vue  |  28 ----
 .../Customer/Card/CustomerFiscalData.vue      |   7 +-
 src/pages/Customer/Card/CustomerGreuges.vue   |   5 +
 .../Customer/Card/CustomerRecoveries.vue      |   1 +
 src/pages/Customer/Card/CustomerSummary.vue   |  26 +++-
 src/pages/Customer/CustomerList.vue           |   6 +-
 .../components/CustomerAddressCreate.vue      |  15 ++-
 .../components/CustomerNewPayment.vue         |  10 +-
 .../components/CustomerSummaryTable.vue       |  14 +-
 .../Customer/composables/getClientRisk.js     |  12 ++
 .../integration/client/clientList.spec.js     |  19 ++-
 test/cypress/support/commands.js              |  33 +++--
 17 files changed, 251 insertions(+), 105 deletions(-)
 create mode 100644 src/components/ui/VnLinkMail.vue
 create mode 100644 src/pages/Customer/composables/getClientRisk.js

diff --git a/src/components/ui/VnLinkMail.vue b/src/components/ui/VnLinkMail.vue
new file mode 100644
index 000000000..a54f463f5
--- /dev/null
+++ b/src/components/ui/VnLinkMail.vue
@@ -0,0 +1,16 @@
+<script setup>
+defineProps({ email: { type: [String], default: null } });
+</script>
+<template>
+    <QBtn
+        v-if="email"
+        flat
+        round
+        icon="email"
+        size="sm"
+        color="primary"
+        padding="none"
+        :href="`mailto:${email}`"
+        @click.stop
+    />
+</template>
diff --git a/src/pages/Customer/Card/CustomerAddress.vue b/src/pages/Customer/Card/CustomerAddress.vue
index 166c33e1a..294e49cc8 100644
--- a/src/pages/Customer/Card/CustomerAddress.vue
+++ b/src/pages/Customer/Card/CustomerAddress.vue
@@ -27,7 +27,7 @@ const addressFilter = {
         'isLogifloraAllowed',
         'postalCode',
     ],
-    order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
+    order: ['isDefaultAddress DESC', 'isActive DESC', 'id DESC', 'nickname ASC'],
     include: [
         {
             relation: 'observations',
diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue
index f148194f8..f6fc3eed2 100644
--- a/src/pages/Customer/Card/CustomerBalance.vue
+++ b/src/pages/Customer/Card/CustomerBalance.vue
@@ -5,7 +5,7 @@ import { useRoute } from 'vue-router';
 import { useAcl } from 'src/composables/useAcl';
 import axios from 'axios';
 import { useQuasar } from 'quasar';
-import FetchData from 'components/FetchData.vue';
+import { getClientRisk } from '../composables/getClientRisk';
 
 import { toCurrency, toDate, toDateHourMin } from 'src/filters';
 import { useState } from 'composables/useState';
@@ -16,7 +16,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnInput from 'components/common/VnInput.vue';
 import VnSubToolbar from 'components/ui/VnSubToolbar.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
+import VnFilter from 'components/VnTable/VnFilter.vue';
 
 import CustomerNewPayment from 'src/pages/Customer/components/CustomerNewPayment.vue';
 import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
@@ -25,7 +25,7 @@ const { openConfirmationModal } = useVnConfirm();
 const { sendEmail, openReport } = usePrintService();
 const { t } = useI18n();
 const { hasAny } = useAcl();
-const currentBalance = ref({});
+
 const quasar = useQuasar();
 const route = useRoute();
 const state = useState();
@@ -33,28 +33,53 @@ const stateStore = useStateStore();
 const user = state.getUser();
 
 const clientRisk = ref([]);
-const companies = ref([]);
 const tableRef = ref();
-const companyId = ref(user.value.companyFk);
+const companyId = ref();
+const companyUser = ref(user.value.companyFk);
 const balances = ref([]);
 const vnFilterRef = ref({});
 const filter = computed(() => {
     return {
         clientId: route.params.id,
-        companyId: companyId.value ?? user.value.companyFk,
+        companyId: companyId.value ?? companyUser.value,
     };
 });
 
+const companyFilterColumn = {
+    align: 'left',
+    name: 'companyId',
+    label: t('Company'),
+    component: 'select',
+    attrs: {
+        url: 'Companies',
+        optionLabel: 'code',
+        optionValue: 'id',
+        sortBy: 'code',
+    },
+    columnFilter: {
+        event: {
+            remove: () => (companyId.value = null),
+            'update:modelValue': (newCompanyFk) => {
+                if (!newCompanyFk) return;
+                vnFilterRef.value.addFilter(newCompanyFk);
+                companyUser.value = newCompanyFk;
+            },
+            blur: () => !companyId.value && (companyId.value = companyUser.value),
+        },
+    },
+    visible: false,
+};
+
 const columns = computed(() => [
     {
-        align: 'right',
+        align: 'left',
         name: 'payed',
         label: t('Date'),
         format: ({ payed }) => toDate(payed),
         cardVisible: true,
     },
     {
-        align: 'right',
+        align: 'left',
         name: 'created',
         label: t('Creation date'),
         format: ({ created }) => toDateHourMin(created),
@@ -65,7 +90,12 @@ const columns = computed(() => [
         label: t('Employee'),
         columnField: {
             component: 'userLink',
-            attrs: ({ row }) => ({ workerId: row.workerFk, name: row.userName }),
+            attrs: ({ row }) => {
+                return {
+                    workerId: row.workerFk,
+                    name: row.userName,
+                };
+            },
         },
         cardVisible: true,
     },
@@ -77,13 +107,13 @@ const columns = computed(() => [
         class: 'extend',
     },
     {
-        align: 'right',
+        align: 'left',
         name: 'bankFk',
         label: t('Bank'),
         cardVisible: true,
     },
     {
-        align: 'right',
+        align: 'left',
         name: 'debit',
         label: t('Debit'),
         format: ({ debit }) => debit && toCurrency(debit),
@@ -136,20 +166,37 @@ const columns = computed(() => [
 
 onBeforeMount(() => {
     stateStore.rightDrawer = true;
+    companyId.value = companyUser.value;
 });
 
-async function getCurrentBalance(data) {
-    currentBalance.value[companyId.value] = {
-        amount: 0,
-        code: companies.value.find((c) => c.id === companyId.value)?.code,
+async function getClientRisks() {
+    const filter = {
+        where: { clientFk: route.params.id, companyFk: companyUser.value },
     };
+    const { data } = await getClientRisk(filter);
+    clientRisk.value = data;
+    return clientRisk.value;
+}
 
-    for (const balance of data) {
-        currentBalance.value[balance.companyFk] = {
-            code: balance.company.code,
-            amount: balance.amount,
-        };
+async function getCurrentBalance() {
+    const currentBalance = (await getClientRisks()).find((balance) => {
+        return balance.companyFk === companyId.value;
+    });
+    return currentBalance && currentBalance.amount;
+}
+
+async function onFetch(data) {
+    balances.value = [];
+    for (const [index, balance] of data.entries()) {
+        if (index === 0) {
+            balance.balance = await getCurrentBalance();
+            continue;
+        }
+        const previousBalance = data[index - 1];
+        balance.balance =
+            previousBalance?.balance - (previousBalance?.debit - previousBalance?.credit);
     }
+    balances.value = data;
 }
 
 const showNewPaymentDialog = () => {
@@ -169,43 +216,25 @@ const showBalancePdf = ({ id }) => {
 </script>
 
 <template>
-    <FetchData
-        url="Companies"
-        auto-load
-        @on-fetch="(data) => (companies = data)"
-    ></FetchData>
-    <FetchData
-        v-if="companies.length > 0"
-        url="clientRisks"
-        :filter="{
-            include: { relation: 'company', scope: { fields: ['code'] } },
-            where: { clientFk: route.params.id },
-        }"
-        auto-load
-        @on-fetch="getCurrentBalance"
-    ></FetchData>
-
     <VnSubToolbar class="q-mb-md">
         <template #st-data>
             <div class="column justify-center q-px-md q-py-sm">
                 <span class="text-bold">{{ t('Total by company') }}</span>
-                <div class="row justify-center">
-                    {{ currentBalance[companyId]?.code }}:
-                    {{ toCurrency(currentBalance[companyId]?.amount) }}
+                <div class="row justify-center" v-if="clientRisk?.length">
+                    {{ clientRisk[0].company.code }}:
+                    {{ toCurrency(clientRisk[0].amount) }}
                 </div>
             </div>
         </template>
         <template #st-actions>
             <div>
-                <VnSelect
-                    :label="t('Company')"
+                <VnFilter
                     ref="vnFilterRef"
                     v-model="companyId"
                     data-key="CustomerBalance"
-                    :options="companies"
-                    option-label="code"
-                    option-value="id"
-                ></VnSelect>
+                    :column="companyFilterColumn"
+                    search-url="balance"
+                />
             </div>
         </template>
     </VnSubToolbar>
@@ -219,6 +248,7 @@ const showBalancePdf = ({ id }) => {
         :right-search="false"
         :is-editable="false"
         :column-search="false"
+        @on-fetch="onFetch"
         :disable-option="{ card: true }"
         auto-load
     >
diff --git a/src/pages/Customer/Card/CustomerCredits.vue b/src/pages/Customer/Card/CustomerCredits.vue
index 377d95412..1fa7047e5 100644
--- a/src/pages/Customer/Card/CustomerCredits.vue
+++ b/src/pages/Customer/Card/CustomerCredits.vue
@@ -49,7 +49,9 @@ const columns = computed(() => [
         name: 'credit',
         create: true,
         visible: false,
-        attrs: {
+        columnCreate: {
+            component: 'number',
+            required: true,
             autofocus: true,
         },
     },
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index 43103bd68..40166aefe 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -150,7 +150,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
             </QCardActions>
         </template>
         <template #actions="{ entity }">
-            <QCardActions class="flex justify-center">
+            <QCardActions class="flex justify-center" style="padding-inline: 0">
                 <QBtn
                     :to="{
                         name: 'TicketList',
@@ -168,6 +168,23 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 >
                     <QTooltip>{{ t('Customer ticket list') }}</QTooltip>
                 </QBtn>
+                <QBtn
+                    :to="{
+                        name: 'TicketList',
+                        query: {
+                            table: JSON.stringify({
+                                clientFk: entity.id,
+                            }),
+                            createForm: JSON.stringify({ clientId: entity.id }),
+                        },
+                    }"
+                    size="md"
+                    color="primary"
+                    target="_blank"
+                    icon="vn:ticketAdd"
+                >
+                    <QTooltip>{{ t('New ticket') }}</QTooltip>
+                </QBtn>
                 <QBtn
                     :to="{
                         name: 'InvoiceOutList',
@@ -179,6 +196,23 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 >
                     <QTooltip>{{ t('Customer invoice out list') }}</QTooltip>
                 </QBtn>
+                <QBtn
+                    :to="{
+                        name: 'OrderList',
+                        query: {
+                            table: JSON.stringify({
+                                clientFk: entity.id,
+                            }),
+                            createForm: JSON.stringify({ clientFk: entity.id }),
+                        },
+                    }"
+                    size="md"
+                    target="_blank"
+                    icon="vn:basketadd"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('New order') }}</QTooltip>
+                </QBtn>
                 <QBtn
                     :to="{
                         name: 'AccountSummary',
@@ -215,6 +249,8 @@ es:
     Go to module index: Ir al índice del módulo
     Customer ticket list: Listado de tickets del cliente
     Customer invoice out list: Listado de facturas del cliente
+    New order: Nuevo pedido
+    New ticket: Nuevo ticket
     Go to user: Ir al usuario
     Go to supplier: Ir al proveedor
     Customer unpaid: Cliente impago
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index 89b10a4fe..a0fbc7f7b 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -8,9 +8,6 @@ import { useQuasar } from 'quasar';
 import useNotify from 'src/composables/useNotify';
 
 import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
-import TicketCreateDialog from 'src/pages/Ticket/TicketCreateDialog.vue';
-import OrderCreateDialog from 'src/pages/Order/Card/OrderCreateDialog.vue';
-import { ref } from 'vue';
 
 const $props = defineProps({
     customer: {
@@ -43,34 +40,9 @@ const sendSms = async (payload) => {
         notify(error.message, 'positive');
     }
 };
-
-const ticketCreateFormDialog = ref(null);
-const openTicketCreateForm = () => {
-    ticketCreateFormDialog.value.show();
-};
-const orderCreateFormDialog = ref(null);
-const openOrderCreateForm = () => {
-    orderCreateFormDialog.value.show();
-};
 </script>
 
 <template>
-    <QItem v-ripple clickable @click="openTicketCreateForm()">
-        <QItemSection>
-            {{ t('globals.pageTitles.createTicket') }}
-            <QDialog ref="ticketCreateFormDialog">
-                <TicketCreateDialog />
-            </QDialog>
-        </QItemSection>
-    </QItem>
-    <QItem v-ripple clickable @click="openOrderCreateForm()">
-        <QItemSection>
-            {{ t('globals.pageTitles.createOrder') }}
-            <QDialog ref="orderCreateFormDialog">
-                <OrderCreateDialog :client-fk="customer.id" />
-            </QDialog>
-        </QItemSection>
-    </QItem>
     <QItem v-ripple clickable>
         <QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
     </QItem>
diff --git a/src/pages/Customer/Card/CustomerFiscalData.vue b/src/pages/Customer/Card/CustomerFiscalData.vue
index 1f5775715..6c5086149 100644
--- a/src/pages/Customer/Card/CustomerFiscalData.vue
+++ b/src/pages/Customer/Card/CustomerFiscalData.vue
@@ -53,11 +53,11 @@ function handleLocation(data, location) {
                         </QIcon>
                     </template>
                 </VnInput>
-                <VnInput :label="t('Tax number')" clearable v-model="data.fi" />
+                <VnInput :label="t('Tax number')" clearable v-model="data.fi" required />
             </VnRow>
 
             <VnRow>
-                <VnInput :label="t('Street')" clearable v-model="data.street" />
+                <VnInput :label="t('Street')" clearable v-model="data.street" required />
             </VnRow>
 
             <VnRow>
@@ -68,6 +68,7 @@ function handleLocation(data, location) {
                     option-label="vat"
                     option-value="id"
                     v-model="data.sageTaxTypeFk"
+                    :required="data.isTaxDataChecked"
                 />
                 <VnSelect
                     :label="t('Sage transaction type')"
@@ -76,6 +77,7 @@ function handleLocation(data, location) {
                     option-label="transaction"
                     option-value="id"
                     v-model="data.sageTransactionTypeFk"
+                    :required="data.isTaxDataChecked"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
@@ -96,6 +98,7 @@ function handleLocation(data, location) {
                     :roles-allowed-to-create="['deliveryAssistant', 'administrative']"
                     :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
                     :location="data"
+                    :required="true"
                     @update:model-value="(location) => handleLocation(data, location)"
                 />
             </VnRow>
diff --git a/src/pages/Customer/Card/CustomerGreuges.vue b/src/pages/Customer/Card/CustomerGreuges.vue
index 1d8b8585f..dcf297d12 100644
--- a/src/pages/Customer/Card/CustomerGreuges.vue
+++ b/src/pages/Customer/Card/CustomerGreuges.vue
@@ -80,6 +80,11 @@ const columns = computed(() => [
         align: 'left',
         name: 'amount',
         label: t('Amount'),
+        columnCreate: {
+            component: 'number',
+            autofocus: true,
+            required: true,
+        },
         format: ({ amount }) => toCurrency(amount),
         create: true,
     },
diff --git a/src/pages/Customer/Card/CustomerRecoveries.vue b/src/pages/Customer/Card/CustomerRecoveries.vue
index 48576ca20..3a8cffff8 100644
--- a/src/pages/Customer/Card/CustomerRecoveries.vue
+++ b/src/pages/Customer/Card/CustomerRecoveries.vue
@@ -56,6 +56,7 @@ const columns = computed(() => [
         label: t('Period'),
         create: true,
         ...componentColumn('number'),
+        required: true,
     },
     {
         align: 'left',
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 8b5f0f2c2..8e41119ef 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -1,13 +1,15 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, onMounted } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 
 import { toCurrency, toPercentage, toDate } from 'src/filters';
 import CardSummary from 'components/ui/CardSummary.vue';
+import { getUrl } from 'src/composables/getUrl';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
+import VnLinkMail from 'src/components/ui/VnLinkMail.vue';
 import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import VnRow from 'src/components/ui/VnRow.vue';
@@ -25,6 +27,11 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const customer = computed(() => summary.value.entity);
 const summary = ref();
+const clientUrl = ref();
+
+onMounted(async () => {
+    clientUrl.value = (await getUrl('client/')) + entityId.value + '/';
+});
 
 const balanceDue = computed(() => {
     return (
@@ -67,6 +74,7 @@ const sumRisk = ({ clientRisks }) => {
         ref="summary"
         :url="`Clients/${entityId}/summary`"
         data-key="CustomerSummary"
+        module-name="Customer"
     >
         <template #body="{ entity }">
             <QCard class="vn-one">
@@ -89,7 +97,11 @@ const sumRisk = ({ clientRisks }) => {
                         <VnLinkPhone :phone-number="entity.mobile" />
                     </template>
                 </VnLv>
-                <VnLv :label="t('customer.summary.email')" :value="entity.email" copy />
+                <VnLv :value="entity.email" copy
+                    ><template #label>
+                        {{ t('customer.summary.email') }}
+                        <VnLinkMail email="entity.email"></VnLinkMail> </template
+                ></VnLv>
                 <VnLv
                     :label="t('customer.summary.salesPerson')"
                     :value="entity?.salesPersonUser?.name"
@@ -166,7 +178,7 @@ const sumRisk = ({ clientRisks }) => {
             <QCard class="vn-one">
                 <VnTitle
                     :url="`#/customer/${entityId}/billing-data`"
-                    :text="t('customer.summary.payMethodFk')"
+                    :text="t('customer.summary.billingData')"
                 />
                 <VnLv
                     :label="t('customer.summary.payMethod')"
@@ -222,6 +234,7 @@ const sumRisk = ({ clientRisks }) => {
             </QCard>
             <QCard class="vn-one" v-if="entity.account">
                 <VnTitle
+                    target="_blank"
                     :url="`${grafanaUrl}/d/adjlxzv5yjt34d/analisis-de-clientes-7c-crm?orgId=1&var-clientFk=${entityId}`"
                     :text="t('customer.summary.businessData')"
                     icon="vn:grafana"
@@ -235,6 +248,7 @@ const sumRisk = ({ clientRisks }) => {
                     :value="toCurrency(entity?.mana?.mana)"
                 />
                 <VnLv
+                    v-if="entity.claimsRatio"
                     :label="t('customer.summary.priceIncreasingRate')"
                     :value="toPercentage(priceIncreasingRate)"
                 />
@@ -243,12 +257,14 @@ const sumRisk = ({ clientRisks }) => {
                     :value="toCurrency(entity?.averageInvoiced?.invoiced)"
                 />
                 <VnLv
+                    v-if="entity.claimsRatio"
                     :label="t('customer.summary.claimRate')"
                     :value="toPercentage(claimRate)"
                 />
             </QCard>
             <QCard class="vn-one" v-if="entity.account">
                 <VnTitle
+                    target="_blank"
                     :url="`${grafanaUrl}/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`"
                     :text="t('customer.summary.payMethodFk')"
                     icon="vn:grafana"
@@ -268,10 +284,12 @@ const sumRisk = ({ clientRisks }) => {
                 />
 
                 <VnLv
+                    v-if="entity.creditInsurance"
                     :label="t('customer.summary.securedCredit')"
                     :value="toCurrency(entity.creditInsurance)"
                     :info="t('customer.summary.securedCreditInfo')"
                 />
+
                 <VnLv
                     :label="t('customer.summary.balance')"
                     :value="toCurrency(sumRisk(entity)) || toCurrency(0)"
@@ -301,7 +319,7 @@ const sumRisk = ({ clientRisks }) => {
                     :value="entity.recommendedCredit"
                 />
             </QCard>
-            <QCard>
+            <QCard class="vn-one">
                 <VnTitle :text="t('Latest tickets')" />
                 <CustomerSummaryTable />
             </QCard>
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 63f5149e8..815ec57fa 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -68,7 +68,6 @@ const columns = computed(() => [
             fields: ['id', 'name'],
             where: { role: 'salesPerson' },
             optionFilter: 'firstName',
-            useLike: false,
         },
         create: false,
         columnField: {
@@ -429,9 +428,10 @@ function handleLocation(data, location) {
                 :params="{
                     departmentCodes: ['VT', 'shopping'],
                 }"
-                :fields="['id', 'nickname']"
+                :fields="['id', 'nickname', 'code']"
                 sort-by="nickname ASC"
-                :use-like="false"
+                option-label="nickname"
+                option-value="id"
                 emit-value
                 auto-load
             >
diff --git a/src/pages/Customer/components/CustomerAddressCreate.vue b/src/pages/Customer/components/CustomerAddressCreate.vue
index 659114744..e3fef8e5f 100644
--- a/src/pages/Customer/components/CustomerAddressCreate.vue
+++ b/src/pages/Customer/components/CustomerAddressCreate.vue
@@ -85,15 +85,26 @@ function handleLocation(data, location) {
             <QCheckbox :label="t('Default')" v-model="data.isDefaultAddress" />
 
             <VnRow>
-                <VnInput :label="t('Consignee')" clearable v-model="data.nickname" />
+                <VnInput
+                    :label="t('Consignee')"
+                    required
+                    clearable
+                    v-model="data.nickname"
+                />
 
-                <VnInput :label="t('Street address')" clearable v-model="data.street" />
+                <VnInput
+                    :label="t('Street address')"
+                    clearable
+                    v-model="data.street"
+                    required
+                />
             </VnRow>
 
             <VnLocation
                 :rules="validate('Worker.postcode')"
                 :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
                 v-model="data.location"
+                :required="true"
                 @update:model-value="(location) => handleLocation(data, location)"
             />
 
diff --git a/src/pages/Customer/components/CustomerNewPayment.vue b/src/pages/Customer/components/CustomerNewPayment.vue
index 16dd28767..291f28642 100644
--- a/src/pages/Customer/components/CustomerNewPayment.vue
+++ b/src/pages/Customer/components/CustomerNewPayment.vue
@@ -3,7 +3,7 @@ import { onBeforeMount, reactive, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import axios from 'axios';
-
+import { getClientRisk } from '../composables/getClientRisk';
 import { useDialogPluginComponent } from 'quasar';
 
 import { usePrintService } from 'composables/usePrintService';
@@ -158,9 +158,7 @@ async function getAmountPaid() {
         },
     };
 
-    const { data } = await axios(`ClientRisks`, {
-        params: { filter: JSON.stringify(filter) },
-    });
+    const { data } = await getClientRisk(filter);
     initialData.amountPaid = (data?.length && data[0].amount) || undefined;
 }
 </script>
@@ -241,7 +239,7 @@ async function getAmountPaid() {
                             </QItem>
                         </template>
                     </VnSelect>
-                    <VnInput
+                    <VnInputNumber
                         :label="t('Amount')"
                         :required="true"
                         @update:model-value="calculateFromAmount($event)"
@@ -254,7 +252,7 @@ async function getAmountPaid() {
                         {{ t('Compensation') }}
                     </div>
                     <VnRow>
-                        <VnInput
+                        <VnInputNumber
                             :label="t('Compensation account')"
                             clearable
                             v-model="data.compensationAccount"
diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue
index e9bb36be7..745cbf29e 100644
--- a/src/pages/Customer/components/CustomerSummaryTable.vue
+++ b/src/pages/Customer/components/CustomerSummaryTable.vue
@@ -63,7 +63,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        format: (row) => row.agencyMode.name,
+        format: (row) => dashIfEmpty(row.agencyMode?.name),
         columnClass: 'expand',
         label: t('Agency'),
     },
@@ -111,7 +111,11 @@ const columns = computed(() => [
             {
                 title: t('customer.summary.goToLines'),
                 icon: 'vn:lines',
-                action: ({ id }) => router.push({ params: { id }, name: 'TicketSale' }),
+                action: ({ id }) =>
+                    window.open(
+                        router.resolve({ params: { id }, name: 'TicketSale' }).href,
+                        '_blank'
+                    ),
                 isPrimary: true,
             },
             {
@@ -150,6 +154,8 @@ const setShippedColor = (date) => {
     if (difference == 0) return 'warning';
     if (difference < 0) return 'success';
 };
+const rowClick = ({ id }) =>
+    window.open(router.resolve({ params: { id }, name: 'TicketSummary' }).href, '_blank');
 
 const getItemPackagingType = (ticketSales) => {
     if (!ticketSales?.length) return '-';
@@ -177,13 +183,15 @@ const getItemPackagingType = (ticketSales) => {
         :column-search="false"
         url="Tickets"
         :columns="columns"
-        search-url="tickets"
+        append-params="false"
         :without-header="true"
         auto-load
+        :row-click="rowClick"
         order="shipped DESC, id"
         :disable-option="{ card: true, table: true }"
         class="full-width"
         :disable-infinite-scroll="true"
+        search-url="tickets"
     >
         <template #column-nickname="{ row }">
             <span class="link">
diff --git a/src/pages/Customer/composables/getClientRisk.js b/src/pages/Customer/composables/getClientRisk.js
new file mode 100644
index 000000000..ebaf545ee
--- /dev/null
+++ b/src/pages/Customer/composables/getClientRisk.js
@@ -0,0 +1,12 @@
+import axios from 'axios';
+
+export async function getClientRisk(_filter) {
+    const filter = {
+        ..._filter,
+        include: { relation: 'company', scope: { fields: ['code'] } },
+    };
+
+    return await axios(`ClientRisks`, {
+        params: { filter: JSON.stringify(filter) },
+    });
+}
diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 22bca15ac..93e53b9f6 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -28,7 +28,7 @@ describe('Client list', () => {
 
         cy.get('.q-mt-lg > .q-btn--standard').click();
 
-        cy.checkNotification('Data created');
+        cy.checkNotification('created');
         cy.url().should('include', '/summary');
     });
     it('Client list search client', () => {
@@ -43,4 +43,21 @@ describe('Client list', () => {
             cy.url().should('include', `/customer/${id}/summary`);
         });
     });
+
+    it('Client founded create ticket', () => {
+        const search = 'Jessica Jones';
+        cy.searchByLabel('Name', search);
+        cy.clickButtonsDescriptor(2);
+        cy.waitForElement('#formModel');
+        cy.waitForElement('.q-form');
+        cy.checkValueForm(1, search);
+    });
+    it('Client founded create order', () => {
+        const search = 'Jessica Jones';
+        cy.searchByLabel('Name', search);
+        cy.clickButtonsDescriptor(4);
+        cy.waitForElement('#formModel');
+        cy.waitForElement('.q-form');
+        cy.checkValueForm(2, search);
+    });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 76bdefd27..6fea4559a 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -264,6 +264,12 @@ Cypress.Commands.add('openActionsDescriptor', () => {
     cy.get('.header > :nth-child(3) > .q-btn__content > .q-icon').click();
 });
 
+Cypress.Commands.add('clickButtonsDescriptor', (id) => {
+    cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
+        .invoke('removeAttr', 'target')
+        .click();
+});
+
 Cypress.Commands.add('openUserPanel', () => {
     cy.get(
         '.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
@@ -274,14 +280,25 @@ Cypress.Commands.add('openActions', (row) => {
     cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
 });
 
-Cypress.Commands.add('checkNotification', (text) => {
-    cy.get('.q-notification')
-        .should('be.visible')
-        .last()
-        .then(($lastNotification) => {
-            if (!Cypress.$($lastNotification).text().includes(text))
-                throw new Error(`Notification not found: "${text}"`);
-        });
+Cypress.Commands.add('checkNotification', (type) => {
+    const values = {
+        created: 'Data created',
+        updated: 'Data saved',
+        deleted: 'Data deleted',
+    };
+    cy.get('.q-notification__message').should('have.text', values[type]);
+});
+
+Cypress.Commands.add('checkValueForm', (id, search) => {
+    cy.get(
+        `.grid-create > :nth-child(${id}) > .q-field__inner>.q-field__control> .q-field__control-container>.q-field__native >.q-field__input`
+    ).should('have.value', search);
+});
+
+Cypress.Commands.add('checkValueSelectForm', (id, search) => {
+    cy.get(
+        `.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container>.q-field__native>.q-field__input`
+    ).should('have.value', search);
 });
 
 Cypress.Commands.add('searchByLabel', (label, value) => {

From 0b2c404ab336d4e0b663b4cdc41b3fb0b772b7a8 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 02:15:21 +0100
Subject: [PATCH 119/207] perf: minor bugs detected

---
 src/components/VnTable/VnTable.vue |  4 ++++
 src/components/common/VnTitle.vue  |  2 +-
 src/components/ui/CardSummary.vue  | 20 +++-----------------
 src/composables/useArrayData.js    |  7 ++++---
 src/filters/index.js               |  2 ++
 src/filters/isDialogOpened.js      |  3 +++
 6 files changed, 17 insertions(+), 21 deletions(-)
 create mode 100644 src/filters/isDialogOpened.js

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index c1680bf13..cdf450966 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -73,6 +73,10 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    appendParams: {
+        type: Boolean,
+        default: true,
+    },
     hasSubToolbar: {
         type: Boolean,
         default: null,
diff --git a/src/components/common/VnTitle.vue b/src/components/common/VnTitle.vue
index 1fbd43972..89dd8cd0c 100644
--- a/src/components/common/VnTitle.vue
+++ b/src/components/common/VnTitle.vue
@@ -8,7 +8,7 @@ defineProps({
 <template>
     <div :class="$q.screen.gt.md ? 'q-pb-lg' : 'q-pb-md'">
         <div class="header-link" :style="{ cursor: url ? 'pointer' : 'default' }">
-            <a :href="url" :class="url ? 'link' : 'color-vn-text'">
+            <a :href="url" :class="url ? 'link' : 'color-vn-text'" v-bind="$attrs">
                 {{ text }}
                 <QIcon v-if="url" :name="icon" />
             </a>
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index 11dcbee3b..f469aa799 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
 import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import { useArrayData } from 'src/composables/useArrayData';
+import { isDialogOpened } from 'src/filters';
 
 const props = defineProps({
     url: {
@@ -58,22 +59,6 @@ async function fetch() {
     emit('onFetch', Array.isArray(data) ? data[0] : data);
     isLoading.value = false;
 }
-
-const showRedirectToSummaryIcon = computed(() => {
-    const exist = existSummary(route.matched);
-    return !isSummary.value && route.meta.moduleName && exist;
-});
-
-function existSummary(routes) {
-    const hasSummary = routes.some((r) => r.name === `${route.meta.moduleName}Summary`);
-    if (hasSummary) return hasSummary;
-    for (const current of routes) {
-        if (current.path != '/' && current.children) {
-            const exist = existSummary(current.children);
-            if (exist) return exist;
-        }
-    }
-}
 </script>
 
 <template>
@@ -84,7 +69,7 @@ function existSummary(routes) {
                 <div class="summaryHeader bg-primary q-pa-sm text-weight-bolder">
                     <slot name="header-left">
                         <router-link
-                            v-if="showRedirectToSummaryIcon"
+                            v-if="isDialogOpened()"
                             class="header link"
                             :to="{
                                 name: `${moduleName ?? route.meta.moduleName}Summary`,
@@ -118,6 +103,7 @@ function existSummary(routes) {
 
 .cardSummary {
     width: 100%;
+    max-height: 70vh;
     .summaryHeader {
         text-align: center;
         font-size: 20px;
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index a2eaa649a..0a060e4c6 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -3,6 +3,7 @@ import { useRouter, useRoute } from 'vue-router';
 import axios from 'axios';
 import { useArrayDataStore } from 'stores/useArrayDataStore';
 import { buildFilter } from 'filters/filterPanel';
+import { isDialogOpened } from 'src/filters';
 
 const arrayDataStore = useArrayDataStore();
 
@@ -114,8 +115,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
             for (const row of response.data) store.data.push(row);
         } else {
             store.data = response.data;
-            if (!document.querySelectorAll('[role="dialog"][aria-modal="true"]').length)
-                updateRouter && updateStateParams();
+            if (!isDialogOpened()) updateRouter && updateStateParams();
         }
 
         store.isLoading = false;
@@ -249,7 +249,8 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
     function updateStateParams() {
         if (!route) return;
         const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
-        newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
+        if (store.appendParams)
+            newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
 
         if (store.navigate) {
             const { customRouteRedirectName, searchText } = store.navigate;
diff --git a/src/filters/index.js b/src/filters/index.js
index 5f08f19c7..ce5c44706 100644
--- a/src/filters/index.js
+++ b/src/filters/index.js
@@ -12,8 +12,10 @@ import dateRange from './dateRange';
 import toHour from './toHour';
 import dashOrCurrency from './dashOrCurrency';
 import getParamWhere from './getParamWhere';
+import isDialogOpened from './isDialogOpened';
 
 export {
+    isDialogOpened,
     toLowerCase,
     toLowerCamel,
     toDate,
diff --git a/src/filters/isDialogOpened.js b/src/filters/isDialogOpened.js
new file mode 100644
index 000000000..9d6f3895e
--- /dev/null
+++ b/src/filters/isDialogOpened.js
@@ -0,0 +1,3 @@
+export default function isDialogOpened(query = '[role="dialog"]') {
+    return document.querySelectorAll(query).length > 0;
+}

From 4b00ab877c9d1a8455e368087cd74dff85f1dab0 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 02:26:35 +0100
Subject: [PATCH 120/207] perf: use required instead :required="true"

---
 src/components/common/VnInput.vue       | 10 +++++-----
 src/components/common/VnInputDate.vue   |  9 +++++----
 src/components/common/VnInputNumber.vue |  7 ++++++-
 src/components/common/VnInputTime.vue   |  7 ++++---
 src/components/common/VnLocation.vue    | 14 ++++++++++++--
 src/components/common/VnSelect.vue      | 11 ++++++-----
 6 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 1246eedcd..4534ae4a0 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -2,6 +2,7 @@
 import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useValidator } from 'src/composables/useValidator';
+import { useAttrs } from 'vue';
 
 const emit = defineEmits([
     'update:modelValue',
@@ -29,10 +30,11 @@ const $props = defineProps({
     },
 });
 const { validations } = useValidator();
+const $attrs = useAttrs();
 
 const { t } = useI18n();
-const requiredFieldRule = (val) => validations().required($attrs.required, val);
-
+const isRequired = computed(() => Object.keys($attrs).includes('required'));
+const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const vnInputRef = ref(null);
 const value = computed({
     get() {
@@ -60,8 +62,6 @@ const focus = () => {
 defineExpose({
     focus,
 });
-import { useAttrs } from 'vue';
-const $attrs = useAttrs();
 
 const mixinRules = [
     requiredFieldRule,
@@ -85,7 +85,7 @@ const mixinRules = [
             v-model="value"
             v-bind="{ ...$attrs, ...styleAttrs }"
             :type="$attrs.type"
-            :class="{ required: $attrs.required }"
+            :class="{ required: isRequired }"
             @keyup.enter="emit('keyup.enter')"
             :clearable="false"
             :rules="mixinRules"
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index 1aa797ab7..87833f411 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -6,6 +6,8 @@ import { useAttrs } from 'vue';
 import VnDate from './VnDate.vue';
 
 const model = defineModel({ type: [String, Date] });
+const $attrs = useAttrs();
+const { t } = useI18n();
 const $props = defineProps({
     isOutlined: {
         type: Boolean,
@@ -19,15 +21,14 @@ const $props = defineProps({
 import { useValidator } from 'src/composables/useValidator';
 const { validations } = useValidator();
 
-const { t } = useI18n();
-const requiredFieldRule = (val) => validations().required($attrs.required, val);
+const isRequired = computed(() => Object.keys($attrs).includes('required'));
+const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const vnInputDateRef = ref(null);
 
 const dateFormat = 'DD/MM/YYYY';
 const isPopupOpen = ref();
 const hover = ref();
 const mask = ref();
-const $attrs = useAttrs();
 
 const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 
@@ -104,7 +105,7 @@ const manageDate = (date) => {
             :mask="mask"
             placeholder="dd/mm/aaaa"
             v-bind="{ ...$attrs, ...styleAttrs }"
-            :class="{ required: $attrs.required }"
+            :class="{ required: isRequired }"
             :rules="mixinRules"
             :clearable="false"
             @click="isPopupOpen = true"
diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue
index ef4bb7512..1cad6c245 100644
--- a/src/components/common/VnInputNumber.vue
+++ b/src/components/common/VnInputNumber.vue
@@ -1,8 +1,13 @@
 <script setup>
 import VnInput from 'src/components/common/VnInput.vue';
+import { ref } from 'vue';
+import { useAttrs } from 'vue';
+
 const model = defineModel({ type: [Number, String] });
+const $attrs = useAttrs();
+const step = ref($attrs.step || 0.01);
 </script>
 
 <template>
-    <VnInput v-bind="$attrs" v-model.number="model" type="number" />
+    <VnInput v-bind="$attrs" v-model.number="model" type="number" :step="step" />
 </template>
diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue
index 6d69bc4a5..13e90e021 100644
--- a/src/components/common/VnInputTime.vue
+++ b/src/components/common/VnInputTime.vue
@@ -6,6 +6,7 @@ import { useValidator } from 'src/composables/useValidator';
 import VnTime from './VnTime.vue';
 
 const { validations } = useValidator();
+const { t } = useI18n();
 const $attrs = useAttrs();
 const model = defineModel({ type: String });
 const props = defineProps({
@@ -20,8 +21,8 @@ const props = defineProps({
 });
 const vnInputTimeRef = ref(null);
 const initialDate = ref(model.value ?? Date.vnNew());
-const { t } = useI18n();
-const requiredFieldRule = (val) => validations().required($attrs.required, val);
+const isRequired = computed(() => Object.keys($attrs).includes('required'));
+const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const dateFormat = 'HH:mm';
 const isPopupOpen = ref();
@@ -78,7 +79,7 @@ function dateToTime(newDate) {
             placeholder="--:--"
             v-model="formattedTime"
             v-bind="{ ...$attrs, ...styleAttrs }"
-            :class="{ required: $attrs.required }"
+            :class="{ required: isRequired }"
             style="min-width: 100px"
             :rules="mixinRules"
             @click="isPopupOpen = false"
diff --git a/src/components/common/VnLocation.vue b/src/components/common/VnLocation.vue
index 5f94c466a..7c6e46fdd 100644
--- a/src/components/common/VnLocation.vue
+++ b/src/components/common/VnLocation.vue
@@ -2,10 +2,14 @@
 import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
 import VnSelectDialog from 'components/common/VnSelectDialog.vue';
 import { useI18n } from 'vue-i18n';
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
 const { t } = useI18n();
 const emit = defineEmits(['update:model-value', 'update:options']);
+const { validations } = useValidator();
 
+import { useAttrs } from 'vue';
+import { useValidator } from 'src/composables/useValidator';
+const $attrs = useAttrs();
 const props = defineProps({
     location: {
         type: Object,
@@ -13,6 +17,10 @@ const props = defineProps({
     },
 });
 
+const isRequired = computed(() => Object.keys($attrs).includes('required'));
+const requiredFieldRule = (val) => validations().required(isRequired.value, val);
+
+const mixinRules = [requiredFieldRule];
 const locationProperties = [
     'postcode',
     (obj) =>
@@ -69,11 +77,13 @@ const handleModelValue = (data) => {
         :label="t('Location')"
         :placeholder="t('search_by_postalcode')"
         :input-debounce="300"
-        :class="{ required: $attrs.required }"
+        :class="{ required: isRequired }"
         v-bind="$attrs"
         clearable
         :emit-value="false"
         :tooltip="t('Create new location')"
+        :rules="mixinRules"
+        :lazy-rules="true"
     >
         <template #form>
             <CreateNewPostcode
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index b0aa648c1..4a4730784 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -4,7 +4,8 @@ import { useI18n } from 'vue-i18n';
 import FetchData from 'src/components/FetchData.vue';
 import { useValidator } from 'src/composables/useValidator';
 const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
-
+const $attrs = useAttrs();
+const { t } = useI18n();
 const $props = defineProps({
     modelValue: {
         type: [String, Number, Object],
@@ -88,9 +89,9 @@ const $props = defineProps({
     },
 });
 const { validations } = useValidator();
-const requiredFieldRule = (val) => validations().required($attrs.required, val);
-const $attrs = useAttrs();
-const { t } = useI18n();
+
+const isRequired = computed(() => Object.keys($attrs).includes('required'));
+const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
     toRefs($props);
@@ -257,7 +258,7 @@ defineExpose({ opts: myOptions });
         :fill-input="nullishToTrue($attrs['fill-input'])"
         ref="vnSelectRef"
         lazy-rules
-        :class="{ required: $attrs.required }"
+        :class="{ required: isRequired }"
         :rules="mixinRules"
         virtual-scroll-slice-size="options.length"
         hide-bottom-space

From d2680b0a1fcccef8b3b5daa9a2ee6b12ddacad34 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 02:38:44 +0100
Subject: [PATCH 121/207] test: fix arrayData

---
 src/composables/useArrayData.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 0a060e4c6..e33cb8b78 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -249,7 +249,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
     function updateStateParams() {
         if (!route) return;
         const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
-        if (store.appendParams)
+        if (store?.appendParams ?? true)
             newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
 
         if (store.navigate) {

From 96f894cc6c6b9be2dc235323a0a874a86b548eb3 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Tue, 29 Oct 2024 08:17:18 +0100
Subject: [PATCH 122/207] fix: refs #7283 filter

---
 src/pages/Item/ItemList.vue    | 2 +-
 src/pages/Item/ItemRequest.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index a6873d10c..a480cfff6 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -215,7 +215,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'workerFk',
             attrs: {
-                url: 'VnUsers/preview',
+                url: 'TicketRequests/getItemTypeWorker',
                 optionValue: 'id',
                 optionLabel: 'nickname',
             },
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 36da0368b..61156640e 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -104,7 +104,7 @@ const columns = computed(() => [
         columnFilter: {
             name: 'attenderFk',
             attrs: {
-                url: 'VnUsers/preview',
+                url: 'TicketRequests/getItemTypeWorker',
                 optionValue: 'id',
                 optionLabel: 'nickname',
             },

From 42fbdff5bd2e4d4e00d4514b35b861440e032ac1 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 29 Oct 2024 08:48:06 +0100
Subject: [PATCH 123/207] test: fix e2e

---
 src/components/ui/VnConfirm.vue                  | 1 +
 test/cypress/integration/outLogin/logout.spec.js | 7 ++-----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index ec9d0f48b..0abfc84bc 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -34,6 +34,7 @@ const emit = defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits
 
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();
+defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
 
 const title = props.title || t('Confirm');
 const message =
diff --git a/test/cypress/integration/outLogin/logout.spec.js b/test/cypress/integration/outLogin/logout.spec.js
index 8d4e90aac..d6c33a65b 100644
--- a/test/cypress/integration/outLogin/logout.spec.js
+++ b/test/cypress/integration/outLogin/logout.spec.js
@@ -13,7 +13,7 @@ describe('Logout', () => {
     });
     describe('not user', () => {
         beforeEach(() => {
-            cy.intercept('GET', '**DefaultViewConfigs**', {
+            cy.intercept('GET', '**StarredModules**', {
                 statusCode: 401,
                 body: {
                     error: {
@@ -29,10 +29,7 @@ describe('Logout', () => {
 
         it('when token not exists', () => {
             cy.get('.q-list > [href="#/item"]').click();
-            cy.get('.q-notification__message').should(
-                'have.text',
-                'Authorization Required'
-            );
+            cy.checkNotification('Authorization Required');
         });
     });
 });

From 5663064dd8ca211f328e96e0bba902685cec0f9a Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 29 Oct 2024 09:23:49 +0100
Subject: [PATCH 124/207] refactor: modified composable

---
 src/pages/Order/Card/OrderLines.vue         |  7 +++++--
 src/pages/Order/Card/OrderSummary.vue       |  9 +++++++--
 src/pages/Order/composables/confirmOrder.js | 21 ++-------------------
 3 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index 90586dc15..58c5c9551 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -6,7 +6,7 @@ import { useQuasar } from 'quasar';
 import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import { useArrayData } from 'composables/useArrayData';
-import { confirmOrder } from 'composables/confirmOrder';
+import { confirm } from 'src/pages/Order/composables/confirmOrder';
 import { toCurrency, toDate } from 'src/filters';
 
 import VnConfirm from 'components/ui/VnConfirm.vue';
@@ -32,7 +32,6 @@ const orderSummary = ref({
 });
 const getTotalRef = ref();
 const getVATRef = ref();
-const { confirm } = confirmOrder();
 const lineFilter = ref({
     include: [
         {
@@ -208,6 +207,10 @@ async function remove(item) {
 async function handleConfirm() {
     const result = await confirm(route.params.id);
     if (result) {
+        quasar.notify({
+            message: t('globals.dataSaved'),
+            type: 'positive',
+        });
         router.push({
             name: 'TicketList',
             query: {
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index 3669fe8d8..032af1993 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -2,9 +2,10 @@
 import { computed, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
+import { useQuasar } from 'quasar';
 import { dashIfEmpty, toCurrency, toDateHourMinSec } from 'src/filters';
 import { useArrayData } from 'composables/useArrayData';
-import { confirmOrder } from 'composables/confirmOrder';
+import { confirm } from 'src/pages/Order/composables/confirmOrder';
 import VnLv from 'components/ui/VnLv.vue';
 import CardSummary from 'components/ui/CardSummary.vue';
 import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
@@ -24,8 +25,8 @@ const $props = defineProps({
 
 const entityId = computed(() => $props.id || route.params.id);
 const summary = ref();
+const quasar = useQuasar();
 const descriptorData = useArrayData('orderData');
-const { confirm } = confirmOrder();
 const detailsColumns = ref([
     {
         name: 'item',
@@ -58,6 +59,10 @@ const detailsColumns = ref([
 async function handleConfirm() {
     const result = await confirm(route.params.id);
     if (result) {
+        quasar.notify({
+            message: t('globals.dataSaved'),
+            type: 'positive',
+        });
         summary.value.fetch({});
         descriptorData.fetch({});
     }
diff --git a/src/pages/Order/composables/confirmOrder.js b/src/pages/Order/composables/confirmOrder.js
index 33e05a1d7..b9eb5d7ac 100644
--- a/src/pages/Order/composables/confirmOrder.js
+++ b/src/pages/Order/composables/confirmOrder.js
@@ -1,22 +1,5 @@
 import axios from 'axios';
-import { useQuasar } from 'quasar';
-import { useI18n } from 'vue-i18n';
 
-export function confirmOrder() {
-    const quasar = useQuasar();
-    const { t } = useI18n();
-
-    async function confirm(route) {
-        const { data } = await axios.post(`Orders/${route}/confirm`);
-        if (data) {
-            quasar.notify({
-                message: t('globals.confirm'),
-                type: 'positive',
-            });
-            return data;
-        }
-        return null;
-    }
-
-    return { confirm };
+export async function confirm(routeId) {
+    return await axios.post(`Orders/${routeId}/confirm`);
 }

From 77cb2d84be6cb11f02effc49371a0ac70e580df2 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 29 Oct 2024 09:38:40 +0100
Subject: [PATCH 125/207] fix: refs #8078 handleSelection

---
 src/components/VnTable/VnTable.vue | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 74a96e0e3..a15ba2f47 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -335,8 +335,9 @@ function handleScroll() {
 function handleSelection({ evt, added, rows: selectedRows }, rows) {
     if (evt?.shiftKey && added) {
         const rowIndex = selectedRows[0].$index;
+        selected.value.length = 0;
         for (const row of rows) {
-            if (row.$index > rowIndex) break;
+            if (row.$index == rowIndex) break;
             selected.value.push(row);
         }
     }
@@ -440,7 +441,6 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
                 :virtual-scroll="isTableMode"
                 @virtual-scroll="handleScroll"
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
-                @update:selected="emit('update:selected', $event)"
                 @selection="(details) => handleSelection(details, rows)"
             >
                 <template #top-left v-if="!$props.withoutHeader">

From 19a7e526059a6b41cd7fb5902f0502aed294b4bd Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 29 Oct 2024 09:39:56 +0100
Subject: [PATCH 126/207] fix: refs #8078 handleSelection

---
 src/components/VnTable/VnTable.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index a15ba2f47..1e949120f 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -441,6 +441,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
                 :virtual-scroll="isTableMode"
                 @virtual-scroll="handleScroll"
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
+                @update:selected="emit('update:selected', $event)"
                 @selection="(details) => handleSelection(details, rows)"
             >
                 <template #top-left v-if="!$props.withoutHeader">

From e39f85ff4bcd45993a65fba6b01a9ef1aac30df8 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 29 Oct 2024 09:56:06 +0100
Subject: [PATCH 127/207] fix: refs #8078  improve handleSelection

---
 src/components/VnTable/VnTable.vue | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 1e949120f..dc8671369 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -335,10 +335,13 @@ function handleScroll() {
 function handleSelection({ evt, added, rows: selectedRows }, rows) {
     if (evt?.shiftKey && added) {
         const rowIndex = selectedRows[0].$index;
-        selected.value.length = 0;
+        const selectedIndexes = new Set(selected.value.map((row) => row.$index));
         for (const row of rows) {
             if (row.$index == rowIndex) break;
-            selected.value.push(row);
+            if (!selectedIndexes.has(row.$index)) {
+                selected.value.push(row);
+                selectedIndexes.add(row.$index);
+            }
         }
     }
 }

From 476ef1dedd7907586b27d80433427f2faf6fefe4 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 29 Oct 2024 13:14:42 +0100
Subject: [PATCH 128/207] feat: refs #7206 added inactive label and corrected
 minor errors

---
 src/components/ui/VnConfirm.vue               |  1 +
 .../components/CustomerSummaryTable.vue       |  2 +-
 src/pages/Order/Card/OrderCreateDialog.vue    |  1 -
 src/pages/Order/OrderList.vue                 | 32 ++++++++++++++++---
 src/pages/Ticket/Card/TicketSummary.vue       |  5 ---
 src/pages/Ticket/TicketList.vue               | 29 +++++++++++------
 6 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index ec9d0f48b..d6b1ac0a3 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -31,6 +31,7 @@ const props = defineProps({
 });
 
 const emit = defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
+defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
 
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();
diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue
index e9bb36be7..e9e30506b 100644
--- a/src/pages/Customer/components/CustomerSummaryTable.vue
+++ b/src/pages/Customer/components/CustomerSummaryTable.vue
@@ -63,7 +63,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        format: (row) => row.agencyMode.name,
+        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyMode?.name),
         columnClass: 'expand',
         label: t('Agency'),
     },
diff --git a/src/pages/Order/Card/OrderCreateDialog.vue b/src/pages/Order/Card/OrderCreateDialog.vue
index bcc62aa43..1239d195b 100644
--- a/src/pages/Order/Card/OrderCreateDialog.vue
+++ b/src/pages/Order/Card/OrderCreateDialog.vue
@@ -10,7 +10,6 @@ import VnSelect from 'components/common/VnSelect.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
 import { useDialogPluginComponent } from 'quasar';
 import { reactive } from 'vue';
-import FetchData from 'components/FetchData.vue';
 
 const { t } = useI18n();
 const state = useState();
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 6b6b41828..e01790c6b 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -233,7 +233,20 @@ onMounted(() => {
                 v-model="data.clientFk"
                 :label="t('module.customer')"
                 @update:model-value="(id) => fetchClientAddress(id, data)"
-            />
+            >
+                <template #option="scope">
+                    <QItem v-bind="scope.itemProps">
+                        <QItemSection>
+                            <QItemLabel>
+                                {{ scope.opt.name }}
+                            </QItemLabel>
+                            <QItemLabel caption>
+                                {{ `#${scope.opt.id}` }}
+                            </QItemLabel>
+                        </QItemSection>
+                    </QItem>
+                </template>
+            </VnSelect>
             <VnSelect
                 v-model="data.addressId"
                 :options="addressesList"
@@ -245,10 +258,21 @@ onMounted(() => {
                 <template #option="scope">
                     <QItem v-bind="scope.itemProps">
                         <QItemSection>
-                            <QItemLabel>
-                                {{ scope.opt?.nickname }}: {{ scope.opt?.street }},
-                                {{ scope.opt?.city }}</QItemLabel
+                            <QItemLabel
+                                :class="{
+                                    'color-vn-label': !scope.opt?.isActive,
+                                }"
                             >
+                                {{
+                                    `${
+                                        !scope.opt?.isActive
+                                            ? t('basicData.inactive')
+                                            : ''
+                                    } `
+                                }}
+                                {{ scope.opt?.nickname }}: {{ scope.opt?.street }},
+                                {{ scope.opt?.city }}
+                            </QItemLabel>
                         </QItemSection>
                     </QItem>
                 </template>
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 5fb99b849..61751357c 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -19,7 +19,6 @@ import VnTitle from 'src/components/common/VnTitle.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
 import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
-import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
 
 const route = useRoute();
@@ -87,10 +86,6 @@ async function changeState(value) {
 function toTicketUrl(section) {
     return '#/ticket/' + entityId.value + '/' + section;
 }
-function isOnTicketCard() {
-    const currentPath = route.path;
-    return currentPath.startsWith('/ticket');
-}
 </script>
 
 <template>
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index dd1f2d69a..4317efb83 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -268,8 +268,7 @@ const fetchAddresses = async (formData) => {
         if (!formData.clientId) return;
 
         const filter = {
-            fields: ['nickname', 'street', 'city', 'id'],
-            where: { isActive: true },
+            fields: ['nickname', 'street', 'city', 'id', 'isActive'],
             order: 'nickname ASC',
         };
         const params = { filter: JSON.stringify(filter) };
@@ -635,24 +634,36 @@ function setReference(data) {
             </VnRow>
             <VnRow>
                 <VnSelect
-                    url="Addresses"
-                    :label="t('ticket.create.address')"
+                    :label="t('basicData.address')"
                     v-model="data.addressId"
                     :options="addressesOptions"
                     option-value="id"
                     option-label="nickname"
                     hide-selected
+                    map-options
                     :disable="!data.clientId"
+                    :sort-by="'isActive DESC'"
                     @update:model-value="() => fetchAvailableAgencies(data)"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
                             <QItemSection>
-                                <QItemLabel>
-                                    {{ scope.opt.nickname }}
-                                </QItemLabel>
-                                <QItemLabel caption>
-                                    {{ `${scope.opt.street}, ${scope.opt.city}` }}
+                                <QItemLabel
+                                    :class="{
+                                        'color-vn-label': !scope.opt?.isActive,
+                                    }"
+                                >
+                                    {{
+                                        `${
+                                            !scope.opt?.isActive
+                                                ? t('basicData.inactive')
+                                                : ''
+                                        } `
+                                    }}
+                                    <span>
+                                        {{ scope.opt?.nickname }}:
+                                        {{ scope.opt?.street }}, {{ scope.opt?.city }}
+                                    </span>
                                 </QItemLabel>
                             </QItemSection>
                         </QItem>

From 282999c49e52e5e36369d82b28b5a55ba3469c3c Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 29 Oct 2024 13:23:15 +0100
Subject: [PATCH 129/207] fix: refs #7206 deleted duplicate code

---
 src/components/ui/VnConfirm.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index 081812093..d6b1ac0a3 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -35,7 +35,6 @@ defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.h
 
 const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
     useDialogPluginComponent();
-defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
 
 const title = props.title || t('Confirm');
 const message =

From bf4bee0f95145b04edf4710eacfba75b5fb2c3ac Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 29 Oct 2024 14:07:34 +0100
Subject: [PATCH 130/207] feat(VnSelect): refs #7136 add scroll

---
 src/components/common/VnSelect.vue    | 50 ++++++++++++++++++---------
 src/pages/Customer/CustomerFilter.vue |  3 +-
 2 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index b0aa648c1..5dc9fc74b 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
-import FetchData from 'src/components/FetchData.vue';
+import { useArrayData } from 'src/composables/useArrayData';
 import { useValidator } from 'src/composables/useValidator';
 const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 
@@ -86,7 +86,12 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    dataKey: {
+        type: String,
+        default: null,
+    },
 });
+
 const { validations } = useValidator();
 const requiredFieldRule = (val) => validations().required($attrs.required, val);
 const $attrs = useAttrs();
@@ -97,14 +102,14 @@ const { optionLabel, optionValue, optionFilter, optionFilterValue, options, mode
 const myOptions = ref([]);
 const myOptionsOriginal = ref([]);
 const vnSelectRef = ref();
-const dataRef = ref();
 const lastVal = ref();
 const noOneText = t('globals.noOne');
 const noOneOpt = ref({
     [optionValue.value]: false,
     [optionLabel.value]: noOneText,
 });
-
+const isLoading = ref(false);
+const useURL = computed(() => $props.url);
 const value = computed({
     get() {
         return $props.modelValue;
@@ -114,6 +119,9 @@ const value = computed({
         emit('update:modelValue', value);
     },
 });
+const arrayDataKey =
+    $props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label);
+const arrayData = useArrayData(arrayDataKey, { url: $props.url, searchUrl: false });
 
 watch(options, (newValue) => {
     setOptions(newValue);
@@ -128,7 +136,7 @@ watch(modelValue, async (newValue) => {
 
 onMounted(() => {
     setOptions(options.value);
-    if ($props.url && $props.modelValue && !findKeyInOptions())
+    if (useURL.value && $props.modelValue && !findKeyInOptions())
         fetchFilter($props.modelValue);
     if ($props.focusOnMount) setTimeout(() => vnSelectRef.value.showPopup(), 300);
 });
@@ -166,7 +174,7 @@ function filter(val, options) {
 }
 
 async function fetchFilter(val) {
-    if (!$props.url || !dataRef.value) return;
+    if (!$props.url) return;
 
     const { fields, include, sortBy, limit } = $props;
     const key =
@@ -188,8 +196,8 @@ async function fetchFilter(val) {
     const fetchOptions = { where, include, limit };
     if (fields) fetchOptions.fields = fields;
     if (sortBy) fetchOptions.order = sortBy;
-
-    return dataRef.value.fetch(fetchOptions);
+    arrayData.reset(['skip', 'filter.skip', 'page']);
+    return (await arrayData.applyFilter({ filter: fetchOptions }))?.data;
 }
 
 async function filterHandler(val, update) {
@@ -229,20 +237,25 @@ function nullishToTrue(value) {
 
 const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
 
+async function onScroll({ to, direction, from, index }) {
+    const lastIndex = myOptions.value.length - 1;
+
+    if (from === 0 && index === 0) return;
+    if (!useURL.value && !$props.fetchRef) return;
+    if (direction === 'decrease') return;
+    if (to === lastIndex && arrayData.store.hasMoreData && !isLoading.value) {
+        isLoading.value = true;
+        await arrayData.loadMore();
+        setOptions(arrayData.store.data);
+        vnSelectRef.value.scrollTo(lastIndex);
+        isLoading.value = false;
+    }
+}
+
 defineExpose({ opts: myOptions });
 </script>
 
 <template>
-    <FetchData
-        ref="dataRef"
-        :url="$props.url"
-        @on-fetch="(data) => setOptions(data)"
-        :where="where || { [optionValue]: value }"
-        :limit="limit"
-        :sort-by="sortBy"
-        :fields="fields"
-        :params="params"
-    />
     <QSelect
         v-model="value"
         :options="myOptions"
@@ -261,6 +274,9 @@ defineExpose({ opts: myOptions });
         :rules="mixinRules"
         virtual-scroll-slice-size="options.length"
         hide-bottom-space
+        :input-debounce="useURL ? '300' : '0'"
+        :loading="isLoading"
+        @virtual-scroll="onScroll"
     >
         <template v-if="isClearable" #append>
             <QIcon
diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index 6c50cc9df..02e07249a 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -53,7 +53,7 @@ defineProps({
                 <QItemSection>
                     <VnSelect
                         url="Workers/activeWithInheritedRole"
-                        :filter="{ where: { role: 'salesPerson' } }"
+                        :where="{ role: 'salesPerson' }"
                         auto-load
                         :label="t('Salesperson')"
                         v-model="params.salesPersonFk"
@@ -67,7 +67,6 @@ defineProps({
                         dense
                         outlined
                         rounded
-                        :input-debounce="0"
                     />
                 </QItemSection>
             </QItem>

From ed8225bf6c0285ef9f89af4ae8d1706b3edbc555 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 14:23:06 +0100
Subject: [PATCH 131/207] feat: #7782 waitUntil domContentLoad

---
 .../vnComponent/vnLocation.spec.js            |  2 +-
 test/cypress/support/commands.js              | 12 +++-
 test/cypress/support/waitUntil.js             | 59 +++++++++++++++++++
 3 files changed, 69 insertions(+), 4 deletions(-)
 create mode 100644 test/cypress/support/waitUntil.js

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index c1b0cf929..924b16adc 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -12,7 +12,7 @@ describe('VnLocation', () => {
             cy.viewport(1280, 720);
             cy.login('developer');
             cy.visit('/#/supplier/567/fiscal-data', { timeout: 7000 });
-            cy.waitForElement('.q-card');
+            cy.domContentLoad();
             cy.get(createLocationButton).click();
         });
         it('should filter provinces based on selected country', () => {
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 76bdefd27..5bb89ecf9 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -27,6 +27,10 @@
 // DO NOT REMOVE
 // Imports Quasar Cypress AE predefined commands
 // import { registerCommands } from '@quasar/quasar-app-extension-testing-e2e-cypress';
+Cypress.Commands.add('waitUntil', { prevSubject: 'optional' }, require('./waitUntil'));
+Cypress.Commands.add('resetDB', () => {
+    cy.exec('pnpm run resetDatabase');
+});
 Cypress.Commands.add('login', (user) => {
     //cy.visit('/#/login');
     cy.request({
@@ -50,10 +54,12 @@ Cypress.Commands.add('login', (user) => {
     });
 });
 
-Cypress.Commands.add('waitForElement', (element, timeout = 5000) => {
-    cy.get(element, { timeout }).should('be.visible');
+Cypress.Commands.add('domContentLoad', (element, timeout = 5000) => {
+    cy.waitUntil(() => cy.document().then((doc) => doc.readyState === 'complete'));
+});
+Cypress.Commands.add('waitForElement', (element, timeout = 5000) => {
+    cy.waitUntil(() => cy.get(element).then(($el) => $el.is(':visible')));
 });
-
 Cypress.Commands.add('getValue', (selector) => {
     cy.get(selector).then(($el) => {
         if ($el.find('.q-checkbox__inner').length > 0) {
diff --git a/test/cypress/support/waitUntil.js b/test/cypress/support/waitUntil.js
new file mode 100644
index 000000000..5fb47a2d8
--- /dev/null
+++ b/test/cypress/support/waitUntil.js
@@ -0,0 +1,59 @@
+const waitUntil = (subject, checkFunction, originalOptions = {}) => {
+    if (!(checkFunction instanceof Function)) {
+        throw new Error(
+            '`checkFunction` parameter should be a function. Found: ' + checkFunction
+        );
+    }
+
+    const defaultOptions = {
+        // base options
+        interval: 200,
+        timeout: 5000,
+        errorMsg: 'Timed out retrying',
+
+        // log options
+        description: 'waitUntil',
+        log: true,
+        customMessage: undefined,
+        logger: Cypress.log,
+        verbose: false,
+        customCheckMessage: undefined,
+    };
+    const options = { ...defaultOptions, ...originalOptions };
+
+    // filter out a falsy passed "customMessage" value
+    options.customMessage = [options.customMessage, originalOptions].filter(Boolean);
+
+    const endTime = Date.now() + options.timeout;
+
+    const check = (result) => {
+        if (result) {
+            return result;
+        }
+        if (Date.now() >= endTime) {
+            const msg =
+                options.errorMsg instanceof Function
+                    ? options.errorMsg(result, options)
+                    : options.errorMsg;
+            throw new Error(msg);
+        }
+        cy.wait(options.interval, { log: false }).then(() => {
+            return resolveValue();
+        });
+    };
+
+    const resolveValue = () => {
+        const result = checkFunction(subject);
+
+        const isAPromise = Boolean(result && result.then);
+        if (isAPromise) {
+            return result.then(check);
+        } else {
+            return check(result);
+        }
+    };
+
+    return resolveValue();
+};
+
+export default waitUntil;

From b817aa92c2b4f09dd4c282d2313551acf8f5be0b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 14:23:22 +0100
Subject: [PATCH 132/207] feat: #7782 npm run resetDatabase

---
 package.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index a61c8f21a..71e95667c 100644
--- a/package.json
+++ b/package.json
@@ -7,10 +7,11 @@
     "private": true,
     "packageManager": "pnpm@8.15.1",
     "scripts": {
+        "resetDatabase": "cd ../salix && gulp docker",
         "lint": "eslint --ext .js,.vue ./",
         "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
         "test:e2e": "cypress open",
-        "test:e2e:ci": "cd ../salix && gulp docker && cd ../salix-front && cypress run",
+        "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
         "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
         "test:unit": "vitest",
         "test:unit:ci": "vitest run",

From 2090b78ce6005df77178925f6e04a3b8c39bce86 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 14:25:34 +0100
Subject: [PATCH 133/207] feat: #7782 cypress.config watchForFileChanges

---
 cypress.config.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/cypress.config.js b/cypress.config.js
index e2046d6c4..1b3e0190f 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -11,6 +11,7 @@ module.exports = defineConfig({
         video: false,
         specPattern: 'test/cypress/integration/**/*.spec.js',
         experimentalRunAllSpecs: true,
+        watchForFileChanges: true,
         component: {
             componentFolder: 'src',
             testFiles: '**/*.spec.js',

From fbbbc331a951734b09cc7bd084209facdb1143cb Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 14:27:24 +0100
Subject: [PATCH 134/207] feat: #7782 add cypress report

---
 cypress.config.js |   9 ++
 package.json      |   1 +
 pnpm-lock.yaml    | 379 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 380 insertions(+), 9 deletions(-)

diff --git a/cypress.config.js b/cypress.config.js
index 1b3e0190f..f8e771093 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -12,12 +12,21 @@ module.exports = defineConfig({
         specPattern: 'test/cypress/integration/**/*.spec.js',
         experimentalRunAllSpecs: true,
         watchForFileChanges: true,
+        reporter: 'cypress-mochawesome-reporter',
+        reporterOptions: {
+            charts: true,
+            reportPageTitle: 'Cypress Inline Reporter',
+            embeddedScreenshots: true,
+            reportDir: 'test/cypress/reports',
+            inlineAssets: true,
+        },
         component: {
             componentFolder: 'src',
             testFiles: '**/*.spec.js',
             supportFile: 'test/cypress/support/unit.js',
         },
         setupNodeEvents(on, config) {
+            require('cypress-mochawesome-reporter/plugin')(on);
             // implement node event listeners here
         },
     },
diff --git a/package.json b/package.json
index 71e95667c..e2e75f253 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
         "@vue/test-utils": "^2.4.4",
         "autoprefixer": "^10.4.14",
         "cypress": "^13.6.6",
+        "cypress-mochawesome-reporter": "^3.8.2",
         "eslint": "^8.41.0",
         "eslint-config-prettier": "^8.8.0",
         "eslint-plugin-cypress": "^2.13.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e336c39bb..83dfa0469 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -70,6 +70,9 @@ devDependencies:
   cypress:
     specifier: ^13.6.6
     version: 13.6.6
+  cypress-mochawesome-reporter:
+    specifier: ^3.8.2
+    version: 3.8.2(cypress@13.6.6)(mocha@10.7.3)
   eslint:
     specifier: ^8.41.0
     version: 8.56.0
@@ -829,8 +832,8 @@ packages:
       vue-i18n:
         optional: true
     dependencies:
-      '@intlify/message-compiler': 10.0.0-beta.5
-      '@intlify/shared': 10.0.0-beta.5
+      '@intlify/message-compiler': 10.0.0
+      '@intlify/shared': 10.0.0
       jsonc-eslint-parser: 1.4.1
       source-map: 0.6.1
       vue-i18n: 9.9.1(vue@3.4.19)
@@ -844,11 +847,11 @@ packages:
       '@intlify/message-compiler': 9.9.1
       '@intlify/shared': 9.9.1
 
-  /@intlify/message-compiler@10.0.0-beta.5:
-    resolution: {integrity: sha512-hLLchnM1dmtSEruerkzvU9vePsLqBXz3RU85SCx/Vd12fFQiymP+/5Rn9MJ8MyfLmIOLDEx4PRh+/GkIQP6oog==}
+  /@intlify/message-compiler@10.0.0:
+    resolution: {integrity: sha512-OcaWc63NC/9p1cMdgoNKBj4d61BH8sUW1Hfs6YijTd9656ZR4rNqXAlRnBrfS5ABq0vjQjpa8VnyvH9hK49yBw==}
     engines: {node: '>= 16'}
     dependencies:
-      '@intlify/shared': 10.0.0-beta.5
+      '@intlify/shared': 10.0.0
       source-map-js: 1.0.2
     dev: true
 
@@ -859,8 +862,8 @@ packages:
       '@intlify/shared': 9.9.1
       source-map-js: 1.0.2
 
-  /@intlify/shared@10.0.0-beta.5:
-    resolution: {integrity: sha512-g9bq5Y1bOcC9qxtNk4UWtF3sXm6Wh0fGISb7vD5aLyF7yQv7ZFjxQjJzBP2GqG/9+PAGYutqjP1GGadNqFtyAQ==}
+  /@intlify/shared@10.0.0:
+    resolution: {integrity: sha512-6ngLfI7DOTew2dcF9WMJx+NnMWghMBhIiHbGg+wRvngpzD5KZJZiJVuzMsUQE1a5YebEmtpTEfUrDp/NqVGdiw==}
     engines: {node: '>= 16'}
     dev: true
 
@@ -884,7 +887,7 @@ packages:
         optional: true
     dependencies:
       '@intlify/bundle-utils': 4.0.0(vue-i18n@9.9.1)
-      '@intlify/shared': 10.0.0-beta.5
+      '@intlify/shared': 10.0.0
       '@rollup/pluginutils': 4.2.1
       '@vue/compiler-sfc': 3.4.19
       debug: 4.3.4(supports-color@8.1.1)
@@ -1999,6 +2002,10 @@ packages:
     dependencies:
       fill-range: 7.0.1
 
+  /browser-stdout@1.3.1:
+    resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
+    dev: true
+
   /browserslist@4.23.0:
     resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
     engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -2106,6 +2113,16 @@ packages:
       upper-case: 1.1.3
     dev: true
 
+  /camelcase@5.3.1:
+    resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /camelcase@6.3.0:
+    resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+    engines: {node: '>=10'}
+    dev: true
+
   /camelcase@7.0.1:
     resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
     engines: {node: '>=14.16'}
@@ -2255,6 +2272,22 @@ packages:
     engines: {node: '>= 10'}
     dev: true
 
+  /cliui@6.0.0:
+    resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 6.2.0
+    dev: true
+
+  /cliui@7.0.4:
+    resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+    dev: true
+
   /cliui@8.0.1:
     resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
     engines: {node: '>=12'}
@@ -2558,6 +2591,23 @@ packages:
   /csstype@3.1.3:
     resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
 
+  /cypress-mochawesome-reporter@3.8.2(cypress@13.6.6)(mocha@10.7.3):
+    resolution: {integrity: sha512-oJZkNzhNmN9ZD+LmZyFuPb8aWaIijyHyqYh52YOBvR6B6ckfJNCHP3A98a+/nG0H4t46CKTNwo+wNpMa4d2kjA==}
+    engines: {node: '>=14'}
+    hasBin: true
+    peerDependencies:
+      cypress: '>=6.2.0'
+    dependencies:
+      commander: 10.0.1
+      cypress: 13.6.6
+      fs-extra: 10.1.0
+      mochawesome: 7.1.3(mocha@10.7.3)
+      mochawesome-merge: 4.3.0
+      mochawesome-report-generator: 6.2.0
+    transitivePeerDependencies:
+      - mocha
+    dev: true
+
   /cypress@13.6.6:
     resolution: {integrity: sha512-S+2S9S94611hXimH9a3EAYt81QM913ZVA03pUmGDfLTFa5gyp85NJ8dJGSlEAEmyRsYkioS1TtnWtbv/Fzt11A==}
     engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
@@ -2627,6 +2677,10 @@ packages:
       time-zone: 1.0.0
     dev: true
 
+  /dateformat@4.6.3:
+    resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
+    dev: true
+
   /dayjs@1.11.10:
     resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
     dev: true
@@ -2676,6 +2730,29 @@ packages:
       ms: 2.1.2
       supports-color: 8.1.1
 
+  /debug@4.3.7(supports-color@8.1.1):
+    resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.3
+      supports-color: 8.1.1
+    dev: true
+
+  /decamelize@1.2.0:
+    resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /decamelize@4.0.0:
+    resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
+    engines: {node: '>=10'}
+    dev: true
+
   /decompress-response@6.0.0:
     resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
     engines: {node: '>=10'}
@@ -2758,6 +2835,11 @@ packages:
     resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
     engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
 
+  /diff@5.2.0:
+    resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
+    engines: {node: '>=0.3.1'}
+    dev: true
+
   /doctrine@3.0.0:
     resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
     engines: {node: '>=6.0.0'}
@@ -3550,6 +3632,14 @@ packages:
     transitivePeerDependencies:
       - supports-color
 
+  /find-up@4.1.0:
+    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+    engines: {node: '>=8'}
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+    dev: true
+
   /find-up@5.0.0:
     resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
     engines: {node: '>=10'}
@@ -3646,6 +3736,15 @@ packages:
     resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
     dev: true
 
+  /fs-extra@10.1.0:
+    resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+    dev: true
+
   /fs-extra@11.2.0:
     resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
     engines: {node: '>=14.14'}
@@ -3654,6 +3753,15 @@ packages:
       jsonfile: 6.1.0
       universalify: 2.0.1
 
+  /fs-extra@7.0.1:
+    resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
+    engines: {node: '>=6 <7 || >=8'}
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 4.0.0
+      universalify: 0.1.2
+    dev: true
+
   /fs-extra@9.1.0:
     resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
     engines: {node: '>=10'}
@@ -3675,6 +3783,10 @@ packages:
     dev: true
     optional: true
 
+  /fsu@1.1.1:
+    resolution: {integrity: sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==}
+    dev: true
+
   /function-bind@1.1.2:
     resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
 
@@ -3775,6 +3887,18 @@ packages:
       once: 1.4.0
       path-is-absolute: 1.0.1
 
+  /glob@8.1.0:
+    resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
+    engines: {node: '>=12'}
+    deprecated: Glob versions prior to v9 are no longer supported
+    dependencies:
+      fs.realpath: 1.0.0
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 5.1.6
+      once: 1.4.0
+    dev: true
+
   /global-directory@4.0.1:
     resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
     engines: {node: '>=18'}
@@ -4189,6 +4313,11 @@ packages:
     resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
     engines: {node: '>=8'}
 
+  /is-plain-obj@2.1.0:
+    resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
+    engines: {node: '>=8'}
+    dev: true
+
   /is-plain-obj@3.0.0:
     resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
     engines: {node: '>=10'}
@@ -4361,6 +4490,12 @@ packages:
     resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==}
     dev: true
 
+  /jsonfile@4.0.0:
+    resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+    optionalDependencies:
+      graceful-fs: 4.2.11
+    dev: true
+
   /jsonfile@6.1.0:
     resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
     dependencies:
@@ -4452,6 +4587,13 @@ packages:
     engines: {node: '>=14'}
     dev: true
 
+  /locate-path@5.0.0:
+    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-locate: 4.1.0
+    dev: true
+
   /locate-path@6.0.0:
     resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
     engines: {node: '>=10'}
@@ -4486,10 +4628,26 @@ packages:
     resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==}
     dev: true
 
+  /lodash.isempty@4.4.0:
+    resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==}
+    dev: true
+
+  /lodash.isfunction@3.0.9:
+    resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==}
+    dev: true
+
+  /lodash.isobject@3.0.2:
+    resolution: {integrity: sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==}
+    dev: true
+
   /lodash.isplainobject@4.0.6:
     resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
     dev: true
 
+  /lodash.isstring@4.0.1:
+    resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+    dev: true
+
   /lodash.kebabcase@4.1.1:
     resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
     dev: true
@@ -4552,6 +4710,13 @@ packages:
       wrap-ansi: 6.2.0
     dev: true
 
+  /loose-envify@1.4.0:
+    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+    hasBin: true
+    dependencies:
+      js-tokens: 4.0.0
+    dev: true
+
   /loupe@2.3.7:
     resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
     dependencies:
@@ -4722,6 +4887,79 @@ packages:
       ufo: 1.4.0
     dev: true
 
+  /mocha@10.7.3:
+    resolution: {integrity: sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==}
+    engines: {node: '>= 14.0.0'}
+    hasBin: true
+    dependencies:
+      ansi-colors: 4.1.3
+      browser-stdout: 1.3.1
+      chokidar: 3.6.0
+      debug: 4.3.7(supports-color@8.1.1)
+      diff: 5.2.0
+      escape-string-regexp: 4.0.0
+      find-up: 5.0.0
+      glob: 8.1.0
+      he: 1.2.0
+      js-yaml: 4.1.0
+      log-symbols: 4.1.0
+      minimatch: 5.1.6
+      ms: 2.1.3
+      serialize-javascript: 6.0.2
+      strip-json-comments: 3.1.1
+      supports-color: 8.1.1
+      workerpool: 6.5.1
+      yargs: 16.2.0
+      yargs-parser: 20.2.9
+      yargs-unparser: 2.0.0
+    dev: true
+
+  /mochawesome-merge@4.3.0:
+    resolution: {integrity: sha512-1roR6g+VUlfdaRmL8dCiVpKiaUhbPVm1ZQYUM6zHX46mWk+tpsKVZR6ba98k2zc8nlPvYd71yn5gyH970pKBSw==}
+    engines: {node: '>=10.0.0'}
+    hasBin: true
+    dependencies:
+      fs-extra: 7.0.1
+      glob: 7.2.3
+      yargs: 15.4.1
+    dev: true
+
+  /mochawesome-report-generator@6.2.0:
+    resolution: {integrity: sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==}
+    hasBin: true
+    dependencies:
+      chalk: 4.1.2
+      dateformat: 4.6.3
+      escape-html: 1.0.3
+      fs-extra: 10.1.0
+      fsu: 1.1.1
+      lodash.isfunction: 3.0.9
+      opener: 1.5.2
+      prop-types: 15.8.1
+      tcomb: 3.2.29
+      tcomb-validation: 3.4.1
+      validator: 13.11.0
+      yargs: 17.7.2
+    dev: true
+
+  /mochawesome@7.1.3(mocha@10.7.3):
+    resolution: {integrity: sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==}
+    peerDependencies:
+      mocha: '>=7'
+    dependencies:
+      chalk: 4.1.2
+      diff: 5.2.0
+      json-stringify-safe: 5.0.1
+      lodash.isempty: 4.4.0
+      lodash.isfunction: 3.0.9
+      lodash.isobject: 3.0.2
+      lodash.isstring: 4.0.1
+      mocha: 10.7.3
+      mochawesome-report-generator: 6.2.0
+      strip-ansi: 6.0.1
+      uuid: 8.3.2
+    dev: true
+
   /ms@2.0.0:
     resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
 
@@ -4870,6 +5108,11 @@ packages:
       is-wsl: 2.2.0
     dev: false
 
+  /opener@1.5.2:
+    resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
+    hasBin: true
+    dev: true
+
   /optionator@0.9.3:
     resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
     engines: {node: '>= 0.8.0'}
@@ -4915,6 +5158,13 @@ packages:
     engines: {node: '>=12.20'}
     dev: false
 
+  /p-limit@2.3.0:
+    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+    engines: {node: '>=6'}
+    dependencies:
+      p-try: 2.2.0
+    dev: true
+
   /p-limit@3.1.0:
     resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
     engines: {node: '>=10'}
@@ -4929,6 +5179,13 @@ packages:
       yocto-queue: 1.0.0
     dev: true
 
+  /p-locate@4.1.0:
+    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-limit: 2.3.0
+    dev: true
+
   /p-locate@5.0.0:
     resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
     engines: {node: '>=10'}
@@ -4950,6 +5207,11 @@ packages:
       aggregate-error: 3.1.0
     dev: true
 
+  /p-try@2.2.0:
+    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+    engines: {node: '>=6'}
+    dev: true
+
   /package-json@8.1.1:
     resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
     engines: {node: '>=14.16'}
@@ -5139,6 +5401,14 @@ packages:
     engines: {node: '>=0.4.0'}
     dev: false
 
+  /prop-types@15.8.1:
+    resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+    dependencies:
+      loose-envify: 1.4.0
+      object-assign: 4.1.1
+      react-is: 16.13.1
+    dev: true
+
   /proto-list@1.2.4:
     resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
 
@@ -5242,6 +5512,10 @@ packages:
       strip-json-comments: 2.0.1
     dev: false
 
+  /react-is@16.13.1:
+    resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+    dev: true
+
   /react-is@17.0.2:
     resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
     dev: true
@@ -5328,6 +5602,10 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /require-main-filename@2.0.0:
+    resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+    dev: true
+
   /requires-port@1.0.0:
     resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
 
@@ -5573,6 +5851,10 @@ packages:
     transitivePeerDependencies:
       - supports-color
 
+  /set-blocking@2.0.0:
+    resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+    dev: true
+
   /set-function-length@1.2.1:
     resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==}
     engines: {node: '>= 0.4'}
@@ -5829,6 +6111,16 @@ packages:
       readable-stream: 3.6.2
     dev: true
 
+  /tcomb-validation@3.4.1:
+    resolution: {integrity: sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==}
+    dependencies:
+      tcomb: 3.2.29
+    dev: true
+
+  /tcomb@3.2.29:
+    resolution: {integrity: sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==}
+    dev: true
+
   /text-extensions@2.4.0:
     resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
     engines: {node: '>=8'}
@@ -6048,6 +6340,11 @@ packages:
       crypto-random-string: 4.0.0
     dev: false
 
+  /universalify@0.1.2:
+    resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+    engines: {node: '>= 4.0.0'}
+    dev: true
+
   /universalify@0.2.0:
     resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
     engines: {node: '>= 4.0.0'}
@@ -6137,7 +6434,6 @@ packages:
   /validator@13.11.0:
     resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==}
     engines: {node: '>= 0.10'}
-    dev: false
 
   /vary@1.1.2:
     resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
@@ -6484,6 +6780,10 @@ packages:
     engines: {node: '>=12'}
     dev: true
 
+  /which-module@2.0.1:
+    resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+    dev: true
+
   /which@2.0.2:
     resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
     engines: {node: '>= 8'}
@@ -6511,6 +6811,10 @@ packages:
     resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
     dev: true
 
+  /workerpool@6.5.1:
+    resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==}
+    dev: true
+
   /wrap-ansi@6.2.0:
     resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
     engines: {node: '>=8'}
@@ -6559,6 +6863,10 @@ packages:
     engines: {node: '>=12'}
     dev: true
 
+  /y18n@4.0.3:
+    resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+    dev: true
+
   /y18n@5.0.8:
     resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
     engines: {node: '>=10'}
@@ -6584,11 +6892,64 @@ packages:
     engines: {node: '>= 6'}
     dev: true
 
+  /yargs-parser@18.1.3:
+    resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
+    engines: {node: '>=6'}
+    dependencies:
+      camelcase: 5.3.1
+      decamelize: 1.2.0
+    dev: true
+
+  /yargs-parser@20.2.9:
+    resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
+    engines: {node: '>=10'}
+    dev: true
+
   /yargs-parser@21.1.1:
     resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
     engines: {node: '>=12'}
     dev: true
 
+  /yargs-unparser@2.0.0:
+    resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
+    engines: {node: '>=10'}
+    dependencies:
+      camelcase: 6.3.0
+      decamelize: 4.0.0
+      flat: 5.0.2
+      is-plain-obj: 2.1.0
+    dev: true
+
+  /yargs@15.4.1:
+    resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
+    engines: {node: '>=8'}
+    dependencies:
+      cliui: 6.0.0
+      decamelize: 1.2.0
+      find-up: 4.1.0
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      require-main-filename: 2.0.0
+      set-blocking: 2.0.0
+      string-width: 4.2.3
+      which-module: 2.0.1
+      y18n: 4.0.3
+      yargs-parser: 18.1.3
+    dev: true
+
+  /yargs@16.2.0:
+    resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+    engines: {node: '>=10'}
+    dependencies:
+      cliui: 7.0.4
+      escalade: 3.1.2
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 20.2.9
+    dev: true
+
   /yargs@17.7.2:
     resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
     engines: {node: '>=12'}

From 4de23c31b3f34f1849c4300e93729b244db9e01d Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 29 Oct 2024 15:01:49 +0100
Subject: [PATCH 135/207] feat: use composable to unify logic

---
 src/components/common/VnInput.vue     | 13 +++++--------
 src/components/common/VnInputDate.vue |  7 +++----
 src/components/common/VnInputTime.vue |  6 ++----
 src/components/common/VnLocation.vue  | 12 ++++--------
 src/components/common/VnSelect.vue    |  6 ++----
 src/composables/useRequired.js        | 13 +++++++++++++
 6 files changed, 29 insertions(+), 28 deletions(-)
 create mode 100644 src/composables/useRequired.js

diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 4534ae4a0..769e7ca44 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -1,9 +1,11 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useValidator } from 'src/composables/useValidator';
-import { useAttrs } from 'vue';
+import { useRequired } from 'src/composables/useRequired';
 
+const $attrs = useAttrs();
+const { isRequired, requiredFieldRule } = useRequired($attrs);
+const { t } = useI18n();
 const emit = defineEmits([
     'update:modelValue',
     'update:options',
@@ -29,12 +31,7 @@ const $props = defineProps({
         default: true,
     },
 });
-const { validations } = useValidator();
-const $attrs = useAttrs();
 
-const { t } = useI18n();
-const isRequired = computed(() => Object.keys($attrs).includes('required'));
-const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const vnInputRef = ref(null);
 const value = computed({
     get() {
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index 87833f411..b822092a5 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -4,10 +4,13 @@ import { date } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import { useAttrs } from 'vue';
 import VnDate from './VnDate.vue';
+import { useRequired } from 'src/composables/useRequired';
 
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 const model = defineModel({ type: [String, Date] });
 const $attrs = useAttrs();
 const { t } = useI18n();
+
 const $props = defineProps({
     isOutlined: {
         type: Boolean,
@@ -18,11 +21,7 @@ const $props = defineProps({
         default: true,
     },
 });
-import { useValidator } from 'src/composables/useValidator';
-const { validations } = useValidator();
 
-const isRequired = computed(() => Object.keys($attrs).includes('required'));
-const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const vnInputDateRef = ref(null);
 
 const dateFormat = 'DD/MM/YYYY';
diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue
index 13e90e021..a0967fdf6 100644
--- a/src/components/common/VnInputTime.vue
+++ b/src/components/common/VnInputTime.vue
@@ -2,10 +2,10 @@
 import { computed, ref, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { date } from 'quasar';
-import { useValidator } from 'src/composables/useValidator';
 import VnTime from './VnTime.vue';
+import { useRequired } from 'src/composables/useRequired';
 
-const { validations } = useValidator();
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 const { t } = useI18n();
 const $attrs = useAttrs();
 const model = defineModel({ type: String });
@@ -21,8 +21,6 @@ const props = defineProps({
 });
 const vnInputTimeRef = ref(null);
 const initialDate = ref(model.value ?? Date.vnNew());
-const isRequired = computed(() => Object.keys($attrs).includes('required'));
-const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const dateFormat = 'HH:mm';
 const isPopupOpen = ref();
diff --git a/src/components/common/VnLocation.vue b/src/components/common/VnLocation.vue
index 7c6e46fdd..16f9fd580 100644
--- a/src/components/common/VnLocation.vue
+++ b/src/components/common/VnLocation.vue
@@ -2,13 +2,12 @@
 import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
 import VnSelectDialog from 'components/common/VnSelectDialog.vue';
 import { useI18n } from 'vue-i18n';
-import { computed, ref } from 'vue';
+import { ref } from 'vue';
+import { useAttrs } from 'vue';
+import { useRequired } from 'src/composables/useRequired';
 const { t } = useI18n();
 const emit = defineEmits(['update:model-value', 'update:options']);
-const { validations } = useValidator();
-
-import { useAttrs } from 'vue';
-import { useValidator } from 'src/composables/useValidator';
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 const $attrs = useAttrs();
 const props = defineProps({
     location: {
@@ -17,9 +16,6 @@ const props = defineProps({
     },
 });
 
-const isRequired = computed(() => Object.keys($attrs).includes('required'));
-const requiredFieldRule = (val) => validations().required(isRequired.value, val);
-
 const mixinRules = [requiredFieldRule];
 const locationProperties = [
     'postcode',
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 4a4730784..662efcfe9 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -2,10 +2,11 @@
 import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import FetchData from 'src/components/FetchData.vue';
-import { useValidator } from 'src/composables/useValidator';
+import { useRequired } from 'src/composables/useRequired';
 const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 const $attrs = useAttrs();
 const { t } = useI18n();
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 const $props = defineProps({
     modelValue: {
         type: [String, Number, Object],
@@ -88,10 +89,7 @@ const $props = defineProps({
         default: false,
     },
 });
-const { validations } = useValidator();
 
-const isRequired = computed(() => Object.keys($attrs).includes('required'));
-const requiredFieldRule = (val) => validations().required(isRequired.value, val);
 const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
     toRefs($props);
diff --git a/src/composables/useRequired.js b/src/composables/useRequired.js
new file mode 100644
index 000000000..e650c91f5
--- /dev/null
+++ b/src/composables/useRequired.js
@@ -0,0 +1,13 @@
+import { useValidator } from 'src/composables/useValidator';
+
+export function useRequired($attrs) {
+    const { validations } = useValidator();
+
+    const isRequired = Object.keys($attrs).includes('required');
+    const requiredFieldRule = (val) => validations().required(isRequired, val);
+
+    return {
+        isRequired,
+        requiredFieldRule,
+    };
+}

From 1761cc23e0166f3c94c4e7b8e72c8883301bb347 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 30 Oct 2024 08:29:04 +0100
Subject: [PATCH 136/207] feat: use composable to unify logic

---
 src/components/common/VnInputDate.vue | 2 +-
 src/components/common/VnInputTime.vue | 2 +-
 src/components/common/VnLocation.vue  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index b822092a5..fcc04ddf7 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -6,9 +6,9 @@ import { useAttrs } from 'vue';
 import VnDate from './VnDate.vue';
 import { useRequired } from 'src/composables/useRequired';
 
+const $attrs = useAttrs();
 const { isRequired, requiredFieldRule } = useRequired($attrs);
 const model = defineModel({ type: [String, Date] });
-const $attrs = useAttrs();
 const { t } = useI18n();
 
 const $props = defineProps({
diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue
index a0967fdf6..6724c00b5 100644
--- a/src/components/common/VnInputTime.vue
+++ b/src/components/common/VnInputTime.vue
@@ -5,9 +5,9 @@ import { date } from 'quasar';
 import VnTime from './VnTime.vue';
 import { useRequired } from 'src/composables/useRequired';
 
+const $attrs = useAttrs();
 const { isRequired, requiredFieldRule } = useRequired($attrs);
 const { t } = useI18n();
-const $attrs = useAttrs();
 const model = defineModel({ type: String });
 const props = defineProps({
     timeOnly: {
diff --git a/src/components/common/VnLocation.vue b/src/components/common/VnLocation.vue
index 16f9fd580..6de402a26 100644
--- a/src/components/common/VnLocation.vue
+++ b/src/components/common/VnLocation.vue
@@ -7,8 +7,8 @@ import { useAttrs } from 'vue';
 import { useRequired } from 'src/composables/useRequired';
 const { t } = useI18n();
 const emit = defineEmits(['update:model-value', 'update:options']);
-const { isRequired, requiredFieldRule } = useRequired($attrs);
 const $attrs = useAttrs();
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 const props = defineProps({
     location: {
         type: Object,

From d627c1f698d5bab8a5368b65d049b17d2bd3f2ae Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Sun, 3 Nov 2024 10:29:03 -0300
Subject: [PATCH 137/207] fix: order catalog

---
 src/components/common/VnSelect.vue            |   2 +-
 src/components/ui/VnFilterPanel.vue           |   1 -
 .../Order/Card/CatalogFilterValueDialog.vue   | 150 +++++++++++
 src/pages/Order/Card/OrderCatalogFilter.vue   | 234 ++++++------------
 4 files changed, 231 insertions(+), 156 deletions(-)
 create mode 100644 src/pages/Order/Card/CatalogFilterValueDialog.vue

diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index b0aa648c1..1b3c94bfc 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -120,7 +120,7 @@ watch(options, (newValue) => {
 });
 
 watch(modelValue, async (newValue) => {
-    if (!myOptions.value.some((option) => option[optionValue.value] == newValue))
+    if (!myOptions?.value?.some((option) => option[optionValue.value] == newValue))
         await fetchFilter(newValue);
 
     if ($props.noOne) myOptions.value.unshift(noOneOpt.value);
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 5bdaf150c..a8aca49dd 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -189,7 +189,6 @@ const tags = computed(() => {
     const filteredTags = tagsList.value.filter(
         (tag) => !($props.customTags || []).includes(tag.label)
     );
-    console.log('formatTags: ', formatTags(filteredTags));
     return formatTags(filteredTags);
 });
 
diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
new file mode 100644
index 000000000..8e4a9315a
--- /dev/null
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -0,0 +1,150 @@
+<script setup>
+import { ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+import axios from 'axios';
+import VnSelect from 'components/common/VnSelect.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+
+const props = defineProps({
+    tags: {
+        type: Array,
+        default: () => [],
+    },
+});
+
+const emit = defineEmits(['applyTags']);
+const { t } = useI18n();
+
+const tagValues = ref([{}]);
+const tagOptions = ref([]);
+const selectedTag = ref(null);
+
+const applyTags = () => {
+    if (tagValues.value.some((tag) => !tag.value)) return;
+    const tagInfo = {
+        values: [...tagValues.value],
+        tagFk: selectedTag?.value?.id,
+        tagSelection: {
+            name: selectedTag?.value?.name,
+        },
+    };
+    emit('applyTags', tagInfo);
+};
+
+const removeTagGroupParam = (valIndex = null) => {
+    if (!valIndex) {
+        tagValues.value = [{}];
+    } else {
+        (tagValues.value || []).splice(valIndex, 1);
+    }
+};
+
+const getSelectedTagValues = async (tag) => {
+    try {
+        if (!tag?.id) return;
+        const filter = {
+            fields: ['value'],
+            order: 'value ASC',
+            limit: 30,
+        };
+
+        const url = `Tags/${tag?.id}/filterValue`;
+        const params = { filter: JSON.stringify(filter) };
+        const { data } = await axios.get(url, {
+            params,
+        });
+        tagOptions.value = data;
+    } catch (err) {
+        console.error('Error getting selected tag values');
+    }
+};
+</script>
+
+<template>
+    <QForm @submit="applyTags(tagValues)" class="all-pointer-events">
+        <QCard class="q-pa-sm column q-pa-lg">
+            <VnSelect
+                :label="t('params.tag')"
+                v-model="selectedTag"
+                :options="props.tags || []"
+                option-value="id"
+                option-label="name"
+                dense
+                outlined
+                class="q-mb-md"
+                rounded
+                :emit-value="false"
+                use-input
+                @update:model-value="($event) => getSelectedTagValues($event)"
+            />
+            <div
+                v-for="(value, index) in tagValues"
+                :key="value"
+                class="filter-value column align-left"
+            >
+                <div class="col row q-mb-md">
+                    <VnSelect
+                        v-if="!selectedTag?.isFree && tagOptions"
+                        :label="t('components.itemsFilterPanel.value')"
+                        v-model="value.value"
+                        :options="tagOptions || []"
+                        option-value="value"
+                        option-label="value"
+                        dense
+                        outlined
+                        rounded
+                        emit-value
+                        use-input
+                        :disable="!value"
+                        :is-clearable="false"
+                        class="col"
+                    />
+                    <VnInput
+                        v-else
+                        v-model="value.value"
+                        :label="t('components.itemsFilterPanel.value')"
+                        :disable="!value"
+                        is-outlined
+                        :is-clearable="false"
+                        class="col"
+                    />
+                    <QIcon
+                        name="delete"
+                        class="filter-icon col-2"
+                        @click="removeTagGroupParam(index)"
+                    />
+                </div>
+            </div>
+            <QBtn
+                icon="add_circle"
+                shortcut="+"
+                flat
+                class="filter-icon q-mb-md"
+                size="md"
+                dense
+                @click="tagValues.push({})"
+            />
+            <QBtn color="primary" type="submit">
+                {{ t('search') }}
+            </QBtn>
+        </QCard>
+    </QForm>
+</template>
+
+<style scoped lang="scss">
+.filter-icon {
+    font-size: 24px;
+    color: $primary;
+    padding: 0 4px;
+    cursor: pointer;
+}
+</style>
+
+<i18n>
+en:
+    params:
+        tag: Tag
+es:
+    params:
+        tag: Etiqueta
+</i18n>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 5612399d7..28c54c120 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -9,6 +9,7 @@ import VnSelect from 'components/common/VnSelect.vue';
 import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
+import CatalogFilterValueDialog from 'src/pages/Order/Card/CatalogFilterValueDialog.vue';
 
 const { t } = useI18n();
 
@@ -28,13 +29,13 @@ const props = defineProps({
     },
 });
 
+const showValueFilterDialog = ref(false);
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
 const selectedTypeFk = ref(null);
-const selectedTag = ref(null);
-const tagValues = ref([{}]);
-const tagOptions = ref([]);
+const generalSearchParam = ref(null);
+
 const vnFilterPanelRef = ref();
 const orderByList = ref([
     { id: 'relevancy DESC, name', name: t('params.relevancy'), priority: 999 },
@@ -49,20 +50,17 @@ const orderWayList = ref([
 const orderBySelected = ref('relevancy DESC, name');
 const orderWaySelected = ref('ASC');
 
-const resetCategory = () => {
+const resetCategory = (params, search) => {
     selectedCategoryFk.value = null;
     typeList.value = null;
-};
-
-const clearFilter = (key) => {
-    if (key === 'categoryFk') {
-        resetCategory();
-    }
+    params.categoryFk = null;
+    params.typeFk = null;
+    search();
 };
 
 const selectCategory = (params, category, search) => {
     if (params.categoryFk === category?.id) {
-        resetCategory();
+        resetCategory(params, search);
         params.categoryFk = null;
     } else {
         selectedCategoryFk.value = category?.id;
@@ -102,37 +100,28 @@ function exprBuilder(param, value) {
     }
 }
 
-const applyTags = (params, search) => {
-    if (!tagValues.value?.length) {
+const applyTags = (tagInfo, params, search) => {
+    if (!tagInfo || !tagInfo.values.length) {
         params.tagGroups = null;
         search();
+        toggleValueFilterDialog();
         return;
     }
 
-    const tagGroups = {
-        values: [...tagValues.value],
-        tagFk: selectedTag?.value?.id,
-        tagSelection: {
-            name: selectedTag?.value?.name,
-        },
-    };
-
-    params.tagGroups = tagGroups;
+    if (!params.tagGroups) params.tagGroups = [];
+    params.tagGroups.push(tagInfo);
     search();
+    toggleValueFilterDialog();
 };
 
 const removeTagGroupParam = (params, search, valIndex = null) => {
-    if (!params.tagGroups) return;
-
     if (!valIndex) {
         params.tagGroups = null;
-        tagValues.value = [{}];
+        search();
     } else {
-        (tagValues.value || []).splice(valIndex, 1);
-        params.tagGroups.values.splice(valIndex, 1);
+        params.tagGroups.splice(valIndex, 1);
+        search();
     }
-
-    search();
 };
 
 const setCategoryList = (data) => {
@@ -160,37 +149,13 @@ function addOrder(value, field, params) {
     vnFilterPanelRef.value.search();
 }
 
-const getSelectedTagValues = async (tag) => {
-    try {
-        if (!tag?.id) return;
-        const filter = {
-            fields: ['value'],
-            order: 'value ASC',
-            limit: 30,
-        };
-
-        const url = `Tags/${tag?.id}/filterValue`;
-        console.log('url', url);
-        const params = { filter: JSON.stringify(filter) };
-        const { data } = await axios.get(url, {
-            params,
-        });
-        tagOptions.value = data;
-    } catch (err) {
-        console.error('Error getting selected tag values');
-    }
+const toggleValueFilterDialog = () => {
+    showValueFilterDialog.value = !showValueFilterDialog.value;
 };
 
 onMounted(() => {
     selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
     selectedTypeFk.value = getParamWhere(route, 'typeFk');
-    if (route.query.params && JSON.parse(route.query.params).tagGroups) {
-        const tagGroups = JSON.parse(route.query.params).tagGroups;
-        tagValues.value = [...tagGroups.values];
-        selectedTag.value = (props.tags || []).find(
-            (tag) => tag.name === tagGroups.tagSelection.name
-        );
-    }
 });
 </script>
 
@@ -202,15 +167,11 @@ onMounted(() => {
         :hidden-tags="['orderFk', 'orderBy']"
         :un-removable-params="['orderFk', 'orderBy']"
         :expr-builder="exprBuilder"
-        :custom-tags="['tagGroups']"
-        @remove="clearFilter"
+        :custom-tags="['tagGroups', 'categoryFk']"
         :redirect="false"
     >
         <template #tags="{ tag, formatFn }">
-            <strong v-if="tag.label === 'categoryFk'">
-                {{ t(selectedCategory?.name || '') }}
-            </strong>
-            <strong v-else-if="tag.label === 'typeFk'">
+            <strong v-if="tag.label === 'typeFk'">
                 {{ t(selectedType?.name || '') }}
             </strong>
             <div v-else class="q-gutter-x-xs">
@@ -219,24 +180,33 @@ onMounted(() => {
             </div>
         </template>
         <template #customTags="{ tags: customTags, params, searchFn }">
-            <template v-for="tag in customTags" :key="tag.label">
-                <template v-if="tag.label === 'tagGroups'">
-                    <VnFilterPanelChip
-                        removable
-                        @remove="removeTagGroupParam(params, searchFn)"
-                    >
-                        <strong class="q-mr-xs">
-                            {{ tag.value?.tagSelection?.name }}:
-                        </strong>
-                        <span>
-                            {{
-                                (tag.value?.values || [])
-                                    .map((item) => `"${item.value}"`)
-                                    .join(', ')
-                            }}
-                        </span>
-                    </VnFilterPanelChip>
-                </template>
+            <template v-for="customTag in customTags" :key="customTag.label">
+                <VnFilterPanelChip
+                    v-for="(tag, valIndex) in Array.isArray(customTag.value)
+                        ? customTag.value
+                        : 1"
+                    :key="valIndex"
+                    removable
+                    @remove="
+                        customTag.label === 'categoryFk'
+                            ? resetCategory(params, searchFn)
+                            : removeTagGroupParam(params, searchFn, valIndex)
+                    "
+                >
+                    <strong v-if="customTag.label === 'categoryFk'">
+                        {{ t(selectedCategory?.name || '') }}
+                    </strong>
+                    <strong v-if="tag?.tagSelection?.name" class="q-mr-xs">
+                        {{ tag.tagSelection.name }}:
+                    </strong>
+                    <span>
+                        {{
+                            (tag?.values || [])
+                                .map((item) => `"${item.value}"`)
+                                .join(', ')
+                        }}
+                    </span>
+                </VnFilterPanelChip>
             </template>
         </template>
         <template #body="{ params, searchFn }">
@@ -320,70 +290,43 @@ onMounted(() => {
                 </QItemSection>
             </QItem>
             <QSeparator />
-            <QItem class="q-mt-md">
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.tag')"
-                        v-model="selectedTag"
-                        :options="props.tags || []"
-                        option-value="id"
-                        option-label="name"
-                        dense
-                        outlined
-                        rounded
-                        :emit-value="false"
-                        use-input
-                        @update:model-value="($event) => getSelectedTagValues($event)"
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem
-                v-for="(value, index) in tagValues"
-                :key="value"
-                class="q-mt-md filter-value"
-            >
-                <VnSelect
-                    v-if="!selectedTag?.isFree && tagOptions"
-                    :label="t('components.itemsFilterPanel.value')"
-                    v-model="value.value"
-                    :options="tagOptions || []"
-                    option-value="value"
-                    option-label="value"
-                    dense
-                    outlined
-                    rounded
-                    emit-value
-                    use-input
-                    :disable="!value"
-                    :is-clearable="false"
-                    @update:model-value="applyTags(params, searchFn)"
-                />
+
+            <QItem class="q-mt-lg">
                 <VnInput
-                    v-else
-                    v-model="value.value"
                     :label="t('components.itemsFilterPanel.value')"
-                    :disable="!value"
                     is-outlined
                     :is-clearable="false"
-                    @keyup.enter="applyTags(params, searchFn)"
-                />
-                <QIcon
-                    name="delete"
-                    class="filter-icon"
-                    @click="removeTagGroupParam(params, searchFn, index)"
-                />
-            </QItem>
-            <QItem class="q-mt-lg">
-                <QBtn
-                    icon="add_circle"
-                    shortcut="+"
-                    flat
-                    class="filter-icon"
-                    size="md"
-                    @click="tagValues.push({})"
-                />
+                    v-model="generalSearchParam"
+                    @keyup.enter="
+                        applyTags(
+                            { values: [{ value: generalSearchParam }] },
+                            params,
+                            searchFn
+                        )
+                    "
+                >
+                    <template #prepend>
+                        <QIcon name="search" />
+                    </template>
+                    <template #append>
+                        <QBtn
+                            icon="add_circle"
+                            shortcut="+"
+                            flat
+                            color="primary"
+                            size="md"
+                            @click="toggleValueFilterDialog()"
+                        />
+                    </template>
+                </VnInput>
             </QItem>
             <QSeparator />
+            <QDialog v-model="showValueFilterDialog">
+                <CatalogFilterValueDialog
+                    :tags="tags"
+                    @apply-tags="($event) => applyTags($event, params, searchFn)"
+                />
+            </QDialog>
         </template>
     </VnFilterPanel>
 </template>
@@ -416,23 +359,6 @@ onMounted(() => {
         cursor: pointer;
     }
 }
-
-.filter-icon {
-    font-size: 24px;
-    color: $primary;
-    padding: 0 4px;
-    cursor: pointer;
-}
-
-.filter-input {
-    flex-shrink: 1;
-    min-width: 0;
-}
-
-.filter-value {
-    display: flex;
-    align-items: center;
-}
 </style>
 
 <i18n>

From 08204aa5f085d9045644a7048d537ab70b9737f0 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 4 Nov 2024 13:02:39 +0100
Subject: [PATCH 138/207] refactor(InvoiceInBasicData): use VnDms

---
 src/components/FormModel.vue                  |   1 +
 src/components/common/VnDms.vue               |   9 +-
 .../InvoiceIn/Card/InvoiceInBasicData.vue     | 440 ++++--------------
 src/pages/InvoiceIn/Card/InvoiceInCard.vue    |  17 +
 4 files changed, 114 insertions(+), 353 deletions(-)

diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 9ac2d38a5..c668769e5 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -272,6 +272,7 @@ defineExpose({
     hasChanges,
     reset,
     fetch,
+    formData,
 });
 </script>
 <template>
diff --git a/src/components/common/VnDms.vue b/src/components/common/VnDms.vue
index 920b7f137..946cd8264 100644
--- a/src/components/common/VnDms.vue
+++ b/src/components/common/VnDms.vue
@@ -31,6 +31,10 @@ const $props = defineProps({
         type: String,
         default: null,
     },
+    description: {
+        type: String,
+        default: null,
+    },
 });
 
 const warehouses = ref();
@@ -43,7 +47,8 @@ const dms = ref({});
 onMounted(() => {
     defaultData();
     if (!$props.formInitialData)
-        dms.value.description = t($props.model + 'Description', dms.value);
+        dms.value.description =
+            $props.description ?? t($props.model + 'Description', dms.value);
 });
 function onFileChange(files) {
     dms.value.hasFileAttached = !!files;
@@ -54,7 +59,6 @@ function mapperDms(data) {
     const formData = new FormData();
     const { files } = data;
     if (files) formData.append(files?.name, files);
-    delete data.files;
 
     const dms = {
         hasFile: !!data.hasFile,
@@ -78,6 +82,7 @@ async function save() {
     const body = mapperDms(dms.value);
     const response = await axios.post(getUrl(), body[0], body[1]);
     emit('onDataSaved', body[1].params, response);
+    delete dms.value.files;
     return response;
 }
 
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index c9468557f..f9498f52e 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -3,8 +3,6 @@ import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
-import axios from 'axios';
-import { useArrayData } from 'src/composables/useArrayData';
 import { downloadFile } from 'src/composables/downloadFile';
 import FormModel from 'components/FormModel.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
@@ -12,15 +10,15 @@ import FetchData from 'src/components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+import VnDms from 'src/components/common/VnDms.vue';
+import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import axios from 'axios';
 
-const quasar = useQuasar();
 const { t } = useI18n();
 
-const dms = ref({});
 const route = useRoute();
+const quasar = useQuasar();
 const editDownloadDisabled = ref(false);
-const arrayData = useArrayData();
-const invoiceIn = computed(() => arrayData.store.data);
 const userConfig = ref(null);
 const invoiceId = computed(() => +route.params.id);
 
@@ -36,98 +34,25 @@ const warehousesRef = ref();
 const allowTypesRef = ref();
 const allowedContentTypes = ref([]);
 const sageWithholdings = ref([]);
-const inputFileRef = ref();
-const editDmsRef = ref();
-const createDmsRef = ref();
+const documentDialogRef = ref({});
+const invoiceInRef = ref({});
 
-async function checkFileExists(dmsId) {
-    if (!dmsId) return;
-    try {
-        await axios.get(`Dms/${dmsId}`, { fields: ['id'] });
-        editDownloadDisabled.value = false;
-    } catch (e) {
-        editDownloadDisabled.value = true;
-    }
-}
-
-async function setEditDms(dmsId) {
-    const { data } = await axios.get(`Dms/${dmsId}`);
-    dms.value = {
-        warehouseId: data.warehouseFk,
-        companyId: data.companyFk,
-        dmsTypeId: data.dmsTypeFk,
-        ...data,
-    };
-
-    if (!allowedContentTypes.value.length) await allowTypesRef.value.fetch();
-
-    editDmsRef.value.show();
-}
-
-async function setCreateDms() {
-    const { data } = await axios.get('DmsTypes/findOne', {
-        where: { code: 'invoiceIn' },
-    });
-    dms.value = {
-        reference: invoiceIn.value.supplierRef,
-        warehouseId: userConfig.value.warehouseFk,
-        companyId: userConfig.value.companyFk,
-        dmsTypeId: data.id,
-        description: invoiceIn.value.supplier.name,
-        hasFile: true,
-        hasFileAttached: true,
-        files: null,
-    };
-
-    createDmsRef.value.show();
-}
-
-async function onSubmit() {
-    try {
-        const isEdit = !!dms.value.id;
-        const errors = {
-            companyId: `The company can't be empty`,
-            warehouseId: `The warehouse can't be empty`,
-            dmsTypeId: `The DMS Type can't be empty`,
-            description: `The description can't be empty`,
-        };
-
-        Object.keys(errors).forEach((key) => {
-            if (!dms.value[key]) throw Error(t(errors[key]));
+function deleteFile(dmsFk) {
+    quasar
+        .dialog({
+            component: VnConfirm,
+            componentProps: {
+                title: t('globals.confirmDeletion'),
+                message: t('globals.confirmDeletionMessage'),
+            },
+        })
+        .onOk(async () => {
+            await axios.post(`dms/${dmsFk}/removeFile`);
+            invoiceInRef.value.formData.dmsFk = null;
+            invoiceInRef.value.formData.dms = undefined;
+            invoiceInRef.value.hasChanges = true;
+            invoiceInRef.value.save();
         });
-
-        if (!isEdit && !dms.value.files) throw Error(t(`The files can't be empty`));
-
-        const formData = new FormData();
-
-        if (dms.value.files) {
-            for (let i = 0; i < dms.value.files.length; i++)
-                formData.append(dms.value.files[i].name, dms.value.files[i]);
-            dms.value.hasFileAttached = true;
-        }
-        const url = isEdit ? `dms/${dms.value.id}/updateFile` : 'Dms/uploadFile';
-        const { data } = await axios.post(url, formData, {
-            params: dms.value,
-        });
-
-        if (data.length) invoiceIn.value.dmsFk = data[0].id;
-
-        if (!isEdit) {
-            createDmsRef.value.hide();
-        } else {
-            editDmsRef.value.hide();
-        }
-
-        quasar.notify({
-            message: t('globals.dataSaved'),
-            type: 'positive',
-        });
-    } catch (error) {
-        quasar.notify({
-            message: t(`${error.message}`),
-            type: 'negative',
-        });
-    }
 }
 </script>
 <template>
@@ -181,10 +106,12 @@ async function onSubmit() {
         @on-fetch="(data) => (sageWithholdings = data)"
     />
     <FormModel
+        ref="invoiceInRef"
         model="InvoiceIn"
         :go-to="`/invoice-in/${invoiceId}/vat`"
-        auto-load
         :url-update="`InvoiceIns/${invoiceId}/updateInvoiceIn`"
+        @on-fetch="(data) => (documentDialogRef.supplierName = data.supplier.nickname)"
+        auto-load
     >
         <template #form="{ data }">
             <VnRow>
@@ -242,16 +169,18 @@ async function onSubmit() {
                         </QItem>
                     </template>
                 </VnSelect>
-                <VnInput
-                    :label="t('Document')"
-                    v-model="data.dmsFk"
-                    clearable
-                    clear-icon="close"
-                    @update:model-value="checkFileExists(data.dmsFk)"
-                >
-                    <template #prepend>
+
+                <div class="row no-wrap">
+                    <VnInput
+                        :label="t('Document')"
+                        v-model="data.dmsFk"
+                        clearable
+                        clear-icon="close"
+                        class="full-width"
+                        :disable="true"
+                    />
+                    <div v-if="data.dmsFk" class="row no-wrap q-pa-xs q-gutter-x-xs">
                         <QBtn
-                            v-if="data.dmsFk"
                             :class="{
                                 'no-pointer-events': editDownloadDisabled,
                             }"
@@ -262,33 +191,51 @@ async function onSubmit() {
                             round
                             @click="downloadFile(data.dmsFk)"
                         />
-                    </template>
-                    <template #append>
                         <QBtn
                             :class="{
                                 'no-pointer-events': editDownloadDisabled,
                             }"
                             :disable="editDownloadDisabled"
-                            v-if="data.dmsFk"
                             icon="edit"
                             round
                             padding="xs"
-                            @click="setEditDms(data.dmsFk)"
+                            @click="
+                                () => {
+                                    documentDialogRef.show = true;
+                                    documentDialogRef.dms = data.dms;
+                                }
+                            "
                         >
                             <QTooltip>{{ t('Edit document') }}</QTooltip>
                         </QBtn>
                         <QBtn
-                            v-else
-                            icon="add_circle"
-                            round
-                            shortcut="+"
+                            :class="{
+                                'no-pointer-events': editDownloadDisabled,
+                            }"
+                            :disable="editDownloadDisabled"
+                            icon="delete"
+                            :title="t('Delete file')"
                             padding="xs"
-                            @click="setCreateDms()"
-                        >
-                            <QTooltip>{{ t('Create document') }}</QTooltip>
-                        </QBtn>
-                    </template>
-                </VnInput>
+                            round
+                            @click="deleteFile(data.dmsFk)"
+                        />
+                    </div>
+                    <QBtn
+                        v-else
+                        icon="add_circle"
+                        round
+                        shortcut="+"
+                        padding="xs"
+                        @click="
+                            () => {
+                                documentDialogRef.show = true;
+                                delete documentDialogRef.dms;
+                            }
+                        "
+                    >
+                        <QTooltip>{{ t('Create document') }}</QTooltip>
+                    </QBtn>
+                </div>
             </VnRow>
             <VnRow>
                 <VnSelect
@@ -319,237 +266,28 @@ async function onSubmit() {
             </VnRow>
         </template>
     </FormModel>
-    <QDialog ref="editDmsRef">
-        <QForm @submit="onSubmit()" class="all-pointer-events">
-            <QCard class="q-pa-sm">
-                <QCardSection class="row items-center q-pb-none">
-                    <span class="text-primary text-h6">
-                        <QIcon name="edit" class="q-mr-xs" />
-                        {{ t('Edit document') }}
-                    </span>
-                    <QSpace />
-                    <QBtn icon="close" flat round dense v-close-popup />
-                </QCardSection>
-                <QCardSection class="q-py-none">
-                    <QItem>
-                        <VnInput
-                            class="full-width q-pa-xs"
-                            :label="t('Reference')"
-                            v-model="dms.reference"
-                            clearable
-                            clear-icon="close"
-                        />
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="t('Company')"
-                            v-model="dms.companyId"
-                            :options="companies"
-                            option-value="id"
-                            option-label="code"
-                            :required="true"
-                        />
-                    </QItem>
-                    <QItem>
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="t('Warehouse')"
-                            v-model="dms.warehouseId"
-                            :options="warehouses"
-                            option-value="id"
-                            option-label="name"
-                            :required="true"
-                        />
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="t('Type')"
-                            v-model="dms.dmsTypeId"
-                            :options="dmsTypes"
-                            option-value="id"
-                            option-label="name"
-                            :required="true"
-                        />
-                    </QItem>
-                    <QItem>
-                        <VnInput
-                            :label="t('Description')"
-                            v-model="dms.description"
-                            :required="true"
-                            type="textarea"
-                            class="full-width q-pa-xs"
-                            size="lg"
-                            autogrow
-                            clearable
-                            clear-icon="close"
-                        />
-                    </QItem>
-                    <QItem>
-                        <QFile
-                            ref="inputFileRef"
-                            class="full-width q-pa-xs"
-                            :label="t('File')"
-                            v-model="dms.files"
-                            multiple
-                            :accept="allowedContentTypes.join(',')"
-                            clearable
-                            clear-icon="close"
-                        >
-                            <template #append>
-                                <QBtn
-                                    icon="attach_file_add"
-                                    flat
-                                    round
-                                    padding="xs"
-                                    @click="inputFileRef.pickFiles()"
-                                >
-                                    <QTooltip>
-                                        {{ t('globals.selectFile') }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QBtn icon="info" flat round padding="xs">
-                                    <QTooltip max-width="30rem">
-                                        {{
-                                            `${t(
-                                                'Allowed content types'
-                                            )}: ${allowedContentTypes.join(', ')}`
-                                        }}
-                                    </QTooltip>
-                                </QBtn>
-                            </template>
-                        </QFile>
-                    </QItem>
-                    <QItem>
-                        <QCheckbox
-                            :label="t('Generate identifier for original file')"
-                            v-model="dms.hasFile"
-                        />
-                    </QItem>
-                </QCardSection>
-                <QCardActions class="justify-end">
-                    <QBtn
-                        flat
-                        :label="t('globals.close')"
-                        color="primary"
-                        v-close-popup
-                    />
-                    <QBtn :label="t('globals.save')" color="primary" @click="onSubmit" />
-                </QCardActions>
-            </QCard>
-        </QForm>
-    </QDialog>
-    <QDialog ref="createDmsRef">
-        <QForm @submit="onSubmit()" class="all-pointer-events">
-            <QCard class="q-pa-sm">
-                <QCardSection class="row items-center q-pb-none">
-                    <span class="text-primary text-h6">
-                        <QIcon name="edit" class="q-mr-xs" />
-                        {{ t('Create document') }}
-                    </span>
-                    <QSpace />
-                    <QBtn icon="close" flat round dense v-close-popup />
-                </QCardSection>
-                <QCardSection class="q-pb-none">
-                    <QItem>
-                        <VnInput
-                            class="full-width q-pa-xs"
-                            :label="t('Reference')"
-                            v-model="dms.reference"
-                        />
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="`${t('Company')}*`"
-                            v-model="dms.companyId"
-                            :options="companies"
-                            option-value="id"
-                            option-label="code"
-                            :required="true"
-                        />
-                    </QItem>
-                    <QItem>
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="`${t('Warehouse')}*`"
-                            v-model="dms.warehouseId"
-                            :options="warehouses"
-                            option-value="id"
-                            option-label="name"
-                            :required="true"
-                        />
-                        <VnSelect
-                            class="full-width q-pa-xs"
-                            :label="`${t('Type')}*`"
-                            v-model="dms.dmsTypeId"
-                            :options="dmsTypes"
-                            option-value="id"
-                            option-label="name"
-                            :required="true"
-                        />
-                    </QItem>
-                    <QItem>
-                        <VnInput
-                            class="full-width q-pa-xs"
-                            type="textarea"
-                            size="lg"
-                            autogrow
-                            :label="`${t('Description')}*`"
-                            v-model="dms.description"
-                            clearable
-                            clear-icon="close"
-                            :rules="[(val) => val.length || t('Required field')]"
-                        />
-                    </QItem>
-                    <QItem>
-                        <QFile
-                            ref="inputFileRef"
-                            class="full-width q-pa-xs"
-                            :label="t('File')"
-                            v-model="dms.files"
-                            multiple
-                            :accept="allowedContentTypes.join(',')"
-                            clearable
-                            clear-icon="close"
-                        >
-                            <template #append>
-                                <QBtn
-                                    icon="attach_file_add"
-                                    flat
-                                    round
-                                    padding="xs"
-                                    @click="inputFileRef.pickFiles()"
-                                >
-                                    <QTooltip>
-                                        {{ t('globals.selectFile') }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QBtn icon="info" flat round padding="xs">
-                                    <QTooltip max-width="30rem">
-                                        {{
-                                            `${t(
-                                                'Allowed content types'
-                                            )}: ${allowedContentTypes.join(', ')}`
-                                        }}
-                                    </QTooltip>
-                                </QBtn>
-                            </template>
-                        </QFile>
-                    </QItem>
-                    <QItem>
-                        <QCheckbox
-                            :label="t('Generate identifier for original file')"
-                            v-model="dms.hasFile"
-                        />
-                    </QItem>
-                </QCardSection>
-                <QCardActions align="right">
-                    <QBtn
-                        flat
-                        :label="t('globals.close')"
-                        color="primary"
-                        v-close-popup
-                    />
-                    <QBtn :label="t('globals.save')" color="primary" @click="onSubmit" />
-                </QCardActions>
-            </QCard>
-        </QForm>
+    <QDialog v-model="documentDialogRef.show">
+        <VnDms
+            model="dms"
+            default-dms-code="invoiceIn"
+            :form-initial-data="documentDialogRef.dms"
+            :url="
+                documentDialogRef.dms
+                    ? `Dms/${documentDialogRef.dms.id}/updateFile`
+                    : 'Dms/uploadFile'
+            "
+            :description="documentDialogRef.supplierName"
+            @on-data-saved="
+                (_, { data }) => {
+                    let dmsData = data;
+                    if (Array.isArray(data)) dmsData = data[0];
+                    invoiceInRef.formData.dmsFk = dmsData.id;
+                    invoiceInRef.formData.dms = dmsData;
+                    invoiceInRef.hasChanges = true;
+                    invoiceInRef.save();
+                }
+            "
+        />
     </QDialog>
 </template>
 <style lang="scss" scoped>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInCard.vue b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
index 0fe2a2368..b16183e52 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInCard.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
@@ -20,6 +20,23 @@ const filter = {
         { relation: 'invoiceInDueDay' },
         { relation: 'company' },
         { relation: 'currency' },
+        {
+            relation: 'dms',
+            scope: {
+                fields: [
+                    'dmsTypeFk',
+                    'reference',
+                    'hardCopyNumber',
+                    'workerFk',
+                    'description',
+                    'hasFile',
+                    'file',
+                    'created',
+                    'companyFk',
+                    'warehouseFk',
+                ],
+            },
+        },
     ],
 };
 

From e050a077d4fdb77e62598c9466eb282fcb67e189 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 4 Nov 2024 13:41:37 +0100
Subject: [PATCH 139/207] test: refactor e2e

---
 src/components/common/VnDms.vue               |  1 +
 src/components/ui/VnConfirm.vue               |  1 +
 .../InvoiceIn/Card/InvoiceInBasicData.vue     |  7 +++-
 .../invoiceIn/invoiceInBasicData.spec.js      | 33 +++++++++++--------
 4 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/components/common/VnDms.vue b/src/components/common/VnDms.vue
index 946cd8264..3f9e65740 100644
--- a/src/components/common/VnDms.vue
+++ b/src/components/common/VnDms.vue
@@ -170,6 +170,7 @@ function addDefaultData(data) {
                     @update:model-value="onFileChange(dms.files)"
                     class="required"
                     :display-value="dms.file"
+                    data-cy="VnDms_inputFile"
                 >
                     <template #append>
                         <QIcon
diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index d6b1ac0a3..0b1913383 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -103,6 +103,7 @@ function cancel() {
                     @click="confirm()"
                     unelevated
                     autofocus
+                    data-cy="VnConfirm_confirm"
                 />
             </QCardActions>
         </QCard>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index f9498f52e..209681b7c 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -179,7 +179,11 @@ function deleteFile(dmsFk) {
                         class="full-width"
                         :disable="true"
                     />
-                    <div v-if="data.dmsFk" class="row no-wrap q-pa-xs q-gutter-x-xs">
+                    <div
+                        v-if="data.dmsFk"
+                        class="row no-wrap q-pa-xs q-gutter-x-xs"
+                        data-cy="dms-buttons"
+                    >
                         <QBtn
                             :class="{
                                 'no-pointer-events': editDownloadDisabled,
@@ -232,6 +236,7 @@ function deleteFile(dmsFk) {
                                 delete documentDialogRef.dms;
                             }
                         "
+                        data-cy="dms-create"
                     >
                         <QTooltip>{{ t('Create document') }}</QTooltip>
                     </QBtn>
diff --git a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
index e1939fe5a..2016fca6d 100644
--- a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
@@ -2,9 +2,8 @@
 describe('InvoiceInBasicData', () => {
     const formInputs = '.q-form > .q-card input';
     const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
-    const documentBtns = '.q-form .q-field button';
+    const documentBtns = '[data-cy="dms-buttons"] button';
     const dialogInputs = '.q-dialog input';
-    const dialogActionBtns = '.q-card__actions button';
 
     beforeEach(() => {
         cy.login('developer');
@@ -21,27 +20,35 @@ describe('InvoiceInBasicData', () => {
         cy.get(formInputs).eq(1).invoke('val').should('eq', '4739');
     });
 
-    it('should edit the dms data', () => {
+    it('should edit, remove and create the dms data', () => {
         const firtsInput = 'Ticket:65';
         const secondInput = "I don't know what posting here!";
 
+        //edit
         cy.get(documentBtns).eq(1).click();
         cy.get(dialogInputs).eq(0).type(`{selectall}${firtsInput}`);
         cy.get('textarea').type(`{selectall}${secondInput}`);
-        cy.get(dialogActionBtns).eq(1).click();
-
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get(documentBtns).eq(1).click();
         cy.get(dialogInputs).eq(0).invoke('val').should('eq', firtsInput);
         cy.get('textarea').invoke('val').should('eq', secondInput);
-    });
+        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.checkNotification('Data saved');
 
-    it('should throw an error creating a new dms if a file is not attached', () => {
-        cy.get(formInputs).eq(7).type('{selectall}{backspace}');
-        cy.get(documentBtns).eq(0).click();
-        cy.get(dialogActionBtns).eq(1).click();
-        cy.get('.q-notification__message').should(
-            'have.text',
-            "The files can't be empty"
+        //remove
+        cy.get(documentBtns).eq(2).click();
+        cy.get('[data-cy="VnConfirm_confirm"]').click();
+        cy.checkNotification('Data saved');
+
+        //create
+        cy.get('[data-cy="dms-create"]').eq(0).click();
+        cy.get('[data-cy="VnDms_inputFile"').selectFile(
+            'test/cypress/fixtures/image.jpg',
+            {
+                force: true,
+            }
         );
+        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.checkNotification('Data saved');
     });
 });

From 1f9d850fbeff23c8d44367704f9945c15920a709 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 5 Nov 2024 10:02:29 +0100
Subject: [PATCH 140/207] chore: refs #8078 rollback ref

---
 src/pages/Ticket/Card/TicketDescriptorMenu.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 8efd0f1e1..bf4a1efb4 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -659,7 +659,7 @@ async function uploadDocuware(force) {
             </QList>
         </QMenu>
     </QItem>
-    <QItem @click="$refs.weightDialog.dialogRef.show()" v-ripple clickable>
+    <QItem @click="$refs.weightDialog.show()" v-ripple clickable>
         <QItemSection avatar>
             <QIcon name="weight" />
         </QItemSection>

From 86e6bef90f18d98c391a2046c9223a140e289f59 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 5 Nov 2024 10:37:35 +0100
Subject: [PATCH 141/207] chore: refs #8078 fiz tests

---
 test/vitest/__tests__/components/VnTable.spec.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/vitest/__tests__/components/VnTable.spec.js b/test/vitest/__tests__/components/VnTable.spec.js
index d11c2b6c3..162df727d 100644
--- a/test/vitest/__tests__/components/VnTable.spec.js
+++ b/test/vitest/__tests__/components/VnTable.spec.js
@@ -20,12 +20,12 @@ describe('VnTable', () => {
     describe('handleSelection()', () => {
         const rows = [{ $index: 0 }, { $index: 1 }, { $index: 2 }];
         const selectedRows = [{ $index: 1 }];
-        it('should add rows to selected when shift key is pressed and rows are added', () => {
+        it('should add rows to selected when shift key is pressed and rows are added except last one', () => {
             vm.handleSelection(
                 { evt: { shiftKey: true }, added: true, rows: selectedRows },
                 rows
             );
-            expect(vm.selected).toEqual([{ $index: 0 }, { $index: 1 }]);
+            expect(vm.selected).toEqual([{ $index: 0 }]);
         });
 
         it('should not add rows to selected when shift key is not pressed', () => {

From 4a95a0e39ae71f8ae8210bfe1d4cabc6021d9e0e Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 5 Nov 2024 11:59:38 +0100
Subject: [PATCH 142/207] chore: refs #7273 sticky add btn & refactor

---
 src/pages/Item/Card/ItemTags.vue | 37 +++++++++++++++++---------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index 6f31d0cf8..e59085402 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -109,7 +109,11 @@ const insertTag = (rows) => {
             >
                 <template #body="{ rows, validate }">
                     <QCard class="q-px-lg q-pt-md q-pb-sm">
-                        <VnRow v-for="(row, index) in rows" :key="index">
+                        <VnRow
+                            v-for="(row, index) in rows"
+                            :key="index"
+                            class="items-center"
+                        >
                             <VnSelect
                                 :label="t('itemTags.tag')"
                                 :options="tagOptions"
@@ -153,13 +157,14 @@ const insertTag = (rows) => {
                                 :required="true"
                                 :rules="validate('itemTag.priority')"
                             />
-                            <div class="row justify-center items-center" style="flex: 0">
+                            <div class="row justify-center" style="flex: 0">
                                 <QIcon
                                     @click="itemTagsRef.remove([row])"
                                     class="fill-icon-on-hover"
                                     color="primary"
                                     name="delete"
                                     size="sm"
+                                    dense
                                 >
                                     <QTooltip>
                                         {{ t('itemTags.removeTag') }}
@@ -167,22 +172,20 @@ const insertTag = (rows) => {
                                 </QIcon>
                             </div>
                         </VnRow>
-                        <VnRow class="justify-center items-center">
-                            <QBtn
-                                @click="insertTag(rows)"
-                                class="cursor-pointer"
-                                color="primary"
-                                flat
-                                icon="add"
-                                shortcut="+"
-                                style="flex: 0"
-                            >
-                                <QTooltip>
-                                    {{ t('itemTags.addTag') }}
-                                </QTooltip>
-                            </QBtn>
-                        </VnRow>
                     </QCard>
+                    <QPageSticky position="bottom-right" :offset="[25, 25]">
+                        <QBtn
+                            @click="insertTag(rows)"
+                            color="primary"
+                            icon="add"
+                            shortcut="+"
+                            fab
+                        >
+                            <QTooltip>
+                                {{ t('itemTags.addTag') }}
+                            </QTooltip>
+                        </QBtn>
+                    </QPageSticky>
                 </template>
             </CrudModel>
         </QPage>

From 9959fbf005f9576fda495ac7b8bcd04542c617ef Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 5 Nov 2024 12:23:11 +0100
Subject: [PATCH 143/207] fix: refs #7273 use same filter

---
 src/pages/Item/ItemList.vue | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index a480cfff6..f789d2cd0 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -12,6 +12,8 @@ import ItemSummary from '../Item/Card/ItemSummary.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
 import { cloneItem } from 'src/pages/Item/composables/cloneItem';
+import RightMenu from 'src/components/common/RightMenu.vue';
+import ItemListFilter from './ItemListFilter.vue';
 
 const entityId = computed(() => route.params.id);
 const { openCloneDialog } = cloneItem();
@@ -311,6 +313,11 @@ const columns = computed(() => [
         :label="t('item.searchbar.label')"
         :info="t('You can search by id')"
     />
+    <RightMenu>
+        <template #right-panel>
+            <ItemListFilter data-key="ItemList" />
+        </template>
+    </RightMenu>
     <VnTable
         ref="tableRef"
         data-key="ItemList"
@@ -329,6 +336,7 @@ const columns = computed(() => [
         auto-load
         redirect="Item"
         :is-editable="false"
+        :right-search="false"
         :filer="itemFilter"
     >
         <template #column-id="{ row }">

From abd7b76636c53f69c5d4ff6e0cec87f037170fa8 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 5 Nov 2024 13:50:25 +0100
Subject: [PATCH 144/207] feat(VnInput): empty to null

---
 src/components/common/VnInput.vue | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 1246eedcd..93cf332a3 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -27,6 +27,10 @@ const $props = defineProps({
         type: Boolean,
         default: true,
     },
+    emptyToNull: {
+        type: Boolean,
+        default: true,
+    },
 });
 const { validations } = useValidator();
 
@@ -39,6 +43,7 @@ const value = computed({
         return $props.modelValue;
     },
     set(value) {
+        if ($props.emptyToNull && value === '') value = null;
         emit('update:modelValue', value);
     },
 });

From a2bbf4474d4a801ece1cb52d57f61f55ecfe2ebb Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 6 Nov 2024 13:52:59 +0100
Subject: [PATCH 145/207] fix(InvoiceOutGlobal): parallelism

---
 src/pages/InvoiceOut/InvoiceOutGlobalForm.vue |  7 ++--
 src/stores/invoiceOutGlobal.js                | 37 +++++++++----------
 2 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
index 5bcb21001..e85f1f44c 100644
--- a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
+++ b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
@@ -13,7 +13,7 @@ const { t } = useI18n();
 const invoiceOutGlobalStore = useInvoiceOutGlobalStore();
 
 // invoiceOutGlobalStore state and getters
-const { initialDataLoading, formInitialData, invoicing, status } =
+const { initialDataLoading, formInitialData, status } =
     storeToRefs(invoiceOutGlobalStore);
 
 // invoiceOutGlobalStore actions
@@ -151,9 +151,8 @@ onMounted(async () => {
                 rounded
             />
         </div>
-
         <QBtn
-            v-if="!invoicing"
+            v-if="!getStatus || getStatus === 'stopping'"
             :label="t('invoiceOut')"
             type="submit"
             color="primary"
@@ -163,7 +162,7 @@ onMounted(async () => {
             dense
         />
         <QBtn
-            v-if="invoicing"
+            v-else
             :label="t('stop')"
             color="primary"
             class="q-mt-md full-width"
diff --git a/src/stores/invoiceOutGlobal.js b/src/stores/invoiceOutGlobal.js
index 42acac013..b17f41564 100644
--- a/src/stores/invoiceOutGlobal.js
+++ b/src/stores/invoiceOutGlobal.js
@@ -93,7 +93,7 @@ export const useInvoiceOutGlobalStore = defineStore({
 
         async makeInvoice(formData, clientsToInvoice) {
             this.invoicing = true;
-            this.status = 'packageInvoicing';
+            const promises = [];
             try {
                 this.printer = formData.printer;
                 const params = {
@@ -118,10 +118,11 @@ export const useInvoiceOutGlobalStore = defineStore({
                     );
                     throw new Error("There aren't addresses to invoice");
                 }
-
-                for (const address of this.addresses) {
-                    await this.invoiceClient(address, formData);
+                this.status = 'invoicing';
+                for (let index = 0; index < this.parallelism; index++) {
+                    promises.push(this.invoiceClient(formData, index));
                 }
+                await Promise.all(promises);
             } catch (err) {
                 this.handleError(err);
             }
@@ -171,17 +172,15 @@ export const useInvoiceOutGlobalStore = defineStore({
             }
         },
 
-        async invoiceClient(address, formData) {
+        async invoiceClient(formData, index) {
+            const address = this.addresses[index];
+            if (!address || !this.status || this.status == 'stopping') {
+                this.status = 'stopping';
+                this.invoicing = false;
+                return;
+            }
+            console.log('address: ', address);
             try {
-                if (this.nRequests === this.parallelism || this.isInvoicing) return;
-
-                if (this.status === 'stopping') {
-                    if (this.nRequests) return;
-                    this.invoicing = false;
-                    this.status = 'done';
-                    return;
-                }
-
                 const params = {
                     clientId: address.clientId,
                     addressId: address.id,
@@ -191,13 +190,11 @@ export const useInvoiceOutGlobalStore = defineStore({
                     serialType: formData.serialType,
                 };
 
-                this.status = 'invoicing';
                 this.invoicing = true;
 
                 const { data } = await axios.post('InvoiceOuts/invoiceClient', params);
 
                 if (data) await this.makePdfAndNotify(data, address);
-                this.addressIndex++;
                 this.isInvoicing = false;
             } catch (err) {
                 if (err?.response?.status >= 400 && err?.response?.status < 500) {
@@ -205,13 +202,16 @@ export const useInvoiceOutGlobalStore = defineStore({
                     return;
                 } else {
                     this.invoicing = false;
-                    this.status = 'done';
                     notify(
                         'invoiceOut.globalInvoices.errors.criticalInvoiceError',
                         'negative'
                     );
                     throw new Error('Critical invoicing error, process stopped');
                 }
+            } finally {
+                this.addressIndex++;
+                if (this.status != 'stopping')
+                    await this.invoiceClient(formData, this.addressIndex);
             }
         },
 
@@ -234,7 +234,6 @@ export const useInvoiceOutGlobalStore = defineStore({
 
         handleError(err) {
             this.invoicing = false;
-            this.status = null;
             throw err;
         },
 
@@ -279,7 +278,7 @@ export const useInvoiceOutGlobalStore = defineStore({
                 return 0;
             }
             let porcentaje = (state.addressIndex / this.getNAddresses) * 100;
-            return porcentaje;
+            return porcentaje?.toFixed(2);
         },
         getAddressNumber(state) {
             return state.addressIndex;

From ead241e7daa826608dfe522349f4691a06dbc2c9 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 6 Nov 2024 13:53:58 +0100
Subject: [PATCH 146/207] chore: remove console.log

---
 src/stores/invoiceOutGlobal.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/stores/invoiceOutGlobal.js b/src/stores/invoiceOutGlobal.js
index b17f41564..35f834f3d 100644
--- a/src/stores/invoiceOutGlobal.js
+++ b/src/stores/invoiceOutGlobal.js
@@ -179,7 +179,6 @@ export const useInvoiceOutGlobalStore = defineStore({
                 this.invoicing = false;
                 return;
             }
-            console.log('address: ', address);
             try {
                 const params = {
                     clientId: address.clientId,

From 2bf7fa46ca8a546e4e5fb379b502407e55c92d0f Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 7 Nov 2024 12:53:17 +0100
Subject: [PATCH 147/207] perf: remove appendParams

---
 src/components/VnTable/VnTable.vue                     | 6 +-----
 src/composables/useArrayData.js                        | 3 +--
 src/pages/Customer/components/CustomerSummaryTable.vue | 3 +--
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index cdf450966..a4948156a 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -62,7 +62,7 @@ const $props = defineProps({
         default: 'flex-one',
     },
     searchUrl: {
-        type: String,
+        type: [String, Boolean],
         default: 'table',
     },
     isEditable: {
@@ -73,10 +73,6 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
-    appendParams: {
-        type: Boolean,
-        default: true,
-    },
     hasSubToolbar: {
         type: Boolean,
         default: null,
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index e33cb8b78..747c6ab64 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -247,9 +247,8 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
     }
 
     function updateStateParams() {
-        if (!route) return;
         const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
-        if (store?.appendParams ?? true)
+        if (store?.searchUrl)
             newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
 
         if (store.navigate) {
diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue
index 745cbf29e..59e82e252 100644
--- a/src/pages/Customer/components/CustomerSummaryTable.vue
+++ b/src/pages/Customer/components/CustomerSummaryTable.vue
@@ -183,7 +183,6 @@ const getItemPackagingType = (ticketSales) => {
         :column-search="false"
         url="Tickets"
         :columns="columns"
-        append-params="false"
         :without-header="true"
         auto-load
         :row-click="rowClick"
@@ -191,7 +190,7 @@ const getItemPackagingType = (ticketSales) => {
         :disable-option="{ card: true, table: true }"
         class="full-width"
         :disable-infinite-scroll="true"
-        search-url="tickets"
+        :search-url="false"
     >
         <template #column-nickname="{ row }">
             <span class="link">

From e210ad7de4d0eaff62cdcd176fdef8026003adac Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 7 Nov 2024 13:06:33 +0100
Subject: [PATCH 148/207] Merge branch 'dev' into fix_customer_issues

---
 src/pages/Customer/components/CustomerSummaryTable.vue | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue
index e0ef6a5ef..59e82e252 100644
--- a/src/pages/Customer/components/CustomerSummaryTable.vue
+++ b/src/pages/Customer/components/CustomerSummaryTable.vue
@@ -63,11 +63,7 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-<<<<<<< HEAD
         format: (row) => dashIfEmpty(row.agencyMode?.name),
-=======
-        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyMode?.name),
->>>>>>> dev
         columnClass: 'expand',
         label: t('Agency'),
     },

From 0b5be9e67fef0e164c3d6ca5c429892263d8c1d4 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 7 Nov 2024 17:19:35 +0100
Subject: [PATCH 149/207] chore: correct checkNotification

---
 test/cypress/support/commands.js | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 73c786680..b536121b1 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -280,13 +280,14 @@ Cypress.Commands.add('openActions', (row) => {
     cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
 });
 
-Cypress.Commands.add('checkNotification', (type) => {
-    const values = {
-        created: 'Data created',
-        updated: 'Data saved',
-        deleted: 'Data deleted',
-    };
-    cy.get('.q-notification__message').should('have.text', values[type]);
+Cypress.Commands.add('checkNotification', (text) => {
+    cy.get('.q-notification')
+        .should('be.visible')
+        .last()
+        .then(($lastNotification) => {
+            if (!Cypress.$($lastNotification).text().includes(text))
+                throw new Error(`Notification not found: "${text}"`);
+        });
 });
 
 Cypress.Commands.add('checkValueForm', (id, search) => {

From 498a52a3e5a78c4e8c8f7c58a3cc4b655ca33cac Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Thu, 7 Nov 2024 19:07:03 -0300
Subject: [PATCH 150/207] refactor: small change

---
 src/pages/Order/Card/CatalogFilterValueDialog.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index 8e4a9315a..ada0c2889 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -66,7 +66,7 @@ const getSelectedTagValues = async (tag) => {
             <VnSelect
                 :label="t('params.tag')"
                 v-model="selectedTag"
-                :options="props.tags || []"
+                :options="props.tags"
                 option-value="id"
                 option-label="name"
                 dense

From 52a2250acc721f80a9a5e5d85dd4b9bad99ea1df Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Thu, 7 Nov 2024 19:16:06 -0300
Subject: [PATCH 151/207] refactor: apply QPopupProxy

---
 src/pages/Order/Card/OrderCatalogFilter.vue | 22 ++++++++-------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 28c54c120..27023262e 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -29,7 +29,6 @@ const props = defineProps({
     },
 });
 
-const showValueFilterDialog = ref(false);
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
@@ -104,14 +103,12 @@ const applyTags = (tagInfo, params, search) => {
     if (!tagInfo || !tagInfo.values.length) {
         params.tagGroups = null;
         search();
-        toggleValueFilterDialog();
         return;
     }
 
     if (!params.tagGroups) params.tagGroups = [];
     params.tagGroups.push(tagInfo);
     search();
-    toggleValueFilterDialog();
 };
 
 const removeTagGroupParam = (params, search, valIndex = null) => {
@@ -149,10 +146,6 @@ function addOrder(value, field, params) {
     vnFilterPanelRef.value.search();
 }
 
-const toggleValueFilterDialog = () => {
-    showValueFilterDialog.value = !showValueFilterDialog.value;
-};
-
 onMounted(() => {
     selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
     selectedTypeFk.value = getParamWhere(route, 'typeFk');
@@ -315,18 +308,19 @@ onMounted(() => {
                             flat
                             color="primary"
                             size="md"
-                            @click="toggleValueFilterDialog()"
                         />
+                        <QPopupProxy>
+                            <CatalogFilterValueDialog
+                                :tags="tags"
+                                @apply-tags="
+                                    ($event) => applyTags($event, params, searchFn)
+                                "
+                            />
+                        </QPopupProxy>
                     </template>
                 </VnInput>
             </QItem>
             <QSeparator />
-            <QDialog v-model="showValueFilterDialog">
-                <CatalogFilterValueDialog
-                    :tags="tags"
-                    @apply-tags="($event) => applyTags($event, params, searchFn)"
-                />
-            </QDialog>
         </template>
     </VnFilterPanel>
 </template>

From 8bff7fc1d617bf1e5d2c06115248232fe673cd4c Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Thu, 7 Nov 2024 21:09:39 -0300
Subject: [PATCH 152/207] fix: reset category

---
 src/pages/Order/Card/OrderCatalogFilter.vue | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 27023262e..532c79322 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -10,10 +10,8 @@ import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import getParamWhere from 'src/filters/getParamWhere';
 import CatalogFilterValueDialog from 'src/pages/Order/Card/CatalogFilterValueDialog.vue';
+import { useArrayData } from 'composables/useArrayData';
 
-const { t } = useI18n();
-
-const route = useRoute();
 const props = defineProps({
     dataKey: {
         type: String,
@@ -29,6 +27,11 @@ const props = defineProps({
     },
 });
 
+const { t } = useI18n();
+const route = useRoute();
+
+const arrayData = useArrayData(props.dataKey);
+
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
@@ -54,7 +57,8 @@ const resetCategory = (params, search) => {
     typeList.value = null;
     params.categoryFk = null;
     params.typeFk = null;
-    search();
+    arrayData.store.userFilter = null;
+    removeTagGroupParam(params, search);
 };
 
 const selectCategory = (params, category, search) => {

From a467c44b91ec3c80d45cfa5dc68a9e7479dcf144 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Fri, 8 Nov 2024 11:51:13 +0100
Subject: [PATCH 153/207] feat: refs #6818 saysimple integration

---
 src/components/ui/VnLinkPhone.vue           | 19 ++++++++++++++++---
 src/pages/Customer/Card/CustomerSummary.vue |  7 ++++++-
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 3ce0b7aa6..490dd838e 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -1,16 +1,29 @@
 <script setup>
-defineProps({ phoneNumber: { type: [String, Number], default: null } });
+import { useAttrs } from 'vue';
+const props = defineProps({
+    phoneNumber: { type: [String, Number], default: null },
+    channel: { type: Number, default: 1320 },
+});
+
+const config = {
+    sip: { icon: 'phone_in_talk', href: `sip:${props.phoneNumber}` },
+    'say-simple': {
+        icon: 'help', // 'whatsapp',
+        href: `https://verdnatura.saysimple.io/start-conversation?customerIdentity=%2B${props.phoneNumber}&channelId=${props.channel}`,
+    },
+};
+const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
 </script>
 <template>
     <QBtn
         v-if="phoneNumber"
         flat
         round
-        icon="phone"
+        :icon="config[type].icon"
         size="sm"
         color="primary"
         padding="none"
-        :href="`sip:${phoneNumber}`"
+        :href="config[type].href"
         @click.stop
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 8e41119ef..4cc6057e8 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -95,6 +95,11 @@ const sumRisk = ({ clientRisks }) => {
                     <template #label>
                         {{ t('customer.summary.mobile') }}
                         <VnLinkPhone :phone-number="entity.mobile" />
+                        <VnLinkPhone
+                            say-simple
+                            :phone-number="entity.mobile"
+                            :channel="entity.country?.saySimpleCountry?.channel"
+                        />
                     </template>
                 </VnLv>
                 <VnLv :value="entity.email" copy
@@ -142,7 +147,7 @@ const sumRisk = ({ clientRisks }) => {
                 <VnLv
                     v-if="entity.country"
                     :label="t('customer.summary.country')"
-                    :value="entity.country.country"
+                    :value="entity.country.name"
                 />
                 <VnLv :label="t('customer.summary.street')" :value="entity.street" />
             </QCard>

From 3825dc385134071cea196a2f640bbd43609b1eee Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 8 Nov 2024 11:54:04 +0100
Subject: [PATCH 154/207] feat: disabled buttons

---
 .../Order/Card/CatalogFilterValueDialog.vue   | 43 ++++++++++++-------
 src/pages/Order/Card/OrderCatalogFilter.vue   | 13 ++++--
 2 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index ada0c2889..28e235f6a 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -63,6 +63,15 @@ const getSelectedTagValues = async (tag) => {
 <template>
     <QForm @submit="applyTags(tagValues)" class="all-pointer-events">
         <QCard class="q-pa-sm column q-pa-lg">
+            <QBtn
+                round
+                color="primary"
+                style="position: absolute; z-index: 1; right: 0; top: 0"
+                icon="search"
+                type="submit"
+            >
+            </QBtn>
+
             <VnSelect
                 :label="t('params.tag')"
                 v-model="selectedTag"
@@ -77,6 +86,16 @@ const getSelectedTagValues = async (tag) => {
                 use-input
                 @update:model-value="($event) => getSelectedTagValues($event)"
             />
+            <QBtn
+                icon="add_circle"
+                shortcut="+"
+                flat
+                class="filter-icon q-mb-md"
+                size="md"
+                dense
+                :disabled="!selectedTag || !tagValues[0].value"
+                @click="tagValues.unshift({})"
+            />
             <div
                 v-for="(value, index) in tagValues"
                 :key="value"
@@ -95,7 +114,7 @@ const getSelectedTagValues = async (tag) => {
                         rounded
                         emit-value
                         use-input
-                        :disable="!value"
+                        :disable="!value || !selectedTag"
                         :is-clearable="false"
                         class="col"
                     />
@@ -108,25 +127,19 @@ const getSelectedTagValues = async (tag) => {
                         :is-clearable="false"
                         class="col"
                     />
-                    <QIcon
-                        name="delete"
+                    <QBtn
+                        icon="delete"
+                        size="md"
+                        outlined
+                        dense
+                        rounded
+                        flat
                         class="filter-icon col-2"
+                        :disabled="!value.value"
                         @click="removeTagGroupParam(index)"
                     />
                 </div>
             </div>
-            <QBtn
-                icon="add_circle"
-                shortcut="+"
-                flat
-                class="filter-icon q-mb-md"
-                size="md"
-                dense
-                @click="tagValues.push({})"
-            />
-            <QBtn color="primary" type="submit">
-                {{ t('search') }}
-            </QBtn>
         </QCard>
     </QForm>
 </template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 532c79322..f684db03e 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -35,6 +35,7 @@ const arrayData = useArrayData(props.dataKey);
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
+const tagsValues = ref([]);
 const selectedTypeFk = ref(null);
 const generalSearchParam = ref(null);
 
@@ -289,9 +290,12 @@ onMounted(() => {
             <QSeparator />
 
             <QItem class="q-mt-lg">
-                <VnInput
+                <VnSelect
                     :label="t('components.itemsFilterPanel.value')"
-                    is-outlined
+                    :options="props.tagValue"
+                    dense
+                    outlined
+                    rounded
                     :is-clearable="false"
                     v-model="generalSearchParam"
                     @keyup.enter="
@@ -305,7 +309,7 @@ onMounted(() => {
                     <template #prepend>
                         <QIcon name="search" />
                     </template>
-                    <template #append>
+                    <template #after>
                         <QBtn
                             icon="add_circle"
                             shortcut="+"
@@ -315,6 +319,7 @@ onMounted(() => {
                         />
                         <QPopupProxy>
                             <CatalogFilterValueDialog
+                                style="display: inline-block"
                                 :tags="tags"
                                 @apply-tags="
                                     ($event) => applyTags($event, params, searchFn)
@@ -322,7 +327,7 @@ onMounted(() => {
                             />
                         </QPopupProxy>
                     </template>
-                </VnInput>
+                </VnSelect>
             </QItem>
             <QSeparator />
         </template>

From 3bae121ed74f6078ed2ccf8769443646487baf5d Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Fri, 8 Nov 2024 13:04:40 +0100
Subject: [PATCH 155/207] fix: refs #6818 use right icon

---
 src/components/ui/VnLinkPhone.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 490dd838e..a69cb4509 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -6,7 +6,7 @@ const props = defineProps({
 });
 
 const config = {
-    sip: { icon: 'phone_in_talk', href: `sip:${props.phoneNumber}` },
+    sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
         icon: 'help', // 'whatsapp',
         href: `https://verdnatura.saysimple.io/start-conversation?customerIdentity=%2B${props.phoneNumber}&channelId=${props.channel}`,

From c1d623622def8b6c576322c7b6c2da673b6fed93 Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Fri, 8 Nov 2024 10:11:15 -0300
Subject: [PATCH 156/207] refactor: remove unused variable

---
 src/pages/Order/Card/OrderCatalogFilter.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index f684db03e..e4868006c 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -35,7 +35,6 @@ const arrayData = useArrayData(props.dataKey);
 const categoryList = ref(null);
 const selectedCategoryFk = ref(null);
 const typeList = ref([]);
-const tagsValues = ref([]);
 const selectedTypeFk = ref(null);
 const generalSearchParam = ref(null);
 

From ade90afd0391a303ea1e15b675f1ebfe01af2d98 Mon Sep 17 00:00:00 2001
From: wbuezas <wbuezas@verdnatura.es>
Date: Fri, 8 Nov 2024 10:13:35 -0300
Subject: [PATCH 157/207] refactor: change keyup.enter for update:model-value

---
 src/pages/Order/Card/OrderCatalogFilter.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index e4868006c..758639f69 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -297,7 +297,7 @@ onMounted(() => {
                     rounded
                     :is-clearable="false"
                     v-model="generalSearchParam"
-                    @keyup.enter="
+                    @update:model-value="
                         applyTags(
                             { values: [{ value: generalSearchParam }] },
                             params,

From 7fb3e71688f874ab6ca76c24bedc139ed890dc08 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Fri, 8 Nov 2024 17:41:27 +0100
Subject: [PATCH 158/207] feat: refs #6818 fetch url & default channel

---
 src/components/ui/VnLinkPhone.vue | 36 +++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index a69cb4509..a7b2d9b77 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -1,18 +1,38 @@
 <script setup>
-import { useAttrs } from 'vue';
+import { reactive, useAttrs, onBeforeMount, capitalize } from 'vue';
+import axios from 'axios';
 const props = defineProps({
     phoneNumber: { type: [String, Number], default: null },
-    channel: { type: Number, default: 1320 },
+    channel: { type: Number, default: null },
 });
 
-const config = {
+const config = reactive({
     sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
         icon: 'help', // 'whatsapp',
-        href: `https://verdnatura.saysimple.io/start-conversation?customerIdentity=%2B${props.phoneNumber}&channelId=${props.channel}`,
+        href: null,
     },
-};
+});
 const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
+
+onBeforeMount(async () => {
+    let url;
+    let channel = props.channel;
+    if (type === 'say-simple')
+        url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
+    if (!props.channel)
+        channel = (
+            await axios.get('SaySimpleCountries/findOne', {
+                params: {
+                    filter: { fields: ['channel'], where: { countryFk: 0 } },
+                },
+            })
+        ).data?.channel;
+
+    config[
+        'say-simple'
+    ].href = `${url}?customerIdentity=%2B${props.phoneNumber}&channelId=${channel}`;
+});
 </script>
 <template>
     <QBtn
@@ -25,5 +45,9 @@ const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
         padding="none"
         :href="config[type].href"
         @click.stop
-    />
+    >
+        <QTooltip>
+            {{ capitalize(type).replace('-', '') }}
+        </QTooltip>
+    </QBtn>
 </template>

From 777ac58f047e9becdb7892dc941820b4be494b3c Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 11 Nov 2024 10:31:41 +0100
Subject: [PATCH 159/207] feat(Supplier): add companySize

---
 src/i18n/locale/en.yml                        |  4 +++
 src/i18n/locale/es.yml                        |  4 +++
 src/pages/Supplier/Card/SupplierBasicData.vue | 32 ++++++++++++++-----
 src/pages/Supplier/Card/SupplierSummary.vue   | 16 ++++++++++
 4 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index a6065e451..c54d80530 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -106,6 +106,9 @@ globals:
     weight: Weight
     error: Ups! Something went wrong
     recalc: Recalculate
+    small: Small
+    medium: Medium
+    big: Big
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -942,6 +945,7 @@ supplier:
         isActive: Active
         isPayMethodChecked: PayMethod checked
         note: Notes
+        size: Size
     fiscalData:
         name: Social name *
         nif: Tax number *
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 6f01f7dd1..8ee3c7d90 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -108,6 +108,9 @@ globals:
     weight: Peso
     error: ¡Ups! Algo salió mal
     recalc: Recalcular
+    small: Pequeño/a
+    medium: Mediano/a
+    big: Grande
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -940,6 +943,7 @@ supplier:
         isActive: Activo
         isPayMethodChecked: Método de pago validado
         note: Notas
+        size: Tamaño
     fiscalData:
         name: Razón social *
         nif: NIF/CIF *
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index 52964557d..ab8f9a4b1 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -1,5 +1,4 @@
 <script setup>
-import { ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import FormModel from 'components/FormModel.vue';
@@ -9,8 +8,11 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 
 const route = useRoute();
 const { t } = useI18n();
-
-const workersOptions = ref([]);
+const companySizes = [
+    { id: 'small', name: t('globals.small'), size: '1-5' },
+    { id: 'medium', name: t('globals.medium'), size: '6-50' },
+    { id: 'big', name: t('globals.big'), size: '>50' },
+];
 </script>
 <template>
     <FormModel
@@ -31,11 +33,6 @@ const workersOptions = ref([]);
                 <VnSelect
                     :label="t('supplier.basicData.workerFk')"
                     v-model="data.workerFk"
-                    :options="workersOptions"
-                    option-value="id"
-                    option-label="name"
-                    hide-selected
-                    map-options
                     url="Workers/search"
                     sort-by="nickname ASC"
                     :rules="validate('supplier.workerFk')"
@@ -58,6 +55,24 @@ const workersOptions = ref([]);
                         </QItem>
                     </template>
                 </VnSelect>
+                <VnSelect
+                    :label="t('supplier.basicData.size')"
+                    v-model="data.companySize"
+                    :options="companySizes"
+                    sort-by="nickname ASC"
+                    :rules="validate('supplier.workerFk')"
+                >
+                    <template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                <QItemLabel caption>
+                                    {{ scope.opt?.size }}
+                                </QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelect>
             </VnRow>
             <VnRow>
                 <QCheckbox
@@ -88,4 +103,5 @@ const workersOptions = ref([]);
 <i18n>
 es:
     Responsible for approving invoices: Responsable de aprobar las facturas
+    Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50)
 </i18n>
diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue
index 5791db1eb..2ce5a7dce 100644
--- a/src/pages/Supplier/Card/SupplierSummary.vue
+++ b/src/pages/Supplier/Card/SupplierSummary.vue
@@ -65,6 +65,22 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
                         <span> {{ dashIfEmpty(supplier.note) }} </span>
                     </template>
                 </VnLv>
+                <VnLv
+                    :label="t('supplier.basicData.size')"
+                    :value="supplier.companySize"
+                    class="q-mb-xs"
+                >
+                    <template #value>
+                        <span>
+                            {{
+                                dashIfEmpty(
+                                    supplier.companySize &&
+                                        t('globals.' + supplier.companySize)
+                                )
+                            }}
+                        </span>
+                    </template>
+                </VnLv>
                 <QCheckbox
                     :label="t('supplier.summary.verified')"
                     v-model="supplier.isSerious"

From 07e7cbc3551db7c7fe5c3e9ad67a7cbcc8939031 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 11 Nov 2024 16:36:18 +0100
Subject: [PATCH 160/207] feat: refs #6839 module searching

---
 src/components/LeftMenu.vue | 77 ++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 10 deletions(-)

diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 03fe11a85..6e0ae5907 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { onMounted, watch, ref, reactive } from 'vue';
+import { onMounted, watch, ref, reactive, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { QSeparator, useQuasar } from 'quasar';
 import { useRoute } from 'vue-router';
@@ -9,6 +9,7 @@ import { toLowerCamel } from 'src/filters';
 import routes from 'src/router/modules';
 import LeftMenuItem from './LeftMenuItem.vue';
 import LeftMenuItemGroup from './LeftMenuItemGroup.vue';
+import VnInput from './common/VnInput.vue';
 
 const { t } = useI18n();
 const route = useRoute();
@@ -22,7 +23,32 @@ const props = defineProps({
     },
 });
 
+const items = ref([]);
 const expansionItemElements = reactive({});
+const pinnedModules = computed(() => {
+    const map = new Map();
+    items.value.forEach((item) => item.isPinned && map.set(item.name, item));
+    return map;
+});
+const search = ref(null);
+
+const filteredItems = computed(() => {
+    if (!search.value) return items.value;
+    return items.value.filter((item) => {
+        const locale = t(item.title).toLowerCase();
+        return locale.includes(search.value.toLowerCase());
+    });
+});
+
+const filteredPinnedModules = computed(() => {
+    if (!search.value) return pinnedModules.value;
+    const map = new Map();
+    for (const [key, pinnedModule] of pinnedModules.value) {
+        const locale = t(pinnedModule.title).toLowerCase();
+        if (locale.includes(search.value.toLowerCase())) map.set(key, pinnedModule);
+    }
+    return map;
+});
 
 onMounted(async () => {
     await navigation.fetchPinned();
@@ -66,8 +92,6 @@ function addChildren(module, route, parent) {
     }
 }
 
-const items = ref([]);
-
 function getRoutes() {
     if (props.source === 'main') {
         const modules = Object.assign([], navigation.getModules().value);
@@ -129,15 +153,44 @@ const handleItemExpansion = (itemName) => {
     <QList padding class="column-max-width">
         <template v-if="$props.source === 'main'">
             <template v-if="$route?.matched[1]?.name === 'Dashboard'">
-                <QItem class="header">
-                    <QItemSection avatar>
-                        <QIcon name="view_module" />
-                    </QItemSection>
-                    <QItemSection> {{ t('globals.modules') }}</QItemSection>
+                <QItem class="q-pb-md">
+                    <VnInput
+                        v-model="search"
+                        :label="t('Search modules')"
+                        class="full-width"
+                        filled
+                        dense
+                    />
                 </QItem>
                 <QSeparator />
-                <template v-for="item in items" :key="item.name">
-                    <template v-if="item.children">
+                <template v-if="filteredPinnedModules.size">
+                    <LeftMenuItem
+                        v-for="[key, pinnedModule] of filteredPinnedModules"
+                        :key="key"
+                        :item="pinnedModule"
+                        group="modules"
+                    >
+                        <template #side>
+                            <QBtn
+                                v-if="pinnedModule.isPinned === true"
+                                @click="togglePinned(pinnedModule, $event)"
+                                icon="remove_circle"
+                                size="xs"
+                                flat
+                                round
+                            >
+                                <QTooltip>
+                                    {{ t('components.leftMenu.removeFromPinned') }}
+                                </QTooltip>
+                            </QBtn>
+                        </template>
+                    </LeftMenuItem>
+                    <QSeparator />
+                </template>
+                <template v-for="item in filteredItems" :key="item.name">
+                    <template
+                        v-if="item.children && !filteredPinnedModules.has(item.name)"
+                    >
                         <LeftMenuItem :item="item" group="modules">
                             <template #side>
                                 <QBtn
@@ -256,3 +309,7 @@ const handleItemExpansion = (itemName) => {
     color: var(--vn-label-color);
 }
 </style>
+<i18n>
+    es:
+        Search modules: Buscar módulos
+</i18n>

From 40ecd6e3584a94627b714c9dd474975cc3d3187e Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Tue, 12 Nov 2024 08:28:02 +0100
Subject: [PATCH 161/207] refactor: refs #7950 Created cmr model

---
 src/pages/Route/Cmr/CmrList.vue | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/Route/Cmr/CmrList.vue b/src/pages/Route/Cmr/CmrList.vue
index ede271960..b3eaf3b48 100644
--- a/src/pages/Route/Cmr/CmrList.vue
+++ b/src/pages/Route/Cmr/CmrList.vue
@@ -116,7 +116,7 @@ function getApiUrl() {
     return new URL(window.location).origin;
 }
 function getCmrUrl(value) {
-    return `${getApiUrl()}/api/Routes/${value}/cmr?access_token=${token}`;
+    return `${getApiUrl()}/api/Cmrs/${value}/print?access_token=${token}`;
 }
 function downloadPdfs() {
     if (!selectedRows.value.length) {
@@ -129,7 +129,7 @@ function downloadPdfs() {
     let cmrs = [];
     for (let value of selectedRows.value) cmrs.push(value.cmrFk);
     // prettier-ignore
-    return window.open(`${getApiUrl()}/api/Routes/downloadCmrsZip?ids=${cmrs.join(',')}&access_token=${token}`);
+    return window.open(`${getApiUrl()}/api/Cmrs/downloadZip?ids=${cmrs.join(',')}&access_token=${token}`);
 }
 </script>
 <template>
@@ -149,7 +149,7 @@ function downloadPdfs() {
     <VnTable
         ref="tableRef"
         data-key="CmrList"
-        url="Routes/cmrs"
+        url="Cmrs/filter"
         :columns="columns"
         :right-search="true"
         default-mode="table"

From 700701f0554c7b06985f31e9dcecc8ad51056de0 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 12 Nov 2024 10:10:26 +0100
Subject: [PATCH 162/207] refactor: refs #6818 channel logic

---
 src/components/ui/VnLinkPhone.vue | 34 +++++++++++++++++--------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index a7b2d9b77..3b3153ac3 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -9,29 +9,33 @@ const props = defineProps({
 const config = reactive({
     sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
-        icon: 'help', // 'whatsapp',
+        icon: 'help', // 'whatsapp icon #6818',
         href: null,
+        channel: props.channel,
     },
 });
 const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
 
 onBeforeMount(async () => {
     let url;
-    let channel = props.channel;
-    if (type === 'say-simple')
-        url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
-    if (!props.channel)
-        channel = (
-            await axios.get('SaySimpleCountries/findOne', {
-                params: {
-                    filter: { fields: ['channel'], where: { countryFk: 0 } },
-                },
-            })
-        ).data?.channel;
+    let { channel } = config[type];
+    if (type === 'sip') return;
 
-    config[
-        'say-simple'
-    ].href = `${url}?customerIdentity=%2B${props.phoneNumber}&channelId=${channel}`;
+    if (type === 'say-simple') {
+        url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
+        if (!channel)
+            channel = (
+                await axios.get('SaySimpleCountries/findOne', {
+                    params: {
+                        filter: { fields: ['channel'], where: { countryFk: 0 } },
+                    },
+                })
+            ).data?.channel;
+
+        config[
+            type
+        ].href = `${url}?customerIdentity=%2B${props.phoneNumber}&channelId=${channel}`;
+    }
 });
 </script>
 <template>

From 81b35aa75b03bab9c35effc1a09056945d86304d Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 12 Nov 2024 10:11:26 +0100
Subject: [PATCH 163/207] chore: refs #6818 add spaces

---
 src/components/ui/VnLinkPhone.vue | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 3b3153ac3..51694b8eb 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -19,9 +19,9 @@ const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
 onBeforeMount(async () => {
     let url;
     let { channel } = config[type];
-    if (type === 'sip') return;
 
-    if (type === 'say-simple') {
+    if (type === 'sip') return;
+    else if (type === 'say-simple') {
         url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
         if (!channel)
             channel = (

From efd66ea02af6ce995b2e08f15552bad4cfb3a0d5 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 12 Nov 2024 11:08:45 +0100
Subject: [PATCH 164/207] feat: refs #6919 sync entry data

---
 src/pages/Entry/Card/EntryBasicData.vue  |  3 +-
 src/pages/Entry/Card/EntryCard.vue       | 45 +++++++++++++++++
 src/pages/Entry/Card/EntryDescriptor.vue | 62 ++----------------------
 3 files changed, 50 insertions(+), 60 deletions(-)

diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index 3288616fb..07f4426ba 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -44,9 +44,8 @@ const onFilterTravelSelected = (formData, id) => {
         auto-load
     />
     <FormModel
-        :url="`Entries/${route.params.id}`"
         :url-update="`Entries/${route.params.id}`"
-        model="entry"
+        model="Entry"
         auto-load
         :clear-store-on-unmount="false"
     >
diff --git a/src/pages/Entry/Card/EntryCard.vue b/src/pages/Entry/Card/EntryCard.vue
index 436f5b9cd..f05f76b50 100644
--- a/src/pages/Entry/Card/EntryCard.vue
+++ b/src/pages/Entry/Card/EntryCard.vue
@@ -2,11 +2,56 @@
 import VnCard from 'components/common/VnCard.vue';
 import EntryDescriptor from './EntryDescriptor.vue';
 import EntryFilter from '../EntryFilter.vue';
+
+const filter = {
+    include: [
+        {
+            relation: 'travel',
+            scope: {
+                fields: [
+                    'id',
+                    'landed',
+                    'shipped',
+                    'agencyModeFk',
+                    'warehouseOutFk',
+                    'daysInForward',
+                ],
+                include: [
+                    {
+                        relation: 'agency',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                    {
+                        relation: 'warehouseOut',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                    {
+                        relation: 'warehouseIn',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            relation: 'supplier',
+            scope: {
+                fields: ['id', 'nickname'],
+            },
+        },
+    ],
+};
 </script>
 <template>
     <VnCard
         data-key="Entry"
         base-url="Entries"
+        :filter="filter"
         :descriptor="EntryDescriptor"
         :filter-panel="EntryFilter"
         search-data-key="EntryList"
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index d66185aa9..37b0aa62d 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -1,11 +1,10 @@
 <script setup>
-import { ref, computed, watch, onMounted } from 'vue';
+import { ref, computed, onMounted } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 
 import { toDate } from 'src/filters';
 import { usePrintService } from 'composables/usePrintService';
@@ -25,50 +24,6 @@ const { openReport } = usePrintService();
 const entryDescriptorRef = ref(null);
 const url = ref();
 
-const entryFilter = {
-    include: [
-        {
-            relation: 'travel',
-            scope: {
-                fields: [
-                    'id',
-                    'landed',
-                    'shipped',
-                    'agencyModeFk',
-                    'warehouseOutFk',
-                    'daysInForward',
-                ],
-                include: [
-                    {
-                        relation: 'agency',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                    {
-                        relation: 'warehouseOut',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                    {
-                        relation: 'warehouseIn',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                ],
-            },
-        },
-        {
-            relation: 'supplier',
-            scope: {
-                fields: ['id', 'nickname'],
-            },
-        },
-    ],
-};
-
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
@@ -76,10 +31,6 @@ onMounted(async () => {
     url.value = await getUrl('');
 });
 
-const data = ref(useCardDescription());
-const setData = (entity) =>
-    (data.value = useCardDescription(entity.supplier?.nickname, entity.id));
-
 const getEntryRedirectionFilter = (entry) => {
     let entryTravel = entry && entry.travel;
 
@@ -104,8 +55,6 @@ const getEntryRedirectionFilter = (entry) => {
 const showEntryReport = () => {
     openReport(`Entries/${route.params.id}/entry-order-pdf`);
 };
-
-watch;
 </script>
 
 <template>
@@ -113,11 +62,8 @@ watch;
         ref="entryDescriptorRef"
         module="Entry"
         :url="`Entries/${entityId}`"
-        :filter="entryFilter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
-        data-key="entry"
+        title="supplier.nickname"
+        data-key="Entry"
     >
         <template #menu="{ entity }">
             <QItem v-ripple clickable @click="showEntryReport(entity)">
@@ -165,7 +111,7 @@ watch;
         <template #actions="{ entity }">
             <QCardActions>
                 <QBtn
-                    :to="`/supplier/${entity.supplier.id}`"
+                    :to="`/supplier/${entity.supplier?.id}`"
                     size="md"
                     icon="vn:supplier"
                     color="primary"

From b4d76536617094d00959fa7ca68960172ce6eba6 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 12 Nov 2024 11:15:34 +0100
Subject: [PATCH 165/207] refactor: refs #6919 export filter

---
 src/pages/Entry/Card/EntryCard.vue       | 45 +-----------------------
 src/pages/Entry/Card/EntryDescriptor.vue |  2 ++
 src/pages/Entry/Card/EntryFilter.js      | 43 ++++++++++++++++++++++
 3 files changed, 46 insertions(+), 44 deletions(-)
 create mode 100644 src/pages/Entry/Card/EntryFilter.js

diff --git a/src/pages/Entry/Card/EntryCard.vue b/src/pages/Entry/Card/EntryCard.vue
index f05f76b50..3f2596338 100644
--- a/src/pages/Entry/Card/EntryCard.vue
+++ b/src/pages/Entry/Card/EntryCard.vue
@@ -2,50 +2,7 @@
 import VnCard from 'components/common/VnCard.vue';
 import EntryDescriptor from './EntryDescriptor.vue';
 import EntryFilter from '../EntryFilter.vue';
-
-const filter = {
-    include: [
-        {
-            relation: 'travel',
-            scope: {
-                fields: [
-                    'id',
-                    'landed',
-                    'shipped',
-                    'agencyModeFk',
-                    'warehouseOutFk',
-                    'daysInForward',
-                ],
-                include: [
-                    {
-                        relation: 'agency',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                    {
-                        relation: 'warehouseOut',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                    {
-                        relation: 'warehouseIn',
-                        scope: {
-                            fields: ['name'],
-                        },
-                    },
-                ],
-            },
-        },
-        {
-            relation: 'supplier',
-            scope: {
-                fields: ['id', 'nickname'],
-            },
-        },
-    ],
-};
+import filter from './EntryFilter.js';
 </script>
 <template>
     <VnCard
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index 37b0aa62d..794f791ae 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -9,6 +9,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
 import { toDate } from 'src/filters';
 import { usePrintService } from 'composables/usePrintService';
 import { getUrl } from 'src/composables/getUrl';
+import filter from './EntryFilter.js';
 
 const $props = defineProps({
     id: {
@@ -62,6 +63,7 @@ const showEntryReport = () => {
         ref="entryDescriptorRef"
         module="Entry"
         :url="`Entries/${entityId}`"
+        :filter="filter"
         title="supplier.nickname"
         data-key="Entry"
     >
diff --git a/src/pages/Entry/Card/EntryFilter.js b/src/pages/Entry/Card/EntryFilter.js
new file mode 100644
index 000000000..3ff62cf27
--- /dev/null
+++ b/src/pages/Entry/Card/EntryFilter.js
@@ -0,0 +1,43 @@
+export default {
+    include: [
+        {
+            relation: 'travel',
+            scope: {
+                fields: [
+                    'id',
+                    'landed',
+                    'shipped',
+                    'agencyModeFk',
+                    'warehouseOutFk',
+                    'daysInForward',
+                ],
+                include: [
+                    {
+                        relation: 'agency',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                    {
+                        relation: 'warehouseOut',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                    {
+                        relation: 'warehouseIn',
+                        scope: {
+                            fields: ['name'],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            relation: 'supplier',
+            scope: {
+                fields: ['id', 'nickname'],
+            },
+        },
+    ],
+};

From 3f15c3cce00f7005237e4a79005ccbe3fad545f6 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 12 Nov 2024 14:35:55 +0100
Subject: [PATCH 166/207] feat(VnSelect): order data equal salix

---
 src/components/common/VnSelect.vue |  3 ++
 src/utils/dataByOrder.js           | 53 ++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 src/utils/dataByOrder.js

diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 32dbbd641..4622f1cb0 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -3,6 +3,8 @@ import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import FetchData from 'src/components/FetchData.vue';
 import { useRequired } from 'src/composables/useRequired';
+import dataByOrder from 'src/utils/dataByOrder';
+
 const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 const $attrs = useAttrs();
 const { t } = useI18n();
@@ -138,6 +140,7 @@ function findKeyInOptions() {
 }
 
 function setOptions(data) {
+    data = dataByOrder(data, $props.sortBy);
     myOptions.value = JSON.parse(JSON.stringify(data));
     myOptionsOriginal.value = JSON.parse(JSON.stringify(data));
     emit('update:options', data);
diff --git a/src/utils/dataByOrder.js b/src/utils/dataByOrder.js
new file mode 100644
index 000000000..72b55ac11
--- /dev/null
+++ b/src/utils/dataByOrder.js
@@ -0,0 +1,53 @@
+function orderData(data, order) {
+    if (typeof order === 'string') order = [order];
+    if (Array.isArray(order)) {
+        let orderComp = [];
+
+        for (let field of order) {
+            let split = field.split(/\s+/);
+            orderComp.push({
+                field: split[0],
+                way: split[1] === 'DESC' ? -1 : 1,
+            });
+        }
+
+        return data.sort((a, b) => sortFunc(a, b, orderComp));
+    } else if (typeof order === 'function') return data.sort(data);
+    return data;
+}
+
+function sortFunc(a, b, order) {
+    for (let i of order) {
+        let compRes = compareFunc(a[i.field], b[i.field]) * i.way;
+        if (compRes !== 0) return compRes;
+    }
+
+    return 0;
+}
+
+function compareFunc(a, b) {
+    if (a === b) return 0;
+    let aType = typeof a;
+    if (aType === typeof b) {
+        switch (aType) {
+            case 'string':
+                return a.localeCompare(b);
+            case 'number':
+                return a - b;
+            case 'boolean':
+                return a ? 1 : -1;
+            case 'object':
+                if (a instanceof Date && b instanceof Date)
+                    return a.getTime() - b.getTime();
+        }
+    }
+
+    if (a === undefined) return -1;
+    if (b === undefined) return 1;
+    if (a === null) return -1;
+    if (b === null) return 1;
+
+    return a > b ? 1 : -1;
+}
+
+export default orderData;

From 83be57a0c4dc88180c52fb08e71de9071c305d83 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 12 Nov 2024 15:01:17 +0100
Subject: [PATCH 167/207] chore: refs #6818 drop useless code & comment

---
 src/components/ui/VnLinkPhone.vue | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 51694b8eb..11339859e 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -9,7 +9,7 @@ const props = defineProps({
 const config = reactive({
     sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
-        icon: 'help', // 'whatsapp icon #6818',
+        icon: 'help',
         href: null,
         channel: props.channel,
     },
@@ -20,8 +20,7 @@ onBeforeMount(async () => {
     let url;
     let { channel } = config[type];
 
-    if (type === 'sip') return;
-    else if (type === 'say-simple') {
+    if (type === 'say-simple') {
         url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
         if (!channel)
             channel = (

From 8269037faad5288ce36146f99e03c372724292c6 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 13 Nov 2024 07:21:42 +0100
Subject: [PATCH 168/207] chore: perf

---
 src/utils/dataByOrder.js | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/utils/dataByOrder.js b/src/utils/dataByOrder.js
index 72b55ac11..1bdedb8a1 100644
--- a/src/utils/dataByOrder.js
+++ b/src/utils/dataByOrder.js
@@ -1,4 +1,5 @@
 function orderData(data, order) {
+    if (typeof order === 'function') return data.sort(data);
     if (typeof order === 'string') order = [order];
     if (Array.isArray(order)) {
         let orderComp = [];
@@ -12,13 +13,13 @@ function orderData(data, order) {
         }
 
         return data.sort((a, b) => sortFunc(a, b, orderComp));
-    } else if (typeof order === 'function') return data.sort(data);
+    }
     return data;
 }
 
 function sortFunc(a, b, order) {
-    for (let i of order) {
-        let compRes = compareFunc(a[i.field], b[i.field]) * i.way;
+    for (let { field, way } of order) {
+        let compRes = compareFunc(a[field], b[field]) * way;
         if (compRes !== 0) return compRes;
     }
 

From 9291c4dd6acc5d12217f8d4d65688d37afc6edc6 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Wed, 13 Nov 2024 11:50:08 +0100
Subject: [PATCH 169/207] feat: refs #6818 add icon

---
 src/components/ui/VnLinkPhone.vue           | 2 +-
 src/pages/Customer/Card/CustomerSummary.vue | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 11339859e..3b63889e1 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -9,7 +9,7 @@ const props = defineProps({
 const config = reactive({
     sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
-        icon: 'help',
+        icon: 'vn:saysimple',
         href: null,
         channel: props.channel,
     },
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 4cc6057e8..555d490d7 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -99,6 +99,7 @@ const sumRisk = ({ clientRisks }) => {
                             say-simple
                             :phone-number="entity.mobile"
                             :channel="entity.country?.saySimpleCountry?.channel"
+                            class="q-ml-xs"
                         />
                     </template>
                 </VnLv>

From c2b6b816a42a90df7d9d0bd8c675bcc853430a59 Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Thu, 14 Nov 2024 08:04:06 +0100
Subject: [PATCH 170/207] fix: refs #7283 Account image resolution

---
 src/pages/Account/Card/AccountDescriptor.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Account/Card/AccountDescriptor.vue b/src/pages/Account/Card/AccountDescriptor.vue
index 4571ee8ab..3156f8e1e 100644
--- a/src/pages/Account/Card/AccountDescriptor.vue
+++ b/src/pages/Account/Card/AccountDescriptor.vue
@@ -54,7 +54,7 @@ const hasAccount = ref(false);
         </template>
         <template #before>
             <!-- falla id :id="entityId.value" collection="user" size="160x160" -->
-            <VnImg :id="entityId" collection="user" resolution="160x160" class="photo">
+            <VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
                 <template #error>
                     <div
                         class="absolute-full picture text-center q-pa-md flex flex-center"

From ef415d080adcd580d92634778bb8a135c9af0b38 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 08:19:19 +0100
Subject: [PATCH 171/207] feat: refs #7308 #7308 remove warnings related to
 useSession

---
 src/boot/quasar.js            | 2 ++
 src/composables/useSession.js | 8 ++++++--
 src/router/index.js           | 8 +++++---
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 01fe68d8b..1cc2e82cf 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -1,6 +1,7 @@
 import { boot } from 'quasar/wrappers';
 import qFormMixin from './qformMixin';
 import keyShortcut from './keyShortcut';
+import { setupAxios } from 'src/boot/axios';
 import useNotify from 'src/composables/useNotify.js';
 import { CanceledError } from 'axios';
 
@@ -48,4 +49,5 @@ export default boot(({ app }) => {
 
         notify(message ?? 'globals.error', 'negative', 'error');
     };
+    setupAxios();
 });
diff --git a/src/composables/useSession.js b/src/composables/useSession.js
index 633a30bb0..5097a1fee 100644
--- a/src/composables/useSession.js
+++ b/src/composables/useSession.js
@@ -8,9 +8,13 @@ import useNotify from './useNotify';
 import { useTokenConfig } from './useTokenConfig';
 const TOKEN_MULTIMEDIA = 'tokenMultimedia';
 const TOKEN = 'token';
-
+let router;
+export default {
+    setup() {
+        router = useRouter();
+    },
+};
 export function useSession() {
-    const router = useRouter();
     const { notify } = useNotify();
     let isCheckingToken = false;
     let intervalId = null;
diff --git a/src/router/index.js b/src/router/index.js
index 18541c0b2..5ed8ad9ed 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -14,8 +14,8 @@ import { useUserConfig } from 'src/composables/useUserConfig';
 import { useTokenConfig } from 'src/composables/useTokenConfig';
 import { useAcl } from 'src/composables/useAcl';
 
-const state = useState();
-const session = useSession();
+let state, session;
+
 const { t, te } = i18n.global;
 
 const createHistory = process.env.SERVER
@@ -43,8 +43,10 @@ const Router = createRouter({
  * with the Router instance.
  */
 export { Router };
-export default route(function (/* { store, ssrContext } */) {
+export default route((/* { store, ssrContext } */) => {
     Router.beforeEach(async (to, from, next) => {
+        state = useState();
+        session = useSession();
         const { isLoggedIn } = session;
         const outLayout = Router.options.routes[0].children.map((r) => r.name);
         if (!isLoggedIn() && !outLayout.includes(to.name)) {

From 590d495dbddfeb6b252e2967c259394ef80f6b2a Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 08:19:41 +0100
Subject: [PATCH 172/207] test: refs #7308 #7308 axios.spec.js

---
 src/boot/axios.js                        | 19 +++++---
 test/vitest/__tests__/boot/axios.spec.js | 62 ++++++++++++++++++------
 2 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/src/boot/axios.js b/src/boot/axios.js
index aee38e887..5da26a404 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -4,9 +4,8 @@ import { Router } from 'src/router';
 import useNotify from 'src/composables/useNotify.js';
 import { useStateQueryStore } from 'src/stores/useStateQueryStore';
 
-const session = useSession();
-const { notify } = useNotify();
-const stateQuery = useStateQueryStore();
+let session, notify, stateQuery;
+
 const baseUrl = '/api/';
 
 axios.defaults.baseURL = baseUrl;
@@ -51,9 +50,15 @@ const onResponseError = (error) => {
     return Promise.reject(error);
 };
 
-axios.interceptors.request.use(onRequest, onRequestError);
-axios.interceptors.response.use(onResponse, onResponseError);
-axiosNoError.interceptors.request.use(onRequest);
-axiosNoError.interceptors.response.use(onResponse);
+export function setupAxios() {
+    session = useSession();
+    notify = useNotify().notify;
+    stateQuery = useStateQueryStore();
+
+    axios.interceptors.request.use(onRequest, onRequestError);
+    axios.interceptors.response.use(onResponse, onResponseError);
+    axiosNoError.interceptors.request.use(onRequest);
+    axiosNoError.interceptors.response.use(onResponse);
+}
 
 export { onRequest, onResponseError, axiosNoError };
diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js
index 19d396ec5..dc321a658 100644
--- a/test/vitest/__tests__/boot/axios.spec.js
+++ b/test/vitest/__tests__/boot/axios.spec.js
@@ -1,23 +1,53 @@
-import { Notify } from 'quasar';
-import { onRequest, onResponseError } from 'src/boot/axios';
-import { describe, expect, it, vi } from 'vitest';
+import { describe, it, expect, beforeEach, vi } from 'vitest';
+import { setupAxios, onRequest, onResponseError } from 'src/boot/axios';
+import { useSession } from 'src/composables/useSession';
+import useNotify from 'src/composables/useNotify';
+import { useStateQueryStore } from 'src/stores/useStateQueryStore';
 
-vi.mock('src/composables/useSession', () => ({
-    useSession: () => ({
-        getToken: () => 'DEFAULT_TOKEN',
-        isLoggedIn: () => vi.fn(),
-        destroy: () => vi.fn(),
-    }),
-}));
+vi.mock('src/composables/useSession');
+vi.mock('src/composables/useNotify');
+vi.mock('src/stores/useStateQueryStore');
 
-vi.mock('src/stores/useStateQueryStore', () => ({
-    useStateQueryStore: () => ({
-        add: () => vi.fn(),
-        remove: () => vi.fn(),
-    }),
-}));
+// vi.mock('src/composables/useSession', () => ({
+//     useSession: () => ({
+//         getToken: () => 'DEFAULT_TOKEN',
+//         isLoggedIn: () => vi.fn(),
+//         destroy: () => vi.fn(),
+//     }),
+// }));
+
+// vi.mock('src/stores/useStateQueryStore', () => ({
+//     useStateQueryStore: () => ({
+//         add: () => vi.fn(),
+//         remove: () => vi.fn(),
+//     }),
+// }));
 
 describe('Axios boot', () => {
+    let sessionMock, notifyMock, stateQueryMock;
+
+    beforeEach(() => {
+        sessionMock = {
+            getToken: vi.fn().mockReturnValue('DEFAULT_TOKEN'),
+            isLoggedIn: vi.fn().mockReturnValue(true),
+            destroy: vi.fn(),
+        };
+
+        notifyMock = {
+            notify: vi.fn(),
+        };
+
+        stateQueryMock = {
+            add: vi.fn(),
+            remove: vi.fn(),
+        };
+
+        useSession.mockReturnValue(sessionMock);
+        useNotify.mockReturnValue(notifyMock);
+        useStateQueryStore.mockReturnValue(stateQueryMock);
+
+        setupAxios();
+    });
     describe('onRequest()', async () => {
         it('should set the "Authorization" property on the headers', async () => {
             const config = { headers: {} };

From b0bb09e9a66f619fee6621f633577f76566e4440 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 09:03:18 +0100
Subject: [PATCH 173/207] perf: refs #7308 #7308 remove comments

---
 test/vitest/__tests__/boot/axios.spec.js | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js
index dc321a658..3c59dbc48 100644
--- a/test/vitest/__tests__/boot/axios.spec.js
+++ b/test/vitest/__tests__/boot/axios.spec.js
@@ -8,21 +8,6 @@ vi.mock('src/composables/useSession');
 vi.mock('src/composables/useNotify');
 vi.mock('src/stores/useStateQueryStore');
 
-// vi.mock('src/composables/useSession', () => ({
-//     useSession: () => ({
-//         getToken: () => 'DEFAULT_TOKEN',
-//         isLoggedIn: () => vi.fn(),
-//         destroy: () => vi.fn(),
-//     }),
-// }));
-
-// vi.mock('src/stores/useStateQueryStore', () => ({
-//     useStateQueryStore: () => ({
-//         add: () => vi.fn(),
-//         remove: () => vi.fn(),
-//     }),
-// }));
-
 describe('Axios boot', () => {
     let sessionMock, notifyMock, stateQueryMock;
 

From 2bcd7061cb00f7450f005d18e774dc5ffbedc0a0 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 09:50:00 +0000
Subject: [PATCH 174/207] revert e57a253c6f649382da187d1129449d265fb26d3b

revert Merge pull request '#7308 Remove console warnings' (!928) from 7308-warning_inject into dev

Reviewed-on: https://gitea.verdnatura.es/verdnatura/salix-front/pulls/928
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
---
 src/boot/axios.js                        | 19 ++++-----
 src/boot/quasar.js                       |  2 -
 src/composables/useSession.js            |  8 +---
 src/router/index.js                      |  8 ++--
 test/vitest/__tests__/boot/axios.spec.js | 49 ++++++++----------------
 5 files changed, 29 insertions(+), 57 deletions(-)

diff --git a/src/boot/axios.js b/src/boot/axios.js
index 5da26a404..aee38e887 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -4,8 +4,9 @@ import { Router } from 'src/router';
 import useNotify from 'src/composables/useNotify.js';
 import { useStateQueryStore } from 'src/stores/useStateQueryStore';
 
-let session, notify, stateQuery;
-
+const session = useSession();
+const { notify } = useNotify();
+const stateQuery = useStateQueryStore();
 const baseUrl = '/api/';
 
 axios.defaults.baseURL = baseUrl;
@@ -50,15 +51,9 @@ const onResponseError = (error) => {
     return Promise.reject(error);
 };
 
-export function setupAxios() {
-    session = useSession();
-    notify = useNotify().notify;
-    stateQuery = useStateQueryStore();
-
-    axios.interceptors.request.use(onRequest, onRequestError);
-    axios.interceptors.response.use(onResponse, onResponseError);
-    axiosNoError.interceptors.request.use(onRequest);
-    axiosNoError.interceptors.response.use(onResponse);
-}
+axios.interceptors.request.use(onRequest, onRequestError);
+axios.interceptors.response.use(onResponse, onResponseError);
+axiosNoError.interceptors.request.use(onRequest);
+axiosNoError.interceptors.response.use(onResponse);
 
 export { onRequest, onResponseError, axiosNoError };
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 1cc2e82cf..01fe68d8b 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -1,7 +1,6 @@
 import { boot } from 'quasar/wrappers';
 import qFormMixin from './qformMixin';
 import keyShortcut from './keyShortcut';
-import { setupAxios } from 'src/boot/axios';
 import useNotify from 'src/composables/useNotify.js';
 import { CanceledError } from 'axios';
 
@@ -49,5 +48,4 @@ export default boot(({ app }) => {
 
         notify(message ?? 'globals.error', 'negative', 'error');
     };
-    setupAxios();
 });
diff --git a/src/composables/useSession.js b/src/composables/useSession.js
index 5097a1fee..633a30bb0 100644
--- a/src/composables/useSession.js
+++ b/src/composables/useSession.js
@@ -8,13 +8,9 @@ import useNotify from './useNotify';
 import { useTokenConfig } from './useTokenConfig';
 const TOKEN_MULTIMEDIA = 'tokenMultimedia';
 const TOKEN = 'token';
-let router;
-export default {
-    setup() {
-        router = useRouter();
-    },
-};
+
 export function useSession() {
+    const router = useRouter();
     const { notify } = useNotify();
     let isCheckingToken = false;
     let intervalId = null;
diff --git a/src/router/index.js b/src/router/index.js
index 5ed8ad9ed..18541c0b2 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -14,8 +14,8 @@ import { useUserConfig } from 'src/composables/useUserConfig';
 import { useTokenConfig } from 'src/composables/useTokenConfig';
 import { useAcl } from 'src/composables/useAcl';
 
-let state, session;
-
+const state = useState();
+const session = useSession();
 const { t, te } = i18n.global;
 
 const createHistory = process.env.SERVER
@@ -43,10 +43,8 @@ const Router = createRouter({
  * with the Router instance.
  */
 export { Router };
-export default route((/* { store, ssrContext } */) => {
+export default route(function (/* { store, ssrContext } */) {
     Router.beforeEach(async (to, from, next) => {
-        state = useState();
-        session = useSession();
         const { isLoggedIn } = session;
         const outLayout = Router.options.routes[0].children.map((r) => r.name);
         if (!isLoggedIn() && !outLayout.includes(to.name)) {
diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js
index 3c59dbc48..19d396ec5 100644
--- a/test/vitest/__tests__/boot/axios.spec.js
+++ b/test/vitest/__tests__/boot/axios.spec.js
@@ -1,38 +1,23 @@
-import { describe, it, expect, beforeEach, vi } from 'vitest';
-import { setupAxios, onRequest, onResponseError } from 'src/boot/axios';
-import { useSession } from 'src/composables/useSession';
-import useNotify from 'src/composables/useNotify';
-import { useStateQueryStore } from 'src/stores/useStateQueryStore';
+import { Notify } from 'quasar';
+import { onRequest, onResponseError } from 'src/boot/axios';
+import { describe, expect, it, vi } from 'vitest';
 
-vi.mock('src/composables/useSession');
-vi.mock('src/composables/useNotify');
-vi.mock('src/stores/useStateQueryStore');
+vi.mock('src/composables/useSession', () => ({
+    useSession: () => ({
+        getToken: () => 'DEFAULT_TOKEN',
+        isLoggedIn: () => vi.fn(),
+        destroy: () => vi.fn(),
+    }),
+}));
+
+vi.mock('src/stores/useStateQueryStore', () => ({
+    useStateQueryStore: () => ({
+        add: () => vi.fn(),
+        remove: () => vi.fn(),
+    }),
+}));
 
 describe('Axios boot', () => {
-    let sessionMock, notifyMock, stateQueryMock;
-
-    beforeEach(() => {
-        sessionMock = {
-            getToken: vi.fn().mockReturnValue('DEFAULT_TOKEN'),
-            isLoggedIn: vi.fn().mockReturnValue(true),
-            destroy: vi.fn(),
-        };
-
-        notifyMock = {
-            notify: vi.fn(),
-        };
-
-        stateQueryMock = {
-            add: vi.fn(),
-            remove: vi.fn(),
-        };
-
-        useSession.mockReturnValue(sessionMock);
-        useNotify.mockReturnValue(notifyMock);
-        useStateQueryStore.mockReturnValue(stateQueryMock);
-
-        setupAxios();
-    });
     describe('onRequest()', async () => {
         it('should set the "Authorization" property on the headers', async () => {
             const config = { headers: {} };

From c4a4f7fcd632bbc99d9a46c4ff546f6e64a2c7f1 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Thu, 14 Nov 2024 11:20:16 +0100
Subject: [PATCH 175/207] refactor: refs #6818 change channel source

---
 src/components/ui/VnLinkPhone.vue | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 3b63889e1..4c045968f 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -17,19 +17,12 @@ const config = reactive({
 const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
 
 onBeforeMount(async () => {
-    let url;
     let { channel } = config[type];
 
     if (type === 'say-simple') {
-        url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
-        if (!channel)
-            channel = (
-                await axios.get('SaySimpleCountries/findOne', {
-                    params: {
-                        filter: { fields: ['channel'], where: { countryFk: 0 } },
-                    },
-                })
-            ).data?.channel;
+        const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne'))
+            .data;
+        if (!channel) channel = defaultChannel;
 
         config[
             type

From ecf131ba78847e8eb8c0f02bff45f3e495da9a8b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 12:06:12 +0100
Subject: [PATCH 176/207] feat: move buttons to DescriptorMenu

---
 .../Customer/Card/CustomerDescriptor.vue      | 34 --------------
 .../Customer/Card/CustomerDescriptorMenu.vue  | 44 +++++++++++++++++++
 src/pages/Ticket/TicketList.vue               | 12 ++---
 3 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index 974b05181..e46d2cb29 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -174,23 +174,6 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 >
                     <QTooltip>{{ t('Customer ticket list') }}</QTooltip>
                 </QBtn>
-                <QBtn
-                    :to="{
-                        name: 'TicketList',
-                        query: {
-                            table: JSON.stringify({
-                                clientFk: entity.id,
-                            }),
-                            createForm: JSON.stringify({ clientId: entity.id }),
-                        },
-                    }"
-                    size="md"
-                    color="primary"
-                    target="_blank"
-                    icon="vn:ticketAdd"
-                >
-                    <QTooltip>{{ t('New ticket') }}</QTooltip>
-                </QBtn>
                 <QBtn
                     :to="{
                         name: 'InvoiceOutList',
@@ -202,23 +185,6 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
                 >
                     <QTooltip>{{ t('Customer invoice out list') }}</QTooltip>
                 </QBtn>
-                <QBtn
-                    :to="{
-                        name: 'OrderList',
-                        query: {
-                            table: JSON.stringify({
-                                clientFk: entity.id,
-                            }),
-                            createForm: JSON.stringify({ clientFk: entity.id }),
-                        },
-                    }"
-                    size="md"
-                    target="_blank"
-                    icon="vn:basketadd"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('New order') }}</QTooltip>
-                </QBtn>
                 <QBtn
                     :to="{
                         name: 'AccountSummary',
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index 7af415820..5ef217a31 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -40,9 +40,53 @@ const sendSms = async (payload) => {
         notify(error.message, 'positive');
     }
 };
+
+const openTicketCreateForm = () => {
+    const query = {
+        table: {
+            clientFk: $props.customer.id,
+        },
+        createForm: {
+            clientId: $props.customer.id,
+            addressId: $props.customer.defaultAddressFk,
+        },
+    };
+    openWindow('ticket', query);
+};
+const openOrderCreateForm = () => {
+    const query = {
+        table: {
+            clientFk: $props.customer.id,
+        },
+        createForm: {
+            clientFk: $props.customer.id,
+            addressId: $props.customer.defaultAddressFk,
+        },
+    };
+    openWindow('order', query);
+};
+
+const openWindow = (type, { createForm, table }) => {
+    window.open(
+        `/#/${type}/list?createForm=${JSON.stringify(createForm)}&table=${JSON.stringify(
+            table
+        )}`,
+        '_blank'
+    );
+};
 </script>
 
 <template>
+    <QItem v-ripple clickable @click="openTicketCreateForm()">
+        <QItemSection>
+            {{ t('globals.pageTitles.createTicket') }}
+        </QItemSection>
+    </QItem>
+    <QItem v-ripple clickable @click="openOrderCreateForm()">
+        <QItemSection>
+            {{ t('globals.pageTitles.createOrder') }}
+        </QItemSection>
+    </QItem>
     <QItem v-ripple clickable>
         <QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
     </QItem>
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index a3876a1a6..0685217ac 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -45,6 +45,13 @@ const userParams = {
     from: null,
     to: null,
 };
+
+onMounted(() => {
+    initializeFromQuery();
+    stateStore.rightDrawer = true;
+    if (!route.query.createForm) return;
+    onClientSelected(JSON.parse(route.query.createForm));
+});
 // Método para inicializar las variables desde la query string
 const initializeFromQuery = () => {
     const query = route.query.table ? JSON.parse(route.query.table) : {};
@@ -301,11 +308,6 @@ const getDateColor = (date) => {
     if (comparation < 0) return 'bg-success';
 };
 
-onMounted(() => {
-    initializeFromQuery();
-    stateStore.rightDrawer = true;
-});
-
 async function makeInvoice(ticket) {
     const ticketsIds = ticket.map((item) => item.id);
     const { data } = await axios.post(`Tickets/invoiceTicketsAndPdf`, { ticketsIds });

From 291e97e540b7a16e7fa6587fe233d5e648b2e853 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 14 Nov 2024 12:48:33 +0100
Subject: [PATCH 177/207] feat: #6943 use openURL quasar

---
 src/composables/useOpenURL.js                 |  8 ++++
 .../Customer/Card/CustomerDescriptorMenu.vue  | 40 +++++++------------
 2 files changed, 22 insertions(+), 26 deletions(-)
 create mode 100644 src/composables/useOpenURL.js

diff --git a/src/composables/useOpenURL.js b/src/composables/useOpenURL.js
new file mode 100644
index 000000000..008774c20
--- /dev/null
+++ b/src/composables/useOpenURL.js
@@ -0,0 +1,8 @@
+import { openURL } from 'quasar';
+const defaultWindowFeatures = {
+    noopener: true,
+    noreferrer: true,
+};
+export default function (url, windowFeatures = defaultWindowFeatures, fn = undefined) {
+    openURL(url, fn, windowFeatures);
+}
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index 5ef217a31..aeaeaef57 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -6,8 +6,8 @@ import axios from 'axios';
 import { useQuasar } from 'quasar';
 
 import useNotify from 'src/composables/useNotify';
-
 import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
+import useOpenURL from 'src/composables/useOpenURL';
 
 const $props = defineProps({
     customer: {
@@ -15,7 +15,6 @@ const $props = defineProps({
         required: true,
     },
 });
-
 const { notify } = useNotify();
 const { t } = useI18n();
 const quasar = useQuasar();
@@ -41,48 +40,37 @@ const sendSms = async (payload) => {
     }
 };
 
-const openTicketCreateForm = () => {
+const openCreateForm = (type) => {
     const query = {
         table: {
             clientFk: $props.customer.id,
         },
         createForm: {
-            clientId: $props.customer.id,
             addressId: $props.customer.defaultAddressFk,
         },
     };
-    openWindow('ticket', query);
-};
-const openOrderCreateForm = () => {
-    const query = {
-        table: {
-            clientFk: $props.customer.id,
-        },
-        createForm: {
-            clientFk: $props.customer.id,
-            addressId: $props.customer.defaultAddressFk,
-        },
+    const clientFk = {
+        ticket: 'clientId',
+        order: 'clientFk',
     };
-    openWindow('order', query);
-};
+    const key = clientFk[type];
+    if (!key) return;
+    query.createForm[key] = $props.customer.id;
 
-const openWindow = (type, { createForm, table }) => {
-    window.open(
-        `/#/${type}/list?createForm=${JSON.stringify(createForm)}&table=${JSON.stringify(
-            table
-        )}`,
-        '_blank'
-    );
+    const params = Object.entries(query)
+        .map(([key, value]) => `${key}=${JSON.stringify(value)}`)
+        .join('&');
+    useOpenURL(`/#/${type}/list?${params}`);
 };
 </script>
 
 <template>
-    <QItem v-ripple clickable @click="openTicketCreateForm()">
+    <QItem v-ripple clickable @click="openCreateForm('ticket')">
         <QItemSection>
             {{ t('globals.pageTitles.createTicket') }}
         </QItemSection>
     </QItem>
-    <QItem v-ripple clickable @click="openOrderCreateForm()">
+    <QItem v-ripple clickable @click="openCreateForm('order')">
         <QItemSection>
             {{ t('globals.pageTitles.createOrder') }}
         </QItemSection>

From 7224860c5cd5359dd04685e58aefb04c6b7dce55 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Thu, 14 Nov 2024 13:51:39 +0100
Subject: [PATCH 178/207] feat: refs #6839 normalize search

---
 src/components/LeftMenu.vue | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 6e0ae5907..b02c0d014 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -34,18 +34,26 @@ const search = ref(null);
 
 const filteredItems = computed(() => {
     if (!search.value) return items.value;
+    const normalizedSearch = normalize(search.value);
     return items.value.filter((item) => {
-        const locale = t(item.title).toLowerCase();
-        return locale.includes(search.value.toLowerCase());
+        const locale = normalize(t(item.title));
+        return locale.includes(normalizedSearch);
     });
 });
 
 const filteredPinnedModules = computed(() => {
     if (!search.value) return pinnedModules.value;
+    const normalizedSearch = search.value
+        .normalize('NFD')
+        .replace(/[\u0300-\u036f]/g, '')
+        .toLowerCase();
     const map = new Map();
     for (const [key, pinnedModule] of pinnedModules.value) {
-        const locale = t(pinnedModule.title).toLowerCase();
-        if (locale.includes(search.value.toLowerCase())) map.set(key, pinnedModule);
+        const locale = t(pinnedModule.title)
+            .normalize('NFD')
+            .replace(/[\u0300-\u036f]/g, '')
+            .toLowerCase();
+        if (locale.includes(normalizedSearch)) map.set(key, pinnedModule);
     }
     return map;
 });
@@ -147,6 +155,13 @@ async function togglePinned(item, event) {
 const handleItemExpansion = (itemName) => {
     expansionItemElements[itemName].scrollToLastElement();
 };
+
+function normalize(text) {
+    return text
+        .normalize('NFD')
+        .replace(/[\u0300-\u036f]/g, '')
+        .toLowerCase();
+}
 </script>
 
 <template>

From 59b40fed45f18c0847c73f102fb409904583c03d Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Thu, 14 Nov 2024 15:57:01 +0100
Subject: [PATCH 179/207] feat: refs #7874 improve vn-notes ui

---
 src/components/ui/VnNotes.vue | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index b395b3934..2164f668e 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -65,15 +65,8 @@ onBeforeRouteLeave((to, from, next) => {
         auto-load
         @on-fetch="(data) => (observationTypes = data)"
     />
-    <QCard class="q-pa-xs q-mb-xl full-width" v-if="$props.addNote">
-        <QCardSection horizontal>
-            <VnAvatar :worker-id="currentUser.id" size="md" />
-            <div class="full-width row justify-between q-pa-xs">
-                <VnUserLink :name="t('New note')" :worker-id="currentUser.id" />
-                {{ t('globals.now') }}
-            </div>
-        </QCardSection>
-        <QCardSection class="q-px-xs q-my-none q-py-none">
+    <QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
+        <QCardSection class="q-px-xs q-mt-sm q-py-none">
             <VnRow class="full-width">
                 <VnSelect
                     :label="t('Observation type')"
@@ -144,7 +137,7 @@ onBeforeRouteLeave((to, from, next) => {
                         <div class="full-width row justify-between q-pa-xs">
                             <div>
                                 <VnUserLink
-                                    :name="`${note.worker.user.nickname}`"
+                                    :name="`${note.worker.user.name}`"
                                     :worker-id="note.worker.id"
                                 />
                                 <QBadge

From 8e0b098756ecb29e3b0e4c6707dcb8a5588b0f51 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Thu, 14 Nov 2024 16:01:09 +0100
Subject: [PATCH 180/207] fix: refs #7874 add title

---
 src/components/ui/VnNotes.vue | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index 2164f668e..dbcb2f3fe 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -66,7 +66,10 @@ onBeforeRouteLeave((to, from, next) => {
         @on-fetch="(data) => (observationTypes = data)"
     />
     <QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
-        <QCardSection class="q-px-xs q-mt-sm q-py-none">
+        <QCardSection horizontal>
+            {{ t('New note') }}
+        </QCardSection>
+        <QCardSection class="q-px-xs q-my-none q-py-none">
             <VnRow class="full-width">
                 <VnSelect
                     :label="t('Observation type')"

From 2bc219a09b8b059d0468510b910e1d9b5561b2bb Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 18 Nov 2024 06:59:09 +0100
Subject: [PATCH 181/207] refactor: refs #8185 modified LeftMenu to avoid
 duplicates

---
 src/components/LeftMenu.vue | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 6e0ae5907..3bbb5b046 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -22,7 +22,7 @@ const props = defineProps({
         default: 'main',
     },
 });
-
+const initialized = ref(false);
 const items = ref([]);
 const expansionItemElements = reactive({});
 const pinnedModules = computed(() => {
@@ -53,11 +53,13 @@ const filteredPinnedModules = computed(() => {
 onMounted(async () => {
     await navigation.fetchPinned();
     getRoutes();
+    initialized.value = true;
 });
 
 watch(
     () => route.matched,
     () => {
+        if (!initialized.value) return;
         items.value = [];
         getRoutes();
     },

From f52095a2fcb6b7fbd783e09456996f5a927f9a43 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 18 Nov 2024 10:57:49 +0100
Subject: [PATCH 182/207] Merge branch 'test' into solveConflicts_test_to_dev

---
 src/pages/Claim/ClaimFilter.vue               |   2 +-
 .../Card/BasicData/TicketBasicDataForm.vue    | 109 +++++++-----------
 src/pages/Ticket/TicketList.vue               |  59 ++++++----
 3 files changed, 77 insertions(+), 93 deletions(-)

diff --git a/src/pages/Claim/ClaimFilter.vue b/src/pages/Claim/ClaimFilter.vue
index dc25fe4a0..f7e2ffbf6 100644
--- a/src/pages/Claim/ClaimFilter.vue
+++ b/src/pages/Claim/ClaimFilter.vue
@@ -23,7 +23,7 @@ defineExpose({ states });
 
 <template>
     <FetchData url="ClaimStates" @on-fetch="(data) => (states = data)" auto-load />
-    <VnFilterPanel :data-key="props.dataKey" :search-button="true" search-url="table">
+    <VnFilterPanel :data-key="props.dataKey" :search-button="true">
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">
                 <strong>{{ t(`params.${tag.label}`) }}: </strong>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index 8c6d454c0..1fc54f486 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -16,12 +16,9 @@ import { useAcl } from 'src/composables/useAcl';
 import { useValidator } from 'src/composables/useValidator';
 import { toTimeFormat } from 'filters/date.js';
 
-const $props = defineProps({
-    formData: {
-        type: Object,
-        required: true,
-        default: () => ({}),
-    },
+const formData = defineModel({
+    type: Object,
+    required: true,
 });
 
 const emit = defineEmits(['updateForm']);
@@ -40,7 +37,6 @@ const agenciesOptions = ref([]);
 const zonesOptions = ref([]);
 const addresses = ref([]);
 const zoneSelectRef = ref();
-const formData = ref($props.formData);
 
 watch(
     () => formData.value,
@@ -69,47 +65,28 @@ const zoneWhere = computed(() => {
         : {};
 });
 
-const getLanded = async (params) => {
-    try {
-        const validParams =
-            shipped.value && addressId.value && agencyModeId.value && warehouseId.value;
-        if (!validParams) return;
+async function getLanded(params) {
+    getDate(`Agencies/getLanded`, params);
+}
 
-        formData.value.zoneFk = null;
-        zonesOptions.value = [];
-        const { data } = await axios.get(`Agencies/getLanded`, { params });
-        if (data) {
-            formData.value.zoneFk = data.zoneFk;
-            formData.value.landed = data.landed;
-            formData.value.shipped = params.shipped;
-        }
-    } catch (error) {
-        console.error(error);
-        notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
+async function getShipped(params) {
+    getDate(`Agencies/getShipped`, params);
+}
+
+async function getDate(query, params) {
+    for (const param in params) {
+        if (!params[param]) return;
     }
-};
 
-const getShipped = async (params) => {
-    try {
-        const validParams =
-            landed.value && addressId.value && agencyModeId.value && warehouseId.value;
-        if (!validParams) return;
+    formData.value.zoneFk = null;
+    zonesOptions.value = [];
+    const { data } = await axios.get(query, { params });
+    if (!data) return notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
 
-        formData.value.zoneFk = null;
-        zonesOptions.value = [];
-        const { data } = await axios.get(`Agencies/getShipped`, { params });
-        if (data) {
-            formData.value.zoneFk = data.zoneFk;
-            formData.value.landed = params.landed;
-            formData.value.shipped = data.shipped;
-        } else {
-            notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
-        }
-    } catch (error) {
-        console.error(error);
-        notify(t('basicData.noDeliveryZoneAvailable'), 'negative');
-    }
-};
+    formData.value.zoneFk = data.zoneFk;
+    if (data.landed) formData.value.landed = data.landed;
+    if (data.shipped) formData.value.shipped = data.shipped;
+}
 
 const onChangeZone = async (zoneId) => {
     formData.value.agencyModeFk = null;
@@ -177,18 +154,26 @@ const clientId = computed({
     },
 });
 
-const landed = computed({
-    get: () => formData.value?.landed,
-    set: (val) => {
-        formData.value.landed = val;
-        getShipped({
-            landed: val,
+function addDateParams(obj) {
+    return {
+        ...obj,
+        ...{
             addressFk: formData.value?.addressFk,
             agencyModeFk: formData.value?.agencyModeFk,
             warehouseFk: formData.value?.warehouseFk,
-        });
-    },
-});
+        },
+    };
+}
+
+async function setLanded(landed) {
+    if (!landed) return;
+    getShipped(addDateParams({ landed }));
+}
+
+async function setShipped(shipped) {
+    if (!shipped) return;
+    getLanded(addDateParams({ shipped }));
+}
 
 const agencyModeId = computed({
     get: () => formData.value.agencyModeFk,
@@ -236,21 +221,6 @@ const warehouseId = computed({
     },
 });
 
-const shipped = computed({
-    get: () => formData.value?.shipped,
-    set: (val) => {
-        if (new Date(formData.value?.shipped).toDateString() != val.toDateString())
-            val.setHours(0, 0, 0, 0);
-        formData.value.shipped = val;
-        getLanded({
-            shipped: val,
-            addressFk: formData.value?.addressFk,
-            agencyModeFk: formData.value?.agencyModeFk,
-            warehouseFk: formData.value?.warehouseFk,
-        });
-    },
-});
-
 const onFormModelInit = () => {
     if (formData.value?.clientFk) clientAddressesList(formData.value?.clientFk);
 };
@@ -451,18 +421,21 @@ async function getZone(options) {
                 v-model="formData.shipped"
                 :required="true"
                 :rules="validate('ticketList.shipped')"
+                @update:model-value="setShipped"
             />
             <VnInputTime
                 :label="t('basicData.shippedHour')"
                 v-model="formData.shipped"
                 :required="true"
                 :rules="validate('basicData.shippedHour')"
+                @update:model-value="setShipped"
             />
             <VnInputDate
                 :label="t('basicData.landed')"
                 v-model="formData.landed"
                 :required="true"
                 :rules="validate('basicData.landed')"
+                @update:model-value="setLanded"
             />
         </VnRow>
     </QForm>
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 0685217ac..aae6f80a7 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -1,7 +1,7 @@
 <script setup>
 import axios from 'axios';
 import { computed, ref, onMounted } from 'vue';
-import { useRoute } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 import { useStateStore } from 'stores/useStateStore';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -18,12 +18,13 @@ import RightMenu from 'src/components/common/RightMenu.vue';
 import TicketFilter from './TicketFilter.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import FetchData from 'src/components/FetchData.vue';
-import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
-import ZoneDescriptorProxy from '../Zone/Card/ZoneDescriptorProxy.vue';
+import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
+import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 import { toTimeFormat } from 'src/filters/date';
-import InvoiceOutDescriptorProxy from '../InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
+import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
 
 const route = useRoute();
+const router = useRouter();
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
 const tableRef = ref();
@@ -40,23 +41,18 @@ from.setDate(from.getDate() - 7);
 const to = Date.vnNew();
 to.setHours(23, 59, 0, 0);
 to.setDate(to.getDate() + 1);
-
 const userParams = {
     from: null,
     to: null,
 };
-
 onMounted(() => {
     initializeFromQuery();
     stateStore.rightDrawer = true;
     if (!route.query.createForm) return;
     onClientSelected(JSON.parse(route.query.createForm));
 });
-// Método para inicializar las variables desde la query string
 const initializeFromQuery = () => {
     const query = route.query.table ? JSON.parse(route.query.table) : {};
-
-    // Asigna los valores a las variables correspondientes
     from.value = query.from || from.toISOString();
     to.value = query.to || to.toISOString();
     Object.assign(userParams, { from, to });
@@ -213,13 +209,19 @@ const columns = computed(() => [
             {
                 title: t('components.smartCard.viewSummary'),
                 icon: 'preview',
-                isPrimary: true,
-                action: (row) => viewSummary(row.id, TicketSummary),
+                action: (row, evt) => {
+                    if (evt && evt.ctrlKey) {
+                        const url = router.resolve({
+                            params: { id: row.id },
+                            name: 'TicketCard',
+                        }).href;
+                        window.open(url, '_blank');
+                    } else viewSummary(row.id, TicketSummary);
+                },
             },
         ],
     },
 ]);
-
 function redirectToLines(id) {
     const url = `#/ticket/${id}/sale`;
     window.open(url, '_blank');
@@ -456,24 +458,24 @@ function setReference(data) {
         auto-load
     />
     <VnSearchbar
-        data-key="Ticket"
+        data-key="TicketList"
         :label="t('Search ticket')"
         :info="t('You can search by ticket id or alias')"
     />
     <RightMenu>
         <template #right-panel>
-            <TicketFilter data-key="Ticket" />
+            <TicketFilter data-key="TicketList" />
         </template>
     </RightMenu>
     <VnTable
         ref="tableRef"
-        data-key="Ticket"
+        data-key="TicketList"
         url="Tickets/filter"
         :create="{
             urlCreate: 'Tickets/new',
             title: t('ticketList.createTicket'),
             onDataSaved: ({ id }) => tableRef.redirect(id),
-            formInitialData: {},
+            formInitialData: { clientId: null },
         }"
         default-mode="table"
         :order="['shippedDate DESC', 'shippedHour ASC', 'zoneLanding ASC', 'id']"
@@ -575,17 +577,17 @@ function setReference(data) {
             </span>
         </template>
         <template #column-stateFk="{ row }">
-            <span v-if="getColor(row)">
-                <QChip :class="getColor(row)" dense square>
-                    {{ row.state }}
-                </QChip>
-            </span>
-            <span v-else-if="row.state === 'Entregado'">
+            <span v-if="row.refFk">
                 <span class="link" @click.stop>
                     {{ row.refFk }}
                     <InvoiceOutDescriptorProxy :id="row.invoiceOutId" />
                 </span>
             </span>
+            <span v-else-if="getColor(row)">
+                <QChip :class="getColor(row)" dense square>
+                    {{ row.state }}
+                </QChip>
+            </span>
             <span v-else>
                 {{ row.state }}
             </span>
@@ -617,6 +619,7 @@ function setReference(data) {
                     option-value="id"
                     option-label="name"
                     hide-selected
+                    required
                     @update:model-value="(client) => onClientSelected(data)"
                     :sort-by="'id ASC'"
                 >
@@ -643,6 +646,7 @@ function setReference(data) {
                     option-label="nickname"
                     hide-selected
                     map-options
+                    required
                     :disable="!data.clientId"
                     :sort-by="'isActive DESC'"
                     @update:model-value="() => fetchAvailableAgencies(data)"
@@ -693,6 +697,7 @@ function setReference(data) {
                         option-value="id"
                         option-label="name"
                         hide-selected
+                        required
                         @update:model-value="() => fetchAvailableAgencies(data)"
                     />
                 </div>
@@ -706,7 +711,6 @@ function setReference(data) {
                         option-value="agencyModeFk"
                         option-label="agencyMode"
                         hide-selected
-                        :disable="!data.clientId || !data.landed || !data.warehouseId"
                     />
                 </div>
             </VnRow>
@@ -842,7 +846,14 @@ function setReference(data) {
         </QTooltip>
     </QPageSticky>
 </template>
-
+<style scoped>
+.disabled,
+.disabled *,
+[disabled],
+[disabled] * {
+    cursor: pointer !important;
+}
+</style>
 <i18n>
 es:
     Search ticket: Buscar ticket

From 0c0b9ca648426bc8aaa91ad46b5902dd178e70ac Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 18 Nov 2024 12:27:07 +0100
Subject: [PATCH 183/207] fix: changed route.query

---
 src/filters/getParamWhere.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/filters/getParamWhere.js b/src/filters/getParamWhere.js
index 22dd69af1..ef00a93ae 100644
--- a/src/filters/getParamWhere.js
+++ b/src/filters/getParamWhere.js
@@ -9,7 +9,7 @@ function parseJSON(str, fallback) {
 }
 export default function (route, param) {
     // catch route query params
-    const params = parseJSON(route?.query?.params, {});
+    const params = parseJSON(route?.query?.table, {});
     // extract and parse filter from params
     const { filter: filterStr = '{}' } = params;
 

From 8d997b5a7a0f2030d2dc78c251e079861608cc72 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 19 Nov 2024 07:59:48 +0100
Subject: [PATCH 184/207] build: refs #8144 change package version

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index e2e75f253..0ee43ce12 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "salix-front",
-    "version": "24.44.0",
+    "version": "24.48.0",
     "description": "Salix frontend",
     "productName": "Salix",
     "author": "Verdnatura",
@@ -64,4 +64,4 @@
         "vite": "^5.1.4",
         "vitest": "^0.31.1"
     }
-}
+}
\ No newline at end of file

From 38ccf464b761e4724c5688a6e01af39a16c07d59 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 19 Nov 2024 11:52:00 +0100
Subject: [PATCH 185/207] fix: refs #7323 locale #7396

---
 src/i18n/locale/en.yml | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index ae7007c32..531b3bc14 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -583,15 +583,15 @@ worker:
         role: Role
         sipExtension: Extension
         locker: Locker
-        fiDueDate: Fecha de caducidad del DNI
-        sex: Sexo
-        seniority: Antigüedad
+        fiDueDate: FI due date
+        sex: Sex
+        seniority: Seniority
         fi: DNI/NIE/NIF
-        birth: Fecha de nacimiento
-        isFreelance: Autónomo
+        birth: Birth
+        isFreelance: Freelance
         isSsDiscounted: Bonificación SS
-        hasMachineryAuthorized: Autorizado para llevar maquinaria
-        isDisable: Trabajador desactivado
+        hasMachineryAuthorized: Machinery authorized
+        isDisable: Disable
     notificationsManager:
         activeNotifications: Active notifications
         availableNotifications: Available notifications

From 1faab668b16baceb6ebec80c9075b1e38ff12acd Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Tue, 19 Nov 2024 11:53:33 +0100
Subject: [PATCH 186/207] fix: refs #7323 show advanced fields

---
 src/i18n/locale/es.yml                  | 6 +++---
 src/pages/Worker/Card/WorkerSummary.vue | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index eb0978ddd..9bfa43c49 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -579,9 +579,9 @@ worker:
         newWorker: Nuevo trabajador
     summary:
         boss: Jefe
-        phoneExtension: Extensión de teléfono
-        entPhone: Teléfono de empresa
-        personalPhone: Teléfono personal
+        phoneExtension: Ext. de teléfono
+        entPhone: Tel. de empresa
+        personalPhone: Tel. personal
         noBoss: Sin jefe
         userData: Datos de usuario
         userId: ID del usuario
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 93866b79f..496f1ca16 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -75,10 +75,10 @@ onBeforeMount(async () => {
                         <VnLinkPhone :phone-number="worker.phone" />
                     </template>
                 </VnLv>
-                <VnLv :value="worker.client?.phone">
+                <VnLv :value="advancedSummary?.client?.phone">
                     <template #label>
                         {{ t('worker.summary.personalPhone') }}
-                        <VnLinkPhone :phone-number="worker.client?.phone" />
+                        <VnLinkPhone :phone-number="advancedSummary?.client?.phone" />
                     </template>
                 </VnLv>
             </QCard>
@@ -86,12 +86,12 @@ onBeforeMount(async () => {
                 <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
                 <VnLv
                     :label="t('worker.summary.fiDueDate')"
-                    :value="toDate(worker.fiDueDate)"
+                    :value="toDate(advancedSummary.fiDueDate)"
                 />
                 <VnLv :label="t('worker.summary.sex')" :value="worker.sex" />
                 <VnLv
                     :label="t('worker.summary.seniority')"
-                    :value="toDate(worker.seniority)"
+                    :value="toDate(advancedSummary.seniority)"
                 />
                 <VnLv :label="t('worker.summary.fi')" :value="advancedSummary.fi" />
                 <VnLv

From 5515f55bf69d3f2121410d28bdf5f35c4f9557b0 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 19 Nov 2024 12:51:05 +0100
Subject: [PATCH 187/207] test: fix e2e

---
 .../integration/client/clientList.spec.js     | 31 ++++++++++++++-----
 .../vnComponent/vnLocation.spec.js            |  6 ++--
 test/cypress/support/commands.js              |  6 ++--
 3 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 93e53b9f6..b87ddff3b 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -6,7 +6,11 @@ describe('Client list', () => {
         cy.visit('/#/customer/list', {
             timeout: 5000,
             onBeforeLoad(win) {
-                cy.stub(win, 'open');
+                cy.stub(win, 'open')
+                    .callsFake((url) => {
+                        return win.open.wrappedMethod.call(win, url, '_self');
+                    })
+                    .as('Open');
             },
         });
     });
@@ -44,20 +48,31 @@ describe('Client list', () => {
         });
     });
 
-    it('Client founded create ticket', () => {
+    it.only('Client founded create ticket', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
-        cy.clickButtonsDescriptor(2);
+        cy.openActionDescriptor('Create ticket');
         cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form');
-        cy.checkValueForm(1, search);
+        cy.waitForElement('.q-form', { timeout: 5000 });
+        cy.checkValueSelectForm(1, 1110);
+        cy.checkValueSelectForm(2, search);
+        // cy.get('@Open').should('have.been.calledOnceWithExactly', [
+        //     '/#/ticket/list?table={"clientFk":1110}&createForm={"addressId":10,"clientId":1110}',
+        //     '_blank',
+        //     'noopener,noreferrer',
+        // ]);
     });
-    it('Client founded create order', () => {
+    it.only('Client founded create order', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
-        cy.clickButtonsDescriptor(4);
+        cy.openActionDescriptor('New order');
         cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form');
+        cy.waitForElement('.q-form', { timeout: 5000 });
+        cy.checkValueForm(1, 1110);
         cy.checkValueForm(2, search);
+        // cy.get('@Open').should(
+        //     'have.been.calledOnceWithExactly',
+        //     '"/#/order/list?table={"clientFk":1110}&createForm={"addressId":10,"clientFk":1110}", "_blank", "noopener,noreferrer"'
+        // );
     });
 });
diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 924b16adc..29e1f868f 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -15,10 +15,10 @@ describe('VnLocation', () => {
             cy.domContentLoad();
             cy.get(createLocationButton).click();
         });
-        it('should filter provinces based on selected country', () => {
+        it.only('shoul d filter provinces based on selected country', () => {
             // Select a country
             cy.selectOption(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(5)> ${createForm.sufix}`,
+                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,
                 'Ecuador'
             );
             // Verify that provinces are filtered
@@ -32,7 +32,7 @@ describe('VnLocation', () => {
             ).should('have.length', 1);
         });
 
-        it('should filter towns based on selected province', () => {
+        it.only('should filter towns based on selected province', () => {
             // Select a country
             cy.selectOption(
                 `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 34aadad1d..b92bbe269 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -295,16 +295,16 @@ Cypress.Commands.add('checkNotification', (text) => {
                 throw new Error(`Notification not found: "${text}"`);
         });
 });
-
+// :nth-child(2) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container
 Cypress.Commands.add('checkValueForm', (id, search) => {
     cy.get(
-        `.grid-create > :nth-child(${id}) > .q-field__inner>.q-field__control> .q-field__control-container>.q-field__native >.q-field__input`
+        `.grid-create > :nth-child(${id})  > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
     ).should('have.value', search);
 });
 
 Cypress.Commands.add('checkValueSelectForm', (id, search) => {
     cy.get(
-        `.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container>.q-field__native>.q-field__input`
+        `.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
     ).should('have.value', search);
 });
 

From 65100fcf256f9c19494088c9c2b3d48422c8970b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 19 Nov 2024 13:45:44 +0100
Subject: [PATCH 188/207] test: fix e2e

---
 test/cypress/integration/vnComponent/vnLocation.spec.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 29e1f868f..0ee453aa0 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -15,7 +15,7 @@ describe('VnLocation', () => {
             cy.domContentLoad();
             cy.get(createLocationButton).click();
         });
-        it.only('shoul d filter provinces based on selected country', () => {
+        it('should filter provinces based on selected country', () => {
             // Select a country
             cy.selectOption(
                 `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,
@@ -32,7 +32,7 @@ describe('VnLocation', () => {
             ).should('have.length', 1);
         });
 
-        it.only('should filter towns based on selected province', () => {
+        it('should filter towns based on selected province', () => {
             // Select a country
             cy.selectOption(
                 `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,

From f43e974bbc595758ab316156b8e9f68d340b70f3 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 19 Nov 2024 14:14:50 +0100
Subject: [PATCH 189/207] fix: worker test e2e

---
 src/pages/Worker/WorkerList.vue  | 2 +-
 test/cypress/support/commands.js | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue
index 022cecdc6..71df273c1 100644
--- a/src/pages/Worker/WorkerList.vue
+++ b/src/pages/Worker/WorkerList.vue
@@ -306,7 +306,7 @@ async function autofillBic(worker) {
                 </VnRow>
                 <VnRow>
                     <VnInput
-                        :label="t('worker.create.street')"
+                        :label="t('globals.street')"
                         :model-value="uppercaseStreetModel(data).get()"
                         @update:model-value="uppercaseStreetModel(data).set"
                         :disable="data.isFreelance"
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 8d48dc71a..0e0cd7d07 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -100,7 +100,6 @@ Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
                     case 'select':
                         cy.wrap(el).type(val);
                         cy.get('.q-menu .q-item').contains(val).click();
-                        cy.get('body').click();
                         break;
                     case 'date':
                         cy.wrap(el).type(val.split('-').join(''));

From 8714980595e0cfa62e24b7a38f0553ad5c2290fa Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 19 Nov 2024 14:28:43 +0100
Subject: [PATCH 190/207] fix(VnSelect):  setOptions when applyFilter

---
 src/components/common/VnSelect.vue | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 227ff9465..f24f054a5 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -202,7 +202,10 @@ async function fetchFilter(val) {
     if (fields) fetchOptions.fields = fields;
     if (sortBy) fetchOptions.order = sortBy;
     arrayData.reset(['skip', 'filter.skip', 'page']);
-    return (await arrayData.applyFilter({ filter: fetchOptions }))?.data;
+
+    const { data } = await arrayData.applyFilter({ filter: fetchOptions });
+    setOptions(data);
+    return data;
 }
 
 async function filterHandler(val, update) {

From 5f7fd91272c4a870de82ef8c42ef50166d7ad1e7 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 19 Nov 2024 14:41:07 +0100
Subject: [PATCH 191/207] feat: add /reports in gitignore

---
 test/cypress/.gitignore | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/cypress/.gitignore b/test/cypress/.gitignore
index 3f91dd465..8d940320e 100644
--- a/test/cypress/.gitignore
+++ b/test/cypress/.gitignore
@@ -1,2 +1,2 @@
-videos/*
-screenshots/*
\ No newline at end of file
+reports/*
+screenshots/*

From b4ee19bcde76c9d44568b7742aeab673fdf61b50 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 19 Nov 2024 15:56:27 +0100
Subject: [PATCH 192/207] test: #8162 fix clientList spec

---
 .../integration/client/clientList.spec.js     | 18 +++++-----
 .../vnComponent/vnLocation.spec.js            | 35 ++++++-------------
 2 files changed, 20 insertions(+), 33 deletions(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index b87ddff3b..b3ac9d3df 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -15,7 +15,7 @@ describe('Client list', () => {
         });
     });
 
-    it('Client list create new client', () => {
+    it.only('Client list create new client', () => {
         cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
         const data = {
             Name: { val: 'Name 1' },
@@ -24,9 +24,9 @@ describe('Client list', () => {
             'Web user': { val: 'user_test_1' },
             Street: { val: 'C/ STREET 1' },
             Email: { val: 'user.test@1.com' },
-            'Business type': { val: 'Otros', type: 'select' },
-            'Sales person': { val: 'salesboss', type: 'select' },
+            'Sales person': { val: 'employee', type: 'select' },
             Location: { val: '46000, Valencia(Province one), España', type: 'select' },
+            'Business type': { val: 'Otros', type: 'select' },
         };
         cy.fillInForm(data);
 
@@ -48,13 +48,13 @@ describe('Client list', () => {
         });
     });
 
-    it.only('Client founded create ticket', () => {
+    it('Client founded create ticket', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
         cy.openActionDescriptor('Create ticket');
         cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form', { timeout: 5000 });
-        cy.checkValueSelectForm(1, 1110);
+        cy.waitForElement('.q-form');
+        cy.checkValueSelectForm(1, search);
         cy.checkValueSelectForm(2, search);
         // cy.get('@Open').should('have.been.calledOnceWithExactly', [
         //     '/#/ticket/list?table={"clientFk":1110}&createForm={"addressId":10,"clientId":1110}',
@@ -62,13 +62,13 @@ describe('Client list', () => {
         //     'noopener,noreferrer',
         // ]);
     });
-    it.only('Client founded create order', () => {
+    it('Client founded create order', () => {
         const search = 'Jessica Jones';
         cy.searchByLabel('Name', search);
         cy.openActionDescriptor('New order');
         cy.waitForElement('#formModel');
-        cy.waitForElement('.q-form', { timeout: 5000 });
-        cy.checkValueForm(1, 1110);
+        cy.waitForElement('.q-form');
+        cy.checkValueForm(1, search);
         cy.checkValueForm(2, search);
         // cy.get('@Open').should(
         //     'have.been.calledOnceWithExactly',
diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 0ee453aa0..70c88b26f 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -7,6 +7,9 @@ describe('VnLocation', () => {
         prefix: '.q-dialog__inner > .column > #formModel > .q-card',
         sufix: ' .q-field__inner > .q-field__control',
     };
+    const countrySelector = `${createForm.prefix} > :nth-child(5) > :nth-child(3) > ${createForm.sufix}`;
+    const provinceSelector = `${createForm.prefix} > :nth-child(5) > :nth-child(2) > ${createForm.sufix}`;
+    const citySelector = `${createForm.prefix} > :nth-child(4) > :nth-child(2) > ${createForm.sufix}`;
     describe('CreateFormDialog ', () => {
         beforeEach(() => {
             cy.viewport(1280, 720);
@@ -17,45 +20,29 @@ describe('VnLocation', () => {
         });
         it('should filter provinces based on selected country', () => {
             // Select a country
-            cy.selectOption(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,
-                'Ecuador'
-            );
+            cy.selectOption(countrySelector, 'Ecuador');
             // Verify that provinces are filtered
-            cy.get(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`
-            ).should('have.length', 1);
+            cy.get(countrySelector).should('have.length', 1);
 
             // Verify that towns are filtered
-            cy.get(
-                `${createForm.prefix} > :nth-child(4) > .q-field:nth-child(3)> ${createForm.sufix}`
-            ).should('have.length', 1);
+            cy.get(citySelector).should('have.length', 1);
         });
 
         it('should filter towns based on selected province', () => {
             // Select a country
-            cy.selectOption(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`,
-                'Ecuador'
-            );
+            cy.selectOption(countrySelector, 'Ecuador');
             // Verify that provinces are filtered
-            cy.get(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(3)> ${createForm.sufix}`
-            ).should('have.length', 1);
+            cy.get(provinceSelector).should('have.length', 1);
 
             // Verify that towns are filtered
-            cy.get(
-                `${createForm.prefix} > :nth-child(4) > .q-field:nth-child(3)> ${createForm.sufix}`
-            ).should('have.length', 1);
+            cy.get(citySelector).should('have.length', 1);
         });
         it('should pass selected country', () => {
             // Select a country
             const country = 'Ecuador';
             const province = 'Province five';
-            cy.selectOption(
-                `${createForm.prefix} > :nth-child(5) > .q-field:nth-child(5)> ${createForm.sufix}`,
-                country
-            );
+
+            cy.selectOption(countrySelector, country);
             cy.selectOption(
                 `${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix}`,
                 province

From 67a5800a6668af882d976182272706176776dc98 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 20 Nov 2024 07:57:45 +0100
Subject: [PATCH 193/207] fix: logout spec

---
 test/cypress/integration/outLogin/logout.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/integration/outLogin/logout.spec.js b/test/cypress/integration/outLogin/logout.spec.js
index d6c33a65b..bcdacec78 100644
--- a/test/cypress/integration/outLogin/logout.spec.js
+++ b/test/cypress/integration/outLogin/logout.spec.js
@@ -28,7 +28,7 @@ describe('Logout', () => {
         });
 
         it('when token not exists', () => {
-            cy.get('.q-list > [href="#/item"]').click();
+            cy.get('.q-list').first().should('be.visible').click();
             cy.checkNotification('Authorization Required');
         });
     });

From 3ba8402dfde616ec0a2a7430ad78acfccf62d755 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 20 Nov 2024 08:01:50 +0100
Subject: [PATCH 194/207] fix: vnSearchbar spec

---
 test/cypress/integration/vnComponent/vnSearchBar.spec.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/cypress/integration/vnComponent/vnSearchBar.spec.js b/test/cypress/integration/vnComponent/vnSearchBar.spec.js
index 580199bc3..b8621118c 100644
--- a/test/cypress/integration/vnComponent/vnSearchBar.spec.js
+++ b/test/cypress/integration/vnComponent/vnSearchBar.spec.js
@@ -5,6 +5,7 @@ describe('VnSearchBar', () => {
     const idGap = '.q-item > .q-item__label';
     const vnTableRow = '.q-virtual-scroll__content';
     beforeEach(() => {
+        cy.viewport(1280, 720);
         cy.login('developer');
         cy.visit('#/customer/list');
     });

From 1fb927488a2df2a312cb06dee4f9880ef014db7e Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 09:26:33 +0100
Subject: [PATCH 195/207] test: #8162 fix clientList spec

---
 test/cypress/integration/client/clientList.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index b3ac9d3df..37983cc70 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -15,7 +15,7 @@ describe('Client list', () => {
         });
     });
 
-    it.only('Client list create new client', () => {
+    it('Client list create new client', () => {
         cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
         const data = {
             Name: { val: 'Name 1' },

From e10ee5e6c77d4dceff48d9eaf0e97a7694461adb Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 09:26:40 +0100
Subject: [PATCH 196/207] test: #8162 fix vnLocation spec

---
 test/cypress/integration/vnComponent/vnLocation.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 70c88b26f..70a943688 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -107,7 +107,7 @@ describe('VnLocation', () => {
             cy.get(inputLocation).should('have.value', postCodeLabel);
         });
 
-        it('Create postCode', () => {
+        it.only('Create postCode', () => {
             const postCode = '1234475';
             const province = 'Valencia';
             cy.get(createLocationButton).click();

From 226f604f9d1f27b2a9bc9b6bc92cd1a72ee12c50 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 09:37:47 +0100
Subject: [PATCH 197/207] test: #8162 fix vnLocation spec

---
 test/cypress/integration/vnComponent/vnLocation.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 70a943688..70c88b26f 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -107,7 +107,7 @@ describe('VnLocation', () => {
             cy.get(inputLocation).should('have.value', postCodeLabel);
         });
 
-        it.only('Create postCode', () => {
+        it('Create postCode', () => {
             const postCode = '1234475';
             const province = 'Valencia';
             cy.get(createLocationButton).click();

From 9da04881841c5fc269f7fdeab4ed8f7f91790f0b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 10:03:23 +0100
Subject: [PATCH 198/207] feat: remove comments

---
 test/cypress/integration/client/clientList.spec.js  |  9 ---------
 .../integration/vnComponent/vnLocation.spec.js      | 13 -------------
 test/cypress/support/commands.js                    |  2 +-
 3 files changed, 1 insertion(+), 23 deletions(-)

diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js
index 37983cc70..431ac0548 100644
--- a/test/cypress/integration/client/clientList.spec.js
+++ b/test/cypress/integration/client/clientList.spec.js
@@ -56,11 +56,6 @@ describe('Client list', () => {
         cy.waitForElement('.q-form');
         cy.checkValueSelectForm(1, search);
         cy.checkValueSelectForm(2, search);
-        // cy.get('@Open').should('have.been.calledOnceWithExactly', [
-        //     '/#/ticket/list?table={"clientFk":1110}&createForm={"addressId":10,"clientId":1110}',
-        //     '_blank',
-        //     'noopener,noreferrer',
-        // ]);
     });
     it('Client founded create order', () => {
         const search = 'Jessica Jones';
@@ -70,9 +65,5 @@ describe('Client list', () => {
         cy.waitForElement('.q-form');
         cy.checkValueForm(1, search);
         cy.checkValueForm(2, search);
-        // cy.get('@Open').should(
-        //     'have.been.calledOnceWithExactly',
-        //     '"/#/order/list?table={"clientFk":1110}&createForm={"addressId":10,"clientFk":1110}", "_blank", "noopener,noreferrer"'
-        // );
     });
 });
diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 70c88b26f..ef08af679 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -19,26 +19,17 @@ describe('VnLocation', () => {
             cy.get(createLocationButton).click();
         });
         it('should filter provinces based on selected country', () => {
-            // Select a country
             cy.selectOption(countrySelector, 'Ecuador');
-            // Verify that provinces are filtered
             cy.get(countrySelector).should('have.length', 1);
-
-            // Verify that towns are filtered
             cy.get(citySelector).should('have.length', 1);
         });
 
         it('should filter towns based on selected province', () => {
-            // Select a country
             cy.selectOption(countrySelector, 'Ecuador');
-            // Verify that provinces are filtered
             cy.get(provinceSelector).should('have.length', 1);
-
-            // Verify that towns are filtered
             cy.get(citySelector).should('have.length', 1);
         });
         it('should pass selected country', () => {
-            // Select a country
             const country = 'Ecuador';
             const province = 'Province five';
 
@@ -67,13 +58,11 @@ describe('VnLocation', () => {
             cy.get(locationOptions).should('have.length.at.least', 5);
         });
         it('input filter location as "al"', function () {
-            // cy.get(inputLocation).click();
             cy.get(inputLocation).clear();
             cy.get(inputLocation).type('al');
             cy.get(locationOptions).should('have.length.at.least', 4);
         });
         it('input filter location as "ecuador"', function () {
-            // cy.get(inputLocation).click();
             cy.get(inputLocation).clear();
             cy.get(inputLocation).type('ecuador');
             cy.get(locationOptions).should('have.length.at.least', 1);
@@ -129,7 +118,6 @@ describe('VnLocation', () => {
             const province = 'Saskatchew';
             cy.get(createLocationButton).click();
             cy.get(dialogInputs).eq(0).type(postCode);
-            // city create button
             cy.get(
                 `${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix} > :nth-child(2) > .q-icon`
             ).click();
@@ -138,7 +126,6 @@ describe('VnLocation', () => {
             cy.get('#q-portal--dialog--3 .q-btn--standard').click();
             cy.get('#q-portal--dialog--1 .q-btn--standard').click();
             cy.waitForElement('.q-form');
-
             checkVnLocation(postCode, province);
         });
 
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index d4b2486e7..add41db57 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -294,7 +294,7 @@ Cypress.Commands.add('checkNotification', (text) => {
                 throw new Error(`Notification not found: "${text}"`);
         });
 });
-// :nth-child(2) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container
+
 Cypress.Commands.add('checkValueForm', (id, search) => {
     cy.get(
         `.grid-create > :nth-child(${id})  > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`

From deb6467af8ed5072dc714cc459ca036b3803302e Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 10:05:10 +0100
Subject: [PATCH 199/207] feat: remove comments

---
 test/cypress/support/commands.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index add41db57..1765b9043 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -297,7 +297,7 @@ Cypress.Commands.add('checkNotification', (text) => {
 
 Cypress.Commands.add('checkValueForm', (id, search) => {
     cy.get(
-        `.grid-create > :nth-child(${id})  > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
+        `.grid-create > :nth-child(${id}) > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
     ).should('have.value', search);
 });
 

From d6aedad38e49ee64b2a6b2f49a107b3b5975a67d Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Wed, 20 Nov 2024 10:07:03 +0100
Subject: [PATCH 200/207] perf: use const in VnLocation

---
 test/cypress/integration/vnComponent/vnLocation.spec.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index ef08af679..aeb938c6f 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -19,13 +19,15 @@ describe('VnLocation', () => {
             cy.get(createLocationButton).click();
         });
         it('should filter provinces based on selected country', () => {
-            cy.selectOption(countrySelector, 'Ecuador');
+            const country = 'Ecuador';
+            cy.selectOption(countrySelector, country);
             cy.get(countrySelector).should('have.length', 1);
             cy.get(citySelector).should('have.length', 1);
         });
 
         it('should filter towns based on selected province', () => {
-            cy.selectOption(countrySelector, 'Ecuador');
+            const country = 'Ecuador';
+            cy.selectOption(countrySelector, country);
             cy.get(provinceSelector).should('have.length', 1);
             cy.get(citySelector).should('have.length', 1);
         });

From 7039b68bba8d540be53d5f19ff3cdfc24ef508f1 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Wed, 20 Nov 2024 17:23:40 +0100
Subject: [PATCH 201/207] fix: refs #7874 show name

---
 src/pages/Claim/Card/ClaimNotes.vue   | 2 +-
 src/pages/Worker/Card/WorkerNotes.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Claim/Card/ClaimNotes.vue b/src/pages/Claim/Card/ClaimNotes.vue
index a4d11e9f6..134ee33ab 100644
--- a/src/pages/Claim/Card/ClaimNotes.vue
+++ b/src/pages/Claim/Card/ClaimNotes.vue
@@ -25,7 +25,7 @@ const claimFilter = computed(() => {
                 include: {
                     relation: 'user',
                     scope: {
-                        fields: ['id', 'nickname'],
+                        fields: ['id', 'nickname', 'name'],
                     },
                 },
             },
diff --git a/src/pages/Worker/Card/WorkerNotes.vue b/src/pages/Worker/Card/WorkerNotes.vue
index c15b1dfab..4f123206b 100644
--- a/src/pages/Worker/Card/WorkerNotes.vue
+++ b/src/pages/Worker/Card/WorkerNotes.vue
@@ -15,7 +15,7 @@ const filter = {
             include: {
                 relation: 'user',
                 scope: {
-                    fields: ['id', 'nickname'],
+                    fields: ['id', 'nickname', 'name'],
                 },
             },
         },

From e5434e743613a0595df2af9aac285b5d7a1f6e91 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 21 Nov 2024 09:08:52 +0000
Subject: [PATCH 202/207] warmfix: ItemLastEntries to date

---
 src/pages/Item/Card/ItemLastEntries.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Item/Card/ItemLastEntries.vue b/src/pages/Item/Card/ItemLastEntries.vue
index 5c0251ea8..22fb9adc7 100644
--- a/src/pages/Item/Card/ItemLastEntries.vue
+++ b/src/pages/Item/Card/ItemLastEntries.vue
@@ -170,7 +170,7 @@ onMounted(async () => {
     from.value = getDate(_from, 'from');
     const _to = Date.vnNew();
     _to.setDate(_to.getDate() + 10);
-    to.value = getDate(Date.vnNew(), 'to');
+    to.value = getDate(_to, 'to');
 
     updateFilter();
 

From 5268140d8bc229dfa59bd67baabb4f8de35800b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= <carlosap@verdnatura.es>
Date: Thu, 21 Nov 2024 15:51:27 +0100
Subject: [PATCH 203/207] feat: refs#8087 Redadas en travel

---
 src/i18n/locale/en.yml                     |  1 +
 src/i18n/locale/es.yml                     |  1 +
 src/pages/Entry/EntryList.vue              |  2 +-
 src/pages/Travel/Card/TravelBasicData.vue  | 12 +++----
 src/pages/Travel/Card/TravelCard.vue       | 29 +---------------
 src/pages/Travel/Card/TravelDescriptor.vue | 39 ++--------------------
 src/pages/Travel/Card/TravelFilter.js      | 29 ++++++++++++++++
 src/pages/Travel/Card/TravelSummary.vue    |  9 +++++
 src/pages/Travel/TravelList.vue            |  6 ++--
 9 files changed, 53 insertions(+), 75 deletions(-)
 create mode 100644 src/pages/Travel/Card/TravelFilter.js

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 60f460b9d..613046f86 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -767,6 +767,7 @@ travel:
         hb: HB
     basicData:
         daysInForward: Days in forward
+        isRaid: Raid
     thermographs:
         temperature: Temperature
         destination: Destination
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index c6ab57dd7..58ddc98ef 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -761,6 +761,7 @@ travel:
         hb: HB
     basicData:
         daysInForward: Días redada
+        isRaid: Redada
     thermographs:
         temperature: Temperatura
         destination: Destino
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 38bf09b53..3487f86c0 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -221,7 +221,7 @@ onMounted(async () => {
                         t('entry.list.tableVisibleColumns.isExcludedFromAvailable')
                     }}</QTooltip>
                 </QIcon>
-                <QIcon v-if="!!row.daysInForward" name="vn:net" color="primary">
+                <QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
                     <QTooltip>
                         {{
                             t('globals.raid', { daysInForward: row.daysInForward })
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index c3a13907a..faf408989 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -21,12 +21,7 @@ const agenciesOptions = ref([]);
         @on-fetch="(data) => (agenciesOptions = data)"
         auto-load
     />
-    <FormModel
-        :url="`Travels/${route.params.id}`"
-        :url-update="`Travels/${route.params.id}`"
-        model="Travel"
-        auto-load
-    >
+    <FormModel :url-update="`Travels/${route.params.id}`" model="Travel" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.ref" :label="t('globals.reference')" />
@@ -78,6 +73,7 @@ const agenciesOptions = ref([]);
                 </VnInput>
             </VnRow>
             <VnRow>
+                <QCheckbox v-model="data.isRaid" :label="t('travel.basicData.isRaid')" />
                 <QCheckbox
                     :label="t('travel.summary.delivered')"
                     v-model="data.isDelivered"
@@ -93,7 +89,7 @@ const agenciesOptions = ref([]);
 
 <i18n>
 es:
-    raidDays: Al rellenarlo, generamos una redada. Indica los días que un travel se moverá automáticamente en el tiempo
+    raidDays: Si se marca "Redada", la fecha de entrega se moverá automáticamente los días indicados (incluido 0). Si se deja vacio, la fecha no cambiará
 en:
-    raidDays: When filling, a raid is generated. Enter the number of days the travel will automatically forward in time
+    raidDays: If "Raid" is checked, the landing date will automatically shift by the specified number of days (including 0). If left empty, the date will stay the same.
 </i18n>
diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue
index 44bd9d430..50cecef34 100644
--- a/src/pages/Travel/Card/TravelCard.vue
+++ b/src/pages/Travel/Card/TravelCard.vue
@@ -1,34 +1,7 @@
 <script setup>
 import VnCard from 'components/common/VnCard.vue';
 import TravelDescriptor from './TravelDescriptor.vue';
-
-const filter = {
-    fields: [
-        'id',
-        'ref',
-        'shipped',
-        'landed',
-        'totalEntries',
-        'warehouseInFk',
-        'warehouseOutFk',
-        'cargoSupplierFk',
-        'agencyModeFk',
-    ],
-    include: [
-        {
-            relation: 'warehouseIn',
-            scope: {
-                fields: ['name'],
-            },
-        },
-        {
-            relation: 'warehouseOut',
-            scope: {
-                fields: ['name'],
-            },
-        },
-    ],
-};
+import filter from './TravelFilter.js';
 </script>
 <template>
     <VnCard
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index 295b47fa0..9d00d371a 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -7,6 +7,7 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import useCardDescription from 'src/composables/useCardDescription';
 import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
+import filter from './TravelFilter.js';
 
 import { toDate } from 'src/filters';
 
@@ -21,35 +22,6 @@ const $props = defineProps({
 const route = useRoute();
 const { t } = useI18n();
 
-const filter = {
-    fields: [
-        'id',
-        'ref',
-        'shipped',
-        'landed',
-        'totalEntries',
-        'warehouseInFk',
-        'warehouseOutFk',
-        'cargoSupplierFk',
-        'agencyModeFk',
-        'daysInForward',
-    ],
-    include: [
-        {
-            relation: 'warehouseIn',
-            scope: {
-                fields: ['name'],
-            },
-        },
-        {
-            relation: 'warehouseOut',
-            scope: {
-                fields: ['name'],
-            },
-        },
-    ],
-};
-
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
@@ -65,7 +37,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
         :title="data.title"
         :subtitle="data.subtitle"
         :filter="filter"
-        data-key="travelData"
+        data-key="Travel"
         @on-fetch="setData"
     >
         <template #menu="{ entity }">
@@ -80,12 +52,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
         </template>
         <template #icons="{ entity }">
             <QCardActions class="q-gutter-x-md">
-                <QIcon
-                    v-if="entity.daysInForward"
-                    name="vn:net"
-                    color="primary"
-                    size="xs"
-                >
+                <QIcon v-if="entity.isRaid" name="vn:net" color="primary" size="xs">
                     <QTooltip>
                         {{
                             t('globals.raid', { daysInForward: entity.daysInForward })
diff --git a/src/pages/Travel/Card/TravelFilter.js b/src/pages/Travel/Card/TravelFilter.js
new file mode 100644
index 000000000..f5f4520fd
--- /dev/null
+++ b/src/pages/Travel/Card/TravelFilter.js
@@ -0,0 +1,29 @@
+export default {
+    fields: [
+        'id',
+        'ref',
+        'shipped',
+        'landed',
+        'totalEntries',
+        'warehouseInFk',
+        'warehouseOutFk',
+        'cargoSupplierFk',
+        'agencyModeFk',
+        'isRaid',
+        'daysInForward',
+    ],
+    include: [
+        {
+            relation: 'warehouseIn',
+            scope: {
+                fields: ['name'],
+            },
+        },
+        {
+            relation: 'warehouseOut',
+            scope: {
+                fields: ['name'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index d720abd11..5ed7da996 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -268,6 +268,11 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                     :label="t('globals.warehouseOut')"
                     :value="travel.warehouseOut?.name"
                 />
+                <QCheckbox
+                    :label="t('travel.basicData.isRaid')"
+                    v-model="travel.isRaid"
+                    :disable="true"
+                />
                 <QCheckbox
                     :label="t('travel.summary.delivered')"
                     v-model="travel.isDelivered"
@@ -286,6 +291,10 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                     :label="t('globals.warehouseIn')"
                     :value="travel.warehouseIn?.name"
                 />
+                <VnLv
+                    :label="t('travel.basicData.daysInForward')"
+                    :value="travel?.daysInForward"
+                />
                 <QCheckbox
                     :label="t('travel.summary.received')"
                     v-model="travel.isReceived"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index ee1427cf0..852003a95 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -227,10 +227,12 @@ const columns = computed(() => [
     >
         <template #column-status="{ row }">
             <div class="row">
-                <QIcon v-if="!!row.daysInForward" name="vn:net" color="primary">
+                <QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
                     <QTooltip>
                         {{
-                            t('globals.raid', { daysInForward: row.daysInForward })
+                            t('globals.raid', {
+                                daysInForward: row.daysInForward,
+                            })
                         }}</QTooltip
                     >
                 </QIcon>

From 14d2ddfa835205c72483585e7d719b4528523dc9 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Fri, 22 Nov 2024 12:40:07 +0100
Subject: [PATCH 204/207] fix: merge errors

---
 src/components/ui/VnFilterPanel.vue         | 2 --
 src/pages/Order/Card/OrderCatalogFilter.vue | 5 -----
 2 files changed, 7 deletions(-)

diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index bf1fcfdb9..b188bde48 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -227,8 +227,6 @@ function sanitizer(params) {
     }
     return params;
 }
-
-defineExpose({ search, sanitizer, userParams });
 </script>
 
 <template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index b839be55e..6202a6f90 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -143,11 +143,6 @@ function addOrder(value, field, params) {
     params.orderBy = JSON.stringify(orderBy);
     vnFilterPanelRef.value.search();
 }
-
-onMounted(() => {
-    selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
-    selectedTypeFk.value = getParamWhere(route, 'typeFk');
-});
 </script>
 
 <template>

From 01ffb663f1f5921f87908cdbffaa3d531a8782cf Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Fri, 22 Nov 2024 15:14:03 +0100
Subject: [PATCH 205/207] fix(ClaimList): stateCode orderBy priority

---
 src/pages/Claim/ClaimList.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue
index 6d85817dc..d561a69f7 100644
--- a/src/pages/Claim/ClaimList.vue
+++ b/src/pages/Claim/ClaimList.vue
@@ -95,6 +95,7 @@ const columns = computed(() => [
                 optionLabel: 'description',
             },
         },
+        orderBy: 'priority',
     },
     {
         align: 'right',

From 594fc60eece8c40a66cd807f63ae87d45aaaa568 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 25 Nov 2024 14:49:10 +0100
Subject: [PATCH 206/207] chore: refs #8231 add changelog

---
 CHANGELOG.md | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 186 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88abb9ae0..03812d252 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,189 @@
+# Version 24.48 - 2024-11-25
+
+### Added 🆕
+
+-   chore: correct checkNotification (fix_customer_issues) by:alexm
+-   chore: perf (warmFix_order_equalSalix) by:alexm
+-   chore: refs #6818 add spaces by:jorgep
+-   chore: refs #6818 drop useless code & comment by:jorgep
+-   chore: refs #7273 sticky add btn & refactor by:jorgep
+-   chore: refs #7524 fix test by:jorgep
+-   chore: refs #8039 not required by:alexm
+-   chore: refs #8078 fiz tests by:jorgep
+-   chore: refs #8078 rollback ref by:jorgep
+-   chore: remove console.log (warmFix_invoiceOut_Global) by:alexm
+-   chore: typo (fix_itemType-redirection) by:alexm
+-   feat: #6943 use openURL quasar by:Javier Segarra
+-   feat: #7782 add cypress report by:Javier Segarra
+-   feat: #7782 cypress.config watchForFileChanges by:Javier Segarra
+-   feat: #7782 npm run resetDatabase by:Javier Segarra
+-   feat: #7782 waitUntil domContentLoad by:Javier Segarra
+-   feat: added composable to confirm orders by:Jon
+-   feat: add /reports in gitignore (warmFix_reports_in_gitignore) by:alexm
+-   feat: apply changes for customerModule by:Javier Segarra
+-   feat: disabled buttons by:Javier Segarra
+-   feat: move buttons to DescriptorMenu by:Javier Segarra
+-   feat: refs #6818 add icon by:jorgep
+-   feat: refs #6818 fetch url & default channel by:jorgep
+-   feat: refs #6818 saysimple integration by:jorgep
+-   feat: refs #6839 module searching (6839-addSearchMenu) by:jorgep
+-   feat: refs #6839 normalize search by:jorgep
+-   feat: refs #6919 sync entry data by:jorgep
+-   feat: refs #7006 itemType basic data new inputs by:guillermo
+-   feat: refs #7006 itemTypeLog added by:guillermo
+-   feat: refs #7193 modified parking to use the scope and corrected small errors by:Jon
+-   feat: refs #7206 added inactive label and corrected minor errors by:Jon
+-   feat: refs #7308 #7308 remove warnings related to useSession by:Javier Segarra
+-   feat: refs #7349 usa back con permisos by:jgallego
+-   feat: refs #7524 add front test by:jorgep
+-   feat: refs #7874 improve vn-notes ui by:jorgep
+-   feat: refs #7970 notify changes by:Jon
+-   feat(): refs #8039 canceledError not notify by:alexm
+-   feat: refs #8039 notify error unify by:alexm
+-   feat: refs #8039 show duplicate request in local by:alexm
+-   feat: refs #8078 add shortcut multi selection by:jorgep
+-   feat: refs #8078 add tests by:jorgep
+-   feat: refs#8087 Redadas en travel by:Carlos Andrés
+-   feat: refs #8087 Traspasar redadas a travels by:Carlos Andrés
+-   feat: remove comments by:Javier Segarra
+-   feat(Supplier): add companySize by:alexm
+-   feat: use composable to unify logic by:Javier Segarra
+-   feat(VnInput): empty to null by:alexm
+-   feat(VnSelect): order data equal salix by:alexm
+-   feat(VnSelect): refs #7136 add scroll (7136-vnSelect_paginate_simplify_2) by:alexm
+
+### Changed 📦
+
+-   chore: perf (warmFix_order_equalSalix) by:alexm
+-   chore: refs #7273 sticky add btn & refactor by:jorgep
+-   fix: better performance (warmFix_accountAcls) by:alexm
+-   perf: minor bugs detected by:Javier Segarra
+-   perf: refs #6943 #6943 merge command by:Javier Segarra
+-   perf: refs #7283 #7283 declare composable inst4ead code duplicated by:Javier Segarra
+-   perf: refs #7283 #7283 handle composable i18n by:Javier Segarra
+-   perf: refs #7283 #7283 handle i18n by:Javier Segarra
+-   perf: refs #7283 #7283 i18n params by:Javier Segarra
+-   perf: refs #7308 #7308 remove comments by:Javier Segarra
+-   perf: remove appendParams by:Javier Segarra
+-   perf: use const in VnLocation by:Javier Segarra
+-   perf: use required instead :required="true" by:Javier Segarra
+-   refactor: apply QPopupProxy by:wbuezas
+-   refactor: changed confirmOrder directory by:Jon
+-   refactor: change keyup.enter for update:model-value by:wbuezas
+-   refactor(InvoiceInBasicData): use VnDms by:alexm
+-   refactor: modified composable by:Jon
+-   refactor: refs #6818 change channel source by:jorgep
+-   refactor: refs #6818 channel logic by:jorgep
+-   refactor: refs #6919 export filter by:jorgep
+-   refactor: refs #7132 1st wave of changes in global translations files by:Jon
+-   refactor: refs #7132 account's module translations by:Jon
+-   refactor: refs #7132 customer's module translations by:Jon
+-   refactor: refs #7132 deleted pageTitles repeated by:Jon
+-   refactor: refs #7132 delete duplicate translations' keys by:Jon
+-   refactor: refs #7132 deleted useless code by:Jon
+-   refactor: refs #7132 global translations files changed by:Jon
+-   refactor: refs #7266 Changed method name by:guillermo
+-   refactor: refs #7950 Created cmr model by:guillermo
+-   refactor: refs #7970 added emit by:Jon
+-   refactor: refs #7970 refactored VnConfirm to emit events by:Jon
+-   refactor: refs #8185 modified LeftMenu to avoid duplicates by:Jon
+-   refactor: remove unused variable by:wbuezas
+-   refactor: revert catalog changes by:Jon
+-   refactor: small change by:wbuezas
+-   test: refactor e2e by:alexm
+-   test: refs #8039 add hasNotify and, refactor: agencyWorkCenter test by:alexm
+
+### Fixed 🛠️
+
+-   chore: refs #7524 fix test by:jorgep
+-   fix: better performance (warmFix_accountAcls) by:alexm
+-   fix: catalog view category and type filter by:wbuezas
+-   fix: category and tags filters by:Jon
+-   fix: changed route.query by:Jon
+-   fix: change type vnput by:Javier Segarra
+-   fix(ClaimList): stateCode orderBy priority by:alexm
+-   fix: entryFilters by:carlossa
+-   fix: filter panel by:Jon
+-   fix(InvoiceOutGlobal): parallelism by:alexm
+-   fix: itemBotanical by:Javier Segarra
+-   fix: itemType redirection and fix filters by:alexm
+-   fix: logout spec (warmFix_logout.spec) by:alexm
+-   fix: merge errors by:alexm
+-   fix: order catalog by:wbuezas
+-   fix: order catalog fixes by:wbuezas
+-   fix: refs #6818 use right icon by:jorgep
+-   fix: refs #6896 fixed module problems by:Jon
+-   fix: refs #7193 fixed e2e test by:Jon
+-   fix: refs #7206 deleted duplicate code by:Jon
+-   fix: refs #7273 use same filter by:jorgep
+-   fix: refs #7283 #7283 bugs by:Javier Segarra
+-   fix: refs #7283 #7283 ItemDiary subToolbar by:Javier Segarra
+-   fix: refs #7283 #7283 ItemSummary bugs by:Javier Segarra
+-   fix: refs #7283 Account image resolution by:guillermo
+-   fix: refs #7283 css by:jorgep
+-   fix: refs #7283 filter by:carlossa
+-   fix: refs #7283 fix image by:carlossa
+-   fix: refs #7283 fix pr by:carlossa
+-   fix: refs #7283 fix preview by:carlossa
+-   fix: refs #7283 fix required by:carlossa
+-   fix: refs #7283 item filters by:carlossa
+-   fix: refs #7283 itemtype fix by:carlossa
+-   fix: refs #7283 order translation by:carlossa
+-   fix: refs #7283 preview by:carlossa
+-   fix: refs #7283 tooltips !Item by:Javier Segarra
+-   fix: refs #7306 clean warning by:carlossa
+-   fix: refs #7310 clean warning by:carlossa
+-   fix: refs #7323 locale #7396 by:jorgep
+-   fix: refs #7323 show advanced fields by:jorgep
+-   fix: refs #7349 dependencia no usada by:jgallego
+-   fix: refs #7524 e2e & worker module by:jorgep
+-   fix: refs #7874 add title by:jorgep
+-   fix: refs #7874 show name by:jorgep
+-   fix: refs #7943 use correct data-key by:jorgep
+-   fix: refs #7943 use summary by:jorgep
+-   fix: refs #8039 bad tests by:alexm
+-   fix: refs #8039 o not handle unnecessary errors by:alexm
+-   fix: refs #8078 e2e #7970 by:jorgep
+-   fix: refs #8078 handleSelection by:jorgep
+-   fix: refs #8078 improve cy command (8078-enableMultiSelection) by:jorgep
+-   fix: refs #8078 improve handleSelection by:jorgep
+-   fix: reset category by:wbuezas
+-   fix: tag chips by:Jon
+-   fix: vnSearchbar spec (warmFix_vnSearchBar.spec) by:alexm
+-   fix(VnSelect): setOptions when applyFilter by:alexm
+-   fix: worker test e2e by:Jon
+-   Merge branch 'dev' into fix_customer_issues by:Javier Segarra
+-   refactor: revert catalog changes by:Jon
+-   refs #7283 fix conflicts by:carlossa
+-   refs #7283 fix descriptorproxy by:carlossa
+-   refs #7283 fixedPrice by:carlossa
+-   refs #7283 fixedPrices by:carlossa
+-   refs #7283 fix itemFixed by:carlossa
+-   refs #7283 fix itemFixedPrice by:carlossa
+-   refs #7283 fix itemMigration by:carlossa
+-   refs #7283 fix itemMigration list filters by:carlossa
+-   refs #7283 fix items by:carlossa
+-   refs #7283 fix items error get images by:carlossa
+-   refs #7283 fix items images by:carlossa
+-   refs #7283 fix request by:carlossa
+-   refs #7283 fix searchbar by:carlossa
+-   refs #7283 fix viewSummary by:carlossa
+-   refs #7283 fix yml list basicData by:carlossa
+-   refs #7283 itemRequest fix by:carlossa
+-   refs #7283 itemRequest fix deny by:carlossa
+-   refs #7283 itemRequest fix reload by:carlossa
+-   refs #72983 fix filters by:carlossa
+-   revert: commit by:Javier Segarra
+-   revert e57a253c6f649382da187d1129449d265fb26d3b by:Javier Segarra
+-   test: #8162 fix clientList spec by:Javier Segarra
+-   test: #8162 fix vnLocation spec by:Javier Segarra
+-   test: fix arrayData by:Javier Segarra
+-   test: fix e2e by:alexm
+-   test: fix e2e by:Javier Segarra
+-   test: refs #8039 fix WorkerNotification e2e by:alexm
+-   test: refs #8039 fix ZoneWarehouse e2e by:alexm
+-   warmfix: ItemLastEntries to date (origin/warmfix_itemLastEntriesFilter) by:Javier Segarra
+
 # Version 24.40 - 2024-10-02
 
 ### Added 🆕

From 2ead484026c2ed48fea357c742ca9dcbe745983c Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 25 Nov 2024 14:59:26 +0100
Subject: [PATCH 207/207] test: refs #8231 fix VnLocation

---
 test/cypress/integration/vnComponent/vnLocation.spec.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index aeb938c6f..06c23f4ee 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -103,12 +103,12 @@ describe('VnLocation', () => {
             const province = 'Valencia';
             cy.get(createLocationButton).click();
             cy.get('.q-card > h1').should('have.text', 'New postcode');
-            cy.get(dialogInputs).eq(0).clear();
-            cy.get(dialogInputs).eq(0).type(postCode);
             cy.selectOption(
                 `${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix}`,
                 province
             );
+            cy.get(dialogInputs).eq(0).clear();
+            cy.get(dialogInputs).eq(0).type(postCode);
             cy.get('.q-mt-lg > .q-btn--standard').click();
             cy.get(`${createForm.prefix}`).should('not.exist');
             cy.waitForElement('.q-form');