From 0b15c284494f6bf8e24fc6207b162a701c385495 Mon Sep 17 00:00:00 2001
From: jtubau <jtubau@verdnatura.es>
Date: Fri, 27 Dec 2024 14:09:27 +0100
Subject: [PATCH 01/21] refactor: refs #8316 used VnSection and VnCardBeta

---
 src/pages/Order/Card/OrderCard.vue |  32 +----
 src/pages/Order/OrderList.vue      | 224 +++++++++++++++--------------
 src/pages/Order/locale/en.yml      |   3 +
 src/pages/Order/locale/es.yml      |   3 +
 src/router/modules/order.js        | 148 ++++++++++---------
 5 files changed, 207 insertions(+), 203 deletions(-)

diff --git a/src/pages/Order/Card/OrderCard.vue b/src/pages/Order/Card/OrderCard.vue
index 67c0f1de510..823815f59b9 100644
--- a/src/pages/Order/Card/OrderCard.vue
+++ b/src/pages/Order/Card/OrderCard.vue
@@ -1,38 +1,12 @@
 <script setup>
-import { computed } from 'vue';
-import { useRoute } from 'vue-router';
-import VnCard from 'components/common/VnCard.vue';
+import VnCardBeta from 'components/common/VnCardBeta.vue';
 import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
-import OrderFilter from './OrderFilter.vue';
-import OrderSearchbar from './OrderSearchbar.vue';
-import OrderCatalogFilter from './OrderCatalogFilter.vue';
-const config = {
-    OrderCatalog: OrderCatalogFilter,
-};
-const route = useRoute();
-
-const routeName = computed(() => route.name);
-const customRouteRedirectName = computed(() => {
-    const route = config[routeName.value];
-    if (route) return null;
-    return 'OrderList';
-});
-const customFilterPanel = computed(() => {
-    const filterPanel = config[routeName.value] ?? OrderFilter;
-    return filterPanel;
-});
 </script>
 
 <template>
-    <VnCard
+    <VnCardBeta
         data-key="Order"
         base-url="Orders"
         :descriptor="OrderDescriptor"
-        :filter-panel="customFilterPanel"
-        :search-data-key="customRouteRedirectName"
-    >
-        <template #searchbar>
-            <OrderSearchbar />
-        </template>
-    </VnCard>
+    />
 </template>
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index baa20354152..6ce3c91a443 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -8,15 +8,14 @@ import { useRoute } from 'vue-router';
 
 import axios from 'axios';
 import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
-import OrderSearchbar from './Card/OrderSearchbar.vue';
 import OrderFilter from './Card/OrderFilter.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
 import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
 import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
 
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import VnSection from 'src/components/common/VnSection.vue';
 
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
@@ -24,6 +23,8 @@ const tableRef = ref();
 const agencyList = ref([]);
 const route = useRoute();
 const addressOptions = ref([]);
+const dataKey='OrderList';
+
 const columns = computed(() => [
     {
         align: 'left',
@@ -178,117 +179,126 @@ const getDateColor = (date) => {
     if (difference < 0) return 'bg-success';
 };
 </script>
+
 <template>
-    <OrderSearchbar />
-    <RightMenu>
+    <VnSection
+        :data-key="dataKey"
+        :columns="columns"
+        prefix="order"
+        :array-data-props="{
+            url: 'Orders/filter',
+            order: ['landed DESC', 'clientFk ASC', 'id DESC'],
+            exprBuilder,
+        }"
+    >
         <template #right-panel>
             <OrderFilter data-key="OrderList" />
         </template>
-    </RightMenu>
-    <VnTable
-        ref="tableRef"
-        data-key="OrderList"
-        url="Orders/filter"
-        :order="['landed DESC', 'clientFk ASC', 'id DESC']"
-        :create="{
-            urlCreate: 'Orders/new',
-            title: t('module.cerateOrder'),
-            onDataSaved: (url) => {
-                tableRef.redirect(`${url}/catalog`);
-            },
-            formInitialData: {
-                active: true,
-                addressId: null,
-                clientFk: null,
-            },
-        }"
-        :user-params="{ showEmpty: false }"
-        :columns="columns"
-        :right-search="false"
-        redirect="order"
-    >
-        <template #column-clientFk="{ row }">
-            <span class="link" @click.stop>
-                {{ row?.clientName }}
-                <CustomerDescriptorProxy :id="row?.clientFk" />
-            </span>
-        </template>
-        <template #column-salesPersonFk="{ row }">
-            <span class="link" @click.stop>
-                {{ row?.name }}
-                <WorkerDescriptorProxy :id="row?.salesPersonFk" />
-            </span>
-        </template>
-        <template #column-landed="{ row }">
-            <span v-if="getDateColor(row.landed)">
-                <QChip :class="getDateColor(row.landed)" dense square>
-                    {{ toDate(row?.landed) }}
-                </QChip>
-            </span>
-        </template>
-        <template #more-create-dialog="{ data }">
-            <VnSelect
-                url="Clients"
-                :include="{ relation: 'addresses' }"
-                v-model="data.clientFk"
-                :label="t('module.customer')"
-                @update:model-value="(id) => fetchClientAddress(id, data)"
+        <template #body>
+            <VnTable
+                ref="tableRef"
+                :data-key="dataKey"
+                :create="{
+                    urlCreate: 'Orders/new',
+                    title: t('module.cerateOrder'),
+                    onDataSaved: (url) => {
+                        tableRef.redirect(`${url}/catalog`);
+                    },
+                    formInitialData: {
+                        active: true,
+                        addressId: null,
+                        clientFk: null,
+                    },
+                }"
+                :user-params="{ showEmpty: false }"
+                :columns="columns"
+                :right-search="false"
+                redirect="order"
             >
-                <template #option="scope">
-                    <QItem v-bind="scope.itemProps">
-                        <QItemSection>
-                            <QItemLabel>
-                                {{ scope.opt.name }}
-                            </QItemLabel>
-                            <QItemLabel caption>
-                                {{ `#${scope.opt.id}` }}
-                            </QItemLabel>
-                        </QItemSection>
-                    </QItem>
+                <template #column-clientFk="{ row }">
+                    <span class="link" @click.stop>
+                        {{ row?.clientName }}
+                        <CustomerDescriptorProxy :id="row?.clientFk" />
+                    </span>
                 </template>
-            </VnSelect>
-            <VnSelect
-                v-model="data.addressId"
-                :options="addressOptions"
-                :label="t('module.address')"
-                option-value="id"
-                option-label="nickname"
-                @update:model-value="() => fetchAgencies(data)"
-            >
-                <template #option="scope">
-                    <QItem v-bind="scope.itemProps">
-                        <QItemSection>
-                            <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 #column-salesPersonFk="{ row }">
+                    <span class="link" @click.stop>
+                        {{ row?.name }}
+                        <WorkerDescriptorProxy :id="row?.salesPersonFk" />
+                    </span>
                 </template>
-            </VnSelect>
-            <VnInputDate
-                v-model="data.landed"
-                :label="t('module.landed')"
-                @update:model-value="() => fetchAgencies(data)"
-            />
-            <VnSelect
-                v-model="data.agencyModeId"
-                :label="t('module.agency')"
-                :options="agencyList"
-                option-value="agencyModeFk"
-                option-label="agencyMode"
-            />
+                <template #column-landed="{ row }">
+                    <span v-if="getDateColor(row.landed)">
+                        <QChip :class="getDateColor(row.landed)" dense square>
+                            {{ toDate(row?.landed) }}
+                        </QChip>
+                    </span>
+                </template>
+                <template #more-create-dialog="{ data }">
+                    <VnSelect
+                        url="Clients"
+                        :include="{ relation: 'addresses' }"
+                        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="addressOptions"
+                        :label="t('module.address')"
+                        option-value="id"
+                        option-label="nickname"
+                        @update:model-value="() => fetchAgencies(data)"
+                    >
+                        <template #option="scope">
+                            <QItem v-bind="scope.itemProps">
+                                <QItemSection>
+                                    <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>
+                    </VnSelect>
+                    <VnInputDate
+                        v-model="data.landed"
+                        :label="t('module.landed')"
+                        @update:model-value="() => fetchAgencies(data)"
+                    />
+                    <VnSelect
+                        v-model="data.agencyModeId"
+                        :label="t('module.agency')"
+                        :options="agencyList"
+                        option-value="agencyModeFk"
+                        option-label="agencyMode"
+                    />
+                </template>
+            </VnTable>
         </template>
-    </VnTable>
+    </VnSection>
 </template>
diff --git a/src/pages/Order/locale/en.yml b/src/pages/Order/locale/en.yml
index 4349bc76f58..04b0f144481 100644
--- a/src/pages/Order/locale/en.yml
+++ b/src/pages/Order/locale/en.yml
@@ -21,3 +21,6 @@ lines:
     image: Image
 params:
     tagGroups: Tags
+order:
+    search: Search orders
+    searchInfo: You can search orders by ticket id
diff --git a/src/pages/Order/locale/es.yml b/src/pages/Order/locale/es.yml
index cef06cb6d97..8366f0ec4fa 100644
--- a/src/pages/Order/locale/es.yml
+++ b/src/pages/Order/locale/es.yml
@@ -21,3 +21,6 @@ lines:
     image: Imagen
 params:
     tagGroups: Tags
+order:
+    search: Buscar pedido
+    searchInfo: Buscar pedidos por el número de ticket
diff --git a/src/router/modules/order.js b/src/router/modules/order.js
index 77af812cf79..bdd080e7fee 100644
--- a/src/router/modules/order.js
+++ b/src/router/modules/order.js
@@ -1,35 +1,102 @@
 import { RouterView } from 'vue-router';
 
+const orderCard = {
+    name: 'OrderCard',
+    path: ':id',
+    component: () => import('src/pages/Order/Card/OrderCard.vue'),
+    redirect: { name: 'OrderSummary' },
+    meta: {
+        menu: [
+            'OrderBasicData',
+            'OrderCatalog',
+            'OrderVolume',
+            'OrderLines',
+        ],
+    },
+    children: [
+        {
+            path: 'summary',
+            name: 'OrderSummary',
+            meta: {
+                title: 'summary',
+                icon: 'launch',
+            },
+            component: () => import('src/pages/Order/Card/OrderSummary.vue'),
+        },
+        {
+            path: 'basic-data',
+            name: 'OrderBasicData',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+            },
+            component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
+        },
+        {
+            path: 'catalog',
+            name: 'OrderCatalog',
+            meta: {
+                title: 'catalog',
+                icon: 'vn:basket',
+            },
+            component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
+        },
+        {
+            path: 'volume',
+            name: 'OrderVolume',
+            meta: {
+                title: 'volume',
+                icon: 'vn:volume',
+            },
+            component: () => import('src/pages/Order/Card/OrderVolume.vue'),
+        },
+        {
+            path: 'line',
+            name: 'OrderLines',
+            meta: {
+                title: 'lines',
+                icon: 'vn:lines',
+            },
+            component: () => import('src/pages/Order/Card/OrderLines.vue'),
+        },
+    ],
+};
+
 export default {
-    path: '/order',
     name: 'Order',
+    path: '/order',
     meta: {
         title: 'order',
         icon: 'vn:basket',
         moduleName: 'Order',
         keyBinding: 'o',
+        menu: ['OrderList'],
     },
     component: RouterView,
     redirect: { name: 'OrderMain' },
-    menus: {
-        main: ['OrderList'],
-        card: ['OrderBasicData', 'OrderCatalog', 'OrderVolume', 'OrderLines'],
-    },
     children: [
         {
-            path: '',
             name: 'OrderMain',
+            path: '',
             component: () => import('src/components/common/VnModule.vue'),
-            redirect: { name: 'OrderList' },
+            redirect: { name: 'OrderIndexMain' },
             children: [
                 {
-                    path: 'list',
-                    name: 'OrderList',
-                    meta: {
-                        title: 'orderList',
-                        icon: 'view_list',
-                    },
+                    path: '',
+                    name: 'OrderIndexMain',            
+                    redirect: { name: 'OrderList' },
                     component: () => import('src/pages/Order/OrderList.vue'),
+                    children: [
+                        {
+                            name: 'OrderList',
+                            path: 'list',
+                            meta: {
+                                title: 'orderList',
+                                icon: 'view_list',
+                            },
+                        },
+                        orderCard,
+                    ],
                 },
                 {
                     path: 'create',
@@ -42,58 +109,5 @@ export default {
                 },
             ],
         },
-        {
-            name: 'OrderCard',
-            path: ':id',
-            component: () => import('src/pages/Order/Card/OrderCard.vue'),
-            redirect: { name: 'OrderSummary' },
-            children: [
-                {
-                    name: 'OrderSummary',
-                    path: 'summary',
-                    meta: {
-                        title: 'summary',
-                        icon: 'launch',
-                    },
-                    component: () => import('src/pages/Order/Card/OrderSummary.vue'),
-                },
-                {
-                    name: 'OrderBasicData',
-                    path: 'basic-data',
-                    meta: {
-                        title: 'basicData',
-                        icon: 'vn:settings',
-                    },
-                    component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
-                },
-                {
-                    name: 'OrderCatalog',
-                    path: 'catalog',
-                    meta: {
-                        title: 'catalog',
-                        icon: 'vn:basket',
-                    },
-                    component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
-                },
-                {
-                    name: 'OrderVolume',
-                    path: 'volume',
-                    meta: {
-                        title: 'volume',
-                        icon: 'vn:volume',
-                    },
-                    component: () => import('src/pages/Order/Card/OrderVolume.vue'),
-                },
-                {
-                    name: 'OrderLines',
-                    path: 'line',
-                    meta: {
-                        title: 'lines',
-                        icon: 'vn:lines',
-                    },
-                    component: () => import('src/pages/Order/Card/OrderLines.vue'),
-                },
-            ],
-        },
     ],
-};
+};
\ No newline at end of file

From 5259b8200bce900b89cde248cab96c690fc7974c Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Thu, 2 Jan 2025 09:57:56 +0100
Subject: [PATCH 02/21] fix: refs #8247 fixed acls and added lost options

---
 src/i18n/locale/en.yml                        |  1 +
 src/i18n/locale/es.yml                        |  1 +
 .../Account/Card/AccountDescriptorMenu.vue    | 99 ++++++++++++++++---
 src/pages/Item/locale/en.yml                  |  1 +
 src/pages/Item/locale/es.yml                  |  1 +
 5 files changed, 92 insertions(+), 11 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 4a78811e69b..a0a678e6ecf 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -346,6 +346,7 @@ globals:
         countryFk: Country
         companyFk: Company
     changePass: Change password
+    setPass: Set password
     deleteConfirmTitle: Delete selected elements
     changeState: Change state
     raid: 'Raid {daysInForward} days'
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 2bfe7ec4beb..e448ead83dc 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -348,6 +348,7 @@ globals:
         countryFk: País
         companyFk: Empresa
     changePass: Cambiar contraseña
+    setPass: Establecer contraseña
     deleteConfirmTitle: Eliminar los elementos seleccionados
     changeState: Cambiar estado
     raid: 'Redada {daysInForward} días'
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 1780b424710..9bb6a7c520e 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -6,9 +6,11 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 import { useRoute } from 'vue-router';
 import { useAcl } from 'src/composables/useAcl';
 import { useArrayData } from 'src/composables/useArrayData';
+import { useState } from 'src/composables/useState';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import VnChangePassword from 'src/components/common/VnChangePassword.vue';
 import { useQuasar } from 'quasar';
+import { useRouter } from 'vue-router';
 
 const $props = defineProps({
     hasAccount: {
@@ -21,11 +23,13 @@ const { t } = useI18n();
 const { hasAccount } = toRefs($props);
 const { openConfirmationModal } = useVnConfirm();
 const route = useRoute();
+const router = useRouter();
+const state = useState();
+const user = state.getUser();
 const { notify } = useQuasar();
 const account = computed(() => useArrayData('AccountId').store.data[0]);
 account.value.hasAccount = hasAccount.value;
 const entityId = computed(() => +route.params.id);
-
 async function updateStatusAccount(active) {
     if (active) {
         await axios.post(`Accounts`, { id: entityId.value });
@@ -36,7 +40,7 @@ async function updateStatusAccount(active) {
     account.value.hasAccount = active;
     const status = active ? 'enable' : 'disable';
     notify({
-        message: t(`account.card.${status}Account.success`),
+        message: t(`account.card.actions.${status}Account.success`),
         type: 'positive',
     });
 }
@@ -49,6 +53,17 @@ async function updateStatusUser(active) {
         type: 'positive',
     });
 }
+
+async function deleteAccount() {
+    const { data } = await axios.delete(`VnUsers/${entityId.value}`);
+    if (data) {
+        notify({
+            message: t('account.card.actions.delete.success'),
+            type: 'positive',
+        });
+        router.push({ name: 'AccountList' });
+    }
+}
 const showSyncDialog = ref(false);
 const syncPassword = ref(null);
 const shouldSyncPassword = ref(false);
@@ -63,11 +78,18 @@ async function sync() {
         type: 'positive',
     });
 }
+const askOldPass = ref(false);
+const changePassRef = ref();
+
+const onChangePass = (oldPass) => {
+    askOldPass.value = oldPass;
+    changePassRef.value.show();
+};
 </script>
 <template>
     <VnChangePassword
         ref="changePassRef"
-        :ask-old-pass="true"
+        :ask-old-pass="askOldPass"
         :submit-fn="
             async (newPassword, oldPassword) => {
                 await axios.patch(`Accounts/change-password`, {
@@ -110,17 +132,57 @@ async function sync() {
     </VnConfirm>
     <QItem
         v-if="
-            entityId == account.id &&
-            useAcl().hasAny([{ model: 'Account', props: '*', accessType: 'WRITE' }])
+            useAcl().hasAny([
+                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
+            ])
         "
         v-ripple
         clickable
-        @click="$refs.changePassRef.show()"
+        @click="
+            openConfirmationModal(
+                t('account.card.actions.disableAccount.title'),
+                t('account.card.actions.disableAccount.subtitle'),
+                () => deleteAccount()
+            )
+        "
     >
-        <QItemSection>{{ t('globals.changePass') }}</QItemSection>
+        <QItemSection>{{ t('globals.delete') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="account.hasAccount"
+        v-if="
+            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
+        "
+        v-ripple
+        clickable
+        @click="user.id === account.id ? onChangePass(true) : onChangePass(false)"
+    >
+        <QItemSection v-if="user.id === account.id">
+            {{ t('globals.changePass') }}
+        </QItemSection>
+        <QItemSection v-else>{{ t('globals.setPass') }}</QItemSection>
+    </QItem>
+    <QItem
+        v-if="
+            !account.hasAccount &&
+            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
+        "
+        v-ripple
+        clickable
+        @click="
+            openConfirmationModal(
+                t('account.card.actions.enableAccount.title'),
+                t('account.card.actions.enableAccount.subtitle'),
+                () => updateStatusAccount(true)
+            )
+        "
+    >
+        <QItemSection>{{ t('account.card.actions.enableAccount.name') }}</QItemSection>
+    </QItem>
+    <QItem
+        v-if="
+            account.hasAccount &&
+            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
+        "
         v-ripple
         clickable
         @click="
@@ -135,7 +197,12 @@ async function sync() {
     </QItem>
 
     <QItem
-        v-if="!account.active"
+        v-if="
+            !account.active &&
+            useAcl().hasAny([
+                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
+            ])
+        "
         v-ripple
         clickable
         @click="
@@ -149,7 +216,12 @@ async function sync() {
         <QItemSection>{{ t('account.card.actions.activateUser.name') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="account.active"
+        v-if="
+            account.active &&
+            useAcl().hasAny([
+                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
+            ])
+        "
         v-ripple
         clickable
         @click="
@@ -162,7 +234,12 @@ async function sync() {
     >
         <QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection>
     </QItem>
-    <QItem v-ripple clickable @click="showSyncDialog = true">
+    <QItem
+        v-if="useAcl().hasAny([{ model: 'VnRole', props: '*', accessType: 'WRITE' }])"
+        v-ripple
+        clickable
+        @click="showSyncDialog = true"
+    >
         <QItemSection>{{ t('account.card.actions.sync.name') }}</QItemSection>
     </QItem>
     <QSeparator />
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index ac5010a1237..aa2e5484225 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -58,6 +58,7 @@ lastEntries:
     pvp: PVP
     label: Label
     grouping: Grouping
+    packing: Packing
     quantity: Quantity
     cost: Cost
     kg: Kg.
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index 96c8cbc9a60..33bee1ae162 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -58,6 +58,7 @@ lastEntries:
     pvp: PVP
     label: Eti.
     grouping: Grouping
+    packing: Packing
     quantity: Cantidad
     cost: Coste
     kg: Kg.

From df1b1205cf4c369c8c38153f8e442f02b71df190 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Thu, 2 Jan 2025 12:16:05 +0100
Subject: [PATCH 03/21] feat: refs #7077 created test for VnInputTime

---
 .../common/__tests__/VnInputTime.spec.js      | 63 +++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 src/components/common/__tests__/VnInputTime.spec.js

diff --git a/src/components/common/__tests__/VnInputTime.spec.js b/src/components/common/__tests__/VnInputTime.spec.js
new file mode 100644
index 00000000000..1ecc01cc398
--- /dev/null
+++ b/src/components/common/__tests__/VnInputTime.spec.js
@@ -0,0 +1,63 @@
+import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+import VnInputTime from 'components/common/VnInputTime.vue';
+
+describe('VnInputTime', () => {
+    let wrapper;
+    let vm;
+
+    beforeAll(() => {
+        wrapper = createWrapper(VnInputTime, {
+            props: {
+                isOutlined: true,
+                timeOnly: false, // Initial props values
+            },
+        });
+        vm = wrapper.vm;
+        wrapper = wrapper.wrapper;
+    });
+
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
+
+    it('should return the correct data if isOutlined is true', () => {
+        expect(vm.isOutlined).toBe(true);
+        expect(vm.styleAttrs).toEqual({ dense: true, outlined: true, rounded: true });
+    });
+
+    it('should return the formatted data', () => {
+        expect(vm.dateToTime('2022-01-01T03:23:43')).toBe('03:23');
+    });
+
+    describe('formattedTime', () => {
+        it('should return the formatted time for a valid ISO date', () => {
+            vm.model = '2025-01-02T15:45:00';
+            expect(vm.formattedTime).toBe('15:45');
+        });
+
+        it('should handle null model value gracefully', () => {
+            vm.model = null;
+            expect(vm.formattedTime).toBe(null);
+        });
+
+        it('should handle time-only input correctly', async () => {
+            await wrapper.setProps({ timeOnly: true });
+            vm.formattedTime = '14:30';
+            expect(vm.model).toBe('14:30');
+        });
+
+        it('should pad short time values correctly', async () => {
+            await wrapper.setProps({ timeOnly: true });
+            vm.formattedTime = '9';
+            expect(vm.model).toBe('09:00');
+        });
+
+        it('should not update the model if the value is unchanged', () => {
+            vm.model = '14:30';
+            const previousModel = vm.model;
+            vm.formattedTime = '14:30';
+            expect(vm.model).toBe(previousModel);
+        });
+    });
+});
\ No newline at end of file

From 2e3e7c6a5d945ce9f8d064b1aed61cf0b3553d7b Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Fri, 3 Jan 2025 09:44:00 +0100
Subject: [PATCH 04/21] fix: refs #8316 use rightMenu

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

diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 6ce3c91a443..ae1fe68bd47 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -23,7 +23,7 @@ const tableRef = ref();
 const agencyList = ref([]);
 const route = useRoute();
 const addressOptions = ref([]);
-const dataKey='OrderList';
+const dataKey = 'OrderList';
 
 const columns = computed(() => [
     {
@@ -188,10 +188,9 @@ const getDateColor = (date) => {
         :array-data-props="{
             url: 'Orders/filter',
             order: ['landed DESC', 'clientFk ASC', 'id DESC'],
-            exprBuilder,
         }"
     >
-        <template #right-panel>
+        <template #rightMenu>
             <OrderFilter data-key="OrderList" />
         </template>
         <template #body>
@@ -278,7 +277,8 @@ const getDateColor = (date) => {
                                                     : ''
                                             } `
                                         }}
-                                        {{ scope.opt?.nickname }}: {{ scope.opt?.street }},
+                                        {{ scope.opt?.nickname }}:
+                                        {{ scope.opt?.street }},
                                         {{ scope.opt?.city }}
                                     </QItemLabel>
                                 </QItemSection>

From bb6fae5d087575a84418549cc75ed22ca8e01a23 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Fri, 10 Jan 2025 14:08:25 +0100
Subject: [PATCH 05/21] feat: refs #7087 created CardSummary test

---
 .../ui/__tests__/CardSummary.spec.js          | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 src/components/ui/__tests__/CardSummary.spec.js

diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
new file mode 100644
index 00000000000..4a32e92e59a
--- /dev/null
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -0,0 +1,48 @@
+import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
+import { createWrapper, axios } from 'app/test/vitest/helper';
+import CardSummary from 'src/components/ui/CardSummary.vue';
+
+describe('CardSummary', () => {
+    let vm;
+    let wrapper;
+    
+    beforeAll(() => {
+        const mockApiResponse = {
+            data: {
+                data: [], 
+                total: 0,
+            }
+        };
+
+        vi.spyOn(axios, 'get').mockResolvedValue(mockApiResponse);
+
+        wrapper = createWrapper(CardSummary, {
+            global: {
+                stubs: [
+                    'arrayData',
+                    'useArrayData',
+                ],
+                mocks: {
+                    validate: vi.fn(),
+                },
+            },
+            propsData: {
+                dataKey: 'cardSummaryKey',
+                url: 'cardSummaryUrl',
+            },
+        });
+        
+        vm = wrapper.vm;
+        wrapper = wrapper.wrapper;
+
+    });
+        
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
+
+    it('should fetch data', async () => {
+        expect(wrapper.emitted('fetch'));
+    });
+    
+});
\ No newline at end of file

From 1295f394f393a6a842f39f94fd0adc034f66b603 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Mon, 13 Jan 2025 08:11:41 +0100
Subject: [PATCH 06/21] feat: refs #7087 added more test cases

---
 .../ui/__tests__/CardSummary.spec.js          | 65 ++++++++++++-------
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index 4a32e92e59a..7a979c2ea6d 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -1,48 +1,63 @@
-import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
+import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import CardSummary from 'src/components/ui/CardSummary.vue';
 
 describe('CardSummary', () => {
     let vm;
     let wrapper;
-    
+
     beforeAll(() => {
-        const mockApiResponse = {
-            data: {
-                data: [], 
-                total: 0,
-            }
-        };
-
-        vi.spyOn(axios, 'get').mockResolvedValue(mockApiResponse);
+        vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
+    });
 
+    beforeEach(() => {
         wrapper = createWrapper(CardSummary, {
-            global: {
-                stubs: [
-                    'arrayData',
-                    'useArrayData',
-                ],
-                mocks: {
-                    validate: vi.fn(),
-                },
-            },
             propsData: {
                 dataKey: 'cardSummaryKey',
                 url: 'cardSummaryUrl',
+                filter: 'cardFilter',
             },
         });
-        
         vm = wrapper.vm;
         wrapper = wrapper.wrapper;
-
     });
-        
+
     afterEach(() => {
         vi.clearAllMocks();
     });
 
-    it('should fetch data', async () => {
-        expect(wrapper.emitted('fetch'));
+    it('should fetch data correctly', async () => {
+        const fetchSpy = vi
+            .spyOn(vm.arrayData, 'fetch')
+            .mockResolvedValue({ data: [{ id: 1, name: 'Test Entity' }] });
+        await vm.fetch();
+
+        expect(fetchSpy).toHaveBeenCalledWith({ append: false, updateRouter: false });
+        expect(wrapper.emitted('onFetch')).toBeTruthy();
+        expect(vm.isLoading).toBe(false);
+    });
+
+    it('should set correct props to the store', () => {
+        expect(vm.store.url).toEqual('cardSummaryUrl');
+        expect(vm.store.filter).toEqual('cardFilter');
+    });
+
+    it('should compute entity correctly from store data', () => {
+        vm.store.data = [{ id: 1, name: 'Entity 1' }];
+        expect(vm.entity).toEqual({ id: 1, name: 'Entity 1' });
+    });
+
+    it('should handle empty data gracefully', () => {
+        vm.store.data = [];
+        expect(vm.entity).toBeUndefined();
+    });
+
+    it('should respond to prop changes and refetch data', async () => {
+        const fetchSpy = vi.spyOn(vm.arrayData, 'fetch');
+        await wrapper.setProps({ url: 'newUrl', filter: { key: 'newValue' } });
+
+        expect(fetchSpy).toHaveBeenCalled();
+        expect(vm.store.url).toBe('newUrl');
+        expect(vm.store.filter).toEqual({ key: 'newValue' });
     });
-    
 });
\ No newline at end of file

From 1af67db6443836ba228aed19f100c20f45617c63 Mon Sep 17 00:00:00 2001
From: jtubau <jtubau@verdnatura.es>
Date: Mon, 13 Jan 2025 08:37:01 +0100
Subject: [PATCH 07/21] refactor: refs #8316 move order localization

---
 src/i18n/locale/en.yml        | 21 ---------------------
 src/i18n/locale/es.yml        | 24 ------------------------
 src/pages/Order/locale/en.yml | 20 ++++++++++++++++++++
 src/pages/Order/locale/es.yml | 23 +++++++++++++++++++++++
 4 files changed, 43 insertions(+), 45 deletions(-)

diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 4a78811e69b..0c90144ad7e 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -558,27 +558,6 @@ parking:
     searchBar:
         info: You can search by parking code
         label: Search parking...
-order:
-    field:
-        salesPersonFk: Sales Person
-    form:
-        clientFk: Client
-        addressFk: Address
-        agencyModeFk: Agency
-    list:
-        newOrder: New Order
-    summary:
-        basket: Basket
-        notConfirmed: Not confirmed
-        created: Created
-        createdFrom: Created From
-        address: Address
-        total: Total
-        items: Items
-        orderTicketList: Order Ticket List
-        amount: Amount
-        confirm: Confirm
-        confirmLines: Confirm lines
 department:
     chat: Chat
     bossDepartment: Boss Department
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 2bfe7ec4beb..3f3eebc4e45 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -544,30 +544,6 @@ invoiceOut:
         comercial: Comercial
         errors:
             downloadCsvFailed: Error al descargar CSV
-order:
-    field:
-        salesPersonFk: Comercial
-    form:
-        clientFk: Cliente
-        addressFk: Dirección
-        agencyModeFk: Agencia
-    list:
-        newOrder: Nuevo Pedido
-    summary:
-        basket: Cesta
-        notConfirmed: No confirmada
-        created: Creado
-        createdFrom: Creado desde
-        address: Dirección
-        total: Total
-        vat: IVA
-        state: Estado
-        alias: Alias
-        items: Artículos
-        orderTicketList: Tickets del pedido
-        amount: Monto
-        confirm: Confirmar
-        confirmLines: Confirmar lineas
 shelving:
     list:
         parking: Parking
diff --git a/src/pages/Order/locale/en.yml b/src/pages/Order/locale/en.yml
index 04b0f144481..14e41c55983 100644
--- a/src/pages/Order/locale/en.yml
+++ b/src/pages/Order/locale/en.yml
@@ -22,5 +22,25 @@ lines:
 params:
     tagGroups: Tags
 order:
+    field:
+        salesPersonFk: Sales Person
+    form:
+        clientFk: Client
+        addressFk: Address
+        agencyModeFk: Agency
+    list:
+        newOrder: New Order
+    summary:
+        basket: Basket
+        notConfirmed: Not confirmed
+        created: Created
+        createdFrom: Created From
+        address: Address
+        total: Total
+        items: Items
+        orderTicketList: Order Ticket List
+        amount: Amount
+        confirm: Confirm
+        confirmLines: Confirm lines
     search: Search orders
     searchInfo: You can search orders by ticket id
diff --git a/src/pages/Order/locale/es.yml b/src/pages/Order/locale/es.yml
index 8366f0ec4fa..44e243ad117 100644
--- a/src/pages/Order/locale/es.yml
+++ b/src/pages/Order/locale/es.yml
@@ -22,5 +22,28 @@ lines:
 params:
     tagGroups: Tags
 order:
+    field:
+        salesPersonFk: Comercial
+    form:
+        clientFk: Cliente
+        addressFk: Dirección
+        agencyModeFk: Agencia
+    list:
+        newOrder: Nuevo Pedido
+    summary:
+        basket: Cesta
+        notConfirmed: No confirmada
+        created: Creado
+        createdFrom: Creado desde
+        address: Dirección
+        total: Total
+        vat: IVA
+        state: Estado
+        alias: Alias
+        items: Artículos
+        orderTicketList: Tickets del pedido
+        amount: Monto
+        confirm: Confirmar
+        confirmLines: Confirmar lineas
     search: Buscar pedido
     searchInfo: Buscar pedidos por el número de ticket

From ed0730df22a40abccb820313b12c7c403927cd14 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 13 Jan 2025 12:17:55 +0100
Subject: [PATCH 08/21] feat: refs #8197 useHasContent and use in VnSection and
 RightMenu

---
 src/components/common/RightMenu.vue   | 18 +++---------------
 src/components/common/VnSection.vue   |  8 ++++++--
 src/composables/useHasContent.js      | 24 ++++++++++++++++++++++++
 src/pages/Order/Card/OrderCatalog.vue | 22 ++++++++++++----------
 4 files changed, 45 insertions(+), 27 deletions(-)
 create mode 100644 src/composables/useHasContent.js

diff --git a/src/components/common/RightMenu.vue b/src/components/common/RightMenu.vue
index 32dc2874dce..9512d32d419 100644
--- a/src/components/common/RightMenu.vue
+++ b/src/components/common/RightMenu.vue
@@ -1,29 +1,17 @@
 <script setup>
-import { ref, onMounted, useSlots } from 'vue';
+import { onMounted, useSlots } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useStateStore } from 'stores/useStateStore';
 import { useQuasar } from 'quasar';
+import { useHasContent } from 'src/composables/useHasContent';
 
 const { t } = useI18n();
 const quasar = useQuasar();
 const stateStore = useStateStore();
 const slots = useSlots();
-const hasContent = ref(false);
-const rightPanel = ref(null);
+const hasContent = useHasContent('#right-panel');
 
 onMounted(() => {
-    rightPanel.value = document.querySelector('#right-panel');
-    if (!rightPanel.value) return;
-
-    const observer = new MutationObserver(() => {
-        hasContent.value = rightPanel.value.childNodes.length;
-    });
-
-    observer.observe(rightPanel.value, {
-        subtree: true,
-        childList: true,
-        attributes: true,
-    });
     if ((!slots['right-panel'] && !hasContent.value) || quasar.platform.is.mobile)
         stateStore.rightDrawer = false;
 });
diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
index edd8d3dfa98..11fd6013f57 100644
--- a/src/components/common/VnSection.vue
+++ b/src/components/common/VnSection.vue
@@ -2,9 +2,10 @@
 import RightMenu from './RightMenu.vue';
 import VnSearchbar from 'components/ui/VnSearchbar.vue';
 import VnTableFilter from '../VnTable/VnTableFilter.vue';
-import { onBeforeMount, computed } from 'vue';
+import { onBeforeMount, computed, ref } from 'vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useRoute } from 'vue-router';
+import { useHasContent } from 'src/composables/useHasContent';
 
 const $props = defineProps({
     section: {
@@ -55,6 +56,8 @@ const isMainSection = computed(() => {
     }
     return isSame;
 });
+const searchbarId = 'section-searchbar';
+const hasContent = useHasContent(`#${searchbarId}`);
 
 onBeforeMount(() => {
     if ($props.dataKey)
@@ -69,12 +72,13 @@ onBeforeMount(() => {
 <template>
     <slot name="searchbar">
         <VnSearchbar
-            v-if="searchBar"
+            v-if="searchBar && !hasContent"
             v-bind="arrayDataProps"
             :data-key="dataKey"
             :label="$t(`${prefix}.search`)"
             :info="$t(`${prefix}.searchInfo`)"
         />
+        <div :id="searchbarId"></div>
     </slot>
 
     <RightMenu>
diff --git a/src/composables/useHasContent.js b/src/composables/useHasContent.js
new file mode 100644
index 00000000000..8ab01837605
--- /dev/null
+++ b/src/composables/useHasContent.js
@@ -0,0 +1,24 @@
+import { onMounted, ref } from 'vue';
+
+export function useHasContent(selector) {
+    const container = ref({});
+    const hasContent = ref();
+
+    onMounted(() => {
+        container.value = document.querySelector(selector);
+        if (!container.value) return;
+
+        const observer = new MutationObserver(() => {
+            if (document.querySelector(selector))
+                hasContent.value = !!container.value.childNodes.length;
+        });
+
+        observer.observe(container.value, {
+            subtree: true,
+            childList: true,
+            attributes: true,
+        });
+    });
+
+    return hasContent;
+}
diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index da2e88aa990..7c454ed0f4f 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -78,16 +78,18 @@ watch(
 </script>
 
 <template>
-    <VnSearchbar
-        :data-key="dataKey"
-        :user-params="catalogParams"
-        :static-params="['orderFk', 'orderBy']"
-        :redirect="false"
-        url="Orders/CatalogFilter"
-        :label="t('Search items')"
-        :info="t('You can search items by name or id')"
-        :search-remove-params="false"
-    />
+    <Teleport to="#section-searchbar" v-if="stateStore.isHeaderMounted()">
+        <VnSearchbar
+            :data-key="dataKey"
+            :user-params="catalogParams"
+            :static-params="['orderFk', 'orderBy']"
+            :redirect="false"
+            url="Orders/CatalogFilter"
+            :label="t('Search items')"
+            :info="t('You can search items by name or id')"
+            :search-remove-params="false"
+        />
+    </Teleport>
     <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
         <OrderCatalogFilter
             :data-key="dataKey"

From dd335ef409f31546854cd6169157238c0ebce034 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 13 Jan 2025 12:18:52 +0100
Subject: [PATCH 09/21] fix: refs #8197 not use yet

---
 src/pages/Order/Card/OrderCatalog.vue | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index 7c454ed0f4f..da2e88aa990 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -78,18 +78,16 @@ watch(
 </script>
 
 <template>
-    <Teleport to="#section-searchbar" v-if="stateStore.isHeaderMounted()">
-        <VnSearchbar
-            :data-key="dataKey"
-            :user-params="catalogParams"
-            :static-params="['orderFk', 'orderBy']"
-            :redirect="false"
-            url="Orders/CatalogFilter"
-            :label="t('Search items')"
-            :info="t('You can search items by name or id')"
-            :search-remove-params="false"
-        />
-    </Teleport>
+    <VnSearchbar
+        :data-key="dataKey"
+        :user-params="catalogParams"
+        :static-params="['orderFk', 'orderBy']"
+        :redirect="false"
+        url="Orders/CatalogFilter"
+        :label="t('Search items')"
+        :info="t('You can search items by name or id')"
+        :search-remove-params="false"
+    />
     <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
         <OrderCatalogFilter
             :data-key="dataKey"

From e5d8bfcf3adf3e292fa163226412720195815022 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 14 Jan 2025 07:37:17 +0100
Subject: [PATCH 10/21] refactor: refs #8247 use new acl for sysadmin

---
 .../Account/Card/AccountDescriptorMenu.vue    | 47 +++++++------------
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 9bb6a7c520e..c1df2115652 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { computed, ref, toRefs } from 'vue';
+import { computed, onMounted, ref, toRefs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import { useRoute } from 'vue-router';
@@ -30,6 +30,8 @@ const { notify } = useQuasar();
 const account = computed(() => useArrayData('AccountId').store.data[0]);
 account.value.hasAccount = hasAccount.value;
 const entityId = computed(() => +route.params.id);
+const hasitManagementAccess = ref();
+const hasSysadminAccess = ref();
 async function updateStatusAccount(active) {
     if (active) {
         await axios.post(`Accounts`, { id: entityId.value });
@@ -85,6 +87,15 @@ const onChangePass = (oldPass) => {
     askOldPass.value = oldPass;
     changePassRef.value.show();
 };
+
+onMounted(() => {
+    hasitManagementAccess.value = useAcl().hasAny([
+        { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
+    ]);
+    hasSysadminAccess.value = useAcl().hasAny([
+        { model: 'VnUser', props: 'adminUser', accessType: 'WRITE' },
+    ]);
+});
 </script>
 <template>
     <VnChangePassword
@@ -131,11 +142,7 @@ const onChangePass = (oldPass) => {
         </template>
     </VnConfirm>
     <QItem
-        v-if="
-            useAcl().hasAny([
-                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
-            ])
-        "
+        v-if="hasitManagementAccess"
         v-ripple
         clickable
         @click="
@@ -149,9 +156,7 @@ const onChangePass = (oldPass) => {
         <QItemSection>{{ t('globals.delete') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="
-            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
-        "
+        v-if="hasSysadminAccess"
         v-ripple
         clickable
         @click="user.id === account.id ? onChangePass(true) : onChangePass(false)"
@@ -162,10 +167,7 @@ const onChangePass = (oldPass) => {
         <QItemSection v-else>{{ t('globals.setPass') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="
-            !account.hasAccount &&
-            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
-        "
+        v-if="!account.hasAccount && hasSysadminAccess"
         v-ripple
         clickable
         @click="
@@ -179,10 +181,7 @@ const onChangePass = (oldPass) => {
         <QItemSection>{{ t('account.card.actions.enableAccount.name') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="
-            account.hasAccount &&
-            useAcl().hasAny([{ model: 'AccountConfig', props: '*', accessType: 'WRITE' }])
-        "
+        v-if="account.hasAccount && hasSysadminAccess"
         v-ripple
         clickable
         @click="
@@ -197,12 +196,7 @@ const onChangePass = (oldPass) => {
     </QItem>
 
     <QItem
-        v-if="
-            !account.active &&
-            useAcl().hasAny([
-                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
-            ])
-        "
+        v-if="!account.active && hasitManagementAccess"
         v-ripple
         clickable
         @click="
@@ -216,12 +210,7 @@ const onChangePass = (oldPass) => {
         <QItemSection>{{ t('account.card.actions.activateUser.name') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="
-            account.active &&
-            useAcl().hasAny([
-                { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
-            ])
-        "
+        v-if="account.active && hasitManagementAccess"
         v-ripple
         clickable
         @click="

From 6e5b70301867d3cd78ea697574e44daabfdb3650 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 14 Jan 2025 07:47:33 +0100
Subject: [PATCH 11/21] fix: refs #8247 conflicts

---
 .../Account/Card/AccountDescriptorMenu.vue    | 30 ++++++++++---------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 151c1bf24a7..ccf029e4493 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -1,43 +1,45 @@
 <script setup>
 import axios from 'axios';
-import { computed, onMounted, onMounted, ref } from 'vue';
+import { computed, onMounted, ref, toRefs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
+import { useRoute } from 'vue-router';
 import { useAcl } from 'src/composables/useAcl';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useState } from 'src/composables/useState';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
-import VnChangePassword from 'src/components/common/VnChangePassword.vue';
-import useNotify from 'src/composables/useNotify.js';
-import useHasAccount from 'src/composables/useHasAccount.js';
 import VnInputPassword from 'src/components/common/VnInputPassword.vue';
+import VnChangePassword from 'src/components/common/VnChangePassword.vue';
+import { useQuasar } from 'quasar';
 import { useRouter } from 'vue-router';
 
 const $props = defineProps({
-    entityId: {
-        type: Number,
+    hasAccount: {
+        type: Boolean,
+        default: false,
         required: true,
     },
 });
 
 const { t } = useI18n();
+const { hasAccount } = toRefs($props);
 const { openConfirmationModal } = useVnConfirm();
+const route = useRoute();
 const router = useRouter();
 const state = useState();
 const user = state.getUser();
-const { notify } = useNotify();
+const { notify } = useQuasar();
 const account = computed(() => useArrayData('AccountId').store.data[0]);
-
-onMounted(async () => {
-    account.value.hasAccount = await useHasAccount($props.entityId);
-});
+account.value.hasAccount = hasAccount.value;
+const entityId = computed(() => +route.params.id);
 const hasitManagementAccess = ref();
 const hasSysadminAccess = ref();
+
 async function updateStatusAccount(active) {
     if (active) {
-        await axios.post(`Accounts`, { id: $props.entityId });
+        await axios.post(`Accounts`, { id: entityId.value });
     } else {
-        await axios.delete(`Accounts/${$props.entityId}`);
+        await axios.delete(`Accounts/${entityId.value}`);
     }
 
     account.value.hasAccount = active;
@@ -48,7 +50,7 @@ async function updateStatusAccount(active) {
     });
 }
 async function updateStatusUser(active) {
-    await axios.patch(`VnUsers/${$props.entityId}`, { active });
+    await axios.patch(`VnUsers/${entityId.value}`, { active });
     account.value.active = active;
     const status = active ? 'activate' : 'deactivate';
     notify({

From bd9c2ad4dc679d97c8e2744d7e269d939e2207da Mon Sep 17 00:00:00 2001
From: jtubau <jtubau@verdnatura.es>
Date: Tue, 14 Jan 2025 07:57:54 +0100
Subject: [PATCH 12/21] refactor: refs #8316 remove unused OrderSearchbar
 component

---
 src/pages/Order/Card/OrderSearchbar.vue | 22 ----------------------
 1 file changed, 22 deletions(-)
 delete mode 100644 src/pages/Order/Card/OrderSearchbar.vue

diff --git a/src/pages/Order/Card/OrderSearchbar.vue b/src/pages/Order/Card/OrderSearchbar.vue
deleted file mode 100644
index fa30a097fd2..00000000000
--- a/src/pages/Order/Card/OrderSearchbar.vue
+++ /dev/null
@@ -1,22 +0,0 @@
-<script setup>
-import { useI18n } from 'vue-i18n';
-import VnSearchbar from 'components/ui/VnSearchbar.vue';
-
-const { t } = useI18n();
-</script>
-
-<template>
-    <VnSearchbar
-        data-key="OrderList"
-        url="Orders/filter"
-        :label="t('Search order')"
-        :info="t('Search orders by ticket id')"
-    />
-</template>
-
-<style scoped lang="scss"></style>
-<i18n>
-es:
-    Search order: Buscar orden
-    Search orders by ticket id: Buscar pedido por id ticket
-</i18n>

From 8b7337f9eec26821305bf4a749340240b72f0607 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 14 Jan 2025 08:37:10 +0100
Subject: [PATCH 13/21] fix: vnlocation

---
 src/components/common/VnLocation.vue | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/components/common/VnLocation.vue b/src/components/common/VnLocation.vue
index f5822218727..3ede24274d9 100644
--- a/src/components/common/VnLocation.vue
+++ b/src/components/common/VnLocation.vue
@@ -2,7 +2,7 @@
 import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
 import VnSelectDialog from 'components/common/VnSelectDialog.vue';
 import { useI18n } from 'vue-i18n';
-import { computed } from 'vue';
+import { ref, watch } from 'vue';
 import { useAttrs } from 'vue';
 import { useRequired } from 'src/composables/useRequired';
 const { t } = useI18n();
@@ -16,6 +16,14 @@ const props = defineProps({
     },
 });
 
+watch(
+    () => props.location,
+    (newValue) => {
+        if (!modelValue.value) return;
+        modelValue.value = formatLocation(newValue) ?? null;
+    }
+);
+
 const mixinRules = [requiredFieldRule];
 const locationProperties = [
     'postcode',
@@ -43,9 +51,7 @@ const formatLocation = (obj, properties = locationProperties) => {
     return filteredParts.join(', ');
 };
 
-const modelValue = computed(() =>
-    props.location ? formatLocation(props.location, locationProperties) : null
-);
+const modelValue = ref(props.location ? formatLocation(props.location) : null);
 
 function showLabel(data) {
     const dataProperties = [

From 54867597aaec1f9a7ae3a9e7937eb6dd3f7a32d2 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Wed, 15 Jan 2025 08:52:43 +0100
Subject: [PATCH 14/21] feat: refs #7087 added new test

---
 src/components/ui/__tests__/CardSummary.spec.js | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index 7a979c2ea6d..b114797ef92 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -1,6 +1,7 @@
 import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import CardSummary from 'src/components/ui/CardSummary.vue';
+import * as vueRouter from 'vue-router';
 
 describe('CardSummary', () => {
     let vm;
@@ -10,6 +11,14 @@ describe('CardSummary', () => {
         vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
     });
 
+    vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
+        query: {},
+        params: {},
+        meta: { moduleName: 'mockName' },
+        path: 'mockName/1/summary',
+        name: 'CardSummary',
+    });
+
     beforeEach(() => {
         wrapper = createWrapper(CardSummary, {
             propsData: {
@@ -60,4 +69,8 @@ describe('CardSummary', () => {
         expect(vm.store.url).toBe('newUrl');
         expect(vm.store.filter).toEqual({ key: 'newValue' });
     });
+
+    it('should return true if route path ends with /summary' , () => {
+        expect(vm.isSummary).toBe(true);
+    });
 });
\ No newline at end of file

From 6ecbaf1a0412538a3eaa06ef269385231adecbe1 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Wed, 15 Jan 2025 08:55:16 +0100
Subject: [PATCH 15/21] Merge branch '7087-testCardSummary' of https: refs
 #7087//gitea.verdnatura.es/verdnatura/salix-front into 7087-testCardSummary

---
 src/components/RegularizeStockForm.vue        |   2 +-
 src/components/ui/CardDescriptor.vue          |  32 +-
 src/components/ui/CardSummary.vue             |  24 +-
 src/components/ui/VnMoreOptions.vue           |  20 ++
 src/composables/useHasAccount.js              |   6 +
 src/pages/Account/Card/AccountDescriptor.vue  |  25 +-
 .../Account/Card/AccountDescriptorMenu.vue    |  29 +-
 src/pages/Account/Card/AccountMailAlias.vue   |  13 +-
 .../Account/Card/AccountMailForwarding.vue    |  21 +-
 src/pages/Account/Card/AccountSummary.vue     |   5 +-
 src/pages/Claim/Card/ClaimCard.vue            |  18 +-
 src/pages/Claim/Card/ClaimSummary.vue         |   4 +
 src/pages/Claim/ClaimList.vue                 |  76 ++---
 src/pages/Claim/locale/en.yml                 |   2 +
 src/pages/Claim/locale/es.yml                 |   4 +-
 src/pages/Customer/Card/CustomerSummary.vue   |   9 +-
 .../components/CustomerAddressEdit.vue        |   8 +-
 src/pages/Entry/Card/EntryDescriptor.vue      |  16 +-
 src/pages/Entry/Card/EntryDescriptorMenu.vue  |  22 ++
 src/pages/Entry/Card/EntrySummary.vue         |   9 +-
 src/pages/Entry/EntryList.vue                 |   1 -
 src/pages/Entry/locale/en.yml                 |   1 +
 src/pages/Entry/locale/es.yml                 |   1 +
 .../InvoiceIn/Card/InvoiceInBasicData.vue     |   2 +-
 .../InvoiceIn/Card/InvoiceInDescriptor.vue    | 274 ++----------------
 .../Card/InvoiceInDescriptorMenu.vue          | 206 +++++++++++++
 src/pages/InvoiceIn/Card/InvoiceInSummary.vue |  72 ++---
 src/pages/InvoiceIn/InvoiceInCreate.vue       |   6 +-
 src/pages/InvoiceIn/InvoiceInFilter.vue       |   2 +-
 src/pages/InvoiceIn/InvoiceInList.vue         |  20 +-
 src/pages/InvoiceIn/locale/en.yml             |  24 +-
 src/pages/InvoiceIn/locale/es.yml             |  26 +-
 .../InvoiceOut/Card/InvoiceOutSummary.vue     |   4 +
 src/pages/InvoiceOut/InvoiceOutList.vue       |   2 +-
 src/pages/Item/Card/ItemDescriptor.vue        |  42 +--
 src/pages/Item/Card/ItemDescriptorImage.vue   |   1 -
 src/pages/Item/Card/ItemDescriptorMenu.vue    |  44 +++
 src/pages/Item/Card/ItemSummary.vue           |   8 +-
 src/pages/Item/ItemList.vue                   |   3 +-
 src/pages/Item/ItemRequest.vue                |  26 +-
 src/pages/Item/locale/en.yml                  |   1 +
 src/pages/Item/locale/es.yml                  |   1 +
 src/pages/Order/Card/OrderDescriptor.vue      |   4 -
 src/pages/Order/Card/OrderSummary.vue         |   4 +
 src/pages/Route/Card/RouteDescriptorMenu.vue  |   2 +-
 src/pages/Route/Card/RouteSummary.vue         |   4 +
 src/pages/Route/Roadmap/RoadmapSummary.vue    |   4 +
 .../Shelving/Card/ShelvingDescriptorMenu.vue  |   7 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |  13 +-
 src/pages/Ticket/Card/TicketSummary.vue       |  18 +-
 src/pages/Travel/Card/TravelSummary.vue       |   5 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |  55 +---
 .../Worker/Card/WorkerDescriptorMenu.vue      |  65 +++++
 src/pages/Worker/Card/WorkerSummary.vue       |   4 +
 src/pages/Zone/Card/ZoneBasicData.vue         |  13 +-
 .../Zone/Card/ZoneEventInclusionForm.vue      |  10 +-
 src/pages/Zone/Card/ZoneSummary.vue           |   4 +
 src/pages/Zone/locale/es.yml                  |   1 +
 src/router/modules/claim.js                   | 223 +++++++-------
 src/stores/invoiceOutGlobal.js                |  44 ++-
 .../invoiceIn/invoiceInCorrective.spec.js     |   4 +-
 61 files changed, 873 insertions(+), 723 deletions(-)
 create mode 100644 src/components/ui/VnMoreOptions.vue
 create mode 100644 src/composables/useHasAccount.js
 create mode 100644 src/pages/Entry/Card/EntryDescriptorMenu.vue
 create mode 100644 src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
 create mode 100644 src/pages/Item/Card/ItemDescriptorMenu.vue
 create mode 100644 src/pages/Worker/Card/WorkerDescriptorMenu.vue

diff --git a/src/components/RegularizeStockForm.vue b/src/components/RegularizeStockForm.vue
index 3cd18d1c87e..91a2e5d39ca 100644
--- a/src/components/RegularizeStockForm.vue
+++ b/src/components/RegularizeStockForm.vue
@@ -44,7 +44,7 @@ const onDataSaved = (data) => {
     <FormModelPopup
         url-create="Items/regularize"
         model="Items"
-        :title="t('Regularize stock')"
+        :title="t('item.regularizeStock')"
         :form-initial-data="regularizeFormData"
         @on-data-saved="onDataSaved($event)"
     >
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index f4c0091d2c1..cf217555a71 100644
--- a/src/components/ui/CardDescriptor.vue
+++ b/src/components/ui/CardDescriptor.vue
@@ -6,6 +6,7 @@ import { useArrayData } from 'composables/useArrayData';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import { useState } from 'src/composables/useState';
 import { useRoute } from 'vue-router';
+import VnMoreOptions from './VnMoreOptions.vue';
 
 const $props = defineProps({
     url: {
@@ -47,7 +48,6 @@ let store;
 let entity;
 const isLoading = ref(false);
 const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
-const menuRef = ref();
 defineExpose({ getData });
 
 onBeforeMount(async () => {
@@ -159,25 +159,11 @@ const toModule = computed(() =>
                         </QTooltip>
                     </QBtn>
                 </RouterLink>
-                <QBtn
-                    v-if="$slots.menu"
-                    color="white"
-                    dense
-                    flat
-                    icon="more_vert"
-                    round
-                    size="md"
-                    data-cy="descriptor-more-opts"
-                >
-                    <QTooltip>
-                        {{ t('components.cardDescriptor.moreOptions') }}
-                    </QTooltip>
-                    <QMenu :ref="menuRef">
-                        <QList>
-                            <slot name="menu" :entity="entity" :menu-ref="menuRef" />
-                        </QList>
-                    </QMenu>
-                </QBtn>
+                <VnMoreOptions v-if="$slots.menu">
+                    <template #menu="{ menuRef }">
+                        <slot name="menu" :entity="entity" :menu-ref="menuRef" />
+                    </template>
+                </VnMoreOptions>
             </div>
             <slot name="before" />
             <div class="body q-py-sm">
@@ -222,8 +208,8 @@ const toModule = computed(() =>
     />
 </template>
 
-<style lang="scss" scoped>
-:deep(.body) {
+<style lang="scss">
+.body {
     background-color: var(--vn-section-color);
     .text-h5 {
         font-size: 20px;
@@ -262,7 +248,9 @@ const toModule = computed(() =>
         }
     }
 }
+</style>
 
+<style lang="scss" scoped>
 .title {
     overflow: hidden;
     text-overflow: ellipsis;
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index 8395dfd73dd..52427f3fec9 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -1,10 +1,11 @@
 <script setup>
-import { ref, computed, watch, onBeforeMount, onMounted } from 'vue';
+import { ref, computed, watch, onBeforeMount } from 'vue';
 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';
-import { useStateStore } from 'src/stores/useStateStore';
+import VnMoreOptions from './VnMoreOptions.vue';
 
 const props = defineProps({
     url: {
@@ -40,7 +41,6 @@ const { store } = arrayData;
 const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
 const isLoading = ref(false);
 
-const stateStore = useStateStore();
 defineExpose({
     entity,
     fetch,
@@ -52,9 +52,6 @@ onBeforeMount(async () => {
     watch(props, async () => await fetch());
 });
 
-onMounted(() => {
-    stateStore.rightDrawerChangeValue(false);
-});
 async function fetch() {
     store.url = props.url;
     store.filter = props.filter ?? {};
@@ -64,6 +61,7 @@ async function fetch() {
     isLoading.value = false;
 }
 </script>
+
 <template>
     <div class="summary container">
         <QCard class="cardSummary">
@@ -84,11 +82,16 @@ async function fetch() {
                         <span v-else></span>
                     </slot>
                     <slot name="header" :entity="entity" dense>
-                        {{ entity.id + ' - ' + entity.name }}
-                    </slot>
-                    <slot name="header-right" :entity="entity">
-                        <span></span>
+                        <VnLv :label="`${entity.id} -`" :value="entity.name" />
                     </slot>
+                    <span class="row no-wrap">
+                        <slot name="header-right" :entity="entity" />
+                        <VnMoreOptions v-if="$slots.menu && isDialogOpened()">
+                            <template #menu="{ menuRef }">
+                                <slot name="menu" :entity="entity" :menu-ref="menuRef" />
+                            </template>
+                        </VnMoreOptions>
+                    </span>
                 </div>
                 <div class="summaryBody row q-mb-md">
                     <slot name="body" :entity="entity" />
@@ -97,6 +100,7 @@ async function fetch() {
         </QCard>
     </div>
 </template>
+
 <style lang="scss">
 .summary.container {
     display: flex;
diff --git a/src/components/ui/VnMoreOptions.vue b/src/components/ui/VnMoreOptions.vue
new file mode 100644
index 00000000000..39e84be2bab
--- /dev/null
+++ b/src/components/ui/VnMoreOptions.vue
@@ -0,0 +1,20 @@
+<template>
+    <QBtn
+        color="white"
+        dense
+        flat
+        icon="more_vert"
+        round
+        size="md"
+        data-cy="descriptor-more-opts"
+    >
+        <QTooltip>
+            {{ $t('components.cardDescriptor.moreOptions') }}
+        </QTooltip>
+        <QMenu ref="menuRef">
+            <QList>
+                <slot name="menu" :menu-ref="$refs.menuRef" />
+            </QList>
+        </QMenu>
+    </QBtn>
+</template>
diff --git a/src/composables/useHasAccount.js b/src/composables/useHasAccount.js
new file mode 100644
index 00000000000..1014bedf3b1
--- /dev/null
+++ b/src/composables/useHasAccount.js
@@ -0,0 +1,6 @@
+import axios from 'axios';
+
+export default async (id) => {
+    const { data } = await axios.get(`Accounts/${id}/exists`);
+    return data.exists;
+};
diff --git a/src/pages/Account/Card/AccountDescriptor.vue b/src/pages/Account/Card/AccountDescriptor.vue
index 8af817fcc00..4e5328de66c 100644
--- a/src/pages/Account/Card/AccountDescriptor.vue
+++ b/src/pages/Account/Card/AccountDescriptor.vue
@@ -1,13 +1,13 @@
 <script setup>
-import { ref, computed } 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 AccountDescriptorMenu from './AccountDescriptorMenu.vue';
-import FetchData from 'src/components/FetchData.vue';
 import VnImg from 'src/components/ui/VnImg.vue';
+import useHasAccount from 'src/composables/useHasAccount.js';
 
 const $props = defineProps({
     id: {
@@ -23,6 +23,7 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 const data = ref(useCardDescription());
+const hasAccount = ref();
 const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
 
 const filter = {
@@ -30,18 +31,16 @@ const filter = {
     fields: ['id', 'nickname', 'name', 'role'],
     include: { relation: 'role', scope: { fields: ['id', 'name'] } },
 };
-const hasAccount = ref(false);
+
+onMounted(async () => {
+    hasAccount.value = await useHasAccount(entityId.value);
+});
 </script>
 
 <template>
-    <FetchData
-        :url="`Accounts/${entityId}/exists`"
-        auto-load
-        @on-fetch="(data) => (hasAccount = data.exists)"
-    />
     <CardDescriptor
         ref="descriptor"
-        url="VnUsers/preview"
+        :url="`VnUsers/preview`"
         :filter="filter"
         module="Account"
         @on-fetch="setData"
@@ -50,7 +49,7 @@ const hasAccount = ref(false);
         :subtitle="data.subtitle"
     >
         <template #menu>
-            <AccountDescriptorMenu :has-account="hasAccount" />
+            <AccountDescriptorMenu :entity-id="entityId" />
         </template>
         <template #before>
             <VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
@@ -74,7 +73,7 @@ const hasAccount = ref(false);
             <VnLv :label="t('account.card.nickname')" :value="entity.name" />
             <VnLv :label="t('account.card.role')" :value="entity.role.name" />
         </template>
-        <template #icons="{ entity }">
+        <template #actions="{ entity }">
             <QCardActions class="q-gutter-x-md">
                 <QIcon
                     v-if="!entity.active"
@@ -82,7 +81,7 @@ const hasAccount = ref(false);
                     name="vn:disabled"
                     flat
                     round
-                    size="xs"
+                    size="sm"
                     class="fill-icon"
                 >
                     <QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
@@ -93,7 +92,7 @@ const hasAccount = ref(false);
                     v-if="hasAccount"
                     flat
                     round
-                    size="xs"
+                    size="sm"
                     class="fill-icon"
                 >
                     <QTooltip>{{ t('account.card.enabled') }}</QTooltip>
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index c091962fcac..aa49dabe887 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -1,37 +1,37 @@
 <script setup>
 import axios from 'axios';
-import { computed, ref, toRefs } from 'vue';
+import { computed, onMounted, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
-import { useRoute } from 'vue-router';
 import { useAcl } from 'src/composables/useAcl';
 import { useArrayData } from 'src/composables/useArrayData';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import VnChangePassword from 'src/components/common/VnChangePassword.vue';
-import { useQuasar } from 'quasar';
+import useNotify from 'src/composables/useNotify.js';
+import useHasAccount from 'src/composables/useHasAccount.js';
 import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const $props = defineProps({
-    hasAccount: {
-        type: Boolean,
-        default: false,
+    entityId: {
+        type: Number,
         required: true,
     },
 });
+
 const { t } = useI18n();
-const { hasAccount } = toRefs($props);
 const { openConfirmationModal } = useVnConfirm();
-const route = useRoute();
-const { notify } = useQuasar();
+const { notify } = useNotify();
 const account = computed(() => useArrayData('AccountId').store.data[0]);
-account.value.hasAccount = hasAccount.value;
-const entityId = computed(() => +route.params.id);
+
+onMounted(async () => {
+    account.value.hasAccount = await useHasAccount($props.entityId);
+});
 
 async function updateStatusAccount(active) {
     if (active) {
-        await axios.post(`Accounts`, { id: entityId.value });
+        await axios.post(`Accounts`, { id: $props.entityId });
     } else {
-        await axios.delete(`Accounts/${entityId.value}`);
+        await axios.delete(`Accounts/${$props.entityId}`);
     }
 
     account.value.hasAccount = active;
@@ -42,7 +42,7 @@ async function updateStatusAccount(active) {
     });
 }
 async function updateStatusUser(active) {
-    await axios.patch(`VnUsers/${entityId.value}`, { active });
+    await axios.patch(`VnUsers/${$props.entityId}`, { active });
     account.value.active = active;
     const status = active ? 'activate' : 'deactivate';
     notify({
@@ -105,6 +105,7 @@ async function sync() {
                 class="full-width"
                 clearable
                 clear-icon="close"
+                type="password"
             />
         </template>
     </VnConfirm>
diff --git a/src/pages/Account/Card/AccountMailAlias.vue b/src/pages/Account/Card/AccountMailAlias.vue
index 8d3bd3b677a..efd2b481b2a 100644
--- a/src/pages/Account/Card/AccountMailAlias.vue
+++ b/src/pages/Account/Card/AccountMailAlias.vue
@@ -9,6 +9,7 @@ import AccountMailAliasCreateForm from './AccountMailAliasCreateForm.vue';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import { useArrayData } from 'composables/useArrayData';
 import useNotify from 'src/composables/useNotify.js';
+import useHasAccount from 'src/composables/useHasAccount.js';
 import axios from 'axios';
 
 const { t } = useI18n();
@@ -50,16 +51,6 @@ const columns = computed(() => [
     },
 ]);
 
-const fetchAccountExistence = async () => {
-    try {
-        const { data } = await axios.get(`Accounts/${route.params.id}/exists`);
-        return data.exists;
-    } catch (error) {
-        console.error('Error fetching account existence', error);
-        return false;
-    }
-};
-
 const deleteMailAlias = async (row) => {
     await axios.delete(`${urlPath}/${row.id}`);
     fetchMailAliases();
@@ -79,7 +70,7 @@ const fetchMailAliases = async () => {
 
 const getAccountData = async (reload = true) => {
     loading.value = true;
-    hasAccount.value = await fetchAccountExistence();
+    hasAccount.value = await useHasAccount(route.params.id);
     if (!hasAccount.value) {
         loading.value = false;
         store.data = [];
diff --git a/src/pages/Account/Card/AccountMailForwarding.vue b/src/pages/Account/Card/AccountMailForwarding.vue
index 30849d44a76..0e5ae3122f3 100644
--- a/src/pages/Account/Card/AccountMailForwarding.vue
+++ b/src/pages/Account/Card/AccountMailForwarding.vue
@@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
 import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import useNotify from 'src/composables/useNotify.js';
+import useHasAccount from 'src/composables/useHasAccount';
 
 const { t } = useI18n();
 const route = useRoute();
@@ -30,23 +31,9 @@ const hasDataChanged = computed(
         initialData.value.hasData !== hasData.value
 );
 
-const fetchAccountExistence = async () => {
-    try {
-        const { data } = await axios.get(`Accounts/${route.params.id}/exists`);
-        return data.exists;
-    } catch (error) {
-        console.error('Error fetching account existence', error);
-        return false;
-    }
-};
-
 const fetchMailForwards = async () => {
-    try {
-        const response = await axios.get(`MailForwards/${route.params.id}`);
-        return response.data;
-    } catch {
-        return null;
-    }
+    const response = await axios.get(`MailForwards/${route.params.id}`);
+    return response.data;
 };
 
 const deleteMailForward = async () => {
@@ -72,7 +59,7 @@ const setInitialData = async () => {
     loading.value = true;
     initialData.value.account = route.params.id;
     formData.value.account = route.params.id;
-    hasAccount.value = await fetchAccountExistence(route.params.id);
+    hasAccount.value = await useHasAccount(route.params.id);
     if (!hasAccount.value) {
         loading.value = false;
         return;
diff --git a/src/pages/Account/Card/AccountSummary.vue b/src/pages/Account/Card/AccountSummary.vue
index e6c21ed34af..ca17c7975bb 100644
--- a/src/pages/Account/Card/AccountSummary.vue
+++ b/src/pages/Account/Card/AccountSummary.vue
@@ -7,6 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
 import { useArrayData } from 'src/composables/useArrayData';
+import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -31,12 +32,14 @@ const filter = {
 <template>
     <CardSummary
         data-key="AccountId"
-        ref="AccountSummary"
         url="VnUsers/preview"
         :filter="filter"
         @on-fetch="(data) => (account = data)"
     >
         <template #header>{{ account.id }} - {{ account.nickname }}</template>
+        <template #menu="">
+            <AccountDescriptorMenu :entity-id="entityId" />
+        </template>
         <template #body>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
diff --git a/src/pages/Claim/Card/ClaimCard.vue b/src/pages/Claim/Card/ClaimCard.vue
index 3642dc0d0fb..e1e00081571 100644
--- a/src/pages/Claim/Card/ClaimCard.vue
+++ b/src/pages/Claim/Card/ClaimCard.vue
@@ -1,21 +1,13 @@
 <script setup>
-import VnCard from 'components/common/VnCard.vue';
+import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ClaimDescriptor from './ClaimDescriptor.vue';
-import ClaimFilter from '../ClaimFilter.vue';
 import filter from './ClaimFilter.js';
 </script>
 <template>
-    <VnCard
-        data-key="Claim"
-        base-url="Claims"
-        :descriptor="ClaimDescriptor"
-        :filter-panel="ClaimFilter"
-        search-data-key="ClaimList"
+    <VnCardBeta 
+        data-key="Claim" 
+        base-url="Claims" 
+        :descriptor="ClaimDescriptor" 
         :filter="filter"
-        :searchbar-props="{
-            url: 'Claims/filter',
-            label: 'Search claim',
-            info: 'You can search by claim id or customer name',
-        }"
     />
 </template>
diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue
index 8939a0785b3..66fb151e523 100644
--- a/src/pages/Claim/Card/ClaimSummary.vue
+++ b/src/pages/Claim/Card/ClaimSummary.vue
@@ -19,6 +19,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
 import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
+import ClaimDescriptorMenu from './ClaimDescriptorMenu.vue';
 
 const route = useRoute();
 const router = useRouter();
@@ -228,6 +229,9 @@ function claimUrl(section) {
                 </QList>
             </QBtnDropdown>
         </template>
+        <template #menu="{ entity }">
+            <ClaimDescriptorMenu :claim="entity.claim" />
+        </template>
         <template #body="{ entity: { claim, salesClaimed, developments } }">
             <QCard class="vn-one" v-if="$route.name != 'ClaimSummary'">
                 <VnTitle
diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue
index bb97162d87c..35b051cdc1e 100644
--- a/src/pages/Claim/ClaimList.vue
+++ b/src/pages/Claim/ClaimList.vue
@@ -2,18 +2,18 @@
 import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { toDate } from 'filters/index';
-import VnSearchbar from 'components/ui/VnSearchbar.vue';
 import ClaimFilter from './ClaimFilter.vue';
 import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import ClaimSummary from './Card/ClaimSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import RightMenu from 'src/components/common/RightMenu.vue';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import ZoneDescriptorProxy from '../Zone/Card/ZoneDescriptorProxy.vue';
+import VnSection from 'src/components/common/VnSection.vue';
 
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
+const dataKey = 'ClaimList';
 
 const claimFilterRef = ref();
 const columns = computed(() => [
@@ -125,48 +125,50 @@ const STATE_COLOR = {
 </script>
 
 <template>
-    <VnSearchbar
-        data-key="ClaimList"
-        :label="t('Search claim')"
-        :info="t('You can search by claim id or customer name')"
-    />
-    <RightMenu>
-        <template #right-panel>
+    <VnSection
+        :data-key="dataKey"
+        :columns="columns"
+        prefix="claim"
+        :array-data-props="{
+            url: 'Claims/filter',
+            order: ['cs.priority ASC', 'created ASC'],
+        }"
+    >
+        <template #rightMenu>
             <ClaimFilter data-key="ClaimList" ref="claimFilterRef" />
         </template>
-    </RightMenu>
-    <VnTable
-        data-key="ClaimList"
-        url="Claims/filter"
-        :order="['cs.priority ASC', 'created ASC']"
-        :columns="columns"
-        redirect="claim"
-        :right-search="false"
-    >
-        <template #column-clientFk="{ row }">
-            <span class="link" @click.stop>
-                {{ row.clientName }}
-                <CustomerDescriptorProxy :id="row.clientFk" />
-            </span>
+        <template #body>
+            <VnTable
+                :data-key="dataKey"
+                :columns="columns"
+                redirect="claim"
+                :right-search="false"
+                auto-load
+            >
+                <template #column-clientFk="{ row }">
+                    <span class="link" @click.stop>
+                        {{ row.clientName }}
+                        <CustomerDescriptorProxy :id="row.clientFk" />
+                    </span>
+                </template>
+                <template #column-attendedBy="{ row }">
+                    <span @click.stop>
+                        <VnUserLink :name="row.workerName" :worker-id="row.workerFk" />
+                    </span>
+                </template>
+                <template #column-zoneFk="{ row }">
+                    <span class="link" @click.stop>
+                        {{ row.zoneName }}
+                        <ZoneDescriptorProxy :id="row.zoneId" />
+                    </span>
+                </template>
+            </VnTable>
         </template>
-        <template #column-attendedBy="{ row }">
-            <span @click.stop>
-                <VnUserLink :name="row.workerName" :worker-id="row.workerFk" />
-            </span>
-        </template>
-        <template #column-zoneFk="{ row }">
-            <span class="link" @click.stop>
-                {{ row.zoneName }}
-                <ZoneDescriptorProxy :id="row.zoneId" />
-            </span>
-        </template>
-    </VnTable>
+    </VnSection>
 </template>
 
 <i18n>
 es:
-    Search claim: Buscar reclamación
-    You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
     params:
         stateCode: Estado
 en:
diff --git a/src/pages/Claim/locale/en.yml b/src/pages/Claim/locale/en.yml
index ffcb44df61c..11b4a2ca473 100644
--- a/src/pages/Claim/locale/en.yml
+++ b/src/pages/Claim/locale/en.yml
@@ -44,3 +44,5 @@ claim:
     fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}'
     noData: 'There are no images/videos, click here or drag and drop the file'
     dragDrop: Drag and drop it here
+    search: Search claims
+    searchInfo: You can search by claim id or customer name
diff --git a/src/pages/Claim/locale/es.yml b/src/pages/Claim/locale/es.yml
index 052416aa7f7..d35d2c8e765 100644
--- a/src/pages/Claim/locale/es.yml
+++ b/src/pages/Claim/locale/es.yml
@@ -1,5 +1,3 @@
-Search claim: Buscar reclamación
-You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
 claim:
     customer: Cliente
     code: Código
@@ -46,3 +44,5 @@ claim:
     fileDescription: 'ID de reclamación {claimId} del cliente {clientName} con ID {clientId}'
     noData: 'No hay imágenes/videos, haz clic aquí o arrastra y suelta el archivo'
     dragDrop: Arrastra y suelta aquí
+    search: Buscar reclamación
+    searchInfo: Puedes buscar por ID de la reclamación o nombre del cliente
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 6650ea39515..d2eb125d724 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -12,6 +12,7 @@ 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';
+import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
 const route = useRoute();
 const { t } = useI18n();
 const grafanaUrl = 'https://grafana.verdnatura.es';
@@ -70,6 +71,9 @@ const sumRisk = ({ clientRisks }) => {
         data-key="CustomerSummary"
         module-name="Customer"
     >
+        <template #menu="{ entity }">
+            <CustomerDescriptorMenu :customer="entity" />
+        </template>
         <template #body="{ entity }">
             <QCard class="vn-one">
                 <VnTitle
@@ -94,14 +98,13 @@ const sumRisk = ({ clientRisks }) => {
                             :phone-number="entity.mobile"
                             :channel="entity.country?.saySimpleCountry?.channel"
                             class="q-ml-xs"
-                            :country="entity.country?.code"
                         />
                     </template>
                 </VnLv>
                 <VnLv :value="entity.email" copy
                     ><template #label>
                         {{ t('globals.params.email') }}
-                        <VnLinkMail :email="entity.email"></VnLinkMail> </template
+                        <VnLinkMail email="entity.email"></VnLinkMail> </template
                 ></VnLv>
                 <VnLv
                     :label="t('customer.summary.salesPerson')"
@@ -173,7 +176,7 @@ const sumRisk = ({ clientRisks }) => {
                         :label="t('customer.summary.notifyByEmail')"
                         :value="entity.isToBeMailed"
                     />
-                    <VnLv :label="t('globals.isVies')" :value="entity.isVies" />
+                    <VnLv :label="t('customer.summary.vies')" :value="entity.isVies" />
                 </VnRow>
             </QCard>
             <QCard class="vn-one">
diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue
index 150ef3b8414..6789ac56b42 100644
--- a/src/pages/Customer/components/CustomerAddressEdit.vue
+++ b/src/pages/Customer/components/CustomerAddressEdit.vue
@@ -247,8 +247,14 @@ function handleLocation(data, location) {
                     :label="t('Longitude')"
                     clearable
                     v-model="data.longitude"
+                    :decimal-places="7"
+                />
+                <VnInputNumber
+                    :label="t('Latitude')"
+                    clearable
+                    v-model="data.latitude"
+                    :decimal-places="7"
                 />
-                <VnInputNumber :label="t('Latitude')" clearable v-model="data.latitude" />
             </VnRow>
             <h4 class="q-mb-xs">{{ t('Notes') }}</h4>
             <VnRow
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index 9814615a69b..c54ecc3f0ac 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -7,9 +7,9 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 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';
+import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -21,7 +21,6 @@ const $props = defineProps({
 
 const route = useRoute();
 const { t } = useI18n();
-const { openReport } = usePrintService();
 const entryDescriptorRef = ref(null);
 const url = ref();
 
@@ -52,10 +51,6 @@ const getEntryRedirectionFilter = (entry) => {
         to,
     });
 };
-
-const showEntryReport = () => {
-    openReport(`Entries/${route.params.id}/entry-order-pdf`);
-};
 </script>
 
 <template>
@@ -68,14 +63,12 @@ const showEntryReport = () => {
         data-key="Entry"
     >
         <template #menu="{ entity }">
-            <QItem v-ripple clickable @click="showEntryReport(entity)">
-                <QItemSection>{{ t('Show entry report') }}</QItemSection>
-            </QItem>
+            <EntryDescriptorMenu :id="entity.id" />
         </template>
         <template #body="{ entity }">
             <VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
-            <VnLv :label="t('globals.shipped')" :value="toDate(entity.travel?.shipped)" />
-            <VnLv :label="t('globals.landed')" :value="toDate(entity.travel?.landed)" />
+            <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
+            <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
             <VnLv
                 :label="t('globals.warehouseOut')"
                 :value="entity.travel?.warehouseOut?.name"
@@ -154,7 +147,6 @@ es:
     Supplier card: Ficha del proveedor
     All travels with current agency: Todos los envíos con la agencia actual
     All entries with current supplier: Todas las entradas con el proveedor actual
-    Show entry report: Ver informe del pedido
     Go to module index: Ir al índice del modulo
     Inventory entry: Es inventario
     Virtual entry: Es una redada
diff --git a/src/pages/Entry/Card/EntryDescriptorMenu.vue b/src/pages/Entry/Card/EntryDescriptorMenu.vue
new file mode 100644
index 00000000000..a357b46fe95
--- /dev/null
+++ b/src/pages/Entry/Card/EntryDescriptorMenu.vue
@@ -0,0 +1,22 @@
+<script setup>
+import { usePrintService } from 'composables/usePrintService';
+
+const { openReport } = usePrintService();
+
+const $props = defineProps({
+    id: {
+        type: Number,
+        required: true,
+    },
+});
+
+function showEntryReport() {
+    openReport(`Entries/${$props.id}/entry-order-pdf`);
+}
+</script>
+
+<template>
+    <QItem v-ripple clickable @click="showEntryReport">
+        <QItemSection>{{ $t('entryList.list.showEntryReport') }}</QItemSection>
+    </QItem>
+</template>
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index 39dad672cef..755e39454b0 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -12,6 +12,7 @@ import { getUrl } from 'src/composables/getUrl';
 import axios from 'axios';
 import FetchedTags from 'src/components/ui/FetchedTags.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
+import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
 import VnRow from 'src/components/ui/VnRow.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 
@@ -172,6 +173,9 @@ const fetchEntryBuys = async () => {
         <template #header>
             <span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
         </template>
+        <template #menu="{ entity }">
+            <EntryDescriptorMenu :id="entity.id" />
+        </template>
         <template #body>
             <QCard class="vn-one">
                 <VnTitle
@@ -207,7 +211,10 @@ const fetchEntryBuys = async () => {
                     :label="t('entry.summary.travelAgency')"
                     :value="entry.travel.agency?.name"
                 />
-                <VnLv :label="t('globals.shipped')" :value="toDate(entry.travel.shipped)" />
+                <VnLv
+                    :label="t('globals.shipped')"
+                    :value="toDate(entry.travel.shipped)"
+                />
                 <VnLv
                     :label="t('globals.warehouseOut')"
                     :value="entry.travel.warehouseOut?.name"
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 7e92fe051ae..879a5091434 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -243,7 +243,6 @@ const columns = computed(() => [
 
 <i18n>
 es:
-    Inventory entry: Es inventario
     Virtual entry: Es una redada
     Search entries: Buscar entradas
     You can search by entry reference: Puedes buscar por referencia de la entrada
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index 6e41566d06c..59c2666a7a9 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -1,6 +1,7 @@
 entryList:
     list:
         inventoryEntry: Inventory entry
+        showEntryReport: Show entry report
 entryFilter:
     filter:
         search: General search
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index 7e627b09fb8..4fb7bbf08b4 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -4,6 +4,7 @@ You can search by entry reference: Puedes buscar por referencia de la entrada
 entryList:
     list:
         inventoryEntry: Es inventario
+        showEntryReport: Ver informe del pedido
 entryFilter:
     filter:
         search: Búsqueda general
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index 83b1aa25e1d..90aa50af798 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -268,7 +268,7 @@ function deleteFile(dmsFk) {
             </VnRow>
             <VnRow>
                 <VnSelect
-                    :label="t('InvoiceIn.summary.sage')"
+                    :label="t('invoicein.summary.sage')"
                     v-model="data.withholdingSageFk"
                     :options="sageWithholdings"
                     option-value="id"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index cb8a45833aa..4d9e180eb4a 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -1,60 +1,30 @@
 <script setup>
-import { ref, reactive, computed, onBeforeMount, capitalize } from 'vue';
+import { ref, reactive, computed, onBeforeMount } from 'vue';
 import { useRouter, onBeforeRouteUpdate } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { useQuasar } from 'quasar';
 import axios from 'axios';
 import { toCurrency, toDate } from 'src/filters';
-import { useAcl } from 'src/composables/useAcl';
-import { downloadFile } from 'src/composables/downloadFile';
-import { useArrayData } from 'src/composables/useArrayData';
-import { usePrintService } from 'composables/usePrintService';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import FetchData from 'src/components/FetchData.vue';
-import SendEmailDialog from 'components/common/SendEmailDialog.vue';
-import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import { useCapitalize } from 'src/composables/useCapitalize';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import InvoiceInToBook from '../InvoiceInToBook.vue';
+import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
 
 const $props = defineProps({ id: { type: Number, default: null } });
-
 const { push, currentRoute } = useRouter();
-
-const quasar = useQuasar();
-const { hasAny } = useAcl();
 const { t } = useI18n();
-const { openReport, sendEmail } = usePrintService();
-const arrayData = useArrayData();
 
-const invoiceIn = computed(() => arrayData.store.data);
 const cardDescriptorRef = ref();
 const correctionDialogRef = ref();
 const entityId = computed(() => $props.id || +currentRoute.value.params.id);
 const totalAmount = ref();
-const currentAction = ref();
 const config = ref();
 const cplusRectificationTypes = ref([]);
 const siiTypeInvoiceIns = ref([]);
 const invoiceCorrectionTypes = ref([]);
-const actions = {
-    unbook: {
-        title: t('assertAction', { action: t('unbook') }),
-        action: toUnbook,
-    },
-    delete: {
-        title: t('assertAction', { action: t('delete') }),
-        action: deleteInvoice,
-    },
-    clone: {
-        title: t('assertAction', { action: t('clone') }),
-        action: cloneInvoice,
-    },
-    showPdf: { cb: showPdfInvoice },
-    sendPdf: { cb: sendPdfInvoiceConfirmation },
-    correct: { cb: () => correctionDialogRef.value.show() },
-};
+
 const filter = {
     include: [
         {
@@ -90,7 +60,7 @@ const routes = reactive({
         return {
             name: 'InvoiceInList',
             query: {
-                table: JSON.stringify({ supplierFk: id }),
+                params: JSON.stringify({ supplierFk: id }),
             },
         };
     },
@@ -99,7 +69,7 @@ const routes = reactive({
             return {
                 name: 'InvoiceInList',
                 query: {
-                    table: JSON.stringify({ correctedFk: entityId.value }),
+                    params: JSON.stringify({ correctedFk: entityId.value }),
                 },
             };
         }
@@ -118,21 +88,21 @@ const routes = reactive({
 const correctionFormData = reactive({
     invoiceReason: 2,
     invoiceType: 2,
-    invoiceClass: 8,
+    invoiceClass: 6,
 });
 const isNotFilled = computed(() => Object.values(correctionFormData).includes(null));
 
 onBeforeMount(async () => {
     await setInvoiceCorrection(entityId.value);
     const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`);
-    totalAmount.value = data.totalTaxableBase;
+    totalAmount.value = data.totalDueDay;
 });
 
 onBeforeRouteUpdate(async (to, from) => {
     if (to.params.id !== from.params.id) {
         await setInvoiceCorrection(to.params.id);
         const { data } = await axios.get(`InvoiceIns/${to.params.id}/getTotals`);
-        totalAmount.value = data.totalTaxableBase;
+        totalAmount.value = data.totalDueDay;
     }
 });
 
@@ -153,94 +123,6 @@ async function setInvoiceCorrection(id) {
     );
 }
 
-function openDialog() {
-    quasar.dialog({
-        component: VnConfirm,
-        componentProps: {
-            title: t(currentAction.value.title),
-            promise: currentAction.value.action,
-        },
-    });
-}
-
-async function toUnbook() {
-    const { data } = await axios.post(`InvoiceIns/${entityId.value}/toUnbook`);
-    const { isLinked, bookEntry, accountingEntries } = data;
-
-    const type = isLinked ? 'warning' : 'positive';
-    const message = isLinked
-        ? t('isLinked', { bookEntry, accountingEntries })
-        : t('isNotLinked', { bookEntry });
-
-    quasar.notify({ type, message });
-    if (!isLinked) arrayData.store.data.isBooked = false;
-}
-
-async function deleteInvoice() {
-    await axios.delete(`InvoiceIns/${entityId.value}`);
-    quasar.notify({
-        type: 'positive',
-        message: t('Invoice deleted'),
-    });
-    push({ path: '/invoice-in' });
-}
-
-async function cloneInvoice() {
-    const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`);
-    quasar.notify({
-        type: 'positive',
-        message: t('Invoice cloned'),
-    });
-    push({ path: `/invoice-in/${data.id}/summary` });
-}
-
-const canEditProp = (props) =>
-    hasAny([{ model: 'InvoiceIn', props, accessType: 'WRITE' }]);
-
-const isAgricultural = () => {
-    if (!config.value) return false;
-    return (
-        invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
-        config?.value[0]?.sageWithholdingFk
-    );
-};
-
-function showPdfInvoice() {
-    if (isAgricultural())
-        openReport(`InvoiceIns/${entityId.value}/invoice-in-pdf`, null, '_blank');
-}
-
-function sendPdfInvoiceConfirmation() {
-    quasar.dialog({
-        component: SendEmailDialog,
-        componentProps: {
-            data: {
-                address: invoiceIn.value.supplier.contacts[0].email,
-            },
-            promise: sendPdfInvoice,
-        },
-    });
-}
-
-function sendPdfInvoice({ address }) {
-    if (!address)
-        quasar.notify({
-            type: 'negative',
-            message: t(`The email can't be empty`),
-        });
-    else
-        return sendEmail(`InvoiceIns/${entityId.value}/invoice-in-email`, {
-            recipientId: invoiceIn.value.supplier.id,
-            recipient: address,
-        });
-}
-
-function triggerMenu(type) {
-    currentAction.value = actions[type];
-    if (currentAction.value.cb) currentAction.value.cb();
-    else openDialog(type);
-}
-
 const createInvoiceInCorrection = async () => {
     const { data: correctingId } = await axios.post(
         'InvoiceIns/corrective',
@@ -262,7 +144,7 @@ const createInvoiceInCorrection = async () => {
         auto-load
     />
     <FetchData
-        url="siiTypeInvoiceIns"
+        url="SiiTypeInvoiceIns"
         :where="{ code: { like: 'R%' } }"
         @on-fetch="(data) => (siiTypeInvoiceIns = data)"
         auto-load
@@ -281,87 +163,13 @@ const createInvoiceInCorrection = async () => {
         title="supplierRef"
     >
         <template #menu="{ entity }">
-            <InvoiceInToBook>
-                <template #content="{ book }">
-                    <QItem
-                        v-if="!entity?.isBooked && canEditProp('toBook')"
-                        v-ripple
-                        clickable
-                        @click="book(entityId)"
-                    >
-                        <QItemSection>{{ t('To book') }}</QItemSection>
-                    </QItem>
-                </template>
-            </InvoiceInToBook>
-            <QItem
-                v-if="entity?.isBooked && canEditProp('toUnbook')"
-                v-ripple
-                clickable
-                @click="triggerMenu('unbook')"
-            >
-                <QItemSection>
-                    {{ t('To unbook') }}
-                </QItemSection>
-            </QItem>
-            <QItem
-                v-if="canEditProp('deleteById')"
-                v-ripple
-                clickable
-                @click="triggerMenu('delete')"
-            >
-                <QItemSection>{{ t('Delete invoice') }}</QItemSection>
-            </QItem>
-            <QItem
-                v-if="canEditProp('clone')"
-                v-ripple
-                clickable
-                @click="triggerMenu('clone')"
-            >
-                <QItemSection>{{ t('Clone invoice') }}</QItemSection>
-            </QItem>
-            <QItem
-                v-if="isAgricultural()"
-                v-ripple
-                clickable
-                @click="triggerMenu('showPdf')"
-            >
-                <QItemSection>{{ t('Show agricultural receipt as PDF') }}</QItemSection>
-            </QItem>
-            <QItem
-                v-if="isAgricultural()"
-                v-ripple
-                clickable
-                @click="triggerMenu('sendPdf')"
-            >
-                <QItemSection
-                    >{{ t('Send agricultural receipt as PDF') }}...</QItemSection
-                >
-            </QItem>
-            <QItem
-                v-if="!invoiceInCorrection.corrected"
-                v-ripple
-                clickable
-                @click="triggerMenu('correct')"
-            >
-                <QItemSection>{{ t('Create rectificative invoice') }}...</QItemSection>
-            </QItem>
-            <QItem
-                v-if="entity.dmsFk"
-                v-ripple
-                clickable
-                @click="downloadFile(entity.dmsFk)"
-            >
-                <QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
-            </QItem>
+            <InvoiceInDescriptorMenu :invoice="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('InvoiceIn.list.issued')" :value="toDate(entity.issued)" />
-            <VnLv
-                :label="t('InvoiceIn.summary.bookedDate')"
-                :value="toDate(entity.booked)"
-            />
-            <VnLv :label="t('InvoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
-            <VnLv :label="t('InvoiceIn.list.supplier')">
+            <VnLv :label="t('invoicein.list.issued')" :value="toDate(entity.issued)" />
+            <VnLv :label="t('invoicein.summary.bookedDate')" :value="toDate(entity.booked)" />
+            <VnLv :label="t('invoicein.list.amount')" :value="toCurrency(totalAmount)" />
+            <VnLv :label="t('invoicein.list.supplier')">
                 <template #value>
                     <span class="link">
                         {{ entity?.supplier?.nickname }}
@@ -378,7 +186,7 @@ const createInvoiceInCorrection = async () => {
                     color="primary"
                     :to="routes.getSupplier(entity.supplierFk)"
                 >
-                    <QTooltip>{{ t('InvoiceIn.list.supplier') }}</QTooltip>
+                    <QTooltip>{{ t('invoicein.list.supplier') }}</QTooltip>
                 </QBtn>
                 <QBtn
                     size="md"
@@ -394,7 +202,7 @@ const createInvoiceInCorrection = async () => {
                     color="primary"
                     :to="routes.getTickets(entity.supplierFk)"
                 >
-                    <QTooltip>{{ t('InvoiceIn.descriptor.ticketList') }}</QTooltip>
+                    <QTooltip>{{ t('InvoiceOut.card.ticketList') }}</QTooltip>
                 </QBtn>
                 <QBtn
                     v-if="
@@ -438,7 +246,7 @@ const createInvoiceInCorrection = async () => {
                             readonly
                         />
                         <VnSelect
-                            :label="`${capitalize(t('globals.class'))}`"
+                            :label="`${useCapitalize(t('globals.class'))}`"
                             v-model="correctionFormData.invoiceClass"
                             :options="siiTypeInvoiceIns"
                             option-value="id"
@@ -448,27 +256,15 @@ const createInvoiceInCorrection = async () => {
                     </QItemSection>
                     <QItemSection>
                         <VnSelect
-                            :label="`${capitalize(t('globals.type'))}`"
+                            :label="`${useCapitalize(t('globals.type'))}`"
                             v-model="correctionFormData.invoiceType"
                             :options="cplusRectificationTypes"
                             option-value="id"
                             option-label="description"
                             :required="true"
-                        >
-                            <template #option="{ opt }">
-                                <QItem>
-                                    <QItemSection>
-                                        <QItemLabel
-                                            >{{ opt.code }} -
-                                            {{ opt.description }}</QItemLabel
-                                        >
-                                    </QItemSection>
-                                </QItem>
-                                <div></div>
-                            </template>
-                        </VnSelect>
+                        />
                         <VnSelect
-                            :label="`${capitalize(t('globals.reason'))}`"
+                            :label="`${useCapitalize(t('globals.reason'))}`"
                             v-model="correctionFormData.invoiceReason"
                             :options="invoiceCorrectionTypes"
                             option-value="id"
@@ -512,31 +308,3 @@ const createInvoiceInCorrection = async () => {
     }
 }
 </style>
-<i18n>
-en:
-    isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
-    isLinked: The entry {bookEntry} has been linked to Sage. Please contact administration for further information
-    assertAction: Are you sure you want to {action} this invoice?
-es:
-    book: asentar
-    unbook: desasentar
-    delete: eliminar
-    clone: clonar
-    To book: Contabilizar
-    To unbook: Descontabilizar
-    Delete invoice: Eliminar factura
-    Invoice deleted: Factura eliminada
-    Clone invoice: Clonar factura
-    Invoice cloned: Factura clonada
-    Show agricultural receipt as PDF: Ver recibo agrícola como PDF
-    Send agricultural receipt as PDF: Enviar recibo agrícola como PDF
-    Are you sure you want to send it?: Estás seguro que quieres enviarlo?
-    Send PDF invoice: Enviar factura a PDF
-    Create rectificative invoice: Crear factura rectificativa
-    Rectificative invoice: Factura rectificativa
-    Original invoice: Factura origen
-    Entry: entrada
-    isNotLinked: Se ha eliminado el asiento nº {bookEntry} con {accountingEntries} apuntes
-    isLinked: El asiento {bookEntry} fue enlazado a Sage, por favor contacta con administración
-    assertAction: Estas seguro de querer {action} esta factura?
-</i18n>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
new file mode 100644
index 00000000000..647b68f88ed
--- /dev/null
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
@@ -0,0 +1,206 @@
+<script setup>
+import { ref, computed, toRefs, reactive } from 'vue';
+import { useRouter } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import { useQuasar } from 'quasar';
+import axios from 'axios';
+import { useAcl } from 'src/composables/useAcl';
+import { downloadFile } from 'src/composables/downloadFile';
+import { useArrayData } from 'src/composables/useArrayData';
+import { usePrintService } from 'composables/usePrintService';
+import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import SendEmailDialog from 'components/common/SendEmailDialog.vue';
+import InvoiceInToBook from '../InvoiceInToBook.vue';
+
+const { hasAny } = useAcl();
+const { t } = useI18n();
+const { openReport, sendEmail } = usePrintService();
+const { push, currentRoute } = useRouter();
+const $props = defineProps({
+    invoice: {
+        type: Object,
+        required: true,
+    },
+});
+const { invoice } = toRefs($props);
+const quasar = useQuasar();
+const arrayData = useArrayData();
+const currentAction = ref();
+const config = ref();
+const correctionDialogRef = ref();
+const invoiceInCorrection = reactive({ correcting: [], corrected: null });
+const entityId = computed(() => $props.invoice.id || +currentRoute.value.params.id);
+const invoiceIn = computed(() => arrayData.store.data);
+const actions = {
+    unbook: {
+        title: t('assertAction', { action: t('invoicein.descriptorMenu.unbook') }),
+        action: toUnbook,
+    },
+    delete: {
+        title: t('assertAction', { action: t('invoicein.descriptorMenu.delete') }),
+        action: deleteInvoice,
+    },
+    clone: {
+        title: t('assertAction', { action: t('invoicein.descriptorMenu.clone') }),
+        action: cloneInvoice,
+    },
+    showPdf: { cb: showPdfInvoice },
+    sendPdf: { cb: sendPdfInvoiceConfirmation },
+    correct: { cb: () => correctionDialogRef.value.show() },
+};
+const canEditProp = (props) =>
+    hasAny([{ model: 'InvoiceIn', props, accessType: 'WRITE' }]);
+
+function triggerMenu(type) {
+    currentAction.value = actions[type];
+    if (currentAction.value.cb) currentAction.value.cb();
+    else openDialog(type);
+}
+
+function openDialog() {
+    quasar.dialog({
+        component: VnConfirm,
+        componentProps: {
+            title: t(currentAction.value.title),
+            promise: currentAction.value.action,
+        },
+    });
+}
+
+async function toUnbook() {
+    const { data } = await axios.post(`InvoiceIns/${entityId.value}/toUnbook`);
+    const { isLinked, bookEntry, accountingEntries } = data;
+
+    const type = isLinked ? 'warning' : 'positive';
+    const message = isLinked
+        ? t('isLinked', { bookEntry })
+        : t('isNotLinked', { bookEntry, accountingEntries });
+
+    quasar.notify({ type, message });
+    if (!isLinked) arrayData.store.data.isBooked = false;
+}
+
+async function deleteInvoice() {
+    await axios.delete(`InvoiceIns/${entityId.value}`);
+    quasar.notify({
+        type: 'positive',
+        message: t('invoicein.descriptorMenu.invoiceDeleted'),
+    });
+    push({ path: '/invoice-in' });
+}
+
+async function cloneInvoice() {
+    const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`);
+    quasar.notify({
+        type: 'positive',
+        message: t('invoicein.descriptorMenu.invoiceCloned'),
+    });
+    push({ path: `/invoice-in/${data.id}/summary` });
+}
+
+const isAgricultural = () => {
+    if (!config.value) return false;
+    return (
+        invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
+        config?.value[0]?.sageWithholdingFk
+    );
+};
+function showPdfInvoice() {
+    if (isAgricultural()) openReport(`InvoiceIns/${entityId.value}/invoice-in-pdf`);
+}
+
+function sendPdfInvoiceConfirmation() {
+    quasar.dialog({
+        component: SendEmailDialog,
+        componentProps: {
+            data: {
+                address: invoiceIn.value.supplier.contacts[0].email,
+            },
+            promise: sendPdfInvoice,
+        },
+    });
+}
+
+function sendPdfInvoice({ address }) {
+    if (!address)
+        quasar.notify({
+            type: 'negative',
+            message: t(`The email can't be empty`),
+        });
+    else
+        return sendEmail(`InvoiceIns/${entityId.value}/invoice-in-email`, {
+            recipientId: invoiceIn.value.supplier.id,
+            recipient: address,
+        });
+}
+</script>
+
+<template>
+    <InvoiceInToBook>
+        <template #content="{ book }">
+            <QItem
+                v-if="!invoice?.isBooked && canEditProp('toBook')"
+                v-ripple
+                clickable
+                @click="book(entityId)"
+            >
+                <QItemSection>{{ t('invoicein.descriptorMenu.toBook') }}</QItemSection>
+            </QItem>
+        </template>
+    </InvoiceInToBook>
+    <QItem
+        v-if="invoice?.isBooked && canEditProp('toUnbook')"
+        v-ripple
+        clickable
+        @click="triggerMenu('unbook')"
+    >
+        <QItemSection>
+            {{ t('invoicein.descriptorMenu.toUnbook') }}
+        </QItemSection>
+    </QItem>
+    <QItem
+        v-if="canEditProp('deleteById')"
+        v-ripple
+        clickable
+        @click="triggerMenu('invoicein.descriptorMenu.delete')"
+    >
+        <QItemSection>{{ t('invoicein.descriptorMenu.deleteInvoice') }}</QItemSection>
+    </QItem>
+    <QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')">
+        <QItemSection>{{ t('invoicein.descriptorMenu.cloneInvoice') }}</QItemSection>
+    </QItem>
+    <QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
+        <QItemSection>{{
+            t('invoicein.descriptorMenu.showAgriculturalPdf')
+        }}</QItemSection>
+    </QItem>
+    <QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
+        <QItemSection
+            >{{ t('invoicein.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
+        >
+    </QItem>
+    <QItem
+        v-if="!invoiceInCorrection.corrected"
+        v-ripple
+        clickable
+        @click="triggerMenu('correct')"
+    >
+        <QItemSection
+            >{{ t('invoicein.descriptorMenu.createCorrective') }}...</QItemSection
+        >
+    </QItem>
+    <QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)">
+        <QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
+    </QItem>
+</template>
+
+<i18n>
+en:
+    isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries		
+    isLinked: The entry has been linked to Sage. Please contact administration for further information		
+    assertAction: Are you sure you want to {action} this invoice?
+es:
+    isNotLinked: Se ha eliminado el asiento nº {bookEntry} con {accountingEntries} apuntes		
+    isLinked: El asiento fue enlazado a Sage, por favor contacta con administración		
+    assertAction: Estas seguro de querer {action} esta factura?
+</i18n>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index 115a3320868..eca0c7af1a0 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -10,6 +10,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
 import InvoiceIntoBook from '../InvoiceInToBook.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
 
 const props = defineProps({ id: { type: [Number, String], default: 0 } });
 const { t } = useI18n();
@@ -26,14 +27,14 @@ const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 });
 const vatColumns = ref([
     {
         name: 'expense',
-        label: 'InvoiceIn.summary.expense',
+        label: 'invoicein.summary.expense',
         field: (row) => row.expenseFk,
         sortable: true,
         align: 'left',
     },
     {
         name: 'landed',
-        label: 'InvoiceIn.summary.taxableBase',
+        label: 'invoicein.summary.taxableBase',
         field: (row) => row.taxableBase,
         format: (value) => toCurrency(value),
         sortable: true,
@@ -41,7 +42,7 @@ const vatColumns = ref([
     },
     {
         name: 'vat',
-        label: 'InvoiceIn.summary.sageVat',
+        label: 'invoicein.summary.sageVat',
         field: (row) => {
             if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`;
         },
@@ -51,7 +52,7 @@ const vatColumns = ref([
     },
     {
         name: 'transaction',
-        label: 'InvoiceIn.summary.sageTransaction',
+        label: 'invoicein.summary.sageTransaction',
         field: (row) => {
             if (row.transactionTypeSage)
                 return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`;
@@ -62,7 +63,7 @@ const vatColumns = ref([
     },
     {
         name: 'rate',
-        label: 'InvoiceIn.summary.rate',
+        label: 'invoicein.summary.rate',
         field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
         format: (value) => toCurrency(value),
         sortable: true,
@@ -70,7 +71,7 @@ const vatColumns = ref([
     },
     {
         name: 'currency',
-        label: 'InvoiceIn.summary.currency',
+        label: 'invoicein.summary.currency',
         field: (row) => row.foreignValue,
         format: (val) => val && toCurrency(val, currency.value),
         sortable: true,
@@ -81,21 +82,21 @@ const vatColumns = ref([
 const dueDayColumns = ref([
     {
         name: 'date',
-        label: 'InvoiceIn.summary.dueDay',
+        label: 'invoicein.summary.dueDay',
         field: (row) => toDate(row.dueDated),
         sortable: true,
         align: 'left',
     },
     {
         name: 'bank',
-        label: 'InvoiceIn.summary.bank',
+        label: 'invoicein.summary.bank',
         field: (row) => row.bank.bank,
         sortable: true,
         align: 'left',
     },
     {
         name: 'amount',
-        label: 'InvoiceIn.list.amount',
+        label: 'invoicein.list.amount',
         field: (row) => row.amount,
         format: (value) => toCurrency(value),
         sortable: true,
@@ -103,7 +104,7 @@ const dueDayColumns = ref([
     },
     {
         name: 'landed',
-        label: 'InvoiceIn.summary.foreignValue',
+        label: 'invoicein.summary.foreignValue',
         field: (row) => row.foreignValue,
         format: (val) => val && toCurrency(val, currency.value),
         sortable: true,
@@ -114,7 +115,7 @@ const dueDayColumns = ref([
 const intrastatColumns = ref([
     {
         name: 'code',
-        label: 'InvoiceIn.summary.code',
+        label: 'invoicein.summary.code',
         field: (row) => {
             return `${row.intrastat.id}: ${row.intrastat?.description}`;
         },
@@ -123,21 +124,21 @@ const intrastatColumns = ref([
     },
     {
         name: 'amount',
-        label: 'InvoiceIn.list.amount',
+        label: 'invoicein.list.amount',
         field: (row) => toCurrency(row.amount),
         sortable: true,
         align: 'left',
     },
     {
         name: 'net',
-        label: 'InvoiceIn.summary.net',
+        label: 'invoicein.summary.net',
         field: (row) => row.net,
         sortable: true,
         align: 'left',
     },
     {
         name: 'stems',
-        label: 'InvoiceIn.summary.stems',
+        label: 'invoicein.summary.stems',
         field: (row) => row.stems,
         format: (value) => value,
         sortable: true,
@@ -145,7 +146,7 @@ const intrastatColumns = ref([
     },
     {
         name: 'landed',
-        label: 'InvoiceIn.summary.country',
+        label: 'invoicein.summary.country',
         field: (row) => row.country?.code,
         format: (value) => value,
         sortable: true,
@@ -200,6 +201,9 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                 </template>
             </InvoiceIntoBook>
         </template>
+        <template #menu="{ entity }">
+            <InvoiceInDescriptorMenu :invoice="entity" />
+        </template>
         <template #body="{ entity }">
             <!--Basic Data-->
             <QCard class="vn-one">
@@ -210,7 +214,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     />
                 </QCardSection>
                 <VnLv
-                    :label="t('InvoiceIn.list.supplier')"
+                    :label="t('invoicein.list.supplier')"
                     :value="entity.supplier?.name"
                 >
                     <template #value>
@@ -221,14 +225,14 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     </template>
                 </VnLv>
                 <VnLv
-                    :label="t('InvoiceIn.list.supplierRef')"
+                    :label="t('invoicein.list.supplierRef')"
                     :value="entity.supplierRef"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.summary.currency')"
+                    :label="t('invoicein.summary.currency')"
                     :value="entity.currency?.code"
                 />
-                <VnLv :label="t('InvoiceIn.serial')" :value="`${entity.serial}`" />
+                <VnLv :label="t('invoicein.serial')" :value="`${entity.serial}`" />
                 <VnLv
                     :label="t('globals.country')"
                     :value="entity.supplier?.country?.code"
@@ -243,19 +247,19 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                 </QCardSection>
                 <VnLv
                     :ellipsis-value="false"
-                    :label="t('InvoiceIn.summary.issued')"
+                    :label="t('invoicein.summary.issued')"
                     :value="toDate(entity.issued)"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.summary.operated')"
+                    :label="t('invoicein.summary.operated')"
                     :value="toDate(entity.operated)"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.summary.bookEntried')"
+                    :label="t('invoicein.summary.bookEntried')"
                     :value="toDate(entity.bookEntried)"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.summary.bookedDate')"
+                    :label="t('invoicein.summary.bookedDate')"
                     :value="toDate(entity.booked)"
                 />
                 <VnLv :label="t('globals.isVies')" :value="entity.supplier?.isVies" />
@@ -268,18 +272,18 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                     />
                 </QCardSection>
                 <VnLv
-                    :label="t('InvoiceIn.summary.sage')"
+                    :label="t('invoicein.summary.sage')"
                     :value="entity.sageWithholding?.withholding"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.summary.vat')"
+                    :label="t('invoicein.summary.vat')"
                     :value="entity.expenseDeductible?.name"
                 />
                 <VnLv
-                    :label="t('InvoiceIn.card.company')"
+                    :label="t('invoicein.card.company')"
                     :value="entity.company?.code"
                 />
-                <VnLv :label="t('InvoiceIn.isBooked')" :value="invoiceIn?.isBooked" />
+                <VnLv :label="t('invoicein.isBooked')" :value="invoiceIn?.isBooked" />
             </QCard>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
@@ -290,11 +294,11 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                 </QCardSection>
                 <QCardSection class="q-pa-none">
                     <VnLv
-                        :label="t('InvoiceIn.summary.taxableBase')"
+                        :label="t('invoicein.summary.taxableBase')"
                         :value="toCurrency(entity.totals.totalTaxableBase)"
                     />
                     <VnLv label="Total" :value="toCurrency(entity.totals.totalVat)" />
-                    <VnLv :label="t('InvoiceIn.summary.dueTotal')">
+                    <VnLv :label="t('invoicein.summary.dueTotal')">
                         <template #value>
                             <QChip
                                 dense
@@ -302,8 +306,8 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                 :color="amountsNotMatch ? 'negative' : 'transparent'"
                                 :title="
                                     amountsNotMatch
-                                        ? t('InvoiceIn.summary.noMatch')
-                                        : t('InvoiceIn.summary.dueTotal')
+                                        ? t('invoicein.summary.noMatch')
+                                        : t('invoicein.summary.dueTotal')
                                 "
                             >
                                 {{ toCurrency(entity.totals.totalDueDay) }}
@@ -314,7 +318,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             </QCard>
             <!--Vat-->
             <QCard v-if="entity.invoiceInTax.length" class="vat">
-                <VnTitle :url="getLink('vat')" :text="t('InvoiceIn.card.vat')" />
+                <VnTitle :url="getLink('vat')" :text="t('invoicein.card.vat')" />
                 <QTable
                     :columns="vatColumns"
                     :rows="entity.invoiceInTax"
@@ -362,7 +366,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             </QCard>
             <!--Due Day-->
             <QCard v-if="entity.invoiceInDueDay.length" class="due-day">
-                <VnTitle :url="getLink('due-day')" :text="t('InvoiceIn.card.dueDay')" />
+                <VnTitle :url="getLink('due-day')" :text="t('invoicein.card.dueDay')" />
                 <QTable :columns="dueDayColumns" :rows="entity.invoiceInDueDay" flat>
                     <template #header="dueDayProps">
                         <QTr :props="dueDayProps" class="bg">
@@ -400,7 +404,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             <QCard v-if="entity.invoiceInIntrastat.length">
                 <VnTitle
                     :url="getLink('intrastat')"
-                    :text="t('InvoiceIn.card.intrastat')"
+                    :text="t('invoicein.card.intrastat')"
                 />
                 <QTable
                     :columns="intrastatColumns"
diff --git a/src/pages/InvoiceIn/InvoiceInCreate.vue b/src/pages/InvoiceIn/InvoiceInCreate.vue
index 200997f6517..f180410aaa2 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.list.supplierRef')"
+                        :label="t('invoicein.list.supplierRef')"
                         v-model="data.supplierRef"
                     />
                 </VnRow>
@@ -97,10 +97,10 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
                         map-options
                         hide-selected
                         :required="true"
-                        :rules="validate('InvoiceIn.companyFk')"
+                        :rules="validate('invoicein.companyFk')"
                     />
                     <VnInputDate
-                        :label="t('InvoiceIn.summary.issued')"
+                        :label="t('invoicein.summary.issued')"
                         v-model="data.issued"
                     />
                 </VnRow>
diff --git a/src/pages/InvoiceIn/InvoiceInFilter.vue b/src/pages/InvoiceIn/InvoiceInFilter.vue
index 6259030e0db..31a611936ab 100644
--- a/src/pages/InvoiceIn/InvoiceInFilter.vue
+++ b/src/pages/InvoiceIn/InvoiceInFilter.vue
@@ -164,7 +164,7 @@ function handleDaysAgo(params, daysAgo) {
             <QItem>
                 <QItemSection>
                     <QCheckbox
-                        :label="$t('InvoiceIn.isBooked')"
+                        :label="$t('invoicein.isBooked')"
                         v-model="params.isBooked"
                         @update:model-value="searchFn()"
                         toggle-indeterminate
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index 2d8fb2989a4..5e80ae652ca 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -26,7 +26,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'isBooked',
-        label: t('InvoiceIn.isBooked'),
+        label: t('invoicein.isBooked'),
         columnFilter: false,
     },
     {
@@ -41,7 +41,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'supplierFk',
-        label: t('InvoiceIn.list.supplier'),
+        label: t('invoicein.list.supplier'),
         columnFilter: {
             component: 'select',
             attrs: {
@@ -55,16 +55,16 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'supplierRef',
-        label: t('InvoiceIn.list.supplierRef'),
+        label: t('invoicein.list.supplierRef'),
     },
     {
         align: 'left',
         name: 'serial',
-        label: t('InvoiceIn.serial'),
+        label: t('invoicein.serial'),
     },
     {
         align: 'left',
-        label: t('InvoiceIn.list.issued'),
+        label: t('invoicein.list.issued'),
         name: 'issued',
         component: null,
         columnFilter: {
@@ -74,7 +74,7 @@ const cols = computed(() => [
     },
     {
         align: 'left',
-        label: t('InvoiceIn.list.dueDated'),
+        label: t('invoicein.list.dueDated'),
         name: 'dueDated',
         component: null,
         columnFilter: {
@@ -86,12 +86,12 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'awbCode',
-        label: t('InvoiceIn.list.awb'),
+        label: t('invoicein.list.awb'),
     },
     {
         align: 'left',
         name: 'amount',
-        label: t('InvoiceIn.list.amount'),
+        label: t('invoicein.list.amount'),
         format: ({ amount }) => toCurrency(amount),
         cardVisible: true,
     },
@@ -182,7 +182,7 @@ const cols = computed(() => [
                 </template>
             </VnSelect>
             <VnInput
-                :label="t('InvoiceIn.list.supplierRef')"
+                :label="t('invoicein.list.supplierRef')"
                 v-model="data.supplierRef"
             />
             <VnSelect
@@ -194,7 +194,7 @@ const cols = computed(() => [
                 option-label="code"
                 :required="true"
             />
-            <VnInputDate :label="t('InvoiceIn.summary.issued')" v-model="data.issued" />
+            <VnInputDate :label="t('invoicein.summary.issued')" v-model="data.issued" />
         </template>
     </VnTable>
 </template>
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index 3723a0f05e7..94db50066aa 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -1,4 +1,4 @@
-InvoiceIn:
+invoicein:
     serial: Serial
     isBooked: Is booked
     list:
@@ -12,6 +12,26 @@ InvoiceIn:
         amount: Amount
     descriptor:
         ticketList: Ticket list
+    descriptorMenu:
+        book: Book
+        unbook: Unbook
+        delete: Delete
+        clone: Clone
+        toBook: To book
+        toUnbook: To unbook
+        deleteInvoice: Delete invoice
+        invoiceDeleted: invoice deleted
+        cloneInvoice: Clone invoice
+        invoiceCloned: Invoice cloned
+        showAgriculturalPdf: Show agricultural receipt as PDF
+        sendAgriculturalPdf: Send agricultural receipt as PDF
+        checkSendInvoice: Are you sure you want to send it?
+        sendPdfInvoice: Send PDF invoice
+        createCorrective: Create rectificative invoice
+        correctiveInvoice: Rectificative invoice
+        originalInvoice: Original invoice
+        entry: Entry
+        emailEmpty: The email can't be empty
     card:
         client: Client
         company: Company
@@ -46,8 +66,6 @@ InvoiceIn:
         search: Id or supplier name
         correctedFk: Corrected
         isBooked: Is booked
-invoicein:
-    params:
         account: Ledger account
         correctingFk: Rectificative
         
\ No newline at end of file
diff --git a/src/pages/InvoiceIn/locale/es.yml b/src/pages/InvoiceIn/locale/es.yml
index 5637605f6bc..bcb9c05516f 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -1,4 +1,4 @@
-InvoiceIn:
+invoicein:
     serial: Serie
     isBooked: Contabilizada
     list:
@@ -12,6 +12,26 @@ InvoiceIn:
         amount: Importe
     descriptor:
         ticketList: Listado de tickets
+    descriptorMenu:
+        book: Asentar
+        unbook: Desasentar
+        delete: Eliminar
+        clone: Clonar
+        toBook: Contabilizar
+        toUnbook: Descontabilizar
+        deleteInvoice: Eliminar factura
+        invoiceDeleted: Factura eliminada
+        cloneInvoice: Clonar factura
+        invoiceCloned: Factura clonada
+        showAgriculturalPdf: Ver recibo agrícola como PDF
+        sendAgriculturalPdf: Enviar recibo agrícola como PDF
+        checkSendInvoice: ¿Estás seguro que quieres enviarlo?
+        sendPdfInvoice: Enviar factura a PDF
+        createCorrective: Crear factura rectificativa
+        correctiveInvoice: Factura rectificativa
+        originalInvoice: Factura origen
+        entry: Entrada
+        emailEmpty: El email no puede estar vacío
     card:
         client: Cliente
         company: Empresa
@@ -43,8 +63,6 @@ InvoiceIn:
     params:
         search: Id o nombre proveedor
         correctedFk: Rectificada
-invoicein:
-    params:
         account: Cuenta contable
         correctingFk: Rectificativa
-        
+
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
index 81b3e7c41aa..3ceb447dd23 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutSummary.vue
@@ -10,6 +10,7 @@ import { getUrl } from 'src/composables/getUrl';
 import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
 
 onMounted(async () => {
     fetch();
@@ -113,6 +114,9 @@ const ticketsColumns = ref([
         <template #header="{ entity: { invoiceOut } }">
             <div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
         </template>
+        <template #menu="{ entity }">
+            <InvoiceOutDescriptorMenu :invoice-out-data="entity.invoiceOut" />
+        </template>
         <template #body="{ entity: { invoiceOut } }">
             <QCard class="vn-one">
                 <VnTitle :text="t('globals.pageTitles.basicData')" />
diff --git a/src/pages/InvoiceOut/InvoiceOutList.vue b/src/pages/InvoiceOut/InvoiceOutList.vue
index 48d61201c5c..09873642d3c 100644
--- a/src/pages/InvoiceOut/InvoiceOutList.vue
+++ b/src/pages/InvoiceOut/InvoiceOutList.vue
@@ -355,7 +355,7 @@ watchEffect(selectedRows);
                         <VnSelect
                             url="InvoiceOutSerials"
                             v-model="data.serial"
-                            :label="t('InvoiceIn.serial')"
+                            :label="t('invoicein.serial')"
                             :options="invoiceOutSerialsOptions"
                             option-label="description"
                             option-value="code"
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index 4705525fb69..c6fee8540ef 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -6,17 +6,16 @@ import { useI18n } from 'vue-i18n';
 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 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 { dashIfEmpty } from 'src/filters';
 import { useArrayData } from 'src/composables/useArrayData';
-import { cloneItem } from 'src/pages/Item/composables/cloneItem';
+import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
-        type: [Number, String],
+        type: Number,
         required: false,
         default: null,
     },
@@ -29,7 +28,7 @@ const $props = defineProps({
         default: null,
     },
     saleFk: {
-        type: [Number, String],
+        type: Number,
         default: null,
     },
     warehouseFk: {
@@ -38,7 +37,6 @@ const $props = defineProps({
     },
 });
 
-const { openCloneDialog } = cloneItem();
 const route = useRoute();
 const { t } = useI18n();
 const warehouseConfig = ref(null);
@@ -46,7 +44,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const regularizeStockFormDialog = ref(null);
 const mounted = ref();
 
 const arrayDataStock = useArrayData('descriptorStock', {
@@ -61,14 +58,14 @@ onMounted(async () => {
 const data = ref(useCardDescription());
 const setData = async (entity) => {
     if (!entity) return;
-    data.value = useCardDescription(entity?.name, entity?.id);
+    data.value = useCardDescription(entity.name, entity.id);
     await updateStock();
 };
 
 const getItemConfigs = async () => {
     const { data } = await axios.get('ItemConfigs/findOne');
     if (!data) return;
-    return (warehouseConfig.value = data.warehouseFk);
+    warehouseConfig.value = data.warehouseFk;
 };
 const updateStock = async () => {
     if (!mounted.value) return;
@@ -89,10 +86,6 @@ const updateStock = async () => {
     if (storeData?.itemFk == entityId.value) return;
     await stock.fetch({});
 };
-
-const openRegularizeStockForm = () => {
-    regularizeStockFormDialog.value.show();
-};
 </script>
 
 <template>
@@ -105,24 +98,12 @@ const openRegularizeStockForm = () => {
         :url="`Items/${entityId}/getCard`"
         @on-fetch="setData"
     >
-        <template #menu="{}">
-            <QItem v-ripple clickable @click="openRegularizeStockForm()">
-                <QItemSection>
-                    {{ t('Regularize stock') }}
-                    <QDialog ref="regularizeStockFormDialog">
-                        <RegularizeStockForm
-                            :item-fk="entityId"
-                            :warehouse-fk="warehouseFk"
-                            @on-data-saved="updateStock()"
-                        />
-                    </QDialog>
-                </QItemSection>
-            </QItem>
-            <QItem v-ripple clickable @click="openCloneDialog(entityId)">
-                <QItemSection>
-                    {{ t('globals.clone') }}
-                </QItemSection>
-            </QItem>
+        <template #menu>
+            <ItemDescriptorMenu
+                :entity-id="entityId"
+                :warehouse-fk="warehouseFk"
+                @regularized="updateStock"
+            />
         </template>
         <template #before>
             <ItemDescriptorImage
@@ -191,7 +172,6 @@ const openRegularizeStockForm = () => {
 
 <i18n>
 es:
-    Regularize stock: Regularizar stock
     Inactive article: Artículo inactivo
 </i18n>
 
diff --git a/src/pages/Item/Card/ItemDescriptorImage.vue b/src/pages/Item/Card/ItemDescriptorImage.vue
index 05185c5891b..a887964e978 100644
--- a/src/pages/Item/Card/ItemDescriptorImage.vue
+++ b/src/pages/Item/Card/ItemDescriptorImage.vue
@@ -131,7 +131,6 @@ const handlePhotoUpdated = (evt = false) => {
 
 <i18n>
 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: Calculado sobre el almacén de { warehouseName }
diff --git a/src/pages/Item/Card/ItemDescriptorMenu.vue b/src/pages/Item/Card/ItemDescriptorMenu.vue
new file mode 100644
index 00000000000..3e9c6f2d4ce
--- /dev/null
+++ b/src/pages/Item/Card/ItemDescriptorMenu.vue
@@ -0,0 +1,44 @@
+<script setup>
+import RegularizeStockForm from 'components/RegularizeStockForm.vue';
+import { cloneItem } from 'src/pages/Item/composables/cloneItem';
+
+const { openCloneDialog } = cloneItem();
+
+defineProps({
+    entityId: {
+        type: Number,
+        default: null,
+    },
+    warehouseFk: {
+        type: Number,
+        default: null,
+    },
+});
+
+defineEmits(['regularized']);
+</script>
+<template>
+    <QItem v-ripple clickable @click="$refs.regularizeStockFormDialog.show()">
+        <QItemSection>
+            {{ $t('item.regularizeStock') }}
+            <QDialog ref="regularizeStockFormDialog">
+                <RegularizeStockForm
+                    :item-fk="entityId"
+                    :warehouse-fk="warehouseFk"
+                    @on-data-saved="$emit('regularized')"
+                />
+            </QDialog>
+        </QItemSection>
+    </QItem>
+    <QItem v-ripple clickable @click="openCloneDialog(entityId)">
+        <QItemSection>
+            {{ $t('globals.clone') }}
+        </QItemSection>
+    </QItem>
+</template>
+
+<style lang="scss" scoped>
+.weekdaysBtn {
+    margin: 1%;
+}
+</style>
diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index e1b97d7c994..bc828bbf64c 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -8,6 +8,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
 import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -43,10 +44,13 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
         <template #header="{ entity: { item } }">
             {{ item.id }} - {{ item.name }}
         </template>
+        <template #menu>
+            <ItemDescriptorMenu :entity-id="entityId" :warehouse-fk="warehouseFk" />
+        </template>
         <template #body="{ entity: { item, tags, visible, available, botanical } }">
             <QCard class="vn-one photo">
                 <ItemDescriptorImage
-                    :entity-id="Number(entityId)"
+                    :entity-id="entityId"
                     :visible="visible"
                     :available="available"
                     :show-edit-button="false"
@@ -89,7 +93,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('item.summary.otherData')"
                 />
                 <VnLv
                     :label="t('item.summary.intrastatCode')"
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index 1d6e6933953..f04563791d5 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -152,7 +152,7 @@ const columns = computed(() => [
         },
         columnField: {
             component: null,
-        }
+        },
     },
     {
         label: t('item.list.category'),
@@ -498,5 +498,4 @@ es:
     Create Item: Crear artículo
     You can search by id: Puedes buscar por id
     Preview: Vista previa
-    Regularize stock: Regularizar stock
 </i18n>
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index 4447d1bcfb7..d96fbca2f57 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -172,24 +172,22 @@ const changeQuantity = async (request) => {
         };
 
         await axios.patch(`Sales/${request.saleFk}`, params);
-        notify(t('globals.dataSaved'), 'positive');
-        confirmRequest(request);
-    } else confirmRequest(request);
+    }
+    await confirmRequest(request);
+    notify(t('globals.dataSaved'), 'positive');
 };
 
 const confirmRequest = async (request) => {
-    if (request.itemFk && request.saleQuantity) {
-        const params = {
-            itemFk: request.itemFk,
-            quantity: request.saleQuantity,
-            attenderFk: request.attenderFk,
-        };
+    if (!request.itemFk || !request.saleQuantity) return;
+    const params = {
+        itemFk: request.itemFk,
+        quantity: request.saleQuantity,
+        attenderFk: request.attenderFk,
+    };
 
-        const { data } = await axios.post(`TicketRequests/${request.id}/confirm`, params);
-        request.itemDescription = data.concept;
-        request.isOk = true;
-        notify(t('globals.dataSaved'), 'positive');
-    }
+    const { data } = await axios.post(`TicketRequests/${request.id}/confirm`, params);
+    request.itemDescription = data.concept;
+    request.isOk = true;
 };
 
 const getState = (isOk) => {
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index c4ad0f5370a..907c72acd89 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -219,3 +219,4 @@ item:
         minSalesQuantity: 'Cantidad mínima de venta'
         genus: 'Genus'
         specie: 'Specie'
+    regularizeStock: Regularize stock
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index d558c38a648..015dea4dd63 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -210,6 +210,7 @@ item:
         minSalesQuantity: 'Cantidad mínima de venta'
         genus: 'Genus'
         specie: 'Specie'
+    regularizeStock: Regularizar stock
     buyRequest:
         ticketId: 'ID Ticket'
         shipped: 'F. envío'
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index e0c613aedc1..0d5f0146f7b 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -9,7 +9,6 @@ import useCardDescription from 'src/composables/useCardDescription';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import FetchData from 'components/FetchData.vue';
-import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
 
 const DEFAULT_ITEMS = 0;
@@ -94,9 +93,6 @@ const total = ref(0);
         @on-fetch="setData"
         data-key="orderData"
     >
-        <template #menu="{ entity }">
-            <OrderDescriptorMenu :order="entity" />
-        </template>
         <template #body="{ entity }">
             <VnLv
                 :label="t('globals.state')"
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index ad06dfe43c1..a289688e47e 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import FetchedTags from 'components/ui/FetchedTags.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
 
 const { t } = useI18n();
 const route = useRoute();
@@ -91,6 +92,9 @@ async function handleConfirm() {
                     <QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
                 </QBtn>
             </template>
+            <template #menu="{ entity }">
+                <OrderDescriptorMenu :order="entity" />
+            </template>
             <template #body="{ entity }">
                 <QCard class="vn-one">
                     <VnTitle
diff --git a/src/pages/Route/Card/RouteDescriptorMenu.vue b/src/pages/Route/Card/RouteDescriptorMenu.vue
index 6092bcd9577..d1a70c86879 100644
--- a/src/pages/Route/Card/RouteDescriptorMenu.vue
+++ b/src/pages/Route/Card/RouteDescriptorMenu.vue
@@ -52,7 +52,7 @@ async function actualizeVolume() {
     const params = { isOk: true };
     await axios.post(`Routes/${routeId}/updateVolume`, params);
     quasar.notify({
-        message: t('globals.dataUpdated'),
+        message: t('globals.dataSaved'),
         type: 'positive',
     });
 }
diff --git a/src/pages/Route/Card/RouteSummary.vue b/src/pages/Route/Card/RouteSummary.vue
index a0b9711956b..3051972b25d 100644
--- a/src/pages/Route/Card/RouteSummary.vue
+++ b/src/pages/Route/Card/RouteSummary.vue
@@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import RouteDescriptorMenu from './RouteDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -128,6 +129,9 @@ const ticketColumns = ref([
             <template #header="{ entity }">
                 <span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span>
             </template>
+            <template #menu="{ entity }">
+                <RouteDescriptorMenu :route="entity.route" />
+            </template>
             <template #body="{ entity }">
                 <QCard class="vn-max">
                     <VnTitle
diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue
index 3fb36b4f7c3..1fbb1897d5b 100644
--- a/src/pages/Route/Roadmap/RoadmapSummary.vue
+++ b/src/pages/Route/Roadmap/RoadmapSummary.vue
@@ -10,6 +10,7 @@ import VnTitle from 'src/components/common/VnTitle.vue';
 import CardSummary from 'components/ui/CardSummary.vue';
 import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
 import VnLinkPhone from 'components/ui/VnLinkPhone.vue';
+import RoadmapDescriptorMenu from './RoadmapDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -86,6 +87,9 @@ const filter = {
             <template #header="{ entity }">
                 <span>{{ `${entity?.id} - ${entity?.name}` }}</span>
             </template>
+            <template #menu="{ entity }">
+                <RoadmapDescriptorMenu :route="entity" />
+            </template>
             <template #body="{ entity }">
                 <QCard class="vn-one">
                     <VnTitle
diff --git a/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue b/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue
index 16351fdd42c..447737e9ce8 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptorMenu.vue
@@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import { useRouter } from 'vue-router';
 import VnConfirm from 'components/ui/VnConfirm.vue';
+import { useRoute } from 'vue-router';
 
 const $props = defineProps({
     shelving: {
@@ -14,8 +15,11 @@ const $props = defineProps({
 
 const router = useRouter();
 const quasar = useQuasar();
+const route = useRoute();
 const { t } = useI18n();
 
+const emit = defineEmits(['onRemove']);
+
 function confirmRemove() {
     quasar.dialog({
         component: VnConfirm,
@@ -32,11 +36,12 @@ async function remove() {
         return;
     }
     await axios.delete(`Shelvings/${$props.shelving.id}`);
-    await router.push({ name: 'ShelvingList' });
+    if (route.name != 'ShelvingList') await router.push({ name: 'ShelvingList' });
     quasar.notify({
         message: t('globals.dataDeleted'),
         type: 'positive',
     });
+    emit('onRemove', {});
 }
 </script>
 <template>
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index 0c1eb2a1df8..39fa4639f23 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -1,10 +1,11 @@
 <script setup>
-import { computed } from 'vue';
+import { computed, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import VnUserLink from 'components/ui/VnUserLink.vue';
+import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -14,7 +15,7 @@ const $props = defineProps({
 });
 const route = useRoute();
 const { t } = useI18n();
-
+const summary = ref({});
 const entityId = computed(() => $props.id || route.params.id);
 
 const filter = {
@@ -43,7 +44,13 @@ const filter = {
             data-key="ShelvingSummary"
         >
             <template #header="{ entity }">
-                <div>{{ entity.id }} - {{ entity.code }}</div>
+                <div>{{ entity.code }}</div>
+            </template>
+            <template #menu="{ entity }">
+                <ShelvingDescriptorMenu
+                    :shelving="entity"
+                    @on-remove="$refs.summary.fetch()"
+                />
             </template>
             <template #body="{ entity }">
                 <QCard class="vn-one">
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 2f5f69e1cec..2c6e34864e5 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -96,7 +96,6 @@ function toTicketUrl(section) {
         ref="summaryRef"
         :url="`Tickets/${entityId}/summary`"
         data-key="TicketSummary"
-        data-cy="ticketSummary"
     >
         <template #header-left>
             <VnToSummary
@@ -114,7 +113,7 @@ function toTicketUrl(section) {
                 {{ entity.nickname }}
             </div>
         </template>
-        <template #header-right="{ entity }">
+        <template #header-right>
             <div>
                 <QBtnDropdown
                     ref="stateBtnDropdownRef"
@@ -133,18 +132,11 @@ function toTicketUrl(section) {
                         @update:model-value="changeState"
                     />
                 </QBtnDropdown>
-                <QBtn color="white" dense flat icon="more_vert" round size="md">
-                    <QTooltip>
-                        {{ t('components.cardDescriptor.moreOptions') }}
-                    </QTooltip>
-                    <QMenu>
-                        <QList>
-                            <TicketDescriptorMenu :ticket="entity" />
-                        </QList>
-                    </QMenu>
-                </QBtn>
             </div>
         </template>
+        <template #menu="{ entity }">
+            <TicketDescriptorMenu :ticket="entity" />
+        </template>
         <template #body="{ entity }">
             <QCard class="vn-one">
                 <VnTitle
@@ -258,7 +250,7 @@ function toTicketUrl(section) {
             <QCard class="vn-one" v-if="entity.notes.length">
                 <VnTitle
                     :url="toTicketUrl('observation')"
-                    :text="t('globals.pageTitles.notes')"
+                    :text="t('ticket.pageTitles.notes')"
                 />
                 <QVirtualScroll
                     :items="entity.notes"
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 59c3a8a91fc..9deb2280858 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -11,6 +11,7 @@ import FetchData from 'src/components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import { toDate, toCurrency } from 'src/filters';
 import axios from 'axios';
+import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
 
 const $props = defineProps({
     id: {
@@ -242,7 +243,9 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
         <template #header>
             <span>{{ travel.id }} - {{ travel.ref }}</span>
         </template>
-
+        <template #menu="{ entity }">
+            <TravelDescriptorMenuItems :travel="entity" />
+        </template>
         <template #body>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index f09aec81607..c09e8868f9a 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -6,11 +6,10 @@ import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
 import VnChangePassword from 'src/components/common/VnChangePassword.vue';
-import { useState } from 'src/composables/useState';
 import axios from 'axios';
 import VnImg from 'src/components/ui/VnImg.vue';
 import EditPictureForm from 'components/EditPictureForm.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -28,8 +27,6 @@ const image = ref(null);
 
 const route = useRoute();
 const { t } = useI18n();
-const state = useState();
-const user = state.getUser();
 const showEditPhotoForm = ref(false);
 const toggleEditPictureForm = () => {
     showEditPhotoForm.value = !showEditPhotoForm.value;
@@ -45,18 +42,6 @@ const getIsExcluded = async () => {
     workerExcluded.value = data.exists;
 };
 
-const handleExcluded = async () => {
-    if (workerExcluded.value)
-        await axios.delete(`WorkerDisableExcludeds/${entityId.value}`);
-    else
-        await axios.post(`WorkerDisableExcludeds`, {
-            workerFk: entityId.value,
-            dated: new Date(),
-        });
-
-    workerExcluded.value = !workerExcluded.value;
-};
-
 const handlePhotoUpdated = (evt = false) => {
     image.value.reload(evt);
 };
@@ -72,25 +57,11 @@ const handlePhotoUpdated = (evt = false) => {
         @on-fetch="getIsExcluded"
     >
         <template #menu="{ entity }">
-            <QItem v-ripple clickable @click="handleExcluded">
-                <QItemSection>
-                    {{
-                        workerExcluded
-                            ? t('Click to allow the user to be disabled')
-                            : t('Click to exclude the user from getting disabled')
-                    }}
-                </QItemSection>
-            </QItem>
-            <QItem
-                v-if="!entity.user.emailVerified && user.id != entity.id"
-                v-ripple
-                clickable
-                @click="$refs.changePassRef.show"
-            >
-                <QItemSection>
-                    {{ t('globals.changePass') }}
-                </QItemSection>
-            </QItem>
+            <WorkerDescriptorMenu
+                :worker="entity"
+                :is-excluded="workerExcluded"
+                @show-dialog="$refs.changePassRef.show"
+            />
         </template>
         <template #before>
             <div class="relative-position">
@@ -144,14 +115,10 @@ const handlePhotoUpdated = (evt = false) => {
                 :value="entity.user?.emailUser?.email"
                 copy
             />
-            <VnLv :label="t('worker.list.department')">
-                <template #value>
-                        <span class="link" v-text="entity.department?.department?.name" />
-                        <DepartmentDescriptorProxy
-                            :id="entity.department?.department?.id"
-                        />
-                </template>
-            </VnLv>
+            <VnLv
+                :label="t('worker.list.department')"
+                :value="entity.department ? entity.department.department.name : null"
+            />
             <VnLv :value="entity.phone">
                 <template #label>
                     {{ t('globals.phone') }}
@@ -211,8 +178,6 @@ const handlePhotoUpdated = (evt = false) => {
 
 <i18n>
 es:
-    Go to client: Ir a cliente
-    Go to user: Ir al usuario
     Click to allow the user to be disabled: Marcar para deshabilitar
     Click to exclude the user from getting disabled: Marcar para no deshabilitar
 </i18n>
diff --git a/src/pages/Worker/Card/WorkerDescriptorMenu.vue b/src/pages/Worker/Card/WorkerDescriptorMenu.vue
new file mode 100644
index 00000000000..8d82dc839f7
--- /dev/null
+++ b/src/pages/Worker/Card/WorkerDescriptorMenu.vue
@@ -0,0 +1,65 @@
+<script setup>
+import { computed, ref, toRefs } from 'vue';
+import axios from 'axios';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
+
+const $props = defineProps({
+    worker: {
+        type: Object,
+        required: true,
+    },
+    isExcluded: {
+        type: Boolean,
+        required: true,
+    },
+});
+const route = useRoute();
+const { t } = useI18n();
+const state = useState();
+const user = state.getUser();
+const { worker } = toRefs($props);
+const workerExcluded = ref($props.isExcluded);
+const entityId = computed(() => {
+    return $props.worker.id || route.params.id;
+});
+const emit = defineEmits(['show-dialog']);
+const handleExcluded = async () => {
+    if (workerExcluded.value)
+        await axios.delete(`WorkerDisableExcludeds/${entityId.value}`);
+    else
+        await axios.post(`WorkerDisableExcludeds`, {
+            workerFk: entityId.value,
+            dated: new Date(),
+        });
+
+    workerExcluded.value = !workerExcluded.value;
+};
+
+const showChangePasswordDialog = () => {
+    emit('show-dialog', true);
+};
+</script>
+
+<template>
+    <QItem v-ripple clickable @click="handleExcluded">
+        <QItemSection>
+            {{
+                workerExcluded
+                    ? t('Click to allow the user to be disabled')
+                    : t('Click to exclude the user from getting disabled')
+            }}
+        </QItemSection>
+    </QItem>
+    <QItem
+        v-if="!worker.user.emailVerified && user.id == worker.id"
+        v-ripple
+        clickable
+        @click="showChangePasswordDialog"
+    >
+        <QItemSection>
+            {{ t('globals.changePass') }}
+        </QItemSection>
+    </QItem>
+</template>
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 496f1ca165f..bfb503f6b7f 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -11,6 +11,7 @@ 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 { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
+import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -42,6 +43,9 @@ onBeforeMount(async () => {
         <template #header="{ entity }">
             <div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
         </template>
+        <template #menu="{ entity }">
+            <WorkerDescriptorMenu :worker="entity" :is-excluded="workerExcluded" />
+        </template>
         <template #body="{ entity: worker }">
             <QCard class="vn-one">
                 <VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
diff --git a/src/pages/Zone/Card/ZoneBasicData.vue b/src/pages/Zone/Card/ZoneBasicData.vue
index 2d65476cea3..c38da614c9f 100644
--- a/src/pages/Zone/Card/ZoneBasicData.vue
+++ b/src/pages/Zone/Card/ZoneBasicData.vue
@@ -100,6 +100,16 @@ const agencyOptions = ref([]);
                     required="true"
                     clearable
                 />
+                <VnInput
+                    v-model="data.priceOptimum"
+                    :label="t('Price optimum')"
+                    type="number"
+                    min="0"
+                    required="true"
+                    clearable
+                />
+            </VnRow>
+            <VnRow>
                 <VnInput
                     v-model="data.bonus"
                     :label="t('Bonus')"
@@ -107,8 +117,6 @@ const agencyOptions = ref([]);
                     min="0"
                     clearable
                 />
-            </VnRow>
-            <VnRow>
                 <VnSelect
                     :label="t('Distribution point')"
                     v-model="data.addressFk"
@@ -152,6 +160,7 @@ es:
     Traveling days: Dias de viaje
     Closing: Cierre
     Price: Precio
+    Price optimum: Precio óptimo
     Bonus: Bonificación
     Inflation: Inflación
     Volumetric: Volumétrico
diff --git a/src/pages/Zone/Card/ZoneEventInclusionForm.vue b/src/pages/Zone/Card/ZoneEventInclusionForm.vue
index b4096e5a23e..805d03b2715 100644
--- a/src/pages/Zone/Card/ZoneEventInclusionForm.vue
+++ b/src/pages/Zone/Card/ZoneEventInclusionForm.vue
@@ -182,13 +182,19 @@ onMounted(() => {
                     min="0"
                 />
                 <VnInput
-                    v-model="eventInclusionFormData.bonus"
-                    :label="t('zone.bonus')"
+                    v-model="eventInclusionFormData.priceOptimum"
+                    :label="t('list.priceOptimum')"
                     type="number"
                     min="0"
                 />
             </VnRow>
             <VnRow>
+                <VnInput
+                    v-model="eventInclusionFormData.bonus"
+                    :label="t('zone.bonus')"
+                    type="number"
+                    min="0"
+                />
                 <VnInput
                     v-model="eventInclusionFormData.m3Max"
                     :label="t('zone.m3Max')"
diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
index 384ee1fe945..12480263321 100644
--- a/src/pages/Zone/Card/ZoneSummary.vue
+++ b/src/pages/Zone/Card/ZoneSummary.vue
@@ -11,6 +11,7 @@ import { getUrl } from 'src/composables/getUrl';
 import { toCurrency } from 'filters/index';
 import { toTimeFormat } from 'src/filters/date';
 import axios from 'axios';
+import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -79,6 +80,9 @@ onMounted(async () => {
         <template #header="{ entity }">
             <div>#{{ entity.id }} - {{ entity.name }}</div>
         </template>
+        <template #menu="{ entity }">
+            <ZoneDescriptorMenuItems :zone="entity" />
+        </template>
         <template #body="{ entity: zone }">
             <QCard class="vn-one">
                 <VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
diff --git a/src/pages/Zone/locale/es.yml b/src/pages/Zone/locale/es.yml
index b277ceabb6c..575b12f7af9 100644
--- a/src/pages/Zone/locale/es.yml
+++ b/src/pages/Zone/locale/es.yml
@@ -22,6 +22,7 @@ list:
     agency: Agencia
     close: Cierre
     price: Precio
+    priceOptimum: Precio óptimo
     create: Crear zona
     openSummary: Detalles
     searchZone: Buscar zonas
diff --git a/src/router/modules/claim.js b/src/router/modules/claim.js
index 8b0a7089667..4dfde08dac5 100644
--- a/src/router/modules/claim.js
+++ b/src/router/modules/claim.js
@@ -1,19 +1,12 @@
 import { RouterView } from 'vue-router';
 
-export default {
-    name: 'Claim',
-    path: '/claim',
+const claimCard = {
+    name: 'ClaimCard',
+    path: ':id',
+    component: () => import('src/pages/Claim/Card/ClaimCard.vue'),
+    redirect: { name: 'ClaimSummary' },
     meta: {
-        title: 'claims',
-        icon: 'vn:claims',
-        moduleName: 'Claim',
-        keyBinding: 'r',
-    },
-    component: RouterView,
-    redirect: { name: 'ClaimMain' },
-    menus: {
-        main: ['ClaimList'],
-        card: [
+        menu: [
             'ClaimBasicData',
             'ClaimLines',
             'ClaimPhotos',
@@ -23,109 +16,125 @@ export default {
             'ClaimLog',
         ],
     },
+    children: [
+        {            
+            path: 'summary',
+            name: 'ClaimSummary',
+            meta: {
+                title: 'summary',
+                icon: 'launch',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimSummary.vue'),
+        },
+        {
+            path: 'basic-data',
+            name: 'ClaimBasicData',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+                acls: [{ model: 'Claim', props: 'findById', accessType: 'READ' }],
+            },
+            component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
+        },
+        {
+            path: 'lines',
+            name: 'ClaimLines',
+            meta: {
+                title: 'lines',
+                icon: 'vn:details',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimLines.vue'),
+        },
+        {
+            path: 'photos',
+            name: 'ClaimPhotos',
+            meta: {
+                title: 'photos',
+                icon: 'image',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimPhoto.vue'),
+        },
+        {
+            path: 'notes',
+            name: 'ClaimNotes',
+            meta: {
+                title: 'notes',
+                icon: 'draft',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimNotes.vue'),
+        },
+        {
+            path: 'development',
+            name: 'ClaimDevelopment',
+            meta: {
+                title: 'development',
+                icon: 'vn:traceability',
+                acls: [
+                    {
+                        model: 'ClaimDevelopment',
+                        props: '*',
+                        accessType: 'WRITE',
+                    },
+                ],
+            },
+            component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
+        },
+        {
+            path: 'action',
+            name: 'ClaimAction',
+            meta: {
+                title: 'action',
+                icon: 'vn:actions',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimAction.vue'),
+        },
+        {
+            path: 'log',
+            name: 'ClaimLog',
+            meta: {
+                title: 'log',
+                icon: 'history',
+            },
+            component: () => import('src/pages/Claim/Card/ClaimLog.vue'),
+        },
+    ],
+}
+
+export default {
+    name: 'Claim',
+    path: '/claim',
+    meta: {
+        title: 'claims',
+        icon: 'vn:claims',
+        moduleName: 'Claim',
+        keyBinding: 'r',
+        menu: ['ClaimList'],
+    },
+    component: RouterView,
+    redirect: { name: 'ClaimMain' },
     children: [
         {
             name: 'ClaimMain',
             path: '',
             component: () => import('src/components/common/VnModule.vue'),
-            redirect: { name: 'ClaimList' },
+            redirect: { name: 'ClaimIndexMain' },
             children: [
                 {
-                    name: 'ClaimList',
-                    path: 'list',
-                    meta: {
-                        title: 'list',
-                        icon: 'view_list',
-                    },
+                    path: '',
+                    name: 'ClaimIndexMain',
+                    redirect: { name: 'ClaimList' },
                     component: () => import('src/pages/Claim/ClaimList.vue'),
-                },
-            ],
-        },
-        {
-            name: 'ClaimCard',
-            path: ':id',
-            component: () => import('src/pages/Claim/Card/ClaimCard.vue'),
-            redirect: { name: 'ClaimSummary' },
-            children: [
-                {
-                    name: 'ClaimSummary',
-                    path: 'summary',
-                    meta: {
-                        title: 'summary',
-                        icon: 'launch',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimSummary.vue'),
-                },
-                {
-                    name: 'ClaimBasicData',
-                    path: 'basic-data',
-                    meta: {
-                        title: 'basicData',
-                        icon: 'vn:settings',
-                        acls: [{ model: 'Claim', props: 'findById', accessType: 'READ' }],
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
-                },
-                {
-                    name: 'ClaimLines',
-                    path: 'lines',
-                    meta: {
-                        title: 'lines',
-                        icon: 'vn:details',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimLines.vue'),
-                },
-                {
-                    name: 'ClaimPhotos',
-                    path: 'photos',
-                    meta: {
-                        title: 'photos',
-                        icon: 'image',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimPhoto.vue'),
-                },
-                {
-                    name: 'ClaimNotes',
-                    path: 'notes',
-                    meta: {
-                        title: 'notes',
-                        icon: 'draft',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimNotes.vue'),
-                },
-                {
-                    name: 'ClaimDevelopment',
-                    path: 'development',
-                    meta: {
-                        title: 'development',
-                        icon: 'vn:traceability',
-                        acls: [
-                            {
-                                model: 'ClaimDevelopment',
-                                props: '*',
-                                accessType: 'WRITE',
+                    children: [
+                        {
+                            name: 'ClaimList',
+                            path: 'list',
+                            meta: {
+                                title: 'list',
+                                icon: 'view_list',
                             },
-                        ],
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
-                },
-                {
-                    name: 'ClaimAction',
-                    path: 'action',
-                    meta: {
-                        title: 'action',
-                        icon: 'vn:actions',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimAction.vue'),
-                },
-                {
-                    name: 'ClaimLog',
-                    path: 'log',
-                    meta: {
-                        title: 'log',
-                        icon: 'history',
-                    },
-                    component: () => import('src/pages/Claim/Card/ClaimLog.vue'),
+                        },
+                        claimCard,
+                    ],
                 },
             ],
         },
diff --git a/src/stores/invoiceOutGlobal.js b/src/stores/invoiceOutGlobal.js
index cc8d86ea8a1..d8649753f3a 100644
--- a/src/stores/invoiceOutGlobal.js
+++ b/src/stores/invoiceOutGlobal.js
@@ -10,7 +10,6 @@ const { notify } = useNotify();
 
 export const useInvoiceOutGlobalStore = defineStore({
     id: 'invoiceOutGlobal',
-
     state: () => ({
         initialDataLoading: true,
         formInitialData: {
@@ -33,6 +32,7 @@ export const useInvoiceOutGlobalStore = defineStore({
         nRequests: 0,
         nPdfs: 0,
         totalPdfs: 0,
+        formData: null,
     }),
     actions: {
         async init() {
@@ -93,8 +93,6 @@ export const useInvoiceOutGlobalStore = defineStore({
         },
 
         async makeInvoice(formData, clientsToInvoice) {
-            this.invoicing = true;
-            const promises = [];
             try {
                 this.printer = formData.printer;
                 const params = {
@@ -119,11 +117,12 @@ export const useInvoiceOutGlobalStore = defineStore({
                     );
                     throw new Error("There aren't addresses to invoice");
                 }
+                this.invoicing = false;
                 this.status = 'invoicing';
-                for (let index = 0; index < this.parallelism; index++) {
-                    promises.push(this.invoiceClient(formData, index));
-                }
-                await Promise.all(promises);
+                this.formData = formData;
+                this.addressIndex = 0;
+                this.errors = [];
+                await this.invoiceClient();
             } catch (err) {
                 this.handleError(err);
             }
@@ -182,45 +181,42 @@ export const useInvoiceOutGlobalStore = defineStore({
             }
         },
 
-        async invoiceClient(formData, index) {
-            const address = this.addresses[index];
+        async invoiceClient() {
+            if (this.invoicing || this.nRequests >= this.parallelism) return;
+            const address = this.addresses[this.addressIndex];
+
             if (!address || !this.status || this.status == 'stopping') {
                 this.status = 'stopping';
                 this.invoicing = false;
                 return;
             }
             try {
+                this.invoicing = true;
                 const params = {
                     clientId: address.clientId,
                     addressId: address.id,
-                    invoiceDate: new Date(formData.invoiceDate),
-                    maxShipped: new Date(formData.maxShipped),
-                    companyFk: formData.companyFk,
-                    serialType: formData.serialType,
+                    invoiceDate: new Date(this.formData.invoiceDate),
+                    maxShipped: new Date(this.formData.maxShipped),
+                    companyFk: this.formData.companyFk,
+                    serialType: this.formData.serialType,
                 };
 
-                this.invoicing = true;
-
                 const { data } = await axios.post('InvoiceOuts/invoiceClient', params);
-
-                if (data) await this.makePdfAndNotify(data, address);
-                this.isInvoicing = false;
+                if (data) this.makePdfAndNotify(data, address);
             } catch (err) {
                 if (err?.response?.status >= 400 && err?.response?.status < 500) {
                     this.invoiceClientError(address, err.response?.data?.error?.message);
                     return;
                 } else {
-                    this.invoicing = false;
                     notify(
                         'invoiceOut.globalInvoices.errors.criticalInvoiceError',
                         'negative'
                     );
-                    throw new Error('Critical invoicing error, process stopped');
                 }
             } finally {
+                this.invoicing = false;
                 this.addressIndex++;
-                if (this.status != 'stopping')
-                    await this.invoiceClient(formData, this.addressIndex);
+                this.invoiceClient();
             }
         },
 
@@ -231,9 +227,11 @@ export const useInvoiceOutGlobalStore = defineStore({
                 const params = { printerFk: this.printer };
                 await axios.post(`InvoiceOuts/${invoiceId}/makePdfAndNotify`, params);
                 this.nPdfs++;
-                this.nRequests--;
             } catch (err) {
                 this.invoiceClientError(client, err.response?.data?.error?.message, true);
+            } finally {
+                this.nRequests--;
+                this.invoiceClient();
             }
         },
 
diff --git a/test/cypress/integration/invoiceIn/invoiceInCorrective.spec.js b/test/cypress/integration/invoiceIn/invoiceInCorrective.spec.js
index a64f98c107f..0eb8733551e 100644
--- a/test/cypress/integration/invoiceIn/invoiceInCorrective.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInCorrective.spec.js
@@ -1,7 +1,7 @@
 /// <reference types="cypress" />
 
 describe('InvoiceInCorrective', () => {
-    const createRectificative = '.q-menu > .q-list > :nth-child(6) > .q-item__section';
+    const createCorrective = '.q-menu > .q-list > :nth-child(6) > .q-item__section';
     const rectificativeSection = '.q-drawer-container .q-list > a:nth-child(6)';
     const saveDialog = '.q-card > .q-card__actions > .q-btn--standard ';
 
@@ -13,7 +13,7 @@ describe('InvoiceInCorrective', () => {
 
         cy.openActionsDescriptor();
 
-        cy.get(createRectificative).click();
+        cy.get(createCorrective).click();
         cy.get(saveDialog).click();
         cy.wait('@corrective').then((interception) => {
             const correctingId = interception.response.body;

From 76968fe6bd27a984687ae816656a4a6fdd6ad177 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Wed, 15 Jan 2025 09:01:37 +0100
Subject: [PATCH 16/21] fix: refs #7087 fixed some tests

---
 src/components/ui/__tests__/CardSummary.spec.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index b114797ef92..411ebf9bb60 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -62,12 +62,14 @@ describe('CardSummary', () => {
     });
 
     it('should respond to prop changes and refetch data', async () => {
+        const newUrl = 'CardSummary/35';
+        const newKey = 'cardSummaryKey/35';
         const fetchSpy = vi.spyOn(vm.arrayData, 'fetch');
-        await wrapper.setProps({ url: 'newUrl', filter: { key: 'newValue' } });
+        await wrapper.setProps({ url: newUrl, filter: { key: newKey } });
 
         expect(fetchSpy).toHaveBeenCalled();
-        expect(vm.store.url).toBe('newUrl');
-        expect(vm.store.filter).toEqual({ key: 'newValue' });
+        expect(vm.store.url).toBe(newUrl);
+        expect(vm.store.filter).toEqual({ key: newKey });
     });
 
     it('should return true if route path ends with /summary' , () => {

From 6a88cad90338bf4d370f77d08a68578f126df104 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Wed, 15 Jan 2025 09:55:59 +0100
Subject: [PATCH 17/21] fix: refs #7077 removed unused imports

---
 src/components/common/VnInputTime.vue | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue
index b4b24661832..4147f89765d 100644
--- a/src/components/common/VnInputTime.vue
+++ b/src/components/common/VnInputTime.vue
@@ -1,13 +1,11 @@
 <script setup>
 import { computed, ref, useAttrs } from 'vue';
-import { useI18n } from 'vue-i18n';
 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 model = defineModel({ type: String });
 const props = defineProps({
     timeOnly: {

From 979353119ab3b33d03d420a82ccf613842f3914c Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Wed, 15 Jan 2025 09:56:43 +0100
Subject: [PATCH 18/21] refactor: refs #7087 removed unused imports

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

diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index a1de3eee392..cf52bcd4063 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -2,7 +2,6 @@
 import { ref, computed, watch, onBeforeMount } from 'vue';
 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';
 import VnMoreOptions from './VnMoreOptions.vue';

From a153dd88604d374bbed95eb422ce456689c97aa7 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 15 Jan 2025 12:11:10 +0100
Subject: [PATCH 19/21] fix: refs #8316 use section-searchbar

---
 src/components/common/VnSection.vue   |  1 -
 src/components/ui/FetchedTags.vue     |  3 +-
 src/pages/Item/ItemList.vue           |  2 +-
 src/pages/Order/Card/OrderCatalog.vue | 43 ++++++++++++---------------
 4 files changed, 21 insertions(+), 28 deletions(-)

diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
index 11fd6013f57..510865530ed 100644
--- a/src/components/common/VnSection.vue
+++ b/src/components/common/VnSection.vue
@@ -80,7 +80,6 @@ onBeforeMount(() => {
         />
         <div :id="searchbarId"></div>
     </slot>
-
     <RightMenu>
         <template #right-panel v-if="$slots['rightMenu'] || rightFilter">
             <slot name="rightMenu">
diff --git a/src/components/ui/FetchedTags.vue b/src/components/ui/FetchedTags.vue
index 6e159087c27..b3912f77944 100644
--- a/src/components/ui/FetchedTags.vue
+++ b/src/components/ui/FetchedTags.vue
@@ -18,8 +18,7 @@ const $props = defineProps({
     },
     columns: {
         type: Number,
-        required: false,
-        default: null,
+        default: 3,
     },
 });
 
diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue
index f04563791d5..00d0f5c4e2e 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -391,7 +391,7 @@ onBeforeMount(async () => {
                     {{ row?.subName.toUpperCase() }}
                 </div>
             </div>
-            <FetchedTags :item="row" :columns="3" />
+            <FetchedTags :item="row" />
         </template>
         <template #more-create-dialog="{ data }">
             <VnInput
diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index da2e88aa990..186f216fb1b 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -15,15 +15,18 @@ const router = useRouter();
 const stateStore = useStateStore();
 const { t } = useI18n();
 const dataKey = 'OrderCatalogList';
-const arrayData = useArrayData(dataKey);
-const store = arrayData.store;
-const tags = ref([]);
-const itemRefs = ref({});
-
-let catalogParams = {
+const catalogParams = {
     orderFk: route.params.id,
     orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
 };
+const arrayData = useArrayData(dataKey, {
+    url: 'Orders/CatalogFilter',
+    limit: 50,
+    userParams: catalogParams,
+});
+const store = arrayData.store;
+const tags = ref([]);
+const itemRefs = ref({});
 
 onMounted(() => {
     stateStore.rightDrawer = true;
@@ -66,7 +69,6 @@ function extractValueTags(items) {
     );
     tagValue.value = resultValueTags;
 }
-const autoLoad = computed(() => !!JSON.parse(route?.query.table ?? '{}')?.categoryFk);
 
 watch(
     () => store.data,
@@ -78,16 +80,15 @@ watch(
 </script>
 
 <template>
-    <VnSearchbar
-        :data-key="dataKey"
-        :user-params="catalogParams"
-        :static-params="['orderFk', 'orderBy']"
-        :redirect="false"
-        url="Orders/CatalogFilter"
-        :label="t('Search items')"
-        :info="t('You can search items by name or id')"
-        :search-remove-params="false"
-    />
+    <Teleport to="#section-searchbar" v-if="stateStore.isHeaderMounted()">
+        <VnSearchbar
+            :data-key="dataKey"
+            :redirect="false"
+            :label="t('Search items')"
+            :info="t('You can search items by name or id')"
+            :search-remove-params="false"
+        />
+    </Teleport>
     <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
         <OrderCatalogFilter
             :data-key="dataKey"
@@ -98,13 +99,7 @@ watch(
     </Teleport>
     <QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
         <div class="full-width">
-            <VnPaginate
-                :data-key="dataKey"
-                url="Orders/CatalogFilter"
-                :limit="50"
-                :user-params="catalogParams"
-                :auto-load="autoLoad"
-            >
+            <VnPaginate :data-key="dataKey">
                 <template #body="{ rows }">
                     <div class="catalog-list">
                         <div v-if="rows && !rows?.length" class="no-result">

From 82e6cc07907d074e82cb51cdec19fe5919ed06c5 Mon Sep 17 00:00:00 2001
From: provira <provira@verdnatura.es>
Date: Thu, 16 Jan 2025 07:18:05 +0100
Subject: [PATCH 20/21] refactor: refs #7077 removed some comments

---
 src/components/common/__tests__/VnInputTime.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/common/__tests__/VnInputTime.spec.js b/src/components/common/__tests__/VnInputTime.spec.js
index 1ecc01cc398..2692ac71bf2 100644
--- a/src/components/common/__tests__/VnInputTime.spec.js
+++ b/src/components/common/__tests__/VnInputTime.spec.js
@@ -10,7 +10,7 @@ describe('VnInputTime', () => {
         wrapper = createWrapper(VnInputTime, {
             props: {
                 isOutlined: true,
-                timeOnly: false, // Initial props values
+                timeOnly: false,
             },
         });
         vm = wrapper.vm;

From 86169d980c6e390fc0591dfe1dd3c992fedaf795 Mon Sep 17 00:00:00 2001
From: guillermo <guillermo@verdnatura.es>
Date: Thu, 16 Jan 2025 09:34:12 +0100
Subject: [PATCH 21/21] feat: refs #7882 Added coords to create a address

---
 .../components/CustomerAddressCreate.vue      | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/pages/Customer/components/CustomerAddressCreate.vue b/src/pages/Customer/components/CustomerAddressCreate.vue
index bc4d6a1285a..32b4078db88 100644
--- a/src/pages/Customer/components/CustomerAddressCreate.vue
+++ b/src/pages/Customer/components/CustomerAddressCreate.vue
@@ -11,6 +11,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
 import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
 
 const { t } = useI18n();
 const route = useRoute();
@@ -150,6 +151,22 @@ function onAgentCreated({ id, fiscalName }, data) {
                     </template>
                 </VnSelectDialog>
             </VnRow>
+            <VnRow>
+                <VnInputNumber
+                    :label="t('Longitude')"
+                    clearable
+                    v-model="data.longitude"
+                    :decimal-places="7"
+                    :positive="false"
+                />
+                <VnInputNumber
+                    :label="t('Latitude')"
+                    clearable
+                    v-model="data.latitude"
+                    :decimal-places="7"
+                    :positive="false"
+                />
+            </VnRow>
         </template>
     </FormModel>
 </template>
@@ -175,4 +192,6 @@ es:
     Mobile: Movíl
     Incoterms: Incoterms
     Customs agent: Agente de aduanas
+    Longitude: Longitud
+    Latitude: Latitud
 </i18n>