From 91b08334607e1e8a820253ad97ffc609a1f9c80a Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Thu, 20 Feb 2025 10:17:59 +0100
Subject: [PATCH 01/28] fix: refs #8198 handle potential null values in
 itemBalances computation

---
 src/pages/Item/Card/ItemDiary.vue | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index 4b6775183..31b3c328e 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -27,7 +27,7 @@ const user = state.getUser();
 const today = Date.vnNew();
 today.setHours(0, 0, 0, 0);
 const warehousesOptions = ref([]);
-const itemBalances = computed(() => arrayDataItemBalances.store.data);
+const itemBalances = computed(() => arrayDataItemBalances.store.data || []);
 const where = computed(() => arrayDataItemBalances.store.filter.where || {});
 const showWhatsBeforeInventory = ref(false);
 const inventoriedDate = ref(null);
@@ -313,8 +313,8 @@ async function updateWarehouse(warehouseFk) {
                             row.lineFk == row.lastPreparedLineFk
                                 ? 'black'
                                 : row.balance < 0
-                                ? 'negative'
-                                : ''
+                                  ? 'negative'
+                                  : ''
                         "
                         dense
                         style="font-size: 14px"

From 64f29e0696b465feee45da34da5954520af0238b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 20 Feb 2025 13:37:17 +0100
Subject: [PATCH 02/28] fix: address

---
 src/pages/Ticket/Card/TicketSummary.vue | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 999240b7c..8cb518823 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -45,6 +45,15 @@ const descriptorData = useArrayData('ticketData');
 onMounted(async () => {
     ticketUrl.value = (await getUrl('ticket/')) + entityId.value + '/';
 });
+const formattedAddress = computed(() => {
+    if (!ticket.value) return '';
+
+    const address = ticket.value.address;
+    const postcode = address.postalCode;
+    const province = address.province ? `(${address.province.name})` : '';
+
+    return `${address.street} - ${postcode} - ${address.city} ${province}`;
+});
 
 function isEditable() {
     try {
@@ -237,7 +246,7 @@ onMounted(async () => {
                 />
                 <VnLv
                     :label="t('ticket.summary.consigneeStreet')"
-                    :value="entity.address?.street"
+                    :value="formattedAddress"
                 />
             </QCard>
             <QCard class="vn-one" v-if="entity.notes.length">

From a3828ab8692a0aee5f8890348b29dc8d233f325e Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Thu, 20 Feb 2025 21:16:05 +0100
Subject: [PATCH 03/28] fix: handle multiple changes

---
 src/pages/Ticket/Card/TicketSale.vue | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 92936b26a..a083ed316 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -174,11 +174,19 @@ const getSaleTotal = (sale) => {
     return price - discount;
 };
 
+const getRowUpdateInputEvents = (sale) => ({
+    'keyup.enter': () => {
+        changeQuantity(sale);
+    },
+    blur: () => {
+        changeQuantity(sale);
+    },
+});
+
 const resetChanges = async () => {
     arrayData.fetch({ append: false });
     tableRef.value.reload();
 };
-const rowToUpdate = ref(null);
 const changeQuantity = async (sale) => {
     if (
         !sale.itemFk ||
@@ -196,11 +204,8 @@ const changeQuantity = async (sale) => {
 const updateQuantity = async (sale) => {
     try {
         let { quantity, id } = sale;
-        if (!rowToUpdate.value) return;
-        rowToUpdate.value = null;
         sale.isNew = false;
-        const params = { quantity: quantity };
-        await axios.post(`Sales/${id}/updateQuantity`, params);
+        await axios.post(`Sales/${id}/updateQuantity`, { quantity });
         notify('globals.dataSaved', 'positive');
         tableRef.value.reload();
     } catch (e) {
@@ -816,9 +821,7 @@ watch(
                 v-if="row.isNew || isTicketEditable"
                 type="number"
                 v-model.number="row.quantity"
-                @blur="changeQuantity(row)"
-                @keyup.enter.stop="changeQuantity(row)"
-                @update:model-value="() => (rowToUpdate = row)"
+                v-on="getRowUpdateInputEvents(row)"
                 @focus="edit.oldQuantity = row.quantity"
             />
             <span v-else>{{ row.quantity }}</span>

From e82dc90ff9a91b26d48fb882a7f351dd5d3923f3 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 21 Feb 2025 09:01:28 +0100
Subject: [PATCH 04/28] fix: ticketSale

---
 src/pages/Ticket/Card/TicketSale.vue | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index a083ed316..f5fb50ecf 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -188,11 +188,7 @@ const resetChanges = async () => {
     tableRef.value.reload();
 };
 const changeQuantity = async (sale) => {
-    if (
-        !sale.itemFk ||
-        sale.quantity == null ||
-        edit.value?.oldQuantity === sale.quantity
-    )
+    if (!sale.itemFk || sale.quantity == null || sale?.originalQuantity === sale.quantity)
         return;
     if (!sale.id) return addSale(sale);
 

From 8536ade5b7e13ec4e1d962863ca49fbce218a501 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 21 Feb 2025 09:01:40 +0100
Subject: [PATCH 05/28] feat: add keyup.enter

---
 src/pages/Ticket/Card/TicketSaleMoreActions.vue | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 4cc96e9e2..8b5537edc 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -50,6 +50,7 @@ const { dialog } = useQuasar();
 const { notify } = useNotify();
 const acl = useAcl();
 const btnDropdownRef = ref(null);
+const editManaProxyRef = ref(null);
 const { openConfirmationModal } = useVnConfirm();
 
 const newDiscount = ref(null);
@@ -131,13 +132,13 @@ const createClaim = () => {
         openConfirmationModal(
             t('Claim out of time'),
             t('Do you want to continue?'),
-            onCreateClaimAccepted
+            onCreateClaimAccepted,
         );
     else
         openConfirmationModal(
             t('Do you want to create a claim?'),
             false,
-            onCreateClaimAccepted
+            onCreateClaimAccepted,
         );
 };
 
@@ -216,8 +217,15 @@ const createRefund = async (withWarehouse) => {
                 <QItemSection>
                     <QItemLabel>{{ t('Update discount') }}</QItemLabel>
                 </QItemSection>
-                <TicketEditManaProxy :mana="props.mana" @save="changeMultipleDiscount()">
+                <TicketEditManaProxy
+                    ref="editManaProxyRef"
+                    :sale="row"
+                    :mana="props.mana"
+                    @save="changeMultipleDiscount"
+                >
                     <VnInput
+                        autofocus
+                        @keyup.enter.stop="() => editManaProxyRef.save(row)"
                         v-model.number="newDiscount"
                         :label="t('ticketSale.discount')"
                         type="number"

From 81a33dd2fc4910c2a5107af7ad14463cd2da83c2 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 21 Feb 2025 11:38:32 +0100
Subject: [PATCH 06/28] fix: shipped columnFilter

---
 src/pages/Ticket/TicketList.vue | 44 +++++++++++++++++----------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 8df19c0d9..dfa1a4e14 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -108,13 +108,11 @@ const columns = computed(() => [
     },
     {
         align: 'left',
-        name: 'shippedDate',
+        name: 'shipped',
         cardVisible: true,
         label: t('ticketList.shipped'),
         columnFilter: {
             component: 'date',
-            alias: 't',
-            inWhere: true,
         },
         format: ({ shippedDate }) => toDate(shippedDate),
     },
@@ -122,6 +120,12 @@ const columns = computed(() => [
         align: 'left',
         name: 'shipped',
         label: t('ticketList.hour'),
+        columnFilter: {
+            component: 'time',
+            attrs: {
+                timeOnly: true,
+            },
+        },
         format: (row) => toTimeFormat(row.shipped),
     },
     {
@@ -232,7 +236,7 @@ const columns = computed(() => [
 
 function resetAgenciesSelector(formData) {
     agenciesOptions.value = [];
-    if(formData) formData.agencyModeId = null;
+    if (formData) formData.agencyModeId = null;
 }
 
 function redirectToLines(id) {
@@ -240,7 +244,7 @@ function redirectToLines(id) {
     window.open(url, '_blank');
 }
 
-const onClientSelected = async (formData) => {    
+const onClientSelected = async (formData) => {
     resetAgenciesSelector(formData);
     await fetchClient(formData);
     await fetchAddresses(formData);
@@ -248,14 +252,12 @@ const onClientSelected = async (formData) => {
 
 const fetchAvailableAgencies = async (formData) => {
     resetAgenciesSelector(formData);
-    const response= await getAgencies(formData, selectedClient.value);
+    const response = await getAgencies(formData, selectedClient.value);
     if (!response) return;
-    
-    const { options, agency } =  response
-    if(options)
-        agenciesOptions.value = options;
-    if(agency)
-        formData.agencyModeId = agency;
+
+    const { options, agency } = response;
+    if (options) agenciesOptions.value = options;
+    if (agency) formData.agencyModeId = agency;
 };
 
 const fetchClient = async (formData) => {
@@ -330,7 +332,7 @@ function openBalanceDialog(ticket) {
     const description = ref([]);
     const firstTicketClientId = checkedTickets[0].clientFk;
     const isSameClient = checkedTickets.every(
-        (ticket) => ticket.clientFk === firstTicketClientId
+        (ticket) => ticket.clientFk === firstTicketClientId,
     );
 
     if (!isSameClient) {
@@ -369,7 +371,7 @@ async function onSubmit() {
             description: dialogData.value.value.description,
             clientFk: dialogData.value.value.clientFk,
             email: email[0].email,
-        }
+        },
     );
 
     if (data) notify('globals.dataSaved', 'positive');
@@ -388,32 +390,32 @@ function setReference(data) {
     switch (data) {
         case 1:
             newDescription = `${t(
-                'ticketList.creditCard'
+                'ticketList.creditCard',
             )}, ${dialogData.value.value.description.replace(
                 /^(Credit Card, |Cash, |Transfers, )/,
-                ''
+                '',
             )}`;
             break;
         case 2:
             newDescription = `${t(
-                'ticketList.cash'
+                'ticketList.cash',
             )}, ${dialogData.value.value.description.replace(
                 /^(Credit Card, |Cash, |Transfers, )/,
-                ''
+                '',
             )}`;
             break;
         case 3:
             newDescription = `${newDescription.replace(
                 /^(Credit Card, |Cash, |Transfers, )/,
-                ''
+                '',
             )}`;
             break;
         case 4:
             newDescription = `${t(
-                'ticketList.transfers'
+                'ticketList.transfers',
             )}, ${dialogData.value.value.description.replace(
                 /^(Credit Card, |Cash, |Transfers, )/,
-                ''
+                '',
             )}`;
             break;
         case 3317:

From ef624af3f8ae3c664b79bbce5483396f0c945d36 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 21 Feb 2025 11:44:07 +0100
Subject: [PATCH 07/28] revert: column time

---
 src/pages/Ticket/TicketList.vue | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index dfa1a4e14..78bebc297 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -120,12 +120,6 @@ const columns = computed(() => [
         align: 'left',
         name: 'shipped',
         label: t('ticketList.hour'),
-        columnFilter: {
-            component: 'time',
-            attrs: {
-                timeOnly: true,
-            },
-        },
         format: (row) => toTimeFormat(row.shipped),
     },
     {

From 680c1f9d9ca1c573f3d41c5446d01130e5c3accc Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Fri, 21 Feb 2025 11:45:41 +0100
Subject: [PATCH 08/28] perf: i18n

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

diff --git a/src/pages/Ticket/TicketFilter.vue b/src/pages/Ticket/TicketFilter.vue
index 4b50892b0..c82c0067f 100644
--- a/src/pages/Ticket/TicketFilter.vue
+++ b/src/pages/Ticket/TicketFilter.vue
@@ -293,6 +293,7 @@ en:
         clientFk: Customer
         orderFk: Order
         from: From
+        shipped: Shipped
         to: To
         salesPersonFk: Salesperson
         stateFk: State
@@ -320,6 +321,7 @@ es:
         clientFk: Cliente
         orderFk: Pedido
         from: Desde
+        shipped: F. envío
         to: Hasta
         salesPersonFk: Comercial
         stateFk: Estado

From 5481ad6478b7924e773083c58f8e4cedca03e1a9 Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Fri, 21 Feb 2025 15:23:44 +0100
Subject: [PATCH 09/28] fix: refs #6553 workerBusiness

---
 src/pages/Worker/Card/WorkerBusiness.vue   | 41 +++++++++++++++-------
 src/pages/Worker/Card/WorkerDescriptor.vue |  7 ++++
 2 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/pages/Worker/Card/WorkerBusiness.vue b/src/pages/Worker/Card/WorkerBusiness.vue
index 6025ae289..e3582a2d5 100644
--- a/src/pages/Worker/Card/WorkerBusiness.vue
+++ b/src/pages/Worker/Card/WorkerBusiness.vue
@@ -3,7 +3,7 @@ import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import VnTable from 'components/VnTable/VnTable.vue';
-import { toDate } from 'src/filters';
+import { dashIfEmpty, toDate } from 'src/filters';
 import { useQuasar } from 'quasar';
 import axios from 'axios';
 
@@ -15,7 +15,7 @@ const quasar = useQuasar();
 
 async function reactivateWorker() {
     const hasToReactive = tableRef.value.CrudModelRef.formData.find(
-        (data) => !data.ended
+        (data) => !data.ended,
     );
     if (hasToReactive) {
         quasar
@@ -38,25 +38,25 @@ const columns = computed(() => [
     {
         name: 'started',
         label: t('worker.business.tableVisibleColumns.started'),
-        align: 'left',
         format: ({ started }) => toDate(started),
         component: 'date',
         cardVisible: true,
         create: true,
+        width: '90px',
     },
 
     {
         name: 'ended',
         label: t('worker.business.tableVisibleColumns.ended'),
-        align: 'left',
         format: ({ ended }) => toDate(ended),
         component: 'date',
         cardVisible: true,
         create: true,
+        width: '90px',
     },
     {
         label: t('worker.business.tableVisibleColumns.company'),
-        align: 'left',
+        toolTip: t('worker.business.tableVisibleColumns.company'),
         name: 'companyCodeFk',
         component: 'select',
         attrs: {
@@ -65,23 +65,23 @@ const columns = computed(() => [
             optionLabel: 'code',
             optionValue: 'code',
         },
-        cardVisible: true,
         create: true,
+        width: '60px',
     },
     {
-        align: 'left',
         name: 'reasonEndFk',
         component: 'select',
         label: t('worker.business.tableVisibleColumns.reasonEnd'),
+        toolTip: t('worker.business.tableVisibleColumns.reasonEnd'),
         attrs: {
             url: 'BusinessReasonEnds',
             fields: ['id', 'reason'],
             optionLabel: 'reason',
         },
         cardVisible: true,
+        format: ({ reason }, dashIfEmpty) => dashIfEmpty(reason),
     },
     {
-        align: 'left',
         name: 'departmentFk',
         component: 'select',
         label: t('worker.business.tableVisibleColumns.department'),
@@ -89,15 +89,19 @@ const columns = computed(() => [
             url: 'Departments',
             fields: ['id', 'name'],
             optionLabel: 'name',
+            optionValue: 'id',
         },
         cardVisible: true,
         create: true,
+        width: '80px',
+        format: ({ departmentName }, dashIfEmpty) => dashIfEmpty(departmentName),
     },
     {
         align: 'left',
         name: 'workerBusinessProfessionalCategoryFk',
         component: 'select',
         label: t('worker.business.tableVisibleColumns.professionalCategory'),
+        toolTip: t('worker.business.tableVisibleColumns.professionalCategory'),
         attrs: {
             url: 'WorkerBusinessProfessionalCategories',
             fields: ['id', 'description', 'code'],
@@ -105,6 +109,9 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        width: '100px',
+        format: ({ professionalDescription }, dashIfEmpty) =>
+            dashIfEmpty(professionalDescription),
     },
     {
         align: 'left',
@@ -118,6 +125,8 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        format: ({ calendarTypeDescription }, dashIfEmpty) =>
+            dashIfEmpty(calendarTypeDescription),
     },
     {
         align: 'left',
@@ -131,6 +140,8 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        width: '100px',
+        format: ({ workCenterName }, dashIfEmpty) => dashIfEmpty(workCenterName),
     },
     {
         align: 'left',
@@ -144,6 +155,7 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        format: ({ payrollDescription }, dashIfEmpty) => dashIfEmpty(payrollDescription),
     },
     {
         align: 'left',
@@ -157,6 +169,7 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        format: ({ occupationName }, dashIfEmpty) => dashIfEmpty(occupationName),
     },
     {
         align: 'left',
@@ -165,6 +178,7 @@ const columns = computed(() => [
         component: 'input',
         cardVisible: true,
         create: true,
+        width: '50px',
     },
     {
         align: 'left',
@@ -177,6 +191,8 @@ const columns = computed(() => [
         },
         cardVisible: true,
         create: true,
+        format: ({ workerBusinessTypeName }, dashIfEmpty) =>
+            dashIfEmpty(workerBusinessTypeName),
     },
     {
         align: 'left',
@@ -185,6 +201,7 @@ const columns = computed(() => [
         component: 'input',
         cardVisible: true,
         create: true,
+        width: '70px',
     },
     {
         align: 'left',
@@ -193,6 +210,7 @@ const columns = computed(() => [
         component: 'input',
         cardVisible: true,
         create: true,
+        width: '70px',
     },
     {
         name: 'notes',
@@ -208,7 +226,7 @@ const columns = computed(() => [
     <VnTable
         ref="tableRef"
         data-key="WorkerBusiness"
-        :url="`Workers/${entityId}/Business`"
+        :url="`Workers/${entityId}/getWorkerBusiness`"
         save-url="/Businesses/crud"
         :create="{
             urlCreate: `Workers/${entityId}/Business`,
@@ -218,13 +236,12 @@ const columns = computed(() => [
         }"
         order="id DESC"
         :columns="columns"
-        default-mode="card"
         auto-load
-        :disable-option="{ table: true }"
+        :disable-option="{ card: true }"
         :right-search="false"
-        card-class="grid-two q-gutter-x-xl q-gutter-y-md q-pr-lg q-py-lg"
         :is-editable="true"
         :use-model="true"
+        :right-search-icon="false"
         @save-changes="(data) => reactivateWorker(data)"
     />
 </template>
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index de3f634e2..0e946f1dd 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -111,6 +111,7 @@ const handlePhotoUpdated = (evt = false) => {
         <template #body="{ entity }">
             <VnLv :label="t('globals.user')" :value="entity.user?.name" />
             <VnLv
+                class="ellipsis-text"
                 :label="t('globals.params.email')"
                 :value="entity.user?.emailUser?.email"
                 copy
@@ -177,6 +178,12 @@ const handlePhotoUpdated = (evt = false) => {
 .photo {
     height: 256px;
 }
+.ellipsis-text {
+    width: 100%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
 </style>
 
 <i18n>

From 24b4d0071a2b9535d1cf9e6985dff50245bf98fc Mon Sep 17 00:00:00 2001
From: pablone <pablone@verdnatura.es>
Date: Sun, 23 Feb 2025 12:57:57 +0100
Subject: [PATCH 10/28] feat: enhance item tags with data attributes for
 improved testing

---
 src/pages/Item/Card/ItemTags.vue              |  6 ++-
 test/cypress/integration/item/itemTag.spec.js | 41 ++++++++++---------
 2 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index 5876cf8dc..5a7d7f818 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -87,7 +87,7 @@ const insertTag = (rows) => {
                     tagFk: undefined,
                 }"
                 :default-remove="false"
-                :filter="{
+                :user-filter="{
                     fields: ['id', 'itemFk', 'tagFk', 'value', 'priority'],
                     where: { itemFk: route.params.id },
                     include: {
@@ -119,6 +119,7 @@ const insertTag = (rows) => {
                                 "
                                 :required="true"
                                 :rules="validate('itemTag.tagFk')"
+                                :data-cy="`tag${row?.tag?.name}`"
                             />
                             <VnSelect
                                 v-if="row.tag?.isFree === false"
@@ -145,6 +146,7 @@ const insertTag = (rows) => {
                                 :label="t('itemTags.value')"
                                 :is-clearable="false"
                                 @keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
+                                :data-cy="`tag${row?.tag?.name}Value`"
                             />
                             <VnInput
                                 :label="t('itemBasicData.relevancy')"
@@ -162,6 +164,7 @@ const insertTag = (rows) => {
                                     name="delete"
                                     size="sm"
                                     dense
+                                    :data-cy="`deleteTag${row?.tag?.name}`"
                                 >
                                     <QTooltip>
                                         {{ t('itemTags.removeTag') }}
@@ -177,6 +180,7 @@ const insertTag = (rows) => {
                             icon="add"
                             shortcut="+"
                             fab
+                            data-cy="createNewTag"
                         >
                             <QTooltip>
                                 {{ t('itemTags.addTag') }}
diff --git a/test/cypress/integration/item/itemTag.spec.js b/test/cypress/integration/item/itemTag.spec.js
index 10d68d08a..17423bc51 100644
--- a/test/cypress/integration/item/itemTag.spec.js
+++ b/test/cypress/integration/item/itemTag.spec.js
@@ -1,33 +1,36 @@
-/// <reference types="cypress" />
 describe('Item tag', () => {
     beforeEach(() => {
         cy.viewport(1920, 1080);
         cy.login('developer');
         cy.visit(`/#/item/1/tags`);
+        cy.get('.q-page').should('be.visible');
+        cy.waitForElement('[data-cy="itemTags"]');
     });
 
+    const createNewTag = 'createNewTag';
+    const saveBtn = 'crudModelDefaultSaveBtn';
+    const newTag = 'tagundefined';
+
     it('should throw an error adding an existent tag', () => {
-        cy.get('.q-page').should('be.visible');
-        cy.get('.q-page-sticky > div').click();
-        cy.get('.q-page-sticky > div').click();
-        cy.dataCy('Tag_select').eq(7).type('Tallos');
-        cy.get('.q-menu .q-item').contains('Tallos').click();
-        cy.get(':nth-child(8) > [label="Value"]').type('1');
-        +cy.dataCy('crudModelDefaultSaveBtn').click();
-        cy.checkNotification("The tag or priority can't be repeated for an item");
+        cy.dataCy(createNewTag).click();
+        cy.dataCy(newTag).should('be.visible').click().type('Genero{enter}');
+        cy.dataCy('tagGeneroValue').eq(1).should('be.visible');
+        cy.dataCy(saveBtn).click();
+        cy.get('.q-notification__message').should(
+            'have.text',
+            "The tag or priority can't be repeated for an item",
+        );
     });
 
     it('should add a new tag', () => {
-        cy.get('.q-page').should('be.visible');
-        cy.get('.q-page-sticky > div').click();
-        cy.get('.q-page-sticky > div').click();
-        cy.dataCy('Tag_select').eq(7).click();
-        cy.get('.q-menu .q-item').contains('Ancho de la base').type('{enter}');
-        cy.get(':nth-child(8) > [label="Value"]').type('50');
-        cy.dataCy('crudModelDefaultSaveBtn').click();
+        cy.dataCy(createNewTag).click();
+        cy.dataCy(newTag).should('be.visible').click().type('Forma{enter}');
+        cy.dataCy('tagFormaValue').should('be.visible').type('50');
+        cy.dataCy(saveBtn).click();
+
         cy.checkNotification('Data saved');
-        cy.dataCy('itemTags').children(':nth-child(8)').find('.justify-center > .q-icon').click();
-        cy.dataCy('VnConfirm_confirm').click();
+        cy.dataCy('deleteTagForma').should('be.visible').click();
+        cy.dataCy('VnConfirm_confirm').should('be.visible').click();
         cy.checkNotification('Data saved');
     });
-});
\ No newline at end of file
+});

From 3b5c4731f09e16d916f3b4878698c5457d7d45db Mon Sep 17 00:00:00 2001
From: carlossa <carlossa@verdnatura.es>
Date: Mon, 24 Feb 2025 08:20:04 +0100
Subject: [PATCH 11/28] fix: hotfix filters

---
 src/pages/Customer/CustomerFilter.vue |  2 +-
 src/pages/Customer/CustomerList.vue   | 12 +++++++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index eae97d1be..9b883daad 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -1,4 +1,3 @@
-
 <script setup>
 import { useI18n } from 'vue-i18n';
 import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
@@ -148,6 +147,7 @@ const exprBuilder = (param, value) => {
                         outlined
                         rounded
                         auto-load
+                        sortBy="name ASC"
                 /></QItemSection>
             </QItem>
             <QItem class="q-mb-sm">
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 3c638b612..2f2dd5978 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -78,10 +78,20 @@ const columns = computed(() => [
         component: 'select',
         attrs: {
             url: 'Workers/activeWithInheritedRole',
-            fields: ['id', 'name'],
+            fields: ['id', 'name', 'firstName'],
             where: { role: 'salesPerson' },
             optionFilter: 'firstName',
         },
+        columnFilter: {
+            component: 'select',
+            attrs: {
+                url: 'Workers/activeWithInheritedRole',
+                fields: ['id', 'name', 'firstName'],
+                where: { role: 'salesPerson' },
+                optionLabel: 'firstName',
+                optionValue: 'id',
+            },
+        },
         create: false,
         columnField: {
             component: null,

From 1e9e5e647d5bb0af8ea8b89ffd502754cb9ab027 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 10:05:13 +0100
Subject: [PATCH 12/28] fix: refs #6919 update customer data retrieval to use
 useArrayData for improved reactivity

---
 src/pages/Customer/components/CustomerSamplesCreate.vue | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/pages/Customer/components/CustomerSamplesCreate.vue b/src/pages/Customer/components/CustomerSamplesCreate.vue
index 8d241441d..7624a3f98 100644
--- a/src/pages/Customer/components/CustomerSamplesCreate.vue
+++ b/src/pages/Customer/components/CustomerSamplesCreate.vue
@@ -39,7 +39,7 @@ const optionsSamplesVisible = ref([]);
 const sampleType = ref({ hasPreview: false });
 const initialData = reactive({});
 const entityId = computed(() => route.params.id);
-const customer = computed(() => state.get('Customer'));
+const customer = computed(() => useArrayData('Customer').store?.data);
 const filterEmailUsers = { where: { userFk: user.value.id } };
 const filterClientsAddresses = {
     include: [
@@ -65,9 +65,9 @@ const filterSamplesVisible = {
 defineEmits(['confirm', ...useDialogPluginComponent.emits]);
 
 onBeforeMount(async () => {
-    initialData.clientFk = customer.value.id;
-    initialData.recipient = customer.value.email;
-    initialData.recipientId = customer.value.id;
+    initialData.clientFk = customer.value?.id;
+    initialData.recipient = customer.value?.email;
+    initialData.recipientId = customer.value?.id;
 });
 
 const setEmailUser = (data) => {

From 5e8ad9df11e5550ec4c4345021a374a8ce0409bf Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 10:13:09 +0100
Subject: [PATCH 13/28] feat: refs #6919 add useArrayData import to
 CustomerSamplesCreate for improved data handling

---
 src/pages/Customer/components/CustomerSamplesCreate.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/Customer/components/CustomerSamplesCreate.vue b/src/pages/Customer/components/CustomerSamplesCreate.vue
index 7624a3f98..1294a5d25 100644
--- a/src/pages/Customer/components/CustomerSamplesCreate.vue
+++ b/src/pages/Customer/components/CustomerSamplesCreate.vue
@@ -18,6 +18,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import CustomerSamplesPreview from 'src/pages/Customer/components/CustomerSamplesPreview.vue';
 import FormPopup from 'src/components/FormPopup.vue';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const { dialogRef, onDialogOK } = useDialogPluginComponent();
 

From 09b613cac19ed233ecfeb3a2012f53bcc52488aa Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 11:03:14 +0100
Subject: [PATCH 14/28] refactor: refs #8372 update FormModelPopup to use props
 for save and continue logic

---
 src/components/FormModelPopup.vue  | 13 +++++++------
 src/components/VnTable/VnTable.vue |  8 --------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index 672eeff7a..db9974422 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -6,7 +6,7 @@ import FormModel from 'components/FormModel.vue';
 
 const emit = defineEmits(['onDataSaved', 'onDataCanceled']);
 
-defineProps({
+const props = defineProps({
     title: {
         type: String,
         default: '',
@@ -25,10 +25,14 @@ const { t } = useI18n();
 
 const formModelRef = ref(null);
 const closeButton = ref(null);
-const isSaveAndContinue = ref(false);
+const isSaveAndContinue = ref(props.showSaveAndContinueBtn);
+const isLoading = computed(() => formModelRef.value?.isLoading);
+const reset = computed(() => formModelRef.value?.reset);
+
 const onDataSaved = (formData, requestResponse) => {
-    if (closeButton.value && !isSaveAndContinue.value) closeButton.value.click();
+    if (!isSaveAndContinue.value) closeButton.value?.click();
     emit('onDataSaved', formData, requestResponse);
+    isSaveAndContinue.value = props.showSaveAndContinueBtn;
 };
 
 const onClick = async (saveAndContinue) => {
@@ -36,9 +40,6 @@ const onClick = async (saveAndContinue) => {
     await formModelRef.value.save();
 };
 
-const isLoading = computed(() => formModelRef.value?.isLoading);
-const reset = computed(() => formModelRef.value?.reset);
-
 defineExpose({
     isLoading,
     onDataSaved,
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 105010140..7ff56860f 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -961,14 +961,6 @@ function cardClick(_, row) {
         transition-show="scale"
         transition-hide="scale"
         :full-width="createComplement?.isFullWidth ?? false"
-        @before-hide="
-            () => {
-                if (createRef.isSaveAndContinue) {
-                    showForm = true;
-                    createForm.formInitialData = { ...create.formInitialData };
-                }
-            }
-        "
         data-cy="vn-table-create-dialog"
     >
         <FormModelPopup

From f551e1a14a71456c0bcff98fb175354e1cc89a3f Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 11:06:20 +0100
Subject: [PATCH 15/28] refactor: refs #8372 simplify cancel btn click

---
 src/components/FormModelPopup.vue | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index db9974422..e87de5c65 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -75,10 +75,7 @@ defineExpose({
                     data-cy="FormModelPopup_cancel"
                     v-close-popup
                     z-max
-                    @click="
-                        isSaveAndContinue = false;
-                        emit('onDataCanceled');
-                    "
+                    @click="emit('onDataCanceled')"
                 />
                 <QBtn
                     :flat="showSaveAndContinueBtn"

From b26db960be4218056d70e015e7b8d6a5758270ba Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 11:43:29 +0100
Subject: [PATCH 16/28] refactor: refs #8372 prueba

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

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index e87de5c65..33041d29a 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -63,6 +63,7 @@ defineExpose({
             <h1 class="title">{{ title }}</h1>
             <p>{{ subtitle }}</p>
             <slot name="form-inputs" :data="data" :validate="validate" />
+
             <div class="q-mt-lg row justify-end">
                 <QBtn
                     :label="t('globals.cancel')"

From fbce97dd01049d7817bc6b7d5282f8fe9793f8e3 Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 11:44:00 +0100
Subject: [PATCH 17/28] chore: refs #8372 rollback

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

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index 33041d29a..e87de5c65 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -63,7 +63,6 @@ defineExpose({
             <h1 class="title">{{ title }}</h1>
             <p>{{ subtitle }}</p>
             <slot name="form-inputs" :data="data" :validate="validate" />
-
             <div class="q-mt-lg row justify-end">
                 <QBtn
                     :label="t('globals.cancel')"

From 659d87020f3eaea4a86ef0310bda1d4ef78e262d Mon Sep 17 00:00:00 2001
From: jorgep <jorgep@verdnatura.es>
Date: Mon, 24 Feb 2025 13:20:59 +0100
Subject: [PATCH 18/28] refactor: refs #8372 update FormModelPopup to enhance
 save and continue logic with state management

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

diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index e87de5c65..85943e91e 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -1,6 +1,7 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, useAttrs, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
 
 import FormModel from 'components/FormModel.vue';
 
@@ -22,17 +23,22 @@ const props = defineProps({
 });
 
 const { t } = useI18n();
-
+const attrs = useAttrs();
+const state = useState();
 const formModelRef = ref(null);
 const closeButton = ref(null);
 const isSaveAndContinue = ref(props.showSaveAndContinueBtn);
 const isLoading = computed(() => formModelRef.value?.isLoading);
 const reset = computed(() => formModelRef.value?.reset);
 
-const onDataSaved = (formData, requestResponse) => {
+const onDataSaved = async (formData, requestResponse) => {
     if (!isSaveAndContinue.value) closeButton.value?.click();
-    emit('onDataSaved', formData, requestResponse);
+    if (isSaveAndContinue.value) {
+        await nextTick();
+        state.set(attrs.model, attrs.formInitialData);
+    }
     isSaveAndContinue.value = props.showSaveAndContinueBtn;
+    emit('onDataSaved', formData, requestResponse);
 };
 
 const onClick = async (saveAndContinue) => {

From 3a9a9bd517f15f2d2f59e4a71351cfb247297b78 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 15:30:30 +0100
Subject: [PATCH 19/28] fix: check type variable

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

diff --git a/src/pages/Ticket/Card/TicketEditMana.vue b/src/pages/Ticket/Card/TicketEditMana.vue
index 14eec9db9..c1bc2639b 100644
--- a/src/pages/Ticket/Card/TicketEditMana.vue
+++ b/src/pages/Ticket/Card/TicketEditMana.vue
@@ -48,7 +48,7 @@ defineExpose({ save });
 <template>
     <QPopupProxy ref="QPopupProxyRef" data-cy="ticketEditManaProxy">
         <div class="container">
-            <QSpinner v-if="!mana" color="primary" size="md" />
+            <QSpinner v-if="typeof mana === 'number' && mana" color="primary" size="md" />
             <div v-else>
                 <div class="header">Mana: {{ toCurrency(mana) }}</div>
                 <div class="q-pa-md">

From ab5ae580b3bfbfb2291b492d25317864c52bdb2c Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 16:08:40 +0100
Subject: [PATCH 20/28] fix: check type variable

---
 src/pages/Ticket/Card/TicketEditMana.vue | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/pages/Ticket/Card/TicketEditMana.vue b/src/pages/Ticket/Card/TicketEditMana.vue
index 14eec9db9..b3ba870fb 100644
--- a/src/pages/Ticket/Card/TicketEditMana.vue
+++ b/src/pages/Ticket/Card/TicketEditMana.vue
@@ -48,7 +48,11 @@ defineExpose({ save });
 <template>
     <QPopupProxy ref="QPopupProxyRef" data-cy="ticketEditManaProxy">
         <div class="container">
-            <QSpinner v-if="!mana" color="primary" size="md" />
+            <QSpinner
+                v-if="!(typeof mana === 'number' && mana >= 0)"
+                color="primary"
+                size="md"
+            />
             <div v-else>
                 <div class="header">Mana: {{ toCurrency(mana) }}</div>
                 <div class="q-pa-md">

From 223a1ea4490ea6ad2a00c60297fd3c74cd713338 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 15:52:21 +0000
Subject: [PATCH 21/28] revert 1015acefb7e400be2d8b5958dba69b4d98276b34

revert Merge branch 'test' into master
---
 cypress.config.js                             |    4 +-
 package.json                                  |  144 +-
 quasar.config.js                              |    1 +
 src/boot/defaults/constants.js                |    2 -
 src/boot/keyShortcut.js                       |   17 +-
 src/boot/qformMixin.js                        |   23 +-
 src/boot/quasar.js                            |    1 -
 src/components/CreateBankEntityForm.vue       |    2 +-
 src/components/CrudModel.vue                  |   16 +-
 src/components/FilterTravelForm.vue           |    4 +-
 src/components/FormModel.vue                  |   46 +-
 src/components/FormModelPopup.vue             |   52 +-
 src/components/ItemsFilterPanel.vue           |    4 +-
 src/components/LeftMenu.vue                   |   69 +-
 src/components/LeftMenuItem.vue               |    1 -
 src/components/RefundInvoiceForm.vue          |   15 +-
 src/components/TicketProblems.vue             |   84 +-
 src/components/TransferInvoiceForm.vue        |   15 +-
 src/components/VnTable/VnColumn.vue           |   51 +-
 src/components/VnTable/VnFilter.vue           |   58 +-
 src/components/VnTable/VnOrder.vue            |  101 +-
 src/components/VnTable/VnTable.vue            |  573 ++------
 src/components/VnTable/VnTableFilter.vue      |   57 +-
 src/components/VnTable/VnVisibleColumn.vue    |   19 +-
 src/components/__tests__/FormModel.spec.js    |   12 +-
 src/components/__tests__/Leftmenu.spec.js     |  372 +----
 src/components/__tests__/UserPanel.spec.js    |  100 +-
 src/components/common/VnCard.vue              |   39 +-
 src/components/common/VnCardBeta.vue          |   61 +-
 src/components/common/VnCheckbox.vue          |   43 -
 src/components/common/VnColor.vue             |   32 -
 src/components/common/VnComponent.vue         |    6 +-
 src/components/common/VnDmsList.vue           |   12 +-
 src/components/common/VnInput.vue             |   22 +-
 src/components/common/VnInputDate.vue         |    8 +-
 src/components/common/VnInputNumber.vue       |    2 -
 src/components/common/VnPopupProxy.vue        |   38 -
 src/components/common/VnSection.vue           |    9 +-
 src/components/common/VnSelect.vue            |   22 +-
 src/components/common/VnSelectCache.vue       |    4 +-
 src/components/common/VnSelectDialog.vue      |    2 +
 src/components/common/VnSelectSupplier.vue    |    6 +-
 .../common/VnSelectTravelExtended.vue         |   50 -
 .../common/__tests__/VnNotes.spec.js          |  151 +--
 src/components/ui/CardDescriptor.vue          |   52 +-
 src/components/ui/CardSummary.vue             |   14 +-
 src/components/ui/SkeletonDescriptor.vue      |   65 +-
 src/components/ui/VnConfirm.vue               |    3 +-
 src/components/ui/VnFilterPanel.vue           |   16 +-
 src/components/ui/VnMoreOptions.vue           |    2 +-
 src/components/ui/VnNotes.vue                 |   94 +-
 src/components/ui/VnStockValueDisplay.vue     |   41 -
 src/components/ui/VnSubToolbar.vue            |   11 +-
 .../ui/__tests__/CardSummary.spec.js          |   14 +-
 .../__tests__/useArrayData.spec.js            |   29 +-
 src/composables/checkEntryLock.js             |   65 -
 src/composables/getColAlign.js                |   22 -
 src/composables/useArrayData.js               |   13 +-
 src/composables/useRole.js                    |   10 -
 src/css/app.scss                              |   28 +-
 src/css/quasar.variables.scss                 |    6 +-
 src/filters/toDate.js                         |   11 +-
 src/i18n/locale/en.yml                        |  117 --
 src/i18n/locale/es.yml                        |  225 +---
 src/layouts/MainLayout.vue                    |    2 +-
 src/layouts/OutLayout.vue                     |    5 +-
 src/pages/Account/AccountAliasList.vue        |   10 +-
 src/pages/Account/AccountExprBuilder.js       |   18 -
 src/pages/Account/AccountList.vue             |   26 +-
 src/pages/Account/Alias/AliasExprBuilder.js   |    8 -
 src/pages/Account/Alias/Card/AliasCard.vue    |   10 +-
 .../Account/Alias/Card/AliasDescriptor.vue    |   11 +-
 src/pages/Account/Alias/Card/AliasSummary.vue |   19 +-
 src/pages/Account/Card/AccountBasicData.vue   |   38 +-
 src/pages/Account/Card/AccountCard.vue        |   10 +-
 src/pages/Account/Card/AccountDescriptor.vue  |   43 +-
 .../Account/Card/AccountDescriptorMenu.vue    |   27 +-
 src/pages/Account/Card/AccountFilter.js       |    3 -
 src/pages/Account/Card/AccountMailAlias.vue   |    7 +-
 src/pages/Account/Card/AccountSummary.vue     |   41 +-
 src/pages/Account/Role/AccountRoles.vue       |   18 +-
 src/pages/Account/Role/Card/RoleBasicData.vue |   14 +-
 src/pages/Account/Role/Card/RoleCard.vue      |    7 +-
 .../Account/Role/Card/RoleDescriptor.vue      |   16 +-
 src/pages/Account/Role/Card/RoleSummary.vue   |   23 +-
 src/pages/Account/Role/Card/SubRoles.vue      |    6 +-
 src/pages/Account/Role/RoleExprBuilder.js     |   16 -
 src/pages/Claim/Card/ClaimBasicData.vue       |    1 +
 src/pages/Claim/Card/ClaimCard.vue            |    9 +-
 src/pages/Claim/Card/ClaimDescriptor.vue      |   17 +-
 src/pages/Claim/Card/ClaimLines.vue           |    8 +-
 src/pages/Claim/Card/ClaimNotes.vue           |    3 +-
 src/pages/Claim/Card/ClaimPhoto.vue           |    4 +-
 src/pages/Claim/ClaimList.vue                 |    2 +-
 src/pages/Customer/Card/CustomerAddress.vue   |    8 +-
 src/pages/Customer/Card/CustomerBalance.vue   |    4 +-
 src/pages/Customer/Card/CustomerBasicData.vue |    4 +-
 .../Customer/Card/CustomerBillingData.vue     |    2 +-
 src/pages/Customer/Card/CustomerCard.vue      |    4 +-
 .../Customer/Card/CustomerConsumption.vue     |   95 +-
 src/pages/Customer/Card/CustomerContacts.vue  |    2 +-
 .../Customer/Card/CustomerCreditContracts.vue |    2 +-
 .../Customer/Card/CustomerDescriptor.vue      |   42 +-
 .../Customer/Card/CustomerDescriptorMenu.vue  |   17 -
 .../Customer/Card/CustomerFileManagement.vue  |    2 +-
 .../Customer/Card/CustomerFiscalData.vue      |   32 +-
 src/pages/Customer/Card/CustomerNotes.vue     |    1 -
 src/pages/Customer/Card/CustomerSamples.vue   |    2 +-
 src/pages/Customer/Card/CustomerWebAccess.vue |    2 +-
 src/pages/Customer/CustomerFilter.vue         |    6 +-
 src/pages/Customer/CustomerList.vue           |    4 +-
 .../Customer/Defaulter/CustomerDefaulter.vue  |    2 +-
 .../components/CustomerAddressEdit.vue        |    4 +-
 .../components/CustomerNewPayment.vue         |    6 +-
 .../components/CustomerSamplesCreate.vue      |    9 +-
 src/pages/Customer/locale/en.yml              |    3 -
 src/pages/Customer/locale/es.yml              |    3 -
 .../Department/Card/DepartmentBasicData.vue   |   35 +-
 .../Department/Card/DepartmentCard.vue        |    4 +-
 .../Department/Card/DepartmentDescriptor.vue  |   23 +-
 .../Card/DepartmentDescriptorProxy.vue        |    0
 .../Department/Card/DepartmentSummary.vue     |    2 +-
 .../Card/DepartmentSummaryDialog.vue          |    0
 src/pages/Entry/Card/EntryBasicData.vue       |   63 +-
 src/pages/Entry/Card/EntryBuys.vue            | 1196 ++++++-----------
 src/pages/Entry/Card/EntryCard.vue            |    6 +-
 src/pages/Entry/Card/EntryDescriptor.vue      |  158 +--
 src/pages/Entry/Card/EntryFilter.js           |   17 +-
 src/pages/Entry/Card/EntryNotes.vue           |    4 +-
 src/pages/Entry/Card/EntrySummary.vue         |  392 ++++--
 src/pages/Entry/EntryFilter.vue               |  277 ++--
 src/pages/Entry/EntryList.vue                 |  372 ++---
 src/pages/Entry/EntryStockBought.vue          |   18 +-
 src/pages/Entry/EntryStockBoughtDetail.vue    |   22 +-
 src/pages/Entry/locale/en.yml                 |   82 +-
 src/pages/Entry/locale/es.yml                 |  105 +-
 .../InvoiceIn/Card/InvoiceInBasicData.vue     |    6 +-
 src/pages/InvoiceIn/Card/InvoiceInCard.vue    |   41 +-
 .../InvoiceIn/Card/InvoiceInDescriptor.vue    |   33 +-
 .../Card/InvoiceInDescriptorMenu.vue          |    4 +-
 src/pages/InvoiceIn/Card/InvoiceInDueDay.vue  |   26 +-
 src/pages/InvoiceIn/Card/InvoiceInFilter.js   |   33 -
 .../InvoiceIn/Card/InvoiceInIntrastat.vue     |    2 +-
 src/pages/InvoiceIn/Card/InvoiceInSummary.vue |   13 +-
 src/pages/InvoiceIn/Card/InvoiceInVat.vue     |   78 +-
 src/pages/InvoiceIn/InvoiceInList.vue         |    5 +-
 src/pages/InvoiceIn/InvoiceInToBook.vue       |   56 +-
 src/pages/InvoiceIn/locale/en.yml             |    5 +-
 src/pages/InvoiceIn/locale/es.yml             |    9 +-
 src/pages/InvoiceOut/Card/InvoiceOutCard.vue  |    4 +-
 .../InvoiceOut/Card/InvoiceOutDescriptor.vue  |   28 +-
 src/pages/InvoiceOut/Card/InvoiceOutFilter.js |   16 -
 .../{components => Card}/CreateGenusForm.vue  |    0
 .../{components => Card}/CreateSpecieForm.vue |    0
 src/pages/Item/Card/ItemBarcode.vue           |    2 +-
 src/pages/Item/Card/ItemBasicData.vue         |   42 +-
 src/pages/Item/Card/ItemBotanical.vue         |    4 +-
 src/pages/Item/Card/ItemCard.vue              |    2 +-
 src/pages/Item/Card/ItemDescriptor.vue        |   26 +-
 src/pages/Item/Card/ItemDescriptorProxy.vue   |    6 +-
 src/pages/Item/Card/ItemShelving.vue          |   10 +-
 src/pages/Item/Card/ItemTags.vue              |    2 +-
 src/pages/Item/ItemFixedPrice.vue             |   16 +-
 .../Item/ItemType/Card/ItemTypeBasicData.vue  |    7 +-
 src/pages/Item/ItemType/Card/ItemTypeCard.vue |    6 +-
 .../Item/ItemType/Card/ItemTypeDescriptor.vue |   40 +-
 .../Item/ItemType/Card/ItemTypeFilter.js      |    8 -
 .../Item/ItemType/Card/ItemTypeSummary.vue    |   15 +-
 src/pages/Item/components/ItemProposal.vue    |  332 -----
 .../Item/components/ItemProposalProxy.vue     |   56 -
 src/pages/Item/locale/en.yml                  |   24 +-
 src/pages/Item/locale/es.yml                  |   31 +-
 src/pages/Monitor/MonitorOrders.vue           |    2 +-
 src/pages/Monitor/locale/en.yml               |    1 -
 src/pages/Monitor/locale/es.yml               |    1 -
 .../Order/Card/CatalogFilterValueDialog.vue   |    2 +-
 src/pages/Order/Card/OrderBasicData.vue       |    6 +-
 src/pages/Order/Card/OrderCard.vue            |    4 +-
 src/pages/Order/Card/OrderCatalogFilter.vue   |    4 +-
 .../Order/Card/OrderCatalogItemDialog.vue     |    8 +-
 src/pages/Order/Card/OrderDescriptor.vue      |   38 +-
 src/pages/Order/Card/OrderFilter.js           |   26 -
 src/pages/Order/Card/OrderLines.vue           |    4 +-
 src/pages/Order/Card/OrderSummary.vue         |    2 +-
 src/pages/Order/OrderList.vue                 |    7 +-
 .../Parking/Card/ParkingBasicData.vue         |   18 +-
 .../Parking/Card/ParkingCard.vue              |    6 +-
 .../Parking/Card/ParkingDescriptor.vue        |   16 +-
 .../Parking/Card/ParkingLog.vue               |    0
 .../Parking/Card/ParkingSummary.vue           |    0
 .../{Shelving => }/Parking/ParkingFilter.vue  |    0
 .../{Shelving => }/Parking/ParkingList.vue    |   13 +-
 .../{Shelving => }/Parking/locale/en.yml      |    0
 .../{Shelving => }/Parking/locale/es.yml      |    0
 src/pages/Route/Agency/AgencyList.vue         |    4 +-
 .../Route/Agency/Card/AgencyBasicData.vue     |    2 +-
 src/pages/Route/Agency/Card/AgencyCard.vue    |    2 +-
 .../Route/Agency/Card/AgencyDescriptor.vue    |    1 +
 .../Route/Agency/Card/AgencyWorkcenter.vue    |    2 +-
 src/pages/Route/Card/RouteCard.vue            |    5 +-
 src/pages/Route/Card/RouteDescriptor.vue      |   70 +-
 src/pages/Route/Card/RouteFilter.js           |   39 -
 src/pages/Route/Card/RouteFilter.vue          |    2 +-
 src/pages/Route/Card/RouteForm.vue            |   54 +-
 src/pages/Route/Roadmap/RoadmapBasicData.vue  |    5 +-
 src/pages/Route/Roadmap/RoadmapCard.vue       |    2 +-
 src/pages/Route/Roadmap/RoadmapDescriptor.vue |   18 +-
 src/pages/Route/Roadmap/RoadmapFilter.js      |    3 -
 src/pages/Route/Roadmap/RoadmapStops.vue      |    2 +-
 src/pages/Route/Roadmap/RoadmapSummary.vue    |    3 +-
 src/pages/Route/RouteExtendedList.vue         |  152 +--
 src/pages/Route/RouteList.vue                 |   31 -
 src/pages/Route/RouteTickets.vue              |   18 +-
 .../Route/Vehicle/Card/VehicleBasicData.vue   |  162 ---
 src/pages/Route/Vehicle/Card/VehicleCard.vue  |   13 -
 .../Route/Vehicle/Card/VehicleDescriptor.vue  |   49 -
 .../Route/Vehicle/Card/VehicleSummary.vue     |  127 --
 src/pages/Route/Vehicle/VehicleFilter.js      |   76 --
 src/pages/Route/Vehicle/VehicleList.vue       |  224 ---
 src/pages/Route/Vehicle/locale/en.yml         |   20 -
 src/pages/Route/Vehicle/locale/es.yml         |   20 -
 src/pages/Shelving/Card/ShelvingCard.vue      |    4 +-
 .../Shelving/Card/ShelvingDescriptor.vue      |   30 +-
 src/pages/Shelving/Card/ShelvingFilter.js     |   15 -
 src/pages/Shelving/Card/ShelvingForm.vue      |   32 +-
 src/pages/Shelving/Card/ShelvingSearchbar.vue |    8 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |   37 +-
 .../Shelving/Parking/Card/ParkingFilter.js    |    4 -
 .../Shelving/Parking/ParkingExprBuilder.js    |   10 -
 src/pages/Shelving/ShelvingExprBuilder.js     |   10 -
 src/pages/Shelving/ShelvingList.vue           |   26 +-
 src/pages/Supplier/Card/SupplierAccounts.vue  |    6 +-
 src/pages/Supplier/Card/SupplierAddresses.vue |    2 +-
 .../Supplier/Card/SupplierAgencyTerm.vue      |    2 +-
 src/pages/Supplier/Card/SupplierBasicData.vue |    3 +-
 src/pages/Supplier/Card/SupplierCard.vue      |   16 +-
 .../Supplier/Card/SupplierConsumption.vue     |  103 +-
 src/pages/Supplier/Card/SupplierContacts.vue  |    2 +-
 .../Supplier/Card/SupplierDescriptor.vue      |   49 +-
 src/pages/Supplier/Card/SupplierFilter.js     |   35 -
 .../Supplier/Card/SupplierFiscalData.vue      |   22 +-
 src/pages/Supplier/SupplierList.vue           |   91 +-
 src/pages/Supplier/SupplierListFilter.vue     |  122 ++
 .../Ticket/Card/BasicData/TicketBasicData.vue |   16 +-
 .../Card/BasicData/TicketBasicDataForm.vue    |    4 +-
 .../Card/BasicData/TicketBasicDataView.vue    |  116 +-
 src/pages/Ticket/Card/TicketCard.vue          |    8 +-
 src/pages/Ticket/Card/TicketComponents.vue    |    2 +-
 src/pages/Ticket/Card/TicketDescriptor.vue    |  139 +-
 src/pages/Ticket/Card/TicketExpedition.vue    |    2 +-
 src/pages/Ticket/Card/TicketFilter.js         |   72 -
 src/pages/Ticket/Card/TicketNotes.vue         |    4 +-
 src/pages/Ticket/Card/TicketPackage.vue       |    4 +-
 src/pages/Ticket/Card/TicketSale.vue          |   60 +-
 src/pages/Ticket/Card/TicketService.vue       |    6 +-
 src/pages/Ticket/Card/TicketSplit.vue         |   37 -
 src/pages/Ticket/Card/TicketSummary.vue       |   81 +-
 src/pages/Ticket/Card/TicketTracking.vue      |    4 +-
 src/pages/Ticket/Card/TicketTransfer.vue      |  131 +-
 src/pages/Ticket/Card/TicketTransferProxy.vue |   54 -
 src/pages/Ticket/Card/components/split.js     |   22 -
 .../Ticket/Negative/TicketLackDetail.vue      |  198 ---
 .../Ticket/Negative/TicketLackFilter.vue      |  175 ---
 src/pages/Ticket/Negative/TicketLackList.vue  |  227 ----
 src/pages/Ticket/Negative/TicketLackTable.vue |  356 -----
 .../Negative/components/ChangeItemDialog.vue  |   90 --
 .../components/ChangeQuantityDialog.vue       |   84 --
 .../Negative/components/ChangeStateDialog.vue |   91 --
 src/pages/Ticket/TicketFuture.vue             |  561 +++++---
 src/pages/Ticket/TicketFutureFilter.vue       |    4 +-
 src/pages/Ticket/locale/en.yml                |   87 +-
 src/pages/Ticket/locale/es.yml                |   83 --
 src/pages/Travel/Card/TravelBasicData.vue     |   19 +-
 src/pages/Travel/Card/TravelCard.vue          |   36 +-
 src/pages/Travel/Card/TravelDescriptor.vue    |    1 +
 src/pages/Travel/Card/TravelFilter.js         |    1 -
 src/pages/Travel/Card/TravelSummary.vue       |    8 -
 src/pages/Travel/Card/TravelThermographs.vue  |    2 +-
 src/pages/Travel/ExtraCommunityFilter.vue     |    2 +-
 src/pages/Travel/TravelList.vue               |   24 -
 src/pages/Wagon/Card/WagonCard.vue            |    2 +-
 src/pages/Wagon/Type/WagonTypeList.vue        |    8 +-
 src/pages/Worker/Card/WorkerBasicData.vue     |   17 +-
 src/pages/Worker/Card/WorkerCalendar.vue      |   32 +-
 .../Worker/Card/WorkerCalendarFilter.vue      |    2 +
 src/pages/Worker/Card/WorkerCard.vue          |    7 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |    9 +-
 .../Worker/Card/WorkerDescriptorProxy.vue     |    7 +-
 src/pages/Worker/Card/WorkerFormation.vue     |    3 +-
 src/pages/Worker/Card/WorkerMedical.vue       |   16 -
 src/pages/Worker/Card/WorkerOperator.vue      |   19 +-
 src/pages/Worker/Card/WorkerPda.vue           |   10 +-
 src/pages/Worker/Card/WorkerPit.vue           |    2 +-
 src/pages/Worker/Card/WorkerSummary.vue       |    2 +-
 src/pages/Worker/Card/WorkerTimeControl.vue   |   16 +-
 src/pages/Worker/WorkerDepartmentTree.vue     |    4 +-
 src/pages/Zone/Card/ZoneBasicData.vue         |   33 +-
 src/pages/Zone/Card/ZoneCard.vue              |   12 +-
 src/pages/Zone/Card/ZoneDescriptor.vue        |   44 +-
 src/pages/Zone/Card/ZoneEvents.vue            |    4 +-
 src/pages/Zone/Card/ZoneFilter.js             |   10 -
 src/pages/Zone/Card/ZoneSearchbar.vue         |   41 +-
 src/pages/Zone/Card/ZoneSummary.vue           |   18 +-
 src/pages/Zone/Card/ZoneWarehouses.vue        |    2 +-
 src/pages/Zone/Delivery/ZoneDeliveryList.vue  |    2 +-
 src/pages/Zone/Upcoming/ZoneUpcomingList.vue  |    2 +-
 src/pages/Zone/ZoneList.vue                   |   29 +-
 src/router/modules/account/aliasCard.js       |    2 +-
 src/router/modules/account/roleCard.js        |    1 -
 src/router/modules/entry.js                   |   17 +-
 src/router/modules/route.js                   |   52 -
 src/router/modules/shelving.js                |   11 +-
 src/router/modules/supplier.js                |  315 ++---
 src/router/modules/ticket.js                  |   34 +-
 src/router/modules/worker.js                  |    9 +-
 .../__tests__/useNavigationStore.spec.js      |  153 ---
 src/stores/useArrayDataStore.js               |    1 -
 src/utils/notifyResults.js                    |   19 -
 .../integration/Order/orderCatalog.spec.js    |    1 +
 .../integration/entry/entryList.spec.js       |  224 ---
 .../integration/entry/stockBought.spec.js     |   37 +-
 .../invoiceIn/invoiceInBasicData.spec.js      |   27 +-
 .../invoiceIn/invoiceInVat.spec.js            |    2 +-
 .../invoiceOutNegativeBases.spec.js           |    4 +-
 .../integration/item/ItemProposal.spec.js     |   11 -
 test/cypress/integration/item/itemTag.spec.js |    5 +-
 .../parking/parkingBasicData.spec.js          |    4 +-
 .../route/agency/agencyWorkCenter.spec.js     |    1 -
 .../integration/route/routeList.spec.js       |   19 +-
 .../route/vehicle/vehicleDescriptor.spec.js   |   13 -
 .../ticket/negative/TicketLackDetail.spec.js  |  147 --
 .../ticket/negative/TicketLackList.spec.js    |   36 -
 .../integration/ticket/ticketList.spec.js     |   25 -
 .../vnComponent/VnShortcut.spec.js            |   11 -
 .../wagon/wagonType/wagonTypeCreate.spec.js   |    2 +-
 .../integration/zone/zoneBasicData.spec.js    |   16 +-
 test/cypress/support/commands.js              |   71 +-
 test/cypress/support/waitUntil.js             |    2 +-
 338 files changed, 4377 insertions(+), 9582 deletions(-)
 delete mode 100644 src/boot/defaults/constants.js
 delete mode 100644 src/components/common/VnCheckbox.vue
 delete mode 100644 src/components/common/VnColor.vue
 delete mode 100644 src/components/common/VnPopupProxy.vue
 delete mode 100644 src/components/common/VnSelectTravelExtended.vue
 delete mode 100644 src/components/ui/VnStockValueDisplay.vue
 delete mode 100644 src/composables/checkEntryLock.js
 delete mode 100644 src/composables/getColAlign.js
 delete mode 100644 src/pages/Account/AccountExprBuilder.js
 delete mode 100644 src/pages/Account/Alias/AliasExprBuilder.js
 delete mode 100644 src/pages/Account/Card/AccountFilter.js
 delete mode 100644 src/pages/Account/Role/RoleExprBuilder.js
 rename src/pages/{Worker => }/Department/Card/DepartmentBasicData.vue (73%)
 rename src/pages/{Worker => }/Department/Card/DepartmentCard.vue (70%)
 rename src/pages/{Worker => }/Department/Card/DepartmentDescriptor.vue (84%)
 rename src/pages/{Worker => }/Department/Card/DepartmentDescriptorProxy.vue (100%)
 rename src/pages/{Worker => }/Department/Card/DepartmentSummary.vue (99%)
 rename src/pages/{Worker => }/Department/Card/DepartmentSummaryDialog.vue (100%)
 delete mode 100644 src/pages/InvoiceIn/Card/InvoiceInFilter.js
 delete mode 100644 src/pages/InvoiceOut/Card/InvoiceOutFilter.js
 rename src/pages/Item/{components => Card}/CreateGenusForm.vue (100%)
 rename src/pages/Item/{components => Card}/CreateSpecieForm.vue (100%)
 delete mode 100644 src/pages/Item/ItemType/Card/ItemTypeFilter.js
 delete mode 100644 src/pages/Item/components/ItemProposal.vue
 delete mode 100644 src/pages/Item/components/ItemProposalProxy.vue
 delete mode 100644 src/pages/Order/Card/OrderFilter.js
 rename src/pages/{Shelving => }/Parking/Card/ParkingBasicData.vue (68%)
 rename src/pages/{Shelving => }/Parking/Card/ParkingCard.vue (53%)
 rename src/pages/{Shelving => }/Parking/Card/ParkingDescriptor.vue (58%)
 rename src/pages/{Shelving => }/Parking/Card/ParkingLog.vue (100%)
 rename src/pages/{Shelving => }/Parking/Card/ParkingSummary.vue (100%)
 rename src/pages/{Shelving => }/Parking/ParkingFilter.vue (100%)
 rename src/pages/{Shelving => }/Parking/ParkingList.vue (90%)
 rename src/pages/{Shelving => }/Parking/locale/en.yml (100%)
 rename src/pages/{Shelving => }/Parking/locale/es.yml (100%)
 delete mode 100644 src/pages/Route/Card/RouteFilter.js
 delete mode 100644 src/pages/Route/Roadmap/RoadmapFilter.js
 delete mode 100644 src/pages/Route/Vehicle/Card/VehicleBasicData.vue
 delete mode 100644 src/pages/Route/Vehicle/Card/VehicleCard.vue
 delete mode 100644 src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
 delete mode 100644 src/pages/Route/Vehicle/Card/VehicleSummary.vue
 delete mode 100644 src/pages/Route/Vehicle/VehicleFilter.js
 delete mode 100644 src/pages/Route/Vehicle/VehicleList.vue
 delete mode 100644 src/pages/Route/Vehicle/locale/en.yml
 delete mode 100644 src/pages/Route/Vehicle/locale/es.yml
 delete mode 100644 src/pages/Shelving/Card/ShelvingFilter.js
 delete mode 100644 src/pages/Shelving/Parking/Card/ParkingFilter.js
 delete mode 100644 src/pages/Shelving/Parking/ParkingExprBuilder.js
 delete mode 100644 src/pages/Shelving/ShelvingExprBuilder.js
 delete mode 100644 src/pages/Supplier/Card/SupplierFilter.js
 create mode 100644 src/pages/Supplier/SupplierListFilter.vue
 delete mode 100644 src/pages/Ticket/Card/TicketFilter.js
 delete mode 100644 src/pages/Ticket/Card/TicketSplit.vue
 delete mode 100644 src/pages/Ticket/Card/TicketTransferProxy.vue
 delete mode 100644 src/pages/Ticket/Card/components/split.js
 delete mode 100644 src/pages/Ticket/Negative/TicketLackDetail.vue
 delete mode 100644 src/pages/Ticket/Negative/TicketLackFilter.vue
 delete mode 100644 src/pages/Ticket/Negative/TicketLackList.vue
 delete mode 100644 src/pages/Ticket/Negative/TicketLackTable.vue
 delete mode 100644 src/pages/Ticket/Negative/components/ChangeItemDialog.vue
 delete mode 100644 src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
 delete mode 100644 src/pages/Ticket/Negative/components/ChangeStateDialog.vue
 delete mode 100644 src/pages/Zone/Card/ZoneFilter.js
 delete mode 100644 src/stores/__tests__/useNavigationStore.spec.js
 delete mode 100644 src/utils/notifyResults.js
 delete mode 100644 test/cypress/integration/entry/entryList.spec.js
 delete mode 100644 test/cypress/integration/item/ItemProposal.spec.js
 delete mode 100644 test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
 delete mode 100644 test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
 delete mode 100644 test/cypress/integration/ticket/negative/TicketLackList.spec.js

diff --git a/cypress.config.js b/cypress.config.js
index a9e27fcfd..1924144f6 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -14,8 +14,8 @@ export default defineConfig({
         downloadsFolder: 'test/cypress/downloads',
         video: false,
         specPattern: 'test/cypress/integration/**/*.spec.js',
-        experimentalRunAllSpecs: false,
-        watchForFileChanges: false,
+        experimentalRunAllSpecs: true,
+        watchForFileChanges: true,
         reporter: 'cypress-mochawesome-reporter',
         reporterOptions: {
             charts: true,
diff --git a/package.json b/package.json
index d23ed0ced..17f39cad7 100644
--- a/package.json
+++ b/package.json
@@ -1,74 +1,74 @@
 {
-    "name": "salix-front",
-    "version": "25.08.0",
-    "description": "Salix frontend",
-    "productName": "Salix",
-    "author": "Verdnatura",
-    "private": true,
-    "packageManager": "pnpm@8.15.1",
-    "type": "module",
-    "scripts": {
-        "resetDatabase": "cd ../salix && gulp docker",
-        "lint": "eslint --ext .js,.vue ./",
-        "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
-        "test:e2e": "cypress open",
-        "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
-        "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
-        "test:unit": "vitest",
-        "test:unit:ci": "vitest run",
-        "commitlint": "commitlint --edit",
-        "prepare": "npx husky install",
-        "addReferenceTag": "node .husky/addReferenceTag.js",
-        "docs:dev": "vitepress dev docs",
-        "docs:build": "vitepress build docs",
-        "docs:preview": "vitepress preview docs"
-    },
-    "dependencies": {
-        "@quasar/cli": "^2.4.1",
-        "@quasar/extras": "^1.16.16",
-        "axios": "^1.4.0",
-        "chromium": "^3.0.3",
-        "croppie": "^2.6.5",
-        "moment": "^2.30.1",
-        "pinia": "^2.1.3",
-        "quasar": "^2.17.7",
-        "validator": "^13.9.0",
-        "vue": "^3.5.13",
-        "vue-i18n": "^9.3.0",
-        "vue-router": "^4.2.5"
-    },
-    "devDependencies": {
-        "@commitlint/cli": "^19.2.1",
-        "@commitlint/config-conventional": "^19.1.0",
-        "@intlify/unplugin-vue-i18n": "^0.8.2",
-        "@pinia/testing": "^0.1.2",
-        "@quasar/app-vite": "^2.0.8",
-        "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
-        "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
-        "@vue/test-utils": "^2.4.4",
-        "autoprefixer": "^10.4.14",
-        "cypress": "^13.6.6",
-        "cypress-mochawesome-reporter": "^3.8.2",
-        "eslint": "^9.18.0",
-        "eslint-config-prettier": "^10.0.1",
-        "eslint-plugin-cypress": "^4.1.0",
-        "eslint-plugin-vue": "^9.32.0",
-        "husky": "^8.0.0",
-        "postcss": "^8.4.23",
-        "prettier": "^3.4.2",
-        "sass": "^1.83.4",
-        "vitepress": "^1.6.3",
-        "vitest": "^0.34.0"
-    },
-    "engines": {
-        "node": "^20 || ^18 || ^16",
-        "npm": ">= 8.1.2",
-        "yarn": ">= 1.21.1",
-        "bun": ">= 1.0.25"
-    },
-    "overrides": {
-        "@vitejs/plugin-vue": "^5.2.1",
-        "vite": "^6.0.11",
-        "vitest": "^0.31.1"
-    }
+  "name": "salix-front",
+  "version": "25.06.0",
+  "description": "Salix frontend",
+  "productName": "Salix",
+  "author": "Verdnatura",
+  "private": true,
+  "packageManager": "pnpm@8.15.1",
+  "type": "module",
+  "scripts": {
+    "resetDatabase": "cd ../salix && gulp docker",
+    "lint": "eslint --ext .js,.vue ./",
+    "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
+    "test:e2e": "cypress open",
+    "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
+    "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+    "test:unit": "vitest",
+    "test:unit:ci": "vitest run",
+    "commitlint": "commitlint --edit",
+    "prepare": "npx husky install",
+    "addReferenceTag": "node .husky/addReferenceTag.js",
+    "docs:dev": "vitepress dev docs",
+    "docs:build": "vitepress build docs",
+    "docs:preview": "vitepress preview docs"
+  },
+  "dependencies": {
+    "@quasar/cli": "^2.4.1",
+    "@quasar/extras": "^1.16.16",
+    "axios": "^1.4.0",
+    "chromium": "^3.0.3",
+    "croppie": "^2.6.5",
+    "moment": "^2.30.1",
+    "pinia": "^2.1.3",
+    "quasar": "^2.17.7",
+    "validator": "^13.9.0",
+    "vue": "^3.5.13",
+    "vue-i18n": "^9.3.0",
+    "vue-router": "^4.2.5"
+  },
+  "devDependencies": {
+    "@commitlint/cli": "^19.2.1",
+    "@commitlint/config-conventional": "^19.1.0",
+    "@intlify/unplugin-vue-i18n": "^0.8.2",
+    "@pinia/testing": "^0.1.2",
+    "@quasar/app-vite": "^2.0.8",
+    "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
+    "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
+    "@vue/test-utils": "^2.4.4",
+    "autoprefixer": "^10.4.14",
+    "cypress": "^13.6.6",
+    "cypress-mochawesome-reporter": "^3.8.2",
+    "eslint": "^9.18.0",
+    "eslint-config-prettier": "^10.0.1",
+    "eslint-plugin-cypress": "^4.1.0",
+    "eslint-plugin-vue": "^9.32.0",
+    "husky": "^8.0.0",
+    "postcss": "^8.4.23",
+    "prettier": "^3.4.2",
+    "sass": "^1.83.4",
+    "vitepress": "^1.6.3",
+    "vitest": "^0.34.0"
+  },
+  "engines": {
+    "node": "^20 || ^18 || ^16",
+    "npm": ">= 8.1.2",
+    "yarn": ">= 1.21.1",
+    "bun": ">= 1.0.25"
+  },
+  "overrides": {
+    "@vitejs/plugin-vue": "^5.2.1",
+    "vite": "^6.0.11",
+    "vitest": "^0.31.1"
+  }
 }
\ No newline at end of file
diff --git a/quasar.config.js b/quasar.config.js
index 9467c92af..6d545c026 100644
--- a/quasar.config.js
+++ b/quasar.config.js
@@ -30,6 +30,7 @@ export default configure(function (/* ctx */) {
         // --> boot files are part of "main.js"
         // https://v2.quasar.dev/quasar-cli/boot-files
         boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'],
+
         // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
         css: ['app.scss'],
 
diff --git a/src/boot/defaults/constants.js b/src/boot/defaults/constants.js
deleted file mode 100644
index c96ceb2d1..000000000
--- a/src/boot/defaults/constants.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const langs = ['en', 'es'];
-export const decimalPlaces = 2;
diff --git a/src/boot/keyShortcut.js b/src/boot/keyShortcut.js
index 6da06c8bf..5afb5b74a 100644
--- a/src/boot/keyShortcut.js
+++ b/src/boot/keyShortcut.js
@@ -1,6 +1,6 @@
 export default {
-    mounted(el, binding) {
-        const shortcut = binding.value || '+';
+    mounted: function (el, binding) {
+        const shortcut = binding.value ?? '+';
 
         const { key, ctrl, alt, callback } =
             typeof shortcut === 'string'
@@ -8,24 +8,25 @@ export default {
                       key: shortcut,
                       ctrl: true,
                       alt: true,
-                      callback: () => el?.click(),
+                      callback: () =>
+                          document
+                              .querySelector(`button[shortcut="${shortcut}"]`)
+                              ?.click(),
                   }
                 : binding.value;
 
-        if (!el.hasAttribute('shortcut')) {
-            el.setAttribute('shortcut', key);
-        }
-
         const handleKeydown = (event) => {
             if (event.key === key && (!ctrl || event.ctrlKey) && (!alt || event.altKey)) {
                 callback();
             }
         };
 
+        // Attach the event listener to the window
         window.addEventListener('keydown', handleKeydown);
+
         el._handleKeydown = handleKeydown;
     },
-    unmounted(el) {
+    unmounted: function (el) {
         if (el._handleKeydown) {
             window.removeEventListener('keydown', el._handleKeydown);
         }
diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js
index 182c51e47..97d80c670 100644
--- a/src/boot/qformMixin.js
+++ b/src/boot/qformMixin.js
@@ -9,19 +9,19 @@ export default {
         if (!form) return;
         try {
             const inputsFormCard = form.querySelectorAll(
-                `input:not([disabled]):not([type="checkbox"])`,
+                `input:not([disabled]):not([type="checkbox"])`
             );
             if (inputsFormCard.length) {
                 focusFirstInput(inputsFormCard[0]);
             }
             const textareas = document.querySelectorAll(
-                'textarea:not([disabled]), [contenteditable]:not([disabled])',
+                'textarea:not([disabled]), [contenteditable]:not([disabled])'
             );
             if (textareas.length) {
                 focusFirstInput(textareas[textareas.length - 1]);
             }
             const inputs = document.querySelectorAll(
-                'form#formModel input:not([disabled]):not([type="checkbox"])',
+                'form#formModel input:not([disabled]):not([type="checkbox"])'
             );
             const input = inputs[0];
             if (!input) return;
@@ -30,5 +30,22 @@ export default {
         } catch (error) {
             console.error(error);
         }
+        form.addEventListener('keyup', function (evt) {
+            if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
+                const input = evt.target;
+                if (input.type == 'textarea' && evt.shiftKey) {
+                    evt.preventDefault();
+                    let { selectionStart, selectionEnd } = input;
+                    input.value =
+                        input.value.substring(0, selectionStart) +
+                        '\n' +
+                        input.value.substring(selectionEnd);
+                    selectionStart = selectionEnd = selectionStart + 1;
+                    return;
+                }
+                evt.preventDefault();
+                that.onSubmit();
+            }
+        });
     },
 };
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index a8c397b83..547517682 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -51,5 +51,4 @@ export default boot(({ app }) => {
 
         await useCau(response, message);
     };
-    app.provide('app', app);
 });
diff --git a/src/components/CreateBankEntityForm.vue b/src/components/CreateBankEntityForm.vue
index 7c4b94a6a..2da3aa994 100644
--- a/src/components/CreateBankEntityForm.vue
+++ b/src/components/CreateBankEntityForm.vue
@@ -14,7 +14,7 @@ const { t } = useI18n();
 const bicInputRef = ref(null);
 const state = useState();
 
-const customer = computed(() => state.get('Customer'));
+const customer = computed(() => state.get('customer'));
 
 const countriesFilter = {
     fields: ['id', 'name', 'code'],
diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue
index 93a2ac96a..d569dfda1 100644
--- a/src/components/CrudModel.vue
+++ b/src/components/CrudModel.vue
@@ -64,10 +64,6 @@ const $props = defineProps({
         type: Function,
         default: null,
     },
-    beforeSaveFn: {
-        type: Function,
-        default: null,
-    },
     goTo: {
         type: String,
         default: '',
@@ -180,11 +176,7 @@ async function saveChanges(data) {
         hasChanges.value = false;
         return;
     }
-    let changes = data || getChanges();
-    if ($props.beforeSaveFn) {
-        changes = await $props.beforeSaveFn(changes, getChanges);
-    }
-
+    const changes = data || getChanges();
     try {
         await axios.post($props.saveUrl || $props.url + '/crud', changes);
     } finally {
@@ -237,12 +229,12 @@ async function remove(data) {
                 componentProps: {
                     title: t('globals.confirmDeletion'),
                     message: t('globals.confirmDeletionMessage'),
-                    data: { deletes: ids },
+                    newData,
                     ids,
-                    promise: saveChanges,
                 },
             })
             .onOk(async () => {
+                await saveChanges({ deletes: ids });
                 newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
                 fetch(newData);
             });
@@ -382,8 +374,6 @@ watch(formUrl, async () => {
                 @click="onSubmit"
                 :disable="!hasChanges"
                 :title="t('globals.save')"
-                v-shortcut="'s'"
-                shortcut="s"
                 data-cy="crudModelDefaultSaveBtn"
             />
             <slot name="moreAfterActions" />
diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue
index 765d97763..4d43c3810 100644
--- a/src/components/FilterTravelForm.vue
+++ b/src/components/FilterTravelForm.vue
@@ -181,7 +181,6 @@ const selectTravel = ({ id }) => {
                     color="primary"
                     :disabled="isLoading"
                     :loading="isLoading"
-                    data-cy="save-filter-travel-form"
                 />
             </div>
             <QTable
@@ -192,10 +191,9 @@ const selectTravel = ({ id }) => {
                 :no-data-label="t('Enter a new search')"
                 class="q-mt-lg"
                 @row-click="(_, row) => selectTravel(row)"
-                data-cy="table-filter-travel-form"
             >
                 <template #body-cell-id="{ row }">
-                    <QTd auto-width @click.stop data-cy="travelFk-travel-form">
+                    <QTd auto-width @click.stop>
                         <QBtn flat color="blue">{{ row.id }}</QBtn>
                         <TravelDescriptorProxy :id="row.id" />
                     </QTd>
diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 04ef13d45..3842ff947 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { onMounted, onUnmounted, computed, ref, watch, nextTick, useAttrs } from 'vue';
+import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue';
 import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -22,7 +22,6 @@ const { validate } = useValidator();
 const { notify } = useNotify();
 const route = useRoute();
 const myForm = ref(null);
-const attrs = useAttrs();
 const $props = defineProps({
     url: {
         type: String,
@@ -85,7 +84,7 @@ const $props = defineProps({
     },
     reload: {
         type: Boolean,
-        default: true,
+        default: false,
     },
     defaultTrim: {
         type: Boolean,
@@ -106,15 +105,15 @@ const isLoading = ref(false);
 // Si elegimos observar los cambios del form significa que inicialmente las actions estaran deshabilitadas
 const isResetting = ref(false);
 const hasChanges = ref(!$props.observeFormChanges);
-const originalData = computed(() => state.get(modelValue));
-const formData = ref();
+const originalData = ref({});
+const formData = computed(() => state.get(modelValue));
 const defaultButtons = computed(() => ({
     save: {
         dataCy: 'saveDefaultBtn',
         color: 'primary',
         icon: 'save',
         label: 'globals.save',
-        click: async () => await save(),
+        click: () => myForm.value.submit(),
         type: 'submit',
     },
     reset: {
@@ -128,6 +127,8 @@ const defaultButtons = computed(() => ({
 }));
 
 onMounted(async () => {
+    originalData.value = JSON.parse(JSON.stringify($props.formInitialData ?? {}));
+
     nextTick(() => (componentIsRendered.value = true));
 
     // Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla
@@ -159,18 +160,10 @@ if (!$props.url)
         (val) => updateAndEmit('onFetch', { val }),
     );
 
-watch(
-    originalData,
-    (val) => {
-        if (val) formData.value = JSON.parse(JSON.stringify(val));
-    },
-    { immediate: true },
-);
-
 watch(
     () => [$props.url, $props.filter],
     async () => {
-        state.set(modelValue, null);
+        originalData.value = null;
         reset();
         await fetch();
     },
@@ -205,6 +198,7 @@ async function fetch() {
         updateAndEmit('onFetch', { val: data });
     } catch (e) {
         state.set(modelValue, {});
+        originalData.value = {};
         throw e;
     }
 }
@@ -247,7 +241,6 @@ async function saveAndGo() {
 }
 
 function reset() {
-    formData.value = JSON.parse(JSON.stringify(originalData.value));
     updateAndEmit('onFetch', { val: originalData.value });
     if ($props.observeFormChanges) {
         hasChanges.value = false;
@@ -272,6 +265,7 @@ function filter(value, update, filterOptions) {
 
 function updateAndEmit(evt, { val, res, old } = { val: null, res: null, old: null }) {
     state.set(modelValue, val);
+    originalData.value = val && JSON.parse(JSON.stringify(val));
     if (!$props.url) arrayData.store.data = val;
 
     emit(evt, state.get(modelValue), res, old);
@@ -285,22 +279,6 @@ function trimData(data) {
     return data;
 }
 
-async function onKeyup(evt) {
-    if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
-        const input = evt.target;
-        if (input.type == 'textarea' && evt.shiftKey) {
-            let { selectionStart, selectionEnd } = input;
-            input.value =
-                input.value.substring(0, selectionStart) +
-                '\n' +
-                input.value.substring(selectionEnd);
-            selectionStart = selectionEnd = selectionStart + 1;
-            return;
-        }
-        await save();
-    }
-}
-
 defineExpose({
     save,
     isLoading,
@@ -315,12 +293,12 @@ defineExpose({
         <QForm
             ref="myForm"
             v-if="formData"
-            @submit.prevent
-            @keyup.prevent="onKeyup"
+            @submit="save"
             @reset="reset"
             class="q-pa-md"
             :style="maxWidth ? 'max-width: ' + maxWidth : ''"
             id="formModel"
+            :prevent-submit="$attrs['prevent-submit']"
         >
             <QCard>
                 <slot
diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index 85943e91e..afdc6efca 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -1,13 +1,12 @@
 <script setup>
-import { ref, computed, useAttrs, nextTick } from 'vue';
+import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useState } from 'src/composables/useState';
 
 import FormModel from 'components/FormModel.vue';
 
 const emit = defineEmits(['onDataSaved', 'onDataCanceled']);
 
-const props = defineProps({
+defineProps({
     title: {
         type: String,
         default: '',
@@ -16,41 +15,23 @@ const props = defineProps({
         type: String,
         default: '',
     },
-    showSaveAndContinueBtn: {
-        type: Boolean,
-        default: false,
-    },
 });
 
 const { t } = useI18n();
-const attrs = useAttrs();
-const state = useState();
+
 const formModelRef = ref(null);
 const closeButton = ref(null);
-const isSaveAndContinue = ref(props.showSaveAndContinueBtn);
-const isLoading = computed(() => formModelRef.value?.isLoading);
-const reset = computed(() => formModelRef.value?.reset);
 
-const onDataSaved = async (formData, requestResponse) => {
-    if (!isSaveAndContinue.value) closeButton.value?.click();
-    if (isSaveAndContinue.value) {
-        await nextTick();
-        state.set(attrs.model, attrs.formInitialData);
-    }
-    isSaveAndContinue.value = props.showSaveAndContinueBtn;
+const onDataSaved = (formData, requestResponse) => {
+    if (closeButton.value) closeButton.value.click();
     emit('onDataSaved', formData, requestResponse);
 };
 
-const onClick = async (saveAndContinue) => {
-    isSaveAndContinue.value = saveAndContinue;
-    await formModelRef.value.save();
-};
+const isLoading = computed(() => formModelRef.value?.isLoading);
 
 defineExpose({
     isLoading,
     onDataSaved,
-    isSaveAndContinue,
-    reset,
 });
 </script>
 
@@ -78,16 +59,15 @@ defineExpose({
                     flat
                     :disabled="isLoading"
                     :loading="isLoading"
-                    data-cy="FormModelPopup_cancel"
-                    v-close-popup
-                    z-max
                     @click="emit('onDataCanceled')"
+                    v-close-popup
+                    data-cy="FormModelPopup_cancel"
+                    z-max
                 />
                 <QBtn
-                    :flat="showSaveAndContinueBtn"
                     :label="t('globals.save')"
                     :title="t('globals.save')"
-                    @click="onClick(false)"
+                    type="submit"
                     color="primary"
                     class="q-ml-sm"
                     :disabled="isLoading"
@@ -95,18 +75,6 @@ defineExpose({
                     data-cy="FormModelPopup_save"
                     z-max
                 />
-                <QBtn
-                    v-if="showSaveAndContinueBtn"
-                    :label="t('globals.isSaveAndContinue')"
-                    :title="t('globals.isSaveAndContinue')"
-                    color="primary"
-                    class="q-ml-sm"
-                    :disabled="isLoading"
-                    :loading="isLoading"
-                    data-cy="FormModelPopup_isSaveAndContinue"
-                    z-max
-                    @click="onClick(true)"
-                />
             </div>
         </template>
     </FormModel>
diff --git a/src/components/ItemsFilterPanel.vue b/src/components/ItemsFilterPanel.vue
index f73753a6b..36123b834 100644
--- a/src/components/ItemsFilterPanel.vue
+++ b/src/components/ItemsFilterPanel.vue
@@ -281,7 +281,7 @@ const setCategoryList = (data) => {
             <QItem class="q-mt-lg">
                 <QBtn
                     icon="add_circle"
-                    v-shortcut="'+'"
+                    shortcut="+"
                     flat
                     class="fill-icon-on-hover q-px-xs"
                     color="primary"
@@ -327,6 +327,7 @@ en:
         active: Is active
         visible: Is visible
         floramondo: Is floramondo
+        salesPersonFk: Buyer
         categoryFk: Category
 
 es:
@@ -337,6 +338,7 @@ es:
         active: Activo
         visible: Visible
         floramondo: Floramondo
+        salesPersonFk: Comprador
         categoryFk: Categoría
     Plant: Planta natural
     Flower: Flor fresca
diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 9a9949499..644f831d4 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -41,6 +41,7 @@ const filteredItems = computed(() => {
         return locale.includes(normalizedSearch);
     });
 });
+
 const filteredPinnedModules = computed(() => {
     if (!search.value) return pinnedModules.value;
     const normalizedSearch = search.value
@@ -71,7 +72,7 @@ watch(
         items.value = [];
         getRoutes();
     },
-    { deep: true },
+    { deep: true }
 );
 
 function findMatches(search, item) {
@@ -103,40 +104,33 @@ function addChildren(module, route, parent) {
 }
 
 function getRoutes() {
-    const handleRoutes = {
-        main: getMainRoutes,
-        card: getCardRoutes,
-    };
-    try {
-        handleRoutes[props.source]();
-    } catch (error) {
-        throw new Error(`Method is not defined`);
-    }
-}
-function getMainRoutes() {
-    const modules = Object.assign([], navigation.getModules().value);
+    if (props.source === 'main') {
+        const modules = Object.assign([], navigation.getModules().value);
 
-    for (const item of modules) {
-        const moduleDef = routes.find(
-            (route) => toLowerCamel(route.name) === item.module,
+        for (const item of modules) {
+            const moduleDef = routes.find(
+                (route) => toLowerCamel(route.name) === item.module
+            );
+            if (!moduleDef) continue;
+            item.children = [];
+
+            addChildren(item.module, moduleDef, item.children);
+        }
+
+        items.value = modules;
+    }
+
+    if (props.source === 'card') {
+        const currentRoute = route.matched[1];
+        const currentModule = toLowerCamel(currentRoute.name);
+        let moduleDef = routes.find(
+            (route) => toLowerCamel(route.name) === currentModule
         );
-        if (!moduleDef) continue;
-        item.children = [];
 
-        addChildren(item.module, moduleDef, item.children);
+        if (!moduleDef) return;
+        if (!moduleDef?.menus) moduleDef = betaGetRoutes();
+        addChildren(currentModule, moduleDef, items.value);
     }
-
-    items.value = modules;
-}
-
-function getCardRoutes() {
-    const currentRoute = route.matched[1];
-    const currentModule = toLowerCamel(currentRoute.name);
-    let moduleDef = routes.find((route) => toLowerCamel(route.name) === currentModule);
-
-    if (!moduleDef) return;
-    if (!moduleDef?.menus) moduleDef = betaGetRoutes();
-    addChildren(currentModule, moduleDef, items.value);
 }
 
 function betaGetRoutes() {
@@ -229,16 +223,9 @@ const searchModule = () => {
                 </template>
                 <template v-for="(item, index) in filteredItems" :key="item.name">
                     <template
-                        v-if="
-                            search ||
-                            (item.children && !filteredPinnedModules.has(item.name))
-                        "
+                        v-if="search ||item.children && !filteredPinnedModules.has(item.name)"
                     >
-                        <LeftMenuItem
-                            :item="item"
-                            group="modules"
-                            :class="search && index === 0 ? 'searched' : ''"
-                        >
+                        <LeftMenuItem :item="item" group="modules" :class="search && index === 0 ? 'searched' : ''">
                             <template #side>
                                 <QBtn
                                     v-if="item.isPinned === true"
@@ -355,7 +342,7 @@ const searchModule = () => {
 .header {
     color: var(--vn-label-color);
 }
-.searched {
+.searched{
     background-color: var(--vn-section-hover-color);
 }
 </style>
diff --git a/src/components/LeftMenuItem.vue b/src/components/LeftMenuItem.vue
index c0cee44fe..a3112b17f 100644
--- a/src/components/LeftMenuItem.vue
+++ b/src/components/LeftMenuItem.vue
@@ -26,7 +26,6 @@ const itemComputed = computed(() => {
         :to="{ name: itemComputed.name }"
         clickable
         v-ripple
-        :data-cy="`${itemComputed.name}-menu-item`"
     >
         <QItemSection avatar v-if="itemComputed.icon">
             <QIcon :name="itemComputed.icon" />
diff --git a/src/components/RefundInvoiceForm.vue b/src/components/RefundInvoiceForm.vue
index 6dcb8b390..590acede0 100644
--- a/src/components/RefundInvoiceForm.vue
+++ b/src/components/RefundInvoiceForm.vue
@@ -9,7 +9,6 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -132,11 +131,15 @@ const refund = async () => {
                         :required="true"
                     /> </VnRow
                 ><VnRow>
-                    <VnCheckbox
-                        v-model="invoiceParams.inheritWarehouse"
-                        :label="t('Inherit warehouse')"
-                        :info="t('Inherit warehouse tooltip')"
-                    />
+                    <div>
+                        <QCheckbox
+                            :label="t('Inherit warehouse')"
+                            v-model="invoiceParams.inheritWarehouse"
+                        />
+                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
+                            <QTooltip>{{ t('Inherit warehouse tooltip') }}</QTooltip>
+                        </QIcon>
+                    </div>
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue
index 783f2556f..934b13a1c 100644
--- a/src/components/TicketProblems.vue
+++ b/src/components/TicketProblems.vue
@@ -4,21 +4,26 @@ import { toCurrency } from 'src/filters';
 defineProps({ row: { type: Object, required: true } });
 </script>
 <template>
-    <span class="q-gutter-x-xs">
-        <router-link
-            v-if="row.claim?.claimFk"
-            :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
-            class="link"
-        >
-            <QIcon name="vn:claims" size="xs">
-                <QTooltip>
-                    {{ t('ticketSale.claim') }}:
-                    {{ row.claim?.claimFk }}
-                </QTooltip>
-            </QIcon>
-        </router-link>
+    <span>
         <QIcon
-            v-if="row?.risk"
+            v-if="row.isTaxDataChecked === 0"
+            name="vn:no036"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row.hasTicketRequest" name="vn:buyrequest" color="primary" size="xs">
+            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row.itemShortage" name="vn:unavailable" color="primary" size="xs">
+            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row.isFreezed" name="vn:frozen" color="primary" size="xs">
+            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row.risk"
             name="vn:risk"
             :color="row.hasHighRisk ? 'negative' : 'primary'"
             size="xs"
@@ -28,57 +33,10 @@ defineProps({ row: { type: Object, required: true } });
                 {{ toCurrency(row.risk - row.credit) }}
             </QTooltip>
         </QIcon>
-        <QIcon
-            v-if="row?.hasComponentLack"
-            name="vn:components"
-            color="primary"
-            size="xs"
-        >
+        <QIcon v-if="row.hasComponentLack" name="vn:components" color="primary" size="xs">
             <QTooltip>{{ $t('salesTicketsTable.componentLack') }}</QTooltip>
         </QIcon>
-        <QIcon v-if="row?.hasItemDelay" color="primary" size="xs" name="vn:hasItemDelay">
-            <QTooltip>
-                {{ $t('ticket.summary.hasItemDelay') }}
-            </QTooltip>
-        </QIcon>
-        <QIcon v-if="row?.hasItemLost" color="primary" size="xs" name="vn:hasItemLost">
-            <QTooltip>
-                {{ $t('salesTicketsTable.hasItemLost') }}
-            </QTooltip>
-        </QIcon>
-        <QIcon
-            v-if="row?.hasItemShortage"
-            name="vn:unavailable"
-            color="primary"
-            size="xs"
-        >
-            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row?.hasRounding" color="primary" name="sync_problem" size="xs">
-            <QTooltip>
-                {{ $t('ticketList.rounding') }}
-            </QTooltip>
-        </QIcon>
-        <QIcon
-            v-if="row?.hasTicketRequest"
-            name="vn:buyrequest"
-            color="primary"
-            size="xs"
-        >
-            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
-        </QIcon>
-        <QIcon
-            v-if="row?.isTaxDataChecked !== 0"
-            name="vn:no036"
-            color="primary"
-            size="xs"
-        >
-            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row?.isFreezed" name="vn:frozen" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row?.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
+        <QIcon v-if="row.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
             <QTooltip>{{ $t('salesTicketsTable.tooLittle') }}</QTooltip>
         </QIcon>
     </span>
diff --git a/src/components/TransferInvoiceForm.vue b/src/components/TransferInvoiceForm.vue
index c4ef1454a..aa71070d6 100644
--- a/src/components/TransferInvoiceForm.vue
+++ b/src/components/TransferInvoiceForm.vue
@@ -10,7 +10,6 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
-import VnCheckbox from './common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -187,11 +186,15 @@ const makeInvoice = async () => {
                     />
                 </VnRow>
                 <VnRow>
-                    <VnCheckbox
-                        v-model="checked"
-                        :label="t('Bill destination client')"
-                        :info="t('transferInvoiceInfo')"
-                    />
+                    <div>
+                        <QCheckbox
+                            :label="t('Bill destination client')"
+                            v-model="checked"
+                        />
+                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
+                            <QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
+                        </QIcon>
+                    </div>
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/VnTable/VnColumn.vue b/src/components/VnTable/VnColumn.vue
index d0e245388..9e9bfad69 100644
--- a/src/components/VnTable/VnColumn.vue
+++ b/src/components/VnTable/VnColumn.vue
@@ -1,8 +1,9 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QIcon, QToggle } from 'quasar';
+import { QIcon, QCheckbox } from 'quasar';
 import { dashIfEmpty } from 'src/filters';
 
+/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnSelectCache from 'components/common/VnSelectCache.vue';
 import VnInput from 'components/common/VnInput.vue';
@@ -11,11 +12,8 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
 import VnComponent from 'components/common/VnComponent.vue';
 import VnUserLink from 'components/ui/VnUserLink.vue';
-import VnSelectEnum from '../common/VnSelectEnum.vue';
-import VnCheckbox from '../common/VnCheckbox.vue';
 
 const model = defineModel(undefined, { required: true });
-const emit = defineEmits(['blur']);
 const $props = defineProps({
     column: {
         type: Object,
@@ -41,18 +39,10 @@ const $props = defineProps({
         type: Object,
         default: null,
     },
-    autofocus: {
-        type: Boolean,
-        default: false,
-    },
     showLabel: {
         type: Boolean,
         default: null,
     },
-    eventHandlers: {
-        type: Object,
-        default: null,
-    },
 });
 
 const defaultSelect = {
@@ -109,8 +99,7 @@ const defaultComponents = {
         },
     },
     checkbox: {
-        ref: 'checkbox',
-        component: markRaw(VnCheckbox),
+        component: markRaw(QCheckbox),
         attrs: ({ model }) => {
             const defaultAttrs = {
                 disable: !$props.isEditable,
@@ -126,10 +115,6 @@ const defaultComponents = {
         },
         forceAttrs: {
             label: $props.showLabel && $props.column.label,
-            autofocus: true,
-        },
-        events: {
-            blur: () => emit('blur'),
         },
     },
     select: {
@@ -140,19 +125,12 @@ const defaultComponents = {
         component: markRaw(VnSelect),
         ...defaultSelect,
     },
-    selectEnum: {
-        component: markRaw(VnSelectEnum),
-        ...defaultSelect,
-    },
     icon: {
         component: markRaw(QIcon),
     },
     userLink: {
         component: markRaw(VnUserLink),
     },
-    toggle: {
-        component: markRaw(QToggle),
-    },
 };
 
 const value = computed(() => {
@@ -182,28 +160,7 @@ const col = computed(() => {
     return newColumn;
 });
 
-const components = computed(() => {
-    const sourceComponents = $props.components ?? defaultComponents;
-
-    return Object.keys(sourceComponents).reduce((acc, key) => {
-        const component = sourceComponents[key];
-
-        if (!component || typeof component !== 'object') {
-            acc[key] = component;
-            return acc;
-        }
-
-        acc[key] = {
-            ...component,
-            attrs: {
-                ...(component.attrs || {}),
-                autofocus: $props.autofocus,
-            },
-            event: { ...component?.event, ...$props?.eventHandlers },
-        };
-        return acc;
-    }, {});
-});
+const components = computed(() => $props.components ?? defaultComponents);
 </script>
 <template>
     <div class="row no-wrap">
diff --git a/src/components/VnTable/VnFilter.vue b/src/components/VnTable/VnFilter.vue
index 0de3834ea..426f5c716 100644
--- a/src/components/VnTable/VnFilter.vue
+++ b/src/components/VnTable/VnFilter.vue
@@ -1,12 +1,14 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QCheckbox, QToggle } from 'quasar';
+import { QCheckbox } from 'quasar';
 import { useArrayData } from 'composables/useArrayData';
+
+/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnInput from 'components/common/VnInput.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
-import VnColumn from 'components/VnTable/VnColumn.vue';
+import VnTableColumn from 'components/VnTable/VnColumn.vue';
 
 const $props = defineProps({
     column: {
@@ -25,10 +27,6 @@ const $props = defineProps({
         type: String,
         default: 'table',
     },
-    customClass: {
-        type: String,
-        default: '',
-    },
 });
 
 defineExpose({ addFilter, props: $props });
@@ -36,7 +34,7 @@ defineExpose({ addFilter, props: $props });
 const model = defineModel(undefined, { required: true });
 const arrayData = useArrayData(
     $props.dataKey,
-    $props.searchUrl ? { searchUrl: $props.searchUrl } : null,
+    $props.searchUrl ? { searchUrl: $props.searchUrl } : null
 );
 const columnFilter = computed(() => $props.column?.columnFilter);
 
@@ -48,18 +46,19 @@ const enterEvent = {
 
 const defaultAttrs = {
     filled: !$props.showTitle,
+    class: 'q-px-xs q-pb-xs q-pt-none fit',
     dense: true,
 };
 
 const forceAttrs = {
-    label: $props.showTitle ? '' : (columnFilter.value?.label ?? $props.column.label),
+    label: $props.showTitle ? '' : columnFilter.value?.label ?? $props.column.label,
 };
 
 const selectComponent = {
     component: markRaw(VnSelect),
     event: updateEvent,
     attrs: {
-        class: `q-pt-none fit ${$props.customClass}`,
+        class: 'q-px-sm q-pb-xs q-pt-none fit',
         dense: true,
         filled: !$props.showTitle,
     },
@@ -110,24 +109,14 @@ const components = {
         component: markRaw(QCheckbox),
         event: updateEvent,
         attrs: {
-            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
+            dense: true,
+            class: $props.showTitle ? 'q-py-sm q-mt-md' : 'q-px-md q-py-xs fit',
             'toggle-indeterminate': true,
-            size: 'sm',
         },
         forceAttrs,
     },
     select: selectComponent,
     rawSelect: selectComponent,
-    toggle: {
-        component: markRaw(QToggle),
-        event: updateEvent,
-        attrs: {
-            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
-            'toggle-indeterminate': true,
-            size: 'sm',
-        },
-        forceAttrs,
-    },
 };
 
 async function addFilter(value, name) {
@@ -143,8 +132,19 @@ async function addFilter(value, name) {
     await arrayData.addFilter({ params: { [field]: value } });
 }
 
+function alignRow() {
+    switch ($props.column.align) {
+        case 'left':
+            return 'justify-start items-start';
+        case 'right':
+            return 'justify-end items-end';
+        default:
+            return 'flex-center';
+    }
+}
+
 const showFilter = computed(
-    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions',
+    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions'
 );
 
 const onTabPressed = async () => {
@@ -152,8 +152,13 @@ const onTabPressed = async () => {
 };
 </script>
 <template>
-    <div v-if="showFilter" class="full-width" style="overflow: hidden">
-        <VnColumn
+    <div
+        v-if="showFilter"
+        class="full-width"
+        :class="alignRow()"
+        style="max-height: 45px; overflow: hidden"
+    >
+        <VnTableColumn
             :column="$props.column"
             default="input"
             v-model="model"
@@ -163,8 +168,3 @@ const onTabPressed = async () => {
         />
     </div>
 </template>
-<style lang="scss" scoped>
-label.vn-label-padding > .q-field__inner > .q-field__control {
-    padding: inherit !important;
-}
-</style>
diff --git a/src/components/VnTable/VnOrder.vue b/src/components/VnTable/VnOrder.vue
index 47ed9acf4..8ffdfe2bc 100644
--- a/src/components/VnTable/VnOrder.vue
+++ b/src/components/VnTable/VnOrder.vue
@@ -23,10 +23,6 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
-    align: {
-        type: String,
-        default: 'end',
-    },
 });
 const hover = ref();
 const arrayData = useArrayData($props.dataKey, { searchUrl: $props.searchUrl });
@@ -45,78 +41,55 @@ async function orderBy(name, direction) {
             break;
     }
     if (!direction) return await arrayData.deleteOrder(name);
-
     await arrayData.addOrder(name, direction);
 }
 
 defineExpose({ orderBy });
-
-function textAlignToFlex(textAlign) {
-    return `justify-content: ${
-        {
-            'text-center': 'center',
-            'text-left': 'start',
-            'text-right': 'end',
-        }[textAlign] || 'start'
-    };`;
-}
 </script>
 <template>
     <div
         @mouseenter="hover = true"
         @mouseleave="hover = false"
         @click="orderBy(name, model?.direction)"
-        class="items-center no-wrap cursor-pointer title"
-        :style="textAlignToFlex(align)"
+        class="row items-center no-wrap cursor-pointer"
     >
         <span :title="label">{{ label }}</span>
-        <div v-if="name && model?.index">
-            <QChip
-                :label="!vertical ? model?.index : ''"
-                :icon="
-                    (model?.index || hover) && !vertical
-                        ? model?.direction == 'DESC'
-                            ? 'arrow_downward'
-                            : 'arrow_upward'
-                        : undefined
-                "
-                :size="vertical ? '' : 'sm'"
-                :class="[
-                    model?.index ? 'color-vn-text' : 'bg-transparent',
-                    vertical ? 'q-px-none' : '',
-                ]"
-                class="no-box-shadow"
-                :clickable="true"
-                style="min-width: 40px; max-height: 30px"
+        <QChip
+            v-if="name"
+            :label="!vertical ? model?.index : ''"
+            :icon="
+                (model?.index || hover) && !vertical
+                    ? model?.direction == 'DESC'
+                        ? 'arrow_downward'
+                        : 'arrow_upward'
+                    : undefined
+            "
+            :size="vertical ? '' : 'sm'"
+            :class="[
+                model?.index ? 'color-vn-text' : 'bg-transparent',
+                vertical ? 'q-px-none' : '',
+            ]"
+            class="no-box-shadow"
+            :clickable="true"
+            style="min-width: 40px"
+        >
+            <div
+                class="column flex-center"
+                v-if="vertical"
+                :style="!model?.index && 'color: #5d5d5d'"
             >
-                <div
-                    class="column flex-center"
-                    v-if="vertical"
-                    :style="!model?.index && 'color: #5d5d5d'"
-                >
-                    {{ model?.index }}
-                    <QIcon
-                        :name="
-                            model?.index
-                                ? model?.direction == 'DESC'
-                                    ? 'arrow_downward'
-                                    : 'arrow_upward'
-                                : 'swap_vert'
-                        "
-                        size="xs"
-                    />
-                </div>
-            </QChip>
-        </div>
+                {{ model?.index }}
+                <QIcon
+                    :name="
+                        model?.index
+                            ? model?.direction == 'DESC'
+                                ? 'arrow_downward'
+                                : 'arrow_upward'
+                            : 'swap_vert'
+                    "
+                    size="xs"
+                />
+            </div>
+        </QChip>
     </div>
 </template>
-<style lang="scss" scoped>
-.title {
-    display: flex;
-    align-items: center;
-    height: 30px;
-    width: 100%;
-    color: var(--vn-label-color);
-    white-space: nowrap;
-}
-</style>
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 7ff56860f..6e5f9fef4 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -1,38 +1,22 @@
 <script setup>
-import {
-    ref,
-    onBeforeMount,
-    onMounted,
-    onUnmounted,
-    computed,
-    watch,
-    h,
-    render,
-    inject,
-    useAttrs,
-    nextTick,
-} from 'vue';
-import { useArrayData } from 'src/composables/useArrayData';
+import { ref, onBeforeMount, onMounted, computed, watch, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
-import { useQuasar, date } from 'quasar';
+import { useQuasar } from 'quasar';
 import { useStateStore } from 'stores/useStateStore';
 import { useFilterParams } from 'src/composables/useFilterParams';
-import { dashIfEmpty, toDate } from 'src/filters';
 
 import CrudModel from 'src/components/CrudModel.vue';
 import FormModelPopup from 'components/FormModelPopup.vue';
 
-import VnColumn from 'components/VnTable/VnColumn.vue';
+import VnTableColumn from 'components/VnTable/VnColumn.vue';
 import VnFilter from 'components/VnTable/VnFilter.vue';
 import VnTableChip from 'components/VnTable/VnChip.vue';
 import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
 import VnTableFilter from './VnTableFilter.vue';
-import { getColAlign } from 'src/composables/getColAlign';
 
-const arrayData = useArrayData(useAttrs()['data-key']);
 const $props = defineProps({
     columns: {
         type: Array,
@@ -58,6 +42,10 @@ const $props = defineProps({
         type: [Function, Boolean],
         default: null,
     },
+    rowCtrlClick: {
+        type: [Function, Boolean],
+        default: null,
+    },
     redirect: {
         type: String,
         default: null,
@@ -126,19 +114,7 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
-    withFilters: {
-        type: Boolean,
-        default: true,
-    },
-    overlay: {
-        type: Boolean,
-        default: false,
-    },
-    createComplement: {
-        type: Object,
-    },
 });
-
 const { t } = useI18n();
 const stateStore = useStateStore();
 const route = useRoute();
@@ -156,18 +132,10 @@ const showForm = ref(false);
 const splittedColumns = ref({ columns: [] });
 const columnsVisibilitySkipped = ref();
 const createForm = ref();
-const createRef = ref(null);
 const tableRef = ref();
 const params = ref(useFilterParams($attrs['data-key']).params);
 const orders = ref(useFilterParams($attrs['data-key']).orders);
-const app = inject('app');
 
-const editingRow = ref(null);
-const editingField = ref(null);
-const isTableMode = computed(() => mode.value == TABLE_MODE);
-const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
-const selectRegex = /select/;
-const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
 const tableModes = [
     {
         icon: 'view_column',
@@ -188,8 +156,7 @@ onBeforeMount(() => {
     hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
 });
 
-onMounted(async () => {
-    if ($props.isEditable) document.addEventListener('click', clickHandler);
+onMounted(() => {
     mode.value =
         quasar.platform.is.mobile && !$props.disableOption?.card
             ? CARD_MODE
@@ -211,25 +178,14 @@ onMounted(async () => {
     }
 });
 
-onUnmounted(async () => {
-    if ($props.isEditable) document.removeEventListener('click', clickHandler);
-});
-
 watch(
     () => $props.columns,
     (value) => splitColumns(value),
     { immediate: true },
 );
 
-defineExpose({
-    create: createForm,
-    reload,
-    redirect: redirectFn,
-    selected,
-    CrudModelRef,
-    params,
-    tableRef,
-});
+const isTableMode = computed(() => mode.value == TABLE_MODE);
+const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
 
 function splitColumns(columns) {
     splittedColumns.value = {
@@ -275,6 +231,16 @@ const rowClickFunction = computed(() => {
     return () => {};
 });
 
+const rowCtrlClickFunction = computed(() => {
+    if ($props.rowCtrlClick != undefined) return $props.rowCtrlClick;
+    if ($props.redirect)
+        return (evt, { id }) => {
+            stopEventPropagation(evt);
+            window.open(`/#/${$props.redirect}/${id}`, '_blank');
+        };
+    return () => {};
+});
+
 function redirectFn(id) {
     router.push({ path: `/${$props.redirect}/${id}` });
 }
@@ -296,6 +262,21 @@ function columnName(col) {
     return name;
 }
 
+function getColAlign(col) {
+    return 'text-' + (col.align ?? 'left');
+}
+
+const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
+defineExpose({
+    create: createForm,
+    reload,
+    redirect: redirectFn,
+    selected,
+    CrudModelRef,
+    params,
+    tableRef,
+});
+
 function handleOnDataSaved(_) {
     if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
     else $props.create.onDataSaved(_);
@@ -324,237 +305,6 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
     }
 }
 
-function isEditableColumn(column) {
-    const isEditableCol = column?.isEditable ?? true;
-    const isVisible = column?.visible ?? true;
-    const hasComponent = column?.component;
-
-    return $props.isEditable && isVisible && hasComponent && isEditableCol;
-}
-
-function hasEditableFormat(column) {
-    if (isEditableColumn(column)) return 'editable-text';
-}
-
-const clickHandler = async (event) => {
-    const clickedElement = event.target.closest('td');
-
-    const isDateElement = event.target.closest('.q-date');
-    const isTimeElement = event.target.closest('.q-time');
-    const isQselectDropDown = event.target.closest('.q-select__dropdown-icon');
-
-    if (isDateElement || isTimeElement || isQselectDropDown) return;
-
-    if (clickedElement === null) {
-        await destroyInput(editingRow.value, editingField.value);
-        return;
-    }
-    const rowIndex = clickedElement.getAttribute('data-row-index');
-    const colField = clickedElement.getAttribute('data-col-field');
-    const column = $props.columns.find((col) => col.name === colField);
-
-    if (editingRow.value !== null && editingField.value !== null) {
-        if (editingRow.value == rowIndex && editingField.value == colField) return;
-
-        await destroyInput(editingRow.value, editingField.value);
-    }
-
-    if (isEditableColumn(column)) {
-        await renderInput(Number(rowIndex), colField, clickedElement);
-    }
-};
-
-async function handleTabKey(event, rowIndex, colField) {
-    if (editingRow.value == rowIndex && editingField.value == colField)
-        await destroyInput(editingRow.value, editingField.value);
-
-    const direction = event.shiftKey ? -1 : 1;
-    const { nextRowIndex, nextColumnName } = await handleTabNavigation(
-        rowIndex,
-        colField,
-        direction,
-    );
-
-    if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return;
-
-    event.preventDefault();
-    await renderInput(nextRowIndex, nextColumnName, null);
-}
-
-async function renderInput(rowId, field, clickedElement) {
-    editingField.value = field;
-    editingRow.value = rowId;
-
-    const originalColumn = $props.columns.find((col) => col.name === field);
-    const column = { ...originalColumn, ...{ label: '' } };
-    const row = CrudModelRef.value.formData[rowId];
-    const oldValue = CrudModelRef.value.formData[rowId][column?.name];
-
-    if (!clickedElement)
-        clickedElement = document.querySelector(
-            `[data-row-index="${rowId}"][data-col-field="${field}"]`,
-        );
-
-    Array.from(clickedElement.childNodes).forEach((child) => {
-        child.style.visibility = 'hidden';
-        child.style.position = 'relative';
-    });
-
-    const isSelect = selectRegex.test(column?.component);
-    if (isSelect) column.attrs = { ...column.attrs, 'emit-value': false };
-
-    const node = h(VnColumn, {
-        row: row,
-        class: 'temp-input',
-        column: column,
-        modelValue: row[column.name],
-        componentProp: 'columnField',
-        autofocus: true,
-        focusOnMount: true,
-        eventHandlers: {
-            'update:modelValue': async (value) => {
-                if (isSelect && value) {
-                    row[column.name] = value[column.attrs?.optionValue ?? 'id'];
-                    row[column?.name + 'TextValue'] =
-                        value[column.attrs?.optionLabel ?? 'name'];
-                    await column?.cellEvent?.['update:modelValue']?.(
-                        value,
-                        oldValue,
-                        row,
-                    );
-                } else row[column.name] = value;
-                await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
-            },
-            keyup: async (event) => {
-                if (event.key === 'Enter')
-                    await destroyInput(rowIndex, field, clickedElement);
-            },
-            keydown: async (event) => {
-                switch (event.key) {
-                    case 'Tab':
-                        await handleTabKey(event, rowId, field);
-                        event.stopPropagation();
-                        break;
-                    case 'Escape':
-                        await destroyInput(rowId, field, clickedElement);
-                        break;
-                    default:
-                        break;
-                }
-            },
-            click: (event) => {
-                column?.cellEvent?.['click']?.(event, row);
-            },
-        },
-    });
-
-    node.appContext = app._context;
-    render(node, clickedElement);
-
-    if (['toggle'].includes(column?.component))
-        node.el?.querySelector('span > div').focus();
-
-    if (['checkbox', undefined].includes(column?.component))
-        node.el?.querySelector('span > div > div').focus();
-}
-
-async function destroyInput(rowIndex, field, clickedElement) {
-    if (!clickedElement)
-        clickedElement = document.querySelector(
-            `[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
-        );
-    if (clickedElement) {
-        await nextTick();
-        render(null, clickedElement);
-        Array.from(clickedElement.childNodes).forEach((child) => {
-            child.style.visibility = 'visible';
-            child.style.position = '';
-        });
-    }
-    if (editingRow.value !== rowIndex || editingField.value !== field) return;
-    editingRow.value = null;
-    editingField.value = null;
-}
-
-async function handleTabNavigation(rowIndex, colName, direction) {
-    const columns = $props.columns;
-    const totalColumns = columns.length;
-    let currentColumnIndex = columns.findIndex((col) => col.name === colName);
-
-    let iterations = 0;
-    let newColumnIndex = currentColumnIndex;
-
-    do {
-        iterations++;
-        newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns;
-
-        if (isEditableColumn(columns[newColumnIndex])) break;
-    } while (iterations < totalColumns);
-
-    if (iterations >= totalColumns + 1) return;
-
-    if (direction === 1 && newColumnIndex <= currentColumnIndex) {
-        rowIndex++;
-    } else if (direction === -1 && newColumnIndex >= currentColumnIndex) {
-        rowIndex--;
-    }
-    return { nextRowIndex: rowIndex, nextColumnName: columns[newColumnIndex].name };
-}
-
-function getCheckboxIcon(value) {
-    switch (typeof value) {
-        case 'boolean':
-            return value ? 'check' : 'close';
-        case 'number':
-            return value === 0 ? 'close' : 'check';
-        case 'undefined':
-            return 'indeterminate_check_box';
-        default:
-            return 'indeterminate_check_box';
-    }
-}
-
-function getToggleIcon(value) {
-    if (value === null) return 'help_outline';
-    return value ? 'toggle_on' : 'toggle_off';
-}
-
-function formatColumnValue(col, row, dashIfEmpty) {
-    if (col?.format || row[col?.name + 'TextValue']) {
-        if (selectRegex.test(col?.component) && row[col?.name + 'TextValue']) {
-            return dashIfEmpty(row[col?.name + 'TextValue']);
-        } else {
-            return col.format(row, dashIfEmpty);
-        }
-    }
-
-    if (col?.component === 'date') return dashIfEmpty(toDate(row[col?.name]));
-
-    if (col?.component === 'time')
-        return row[col?.name] >= 5
-            ? dashIfEmpty(date.formatDate(new Date(row[col?.name]), 'HH:mm'))
-            : row[col?.name];
-
-    if (selectRegex.test(col?.component) && $props.isEditable) {
-        const { find, url } = col.attrs;
-        const urlRelation = url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
-
-        if (col?.attrs.options) {
-            const find = col?.attrs.options.find((option) => option.id === row[col.name]);
-            if (!col.attrs?.optionLabel || !find) return dashIfEmpty(row[col?.name]);
-            return dashIfEmpty(find[col.attrs?.optionLabel ?? 'name']);
-        }
-
-        if (typeof row[urlRelation] == 'object') {
-            if (typeof find == 'object')
-                return dashIfEmpty(row[urlRelation][find?.label ?? 'name']);
-
-            return dashIfEmpty(row[urlRelation][col?.attrs.optionLabel ?? 'name']);
-        }
-        if (typeof row[urlRelation] == 'string') return dashIfEmpty(row[urlRelation]);
-    }
-    return dashIfEmpty(row[col?.name]);
-}
 function cardClick(_, row) {
     if ($props.redirect) router.push({ path: `/${$props.redirect}/${row.id}` });
 }
@@ -565,7 +315,7 @@ function cardClick(_, row) {
         v-model="stateStore.rightDrawer"
         side="right"
         :width="256"
-        :overlay="$props.overlay"
+        show-if-above
     >
         <QScrollArea class="fit">
             <VnTableFilter
@@ -586,7 +336,7 @@ function cardClick(_, row) {
     <CrudModel
         v-bind="$attrs"
         :class="$attrs['class'] ?? 'q-px-md'"
-        :limit="$attrs['limit'] ?? 100"
+        :limit="$attrs['limit'] ?? 20"
         ref="CrudModelRef"
         @on-fetch="(...args) => emit('onFetch', ...args)"
         :search-url="searchUrl"
@@ -602,12 +352,8 @@ function cardClick(_, row) {
             <QTable
                 ref="tableRef"
                 v-bind="table"
-                :class="[
-                    'vnTable',
-                    table ? 'selection-cell' : '',
-                    $props.footer ? 'last-row-sticky' : '',
-                ]"
-                wrap-cells
+                class="vnTable"
+                :class="{ 'last-row-sticky': $props.footer }"
                 :columns="splittedColumns.columns"
                 :rows="rows"
                 v-model:selected="selected"
@@ -621,13 +367,11 @@ function cardClick(_, row) {
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
                 @update:selected="emit('update:selected', $event)"
                 @selection="(details) => handleSelection(details, rows)"
-                :hide-selected-banner="true"
             >
                 <template #top-left v-if="!$props.withoutHeader">
-                    <slot name="top-left"> </slot>
+                    <slot name="top-left"></slot>
                 </template>
                 <template #top-right v-if="!$props.withoutHeader">
-                    <slot name="top-right"></slot>
                     <VnVisibleColumn
                         v-if="isTableMode"
                         v-model="splittedColumns.columns"
@@ -641,7 +385,6 @@ function cardClick(_, row) {
                         dense
                         :options="tableModes.filter((mode) => !mode.disable)"
                     />
-
                     <QBtn
                         v-if="showRightIcon"
                         icon="filter_alt"
@@ -653,39 +396,32 @@ function cardClick(_, row) {
                 <template #header-cell="{ col }">
                     <QTh
                         v-if="col.visible ?? true"
-                        v-bind:class="col.headerClass"
-                        class="body-cell"
-                        :style="col?.width ? `max-width: ${col?.width}` : ''"
+                        :style="col.headerStyle"
+                        :class="col.headerClass"
                     >
                         <div
-                            class="no-padding"
-                            :style="[
-                                withFilters && $props.columnSearch ? 'height: 75px' : '',
-                            ]"
+                            class="column ellipsis"
+                            :class="`text-${col?.align ?? 'left'}`"
+                            :style="$props.columnSearch ? 'height: 75px' : ''"
                         >
-                            <div style="height: 30px">
+                            <div class="row items-center no-wrap" style="height: 30px">
                                 <QTooltip v-if="col.toolTip">{{ col.toolTip }}</QTooltip>
                                 <VnTableOrder
                                     v-model="orders[col.orderBy ?? col.name]"
                                     :name="col.orderBy ?? col.name"
-                                    :label="col?.labelAbbreviation ?? col?.label"
+                                    :label="col?.label"
                                     :data-key="$attrs['data-key']"
                                     :search-url="searchUrl"
-                                    :align="getColAlign(col)"
                                 />
                             </div>
                             <VnFilter
-                                v-if="
-                                    $props.columnSearch &&
-                                    col.columnSearch !== false &&
-                                    withFilters
-                                "
+                                v-if="$props.columnSearch"
                                 :column="col"
                                 :show-title="true"
                                 :data-key="$attrs['data-key']"
                                 v-model="params[columnName(col)]"
                                 :search-url="searchUrl"
-                                customClass="header-filter"
+                                class="full-width"
                             />
                         </div>
                     </QTh>
@@ -703,67 +439,32 @@ function cardClick(_, row) {
                     </QTd>
                 </template>
                 <template #body-cell="{ col, row, rowIndex }">
+                    <!-- Columns -->
                     <QTd
-                        class="no-margin q-px-xs"
+                        auto-width
+                        class="no-margin"
+                        :class="[getColAlign(col), col.columnClass]"
+                        :style="col.style"
                         v-if="col.visible ?? true"
-                        :style="{
-                            'max-width': col?.width ?? false,
-                            position: 'relative',
-                        }"
-                        :class="[
-                            col.columnClass,
-                            'body-cell no-margin no-padding',
-                            getColAlign(col),
-                        ]"
-                        :data-row-index="rowIndex"
-                        :data-col-field="col?.name"
+                        @click.ctrl="
+                            ($event) =>
+                                rowCtrlClickFunction && rowCtrlClickFunction($event, row)
+                        "
                     >
-                        <div
-                            class="no-padding no-margin peter"
-                            style="
-                                overflow: hidden;
-                                text-overflow: ellipsis;
-                                white-space: nowrap;
-                            "
+                        <slot
+                            :name="`column-${col.name}`"
+                            :col="col"
+                            :row="row"
+                            :row-index="rowIndex"
                         >
-                            <slot
-                                :name="`column-${col.name}`"
-                                :col="col"
+                            <VnTableColumn
+                                :column="col"
                                 :row="row"
-                                :row-index="rowIndex"
-                            >
-                                <QIcon
-                                    v-if="col?.component === 'toggle'"
-                                    :name="
-                                        col?.getIcon
-                                            ? col.getIcon(row[col?.name])
-                                            : getToggleIcon(row[col?.name])
-                                    "
-                                    style="color: var(--vn-text-color)"
-                                    :class="hasEditableFormat(col)"
-                                    size="14px"
-                                />
-                                <QIcon
-                                    v-else-if="col?.component === 'checkbox'"
-                                    :name="getCheckboxIcon(row[col?.name])"
-                                    style="color: var(--vn-text-color)"
-                                    :class="hasEditableFormat(col)"
-                                    size="14px"
-                                />
-                                <span
-                                    v-else
-                                    :class="hasEditableFormat(col)"
-                                    :style="
-                                        typeof col?.style == 'function'
-                                            ? col.style(row)
-                                            : col?.style
-                                    "
-                                    style="bottom: 0"
-                                >
-                                    {{ formatColumnValue(col, row, dashIfEmpty) }}
-                                </span>
-                            </slot>
-                        </div>
+                                :is-editable="col.isEditable ?? isEditable"
+                                v-model="row[col.name]"
+                                component-prop="columnField"
+                            />
+                        </slot>
                     </QTd>
                 </template>
                 <template #body-cell-tableActions="{ col, row }">
@@ -784,7 +485,7 @@ function cardClick(_, row) {
                             flat
                             dense
                             :class="
-                                btn.isPrimary ? 'text-primary-light' : 'color-vn-label'
+                                btn.isPrimary ? 'text-primary-light' : 'color-vn-text '
                             "
                             :style="`visibility: ${
                                 ((btn.show && btn.show(row)) ?? true)
@@ -792,7 +493,6 @@ function cardClick(_, row) {
                                     : 'hidden'
                             }`"
                             @click="btn.action(row)"
-                            :data-cy="btn?.name ?? `tableAction-${index}`"
                         />
                     </QTd>
                 </template>
@@ -841,7 +541,7 @@ function cardClick(_, row) {
                                 </QCardSection>
                                 <!-- Fields -->
                                 <QCardSection
-                                    class="q-pl-sm q-py-xs"
+                                    class="q-pl-sm q-pr-lg q-py-xs"
                                     :class="$props.cardClass"
                                 >
                                     <div
@@ -862,7 +562,7 @@ function cardClick(_, row) {
                                                         :row="row"
                                                         :row-index="index"
                                                     >
-                                                        <VnColumn
+                                                        <VnTableColumn
                                                             :column="col"
                                                             :row="row"
                                                             :is-editable="false"
@@ -889,12 +589,12 @@ function cardClick(_, row) {
                                     :title="btn.title"
                                     :icon="btn.icon"
                                     class="q-pa-xs"
+                                    flat
                                     :class="
                                         btn.isPrimary
                                             ? 'text-primary-light'
-                                            : 'color-vn-label'
+                                            : 'color-vn-text '
                                     "
-                                    flat
                                     @click="btn.action(row)"
                                 />
                             </QCardSection>
@@ -902,17 +602,14 @@ function cardClick(_, row) {
                     </component>
                 </template>
                 <template #bottom-row="{ cols }" v-if="$props.footer">
-                    <QTr v-if="rows.length" style="height: 45px">
-                        <QTh v-if="table.selection" />
+                    <QTr v-if="rows.length" style="height: 30px">
                         <QTh
                             v-for="col of cols.filter((cols) => cols.visible ?? true)"
                             :key="col?.id"
+                            class="text-center"
                             :class="getColAlign(col)"
                         >
-                            <slot
-                                :name="`column-footer-${col.name}`"
-                                :isEditableColumn="isEditableColumn(col)"
-                            />
+                            <slot :name="`column-footer-${col.name}`" />
                         </QTh>
                     </QTr>
                 </template>
@@ -931,7 +628,7 @@ function cardClick(_, row) {
                     size="md"
                     round
                     flat
-                    v-shortcut="'+'"
+                    shortcut="+"
                     :disabled="!disabledAttr"
                 />
                 <QTooltip>
@@ -949,52 +646,39 @@ function cardClick(_, row) {
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
             data-cy="vnTableCreateBtn"
         />
         <QTooltip self="top right">
             {{ createForm?.title }}
         </QTooltip>
     </QPageSticky>
-    <QDialog
-        v-model="showForm"
-        transition-show="scale"
-        transition-hide="scale"
-        :full-width="createComplement?.isFullWidth ?? false"
-        data-cy="vn-table-create-dialog"
-    >
+    <QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
         <FormModelPopup
-            ref="createRef"
             v-bind="createForm"
             :model="$attrs['data-key'] + 'Create'"
             @on-data-saved="(_, res) => createForm.onDataSaved(res)"
         >
             <template #form-inputs="{ data }">
-                <div :style="createComplement?.containerStyle">
-                    <div>
-                        <slot name="previous-create-dialog" :data="data" />
-                    </div>
-                    <div class="grid-create" :style="createComplement?.columnGridStyle">
-                        <slot
-                            v-for="column of splittedColumns.create"
-                            :key="column.name"
-                            :name="`column-create-${column.name}`"
-                            :data="data"
-                            :column-name="column.name"
-                            :label="column.label"
-                        >
-                            <VnColumn
-                                :column="column"
-                                :row="{}"
-                                default="input"
-                                v-model="data[column.name]"
-                                :show-label="true"
-                                component-prop="columnCreate"
-                                :data-cy="`${column.name}-create-popup`"
-                            />
-                        </slot>
-                        <slot name="more-create-dialog" :data="data" />
-                    </div>
+                <div class="grid-create">
+                    <slot
+                        v-for="column of splittedColumns.create"
+                        :key="column.name"
+                        :name="`column-create-${column.name}`"
+                        :data="data"
+                        :column-name="column.name"
+                        :label="column.label"
+                    >
+                        <VnTableColumn
+                            :column="column"
+                            :row="{}"
+                            default="input"
+                            v-model="data[column.name]"
+                            :show-label="true"
+                            component-prop="columnCreate"
+                        />
+                    </slot>
+                    <slot name="more-create-dialog" :data="data" />
                 </div>
             </template>
         </FormModelPopup>
@@ -1012,42 +696,6 @@ es:
 </i18n>
 
 <style lang="scss">
-.selection-cell {
-    table td:first-child {
-        padding: 0px;
-    }
-}
-.side-padding {
-    padding-left: 1px;
-    padding-right: 1px;
-}
-.editable-text:hover {
-    border-bottom: 1px dashed var(--q-primary);
-    @extend .side-padding;
-}
-.editable-text {
-    border-bottom: 1px dashed var(--vn-label-color);
-    @extend .side-padding;
-}
-.cell-input {
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    padding-top: 0px !important;
-}
-.q-field--labeled .q-field__native,
-.q-field--labeled .q-field__prefix,
-.q-field--labeled .q-field__suffix {
-    padding-top: 20px;
-}
-
-.body-cell {
-    padding-left: 4px !important;
-    padding-right: 4px !important;
-    position: relative;
-}
 .bg-chip-secondary {
     background-color: var(--vn-page-color);
     color: var(--vn-text-color);
@@ -1064,8 +712,8 @@ es:
 
 .grid-three {
     display: grid;
-    grid-template-columns: repeat(auto-fit, minmax(300px, max-content));
-    width: 100%;
+    grid-template-columns: repeat(auto-fit, minmax(350px, max-content));
+    max-width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -1073,6 +721,7 @@ es:
 .grid-create {
     display: grid;
     grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
+    max-width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -1088,9 +737,7 @@ es:
         }
     }
 }
-.q-table tbody tr td {
-    position: relative;
-}
+
 .q-table {
     th {
         padding: 0;
@@ -1139,7 +786,6 @@ es:
 .vn-label-value {
     display: flex;
     flex-direction: row;
-    align-items: center;
     color: var(--vn-text-color);
     .value {
         overflow: hidden;
@@ -1191,15 +837,4 @@ es:
 .q-table__middle.q-virtual-scroll.q-virtual-scroll--vertical.scroll {
     background-color: var(--vn-section-color);
 }
-.temp-input {
-    top: 0;
-    position: absolute;
-    width: 100%;
-    height: 100%;
-    display: flex;
-}
-
-label.header-filter > .q-field__inner > .q-field__control {
-    padding: inherit;
-}
 </style>
diff --git a/src/components/VnTable/VnTableFilter.vue b/src/components/VnTable/VnTableFilter.vue
index 79b903e54..732605ce5 100644
--- a/src/components/VnTable/VnTableFilter.vue
+++ b/src/components/VnTable/VnTableFilter.vue
@@ -27,36 +27,31 @@ function columnName(col) {
 </script>
 <template>
     <VnFilterPanel v-bind="$attrs" :search-button="true" :disable-submit-event="true">
-        <template #body="{ params, orders, searchFn }">
+        <template #body="{ params, orders }">
             <div
-                class="container"
+                class="row no-wrap flex-center"
                 v-for="col of columns.filter((c) => c.columnFilter ?? true)"
                 :key="col.id"
             >
-                <div class="filter">
-                    <VnFilter
-                        ref="tableFilterRef"
-                        :column="col"
-                        :data-key="$attrs['data-key']"
-                        v-model="params[columnName(col)]"
-                        :search-url="searchUrl"
-                    />
-                </div>
-                <div class="order">
-                    <VnTableOrder
-                        v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
-                        v-model="orders[col.orderBy ?? col.name]"
-                        :name="col.orderBy ?? col.name"
-                        :data-key="$attrs['data-key']"
-                        :search-url="searchUrl"
-                        :vertical="true"
-                    />
-                </div>
+                <VnFilter
+                    ref="tableFilterRef"
+                    :column="col"
+                    :data-key="$attrs['data-key']"
+                    v-model="params[columnName(col)]"
+                    :search-url="searchUrl"
+                />
+                <VnTableOrder
+                    v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
+                    v-model="orders[col.orderBy ?? col.name]"
+                    :name="col.orderBy ?? col.name"
+                    :data-key="$attrs['data-key']"
+                    :search-url="searchUrl"
+                    :vertical="true"
+                />
             </div>
             <slot
                 name="moreFilterPanel"
                 :params="params"
-                :search-fn="searchFn"
                 :orders="orders"
                 :columns="columns"
             />
@@ -72,21 +67,3 @@ function columnName(col) {
         </template>
     </VnFilterPanel>
 </template>
-<style lang="scss" scoped>
-.container {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    height: 45px;
-    gap: 10px;
-}
-
-.filter {
-    width: 70%;
-    height: 40px;
-    text-align: center;
-}
-.order {
-    width: 10%;
-}
-</style>
diff --git a/src/components/VnTable/VnVisibleColumn.vue b/src/components/VnTable/VnVisibleColumn.vue
index 6d15c585e..dad950d73 100644
--- a/src/components/VnTable/VnVisibleColumn.vue
+++ b/src/components/VnTable/VnVisibleColumn.vue
@@ -32,21 +32,16 @@ const areAllChecksMarked = computed(() => {
 
 function setUserConfigViewData(data, isLocal) {
     if (!data) return;
+    // Importante: El name de las columnas de la tabla debe conincidir con el name de las variables que devuelve la view config
     if (!isLocal) localColumns.value = [];
-
+    // Array to Object
     const skippeds = $props.skip.reduce((a, v) => ({ ...a, [v]: v }), {});
 
     for (let column of columns.value) {
-        const { label, name, labelAbbreviation } = column;
+        const { label, name } = column;
         if (skippeds[name]) continue;
         column.visible = data[name] ?? true;
-        if (!isLocal)
-            localColumns.value.push({
-                name,
-                label,
-                labelAbbreviation,
-                visible: column.visible,
-            });
+        if (!isLocal) localColumns.value.push({ name, label, visible: column.visible });
     }
 }
 
@@ -157,11 +152,7 @@ onMounted(async () => {
                     <QCheckbox
                         v-for="col in localColumns"
                         :key="col.name"
-                        :label="
-                            col?.labelAbbreviation
-                                ? col.labelAbbreviation + ` (${col.label ?? col.name})`
-                                : (col.label ?? col.name)
-                        "
+                        :label="col.label ?? col.name"
                         v-model="col.visible"
                     />
                 </div>
diff --git a/src/components/__tests__/FormModel.spec.js b/src/components/__tests__/FormModel.spec.js
index 3dce04374..e35684bc3 100644
--- a/src/components/__tests__/FormModel.spec.js
+++ b/src/components/__tests__/FormModel.spec.js
@@ -57,7 +57,6 @@ describe('FormModel', () => {
             vm.state.set(model, formInitialData);
             expect(vm.hasChanges).toBe(false);
 
-            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             expect(vm.hasChanges).toBe(true);
@@ -94,13 +93,9 @@ describe('FormModel', () => {
 
         it('should call axios.patch with the right data', async () => {
             const spy = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
-            const { vm } = mount({ propsData: { url, model } });
-
-            vm.formData = {};
+            const { vm } = mount({ propsData: { url, model, formInitialData } });
+            vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
-            vm.formData = { mockKey: 'newVal' };
-            await vm.$nextTick();
-
             await vm.save();
             expect(spy).toHaveBeenCalled();
             vm.formData.mockKey = 'mockVal';
@@ -111,7 +106,6 @@ describe('FormModel', () => {
             const { vm } = mount({
                 propsData: { url, model, formInitialData, urlCreate: 'mockUrlCreate' },
             });
-            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
@@ -125,7 +119,7 @@ describe('FormModel', () => {
             });
             const spyPatch = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
             const spySaveFn = vi.spyOn(vm.$props, 'saveFn');
-            await vm.$nextTick();
+
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
diff --git a/src/components/__tests__/Leftmenu.spec.js b/src/components/__tests__/Leftmenu.spec.js
index 4ab8b527f..10d9d66fb 100644
--- a/src/components/__tests__/Leftmenu.spec.js
+++ b/src/components/__tests__/Leftmenu.spec.js
@@ -1,11 +1,8 @@
-import { vi, describe, expect, it, beforeAll, beforeEach, afterEach } from 'vitest';
+import { vi, describe, expect, it, beforeAll } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import Leftmenu from 'components/LeftMenu.vue';
-import * as vueRouter from 'vue-router';
-import { useNavigationStore } from 'src/stores/useNavigationStore';
 
-let vm;
-let navigation;
+import { useNavigationStore } from 'src/stores/useNavigationStore';
 
 vi.mock('src/router/modules', () => ({
     default: [
@@ -24,16 +21,6 @@ vi.mock('src/router/modules', () => ({
                 {
                     path: '',
                     name: 'CustomerMain',
-                    meta: {
-                        menu: 'Customer',
-                        menuChildren: [
-                            {
-                                name: 'CustomerCreditContracts',
-                                title: 'creditContracts',
-                                icon: 'vn:solunion',
-                            },
-                        ],
-                    },
                     children: [
                         {
                             path: 'list',
@@ -41,13 +28,6 @@ vi.mock('src/router/modules', () => ({
                             meta: {
                                 title: 'list',
                                 icon: 'view_list',
-                                menuChildren: [
-                                    {
-                                        name: 'CustomerCreditContracts',
-                                        title: 'creditContracts',
-                                        icon: 'vn:solunion',
-                                    },
-                                ],
                             },
                         },
                         {
@@ -64,325 +44,51 @@ vi.mock('src/router/modules', () => ({
         },
     ],
 }));
-vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
-    matched: [
-        {
-            path: '/',
-            redirect: {
-                name: 'Dashboard',
+
+describe('Leftmenu', () => {
+    let vm;
+    let navigation;
+    beforeAll(() => {
+        vi.spyOn(axios, 'get').mockResolvedValue({
+            data: [],
+        });
+
+        vm = createWrapper(Leftmenu, {
+            propsData: {
+                source: 'main',
             },
-            name: 'Main',
-            meta: {},
-            props: {
-                default: false,
-            },
-            children: [
+        }).vm;
+
+        navigation = useNavigationStore();
+        navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
+        navigation.getModules = vi.fn().mockReturnValue({
+            value: [
                 {
-                    path: '/dashboard',
-                    name: 'Dashboard',
-                    meta: {
-                        title: 'dashboard',
-                        icon: 'dashboard',
-                    },
+                    name: 'customer',
+                    title: 'customer.pageTitles.customers',
+                    icon: 'vn:customer',
+                    module: 'customer',
                 },
             ],
-        },
-        {
-            path: '/customer',
-            redirect: {
-                name: 'CustomerMain',
-            },
-            name: 'Customer',
-            meta: {
-                title: 'customers',
-                icon: 'vn:client',
-                moduleName: 'Customer',
-                keyBinding: 'c',
-                menu: 'customer',
-            },
-        },
-    ],
-    query: {},
-    params: {},
-    meta: { moduleName: 'mockName' },
-    path: 'mockName/1',
-    name: 'Customer',
-});
-function mount(source = 'main') {
-    vi.spyOn(axios, 'get').mockResolvedValue({
-        data: [],
-    });
-    const wrapper = createWrapper(Leftmenu, {
-        propsData: {
-            source,
-        },
-    });
-
-    navigation = useNavigationStore();
-    navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
-    navigation.getModules = vi.fn().mockReturnValue({
-        value: [
-            {
-                name: 'customer',
-                title: 'customer.pageTitles.customers',
-                icon: 'vn:customer',
-                module: 'customer',
-            },
-        ],
-    });
-    return wrapper;
-}
-
-describe('getRoutes', () => {
-    afterEach(() => vi.clearAllMocks());
-    const getRoutes = vi.fn().mockImplementation((props, getMethodA, getMethodB) => {
-        const handleRoutes = {
-            methodA: getMethodA,
-            methodB: getMethodB,
-        };
-        try {
-            handleRoutes[props.source]();
-        } catch (error) {
-            throw Error('Method not defined');
-        }
-    });
-
-    const getMethodA = vi.fn();
-    const getMethodB = vi.fn();
-    const fn = (props) => getRoutes(props, getMethodA, getMethodB);
-
-    it('should call getMethodB when source is card', () => {
-        let props = { source: 'methodB' };
-        fn(props);
-
-        expect(getMethodB).toHaveBeenCalled();
-        expect(getMethodA).not.toHaveBeenCalled();
-    });
-    it('should call getMethodA when source is main', () => {
-        let props = { source: 'methodA' };
-        fn(props);
-
-        expect(getMethodA).toHaveBeenCalled();
-        expect(getMethodB).not.toHaveBeenCalled();
-    });
-
-    it('should call getMethodA when source is not exists or undefined', () => {
-        let props = { source: 'methodC' };
-        expect(() => fn(props)).toThrowError('Method not defined');
-
-        expect(getMethodA).not.toHaveBeenCalled();
-        expect(getMethodB).not.toHaveBeenCalled();
-    });
-});
-
-describe('Leftmenu as card', () => {
-    beforeAll(() => {
-        vm = mount('card').vm;
-    });
-
-    it('should get routes for card source', async () => {
-        vm.getRoutes();
-    });
-});
-describe('Leftmenu as main', () => {
-    beforeEach(() => {
-        vm = mount().vm;
-    });
-
-    it('should initialize with default props', () => {
-        expect(vm.source).toBe('main');
-    });
-
-    it('should filter items based on search input', async () => {
-        vm.search = 'cust';
-        await vm.$nextTick();
-        expect(vm.filteredItems[0].name).toEqual('customer');
-        expect(vm.filteredItems[0].module).toEqual('customer');
-    });
-    it('should filter items based on search input', async () => {
-        vm.search = 'Rou';
-        await vm.$nextTick();
-        expect(vm.filteredItems).toEqual([]);
-    });
-
-    it('should return pinned items', () => {
-        vm.items = [
-            { name: 'Item 1', isPinned: false },
-            { name: 'Item 2', isPinned: true },
-        ];
-        expect(vm.pinnedModules).toEqual(
-            new Map([['Item 2', { name: 'Item 2', isPinned: true }]]),
-        );
-    });
-
-    it('should find matches in routes', () => {
-        const search = 'child1';
-        const item = {
-            children: [
-                { name: 'child1', children: [] },
-                { name: 'child2', children: [] },
-            ],
-        };
-        const matches = vm.findMatches(search, item);
-        expect(matches).toEqual([{ name: 'child1', children: [] }]);
-    });
-    it('should not proceed if event is already prevented', async () => {
-        const item = { module: 'testModule', isPinned: false };
-        const event = {
-            preventDefault: vi.fn(),
-            stopPropagation: vi.fn(),
-            defaultPrevented: true,
-        };
-
-        await vm.togglePinned(item, event);
-
-        expect(event.preventDefault).not.toHaveBeenCalled();
-        expect(event.stopPropagation).not.toHaveBeenCalled();
-    });
-
-    it('should call quasar.notify with success message', async () => {
-        const item = { module: 'testModule', isPinned: false };
-        const event = {
-            preventDefault: vi.fn(),
-            stopPropagation: vi.fn(),
-            defaultPrevented: false,
-        };
-        const response = { data: { id: 1 } };
-
-        vi.spyOn(axios, 'post').mockResolvedValue(response);
-        vi.spyOn(vm.quasar, 'notify');
-
-        await vm.togglePinned(item, event);
-
-        expect(vm.quasar.notify).toHaveBeenCalledWith({
-            message: 'Data saved',
-            type: 'positive',
         });
     });
 
-    it('should handle a single matched route with a menu', () => {
-        const route = {
-            matched: [{ meta: { menu: 'customer' } }],
-        };
-
-        const result = vm.betaGetRoutes();
-
-        expect(result.meta.menu).toEqual(route.matched[0].meta.menu);
-    });
-    it('should get routes for main source', () => {
-        vm.props.source = 'main';
-        vm.getRoutes();
-        expect(navigation.getModules).toHaveBeenCalled();
-    });
-
-    it('should find direct child matches', () => {
-        const search = 'child1';
-        const item = {
-            children: [{ name: 'child1' }, { name: 'child2' }],
-        };
-        const result = vm.findMatches(search, item);
-        expect(result).toEqual([{ name: 'child1' }]);
-    });
-
-    it('should find nested child matches', () => {
-        const search = 'child3';
-        const item = {
-            children: [
-                { name: 'child1' },
-                {
-                    name: 'child2',
-                    children: [{ name: 'child3' }],
-                },
-            ],
-        };
-        const result = vm.findMatches(search, item);
-        expect(result).toEqual([{ name: 'child3' }]);
-    });
-});
-
-describe('normalize', () => {
-    beforeAll(() => {
-        vm = mount('card').vm;
-    });
-    it('should normalize and lowercase text', () => {
-        const input = 'ÁÉÍÓÚáéíóú';
-        const expected = 'aeiouaeiou';
-        expect(vm.normalize(input)).toBe(expected);
-    });
-
-    it('should handle empty string', () => {
-        const input = '';
-        const expected = '';
-        expect(vm.normalize(input)).toBe(expected);
-    });
-
-    it('should handle text without diacritics', () => {
-        const input = 'hello';
-        const expected = 'hello';
-        expect(vm.normalize(input)).toBe(expected);
-    });
-
-    it('should handle mixed text', () => {
-        const input = 'Héllo Wórld!';
-        const expected = 'hello world!';
-        expect(vm.normalize(input)).toBe(expected);
-    });
-});
-
-describe('addChildren', () => {
-    const module = 'testModule';
-    beforeEach(() => {
-        vm = mount().vm;
-        vi.clearAllMocks();
-    });
-
-    it('should add menu items to parent if matches are found', () => {
-        const parent = 'testParent';
-        const route = {
-            meta: {
-                menu: 'testMenu',
+    it('should return a proper formated object with two child items', async () => {
+        const expectedMenuItem = [
+            {
+                children: null,
+                name: 'CustomerList',
+                title: 'globals.pageTitles.list',
+                icon: 'view_list',
             },
-            children: [{ name: 'child1' }, { name: 'child2' }],
-        };
-        vm.addChildren(module, route, parent);
-
-        expect(navigation.addMenuItem).toHaveBeenCalled();
-    });
-
-    it('should handle routes with no meta menu', () => {
-        const route = {
-            meta: {},
-            menus: {},
-        };
-
-        const parent = [];
-
-        vm.addChildren(module, route, parent);
-        expect(navigation.addMenuItem).toHaveBeenCalled();
-    });
-
-    it('should handle empty parent array', () => {
-        const parent = [];
-        const route = {
-            meta: {
-                menu: 'child11',
+            {
+                children: null,
+                name: 'CustomerCreate',
+                title: 'globals.pageTitles.createCustomer',
+                icon: 'vn:addperson',
             },
-            children: [
-                {
-                    name: 'child1',
-                    meta: {
-                        menuChildren: [
-                            {
-                                name: 'CustomerCreditContracts',
-                                title: 'creditContracts',
-                                icon: 'vn:solunion',
-                            },
-                        ],
-                    },
-                },
-            ],
-        };
-        vm.addChildren(module, route, parent);
-        expect(navigation.addMenuItem).toHaveBeenCalled();
+        ];
+        const firstMenuItem = vm.items[0];
+        expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
     });
 });
diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js
index 9e449745a..ac20f911e 100644
--- a/src/components/__tests__/UserPanel.spec.js
+++ b/src/components/__tests__/UserPanel.spec.js
@@ -1,65 +1,61 @@
-import { vi, describe, expect, it, beforeEach, afterEach } from 'vitest';
+import { vi, describe, expect, it, beforeEach, beforeAll, afterEach } from 'vitest';
 import { createWrapper } from 'app/test/vitest/helper';
 import UserPanel from 'src/components/UserPanel.vue';
 import axios from 'axios';
 import { useState } from 'src/composables/useState';
 
-vi.mock('src/utils/quasarLang', () => ({
-  default: vi.fn(),
-}));
-
 describe('UserPanel', () => {
-  let wrapper;
-  let vm;
-  let state;
+    let wrapper;
+    let vm;
+    let state;
 
-  beforeEach(() => {
-    wrapper = createWrapper(UserPanel, {});
-    state = useState();
-    state.setUser({
-      id: 115,
-      name: 'itmanagement',
-      nickname: 'itManagementNick',
-      lang: 'en',
-      darkMode: false,
-      companyFk: 442,
-      warehouseFk: 1,
+    beforeEach(() => {
+        wrapper = createWrapper(UserPanel, {});
+        state = useState();
+        state.setUser({
+            id: 115,
+            name: 'itmanagement',
+            nickname: 'itManagementNick',
+            lang: 'en',
+            darkMode: false,
+            companyFk: 442,
+            warehouseFk: 1,
+        });
+        wrapper = wrapper.wrapper;
+        vm = wrapper.vm;
     });
-    wrapper = wrapper.wrapper;
-    vm = wrapper.vm;
-  });
 
-  afterEach(() => {
-    vi.clearAllMocks();
-  });
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
 
-  it('should fetch warehouses data on mounted', async () => {
-    const fetchData = wrapper.findComponent({ name: 'FetchData' });
-    expect(fetchData.props('url')).toBe('Warehouses');
-    expect(fetchData.props('autoLoad')).toBe(true);
-  });
+    it('should fetch warehouses data on mounted', async () => {
+        const fetchData = wrapper.findComponent({ name: 'FetchData' });
+        expect(fetchData.props('url')).toBe('Warehouses');
+        expect(fetchData.props('autoLoad')).toBe(true);
+    });
 
-  it('should toggle dark mode correctly and update preferences', async () => {
-    await vm.saveDarkMode(true);
-    expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
-    expect(vm.user.darkMode).toBe(true);
-    await vm.updatePreferences();
-    expect(vm.darkMode).toBe(true);
-  });
+    it('should toggle dark mode correctly and update preferences', async () => {
+        await vm.saveDarkMode(true);
+        expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
+        expect(vm.user.darkMode).toBe(true);
+        vm.updatePreferences();
+        expect(vm.darkMode).toBe(true);
+    });
 
-  it('should change user language and update preferences', async () => {
-    const userLanguage = 'es';
-    await vm.saveLanguage(userLanguage);
-    expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
-    expect(vm.user.lang).toBe(userLanguage);
-    await vm.updatePreferences();
-    expect(vm.locale).toBe(userLanguage);
-  });
+    it('should change user language and update preferences', async () => {
+        const userLanguage = 'es';
+        await vm.saveLanguage(userLanguage);
+        expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
+        expect(vm.user.lang).toBe(userLanguage);
+        vm.updatePreferences();
+        expect(vm.locale).toBe(userLanguage);
+    });
 
-  it('should update user data', async () => {
-    const key = 'name';
-    const value = 'itboss';
-    await vm.saveUserData(key, value);
-    expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
-  });
-});
\ No newline at end of file
+    it('should update user data', async () => {
+        const key = 'name';
+        const value = 'itboss';
+        await vm.saveUserData(key, value);
+        expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
+    });
+});
diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue
index 44002c22a..0d80f43ce 100644
--- a/src/components/common/VnCard.vue
+++ b/src/components/common/VnCard.vue
@@ -10,11 +10,11 @@ import LeftMenu from 'components/LeftMenu.vue';
 import RightMenu from 'components/common/RightMenu.vue';
 const props = defineProps({
     dataKey: { type: String, required: true },
-    url: { type: String, default: undefined },
+    baseUrl: { type: String, default: undefined },
+    customUrl: { type: String, default: undefined },
     filter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
-    idInWhere: { type: Boolean, default: false },
     searchDataKey: { type: String, default: undefined },
     searchbarProps: { type: Object, default: undefined },
     redirectOnError: { type: Boolean, default: false },
@@ -23,20 +23,25 @@ const props = defineProps({
 const stateStore = useStateStore();
 const route = useRoute();
 const router = useRouter();
+const url = computed(() => {
+    if (props.baseUrl) {
+        return `${props.baseUrl}/${route.params.id}`;
+    }
+    return props.customUrl;
+});
 const searchRightDataKey = computed(() => {
     if (!props.searchDataKey) return route.name;
     return props.searchDataKey;
 });
-
 const arrayData = useArrayData(props.dataKey, {
-    url: props.url,
-    userFilter: props.filter,
-    oneRecord: true,
+    url: url.value,
+    filter: props.filter,
 });
 
 onBeforeMount(async () => {
     try {
-        await fetch(route.params.id);
+        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
+        await arrayData.fetch({ append: false, updateRouter: false });
     } catch {
         const { matched: matches } = router.currentRoute.value;
         const { path } = matches.at(-1);
@@ -44,17 +49,13 @@ onBeforeMount(async () => {
     }
 });
 
-onBeforeRouteUpdate(async (to, from) => {
-    const id = to.params.id;
-    if (id !== from.params.id) await fetch(id, true);
-});
-
-async function fetch(id, append = false) {
-    const regex = /\/(\d+)/;
-    if (props.idInWhere) arrayData.store.filter.where = { id };
-    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
-    else arrayData.store.url = props.url.replace(regex, `/${id}`);
-    await arrayData.fetch({ append, updateRouter: false });
+if (props.baseUrl) {
+    onBeforeRouteUpdate(async (to, from) => {
+        if (to.params.id !== from.params.id) {
+            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
+            await arrayData.fetch({ append: false, updateRouter: false });
+        }
+    });
 }
 </script>
 <template>
@@ -82,7 +83,7 @@ async function fetch(id, append = false) {
         <QPage>
             <VnSubToolbar />
             <div :class="[useCardSize(), $attrs.class]">
-                <RouterView :key="$route.path" />
+                <RouterView :key="route.path" />
             </div>
         </QPage>
     </QPageContainer>
diff --git a/src/components/common/VnCardBeta.vue b/src/components/common/VnCardBeta.vue
index 7c82316dc..f237a300c 100644
--- a/src/components/common/VnCardBeta.vue
+++ b/src/components/common/VnCardBeta.vue
@@ -1,6 +1,6 @@
 <script setup>
-import { onBeforeMount } from 'vue';
-import { useRouter, onBeforeRouteUpdate } from 'vue-router';
+import { onBeforeMount, computed } from 'vue';
+import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useStateStore } from 'stores/useStateStore';
 import useCardSize from 'src/composables/useCardSize';
@@ -9,9 +9,10 @@ import VnSubToolbar from '../ui/VnSubToolbar.vue';
 
 const props = defineProps({
     dataKey: { type: String, required: true },
-    url: { type: String, default: undefined },
-    idInWhere: { type: Boolean, default: false },
+    baseUrl: { type: String, default: undefined },
+    customUrl: { type: String, default: undefined },
     filter: { type: Object, default: () => {} },
+    userFilter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
     searchDataKey: { type: String, default: undefined },
@@ -20,42 +21,46 @@ const props = defineProps({
 });
 
 const stateStore = useStateStore();
+const route = useRoute();
 const router = useRouter();
+const url = computed(() => {
+    if (props.baseUrl) {
+        return `${props.baseUrl}/${route.params.id}`;
+    }
+    return props.customUrl;
+});
+
 const arrayData = useArrayData(props.dataKey, {
-    url: props.url,
-    userFilter: props.filter,
-    oneRecord: true,
+    url: url.value,
+    filter: props.filter,
+    userFilter: props.userFilter,
 });
 
 onBeforeMount(async () => {
-    const route = router.currentRoute.value;
     try {
-        await fetch(route.params.id);
+        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
+        await arrayData.fetch({ append: false, updateRouter: false });
     } catch {
-        const { matched: matches } = route;
+        const { matched: matches } = router.currentRoute.value;
         const { path } = matches.at(-1);
         router.push({ path: path.replace(/:id.*/, '') });
     }
 });
 
-onBeforeRouteUpdate(async (to, from) => {
-    if (hasRouteParam(to.params)) {
-        const { matched } = router.currentRoute.value;
-        const { name } = matched.at(-3);
-        if (name) {
-            router.push({ name, params: to.params });
+if (props.baseUrl) {
+    onBeforeRouteUpdate(async (to, from) => {
+        if (hasRouteParam(to.params)) {
+            const { matched } = router.currentRoute.value;
+            const { name } = matched.at(-3);
+            if (name) {
+                router.push({ name, params: to.params });
+            }
         }
-    }
-    const id = to.params.id;
-    if (id !== from.params.id) await fetch(id, true);
-});
-
-async function fetch(id, append = false) {
-    const regex = /\/(\d+)/;
-    if (props.idInWhere) arrayData.store.filter.where = { id };
-    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
-    else arrayData.store.url = props.url.replace(regex, `/${id}`);
-    await arrayData.fetch({ append, updateRouter: false });
+        if (to.params.id !== from.params.id) {
+            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
+            await arrayData.fetch({ append: false, updateRouter: false });
+        }
+    });
 }
 function hasRouteParam(params, valueToCheck = ':addressId') {
     return Object.values(params).includes(valueToCheck);
@@ -69,6 +74,6 @@ function hasRouteParam(params, valueToCheck = ':addressId') {
     </Teleport>
     <VnSubToolbar />
     <div :class="[useCardSize(), $attrs.class]">
-        <RouterView :key="$route.path" />
+        <RouterView :key="route.path" />
     </div>
 </template>
diff --git a/src/components/common/VnCheckbox.vue b/src/components/common/VnCheckbox.vue
deleted file mode 100644
index 27131d45e..000000000
--- a/src/components/common/VnCheckbox.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-<script setup>
-import { computed } from 'vue';
-
-const model = defineModel({ type: [Number, Boolean] });
-const $props = defineProps({
-    info: {
-        type: String,
-        default: null,
-    },
-});
-
-const checkboxModel = computed({
-    get() {
-        if (typeof model.value === 'number') {
-            return model.value !== 0;
-        }
-        return model.value;
-    },
-    set(value) {
-        if (typeof model.value === 'number') {
-            model.value = value ? 1 : 0;
-        } else {
-            model.value = value;
-        }
-    },
-});
-</script>
-<template>
-    <div>
-        <QCheckbox v-bind="$attrs" v-on="$attrs" v-model="checkboxModel" />
-        <QIcon
-            v-if="info"
-            v-bind="$attrs"
-            class="cursor-info q-ml-sm"
-            name="info"
-            size="sm"
-        >
-            <QTooltip>
-                {{ info }}
-            </QTooltip>
-        </QIcon>
-    </div>
-</template>
diff --git a/src/components/common/VnColor.vue b/src/components/common/VnColor.vue
deleted file mode 100644
index 8a5a787b0..000000000
--- a/src/components/common/VnColor.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-<script setup>
-const $props = defineProps({
-    colors: {
-        type: String,
-        default: '{"value": []}',
-    },
-});
-
-const colorArray = JSON.parse($props.colors)?.value;
-const maxHeight = 30;
-const colorHeight = maxHeight / colorArray?.length;
-</script>
-<template>
-    <div v-if="colors" class="color-div" :style="{ height: `${maxHeight}px` }">
-        <div
-            v-for="(color, index) in colorArray"
-            :key="index"
-            :style="{
-                backgroundColor: `#${color}`,
-                height: `${colorHeight}px`,
-            }"
-        >
-            &nbsp;
-        </div>
-    </div>
-</template>
-<style scoped>
-.color-div {
-    display: flex;
-    flex-direction: column;
-}
-</style>
diff --git a/src/components/common/VnComponent.vue b/src/components/common/VnComponent.vue
index a9e1c8cff..580bcf348 100644
--- a/src/components/common/VnComponent.vue
+++ b/src/components/common/VnComponent.vue
@@ -17,8 +17,6 @@ const $props = defineProps({
     },
 });
 
-const emit = defineEmits(['blur']);
-
 const componentArray = computed(() => {
     if (typeof $props.prop === 'object') return [$props.prop];
     return $props.prop;
@@ -48,8 +46,7 @@ function toValueAttrs(attrs) {
     <span
         v-for="toComponent of componentArray"
         :key="toComponent.name"
-        class="column fit"
-        :class="toComponent?.component == 'checkbox' ? 'flex-center' : ''"
+        class="column flex-center fit"
     >
         <component
             v-if="toComponent?.component"
@@ -57,7 +54,6 @@ function toValueAttrs(attrs) {
             v-bind="mix(toComponent).attrs"
             v-on="mix(toComponent).event ?? {}"
             v-model="model"
-            @blur="emit('blur')"
         />
     </span>
 </template>
diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue
index 424781a26..36c87bab0 100644
--- a/src/components/common/VnDmsList.vue
+++ b/src/components/common/VnDmsList.vue
@@ -17,7 +17,7 @@ import { useSession } from 'src/composables/useSession';
 const route = useRoute();
 const quasar = useQuasar();
 const { t } = useI18n();
-const rows = ref([]);
+const rows = ref();
 const dmsRef = ref();
 const formDialog = ref({});
 const token = useSession().getTokenMultimedia();
@@ -389,14 +389,6 @@ defineExpose({
                     </div>
                 </template>
             </QTable>
-            <div 
-                v-else 
-                class="info-row q-pa-md text-center"
-            >
-                <h5>
-                    {{ t('No data to display') }}
-                </h5>
-            </div>
         </template>
     </VnPaginate>
     <QDialog v-model="formDialog.show">
@@ -413,7 +405,7 @@ defineExpose({
             fab
             color="primary"
             icon="add"
-            v-shortcut
+            shortcut="+"
             @click="showFormDialog()"
             class="fill-icon"
         >
diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index aeb4a31fd..78f08a479 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -11,7 +11,6 @@ const emit = defineEmits([
     'update:options',
     'keyup.enter',
     'remove',
-    'blur',
 ]);
 
 const $props = defineProps({
@@ -137,7 +136,6 @@ const handleUppercase = () => {
             :type="$attrs.type"
             :class="{ required: isRequired }"
             @keyup.enter="emit('keyup.enter')"
-            @blur="emit('blur')"
             @keydown="handleKeydown"
             :clearable="false"
             :rules="mixinRules"
@@ -145,7 +143,7 @@ const handleUppercase = () => {
             hide-bottom-space
             :data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
         >
-            <template #prepend v-if="$slots.prepend">
+            <template #prepend>
                 <slot name="prepend" />
             </template>
             <template #append>
@@ -170,11 +168,11 @@ const handleUppercase = () => {
                         }
                     "
                 ></QIcon>
-
+                
                 <QIcon
                     name="match_case"
                     size="xs"
-                    v-if="!$attrs.disabled && !$attrs.readonly && $props.uppercase"
+                    v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
                     @click="handleUppercase"
                     class="uppercase-icon"
                 >
@@ -182,7 +180,7 @@ const handleUppercase = () => {
                         {{ t('Convert to uppercase') }}
                     </QTooltip>
                 </QIcon>
-
+                
                 <slot name="append" v-if="$slots.append && !$attrs.disabled" />
                 <QIcon v-if="info" name="info">
                     <QTooltip max-width="350px">
@@ -196,15 +194,13 @@ const handleUppercase = () => {
 
 <style>
 .uppercase-icon {
-    transition:
-        color 0.3s,
-        transform 0.2s;
-    cursor: pointer;
+  transition: color 0.3s, transform 0.2s;
+  cursor: pointer;
 }
 
 .uppercase-icon:hover {
-    color: #ed9937;
-    transform: scale(1.2);
+  color: #ed9937;
+  transform: scale(1.2);
 }
 </style>
 <i18n>
@@ -218,4 +214,4 @@ const handleUppercase = () => {
         maxLength: El valor excede los {value} carácteres
         inputMax: Debe ser menor a {value}
         Convert to uppercase: Convertir a mayúsculas
-</i18n>
+</i18n>
\ No newline at end of file
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index 73c825e1e..a8888aad8 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -42,7 +42,7 @@ const formattedDate = computed({
                 if (value.at(2) == '/') value = value.split('/').reverse().join('/');
                 value = date.formatDate(
                     new Date(value).toISOString(),
-                    'YYYY-MM-DDTHH:mm:ss.SSSZ',
+                    'YYYY-MM-DDTHH:mm:ss.SSSZ'
                 );
             }
             const [year, month, day] = value.split('-').map((e) => parseInt(e));
@@ -55,7 +55,7 @@ const formattedDate = computed({
                     orgDate.getHours(),
                     orgDate.getMinutes(),
                     orgDate.getSeconds(),
-                    orgDate.getMilliseconds(),
+                    orgDate.getMilliseconds()
                 );
             }
         }
@@ -64,7 +64,7 @@ const formattedDate = computed({
 });
 
 const popupDate = computed(() =>
-    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value,
+    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
 );
 onMounted(() => {
     // fix quasar bug
@@ -73,7 +73,7 @@ onMounted(() => {
 watch(
     () => model.value,
     (val) => (formattedDate.value = val),
-    { immediate: true },
+    { immediate: true }
 );
 
 const styleAttrs = computed(() => {
diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue
index 274f78b21..165cfae3d 100644
--- a/src/components/common/VnInputNumber.vue
+++ b/src/components/common/VnInputNumber.vue
@@ -8,7 +8,6 @@ defineProps({
 });
 
 const model = defineModel({ type: [Number, String] });
-const emit = defineEmits(['blur']);
 </script>
 <template>
     <VnInput
@@ -25,6 +24,5 @@ const emit = defineEmits(['blur']);
                     model = parseFloat(val).toFixed(decimalPlaces);
             }
         "
-        @blur="emit('blur')"
     />
 </template>
diff --git a/src/components/common/VnPopupProxy.vue b/src/components/common/VnPopupProxy.vue
deleted file mode 100644
index f386bfff8..000000000
--- a/src/components/common/VnPopupProxy.vue
+++ /dev/null
@@ -1,38 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-
-defineProps({
-    label: {
-        type: String,
-        default: '',
-    },
-    icon: {
-        type: String,
-        required: true,
-        default: null,
-    },
-    color: {
-        type: String,
-        default: 'primary',
-    },
-    tooltip: {
-        type: String,
-        default: null,
-    },
-});
-const popupProxyRef = ref(null);
-</script>
-
-<template>
-    <QBtn :color="$props.color" :icon="$props.icon" :label="$t($props.label)">
-        <template #default>
-            <slot name="extraIcon"></slot>
-            <QPopupProxy ref="popupProxyRef" style="max-width: none">
-                <QCard>
-                    <slot :popup="popupProxyRef"></slot>
-                </QCard>
-            </QPopupProxy>
-            <QTooltip>{{ $t($props.tooltip) }}</QTooltip>
-        </template>
-    </QBtn>
-</template>
diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
index 4bd17124f..ef65b841f 100644
--- a/src/components/common/VnSection.vue
+++ b/src/components/common/VnSection.vue
@@ -106,14 +106,7 @@ function checkIsMain() {
                     :data-key="dataKey"
                     :array-data="arrayData"
                     :columns="columns"
-                >
-                    <template #moreFilterPanel="{ params, orders, searchFn }">
-                        <slot
-                            name="moreFilterPanel"
-                            v-bind="{ params, orders, searchFn }"
-                        />
-                    </template>
-                </VnTableFilter>
+                />
             </slot>
         </template>
     </RightAdvancedMenu>
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 339f90e0e..95fe80a69 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -10,12 +10,7 @@ const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 const $attrs = useAttrs();
 const { t } = useI18n();
 
-const isRequired = computed(() => {
-    return useRequired($attrs).isRequired;
-});
-const requiredFieldRule = computed(() => {
-    return useRequired($attrs).requiredFieldRule;
-});
+const { isRequired, requiredFieldRule } = useRequired($attrs);
 
 const $props = defineProps({
     modelValue: {
@@ -171,8 +166,7 @@ onMounted(() => {
 });
 
 const arrayDataKey =
-    $props.dataKey ??
-    ($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
+    $props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label);
 
 const arrayData = useArrayData(arrayDataKey, {
     url: $props.url,
@@ -221,7 +215,7 @@ async function fetchFilter(val) {
         optionFilterValue.value ??
         (new RegExp(/\d/g).test(val)
             ? optionValue.value
-            : (optionFilter.value ?? optionLabel.value));
+            : optionFilter.value ?? optionLabel.value);
 
     let defaultWhere = {};
     if ($props.filterOptions.length) {
@@ -240,7 +234,7 @@ async function fetchFilter(val) {
 
     const { data } = await arrayData.applyFilter(
         { filter: filterOptions },
-        { updateRouter: false },
+        { updateRouter: false }
     );
     setOptions(data);
     return data;
@@ -273,7 +267,7 @@ async function filterHandler(val, update) {
                 ref.setOptionIndex(-1);
                 ref.moveOptionSelection(1, true);
             }
-        },
+        }
     );
 }
 
@@ -309,7 +303,7 @@ function handleKeyDown(event) {
         if (inputValue) {
             const matchingOption = myOptions.value.find(
                 (option) =>
-                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase(),
+                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase()
             );
 
             if (matchingOption) {
@@ -321,11 +315,11 @@ function handleKeyDown(event) {
         }
 
         const focusableElements = document.querySelectorAll(
-            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])',
+            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])'
         );
         const currentIndex = Array.prototype.indexOf.call(
             focusableElements,
-            event.target,
+            event.target
         );
         if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) {
             focusableElements[currentIndex + 1].focus();
diff --git a/src/components/common/VnSelectCache.vue b/src/components/common/VnSelectCache.vue
index f0f3357f6..29cf22dc5 100644
--- a/src/components/common/VnSelectCache.vue
+++ b/src/components/common/VnSelectCache.vue
@@ -14,7 +14,7 @@ const $props = defineProps({
     },
 });
 const options = ref([]);
-const emit = defineEmits(['blur']);
+
 onBeforeMount(async () => {
     const { url, optionValue, optionLabel } = useAttrs();
     const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
@@ -35,5 +35,5 @@ onBeforeMount(async () => {
 });
 </script>
 <template>
-    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" @blur="emit('blur')" />
+    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" />
 </template>
diff --git a/src/components/common/VnSelectDialog.vue b/src/components/common/VnSelectDialog.vue
index 41730b217..a4cd0011d 100644
--- a/src/components/common/VnSelectDialog.vue
+++ b/src/components/common/VnSelectDialog.vue
@@ -37,6 +37,7 @@ const isAllowedToCreate = computed(() => {
 
 defineExpose({ vnSelectDialogRef: select });
 </script>
+
 <template>
     <VnSelect
         ref="select"
@@ -66,6 +67,7 @@ defineExpose({ vnSelectDialogRef: select });
         </template>
     </VnSelect>
 </template>
+
 <style lang="scss" scoped>
 .default-icon {
     cursor: pointer;
diff --git a/src/components/common/VnSelectSupplier.vue b/src/components/common/VnSelectSupplier.vue
index 5b52ae75b..f86db4f2d 100644
--- a/src/components/common/VnSelectSupplier.vue
+++ b/src/components/common/VnSelectSupplier.vue
@@ -1,7 +1,9 @@
 <script setup>
+import { computed } from 'vue';
 import VnSelect from 'components/common/VnSelect.vue';
 
 const model = defineModel({ type: [String, Number, Object] });
+const url = 'Suppliers';
 </script>
 
 <template>
@@ -9,13 +11,11 @@ const model = defineModel({ type: [String, Number, Object] });
         :label="$t('globals.supplier')"
         v-bind="$attrs"
         v-model="model"
-        url="Suppliers"
+        :url="url"
         option-value="id"
         option-label="nickname"
         :fields="['id', 'name', 'nickname', 'nif']"
-        :filter-options="['id', 'name', 'nickname', 'nif']"
         sort-by="name ASC"
-        data-cy="vnSupplierSelect"
     >
         <template #option="scope">
             <QItem v-bind="scope.itemProps">
diff --git a/src/components/common/VnSelectTravelExtended.vue b/src/components/common/VnSelectTravelExtended.vue
deleted file mode 100644
index 46538f5f9..000000000
--- a/src/components/common/VnSelectTravelExtended.vue
+++ /dev/null
@@ -1,50 +0,0 @@
-<script setup>
-import VnSelectDialog from './VnSelectDialog.vue';
-import FilterTravelForm from 'src/components/FilterTravelForm.vue';
-import { useI18n } from 'vue-i18n';
-import { toDate } from 'src/filters';
-const { t } = useI18n();
-
-const $props = defineProps({
-    data: {
-        type: Object,
-        required: true,
-    },
-    onFilterTravelSelected: {
-        type: Function,
-        required: true,
-    },
-});
-</script>
-<template>
-    <VnSelectDialog
-        :label="t('entry.basicData.travel')"
-        v-bind="$attrs"
-        url="Travels/filter"
-        :fields="['id', 'warehouseInName']"
-        option-value="id"
-        option-label="warehouseInName"
-        map-options
-        hide-selected
-        :required="true"
-        action-icon="filter_alt"
-        :roles-allowed-to-create="['buyer']"
-    >
-        <template #form>
-            <FilterTravelForm @travel-selected="onFilterTravelSelected(data, $event)" />
-        </template>
-        <template #option="scope">
-            <QItem v-bind="scope.itemProps">
-                <QItemSection>
-                    <QItemLabel>
-                        {{ scope.opt?.agencyModeName }} -
-                        {{ scope.opt?.warehouseInName }}
-                        ({{ toDate(scope.opt?.shipped) }}) →
-                        {{ scope.opt?.warehouseOutName }}
-                        ({{ toDate(scope.opt?.landed) }})
-                    </QItemLabel>
-                </QItemSection>
-            </QItem>
-        </template>
-    </VnSelectDialog>
-</template>
diff --git a/src/components/common/__tests__/VnNotes.spec.js b/src/components/common/__tests__/VnNotes.spec.js
index 2603bf03c..8f24a7f14 100644
--- a/src/components/common/__tests__/VnNotes.spec.js
+++ b/src/components/common/__tests__/VnNotes.spec.js
@@ -1,78 +1,51 @@
-import {
-    describe,
-    it,
-    expect,
-    vi,
-    beforeAll,
-    afterEach,
-    beforeEach,
-    afterAll,
-} from 'vitest';
+import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import VnNotes from 'src/components/ui/VnNotes.vue';
-import vnDate from 'src/boot/vnDate';
 
 describe('VnNotes', () => {
     let vm;
     let wrapper;
     let spyFetch;
     let postMock;
-    let patchMock;
-    let expectedInsertBody;
-    let expectedUpdateBody;
-    const defaultOptions = {
-        url: '/test',
-        body: { name: 'Tony', lastName: 'Stark' },
-        selectType: false,
-        saveUrl: null,
-        justInput: false,
-    };
-    function generateWrapper(
-        options = defaultOptions,
-        text = null,
-        observationType = null,
-    ) {
-        vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
+    let expectedBody;
+    const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
+
+    function generateExpectedBody() {
+        expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
+    }
+
+    async function setTestParams(text, observationType, type){
+        vm.newNote.text = text;
+        vm.newNote.observationTypeFk = observationType;
+        wrapper.setProps({ selectType: type });
+    }
+
+    beforeAll(async () => {        
+        vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
+
         wrapper = createWrapper(VnNotes, {
-            propsData: options,
+            propsData: {
+                url: '/test',
+                body: { name: 'Tony', lastName: 'Stark' },
+            }
         });
         wrapper = wrapper.wrapper;
         vm = wrapper.vm;
-        vm.newNote.text = text;
-        vm.newNote.observationTypeFk = observationType;
-    }
-
-    function createSpyFetch() {
-        spyFetch = vi.spyOn(vm.$refs.vnPaginateRef, 'fetch');
-    }
-
-    function generateExpectedBody() {
-        expectedInsertBody = {
-            ...vm.$props.body,
-            ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk },
-        };
-        expectedUpdateBody = { ...vm.$props.body, ...{ notes: vm.newNote.text } };
-    }
+    });
 
     beforeEach(() => {
-        postMock = vi.spyOn(axios, 'post');
-        patchMock = vi.spyOn(axios, 'patch');
+        postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
+        spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
     });
 
     afterEach(() => {
         vi.clearAllMocks();
-        expectedInsertBody = {};
-        expectedUpdateBody = {};
-    });
-
-    afterAll(() => {
-        vi.restoreAllMocks();
+        expectedBody = {};
     });
 
     describe('insert', () => {
-        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is null', async () => {
-            generateWrapper({ selectType: true });
-            createSpyFetch();
+        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
+            await setTestParams( null, null, true );
 
             await vm.insert();
 
@@ -80,9 +53,8 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is empty', async () => {
-            generateWrapper(null, '');
-            createSpyFetch();
+        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
+            await setTestParams( "", null, false );
 
             await vm.insert();
 
@@ -90,9 +62,8 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch when observationTypeFk is null and selectType is true', async () => {
-            generateWrapper({ selectType: true }, 'Test Note');
-            createSpyFetch();
+        it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
+            await setTestParams( "Test Note", null, true );
 
             await vm.insert();
 
@@ -100,57 +71,37 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should call axios.post and vnPaginateRef.fetch when observationTypeFk is missing and selectType is false', async () => {
-            generateWrapper(null, 'Test Note');
-            createSpyFetch();
+        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
+            await setTestParams( "Test Note", null, false );
+
             generateExpectedBody();
 
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+            expect(spyFetch).toHaveBeenCalled();
+        });
+
+        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {            
+            await setTestParams( "Test Note", 1, false );
+
+            generateExpectedBody();
+
+            await vm.insert();
+
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
             expect(spyFetch).toHaveBeenCalled();
         });
 
         it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
-            generateWrapper({ selectType: true }, 'Test Note', 1);
-            createSpyFetch();
-            generateExpectedBody();
+            await setTestParams( "Test Note", 1, true );
 
+            generateExpectedBody();
+            
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
             expect(spyFetch).toHaveBeenCalled();
         });
     });
-
-    describe('update', () => {
-        it('should call axios.patch with saveUrl when saveUrl is set and justInput is true', async () => {
-            generateWrapper({
-                url: '/business',
-                justInput: true,
-                saveUrl: '/saveUrlTest',
-            });
-            generateExpectedBody();
-
-            await vm.update();
-
-            expect(patchMock).toHaveBeenCalledWith(vm.$props.saveUrl, expectedUpdateBody);
-        });
-
-        it('should call axios.patch with url when saveUrl is not set and justInput is true', async () => {
-            generateWrapper({
-                url: '/business',
-                body: { workerFk: 1110 },
-                justInput: true,
-            });
-            generateExpectedBody();
-
-            await vm.update();
-
-            expect(patchMock).toHaveBeenCalledWith(
-                `${vm.$props.url}/${vm.$props.body.workerFk}`,
-                expectedUpdateBody,
-            );
-        });
-    });
-});
+});
\ No newline at end of file
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index e6e7e6fa0..43dc15e9b 100644
--- a/src/components/ui/CardDescriptor.vue
+++ b/src/components/ui/CardDescriptor.vue
@@ -6,7 +6,6 @@ import { useArrayData } from 'composables/useArrayData';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import { useState } from 'src/composables/useState';
 import { useRoute } from 'vue-router';
-import { useClipboard } from 'src/composables/useClipboard';
 import VnMoreOptions from './VnMoreOptions.vue';
 
 const $props = defineProps({
@@ -30,6 +29,10 @@ const $props = defineProps({
         type: String,
         default: null,
     },
+    module: {
+        type: String,
+        default: null,
+    },
     summary: {
         type: Object,
         default: null,
@@ -43,7 +46,6 @@ const $props = defineProps({
 const state = useState();
 const route = useRoute();
 const { t } = useI18n();
-const { copyText } = useClipboard();
 const { viewSummary } = useSummaryDialog();
 let arrayData;
 let store;
@@ -55,13 +57,12 @@ defineExpose({ getData });
 onBeforeMount(async () => {
     arrayData = useArrayData($props.dataKey, {
         url: $props.url,
-        userFilter: $props.filter,
+        filter: $props.filter,
         skip: 0,
-        oneRecord: true,
     });
     store = arrayData.store;
     entity = computed(() => {
-        const data = store.data ?? {};
+        const data = (Array.isArray(store.data) ? store.data[0] : store.data) ?? {};
         if (data) emit('onFetch', data);
         return data;
     });
@@ -72,7 +73,7 @@ onBeforeMount(async () => {
         () => [$props.url, $props.filter],
         async () => {
             if (!isSameDataKey.value) await getData();
-        },
+        }
     );
 });
 
@@ -83,7 +84,7 @@ async function getData() {
     try {
         const { data } = await arrayData.fetch({ append: false, updateRouter: false });
         state.set($props.dataKey, data);
-        emit('onFetch', data);
+        emit('onFetch', Array.isArray(data) ? data[0] : data);
     } finally {
         isLoading.value = false;
     }
@@ -101,21 +102,13 @@ function getValueFromPath(path) {
     return current;
 }
 
-function copyIdText(id) {
-    copyText(id, {
-        component: {
-            copyValue: id,
-        },
-    });
-}
-
 const emit = defineEmits(['onFetch']);
 
 const iconModule = computed(() => route.matched[1].meta.icon);
 const toModule = computed(() =>
     route.matched[1].path.split('/').length > 2
         ? route.matched[1].redirect
-        : route.matched[1].children[0].redirect,
+        : route.matched[1].children[0].redirect
 );
 </script>
 
@@ -154,9 +147,7 @@ const toModule = computed(() =>
                         {{ t('components.smartCard.openSummary') }}
                     </QTooltip>
                 </QBtn>
-                <RouterLink
-                    :to="{ name: `${dataKey}Summary`, params: { id: entity.id } }"
-                >
+                <RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }">
                     <QBtn
                         class="link"
                         color="white"
@@ -192,22 +183,9 @@ const toModule = computed(() =>
                             </slot>
                         </div>
                     </QItemLabel>
-                    <QItem>
+                    <QItem dense>
                         <QItemLabel class="subtitle" caption>
                             #{{ getValueFromPath(subtitle) ?? entity.id }}
-                            <QBtn
-                                round
-                                flat
-                                dense
-                                size="sm"
-                                icon="content_copy"
-                                color="primary"
-                                @click.stop="copyIdText(entity.id)"
-                            >
-                                <QTooltip>
-                                    {{ t('globals.copyId') }}
-                                </QTooltip>
-                            </QBtn>
                         </QItemLabel>
                     </QItem>
                 </QList>
@@ -315,11 +293,3 @@ const toModule = computed(() =>
     }
 }
 </style>
-<i18n>
-    en:
-        globals:
-            copyId: Copy ID
-    es:
-        globals:
-            copyId: Copiar ID
-</i18n>
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index 6a61994c1..c815b8e16 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -40,10 +40,9 @@ const arrayData = useArrayData(props.dataKey, {
     filter: props.filter,
     userFilter: props.userFilter,
     skip: 0,
-    oneRecord: true,
 });
 const { store } = arrayData;
-const entity = computed(() => store.data);
+const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
 const isLoading = ref(false);
 
 defineExpose({
@@ -62,7 +61,7 @@ async function fetch() {
     store.filter = props.filter ?? {};
     isLoading.value = true;
     const { data } = await arrayData.fetch({ append: false, updateRouter: false });
-    emit('onFetch', data);
+    emit('onFetch', Array.isArray(data) ? data[0] : data);
     isLoading.value = false;
 }
 </script>
@@ -209,13 +208,4 @@ async function fetch() {
 .summaryHeader {
     color: $white;
 }
-
-.cardSummary :deep(.q-card__section[content]) {
-    display: flex;
-    flex-wrap: wrap;
-    padding: 0;
-    > * {
-        flex: 1;
-    }
-}
 </style>
diff --git a/src/components/ui/SkeletonDescriptor.vue b/src/components/ui/SkeletonDescriptor.vue
index f9188221a..9679751f5 100644
--- a/src/components/ui/SkeletonDescriptor.vue
+++ b/src/components/ui/SkeletonDescriptor.vue
@@ -1,32 +1,53 @@
-<script setup>
-defineProps({
-    hasImage: {
-        type: Boolean,
-        default: false,
-    },
-});
-</script>
 <template>
-    <div id="descriptor-skeleton" class="bg-vn-page">
+    <div id="descriptor-skeleton">
         <div class="row justify-between q-pa-sm">
-            <QSkeleton square size="30px" v-for="i in 3" :key="i" />
+            <QSkeleton square size="40px" />
+            <QSkeleton square size="40px" />
+            <QSkeleton square height="40px" width="20px" />
         </div>
-        <div class="q-pa-xs" v-if="hasImage">
-            <QSkeleton square height="200px" width="100%" />
+        <div class="col justify-between q-pa-sm q-gutter-y-xs">
+            <QSkeleton square height="40px" width="150px" />
+            <QSkeleton square height="30px" width="70px" />
         </div>
-        <div class="col justify-between q-pa-md q-gutter-y-xs">
-            <QSkeleton square height="25px" width="150px" />
-            <QSkeleton square height="15px" width="70px" />
-        </div>
-        <div class="q-pl-sm q-pa-sm q-mb-md">
-            <div class="row q-gutter-x-sm q-pa-none q-ma-none" v-for="i in 5" :key="i">
-                <QSkeleton type="text" square height="20px" width="30%" />
-                <QSkeleton type="text" square height="20px" width="60%" />
+        <div class="col q-pl-sm q-pa-sm q-mb-md">
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
+            </div>
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
+            </div>
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
+            </div>
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
+            </div>
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
+            </div>
+            <div class="row justify-between">
+                <QSkeleton type="text" square height="30px" width="20%" />
+                <QSkeleton type="text" square height="30px" width="60%" />
             </div>
         </div>
 
-        <QCardActions class="q-gutter-x-sm justify-between">
-            <QSkeleton size="40px" v-for="i in 5" :key="i" />
+        <QCardActions>
+            <QSkeleton size="40px" />
+            <QSkeleton size="40px" />
+            <QSkeleton size="40px" />
+            <QSkeleton size="40px" />
+            <QSkeleton size="40px" />
         </QCardActions>
     </div>
 </template>
+
+<style lang="scss" scoped>
+#descriptor-skeleton .q-card__actions {
+    justify-content: space-between;
+}
+</style>
diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index c6f539879..a02b56bdb 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -82,7 +82,7 @@ function cancel() {
                     @click="cancel()"
                 />
             </QCardSection>
-            <QCardSection class="q-pb-none" data-cy="VnConfirm_message">
+            <QCardSection class="q-pb-none">
                 <span v-if="message !== false" v-html="message" />
             </QCardSection>
             <QCardSection class="row items-center q-pt-none">
@@ -95,7 +95,6 @@ function cancel() {
                     :disable="isLoading"
                     flat
                     @click="cancel()"
-                    data-cy="VnConfirm_cancel"
                 />
                 <QBtn
                     :label="t('globals.confirm')"
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index d6b525dc8..93f069cc6 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -114,7 +114,7 @@ async function clearFilters() {
         arrayData.resetPagination();
         // Filtrar los params no removibles
         const removableFilters = Object.keys(userParams.value).filter((param) =>
-            $props.unremovableParams.includes(param),
+            $props.unremovableParams.includes(param)
         );
         const newParams = {};
         // Conservar solo los params que no son removibles
@@ -162,13 +162,13 @@ const formatTags = (tags) => {
 
 const tags = computed(() => {
     const filteredTags = tagsList.value.filter(
-        (tag) => !($props.customTags || []).includes(tag.label),
+        (tag) => !($props.customTags || []).includes(tag.label)
     );
     return formatTags(filteredTags);
 });
 
 const customTags = computed(() =>
-    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label)),
+    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
 );
 
 async function remove(key) {
@@ -188,13 +188,10 @@ function formatValue(value) {
 const getLocale = (label) => {
     const param = label.split('.').at(-1);
     const globalLocale = `globals.params.${param}`;
-    const moduleName = route.meta.moduleName;
-    const moduleLocale = `${moduleName.toLowerCase()}.${param}`;
     if (te(globalLocale)) return t(globalLocale);
-    else if (te(moduleLocale)) return t(moduleLocale);
+    else if (te(t(`params.${param}`)));
     else {
-        const camelCaseModuleName =
-            moduleName.charAt(0).toLowerCase() + moduleName.slice(1);
+        const camelCaseModuleName = route.meta.moduleName.charAt(0).toLowerCase() + route.meta.moduleName.slice(1);    
         return t(`${camelCaseModuleName}.params.${param}`);
     }
 };
@@ -293,9 +290,6 @@ const getLocale = (label) => {
     />
 </template>
 <style scoped lang="scss">
-.q-field__label.no-pointer-events.absolute.ellipsis {
-    margin-left: 6px !important;
-}
 .list {
     width: 256px;
 }
diff --git a/src/components/ui/VnMoreOptions.vue b/src/components/ui/VnMoreOptions.vue
index 8a1c7a0f2..39e84be2b 100644
--- a/src/components/ui/VnMoreOptions.vue
+++ b/src/components/ui/VnMoreOptions.vue
@@ -11,7 +11,7 @@
         <QTooltip>
             {{ $t('components.cardDescriptor.moreOptions') }}
         </QTooltip>
-        <QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
+        <QMenu ref="menuRef">
             <QList>
                 <slot name="menu" :menu-ref="$refs.menuRef" />
             </QList>
diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index ec6289a67..1690a94ba 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { ref, reactive, useAttrs, computed } from 'vue';
+import { ref, reactive } from 'vue';
 import { onBeforeRouteLeave } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -16,27 +16,12 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FetchData from 'components/FetchData.vue';
 import VnInput from 'components/common/VnInput.vue';
 
-const emit = defineEmits(['onFetch']);
-
-const originalAttrs = useAttrs();
-
-const $attrs = computed(() => {
-    const { style, ...rest } = originalAttrs;
-    return rest;
-});
-
-const isRequired = computed(() => {
-    return Object.keys($attrs).includes('required')
-});
-
 const $props = defineProps({
     url: { type: String, default: null },
-    saveUrl: {type: String, default: null},
     filter: { type: Object, default: () => {} },
     body: { type: Object, default: () => {} },
     addNote: { type: Boolean, default: false },
     selectType: { type: Boolean, default: false },
-    justInput: { type: Boolean, default: false },
 });
 
 const { t } = useI18n();
@@ -44,13 +29,6 @@ const quasar = useQuasar();
 const newNote = reactive({ text: null, observationTypeFk: null });
 const observationTypes = ref([]);
 const vnPaginateRef = ref();
-let originalText;
-
-function handleClick(e) {
-    if (e.shiftKey && e.key === 'Enter') return;
-    if ($props.justInput) confirmAndUpdate();
-    else insert();
-}
 
 async function insert() {
     if (!newNote.text || ($props.selectType && !newNote.observationTypeFk)) return;
@@ -63,36 +41,8 @@ async function insert() {
     await axios.post($props.url, newBody);
     await vnPaginateRef.value.fetch();
 }
-
-function confirmAndUpdate() {
-    if(!newNote.text && originalText)
-        quasar
-            .dialog({
-                component: VnConfirm,
-                componentProps: {
-                    title: t('New note is empty'),
-                    message: t('Are you sure remove this note?'),
-                },
-            })
-            .onOk(update)
-            .onCancel(() => {
-                newNote.text = originalText;
-            });
-    else update();
-}
-
-async function update() {
-    originalText = newNote.text;
-    const body = $props.body;
-    const newBody = {
-        ...body,
-        ...{ notes: newNote.text },
-    };
-    await axios.patch(`${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, newBody);
-}
-
 onBeforeRouteLeave((to, from, next) => {
-    if ((newNote.text && !$props.justInput) || (newNote.text !== originalText) && $props.justInput)
+    if (newNote.text)
         quasar.dialog({
             component: VnConfirm,
             componentProps: {
@@ -103,13 +53,6 @@ onBeforeRouteLeave((to, from, next) => {
         });
     else next();
 });
-
-function fetchData([ data ]) {
-    newNote.text = data?.notes;
-    originalText = data?.notes;
-    emit('onFetch', data);
-}
-
 </script>
 <template>
     <FetchData
@@ -119,19 +62,8 @@ function fetchData([ data ]) {
         auto-load
         @on-fetch="(data) => (observationTypes = data)"
     />
-    <FetchData
-        v-if="justInput"
-        :url="url"
-        :filter="filter"
-        @on-fetch="fetchData"
-        auto-load
-    />
-    <QCard 
-        class="q-pa-xs q-mb-lg full-width" 
-        :class="{ 'just-input': $props.justInput }"
-        v-if="$props.addNote || $props.justInput"
-    >
-        <QCardSection horizontal v-if="!$props.justInput">
+    <QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
+        <QCardSection horizontal>
             {{ t('New note') }}
         </QCardSection>
         <QCardSection class="q-px-xs q-my-none q-py-none">
@@ -143,19 +75,19 @@ function fetchData([ data ]) {
                     v-model="newNote.observationTypeFk"
                     option-label="description"
                     style="flex: 0.15"
-                    :required="isRequired"
+                    :required="true"
                     @keyup.enter.stop="insert"
                 />
                 <VnInput
                     v-model.trim="newNote.text"
                     type="textarea"
-                    :label="$props.justInput && newNote.text ? '' : t('Add note here...')"
+                    :label="t('Add note here...')"
                     filled
                     size="lg"
                     autogrow
-                    @keyup.enter.stop="handleClick"
-                    :required="isRequired"
+                    @keyup.enter.stop="insert"
                     clearable
+                    :required="true"
                 >
                     <template #append>
                         <QBtn
@@ -163,7 +95,7 @@ function fetchData([ data ]) {
                             icon="save"
                             color="primary"
                             flat
-                            @click="handleClick"
+                            @click="insert"
                             class="q-mb-xs"
                             dense
                             data-cy="saveNote"
@@ -174,7 +106,6 @@ function fetchData([ data ]) {
         </QCardSection>
     </QCard>
     <VnPaginate
-        v-if="!$props.justInput"
         :data-key="$props.url"
         :url="$props.url"
         order="created DESC"
@@ -267,11 +198,6 @@ function fetchData([ data ]) {
         }
     }
 }
-.just-input {
-    padding-right: 18px;
-    margin-bottom: 2px;
-    box-shadow: none;
-}
 </style>
 <i18n>
     es:
@@ -279,6 +205,4 @@ function fetchData([ data ]) {
         New note: Nueva nota
         Save (Enter): Guardar (Intro)
         Observation type: Tipo de observación
-        New note is empty: La nueva nota esta vacia
-        Are you sure remove this note?: Estas seguro de quitar esta nota?
 </i18n>
diff --git a/src/components/ui/VnStockValueDisplay.vue b/src/components/ui/VnStockValueDisplay.vue
deleted file mode 100644
index d8f43323b..000000000
--- a/src/components/ui/VnStockValueDisplay.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-<script setup>
-import { toPercentage } from 'filters/index';
-
-import { computed } from 'vue';
-
-const props = defineProps({
-    value: {
-        type: Number,
-        required: true,
-    },
-});
-
-const valueClass = computed(() =>
-    props.value === 0 ? 'neutral' : props.value > 0 ? 'positive' : 'negative',
-);
-const iconName = computed(() =>
-    props.value === 0 ? 'equal' : props.value > 0 ? 'arrow_upward' : 'arrow_downward',
-);
-const formattedValue = computed(() => props.value);
-</script>
-<template>
-    <span :class="valueClass">
-        <QIcon :name="iconName" size="sm" class="value-icon" />
-        {{ toPercentage(formattedValue) }}
-    </span>
-</template>
-
-<style lang="scss" scoped>
-.positive {
-    color: $secondary;
-}
-.negative {
-    color: $negative;
-}
-.neutral {
-    color: $primary;
-}
-.value-icon {
-    margin-right: 4px;
-}
-</style>
diff --git a/src/components/ui/VnSubToolbar.vue b/src/components/ui/VnSubToolbar.vue
index 8d4126d1d..5ded4be00 100644
--- a/src/components/ui/VnSubToolbar.vue
+++ b/src/components/ui/VnSubToolbar.vue
@@ -19,26 +19,23 @@ onMounted(() => {
     const observer = new MutationObserver(
         () =>
             (hasContent.value =
-                actions.value?.childNodes?.length + data.value?.childNodes?.length),
+                actions.value?.childNodes?.length + data.value?.childNodes?.length)
     );
     if (actions.value) observer.observe(actions.value, opts);
     if (data.value) observer.observe(data.value, opts);
 });
 
-const actionsChildCount = () => !!actions.value?.childNodes?.length;
-
-onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
+onBeforeUnmount(() => stateStore.toggleSubToolbar());
 </script>
 
 <template>
     <QToolbar
         id="subToolbar"
-        v-show="hasContent || $slots['st-actions'] || $slots['st-data']"
         class="justify-end sticky"
+        v-show="hasContent || $slots['st-actions'] || $slots['st-data']"
     >
         <slot name="st-data">
-            <div id="st-data" :class="{ 'full-width': !actionsChildCount() }">
-            </div>
+            <div id="st-data"></div>
         </slot>
         <QSpace />
         <slot name="st-actions">
diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index 2f7f90882..411ebf9bb 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -51,6 +51,16 @@ describe('CardSummary', () => {
         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 newUrl = 'CardSummary/35';
         const newKey = 'cardSummaryKey/35';
@@ -62,7 +72,7 @@ describe('CardSummary', () => {
         expect(vm.store.filter).toEqual({ key: newKey });
     });
 
-    it('should return true if route path ends with /summary', () => {
+    it('should return true if route path ends with /summary' , () => {
         expect(vm.isSummary).toBe(true);
     });
-});
+});
\ No newline at end of file
diff --git a/src/composables/__tests__/useArrayData.spec.js b/src/composables/__tests__/useArrayData.spec.js
index a610ba9eb..d4c5d0949 100644
--- a/src/composables/__tests__/useArrayData.spec.js
+++ b/src/composables/__tests__/useArrayData.spec.js
@@ -16,7 +16,7 @@ describe('useArrayData', () => {
         vi.clearAllMocks();
     });
 
-    it('should fetch and replace url with new params', async () => {
+    it('should fetch and repalce url with new params', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
@@ -33,11 +33,11 @@ describe('useArrayData', () => {
         });
         expect(routerReplace.path).toEqual('mockSection/list');
         expect(JSON.parse(routerReplace.query.params)).toEqual(
-            expect.objectContaining(params),
+            expect.objectContaining(params)
         );
     });
 
-    it('should get data and send new URL without keeping parameters, if there is only one record', async () => {
+    it('Should get data and send new URL without keeping parameters, if there is only one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl', navigate: {} });
@@ -56,7 +56,7 @@ describe('useArrayData', () => {
         expect(routerPush.query).toBeUndefined();
     });
 
-    it('should get data and send new URL keeping parameters, if you have more than one record', async () => {
+    it('Should get data and send new URL keeping parameters, if you have more than one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }, { id: 2 }] });
 
         vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
@@ -95,25 +95,4 @@ describe('useArrayData', () => {
         expect(routerPush.path).toEqual('mockName/');
         expect(routerPush.query.params).toBeDefined();
     });
-
-    it('should return one record', async () => {
-        vi.spyOn(axios, 'get').mockReturnValueOnce({
-            data: [
-                { id: 1, name: 'Entity 1' },
-                { id: 2, name: 'Entity 2' },
-            ],
-        });
-        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
-        await arrayData.fetch({});
-
-        expect(arrayData.store.data).toEqual({ id: 1, name: 'Entity 1' });
-    });
-
-    it('should handle empty data gracefully if has to return one record', async () => {
-        vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
-        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
-        await arrayData.fetch({});
-
-        expect(arrayData.store.data).toBeUndefined();
-    });
 });
diff --git a/src/composables/checkEntryLock.js b/src/composables/checkEntryLock.js
deleted file mode 100644
index f964dea27..000000000
--- a/src/composables/checkEntryLock.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { useQuasar } from 'quasar';
-import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
-import axios from 'axios';
-import VnConfirm from 'components/ui/VnConfirm.vue';
-
-export async function checkEntryLock(entryFk, userFk) {
-    const { t } = useI18n();
-    const quasar = useQuasar();
-    const { push } = useRouter();
-    const { data } = await axios.get(`Entries/${entryFk}`, {
-        params: {
-            filter: JSON.stringify({
-                fields: ['id', 'locked', 'lockerUserFk'],
-                include: { relation: 'user', scope: { fields: ['id', 'nickname'] } },
-            }),
-        },
-    });
-    const entryConfig = await axios.get('EntryConfigs/findOne');
-
-    if (data?.lockerUserFk && data?.locked) {
-        const now = new Date(Date.vnNow()).getTime();
-        const lockedTime = new Date(data.locked).getTime();
-        const timeDiff = (now - lockedTime) / 1000;
-        const isMaxTimeLockExceeded = entryConfig.data.maxLockTime > timeDiff;
-
-        if (data?.lockerUserFk !== userFk && isMaxTimeLockExceeded) {
-            quasar
-                .dialog({
-                    component: VnConfirm,
-                    componentProps: {
-                        'data-cy': 'entry-lock-confirm',
-                        title: t('entry.lock.title'),
-                        message: t('entry.lock.message', {
-                            userName: data?.user?.nickname,
-                            time: timeDiff / 60,
-                        }),
-                    },
-                })
-                .onOk(
-                    async () =>
-                        await axios.patch(`Entries/${entryFk}`, {
-                            locked: Date.vnNow(),
-                            lockerUserFk: userFk,
-                        }),
-                )
-                .onCancel(() => {
-                    push({ path: `summary` });
-                });
-        }
-    } else {
-        await axios
-            .patch(`Entries/${entryFk}`, {
-                locked: Date.vnNow(),
-                lockerUserFk: userFk,
-            })
-            .then(
-                quasar.notify({
-                    message: t('entry.lock.success'),
-                    color: 'positive',
-                    group: false,
-                }),
-            );
-    }
-}
diff --git a/src/composables/getColAlign.js b/src/composables/getColAlign.js
deleted file mode 100644
index a930fd7d8..000000000
--- a/src/composables/getColAlign.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export function getColAlign(col) {
-    let align;
-    switch (col.component) {
-        case 'time':
-        case 'date':
-        case 'select':
-            align = 'left';
-            break;
-        case 'number':
-            align = 'right';
-            break;
-        case 'checkbox':
-            align = 'center';
-            break;
-        default:
-            align = col?.align;
-    }
-
-    if (/^is[A-Z]/.test(col.name) || /^has[A-Z]/.test(col.name)) align = 'center';
-
-    return 'text-' + (align ?? 'center');
-}
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index fcc61972a..bd3cecf08 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -57,7 +57,6 @@ export function useArrayData(key, userOptions) {
             'navigate',
             'mapKey',
             'keepData',
-            'oneRecord',
         ];
         if (typeof userOptions === 'object') {
             for (const option in userOptions) {
@@ -113,11 +112,7 @@ export function useArrayData(key, userOptions) {
         store.isLoading = false;
         canceller = null;
 
-        processData(response.data, {
-            map: !!store.mapKey,
-            append,
-            oneRecord: store.oneRecord,
-        });
+        processData(response.data, { map: !!store.mapKey, append });
 
         return response;
     }
@@ -319,11 +314,7 @@ export function useArrayData(key, userOptions) {
         return { params, limit };
     }
 
-    function processData(data, { map = true, append = true, oneRecord = false }) {
-        if (oneRecord) {
-            store.data = Array.isArray(data) ? data[0] : data;
-            return;
-        }
+    function processData(data, { map = true, append = true }) {
         if (!append) {
             store.data = [];
             store.map = new Map();
diff --git a/src/composables/useRole.js b/src/composables/useRole.js
index ff54b409c..3ec65dd0a 100644
--- a/src/composables/useRole.js
+++ b/src/composables/useRole.js
@@ -27,15 +27,6 @@ export function useRole() {
 
         return false;
     }
-    function likeAny(roles) {
-        const roleStore = state.getRoles();
-        for (const role of roles) {
-            if (!roleStore.value.findIndex((rs) => rs.startsWith(role)) !== -1)
-                return true;
-        }
-
-        return false;
-    }
     function isEmployee() {
         return hasAny(['employee']);
     }
@@ -44,7 +35,6 @@ export function useRole() {
         isEmployee,
         fetch,
         hasAny,
-        likeAny,
         state,
     };
 }
diff --git a/src/css/app.scss b/src/css/app.scss
index 0c5dc97fa..7296b079f 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -21,10 +21,7 @@ body.body--light {
     .q-header .q-toolbar {
         color: var(--vn-text-color);
     }
-
-    --vn-color-negative: $negative;
 }
-
 body.body--dark {
     --vn-header-color: #5d5d5d;
     --vn-page-color: #222;
@@ -40,8 +37,6 @@ body.body--dark {
     --vn-text-color-contrast: black;
 
     background-color: var(--vn-page-color);
-
-    --vn-color-negative: $negative;
 }
 
 a {
@@ -80,6 +75,7 @@ a {
     text-decoration: underline;
 }
 
+// Removes chrome autofill background
 input:-webkit-autofill,
 select:-webkit-autofill {
     color: var(--vn-text-color);
@@ -153,6 +149,11 @@ select:-webkit-autofill {
     cursor: pointer;
 }
 
+.vn-table-separation-row {
+    height: 16px !important;
+    background-color: var(--vn-section-color) !important;
+}
+
 /* Estilo para el asterisco en campos requeridos */
 .q-field.required .q-field__label:after {
     content: ' *';
@@ -211,10 +212,6 @@ select:-webkit-autofill {
     justify-content: center;
 }
 
-.q-card__section[dense] {
-    padding: 0;
-}
-
 input[type='number'] {
     -moz-appearance: textfield;
 }
@@ -229,12 +226,10 @@ input::-webkit-inner-spin-button {
     max-width: 100%;
 }
 
-.remove-bg {
-    filter: brightness(1.1);
-    mix-blend-mode: multiply;
-}
-
 .q-table__container {
+    /* ===== Scrollbar CSS ===== /
+    / Firefox */
+
     * {
         scrollbar-width: auto;
         scrollbar-color: var(--vn-label-color) transparent;
@@ -275,6 +270,8 @@ input::-webkit-inner-spin-button {
             font-size: 11pt;
         }
         td {
+            font-size: 11pt;
+            border-top: 1px solid var(--vn-page-color);
             border-collapse: collapse;
         }
     }
@@ -318,6 +315,9 @@ input::-webkit-inner-spin-button {
     max-width: fit-content;
 }
 
+.row > .column:has(.q-checkbox) {
+    max-width: fit-content;
+}
 .q-field__inner {
     .q-field__control {
         min-height: auto !important;
diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss
index 22c6d2b56..d6e992437 100644
--- a/src/css/quasar.variables.scss
+++ b/src/css/quasar.variables.scss
@@ -13,7 +13,7 @@
 // Tip: Use the "Theme Builder" on Quasar's documentation website.
 // Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors
 $primary: #ec8916;
-$secondary: #89be34;
+$secondary: $primary;
 $positive: #c8e484;
 $negative: #fb5252;
 $info: #84d0e2;
@@ -30,9 +30,7 @@ $color-spacer: #7979794d;
 $border-thin-light: 1px solid $color-spacer-light;
 $primary-light: #f5b351;
 $dark-shadow-color: black;
-$layout-shadow-dark:
-    0 0 10px 2px #00000033,
-    0 0px 10px #0000003d;
+$layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d;
 $spacing-md: 16px;
 $color-font-secondary: #777;
 $width-xs: 400px;
diff --git a/src/filters/toDate.js b/src/filters/toDate.js
index 002797af5..8fe8f3836 100644
--- a/src/filters/toDate.js
+++ b/src/filters/toDate.js
@@ -3,8 +3,6 @@ import { useI18n } from 'vue-i18n';
 export default function (value, options = {}) {
     if (!value) return;
 
-    if (!isValidDate(value)) return null;
-
     if (!options.dateStyle && !options.timeStyle) {
         options.day = '2-digit';
         options.month = '2-digit';
@@ -12,12 +10,7 @@ export default function (value, options = {}) {
     }
 
     const { locale } = useI18n();
-    const newDate = new Date(value);
+    const date = new Date(value);
 
-    return new Intl.DateTimeFormat(locale.value, options).format(newDate);
-}
-// handle 0000-00-00
-function isValidDate(date) {
-    const parsedDate = new Date(date);
-    return parsedDate instanceof Date && !isNaN(parsedDate.getTime());
+    return new Intl.DateTimeFormat(locale.value, options).format(date);
 }
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 9a60e9da1..7d0f3e0b2 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -33,7 +33,6 @@ globals:
     reset: Reset
     close: Close
     cancel: Cancel
-    isSaveAndContinue: Save and continue
     clone: Clone
     confirm: Confirm
     assign: Assign
@@ -157,7 +156,6 @@ globals:
     changeState: Change state
     raid: 'Raid {daysInForward} days'
     isVies: Vies
-    noData: No data available
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -170,7 +168,6 @@ globals:
         workCenters: Work centers
         modes: Modes
         zones: Zones
-        negative: Negative
         zonesList: List
         deliveryDays: Delivery days
         upcomingDeliveries: Upcoming deliveries
@@ -178,7 +175,6 @@ globals:
         alias: Alias
         aliasUsers: Users
         subRoles: Subroles
-        myAccount: Mi cuenta
         inheritedRoles: Inherited Roles
         customers: Customers
         customerCreate: New customer
@@ -337,13 +333,10 @@ globals:
         wasteRecalc: Waste recaclulate
         operator: Operator
         parking: Parking
-        vehicleList: Vehicles
-        vehicle: Vehicle
     unsavedPopup:
         title: Unsaved changes will be lost
         subtitle: Are you sure exit without saving?
     params:
-        description: Description
         clientFk: Client id
         salesPersonFk: Sales person
         warehouseFk: Warehouse
@@ -366,13 +359,7 @@ globals:
         correctingFk: Rectificative
         daysOnward: Days onward
         countryFk: Country
-        countryCodeFk: Country
         companyFk: Company
-    model: Model
-    fuel: Fuel
-    active: Active
-    inactive: Inactive
-    deliveryPoint: Delivery point
 errors:
     statusUnauthorized: Access denied
     statusInternalServerError: An internal server error has ocurred
@@ -411,106 +398,6 @@ cau:
     subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
     inputLabel: Explain why this error should not appear
     askPrivileges: Ask for privileges
-entry:
-    list:
-        newEntry: New entry
-        tableVisibleColumns:
-            isExcludedFromAvailable: Exclude from inventory
-            isOrdered: Ordered
-            isConfirmed: Ready to label
-            isReceived: Received
-            isRaid: Raid
-            landed: Date
-            supplierFk: Supplier
-            reference: Ref/Alb/Guide
-            invoiceNumber: Invoice
-            agencyModeId: Agency
-            isBooked: Booked
-            companyFk: Company
-            evaNotes: Notes
-            warehouseOutFk: Origin
-            warehouseInFk: Destiny
-            entryTypeDescription: Entry type
-            invoiceAmount: Import
-            travelFk: Travel
-    summary:
-        invoiceAmount: Amount
-        commission: Commission
-        currency: Currency
-        invoiceNumber: Invoice number
-        ordered: Ordered
-        booked: Booked
-        excludedFromAvailable: Inventory
-        travelReference: Reference
-        travelAgency: Agency
-        travelShipped: Shipped
-        travelDelivered: Delivered
-        travelLanded: Landed
-        travelReceived: Received
-        buys: Buys
-        stickers: Stickers
-        package: Package
-        packing: Pack.
-        grouping: Group.
-        buyingValue: Buying value
-        import: Import
-        pvp: PVP
-    basicData:
-        travel: Travel
-        currency: Currency
-        commission: Commission
-        observation: Observation
-        booked: Booked
-        excludedFromAvailable: Inventory
-    buys:
-        observations: Observations
-        packagingFk: Box
-        color: Color
-        printedStickers: Printed stickers
-    notes:
-        observationType: Observation type
-    latestBuys:
-        tableVisibleColumns:
-            image: Picture
-            itemFk: Item ID
-            weightByPiece: Weight/Piece
-            isActive: Active
-            family: Family
-            entryFk: Entry
-            freightValue: Freight value
-            comissionValue: Commission value
-            packageValue: Package value
-            isIgnored: Is ignored
-            price2: Grouping
-            price3: Packing
-            minPrice: Min
-            ektFk: Ekt
-            packingOut: Package out
-            landing: Landing
-            isExcludedFromAvailable: Exclude from inventory
-            isRaid: Raid
-            invoiceNumber: Invoice
-            reference: Ref/Alb/Guide
-    params:
-        isExcludedFromAvailable: Excluir del inventario
-        isOrdered: Pedida
-        isConfirmed: Lista para etiquetar
-        isReceived: Recibida
-        isRaid: Redada
-        landed: Fecha
-        supplierFk: Proveedor
-        invoiceNumber: Nº Factura
-        reference: Ref/Alb/Guía
-        agencyModeId: Agencia
-        isBooked: Asentado
-        companyFk: Empresa
-        travelFk: Envio
-        evaNotes: Notas
-        warehouseOutFk: Origen
-        warehouseInFk: Destino
-        entryTypeDescription: Tipo entrada
-        invoiceAmount: Importe
-        dated: Fecha
 ticket:
     params:
         ticketFk: Ticket ID
@@ -740,8 +627,6 @@ wagon:
         name: Name
 
 supplier:
-    search: Search supplier
-    searchInfo: Search supplier by id or name
     list:
         payMethod: Pay method
         account: Account
@@ -831,8 +716,6 @@ travel:
         CloneTravelAndEntries: Clone travel and his entries
         deleteTravel: Delete travel
         AddEntry: Add entry
-        availabled: Availabled
-        availabledHour: Availabled hour
         thermographs: Thermographs
         hb: HB
     basicData:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 846c442ea..7ca9e4b4c 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -33,11 +33,9 @@ globals:
     reset: Restaurar
     close: Cerrar
     cancel: Cancelar
-    isSaveAndContinue: Guardar y continuar
     clone: Clonar
     confirm: Confirmar
     assign: Asignar
-    replace: Sustituir
     back: Volver
     yes: Si
     no: No
@@ -50,7 +48,6 @@ globals:
     rowRemoved: Fila eliminada
     pleaseWait: Por favor espera...
     noPinnedModules: No has fijado ningún módulo
-    split: Split
     enterToConfirm: Pulsa Enter para confirmar
     summary:
         basicData: Datos básicos
@@ -59,8 +56,8 @@ globals:
     today: Hoy
     yesterday: Ayer
     dateFormat: es-ES
-    noSelectedRows: No tienes ninguna línea seleccionada
     microsip: Abrir en MicroSIP
+    noSelectedRows: No tienes ninguna línea seleccionada
     downloadCSVSuccess: Descarga de CSV exitosa
     reference: Referencia
     agency: Agencia
@@ -80,10 +77,8 @@ globals:
     requiredField: Campo obligatorio
     class: clase
     type: Tipo
-    reason: Motivo
-    removeSelection: Eliminar selección
+    reason: motivo
     noResults: Sin resultados
-    results: resultados
     system: Sistema
     notificationSent: Notificación enviada
     warehouse: Almacén
@@ -161,7 +156,6 @@ globals:
     changeState: Cambiar estado
     raid: 'Redada {daysInForward} días'
     isVies: Vies
-    noData: Datos no disponibles
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -173,7 +167,6 @@ globals:
         agency: Agencia
         workCenters: Centros de trabajo
         modes: Modos
-        negative: Tickets negativos
         zones: Zonas
         zonesList: Listado
         deliveryDays: Días de entrega
@@ -294,9 +287,9 @@ globals:
         buyRequest: Peticiones de compra
         wasteBreakdown: Deglose de mermas
         itemCreate: Nuevo artículo
-        tax: IVA
-        botanical: Botánico
-        barcode: Código de barras
+        tax: 'IVA'
+        botanical: 'Botánico'
+        barcode: 'Código de barras'
         itemTypeCreate: Nueva familia
         family: Familia
         lastEntries: Últimas entradas
@@ -340,13 +333,10 @@ globals:
         wasteRecalc: Recalcular mermas
         operator: Operario
         parking: Parking
-        vehicleList: Vehículos
-        vehicle: Vehículo
     unsavedPopup:
         title: Los cambios que no haya guardado se perderán
         subtitle: ¿Seguro que quiere salir sin guardar?
     params:
-        description: Descripción
         clientFk: Id cliente
         salesPersonFk: Comercial
         warehouseFk: Almacén
@@ -360,14 +350,13 @@ globals:
         from: Desde
         to: Hasta
         supplierFk: Proveedor
-        supplierRef: Nº factura
+        supplierRef: Ref. proveedor
         serial: Serie
         amount: Importe
         awbCode: AWB
         daysOnward: Días adelante
         packing: ITP
         countryFk: País
-        countryCodeFk: País
         companyFk: Empresa
 errors:
     statusUnauthorized: Acceso denegado
@@ -405,87 +394,6 @@ cau:
     subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
     inputLabel: Explique el motivo por el que no deberia aparecer este fallo
     askPrivileges: Solicitar permisos
-entry:
-    list:
-        newEntry: Nueva entrada
-        tableVisibleColumns:
-            isExcludedFromAvailable: Excluir del inventario
-            isOrdered: Pedida
-            isConfirmed: Lista para etiquetar
-            isReceived: Recibida
-            isRaid: Redada
-            landed: Fecha
-            supplierFk: Proveedor
-            invoiceNumber: Nº Factura
-            reference: Ref/Alb/Guía
-            agencyModeId: Agencia
-            isBooked: Asentado
-            companyFk: Empresa
-            travelFk: Envio
-            evaNotes: Notas
-            warehouseOutFk: Origen
-            warehouseInFk: Destino
-            entryTypeDescription: Tipo entrada
-            invoiceAmount: Importe
-    summary:
-        invoiceAmount: Importe
-        commission: Comisión
-        currency: Moneda
-        invoiceNumber: Núm. factura
-        ordered: Pedida
-        booked: Contabilizada
-        excludedFromAvailable: Inventario
-        travelReference: Referencia
-        travelAgency: Agencia
-        travelShipped: F. envio
-        travelWarehouseOut: Alm. salida
-        travelDelivered: Enviada
-        travelLanded: F. entrega
-        travelReceived: Recibida
-        buys: Compras
-        stickers: Etiquetas
-        package: Embalaje
-        packing: Pack.
-        grouping: Group.
-        buyingValue: Coste
-        import: Importe
-        pvp: PVP
-    basicData:
-        travel: Envío
-        currency: Moneda
-        observation: Observación
-        commission: Comisión
-        booked: Asentado
-        excludedFromAvailable: Inventario
-    buys:
-        observations: Observaciónes
-        packagingFk: Embalaje
-        color: Color
-        printedStickers: Etiquetas impresas
-    notes:
-        observationType: Tipo de observación
-    latestBuys:
-        tableVisibleColumns:
-            image: Foto
-            itemFk: Id Artículo
-            weightByPiece: Peso (gramos)/tallo
-            isActive: Activo
-            family: Familia
-            entryFk: Entrada
-            freightValue: Porte
-            comissionValue: Comisión
-            packageValue: Embalaje
-            isIgnored: Ignorado
-            price2: Grouping
-            price3: Packing
-            minPrice: Min
-            ektFk: Ekt
-            packingOut: Embalaje envíos
-            landing: Llegada
-            isExcludedFromAvailable: Excluir del inventario
-            isRaid: Redada
-            invoiceNumber: Nº Factura
-            reference: Ref/Alb/Guía
 ticket:
     params:
         ticketFk: ID de ticket
@@ -499,38 +407,6 @@ ticket:
         freightItemName: Nombre
         packageItemName: Embalaje
         longName: Descripción
-    pageTitles:
-        tickets: Tickets
-        list: Listado
-        ticketCreate: Nuevo ticket
-        summary: Resumen
-        basicData: Datos básicos
-        boxing: Encajado
-        sms: Sms
-        notes: Notas
-        sale: Lineas del pedido
-        dms: Gestión documental
-        negative: Tickets negativos
-        volume: Volumen
-        observation: Notas
-        ticketAdvance: Adelantar tickets
-        futureTickets: Tickets a futuro
-        expedition: Expedición
-        purchaseRequest: Petición de compra
-        weeklyTickets: Tickets programados
-        saleTracking: Líneas preparadas
-        services: Servicios
-        tracking: Estados
-        components: Componentes
-        pictures: Fotos
-        packages: Bultos
-    list:
-        nickname: Alias
-        state: Estado
-        shipped: Enviado
-        landed: Entregado
-        salesPerson: Comercial
-        total: Total
     card:
         customerId: ID cliente
         customerCard: Ficha del cliente
@@ -577,48 +453,6 @@ ticket:
         consigneeStreet: Dirección
     create:
         address: Dirección
-invoiceOut:
-    card:
-        issued: Fecha emisión
-        customerCard: Ficha del cliente
-        ticketList: Listado de tickets
-    summary:
-        issued: Fecha
-        dued: Fecha límite
-        booked: Contabilizada
-        taxBreakdown: Desglose impositivo
-        taxableBase: Base imp.
-        rate: Tarifa
-        fee: Cuota
-        tickets: Tickets
-        totalWithVat: Importe
-    globalInvoices:
-        errors:
-            chooseValidClient: Selecciona un cliente válido
-            chooseValidCompany: Selecciona una empresa válida
-            chooseValidPrinter: Selecciona una impresora válida
-            chooseValidSerialType: Selecciona una tipo de serie válida
-            fillDates: La fecha de la factura y la fecha máxima deben estar completas
-            invoiceDateLessThanMaxDate: La fecha de la factura no puede ser menor que la fecha máxima
-            invoiceWithFutureDate: Existe una factura con una fecha futura
-            noTicketsToInvoice: No existen tickets para facturar
-            criticalInvoiceError: Error crítico en la facturación proceso detenido
-            invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
-        table:
-            addressId: Id dirección
-            streetAddress: Dirección fiscal
-        statusCard:
-            percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
-            pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
-    negativeBases:
-        clientId: Id cliente
-        base: Base
-        active: Activo
-        hasToInvoice: Facturar
-        verifiedData: Datos comprobados
-        comercial: Comercial
-        errors:
-            downloadCsvFailed: Error al descargar CSV
 order:
     field:
         salesPersonFk: Comercial
@@ -629,34 +463,15 @@ order:
     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
-        priority: Prioridad
-        newShelving: Nuevo Carro
-    summary:
-        recyclable: Reciclable
-parking:
-    pickingOrder: Orden de recogida
-    row: Fila
-    column: Columna
-    searchBar:
-        info: Puedes buscar por código de parking
-        label: Buscar parking...
+        issued: Fecha
+        dued: Fecha límite
+        booked: Contabilizada
+        taxBreakdown: Desglose impositivo
+        taxableBase: Base imp.
+        rate: Tarifa
+        fee: Cuota
+        tickets: Tickets
+        totalWithVat: Importe
 department:
     chat: Chat
     bossDepartment: Jefe de departamento
@@ -817,8 +632,8 @@ wagon:
         volumeNotEmpty: El volumen no puede estar vacío
         typeNotEmpty: El tipo no puede estar vacío
         maxTrays: Has alcanzado el número máximo de bandejas
-        minHeightBetweenTrays: La distancia mínima entre bandejas es
-        maxWagonHeight: La altura máxima del vagón es
+        minHeightBetweenTrays: 'La distancia mínima entre bandejas es '
+        maxWagonHeight: 'La altura máxima del vagón es '
         uncompleteTrays: Hay bandejas sin completar
     params:
         label: Etiqueta
@@ -826,8 +641,6 @@ wagon:
         volume: Volumen
         name: Nombre
 supplier:
-    search: Buscar proveedor
-    searchInfo: Buscar proveedor por id o nombre
     list:
         payMethod: Método de pago
         account: Cuenta
@@ -918,8 +731,6 @@ travel:
         deleteTravel: Eliminar envío
         AddEntry: Añadir entrada
         thermographs: Termógrafos
-        availabled: F. Disponible
-        availabledHour: Hora Disponible
         hb: HB
     basicData:
         daysInForward: Desplazamiento automatico (redada)
@@ -968,7 +779,7 @@ components:
     cardDescriptor:
         mainList: Listado principal
         summary: Resumen
-        moreOptions: Más opciones
+        moreOptions: 'Más opciones'
     leftMenu:
         addToPinned: Añadir a fijados
         removeFromPinned: Eliminar de fijados
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 3ad1c79bc..2a84e5aa1 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -2,7 +2,7 @@
 import Navbar from 'src/components/NavBar.vue';
 </script>
 <template>
-    <QLayout view="hHh LpR fFf">
+    <QLayout view="hHh LpR fFf" v-shortcut>
         <Navbar />
         <RouterView></RouterView>
         <QFooter v-if="$q.platform.is.mobile"></QFooter>
diff --git a/src/layouts/OutLayout.vue b/src/layouts/OutLayout.vue
index eba57c198..4ccc6bf9e 100644
--- a/src/layouts/OutLayout.vue
+++ b/src/layouts/OutLayout.vue
@@ -1,12 +1,12 @@
 <script setup>
 import { Dark, Quasar } from 'quasar';
-import { computed, onMounted } from 'vue';
+import { computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { localeEquivalence } from 'src/i18n/index';
 import quasarLang from 'src/utils/quasarLang';
-import { langs } from 'src/boot/defaults/constants.js';
 
 const { t, locale } = useI18n();
+
 const userLocale = computed({
     get() {
         return locale.value;
@@ -28,6 +28,7 @@ const darkMode = computed({
         Dark.set(value);
     },
 });
+const langs = ['en', 'es'];
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountAliasList.vue b/src/pages/Account/AccountAliasList.vue
index 19682286c..f6016fb6c 100644
--- a/src/pages/Account/AccountAliasList.vue
+++ b/src/pages/Account/AccountAliasList.vue
@@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n';
 import { ref, computed } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnSection from 'src/components/common/VnSection.vue';
-import exprBuilder from './Alias/AliasExprBuilder';
 
 const tableRef = ref();
 const { t } = useI18n();
@@ -32,6 +31,15 @@ const columns = computed(() => [
         create: true,
     },
 ]);
+
+const exprBuilder = (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : { alias: { like: `%${value}%` } };
+    }
+};
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountExprBuilder.js b/src/pages/Account/AccountExprBuilder.js
deleted file mode 100644
index 6497a9d30..000000000
--- a/src/pages/Account/AccountExprBuilder.js
+++ /dev/null
@@ -1,18 +0,0 @@
-export default (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'nickname':
-            return { [param]: { like: `%${value}%` } };
-        case 'roleFk':
-            return { [param]: value };
-    }
-};
diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue
index 976af1d19..ea8daba0d 100644
--- a/src/pages/Account/AccountList.vue
+++ b/src/pages/Account/AccountList.vue
@@ -4,16 +4,15 @@ import { computed, ref } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import AccountSummary from './Card/AccountSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import exprBuilder from './AccountExprBuilder.js';
-import filter from './Card/AccountFilter.js';
 import VnSection from 'src/components/common/VnSection.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
-const tableRef = ref();
-
+const filter = {
+    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
+};
 const dataKey = 'AccountList';
 const roles = ref([]);
 const columns = computed(() => [
@@ -118,6 +117,25 @@ const columns = computed(() => [
         ],
     },
 ]);
+
+function exprBuilder(param, value) {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'nickname':
+            return { [param]: { like: `%${value}%` } };
+        case 'roleFk':
+            return { [param]: value };
+    }
+}
 </script>
 <template>
     <FetchData url="VnRoles" @on-fetch="(data) => (roles = data)" auto-load />
diff --git a/src/pages/Account/Alias/AliasExprBuilder.js b/src/pages/Account/Alias/AliasExprBuilder.js
deleted file mode 100644
index f7a5a104c..000000000
--- a/src/pages/Account/Alias/AliasExprBuilder.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : { alias: { like: `%${value}%` } };
-    }
-};
diff --git a/src/pages/Account/Alias/Card/AliasCard.vue b/src/pages/Account/Alias/Card/AliasCard.vue
index f37bd7d0f..3a814edc0 100644
--- a/src/pages/Account/Alias/Card/AliasCard.vue
+++ b/src/pages/Account/Alias/Card/AliasCard.vue
@@ -1,13 +1,21 @@
 <script setup>
+import { useI18n } from 'vue-i18n';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AliasDescriptor from './AliasDescriptor.vue';
+const { t } = useI18n();
 </script>
 
 <template>
     <VnCardBeta
         data-key="Alias"
-        url="MailAliases"
+        base-url="MailAliases"
         :descriptor="AliasDescriptor"
         search-data-key="AccountAliasList"
+        :searchbar-props="{
+            url: 'MailAliases',
+            info: t('mailAlias.searchInfo'),
+            label: t('mailAlias.search'),
+            searchUrl: 'table',
+        }"
     />
 </template>
diff --git a/src/pages/Account/Alias/Card/AliasDescriptor.vue b/src/pages/Account/Alias/Card/AliasDescriptor.vue
index 671ef7fbc..2e01fad01 100644
--- a/src/pages/Account/Alias/Card/AliasDescriptor.vue
+++ b/src/pages/Account/Alias/Card/AliasDescriptor.vue
@@ -7,6 +7,7 @@ import { useQuasar } from 'quasar';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
+import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 
@@ -28,6 +29,9 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.alias, entity.id));
+
 const removeAlias = () => {
     quasar
         .dialog({
@@ -51,8 +55,11 @@ const removeAlias = () => {
     <CardDescriptor
         ref="descriptor"
         :url="`MailAliases/${entityId}`"
-        data-key="Alias"
-        title="alias"
+        module="Alias"
+        @on-fetch="setData"
+        data-key="aliasData"
+        :title="data.title"
+        :subtitle="data.subtitle"
     >
         <template #menu>
             <QItem v-ripple clickable @click="removeAlias()">
diff --git a/src/pages/Account/Alias/Card/AliasSummary.vue b/src/pages/Account/Alias/Card/AliasSummary.vue
index b4b9abd25..1f76fe7c2 100644
--- a/src/pages/Account/Alias/Card/AliasSummary.vue
+++ b/src/pages/Account/Alias/Card/AliasSummary.vue
@@ -1,11 +1,13 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
+import { useArrayData } from 'src/composables/useArrayData';
+
 const route = useRoute();
 const { t } = useI18n();
 
@@ -16,15 +18,20 @@ const $props = defineProps({
     },
 });
 
+const { store } = useArrayData('Alias');
+const alias = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
 </script>
 
 <template>
-    <CardSummary ref="summary" :url="`MailAliases/${entityId}`" data-key="Alias">
-        <template #header="{ entity: alias }">
-            {{ alias.id }} - {{ alias.alias }}
-        </template>
-        <template #body="{ entity: alias }">
+    <CardSummary
+        ref="summary"
+        :url="`MailAliases/${entityId}`"
+        @on-fetch="(data) => (alias = data)"
+        data-key="MailAliasesSummary"
+    >
+        <template #header> {{ alias.id }} - {{ alias.alias }} </template>
+        <template #body>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
diff --git a/src/pages/Account/Card/AccountBasicData.vue b/src/pages/Account/Card/AccountBasicData.vue
index 393f9eb80..e6c9da6fe 100644
--- a/src/pages/Account/Card/AccountBasicData.vue
+++ b/src/pages/Account/Card/AccountBasicData.vue
@@ -1,20 +1,46 @@
 <script setup>
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
 import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+import { ref, watch } from 'vue';
+
+const route = useRoute();
+const { t } = useI18n();
+const formModelRef = ref(null);
+
+const accountFilter = {
+    where: { id: route.params.id },
+    fields: ['id', 'email', 'nickname', 'name', 'accountStateFk', 'packages', 'pickup'],
+    include: [],
+};
+
+watch(
+    () => route.params.id,
+    () => formModelRef.value.reset()
+);
 </script>
 <template>
-    <FormModel :url-update="`VnUsers/${$route.params.id}/update-user`" model="Account">
+    <FormModel
+        ref="formModelRef"
+        url="VnUsers/preview"
+        :url-update="`VnUsers/${route.params.id}/update-user`"
+        :filter="accountFilter"
+        model="Accounts"
+        auto-load
+        @on-data-saved="formModelRef.fetch()"
+    >
         <template #form="{ data }">
             <div class="q-gutter-y-sm">
-                <VnInput v-model="data.name" :label="$t('account.card.nickname')" />
-                <VnInput v-model="data.nickname" :label="$t('account.card.alias')" />
-                <VnInput v-model="data.email" :label="$t('globals.params.email')" />
+                <VnInput v-model="data.name" :label="t('account.card.nickname')" />
+                <VnInput v-model="data.nickname" :label="t('account.card.alias')" />
+                <VnInput v-model="data.email" :label="t('globals.params.email')" />
                 <VnSelect
                     url="Languages"
                     v-model="data.lang"
-                    :label="$t('account.card.lang')"
+                    :label="t('account.card.lang')"
                     option-value="code"
                     option-label="code"
                 />
@@ -23,7 +49,7 @@ import VnInput from 'src/components/common/VnInput.vue';
                     table="user"
                     column="twoFactor"
                     v-model="data.twoFactor"
-                    :label="$t('account.card.twoFactor')"
+                    :label="t('account.card.twoFactor')"
                     option-value="code"
                     option-label="code"
                 />
diff --git a/src/pages/Account/Card/AccountCard.vue b/src/pages/Account/Card/AccountCard.vue
index a5037e301..35ff7e732 100644
--- a/src/pages/Account/Card/AccountCard.vue
+++ b/src/pages/Account/Card/AccountCard.vue
@@ -1,14 +1,8 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AccountDescriptor from './AccountDescriptor.vue';
-import filter from './AccountFilter.js';
 </script>
+
 <template>
-    <VnCardBeta
-        url="VnUsers/preview"
-        :id-in-where="true"
-        data-key="Account"
-        :descriptor="AccountDescriptor"
-        :filter="filter"
-    />
+    <VnCardBeta data-key="AccountId" :descriptor="AccountDescriptor" />
 </template>
diff --git a/src/pages/Account/Card/AccountDescriptor.vue b/src/pages/Account/Card/AccountDescriptor.vue
index 49328fe87..4e5328de6 100644
--- a/src/pages/Account/Card/AccountDescriptor.vue
+++ b/src/pages/Account/Card/AccountDescriptor.vue
@@ -1,18 +1,36 @@
 <script setup>
 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 VnImg from 'src/components/ui/VnImg.vue';
-import filter from './AccountFilter.js';
 import useHasAccount from 'src/composables/useHasAccount.js';
 
-const $props = defineProps({ id: { type: Number, default: null } });
+const $props = defineProps({
+    id: {
+        type: Number,
+        required: false,
+        default: null,
+    },
+});
 
 const route = useRoute();
-const entityId = computed(() => $props.id || route.params.id);
+const { t } = useI18n();
+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 = {
+    where: { id: entityId },
+    fields: ['id', 'nickname', 'name', 'role'],
+    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
+};
 
 onMounted(async () => {
     hasAccount.value = await useHasAccount(entityId.value);
@@ -23,9 +41,12 @@ onMounted(async () => {
     <CardDescriptor
         ref="descriptor"
         :url="`VnUsers/preview`"
-        :filter="{ ...filter, where: { id: entityId } }"
-        data-key="Account"
-        title="nickname"
+        :filter="filter"
+        module="Account"
+        @on-fetch="setData"
+        data-key="AccountId"
+        :title="data.title"
+        :subtitle="data.subtitle"
     >
         <template #menu>
             <AccountDescriptorMenu :entity-id="entityId" />
@@ -41,7 +62,7 @@ onMounted(async () => {
                                 <QIcon name="vn:claims" />
                             </div>
                             <div class="text-grey-5" style="opacity: 0.4">
-                                {{ $t('account.imageNotFound') }}
+                                {{ t('account.imageNotFound') }}
                             </div>
                         </div>
                     </div>
@@ -49,8 +70,8 @@ onMounted(async () => {
             </VnImg>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
-            <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
+            <VnLv :label="t('account.card.nickname')" :value="entity.name" />
+            <VnLv :label="t('account.card.role')" :value="entity.role.name" />
         </template>
         <template #actions="{ entity }">
             <QCardActions class="q-gutter-x-md">
@@ -63,7 +84,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ $t('account.card.deactivated') }}</QTooltip>
+                    <QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
                 </QIcon>
                 <QIcon
                     color="primary"
@@ -74,7 +95,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ $t('account.card.enabled') }}</QTooltip>
+                    <QTooltip>{{ t('account.card.enabled') }}</QTooltip>
                 </QIcon>
             </QCardActions>
         </template>
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 30584c61f..961323d3a 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -12,7 +12,6 @@ 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';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     hasAccount: {
@@ -30,7 +29,7 @@ const router = useRouter();
 const state = useState();
 const user = state.getUser();
 const { notify } = useQuasar();
-const account = computed(() => useArrayData('Account').store.data[0]);
+const account = computed(() => useArrayData('AccountId').store.data[0]);
 account.value.hasAccount = hasAccount.value;
 const entityId = computed(() => +route.params.id);
 const hasitManagementAccess = ref();
@@ -125,14 +124,18 @@ onMounted(() => {
         :promise="sync"
     >
         <template #customHTML>
-            <VnCheckbox
-                v-model="shouldSyncPassword"
+            {{ shouldSyncPassword }}
+            <QCheckbox
                 :label="t('account.card.actions.sync.checkbox')"
-                :info="t('account.card.actions.sync.tooltip')"
+                v-model="shouldSyncPassword"
+                class="full-width"
                 clearable
                 clear-icon="close"
-                color="primary"
-            />
+            >
+                <QIcon style="padding-left: 10px" color="primary" name="info" size="sm">
+                    <QTooltip>{{ t('account.card.actions.sync.tooltip') }}</QTooltip>
+                </QIcon></QCheckbox
+            >
             <VnInputPassword
                 v-if="shouldSyncPassword"
                 :label="t('login.password')"
@@ -152,7 +155,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => deleteAccount(),
+                () => deleteAccount()
             )
         "
     >
@@ -171,7 +174,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.enableAccount.title'),
                 t('account.card.actions.enableAccount.subtitle'),
-                () => updateStatusAccount(true),
+                () => updateStatusAccount(true)
             )
         "
     >
@@ -185,7 +188,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => updateStatusAccount(false),
+                () => updateStatusAccount(false)
             )
         "
     >
@@ -200,7 +203,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.activateUser.title'),
                 t('account.card.actions.activateUser.title'),
-                () => updateStatusUser(true),
+                () => updateStatusUser(true)
             )
         "
     >
@@ -214,7 +217,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.deactivateUser.title'),
                 t('account.card.actions.deactivateUser.title'),
-                () => updateStatusUser(false),
+                () => updateStatusUser(false)
             )
         "
     >
diff --git a/src/pages/Account/Card/AccountFilter.js b/src/pages/Account/Card/AccountFilter.js
deleted file mode 100644
index 017876564..000000000
--- a/src/pages/Account/Card/AccountFilter.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default {
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
diff --git a/src/pages/Account/Card/AccountMailAlias.vue b/src/pages/Account/Card/AccountMailAlias.vue
index 7a060cff1..ef1707cf2 100644
--- a/src/pages/Account/Card/AccountMailAlias.vue
+++ b/src/pages/Account/Card/AccountMailAlias.vue
@@ -86,7 +86,7 @@ watch(
     () => route.params.id,
     () => {
         getAccountData();
-    },
+    }
 );
 
 onMounted(async () => await getAccountData(false));
@@ -130,8 +130,7 @@ onMounted(async () => await getAccountData(false));
                                             openConfirmationModal(
                                                 t('User will be removed from alias'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () =>
-                                                    deleteMailAlias(row, rows, rowIndex),
+                                                () => deleteMailAlias(row, rows, rowIndex)
                                             )
                                         "
                                     >
@@ -158,7 +157,7 @@ onMounted(async () => await getAccountData(false));
                 icon="add"
                 color="primary"
                 @click="openCreateMailAliasForm()"
-                v-shortcut="'+'"
+                shortcut="+"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Account/Card/AccountSummary.vue b/src/pages/Account/Card/AccountSummary.vue
index f7a16e8c3..ca17c7975 100644
--- a/src/pages/Account/Card/AccountSummary.vue
+++ b/src/pages/Account/Card/AccountSummary.vue
@@ -1,41 +1,58 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import filter from './AccountFilter.js';
+
+import { useArrayData } from 'src/composables/useArrayData';
 import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
 
-const $props = defineProps({ id: { type: Number, default: 0 } });
-
 const route = useRoute();
+const { t } = useI18n();
+
+const $props = defineProps({
+    id: {
+        type: Number,
+        default: 0,
+    },
+});
+const { store } = useArrayData('Account');
+const account = ref(store.data);
+
 const entityId = computed(() => $props.id || route.params.id);
+const filter = {
+    where: { id: entityId },
+    fields: ['id', 'nickname', 'name', 'role'],
+    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
+};
 </script>
 
 <template>
     <CardSummary
-        data-key="Account"
-        ref="AccountSummary"
+        data-key="AccountId"
         url="VnUsers/preview"
         :filter="filter"
+        @on-fetch="(data) => (account = data)"
     >
-        <template #header="{ entity }">{{ entity.id }} - {{ entity.nickname }}</template>
-        <template #menu>
+        <template #header>{{ account.id }} - {{ account.nickname }}</template>
+        <template #menu="">
             <AccountDescriptorMenu :entity-id="entityId" />
         </template>
-        <template #body="{ entity }">
+        <template #body>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
                         :to="{ name: 'AccountBasicData', params: { id: entityId } }"
                         class="header header-link"
                     >
-                        {{ $t('globals.pageTitles.basicData') }}
+                        {{ t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </router-link>
                 </QCardSection>
-                <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
-                <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
+                <VnLv :label="t('account.card.nickname')" :value="account.name" />
+                <VnLv :label="t('account.card.role')" :value="account.role.name" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/AccountRoles.vue b/src/pages/Account/Role/AccountRoles.vue
index 02f5400c6..3c3d6b243 100644
--- a/src/pages/Account/Role/AccountRoles.vue
+++ b/src/pages/Account/Role/AccountRoles.vue
@@ -5,7 +5,6 @@ import VnTable from 'components/VnTable/VnTable.vue';
 import { useRoute } from 'vue-router';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import RoleSummary from './Card/RoleSummary.vue';
-import exprBuilder from './RoleExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const route = useRoute();
@@ -67,7 +66,24 @@ const columns = computed(() => [
         ],
     },
 ]);
+const exprBuilder = (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'description':
+            return { [param]: { like: `%${value}%` } };
+    }
+};
 </script>
+
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Account/Role/Card/RoleBasicData.vue b/src/pages/Account/Role/Card/RoleBasicData.vue
index de70b0fb6..1de9ff387 100644
--- a/src/pages/Account/Role/Card/RoleBasicData.vue
+++ b/src/pages/Account/Role/Card/RoleBasicData.vue
@@ -1,16 +1,24 @@
 <script setup>
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+const route = useRoute();
+const { t } = useI18n();
 </script>
 <template>
-    <FormModel model="Role" auto-load>
+    <FormModel :url="`VnRoles/${route.params.id}`" model="VnRole" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <VnInput v-model="data.name" :label="$t('globals.name')" />
+                <div class="col">
+                    <VnInput v-model="data.name" :label="t('globals.name')" />
+                </div>
             </VnRow>
             <VnRow>
-                <VnInput v-model="data.description" :label="$t('role.description')" />
+                <div class="col">
+                    <VnInput v-model="data.description" :label="t('role.description')" />
+                </div>
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/Account/Role/Card/RoleCard.vue b/src/pages/Account/Role/Card/RoleCard.vue
index ef5b9db04..7664deca8 100644
--- a/src/pages/Account/Role/Card/RoleCard.vue
+++ b/src/pages/Account/Role/Card/RoleCard.vue
@@ -3,10 +3,5 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoleDescriptor from './RoleDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta
-        url="VnRoles"
-        data-key="Role"
-        :id-in-where="true"
-        :descriptor="RoleDescriptor"
-    />
+    <VnCardBeta data-key="Role" :descriptor="RoleDescriptor" />
 </template>
diff --git a/src/pages/Account/Role/Card/RoleDescriptor.vue b/src/pages/Account/Role/Card/RoleDescriptor.vue
index 517517af0..0a555346d 100644
--- a/src/pages/Account/Role/Card/RoleDescriptor.vue
+++ b/src/pages/Account/Role/Card/RoleDescriptor.vue
@@ -1,9 +1,10 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } 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 axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 const $props = defineProps({
@@ -25,6 +26,11 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.name, entity.id));
+const filter = {
+    where: { id: entityId },
+};
 const removeRole = async () => {
     await axios.delete(`VnRoles/${entityId.value}`);
     notify(t('Role removed'), 'positive');
@@ -33,9 +39,13 @@ const removeRole = async () => {
 
 <template>
     <CardDescriptor
-        url="VnRoles"
-        :filter="{ where: { id: entityId } }"
+        :url="`VnRoles/${entityId}`"
+        :filter="filter"
+        module="Role"
+        @on-fetch="setData"
         data-key="Role"
+        :title="data.title"
+        :subtitle="data.subtitle"
         :summary="$props.summary"
     >
         <template #menu>
diff --git a/src/pages/Account/Role/Card/RoleSummary.vue b/src/pages/Account/Role/Card/RoleSummary.vue
index 410f90b17..f0daa77fb 100644
--- a/src/pages/Account/Role/Card/RoleSummary.vue
+++ b/src/pages/Account/Role/Card/RoleSummary.vue
@@ -1,9 +1,10 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -15,18 +16,24 @@ const $props = defineProps({
     },
 });
 
+const { store } = useArrayData('Role');
+const role = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
+const filter = {
+    where: { id: entityId },
+};
 </script>
 
 <template>
     <CardSummary
         ref="summary"
-        url="VnRoles"
-        :filter="{ where: { id: entityId } }"
+        :url="`VnRoles/${entityId}`"
+        :filter="filter"
+        @on-fetch="(data) => (role = data)"
         data-key="Role"
     >
-        <template #header="{ entity }"> {{ entity.id }} - {{ entity.name }} </template>
-        <template #body="{ entity }">
+        <template #header> {{ role.id }} - {{ role.name }} </template>
+        <template #body>
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <a
@@ -37,9 +44,9 @@ const entityId = computed(() => $props.id || route.params.id);
                         <QIcon name="open_in_new" />
                     </a>
                 </QCardSection>
-                <VnLv :label="t('role.id')" :value="entity.id" />
-                <VnLv :label="t('globals.name')" :value="entity.name" />
-                <VnLv :label="t('role.description')" :value="entity.description" />
+                <VnLv :label="t('role.id')" :value="role.id" />
+                <VnLv :label="t('globals.name')" :value="role.name" />
+                <VnLv :label="t('role.description')" :value="role.description" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/Card/SubRoles.vue b/src/pages/Account/Role/Card/SubRoles.vue
index 99cf5e8f0..0077f12b0 100644
--- a/src/pages/Account/Role/Card/SubRoles.vue
+++ b/src/pages/Account/Role/Card/SubRoles.vue
@@ -63,7 +63,7 @@ watch(
         store.url = urlPath.value;
         store.filter = filter.value;
         fetchSubRoles();
-    },
+    }
 );
 
 const fetchSubRoles = () => paginateRef.value.fetch();
@@ -109,7 +109,7 @@ const redirectToRoleSummary = (id) =>
                                             openConfirmationModal(
                                                 t('El rol va a ser eliminado'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () => deleteSubRole(row, rows, rowIndex),
+                                                () => deleteSubRole(row, rows, rowIndex)
                                             )
                                         "
                                     >
@@ -131,7 +131,7 @@ const redirectToRoleSummary = (id) =>
             <QBtn
                 fab
                 icon="add"
-                v-shortcut="'+'"
+                shortcut="+"
                 color="primary"
                 @click="openCreateSubRoleForm()"
             >
diff --git a/src/pages/Account/Role/RoleExprBuilder.js b/src/pages/Account/Role/RoleExprBuilder.js
deleted file mode 100644
index cc4fab399..000000000
--- a/src/pages/Account/Role/RoleExprBuilder.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export default (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'description':
-            return { [param]: { like: `%${value}%` } };
-    }
-};
diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue
index 67034da1a..63b0b7c0d 100644
--- a/src/pages/Claim/Card/ClaimBasicData.vue
+++ b/src/pages/Claim/Card/ClaimBasicData.vue
@@ -28,6 +28,7 @@ const workersOptions = ref([]);
         model="Claim"
         :url-update="`Claims/updateClaim/${route.params.id}`"
         auto-load
+        :reload="true"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Claim/Card/ClaimCard.vue b/src/pages/Claim/Card/ClaimCard.vue
index 05f3b53a8..e1e000815 100644
--- a/src/pages/Claim/Card/ClaimCard.vue
+++ b/src/pages/Claim/Card/ClaimCard.vue
@@ -4,11 +4,10 @@ import ClaimDescriptor from './ClaimDescriptor.vue';
 import filter from './ClaimFilter.js';
 </script>
 <template>
-    <VnCardBeta
-        data-key="Claim"
-        url="Claims"
-        :descriptor="ClaimDescriptor"
-        search-data-key="ClaimList"
+    <VnCardBeta 
+        data-key="Claim" 
+        base-url="Claims" 
+        :descriptor="ClaimDescriptor" 
         :filter="filter"
     />
 </template>
diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue
index 4551c58fe..02b63dd8e 100644
--- a/src/pages/Claim/Card/ClaimDescriptor.vue
+++ b/src/pages/Claim/Card/ClaimDescriptor.vue
@@ -3,10 +3,12 @@ import { ref, computed, onMounted } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toDateHourMinSec, toPercentage } from 'src/filters';
+import { useState } from 'src/composables/useState';
 import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
 import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
+import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { getUrl } from 'src/composables/getUrl';
 import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
@@ -21,6 +23,7 @@ const $props = defineProps({
 });
 
 const route = useRoute();
+const state = useState();
 const { t } = useI18n();
 const salixUrl = ref();
 const entityId = computed(() => {
@@ -36,7 +39,12 @@ const STATE_COLOR = {
 function stateColor(code) {
     return STATE_COLOR[code];
 }
-
+const data = ref(useCardDescription());
+const setData = (entity) => {
+    if (!entity) return;
+    data.value = useCardDescription(entity?.client?.name, entity.id);
+    state.set('ClaimDescriptor', entity);
+};
 onMounted(async () => {
     salixUrl.value = await getUrl('');
 });
@@ -46,7 +54,9 @@ onMounted(async () => {
     <CardDescriptor
         :url="`Claims/${entityId}`"
         :filter="filter"
+        module="Claim"
         title="client.name"
+        @on-fetch="setData"
         data-key="Claim"
     >
         <template #menu="{ entity }">
@@ -85,7 +95,7 @@ onMounted(async () => {
                     />
                 </template>
             </VnLv>
-            <VnLv v-if="entity.ticket?.zone?.id" :label="t('claim.zone')">
+            <VnLv :label="t('claim.zone')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticket?.zone?.name }}
@@ -97,10 +107,11 @@ onMounted(async () => {
                 :label="t('claim.province')"
                 :value="entity.ticket?.address?.province?.name"
             />
-            <VnLv v-if="entity.ticketFk" :label="t('claim.ticketId')">
+            <VnLv :label="t('claim.ticketId')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticketFk }}
+
                         <TicketDescriptorProxy :id="entity.ticketFk" />
                     </span>
                 </template>
diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue
index dee03b95d..33fadd020 100644
--- a/src/pages/Claim/Card/ClaimLines.vue
+++ b/src/pages/Claim/Card/ClaimLines.vue
@@ -317,13 +317,7 @@ async function saveWhenHasChanges() {
     </div>
 
     <QPageSticky position="bottom-right" :offset="[25, 25]">
-        <QBtn
-            fab
-            color="primary"
-            v-shortcut="'+'"
-            icon="add"
-            @click="showImportDialog()"
-        />
+        <QBtn fab color="primary" shortcut="+" icon="add" @click="showImportDialog()" />
     </QPageSticky>
 </template>
 
diff --git a/src/pages/Claim/Card/ClaimNotes.vue b/src/pages/Claim/Card/ClaimNotes.vue
index cc6e33779..134ee33ab 100644
--- a/src/pages/Claim/Card/ClaimNotes.vue
+++ b/src/pages/Claim/Card/ClaimNotes.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed, useAttrs } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useState } from 'src/composables/useState';
 import VnNotes from 'src/components/ui/VnNotes.vue';
@@ -7,7 +7,6 @@ import VnNotes from 'src/components/ui/VnNotes.vue';
 const route = useRoute();
 const state = useState();
 const user = state.getUser();
-const $attrs = useAttrs();
 
 const $props = defineProps({
     id: { type: [Number, String], default: null },
diff --git a/src/pages/Claim/Card/ClaimPhoto.vue b/src/pages/Claim/Card/ClaimPhoto.vue
index d4acc9bbe..d4321d8eb 100644
--- a/src/pages/Claim/Card/ClaimPhoto.vue
+++ b/src/pages/Claim/Card/ClaimPhoto.vue
@@ -61,7 +61,7 @@ watch(
     () => {
         claimDmsFilter.value.where.id = router.currentRoute.value.params.id;
         claimDmsRef.value.fetch();
-    },
+    }
 );
 
 function openDialog(dmsId) {
@@ -248,7 +248,7 @@ function onDrag() {
             <QBtn
                 fab
                 @click="inputFile.nativeEl.click()"
-                v-shortcut="'+'"
+                shortcut="+"
                 icon="add"
                 color="primary"
             >
diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue
index 41d0c5598..63fd035da 100644
--- a/src/pages/Claim/ClaimList.vue
+++ b/src/pages/Claim/ClaimList.vue
@@ -132,7 +132,7 @@ const STATE_COLOR = {
         prefix="claim"
         :array-data-props="{
             url: 'Claims/filter',
-            order: 'cs.priority ASC, created ASC',
+            order: ['cs.priority ASC', 'created ASC'],
         }"
     >
         <template #advanced-menu>
diff --git a/src/pages/Customer/Card/CustomerAddress.vue b/src/pages/Customer/Card/CustomerAddress.vue
index f1799d0cc..1b0d1dde1 100644
--- a/src/pages/Customer/Card/CustomerAddress.vue
+++ b/src/pages/Customer/Card/CustomerAddress.vue
@@ -61,7 +61,7 @@ watch(
     (newValue) => {
         if (!newValue) return;
         getClientData(newValue);
-    },
+    }
 );
 
 const getClientData = async (id) => {
@@ -137,7 +137,7 @@ const toCustomerAddressEdit = (addressId) => {
                         <QIcon
                             :style="{
                                 'font-variation-settings': `'FILL' ${isDefaultAddress(
-                                    item,
+                                    item
                                 )}`,
                             }"
                             color="primary"
@@ -150,7 +150,7 @@ const toCustomerAddressEdit = (addressId) => {
                                     t(
                                         isDefaultAddress(item)
                                             ? 'Default address'
-                                            : 'Set as default',
+                                            : 'Set as default'
                                     )
                                 }}
                             </QTooltip>
@@ -216,7 +216,7 @@ const toCustomerAddressEdit = (addressId) => {
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip>
             {{ t('New consignee') }}
diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue
index 11db92eab..04ef5f882 100644
--- a/src/pages/Customer/Card/CustomerBalance.vue
+++ b/src/pages/Customer/Card/CustomerBalance.vue
@@ -158,7 +158,7 @@ const columns = computed(() => [
                     openConfirmationModal(
                         t('Send compensation'),
                         t('Do you want to report compensation to the client by mail?'),
-                        () => sendEmail(`Receipts/${id}/balance-compensation-email`),
+                        () => sendEmail(`Receipts/${id}/balance-compensation-email`)
                     ),
             },
         ],
@@ -291,7 +291,7 @@ const showBalancePdf = ({ id }) => {
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip>
             {{ t('New payment') }}
diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue
index 36ec4763e..e9a349e0b 100644
--- a/src/pages/Customer/Card/CustomerBasicData.vue
+++ b/src/pages/Customer/Card/CustomerBasicData.vue
@@ -54,10 +54,10 @@ function onBeforeSave(formData, originalData) {
         auto-load
     />
     <FormModel
-        :url-update="`Clients/${route.params.id}`"
+        :url="`Clients/${route.params.id}`"
         auto-load
+        model="customer"
         :mapper="onBeforeSave"
-        model="Customer"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Customer/Card/CustomerBillingData.vue b/src/pages/Customer/Card/CustomerBillingData.vue
index cc894d01e..f1e78d9e5 100644
--- a/src/pages/Customer/Card/CustomerBillingData.vue
+++ b/src/pages/Customer/Card/CustomerBillingData.vue
@@ -27,7 +27,7 @@ const getBankEntities = (data, formData) => {
 </script>
 
 <template>
-    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="Customer">
+    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="customer">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnSelect
diff --git a/src/pages/Customer/Card/CustomerCard.vue b/src/pages/Customer/Card/CustomerCard.vue
index 75fcb98fa..f46884834 100644
--- a/src/pages/Customer/Card/CustomerCard.vue
+++ b/src/pages/Customer/Card/CustomerCard.vue
@@ -5,8 +5,8 @@ import CustomerDescriptor from './CustomerDescriptor.vue';
 
 <template>
     <VnCardBeta
-        data-key="Customer"
-        :url="`Clients/${$route.params.id}/getCard`"
+        data-key="Client"
+        base-url="Clients"
         :descriptor="CustomerDescriptor"
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerConsumption.vue b/src/pages/Customer/Card/CustomerConsumption.vue
index f3949bb32..f0d8dea47 100644
--- a/src/pages/Customer/Card/CustomerConsumption.vue
+++ b/src/pages/Customer/Card/CustomerConsumption.vue
@@ -61,23 +61,6 @@ const columns = computed(() => [
         columnFilter: false,
         cardVisible: true,
     },
-    {
-        align: 'left',
-        name: 'buyerId',
-        label: t('customer.params.buyerId'),
-        component: 'select',
-        attrs: {
-            url: 'TicketRequests/getItemTypeWorker',
-            optionLabel: 'nickname',
-            optionValue: 'id',
-
-            fields: ['id', 'nickname'],
-            sortBy: ['nickname ASC'],
-            optionFilter: 'firstName',
-        },
-        cardVisible: false,
-        visible: false,
-    },
     {
         name: 'description',
         align: 'left',
@@ -91,7 +74,6 @@ const columns = computed(() => [
         name: 'quantity',
         label: t('globals.quantity'),
         cardVisible: true,
-        visible: true,
         columnFilter: {
             inWhere: true,
         },
@@ -137,7 +119,7 @@ const openSendEmailDialog = async () => {
     openConfirmationModal(
         t('The consumption report will be sent'),
         t('Please, confirm'),
-        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email }),
+        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email })
     );
 };
 const sendCampaignMetricsEmail = ({ address }) => {
@@ -156,11 +138,11 @@ const updateDateParams = (value, params) => {
     const campaign = campaignList.value.find((c) => c.id === value);
     if (!campaign) return;
 
-    const { dated, scopeDays } = campaign;
-    const from = new Date(dated);
-    from.setDate(from.getDate() - scopeDays);
-    params.from = from;
-    params.to = dated;
+    const { dated, previousDays, scopeDays } = campaign;
+    const _date = new Date(dated);
+    const [from, to] = dateRange(_date);
+    params.from = new Date(from.setDate(from.getDate() - previousDays)).toISOString();
+    params.to = new Date(to.setDate(to.getDate() + scopeDays)).toISOString();
     return params;
 };
 </script>
@@ -170,7 +152,7 @@ const updateDateParams = (value, params) => {
         v-if="campaignList"
         data-key="CustomerConsumption"
         url="Clients/consumption"
-        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"
+        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"        
         :filter="{ where: { clientFk: route.params.id } }"
         :columns="columns"
         search-url="consumption"
@@ -218,60 +200,29 @@ const updateDateParams = (value, params) => {
             <div v-if="row.subName" class="subName">
                 {{ row.subName }}
             </div>
-            <FetchedTags :item="row" />
+            <FetchedTags :item="row" :max-length="3" />
         </template>
         <template #moreFilterPanel="{ params }">
             <div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
-                <VnSelect
-                    :filled="true"
-                    class="q-px-sm q-pt-none fit"
-                    url="ItemTypes"
-                    v-model="params.typeId"
-                    :label="t('item.list.typeName')"
-                    :fields="['id', 'name', 'categoryFk']"
-                    :include="'category'"
-                    :sortBy="'name ASC'"
-                    dense
-                >
-                    <template #option="scope">
-                        <QItem v-bind="scope.itemProps">
-                            <QItemSection>
-                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
-                                <QItemLabel caption>{{
-                                    scope.opt?.category?.name
-                                }}</QItemLabel>
-                            </QItemSection>
-                        </QItem>
-                    </template>
-                </VnSelect>
-                <VnSelect
-                    :filled="true"
-                    class="q-px-sm q-pt-none fit"
-                    url="ItemCategories"
-                    v-model="params.categoryId"
-                    :label="t('item.list.category')"
-                    :fields="['id', 'name']"
-                    :sortBy="'name ASC'"
-                    dense
-                />
                 <VnSelect
                     v-model="params.campaign"
                     :options="campaignList"
                     :label="t('globals.campaign')"
                     :filled="true"
                     class="q-px-sm q-pt-none fit"
-                    :option-label="(opt) => t(opt.code)"
-                    :fields="['id', 'code', 'dated', 'scopeDays']"
-                    @update:model-value="(data) => updateDateParams(data, params)"
                     dense
+                    option-label="code"
+                    @update:model-value="(data) => updateDateParams(data, params)"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
                             <QItemSection>
-                                <QItemLabel> {{ t(scope.opt?.code) }} </QItemLabel>
-                                <QItemLabel caption>
-                                    {{ new Date(scope.opt?.dated).getFullYear() }}
-                                </QItemLabel>
+                                <QItemLabel>
+                                    {{ scope.opt?.code }}
+                                    {{
+                                        new Date(scope.opt?.dated).getFullYear()
+                                    }}</QItemLabel
+                                >
                             </QItemSection>
                         </QItem>
                     </template>
@@ -296,21 +247,7 @@ const updateDateParams = (value, params) => {
 </template>
 
 <i18n>
-en:
-
-    valentinesDay: Valentine's Day
-    mothersDay: Mother's Day
-    allSaints: All Saints' Day
-    frenchMothersDay: Mother's Day in France
 es:
     Enter a new search: Introduce una nueva búsqueda
     Group by items: Agrupar por artículos
-    valentinesDay: Día de San Valentín
-    mothersDay: Día de la Madre
-    allSaints: Día de Todos los Santos
-    frenchMothersDay: (Francia) Día de la Madre
-    Campaign consumption: Consumo campaña
-    Campaign: Campaña
-    From: Desde
-    To: Hasta
 </i18n>
diff --git a/src/pages/Customer/Card/CustomerContacts.vue b/src/pages/Customer/Card/CustomerContacts.vue
index d03f71244..c420f650e 100644
--- a/src/pages/Customer/Card/CustomerContacts.vue
+++ b/src/pages/Customer/Card/CustomerContacts.vue
@@ -62,7 +62,7 @@ const customerContactsRef = ref(null);
                                 color="primary"
                                 flat
                                 icon="add"
-                                v-shortcut="'+'"
+                                shortcut="+"
                             >
                                 <QTooltip>
                                     {{ t('Add contact') }}
diff --git a/src/pages/Customer/Card/CustomerCreditContracts.vue b/src/pages/Customer/Card/CustomerCreditContracts.vue
index a49faeb8d..7dc53db72 100644
--- a/src/pages/Customer/Card/CustomerCreditContracts.vue
+++ b/src/pages/Customer/Card/CustomerCreditContracts.vue
@@ -195,7 +195,7 @@ const updateData = () => {
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip>
             {{ t('New contract') }}
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index 89f9d9449..d7a8a59a1 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { onMounted, ref, computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
@@ -11,15 +11,6 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
-import { useState } from 'src/composables/useState';
-const state = useState();
-
-const customer = ref();
-
-onMounted(async () => {
-    customer.value = state.get('Customer');
-    if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
-});
 
 const customerDebt = ref();
 const customerCredit = ref();
@@ -55,10 +46,13 @@ const debtWarning = computed(() => {
 
 <template>
     <CardDescriptor
+        module="Customer"
         :url="`Clients/${entityId}/getCard`"
-        :summary="$props.summary"
-        data-key="Customer"
+        :title="data.title"
+        :subtitle="data.subtitle"
         @on-fetch="setData"
+        :summary="$props.summary"
+        data-key="customer"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -67,7 +61,7 @@ const debtWarning = computed(() => {
         <template #body="{ entity }">
             <VnLv
                 :label="t('customer.summary.payMethod')"
-                :value="entity.payMethod?.name"
+                :value="entity.payMethod.name"
             />
 
             <VnLv
@@ -96,7 +90,7 @@ const debtWarning = computed(() => {
             </VnLv>
             <VnLv
                 :label="t('customer.extendedList.tableVisibleColumns.businessTypeFk')"
-                :value="entity.businessType?.description"
+                :value="entity.businessType.description"
             />
         </template>
         <template #icons="{ entity }">
@@ -109,21 +103,7 @@ const debtWarning = computed(() => {
                 >
                     <QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
                 </QIcon>
-
-                <QIcon
-                    v-if="entity?.substitutionAllowed"
-                    name="help"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Allowed substitution') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="customer?.isFreezed"
-                    name="vn:frozen"
-                    size="xs"
-                    color="primary"
-                >
+                <QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
                     <QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
                 </QIcon>
                 <QIcon
@@ -163,13 +143,13 @@ const debtWarning = computed(() => {
                         <br />
                         {{
                             t('unpaidDated', {
-                                dated: toDate(customer.unpaid?.dated),
+                                dated: toDate(customer.unpaid.dated),
                             })
                         }}
                         <br />
                         {{
                             t('unpaidAmount', {
-                                amount: toCurrency(customer.unpaid?.amount),
+                                amount: toCurrency(customer.unpaid.amount),
                             })
                         }}
                     </QTooltip>
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index aea45721c..fb78eab69 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -61,16 +61,6 @@ const openCreateForm = (type) => {
         .join('&');
     useOpenURL(`/#/${type}/list?${params}`);
 };
-const updateSubstitutionAllowed = async () => {
-    try {
-        await axios.patch(`Clients/${route.params.id}`, {
-            substitutionAllowed: !$props.customer.substitutionAllowed,
-        });
-        notify('globals.notificationSent', 'positive');
-    } catch (error) {
-        notify(error.message, 'positive');
-    }
-};
 </script>
 
 <template>
@@ -79,13 +69,6 @@ const updateSubstitutionAllowed = async () => {
             {{ t('globals.pageTitles.createTicket') }}
         </QItemSection>
     </QItem>
-    <QItem v-ripple clickable>
-        <QItemSection @click="updateSubstitutionAllowed()">{{
-            $props.customer.substitutionAllowed
-                ? t('Disable substitution')
-                : t('Allow substitution')
-        }}</QItemSection>
-    </QItem>
     <QItem v-ripple clickable>
         <QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
     </QItem>
diff --git a/src/pages/Customer/Card/CustomerFileManagement.vue b/src/pages/Customer/Card/CustomerFileManagement.vue
index b565db6e7..134d8dbd6 100644
--- a/src/pages/Customer/Card/CustomerFileManagement.vue
+++ b/src/pages/Customer/Card/CustomerFileManagement.vue
@@ -236,7 +236,7 @@ const toCustomerFileManagementCreate = () => {
             @click.stop="toCustomerFileManagementCreate()"
             color="primary"
             fab
-            v-shortcut="'+'"
+            shortcut="+"
             icon="add"
         />
         <QTooltip>
diff --git a/src/pages/Customer/Card/CustomerFiscalData.vue b/src/pages/Customer/Card/CustomerFiscalData.vue
index 93909eb9c..ceeb70bb6 100644
--- a/src/pages/Customer/Card/CustomerFiscalData.vue
+++ b/src/pages/Customer/Card/CustomerFiscalData.vue
@@ -12,7 +12,6 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 import { getDifferences, getUpdatedValues } from 'src/filters';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 
@@ -74,7 +73,7 @@ async function acceptPropagate({ isEqualizated }) {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateFiscalData`"
         auto-load
-        model="Customer"
+        model="customer"
         :mapper="onBeforeSave"
         observe-form-changes
         @on-data-saved="checkEtChanges"
@@ -152,11 +151,14 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
             <VnRow>
                 <QCheckbox :label="t('Has to invoice')" v-model="data.hasToInvoice" />
-                <VnCheckbox
-                    v-model="data.isVies"
-                    :label="t('globals.isVies')"
-                    :info="t('whenActivatingIt')"
-                />
+                <div>
+                    <QCheckbox :label="t('globals.isVies')" v-model="data.isVies" />
+                    <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
+                        <QTooltip>
+                            {{ t('whenActivatingIt') }}
+                        </QTooltip>
+                    </QIcon>
+                </div>
             </VnRow>
 
             <VnRow>
@@ -168,11 +170,17 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
 
             <VnRow>
-                <VnCheckbox
-                    v-model="data.isEqualizated"
-                    :label="t('Is equalizated')"
-                    :info="t('inOrderToInvoice')"
-                />
+                <div>
+                    <QCheckbox
+                        :label="t('Is equalizated')"
+                        v-model="data.isEqualizated"
+                    />
+                    <QIcon class="cursor-info q-ml-sm" name="info" size="sm">
+                        <QTooltip>
+                            {{ t('inOrderToInvoice') }}
+                        </QTooltip>
+                    </QIcon>
+                </div>
                 <QCheckbox :label="t('Daily invoice')" v-model="data.hasDailyInvoice" />
             </VnRow>
 
diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue
index 189b59904..b85174696 100644
--- a/src/pages/Customer/Card/CustomerNotes.vue
+++ b/src/pages/Customer/Card/CustomerNotes.vue
@@ -23,6 +23,5 @@ const noteFilter = computed(() => {
         :body="{ clientFk: route.params.id }"
         style="overflow-y: auto"
         :select-type="true"
-        required
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerSamples.vue b/src/pages/Customer/Card/CustomerSamples.vue
index 19a7f8759..f12691112 100644
--- a/src/pages/Customer/Card/CustomerSamples.vue
+++ b/src/pages/Customer/Card/CustomerSamples.vue
@@ -104,7 +104,7 @@ const tableRef = ref();
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip>
             {{ t('Send sample') }}
diff --git a/src/pages/Customer/Card/CustomerWebAccess.vue b/src/pages/Customer/Card/CustomerWebAccess.vue
index 809f10918..3c4106846 100644
--- a/src/pages/Customer/Card/CustomerWebAccess.vue
+++ b/src/pages/Customer/Card/CustomerWebAccess.vue
@@ -27,7 +27,7 @@ async function hasCustomerRole() {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateUser`"
         :filter="filter"
-        model="Customer"
+        model="customer"
         :mapper="
             ({ account }) => {
                 const { name, email, active } = account;
diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index 1c5a08304..9b883daad 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -51,7 +51,11 @@ const exprBuilder = (param, value) => {
             </QItem>
             <QItem class="q-mb-sm">
                 <QItemSection>
-                    <VnInput :label="t('Name')" v-model="params.name" is-outlined />
+                    <VnInput
+                        :label="t('globals.name')"
+                        v-model="params.name"
+                        is-outlined
+                    />
                 </QItemSection>
             </QItem>
             <QItem class="q-mb-sm">
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 0bfca7910..2f2dd5978 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -274,7 +274,6 @@ const columns = computed(() => [
         align: 'left',
         name: 'isActive',
         label: t('customer.summary.isActive'),
-        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => !value,
@@ -313,7 +312,6 @@ const columns = computed(() => [
         align: 'left',
         name: 'isFreezed',
         label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
-        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => value,
@@ -431,7 +429,7 @@ function handleLocation(data, location) {
             <VnTable
                 ref="tableRef"
                 :data-key="dataKey"
-                url="Clients/extendedListFilter"
+                url="Clients/filter"
                 :create="{
                     urlCreate: 'Clients/createWithUser',
                     title: t('globals.pageTitles.customerCreate'),
diff --git a/src/pages/Customer/Defaulter/CustomerDefaulter.vue b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
index dc4ac9162..eca2ad596 100644
--- a/src/pages/Customer/Defaulter/CustomerDefaulter.vue
+++ b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
@@ -9,7 +9,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import CustomerDefaulterAddObservation from './CustomerDefaulterAddObservation.vue';
-import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 
diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue
index f852c160a..d650bbbda 100644
--- a/src/pages/Customer/components/CustomerAddressEdit.vue
+++ b/src/pages/Customer/components/CustomerAddressEdit.vue
@@ -233,7 +233,7 @@ function handleLocation(data, location) {
                             postcode: data.postalCode,
                             city: data.city,
                             province: data.province,
-                            country: data.province?.country,
+                            country: data.province.country,
                         }"
                         @update:model-value="(location) => handleLocation(data, location)"
                     ></VnLocation>
@@ -336,7 +336,7 @@ function handleLocation(data, location) {
                 class="cursor-pointer add-icon q-mt-md"
                 flat
                 icon="add"
-                v-shortcut="'+'"
+                shortcut="+"
             >
                 <QTooltip>
                     {{ t('Add note') }}
diff --git a/src/pages/Customer/components/CustomerNewPayment.vue b/src/pages/Customer/components/CustomerNewPayment.vue
index 8f61bac89..c2c38b55a 100644
--- a/src/pages/Customer/components/CustomerNewPayment.vue
+++ b/src/pages/Customer/components/CustomerNewPayment.vue
@@ -84,7 +84,7 @@ function setPaymentType(accounting) {
     viewReceipt.value = isCash.value;
     if (accountingType.value.daysInFuture)
         initialData.payed.setDate(
-            initialData.payed.getDate() + accountingType.value.daysInFuture,
+            initialData.payed.getDate() + accountingType.value.daysInFuture
         );
     maxAmount.value = accountingType.value && accountingType.value.maxAmount;
 
@@ -114,7 +114,7 @@ function onBeforeSave(data) {
     if (isCash.value && shouldSendEmail.value && !data.email)
         return notify(t('There is no assigned email for this client'), 'negative');
 
-    data.bankFk = data.bankFk?.id;
+    data.bankFk = data.bankFk.id;
     return data;
 }
 
@@ -189,7 +189,7 @@ async function getAmountPaid() {
             :url-create="urlCreate"
             :mapper="onBeforeSave"
             @on-data-saved="onDataSaved"
-            prevent-submit
+            :prevent-submit="true"
         >
             <template #form="{ data, validate }">
                 <span ref="closeButton" class="row justify-end close-icon" v-close-popup>
diff --git a/src/pages/Customer/components/CustomerSamplesCreate.vue b/src/pages/Customer/components/CustomerSamplesCreate.vue
index 1294a5d25..754693672 100644
--- a/src/pages/Customer/components/CustomerSamplesCreate.vue
+++ b/src/pages/Customer/components/CustomerSamplesCreate.vue
@@ -18,7 +18,6 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import CustomerSamplesPreview from 'src/pages/Customer/components/CustomerSamplesPreview.vue';
 import FormPopup from 'src/components/FormPopup.vue';
-import { useArrayData } from 'src/composables/useArrayData';
 
 const { dialogRef, onDialogOK } = useDialogPluginComponent();
 
@@ -40,7 +39,7 @@ const optionsSamplesVisible = ref([]);
 const sampleType = ref({ hasPreview: false });
 const initialData = reactive({});
 const entityId = computed(() => route.params.id);
-const customer = computed(() => useArrayData('Customer').store?.data);
+const customer = computed(() => state.get('customer'));
 const filterEmailUsers = { where: { userFk: user.value.id } };
 const filterClientsAddresses = {
     include: [
@@ -66,9 +65,9 @@ const filterSamplesVisible = {
 defineEmits(['confirm', ...useDialogPluginComponent.emits]);
 
 onBeforeMount(async () => {
-    initialData.clientFk = customer.value?.id;
-    initialData.recipient = customer.value?.email;
-    initialData.recipientId = customer.value?.id;
+    initialData.clientFk = customer.value.id;
+    initialData.recipient = customer.value.email;
+    initialData.recipientId = customer.value.id;
 });
 
 const setEmailUser = (data) => {
diff --git a/src/pages/Customer/locale/en.yml b/src/pages/Customer/locale/en.yml
index b6d495335..118f04a31 100644
--- a/src/pages/Customer/locale/en.yml
+++ b/src/pages/Customer/locale/en.yml
@@ -107,9 +107,6 @@ customer:
         defaulterSinced: Defaulted Since
         hasRecovery: Has Recovery
         socialName: Social name
-        typeId: Type
-        buyerId: Buyer
-        categoryId: Category
         city: City
         phone: Phone
         postcode: Postcode
diff --git a/src/pages/Customer/locale/es.yml b/src/pages/Customer/locale/es.yml
index f50d049da..7c33ffee8 100644
--- a/src/pages/Customer/locale/es.yml
+++ b/src/pages/Customer/locale/es.yml
@@ -108,9 +108,6 @@ customer:
         hasRecovery: Tiene recobro
         socialName: Razón social
         campaign: Campaña
-        typeId: Familia
-        buyerId: Comprador
-        categoryId: Reino
         city: Ciudad
         phone: Teléfono
         postcode: Código postal
diff --git a/src/pages/Worker/Department/Card/DepartmentBasicData.vue b/src/pages/Department/Card/DepartmentBasicData.vue
similarity index 73%
rename from src/pages/Worker/Department/Card/DepartmentBasicData.vue
rename to src/pages/Department/Card/DepartmentBasicData.vue
index 66210be7b..b13aed2d3 100644
--- a/src/pages/Worker/Department/Card/DepartmentBasicData.vue
+++ b/src/pages/Department/Card/DepartmentBasicData.vue
@@ -1,16 +1,27 @@
 <script setup>
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
+
+const route = useRoute();
+const { t } = useI18n();
 </script>
 <template>
-    <FormModel model="Department" auto-load class="full-width">
+    <FormModel
+        :url="`Departments/${route.params.id}`"
+        model="department"
+        auto-load
+        class="full-width"
+    >
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
-                    :label="$t('globals.name')"
+                    :label="t('globals.name')"
                     v-model="data.name"
                     :rules="validate('globals.name')"
                     clearable
@@ -18,33 +29,33 @@ import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
                 />
                 <VnInput
                     v-model="data.code"
-                    :label="$t('globals.code')"
+                    :label="t('globals.code')"
                     :rules="validate('globals.code')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="$t('department.chat')"
+                    :label="t('department.chat')"
                     v-model="data.chatName"
                     :rules="validate('department.chat')"
                     clearable
                 />
                 <VnInput
                     v-model="data.notificationEmail"
-                    :label="$t('globals.params.email')"
+                    :label="t('globals.params.email')"
                     :rules="validate('globals.params.email')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnSelectWorker
-                    :label="$t('department.bossDepartment')"
+                    :label="t('department.bossDepartment')"
                     v-model="data.workerFk"
                     :rules="validate('department.bossDepartment')"
                 />
                 <VnSelect
-                    :label="$t('department.selfConsumptionCustomer')"
+                    :label="t('department.selfConsumptionCustomer')"
                     v-model="data.clientFk"
                     url="Clients"
                     option-value="id"
@@ -56,11 +67,11 @@ import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="$t('department.telework')"
+                    :label="t('department.telework')"
                     v-model="data.isTeleworking"
                 />
                 <QCheckbox
-                    :label="$t('department.notifyOnErrors')"
+                    :label="t('department.notifyOnErrors')"
                     v-model="data.hasToMistake"
                     :false-value="0"
                     :true-value="1"
@@ -68,17 +79,17 @@ import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="$t('department.worksInProduction')"
+                    :label="t('department.worksInProduction')"
                     v-model="data.isProduction"
                 />
                 <QCheckbox
-                    :label="$t('department.hasToRefill')"
+                    :label="t('department.hasToRefill')"
                     v-model="data.hasToRefill"
                 />
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="$t('department.hasToSendMail')"
+                    :label="t('department.hasToSendMail')"
                     v-model="data.hasToSendMail"
                 />
             </VnRow>
diff --git a/src/pages/Worker/Department/Card/DepartmentCard.vue b/src/pages/Department/Card/DepartmentCard.vue
similarity index 70%
rename from src/pages/Worker/Department/Card/DepartmentCard.vue
rename to src/pages/Department/Card/DepartmentCard.vue
index 2e3f11521..4b9fe419c 100644
--- a/src/pages/Worker/Department/Card/DepartmentCard.vue
+++ b/src/pages/Department/Card/DepartmentCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import DepartmentDescriptor from 'pages/Worker/Department/Card/DepartmentDescriptor.vue';
+import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
 </script>
 <template>
     <VnCardBeta
         class="q-pa-md column items-center"
         v-bind="{ ...$attrs }"
         data-key="Department"
-        url="Departments"
+        base-url="Departments"
         :descriptor="DepartmentDescriptor"
     />
 </template>
diff --git a/src/pages/Worker/Department/Card/DepartmentDescriptor.vue b/src/pages/Department/Card/DepartmentDescriptor.vue
similarity index 84%
rename from src/pages/Worker/Department/Card/DepartmentDescriptor.vue
rename to src/pages/Department/Card/DepartmentDescriptor.vue
index 4b7dfd9b8..b219ccfe1 100644
--- a/src/pages/Worker/Department/Card/DepartmentDescriptor.vue
+++ b/src/pages/Department/Card/DepartmentDescriptor.vue
@@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
+import useCardDescription from 'src/composables/useCardDescription';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
@@ -31,6 +32,15 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
+const department = ref();
+
+const data = ref(useCardDescription());
+
+const setData = (entity) => {
+    if (!entity) return;
+    data.value = useCardDescription(entity.name, entity.id);
+};
+
 const removeDepartment = async () => {
     await axios.post(`/Departments/${entityId.value}/removeChild`, entityId.value);
     router.push({ name: 'WorkerDepartment' });
@@ -42,10 +52,19 @@ const { openConfirmationModal } = useVnConfirm();
 <template>
     <CardDescriptor
         ref="DepartmentDescriptorRef"
+        module="Department"
         :url="`Departments/${entityId}`"
+        :title="data.title"
+        :subtitle="data.subtitle"
         :summary="$props.summary"
         :to-module="{ name: 'WorkerDepartment' }"
-        data-key="Department"
+        @on-fetch="
+            (data) => {
+                department = data;
+                setData(data);
+            }
+        "
+        data-key="department"
     >
         <template #menu="{}">
             <QItem
@@ -55,7 +74,7 @@ const { openConfirmationModal } = useVnConfirm();
                     openConfirmationModal(
                         t('Are you sure you want to delete it?'),
                         t('Delete department'),
-                        removeDepartment,
+                        removeDepartment
                     )
                 "
             >
diff --git a/src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue b/src/pages/Department/Card/DepartmentDescriptorProxy.vue
similarity index 100%
rename from src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue
rename to src/pages/Department/Card/DepartmentDescriptorProxy.vue
diff --git a/src/pages/Worker/Department/Card/DepartmentSummary.vue b/src/pages/Department/Card/DepartmentSummary.vue
similarity index 99%
rename from src/pages/Worker/Department/Card/DepartmentSummary.vue
rename to src/pages/Department/Card/DepartmentSummary.vue
index 3719137e4..3d481601f 100644
--- a/src/pages/Worker/Department/Card/DepartmentSummary.vue
+++ b/src/pages/Department/Card/DepartmentSummary.vue
@@ -27,7 +27,7 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="Department"
+        data-key="DepartmentSummary"
         ref="summary"
         :url="`Departments/${entityId}`"
         class="full-width"
diff --git a/src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue b/src/pages/Department/Card/DepartmentSummaryDialog.vue
similarity index 100%
rename from src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue
rename to src/pages/Department/Card/DepartmentSummaryDialog.vue
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index 6462ed24a..689eea686 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -1,32 +1,30 @@
 <script setup>
-import { onMounted, ref } from 'vue';
+import { ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useRole } from 'src/composables/useRole';
-import { useState } from 'src/composables/useState';
-import { checkEntryLock } from 'src/composables/checkEntryLock';
 import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
+import FilterTravelForm from 'src/components/FilterTravelForm.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
+import { toDate } from 'src/filters';
 import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 
 const route = useRoute();
 const { t } = useI18n();
 const { hasAny } = useRole();
 const isAdministrative = () => hasAny(['administrative']);
-const state = useState();
-const user = state.getUser().fn();
 
 const companiesOptions = ref([]);
 const currenciesOptions = ref([]);
 
-onMounted(() => {
-    checkEntryLock(route.params.id, user.id);
-});
+const onFilterTravelSelected = (formData, id) => {
+    formData.travelFk = id;
+};
 </script>
 
 <template>
@@ -54,24 +52,46 @@ onMounted(() => {
     >
         <template #form="{ data }">
             <VnRow>
-                <VnSelectTravelExtended
-                    :data="data"
-                    v-model="data.travelFk"
-                    :onFilterTravelSelected="(data, result) => (data.travelFk = result)"
-                />
                 <VnSelectSupplier
                     v-model="data.supplierFk"
                     hide-selected
                     :required="true"
+                    map-options
                 />
+                <VnSelectDialog
+                    :label="t('entry.basicData.travel')"
+                    v-model="data.travelFk"
+                    url="Travels/filter"
+                    :fields="['id', 'warehouseInName']"
+                    option-value="id"
+                    option-label="warehouseInName"
+                    map-options
+                    hide-selected
+                    :required="true"
+                    action-icon="filter_alt"
+                >
+                    <template #form>
+                        <FilterTravelForm
+                            @travel-selected="onFilterTravelSelected(data, $event)"
+                        />
+                    </template>
+                    <template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>
+                                    {{ scope.opt?.agencyModeName }} -
+                                    {{ scope.opt?.warehouseInName }}
+                                    ({{ toDate(scope.opt?.shipped) }}) →
+                                    {{ scope.opt?.warehouseOutName }}
+                                    ({{ toDate(scope.opt?.landed) }})
+                                </QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelectDialog>
             </VnRow>
             <VnRow>
                 <VnInput v-model="data.reference" :label="t('globals.reference')" />
-                <VnInputNumber
-                    v-model="data.invoiceAmount"
-                    :label="t('entry.summary.invoiceAmount')"
-                    :positive="false"
-                />
             </VnRow>
             <VnRow>
                 <VnInput
@@ -93,7 +113,8 @@ onMounted(() => {
                 <VnInputNumber
                     :label="t('entry.summary.commission')"
                     v-model="data.commission"
-                    :step="1"
+                    step="1"
+                    autofocus
                     :positive="false"
                 />
                 <VnSelect
@@ -140,7 +161,7 @@ onMounted(() => {
                     :label="t('entry.summary.excludedFromAvailable')"
                 />
                 <QCheckbox
-                    :disable="!isAdministrative()"
+                    v-if="isAdministrative()"
                     v-model="data.isBooked"
                     :label="t('entry.basicData.booked')"
                 />
diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue
index 81578c609..6194ce5b8 100644
--- a/src/pages/Entry/Card/EntryBuys.vue
+++ b/src/pages/Entry/Card/EntryBuys.vue
@@ -1,806 +1,478 @@
 <script setup>
-import { useStateStore } from 'stores/useStateStore';
-import { useRoute } from 'vue-router';
+import { ref, computed } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { onMounted, ref } from 'vue';
+import { QBtn } from 'quasar';
 
-import { useState } from 'src/composables/useState';
-
-import FetchData from 'src/components/FetchData.vue';
-import VnTable from 'src/components/VnTable/VnTable.vue';
+import VnPaginate from 'src/components/ui/VnPaginate.vue';
+import VnSelect from 'components/common/VnSelect.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import FetchedTags from 'components/ui/FetchedTags.vue';
+import VnConfirm from 'components/ui/VnConfirm.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import FetchedTags from 'src/components/ui/FetchedTags.vue';
-import VnColor from 'src/components/common/VnColor.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
+import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
+
+import { useQuasar } from 'quasar';
+import { toCurrency } from 'src/filters';
 import axios from 'axios';
-import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
-import { checkEntryLock } from 'src/composables/checkEntryLock';
+import useNotify from 'src/composables/useNotify.js';
 
-const $props = defineProps({
-    id: {
-        type: Number,
-        default: null,
-    },
-    editableMode: {
-        type: Boolean,
-        default: true,
-    },
-    tableHeight: {
-        type: String,
-        default: null,
-    },
-});
-
-const state = useState();
-const user = state.getUser().fn();
-const stateStore = useStateStore();
-const { t } = useI18n();
+const quasar = useQuasar();
 const route = useRoute();
-const selectedRows = ref([]);
-const entityId = ref($props.id ?? route.params.id);
-const entryBuysRef = ref();
-const footerFetchDataRef = ref();
-const footer = ref({});
-const columns = [
-    {
-        align: 'center',
-        labelAbbreviation: 'NV',
-        label: t('Ignore'),
-        toolTip: t('Ignored for available'),
-        name: 'isIgnored',
-        component: 'checkbox',
-        attrs: {
-            toggleIndeterminate: false,
+const router = useRouter();
+const { t } = useI18n();
+const { notify } = useNotify();
+
+const rowsSelected = ref([]);
+const entryBuysPaginateRef = ref(null);
+const originalRowDataCopy = ref(null);
+
+const getInputEvents = (colField, props) => {
+    return colField === 'packagingFk'
+        ? { 'update:modelValue': () => saveChange(colField, props) }
+        : {
+              'keyup.enter': () => saveChange(colField, props),
+              blur: () => saveChange(colField, props),
+          };
+};
+
+const tableColumnComponents = computed(() => ({
+    item: {
+        component: QBtn,
+        props: {
+            color: 'primary',
+            flat: true,
         },
-        create: true,
-        width: '25px',
+        event: () => ({}),
     },
-    {
-        label: t('Buyer'),
-        name: 'workerFk',
-        component: 'select',
-        attrs: {
-            url: 'Workers/search',
-            fields: ['id', 'nickname'],
-            optionLabel: 'nickname',
-            optionValue: 'id',
+    quantity: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            class: 'input-number',
+            dense: true,
         },
-        visible: false,
+        event: getInputEvents,
     },
-    {
-        label: t('Family'),
-        name: 'itemTypeFk',
-        component: 'select',
-        attrs: {
-            url: 'itemTypes',
-            fields: ['id', 'name'],
-            optionLabel: 'name',
-            optionValue: 'id',
-        },
-        visible: false,
-    },
-    {
-        name: 'id',
-        isId: true,
-        visible: false,
-        isEditable: false,
-        columnFilter: false,
-    },
-    {
-        name: 'entryFk',
-        isId: true,
-        visible: false,
-        isEditable: false,
-        disable: true,
-        create: true,
-        columnFilter: false,
-    },
-    {
-        align: 'center',
-        label: 'Id',
-        name: 'itemFk',
-        component: 'number',
-        isEditable: false,
-        width: '35px',
-    },
-    {
-        labelAbbreviation: '',
-        label: 'Color',
-        name: 'hex',
-        columnSearch: false,
-        isEditable: false,
-        width: '9px',
-        component: 'select',
-        attrs: {
-            url: 'Inks',
-            fields: ['id', 'name'],
-        },
-    },
-    {
-        align: 'center',
-        label: t('Article'),
-        name: 'name',
-        component: 'select',
-        attrs: {
-            url: 'Items',
-            fields: ['id', 'name'],
-            optionLabel: 'name',
-            optionValue: 'id',
-        },
-        width: '85px',
-        isEditable: false,
-    },
-    {
-        align: 'center',
-        label: t('Article'),
-        name: 'itemFk',
-        visible: false,
-        create: true,
-        columnFilter: false,
-    },
-    {
-        align: 'center',
-        labelAbbreviation: t('Siz.'),
-        label: t('Size'),
-        toolTip: t('Size'),
-        component: 'number',
-        name: 'size',
-        width: '35px',
-        isEditable: false,
-        style: () => {
-            return { color: 'var(--vn-label-color)' };
-        },
-    },
-    {
-        align: 'center',
-        labelAbbreviation: t('Sti.'),
-        label: t('Stickers'),
-        toolTip: t('Printed Stickers/Stickers'),
-        name: 'stickers',
-        component: 'input',
-        create: true,
-        attrs: {
-            positive: false,
-        },
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                row['quantity'] = value * row['packing'];
-                row['amount'] = row['quantity'] * row['buyingValue'];
-            },
-        },
-        width: '35px',
-    },
-    {
-        align: 'center',
-        label: t('Bucket'),
-        name: 'packagingFk',
-        component: 'select',
-        attrs: {
-            url: 'packagings',
+    packagingFk: {
+        component: VnSelect,
+        props: {
+            'option-value': 'id',
+            'option-label': 'id',
+            'emit-value': true,
+            'map-options': true,
+            'use-input': true,
+            'hide-selected': true,
+            url: 'Packagings',
             fields: ['id'],
-            optionLabel: 'id',
-            optionValue: 'id',
+            where: { freightItemFk: true },
+            'sort-by': 'id ASC',
+            dense: true,
         },
-        create: true,
-        width: '40px',
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        label: 'Kg',
-        name: 'weight',
-        component: 'number',
-        create: true,
-        width: '35px',
-        format: (row) => parseFloat(row['weight']).toFixed(1),
+    stickers: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            class: 'input-number',
+            dense: true,
+        },
+        event: getInputEvents,
     },
-    {
-        labelAbbreviation: 'P',
-        label: 'Packing',
-        toolTip: 'Packing',
-        name: 'packing',
-        component: 'number',
-        create: true,
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                const oldPacking = oldValue === 1 || oldValue === null ? 1 : oldValue;
-                row['weight'] = (row['weight'] * value) / oldPacking;
-                row['quantity'] = row['stickers'] * value;
-                row['amount'] = row['quantity'] * row['buyingValue'];
-            },
-        },
-        width: '30px',
-        style: (row) => {
-            if (row.groupingMode === 'grouping')
-                return { color: 'var(--vn-label-color)' };
+    printedStickers: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            class: 'input-number',
+            dense: true,
         },
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        labelAbbreviation: 'GM',
-        label: t('Grouping selector'),
-        toolTip: t('Grouping selector'),
-        name: 'groupingMode',
-        component: 'toggle',
-        attrs: {
-            'toggle-indeterminate': true,
-            trueValue: 'grouping',
-            falseValue: 'packing',
-            indeterminateValue: null,
-        },
-        size: 'xs',
-        width: '25px',
-        create: true,
-        rightFilter: false,
-        getIcon: (value) => {
-            switch (value) {
-                case 'grouping':
-                    return 'toggle_on';
-                case 'packing':
-                    return 'toggle_off';
-                default:
-                    return 'minimize';
-            }
+    weight: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        labelAbbreviation: 'G',
-        label: 'Grouping',
-        toolTip: 'Grouping',
-        name: 'grouping',
-        component: 'number',
-        width: '30px',
-        create: true,
-        style: (row) => {
-            if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
+    packing: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        label: t('Quantity'),
-        name: 'quantity',
-        component: 'number',
-        attrs: {
-            positive: false,
+    grouping: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                row['amount'] = value * row['buyingValue'];
-            },
-        },
-        width: '45px',
-        create: true,
-        style: getQuantityStyle,
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        labelAbbreviation: t('Cost'),
-        label: t('Buying value'),
-        toolTip: t('Buying value'),
-        name: 'buyingValue',
-        create: true,
-        component: 'number',
-        attrs: {
-            positive: false,
+    buyingValue: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                row['amount'] = row['quantity'] * value;
-            },
+        event: getInputEvents,
+    },
+    price2: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
-        width: '45px',
-        format: (row) => parseFloat(row['buyingValue']).toFixed(3),
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        label: t('Amount'),
-        name: 'amount',
-        width: '45px',
-        component: 'number',
-        attrs: {
-            positive: false,
+    price3: {
+        component: VnInput,
+        props: {
+            type: 'number',
+            min: 0,
+            dense: true,
         },
-        isEditable: false,
-        format: (row) => parseFloat(row['amount']).toFixed(2),
-        style: getAmountStyle,
+        event: getInputEvents,
     },
-    {
-        align: 'center',
-        labelAbbreviation: t('Pack.'),
-        label: t('Package'),
-        toolTip: t('Package'),
-        name: 'price2',
-        component: 'number',
-        width: '35px',
-        create: true,
-        format: (row) => parseFloat(row['price2']).toFixed(2),
+    import: {
+        component: 'span',
+        props: {},
+        event: () => ({}),
     },
-    {
-        align: 'center',
-        label: t('Box'),
-        name: 'price3',
-        component: 'number',
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                row['price2'] = row['price2'] * (value / oldValue);
-            },
-        },
-        width: '35px',
-        create: true,
-        format: (row) => parseFloat(row['price3']).toFixed(2),
-    },
-    {
-        align: 'center',
-        labelAbbreviation: 'CM',
-        label: t('Check min price'),
-        toolTip: t('Check min price'),
-        name: 'hasMinPrice',
-        attrs: {
-            toggleIndeterminate: false,
-        },
-        component: 'checkbox',
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                await axios.patch(`Items/${row['itemFk']}`, {
-                    hasMinPrice: value,
-                });
-            },
-        },
-        width: '25px',
-    },
-    {
-        align: 'center',
-        labelAbbreviation: 'Min.',
-        label: t('Minimum price'),
-        toolTip: t('Minimum price'),
-        name: 'minPrice',
-        component: 'number',
-        cellEvent: {
-            'update:modelValue': async (value, oldValue, row) => {
-                await axios.patch(`Items/${row['itemFk']}`, {
-                    minPrice: value,
-                });
-            },
-        },
-        width: '35px',
-        style: (row) => {
-            if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
-        },
-        format: (row) => parseFloat(row['minPrice']).toFixed(2),
-    },
-    {
-        align: 'center',
-        labelAbbreviation: t('P.Sen'),
-        label: t('Packing sent'),
-        toolTip: t('Packing sent'),
-        name: 'packingOut',
-        component: 'number',
-        isEditable: false,
-        width: '40px',
-        style: () => {
-            return { color: 'var(--vn-label-color)' };
-        },
-    },
-    {
-        align: 'center',
-        labelAbbreviation: t('Com.'),
-        label: t('Comment'),
-        toolTip: t('Comment'),
-        name: 'comment',
-        component: 'input',
-        isEditable: false,
-        width: '50px',
-    },
-    {
-        align: 'center',
-        labelAbbreviation: 'Prod.',
-        label: t('Producer'),
-        toolTip: t('Producer'),
-        name: 'subName',
-        isEditable: false,
-        width: '45px',
-        style: () => {
-            return { color: 'var(--vn-label-color)' };
-        },
-    },
-    {
-        align: 'center',
-        label: t('Tags'),
-        name: 'tags',
-        width: '125px',
-        columnSearch: false,
-    },
-    {
-        align: 'center',
-        labelAbbreviation: 'Comp.',
-        label: t('Company'),
-        toolTip: t('Company'),
-        name: 'company_name',
-        component: 'input',
-        isEditable: false,
-        width: '35px',
-        style: () => {
-            return { color: 'var(--vn-label-color)' };
-        },
-    },
-];
+}));
 
-function getQuantityStyle(row) {
-    if (row?.quantity !== row?.stickers * row?.packing)
-        return { color: 'var(--q-negative)' };
-}
-function getAmountStyle(row) {
-    if (row?.isChecked) return { color: 'var(--q-positive)' };
-    return { color: 'var(--vn-label-color)' };
-}
-
-async function beforeSave(data, getChanges) {
-    try {
-        const changes = data.updates;
-        if (!changes) return data;
-        const patchPromises = [];
-
-        for (const change of changes) {
-            let patchData = {};
-
-            if ('hasMinPrice' in change.data) {
-                patchData.hasMinPrice = change.data?.hasMinPrice;
-                delete change.data.hasMinPrice;
-            }
-            if ('minPrice' in change.data) {
-                patchData.minPrice = change.data?.minPrice;
-                delete change.data.minPrice;
-            }
-
-            if (Object.keys(patchData).length > 0) {
-                const promise = axios
-                    .get('Buys/findOne', {
-                        params: {
-                            filter: {
-                                fields: ['itemFk'],
-                                where: { id: change.where.id },
-                            },
-                        },
-                    })
-                    .then((buy) => {
-                        return axios.patch(`Items/${buy.data.itemFk}`, patchData);
-                    })
-                    .catch((error) => {
-                        console.error('Error processing change: ', change, error);
-                    });
-
-                patchPromises.push(promise);
-            }
-        }
-
-        await Promise.all(patchPromises);
-
-        data.updates = changes.filter((change) => Object.keys(change.data).length > 0);
-
-        return data;
-    } catch (error) {
-        console.error('Error in beforeSave:', error);
-        throw error;
-    }
-}
-
-function invertQuantitySign(rows, sign) {
-    for (const row of rows) {
-        if (sign > 0) row.quantity = Math.abs(row.quantity);
-        else if (row.quantity > 0) row.quantity = -row.quantity;
-    }
-}
-function setIsChecked(rows, value) {
-    for (const row of rows) {
-        row.isChecked = value;
-    }
-    footerFetchDataRef.value.fetch();
-}
-
-async function setBuyUltimate(itemFk, data) {
-    if (!itemFk) return;
-    const buyUltimate = await axios.get(`Entries/getBuyUltimate`, {
-        params: {
-            itemFk,
-            warehouseFk: user.warehouseFk,
-            date: Date.vnNew(),
+const entriesTableColumns = computed(() => {
+    return [
+        {
+            label: t('globals.item'),
+            field: 'itemFk',
+            name: 'item',
+            align: 'left',
         },
-    });
-    const buyUltimateData = buyUltimate.data[0];
-
-    const allowedKeys = columns
-        .filter((col) => col.create === true)
-        .map((col) => col.name);
-
-    allowedKeys.forEach((key) => {
-        if (buyUltimateData.hasOwnProperty(key) && key !== 'entryFk') {
-            if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
-        }
-    });
-}
-
-onMounted(() => {
-    stateStore.rightDrawer = false;
-    if ($props.editableMode) checkEntryLock(entityId.value, user.id);
+        {
+            label: t('globals.quantity'),
+            field: 'quantity',
+            name: 'quantity',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.package'),
+            field: 'packagingFk',
+            name: 'packagingFk',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.stickers'),
+            field: 'stickers',
+            name: 'stickers',
+            align: 'left',
+        },
+        {
+            label: t('entry.buys.printedStickers'),
+            field: 'printedStickers',
+            name: 'printedStickers',
+            align: 'left',
+        },
+        {
+            label: t('globals.weight'),
+            field: 'weight',
+            name: 'weight',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.packing'),
+            field: 'packing',
+            name: 'packing',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.grouping'),
+            field: 'grouping',
+            name: 'grouping',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.buyingValue'),
+            field: 'buyingValue',
+            name: 'buyingValue',
+            align: 'left',
+            format: (value) => toCurrency(value),
+        },
+        {
+            label: t('item.fixedPrice.groupingPrice'),
+            field: 'price2',
+            name: 'price2',
+            align: 'left',
+        },
+        {
+            label: t('item.fixedPrice.packingPrice'),
+            field: 'price3',
+            name: 'price3',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.import'),
+            name: 'import',
+            align: 'left',
+            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
+        },
+    ];
 });
+
+const copyOriginalRowsData = (rows) => {
+    originalRowDataCopy.value = JSON.parse(JSON.stringify(rows));
+};
+
+const saveChange = async (field, { rowIndex, row }) => {
+    if (originalRowDataCopy.value[rowIndex][field] == row[field]) return;
+    await axios.patch(`Buys/${row.id}`, row);
+    originalRowDataCopy.value[rowIndex][field] = row[field];
+};
+
+const openRemoveDialog = async () => {
+    quasar
+        .dialog({
+            component: VnConfirm,
+            componentProps: {
+                title: t('Confirm deletion'),
+                message: t(
+                    `Are you sure you want to delete this buy${
+                        rowsSelected.value.length > 1 ? 's' : ''
+                    }?`
+                ),
+                data: rowsSelected.value,
+            },
+        })
+        .onOk(async () => {
+            await deleteBuys();
+            const notifyMessage = t(
+                `Buy${rowsSelected.value.length > 1 ? 's' : ''} deleted`
+            );
+            notify(notifyMessage, 'positive');
+        });
+};
+
+const deleteBuys = async () => {
+    await axios.post('Buys/deleteBuys', { buys: rowsSelected.value });
+    entryBuysPaginateRef.value.fetch();
+};
+
+const importBuys = () => {
+    router.push({ name: 'EntryBuysImport' });
+};
+
+const toggleGroupingMode = async (buy, mode) => {
+    const groupingMode = mode === 'grouping' ? mode : 'packing';
+    const newGroupingMode = buy.groupingMode === groupingMode ? null : groupingMode;
+    const params = {
+        groupingMode: newGroupingMode,
+    };
+    await axios.patch(`Buys/${buy.id}`, params);
+    buy.groupingMode = newGroupingMode;
+};
+
+const lockIconType = (groupingMode, mode) => {
+    if (mode === 'packing') {
+        return groupingMode === 'packing' ? 'lock' : 'lock_open';
+    } else {
+        return groupingMode === 'grouping' ? 'lock' : 'lock_open';
+    }
+};
 </script>
+
 <template>
-    <Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown() && editableMode">
-        <QBtnGroup push style="column-gap: 1px">
-            <QBtnDropdown
-                label="+/-"
-                color="primary"
-                flat
-                :title="t('Invert quantity value')"
-                :disable="!selectedRows.length"
-                data-cy="change-quantity-sign"
-            >
-                <QList>
-                    <QItem>
-                        <QItemSection>
-                            <QBtn
-                                flat
-                                @click="invertQuantitySign(selectedRows, -1)"
-                                data-cy="set-negative-quantity"
-                            >
-                                <span style="font-size: large">-</span>
-                            </QBtn>
-                        </QItemSection>
-                    </QItem>
-                    <QItem>
-                        <QItemSection>
-                            <QBtn
-                                flat
-                                @click="invertQuantitySign(selectedRows, 1)"
-                                data-cy="set-positive-quantity"
-                            >
-                                <span style="font-size: large">+</span>
-                            </QBtn>
-                        </QItemSection>
-                    </QItem>
-                </QList>
-            </QBtnDropdown>
-            <QBtnDropdown
-                icon="price_check"
-                color="primary"
-                flat
-                :title="t('Check buy amount')"
-                :disable="!selectedRows.length"
-                data-cy="check-buy-amount"
-            >
-                <QList>
-                    <QItem>
-                        <QItemSection>
-                            <QBtn
-                                size="sm"
-                                icon="check"
-                                flat
-                                @click="setIsChecked(selectedRows, true)"
-                                data-cy="check-amount"
-                            />
-                        </QItemSection>
-                    </QItem>
-                    <QItem>
-                        <QItemSection>
-                            <QBtn
-                                size="sm"
-                                icon="close"
-                                flat
-                                @click="setIsChecked(selectedRows, false)"
-                                data-cy="uncheck-amount"
-                            />
-                        </QItemSection>
-                    </QItem>
-                </QList>
-            </QBtnDropdown>
-        </QBtnGroup>
-    </Teleport>
-    <FetchData
-        ref="footerFetchDataRef"
-        :url="`Entries/${entityId}/getBuyList`"
-        :params="{ groupBy: 'GROUP BY b.entryFk' }"
-        @on-fetch="(data) => (footer = data[0])"
-        auto-load
-    />
-    <VnTable
-        ref="entryBuysRef"
+    <VnSubToolbar>
+        <template #st-actions>
+            <QBtnGroup push style="column-gap: 10px">
+                <slot name="moreBeforeActions" />
+                <QBtn
+                    :label="t('globals.remove')"
+                    color="primary"
+                    icon="delete"
+                    flat
+                    @click="openRemoveDialog()"
+                    :disable="!rowsSelected?.length"
+                    :title="t('globals.remove')"
+                />
+            </QBtnGroup>
+        </template>
+    </VnSubToolbar>
+    <VnPaginate
+        ref="entryBuysPaginateRef"
         data-key="EntryBuys"
-        :url="`Entries/${entityId}/getBuyList`"
-        save-url="Buys/crud"
-        :disable-option="{ card: true }"
-        v-model:selected="selectedRows"
-        @on-fetch="() => footerFetchDataRef.fetch()"
-        :table="
-            editableMode
-                ? {
-                      'row-key': 'id',
-                      selection: 'multiple',
-                  }
-                : {}
-        "
-        :create="
-            editableMode
-                ? {
-                      urlCreate: 'Buys',
-                      title: t('Create buy'),
-                      onDataSaved: () => {
-                          entryBuysRef.reload();
-                      },
-                      formInitialData: { entryFk: entityId, isIgnored: false },
-                      showSaveAndContinueBtn: true,
-                  }
-                : null
-        "
-        :create-complement="{
-            isFullWidth: true,
-            containerStyle: {
-                display: 'flex',
-                'flex-wrap': 'wrap',
-                gap: '16px',
-                position: 'relative',
-                height: '450px',
-            },
-            columnGridStyle: {
-                'max-width': '50%',
-                flex: 1,
-                'margin-right': '30px',
-            },
-        }"
-        :is-editable="editableMode"
-        :without-header="!editableMode"
-        :with-filters="editableMode"
-        :right-search="true"
-        :right-search-icon="true"
-        :row-click="false"
-        :columns="columns"
-        :beforeSaveFn="beforeSave"
-        class="buyList"
-        :table-height="$props.tableHeight ?? '84vh'"
+        :url="`Entries/${route.params.id}/getBuys`"
+        @on-fetch="copyOriginalRowsData($event)"
         auto-load
-        footer
-        data-cy="entry-buys"
     >
-        <template #column-hex="{ row }">
-            <VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
-        </template>
-        <template #column-name="{ row }">
-            <span class="link">
-                {{ row?.name }}
-                <ItemDescriptorProxy :id="row?.itemFk" />
-            </span>
-        </template>
-        <template #column-tags="{ row }">
-            <FetchedTags :item="row" :columns="3" />
-        </template>
-        <template #column-stickers="{ row }">
-            <span :class="editableMode ? 'editable-text' : ''">
-                <span style="color: var(--vn-label-color)">
-                    {{ row.printedStickers }}
-                </span>
-                <span>/{{ row.stickers }}</span>
-            </span>
-        </template>
-        <template #column-footer-stickers>
-            <div>
-                <span style="color: var(--vn-label-color)">
-                    {{ footer?.printedStickers }}</span
-                >
-                <span>/</span>
-                <span data-cy="footer-stickers">{{ footer?.stickers }}</span>
-            </div>
-        </template>
-        <template #column-footer-weight>
-            {{ footer?.weight }}
-        </template>
-        <template #column-footer-quantity>
-            <span :style="getQuantityStyle(footer)" data-cy="footer-quantity">
-                {{ footer?.quantity }}
-            </span>
-        </template>
-        <template #column-footer-amount>
-            <span :style="getAmountStyle(footer)" data-cy="footer-amount">
-                {{ footer?.amount }}
-            </span>
-        </template>
-        <template #column-create-itemFk="{ data }">
-            <VnSelect
-                url="Items/search"
-                v-model="data.itemFk"
-                :label="t('Article')"
-                :fields="['id', 'name', 'size', 'producerName']"
-                :filter-options="['id', 'name', 'size', 'producerName']"
-                option-label="name"
-                option-value="id"
-                @update:modelValue="
-                    async (value) => {
-                        await setBuyUltimate(value, data);
-                    }
-                "
-                :required="true"
-                data-cy="itemFk-create-popup"
-                sort-by="nickname DESC"
+        <template #body="{ rows }">
+            <QTable
+                :rows="rows"
+                :columns="entriesTableColumns"
+                selection="multiple"
+                row-key="id"
+                class="full-width q-mt-md"
+                :grid="$q.screen.lt.md"
+                v-model:selected="rowsSelected"
+                :no-data-label="t('globals.noResults')"
             >
-                <template #option="scope">
-                    <QItem v-bind="scope.itemProps">
-                        <QItemSection>
-                            <QItemLabel>
-                                {{ scope.opt.name }}
-                            </QItemLabel>
-                            <QItemLabel caption>
-                                #{{ scope.opt.id }}, {{ scope.opt?.size }},
-                                {{ scope.opt?.producerName }}
-                            </QItemLabel>
-                        </QItemSection>
-                    </QItem>
+                <template #body="props">
+                    <QTr>
+                        <QTd>
+                            <QCheckbox v-model="props.selected" />
+                        </QTd>
+                        <QTd
+                            v-for="col in props.cols"
+                            :key="col.name"
+                            style="max-width: 100px"
+                        >
+                            <component
+                                :is="tableColumnComponents[col.name].component"
+                                v-bind="tableColumnComponents[col.name].props"
+                                v-model="props.row[col.field]"
+                                v-on="
+                                    tableColumnComponents[col.name].event(
+                                        col.field,
+                                        props
+                                    )
+                                "
+                            >
+                                <template
+                                    v-if="
+                                        col.name === 'grouping' || col.name === 'packing'
+                                    "
+                                    #append
+                                >
+                                    <QBtn
+                                        :icon="
+                                            lockIconType(props.row.groupingMode, col.name)
+                                        "
+                                        @click="toggleGroupingMode(props.row, col.name)"
+                                        class="cursor-pointer"
+                                        size="sm"
+                                        flat
+                                        dense
+                                        unelevated
+                                        push
+                                        :style="{
+                                            'font-variation-settings': `'FILL' ${
+                                                lockIconType(
+                                                    props.row.groupingMode,
+                                                    col.name
+                                                ) === 'lock'
+                                                    ? 1
+                                                    : 0
+                                            }`,
+                                        }"
+                                    />
+                                </template>
+                                <template
+                                    v-if="col.name === 'item' || col.name === 'import'"
+                                >
+                                    {{ col.value }}
+                                </template>
+                                <ItemDescriptorProxy
+                                    v-if="col.name === 'item'"
+                                    :id="props.row.item.id"
+                                />
+                            </component>
+                        </QTd>
+                    </QTr>
+                    <QTr no-hover class="full-width infoRow" style="column-span: all">
+                        <QTd />
+                        <QTd cols>
+                            <span>{{ props.row.item.itemType.code }}</span>
+                        </QTd>
+                        <QTd>
+                            <span>{{ props.row.item.size }}</span>
+                        </QTd>
+                        <QTd>
+                            <span>{{ toCurrency(props.row.item.minPrice) }}</span>
+                        </QTd>
+                        <QTd colspan="7">
+                            <span>{{ props.row.item.concept }}</span>
+                            <span v-if="props.row.item.subName" class="subName">
+                                {{ props.row.item.subName }}
+                            </span>
+                            <FetchedTags :item="props.row.item" />
+                        </QTd>
+                    </QTr>
                 </template>
-            </VnSelect>
+                <template #item="props">
+                    <div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
+                        <QCard bordered flat>
+                            <QCardSection>
+                                <QCheckbox v-model="props.selected" dense />
+                            </QCardSection>
+                            <QSeparator />
+                            <QList dense>
+                                <QItem v-for="col in props.cols" :key="col.name">
+                                    <component
+                                        :is="tableColumnComponents[col.name].component"
+                                        v-bind="tableColumnComponents[col.name].props"
+                                        v-model="props.row[col.field]"
+                                        v-on="
+                                            tableColumnComponents[col.name].event(
+                                                col.field,
+                                                props
+                                            )
+                                        "
+                                        class="full-width"
+                                    >
+                                        <template
+                                            v-if="
+                                                col.name === 'item' ||
+                                                col.name === 'import'
+                                            "
+                                        >
+                                            {{ col.label + ': ' + col.value }}
+                                        </template>
+                                    </component>
+                                </QItem>
+                            </QList>
+                        </QCard>
+                    </div>
+                </template>
+            </QTable>
         </template>
-        <template #column-create-groupingMode="{ data }">
-            <VnSelectEnum
-                :label="t('Grouping mode')"
-                v-model="data.groupingMode"
-                schema="vn"
-                table="buy"
-                column="groupingMode"
-                option-value="groupingMode"
-                option-label="groupingMode"
-            />
-        </template>
-        <template #previous-create-dialog="{ data }">
-            <div
-                style="position: absolute"
-                :class="{ 'centered-container': !data.itemFk }"
-            >
-                <ItemDescriptor :id="data.itemFk" v-if="data.itemFk" />
-                <div v-else>
-                    <span>{{ t('globals.noData') }}</span>
-                </div>
-            </div>
-        </template>
-    </VnTable>
+    </VnPaginate>
+
+    <QPageSticky :offset="[20, 20]">
+        <QBtn fab icon="upload" color="primary" @click="importBuys()" />
+        <QTooltip class="text-no-wrap">
+            {{ t('Import buys') }}
+        </QTooltip>
+    </QPageSticky>
 </template>
-<i18n>
-es:
-    Article: Artículo
-    Siz.: Med.
-    Size: Medida
-    Sti.: Eti.
-    Bucket: Cubo
-    Quantity: Cantidad
-    Amount: Importe
-    Pack.: Paq.
-    Package: Paquete
-    Box: Caja
-    P.Sen: P.Env
-    Packing sent: Packing envíos
-    Com.: Ref.
-    Comment: Referencia
-    Minimum price: Precio mínimo
-    Stickers: Etiquetas
-    Printed Stickers/Stickers: Etiquetas impresas/Etiquetas
-    Cost: Cost.
-    Buying value: Coste
-    Producer: Productor
-    Company: Compañia
-    Tags: Etiquetas
-    Grouping mode: Modo de agrupación
-    C.min: P.min
-    Ignore: Ignorar
-    Ignored for available: Ignorado para disponible
-    Grouping selector: Selector de grouping
-    Check min price: Marcar precio mínimo
-    Create buy: Crear compra
-    Invert quantity value: Invertir valor de cantidad
-    Check buy amount: Marcar como correcta la cantidad de compra
-</i18n>
+
 <style lang="scss" scoped>
-.centered-container {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    position: absolute;
-    width: 40%;
-    height: 100%;
+.q-table--horizontal-separator tbody tr:nth-child(odd) > td {
+    border-bottom-width: 0px;
+    border-top-width: 2px;
+    border-color: var(--vn-text-color);
+}
+.infoRow > td {
+    color: var(--vn-label-color);
 }
 </style>
+
+<i18n>
+es:
+    Import buys: Importar compras
+    Buy deleted: Compra eliminada
+    Buys deleted: Compras eliminadas
+    Confirm deletion: Confirmar eliminación
+    Are you sure you want to delete this buy?: Seguro que quieres eliminar esta compra?
+    Are you sure you want to delete this buys?: Seguro que quieres eliminar estas compras?
+</i18n>
diff --git a/src/pages/Entry/Card/EntryCard.vue b/src/pages/Entry/Card/EntryCard.vue
index be82289f4..e00623a21 100644
--- a/src/pages/Entry/Card/EntryCard.vue
+++ b/src/pages/Entry/Card/EntryCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import EntryDescriptor from './EntryDescriptor.vue';
-import filter from './EntryFilter.js';
+import filter from './EntryFilter.js'
 </script>
 <template>
     <VnCardBeta
         data-key="Entry"
-        url="Entries"
+        base-url="Entries"
         :descriptor="EntryDescriptor"
-        :filter="filter"
+        :user-filter="filter"
     />
 </template>
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index 69b300cb2..19d13e51a 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -1,19 +1,12 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
+import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { toDate } from 'src/filters';
-import { getUrl } from 'src/composables/getUrl';
-import { useQuasar } from 'quasar';
-import { usePrintService } from 'composables/usePrintService';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-import axios from 'axios';
-
-const quasar = useQuasar();
-const { push } = useRouter();
-const { openReport } = usePrintService();
+import { toDate } from 'src/filters';
+import { getUrl } from 'src/composables/getUrl';
+import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
 
 const $props = defineProps({
     id: {
@@ -90,63 +83,12 @@ const getEntryRedirectionFilter = (entry) => {
         to,
     });
 };
-
-function showEntryReport() {
-    openReport(`Entries/${entityId.value}/entry-order-pdf`);
-}
-
-function showNotification(type, message) {
-    quasar.notify({
-        type: type,
-        message: t(message),
-    });
-}
-
-async function recalculateRates(entity) {
-    try {
-        const entryConfig = await axios.get('EntryConfigs/findOne');
-        if (entryConfig.data?.inventorySupplierFk === entity.supplierFk) {
-            showNotification(
-                'negative',
-                'Cannot recalculate prices because this is an inventory entry',
-            );
-            return;
-        }
-
-        await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);
-        showNotification('positive', 'Entry prices recalculated');
-    } catch (error) {
-        showNotification('negative', 'Failed to recalculate rates');
-        console.error(error);
-    }
-}
-
-async function cloneEntry() {
-    try {
-        const response = await axios.post(`Entries/${entityId.value}/cloneEntry`);
-        push({ path: `/entry/${response.data}` });
-        showNotification('positive', 'Entry cloned');
-    } catch (error) {
-        showNotification('negative', 'Failed to clone entry');
-        console.error(error);
-    }
-}
-
-async function deleteEntry() {
-    try {
-        await axios.post(`Entries/${entityId.value}/deleteEntry`);
-        push({ path: `/entry/list` });
-        showNotification('positive', 'Entry deleted');
-    } catch (error) {
-        showNotification('negative', 'Failed to delete entry');
-        console.error(error);
-    }
-}
 </script>
 
 <template>
     <CardDescriptor
         ref="entryDescriptorRef"
+        module="Entry"
         :url="`Entries/${entityId}`"
         :userFilter="entryFilter"
         title="supplier.nickname"
@@ -154,56 +96,15 @@ async function deleteEntry() {
         width="lg-width"
     >
         <template #menu="{ entity }">
-            <QItem
-                v-ripple
-                clickable
-                @click="showEntryReport(entity)"
-                data-cy="show-entry-report"
-            >
-                <QItemSection>{{ t('Show entry report') }}</QItemSection>
-            </QItem>
-            <QItem
-                v-ripple
-                clickable
-                @click="recalculateRates(entity)"
-                data-cy="recalculate-rates"
-            >
-                <QItemSection>{{ t('Recalculate rates') }}</QItemSection>
-            </QItem>
-            <QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry">
-                <QItemSection>{{ t('Clone') }}</QItemSection>
-            </QItem>
-            <QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry">
-                <QItemSection>{{ t('Delete') }}</QItemSection>
-            </QItem>
+            <EntryDescriptorMenu :id="entity.id" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('Travel')">
-                <template #value>
-                    <span class="link" v-if="entity?.travelFk">
-                        {{ entity.travel?.agency?.name }}
-                        {{ entity.travel?.warehouseOut?.code }} &rarr;
-                        {{ entity.travel?.warehouseIn?.code }}
-                        <TravelDescriptorProxy :id="entity?.travelFk" />
-                    </span>
-                </template>
-            </VnLv>
+            <VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
+            <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
+            <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
             <VnLv
-                :label="t('entry.summary.travelShipped')"
-                :value="toDate(entity.travel?.shipped)"
-            />
-            <VnLv
-                :label="t('entry.summary.travelLanded')"
-                :value="toDate(entity.travel?.landed)"
-            />
-            <VnLv :label="t('entry.summary.currency')" :value="entity?.currency?.code" />
-            <VnLv
-                :label="t('entry.summary.invoiceAmount')"
-                :value="entity?.invoiceAmount"
-            />
-            <VnLv
-                :label="t('entry.summary.entryType')"
-                :value="entity?.entryType?.description"
+                :label="t('globals.warehouseOut')"
+                :value="entity.travel?.warehouseOut?.name"
             />
         </template>
         <template #icons="{ entity }">
@@ -230,14 +131,6 @@ async function deleteEntry() {
                         }}</QTooltip
                     >
                 </QIcon>
-                <QIcon
-                    v-if="!entity?.travelFk"
-                    name="vn:deletedTicket"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('This entry is deleted') }}</QTooltip>
-                </QIcon>
             </QCardActions>
         </template>
         <template #actions="{ entity }">
@@ -250,6 +143,21 @@ async function deleteEntry() {
                 >
                     <QTooltip>{{ t('Supplier card') }}</QTooltip>
                 </QBtn>
+                <QBtn
+                    :to="{
+                        name: 'TravelMain',
+                        query: {
+                            params: JSON.stringify({
+                                agencyModeFk: entity.travel?.agencyModeFk,
+                            }),
+                        },
+                    }"
+                    size="md"
+                    icon="local_airport"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('All travels with current agency') }}</QTooltip>
+                </QBtn>
                 <QBtn
                     :to="{
                         name: 'EntryMain',
@@ -269,24 +177,10 @@ async function deleteEntry() {
 </template>
 <i18n>
 es:
-    Travel: Envío
     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
     Inventory entry: Es inventario
     Virtual entry: Es una redada
-    shipped: Enviado
-    landed: Recibido
-    This entry is deleted: Esta entrada está eliminada
-    Cannot recalculate prices because this is an inventory entry: No se pueden recalcular los precios porque es una entrada de inventario
-    Entry deleted: Entrada eliminada
-    Entry cloned: Entrada clonada
-    Entry prices recalculated: Precios de la entrada recalculados
-    Failed to recalculate rates: No se pudieron recalcular las tarifas
-    Failed to clone entry: No se pudo clonar la entrada
-    Failed to delete entry: No se pudo eliminar la entrada
-    Recalculate rates: Recalcular tarifas
-    Clone: Clonar
-    Delete: Eliminar
 </i18n>
diff --git a/src/pages/Entry/Card/EntryFilter.js b/src/pages/Entry/Card/EntryFilter.js
index d9fd1c2be..3ff62cf27 100644
--- a/src/pages/Entry/Card/EntryFilter.js
+++ b/src/pages/Entry/Card/EntryFilter.js
@@ -9,7 +9,6 @@ export default {
                     'shipped',
                     'agencyModeFk',
                     'warehouseOutFk',
-                    'warehouseInFk',
                     'daysInForward',
                 ],
                 include: [
@@ -22,13 +21,13 @@ export default {
                     {
                         relation: 'warehouseOut',
                         scope: {
-                            fields: ['name', 'code'],
+                            fields: ['name'],
                         },
                     },
                     {
                         relation: 'warehouseIn',
                         scope: {
-                            fields: ['name', 'code'],
+                            fields: ['name'],
                         },
                     },
                 ],
@@ -40,17 +39,5 @@ export default {
                 fields: ['id', 'nickname'],
             },
         },
-        {
-            relation: 'currency',
-            scope: {
-                fields: ['id', 'code'],
-            },
-        },
-        {
-            relation: 'entryType',
-            scope: {
-                fields: ['code', 'description'],
-            },
-        },
     ],
 };
diff --git a/src/pages/Entry/Card/EntryNotes.vue b/src/pages/Entry/Card/EntryNotes.vue
index 459c3b069..55cac0437 100644
--- a/src/pages/Entry/Card/EntryNotes.vue
+++ b/src/pages/Entry/Card/EntryNotes.vue
@@ -17,7 +17,7 @@ const selected = ref([]);
 
 const sortEntryObservationOptions = (data) => {
     entryObservationsOptions.value = [...data].sort((a, b) =>
-        a.description.localeCompare(b.description),
+        a.description.localeCompare(b.description)
     );
 };
 
@@ -142,7 +142,7 @@ const columns = computed(() => [
             fab
             color="primary"
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
             @click="entryObservationsRef.insert()"
         />
     </QPageSticky>
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index c40e2ba46..8c46fb6e6 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -2,17 +2,19 @@
 import { onMounted, ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { toDate } from 'src/filters';
-import { getUrl } from 'src/composables/getUrl';
-import axios from 'axios';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-import EntryBuys from './EntryBuys.vue';
-import VnTitle from 'src/components/common/VnTitle.vue';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
+
+import { toDate, toCurrency, toCelsius } from 'src/filters';
+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';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -31,6 +33,117 @@ const entry = ref();
 const entryBuys = ref([]);
 const entryUrl = ref();
 
+onMounted(async () => {
+    entryUrl.value = (await getUrl('entry/')) + entityId.value;
+});
+
+const tableColumnComponents = {
+    quantity: {
+        component: () => 'span',
+        props: () => {},
+    },
+    stickers: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    packagingFk: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    weight: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    packing: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    grouping: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    buyingValue: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    amount: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+    pvp: {
+        component: () => 'span',
+        props: () => {},
+        event: () => {},
+    },
+};
+
+const entriesTableColumns = computed(() => {
+    return [
+        {
+            label: t('globals.quantity'),
+            field: 'quantity',
+            name: 'quantity',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.stickers'),
+            field: 'stickers',
+            name: 'stickers',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.package'),
+            field: 'packagingFk',
+            name: 'packagingFk',
+            align: 'left',
+        },
+        {
+            label: t('globals.weight'),
+            field: 'weight',
+            name: 'weight',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.packing'),
+            field: 'packing',
+            name: 'packing',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.grouping'),
+            field: 'grouping',
+            name: 'grouping',
+            align: 'left',
+        },
+        {
+            label: t('entry.summary.buyingValue'),
+            field: 'buyingValue',
+            name: 'buyingValue',
+            align: 'left',
+            format: (value) => toCurrency(value),
+        },
+        {
+            label: t('entry.summary.import'),
+            name: 'amount',
+            align: 'left',
+            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
+        },
+        {
+            label: t('entry.summary.pvp'),
+            name: 'pvp',
+            align: 'left',
+            format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
+        },
+    ];
+});
+
 async function setEntryData(data) {
     if (data) entry.value = data;
     await fetchEntryBuys();
@@ -40,18 +153,14 @@ const fetchEntryBuys = async () => {
     const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
     if (data) entryBuys.value = data;
 };
-
-onMounted(async () => {
-    entryUrl.value = (await getUrl('entry/')) + entityId.value;
-});
 </script>
+
 <template>
     <CardSummary
         ref="summaryRef"
         :url="`Entries/${entityId}/getEntry`"
         @on-fetch="(data) => setEntryData(data)"
         data-key="EntrySummary"
-        data-cy="entry-summary"
     >
         <template #header-left>
             <VnToSummary
@@ -64,154 +173,159 @@ onMounted(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
                     :url="`#/entry/${entityId}/basic-data`"
                     :text="t('globals.summary.basicData')"
                 />
-                <div class="card-group">
-                    <div class="card-content">
-                        <VnLv
-                            :label="t('entry.summary.commission')"
-                            :value="entry?.commission"
-                        />
-                        <VnLv
-                            :label="t('entry.summary.currency')"
-                            :value="entry?.currency?.name"
-                        />
-                        <VnLv
-                            :label="t('globals.company')"
-                            :value="entry?.company?.code"
-                        />
-                        <VnLv :label="t('globals.reference')" :value="entry?.reference" />
-                        <VnLv
-                            :label="t('entry.summary.invoiceNumber')"
-                            :value="entry?.invoiceNumber"
-                        />
-                    </div>
-                    <div class="card-content">
-                        <VnCheckbox
-                            :label="t('entry.summary.ordered')"
-                            v-model="entry.isOrdered"
-                            :disable="true"
-                            size="xs"
-                        />
-                        <VnCheckbox
-                            :label="t('globals.confirmed')"
-                            v-model="entry.isConfirmed"
-                            :disable="true"
-                            size="xs"
-                        />
-                        <VnCheckbox
-                            :label="t('entry.summary.booked')"
-                            v-model="entry.isBooked"
-                            :disable="true"
-                            size="xs"
-                        />
-                        <VnCheckbox
-                            :label="t('entry.summary.excludedFromAvailable')"
-                            v-model="entry.isExcludedFromAvailable"
-                            :disable="true"
-                            size="xs"
-                        />
-                    </div>
-                </div>
-            </QCard>
-            <QCard class="vn-one" v-if="entry?.travelFk">
-                <VnTitle
-                    :url="`#/travel/${entry.travel.id}/summary`"
-                    :text="t('Travel')"
+                <VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
+                <VnLv
+                    :label="t('entry.summary.currency')"
+                    :value="entry.currency?.name"
                 />
-                <div class="card-group">
-                    <div class="card-content">
-                        <VnLv :label="t('entry.summary.travelReference')">
-                            <template #value>
-                                <span class="link">
-                                    {{ entry.travel.ref }}
-                                    <TravelDescriptorProxy :id="entry.travel.id" />
-                                </span>
-                            </template>
-                        </VnLv>
-                        <VnLv
-                            :label="t('entry.summary.travelAgency')"
-                            :value="entry.travel.agency?.name"
-                        />
-                        <VnLv
-                            :label="t('entry.summary.travelShipped')"
-                            :value="toDate(entry.travel.shipped)"
-                        />
-                        <VnLv
-                            :label="t('globals.warehouseOut')"
-                            :value="entry.travel.warehouseOut?.name"
-                        />
-                        <VnLv
-                            :label="t('entry.summary.travelLanded')"
-                            :value="toDate(entry.travel.landed)"
-                        />
-                        <VnLv
-                            :label="t('globals.warehouseIn')"
-                            :value="entry.travel.warehouseIn?.name"
-                        />
-                    </div>
-                    <div class="card-content">
-                        <VnCheckbox
-                            :label="t('entry.summary.travelDelivered')"
-                            v-model="entry.travel.isDelivered"
-                            :disable="true"
-                            size="xs"
-                        />
-                        <VnCheckbox
-                            :label="t('entry.summary.travelReceived')"
-                            v-model="entry.travel.isReceived"
-                            :disable="true"
-                            size="xs"
-                        />
-                    </div>
-                </div>
+                <VnLv :label="t('globals.company')" :value="entry.company.code" />
+                <VnLv :label="t('globals.reference')" :value="entry.reference" />
+                <VnLv
+                    :label="t('entry.summary.invoiceNumber')"
+                    :value="entry.invoiceNumber"
+                />
+                <VnLv
+                    :label="t('entry.basicData.initialTemperature')"
+                    :value="toCelsius(entry.initialTemperature)"
+                />
+                <VnLv
+                    :label="t('entry.basicData.finalTemperature')"
+                    :value="toCelsius(entry.finalTemperature)"
+                />
+            </QCard>
+            <QCard class="vn-one">
+                <VnTitle
+                    :url="`#/entry/${entityId}/basic-data`"
+                    :text="t('globals.summary.basicData')"
+                />
+                <VnLv :label="t('entry.summary.travelReference')">
+                    <template #value>
+                        <span class="link">
+                            {{ entry.travel.ref }}
+                            <TravelDescriptorProxy :id="entry.travel.id" />
+                        </span>
+                    </template>
+                </VnLv>
+                <VnLv
+                    :label="t('entry.summary.travelAgency')"
+                    :value="entry.travel.agency?.name"
+                />
+                <VnLv
+                    :label="t('globals.shipped')"
+                    :value="toDate(entry.travel.shipped)"
+                />
+                <VnLv
+                    :label="t('globals.warehouseOut')"
+                    :value="entry.travel.warehouseOut?.name"
+                />
+                <VnLv
+                    :label="t('entry.summary.travelDelivered')"
+                    :value="entry.travel.isDelivered"
+                />
+                <VnLv :label="t('globals.landed')" :value="toDate(entry.travel.landed)" />
+                <VnLv
+                    :label="t('globals.warehouseIn')"
+                    :value="entry.travel.warehouseIn?.name"
+                />
+                <VnLv
+                    :label="t('entry.summary.travelReceived')"
+                    :value="entry.travel.isReceived"
+                />
+            </QCard>
+            <QCard class="vn-one">
+                <VnTitle :url="`#/travel/${entityId}/summary`" :text="t('Travel data')" />
+                <VnRow class="block">
+                    <VnLv :label="t('entry.summary.ordered')" :value="entry.isOrdered" />
+                    <VnLv :label="t('globals.confirmed')" :value="entry.isConfirmed" />
+                    <VnLv :label="t('entry.summary.booked')" :value="entry.isBooked" />
+                    <VnLv
+                        :label="t('entry.summary.excludedFromAvailable')"
+                        :value="entry.isExcludedFromAvailable"
+                    />
+                </VnRow>
             </QCard>
             <QCard class="vn-max">
                 <VnTitle
                     :url="`#/entry/${entityId}/buys`"
                     :text="t('entry.summary.buys')"
                 />
-                <EntryBuys
-                    v-if="entityId"
-                    :id="Number(entityId)"
-                    :editable-mode="false"
-                    table-height="49vh"
-                />
+                <QTable
+                    :rows="entryBuys"
+                    :columns="entriesTableColumns"
+                    row-key="index"
+                    class="full-width q-mt-md"
+                    :no-data-label="t('globals.noResults')"
+                >
+                    <template #body="{ cols, row, rowIndex }">
+                        <QTr no-hover>
+                            <QTd v-for="col in cols" :key="col?.name">
+                                <component
+                                    :is="tableColumnComponents[col?.name].component()"
+                                    v-bind="tableColumnComponents[col?.name].props()"
+                                    @click="tableColumnComponents[col?.name].event()"
+                                    class="col-content"
+                                >
+                                    <template
+                                        v-if="
+                                            col?.name !== 'observation' &&
+                                            col?.name !== 'isConfirmed'
+                                        "
+                                        >{{ col.value }}</template
+                                    >
+                                    <QTooltip v-if="col.toolTip">{{
+                                        col.toolTip
+                                    }}</QTooltip>
+                                </component>
+                            </QTd>
+                        </QTr>
+                        <QTr no-hover>
+                            <QTd>
+                                <span>{{ row.item.itemType.code }}</span>
+                            </QTd>
+                            <QTd>
+                                <span>{{ row.item.id }}</span>
+                            </QTd>
+                            <QTd>
+                                <span>{{ row.item.size }}</span>
+                            </QTd>
+                            <QTd>
+                                <span>{{ toCurrency(row.item.minPrice) }}</span>
+                            </QTd>
+                            <QTd colspan="6">
+                                <span>{{ row.item.concept }}</span>
+                                <span v-if="row.item.subName" class="subName">
+                                    {{ row.item.subName }}
+                                </span>
+                                <FetchedTags :item="row.item" />
+                            </QTd>
+                        </QTr>
+                        <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
+                        <QTr v-if="rowIndex !== entryBuys.length - 1">
+                            <QTd colspan="10" class="vn-table-separation-row" />
+                        </QTr>
+                    </template>
+                </QTable>
             </QCard>
         </template>
     </CardSummary>
 </template>
+
 <style lang="scss" scoped>
-.card-group {
-    display: flex;
-    flex-direction: column;
-}
-
-.card-content {
-    display: flex;
-    flex-direction: column;
-    text-overflow: ellipsis;
-    > div {
-        max-height: 24px;
-    }
-}
-
-@media (min-width: 1010px) {
-    .card-group {
-        flex-direction: row;
-    }
-    .card-content {
-        flex: 1;
-        margin-right: 16px;
-    }
+.separation-row {
+    background-color: var(--vn-section-color) !important;
 }
 </style>
+
 <i18n>
 es:
-    Travel: Envío
-    InvoiceIn data: Datos factura
+    Travel data: Datos envío
 </i18n>
diff --git a/src/pages/Entry/EntryFilter.vue b/src/pages/Entry/EntryFilter.vue
index 8c60918a8..0f632c0ef 100644
--- a/src/pages/Entry/EntryFilter.vue
+++ b/src/pages/Entry/EntryFilter.vue
@@ -19,7 +19,6 @@ const props = defineProps({
 
 const currenciesOptions = ref([]);
 const companiesOptions = ref([]);
-const entryFilterPanel = ref();
 </script>
 
 <template>
@@ -39,7 +38,7 @@ const entryFilterPanel = ref();
         @on-fetch="(data) => (currenciesOptions = data)"
         auto-load
     />
-    <VnFilterPanel ref="entryFilterPanel" :data-key="props.dataKey" :search-button="true">
+    <VnFilterPanel :data-key="props.dataKey" :search-button="true">
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">
                 <strong>{{ t(`entryFilter.params.${tag.label}`) }}: </strong>
@@ -49,65 +48,70 @@ const entryFilterPanel = ref();
         <template #body="{ params, searchFn }">
             <QItem>
                 <QItemSection>
-                    <QCheckbox
-                        :label="t('params.isExcludedFromAvailable')"
-                        v-model="params.isExcludedFromAvailable"
-                        toggle-indeterminate
-                    >
-                        <QTooltip>
-                            {{ t('params.isExcludedFromAvailable') }}
-                        </QTooltip>
-                    </QCheckbox>
-                </QItemSection>
-                <QItemSection>
-                    <QCheckbox
-                        :label="t('params.isOrdered')"
-                        v-model="params.isOrdered"
-                        toggle-indeterminate
-                    >
-                        <QTooltip>
-                            {{ t('entry.list.tableVisibleColumns.isOrdered') }}
-                        </QTooltip>
-                    </QCheckbox>
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <QCheckbox
-                        :label="t('params.isReceived')"
-                        v-model="params.isReceived"
-                        toggle-indeterminate
-                    >
-                        <QTooltip>
-                            {{ t('entry.list.tableVisibleColumns.isReceived') }}
-                        </QTooltip>
-                    </QCheckbox>
-                </QItemSection>
-                <QItemSection>
-                    <QCheckbox
-                        :label="t('entry.list.tableVisibleColumns.isConfirmed')"
-                        v-model="params.isConfirmed"
-                        toggle-indeterminate
-                    >
-                        <QTooltip>
-                            {{ t('entry.list.tableVisibleColumns.isConfirmed') }}
-                        </QTooltip>
-                    </QCheckbox>
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInputDate
-                        :label="t('params.landed')"
-                        v-model="params.landed"
-                        @update:model-value="searchFn()"
+                    <VnInput
+                        v-model="params.search"
+                        :label="t('entryFilter.params.search')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput v-model="params.id" label="Id" is-outlined />
+                    <VnInput
+                        v-model="params.reference"
+                        :label="t('entryFilter.params.reference')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.invoiceNumber"
+                        :label="t('entryFilter.params.invoiceNumber')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.travelFk"
+                        :label="t('entryFilter.params.travelFk')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('entryFilter.params.companyFk')"
+                        v-model="params.companyFk"
+                        @update:model-value="searchFn()"
+                        :options="companiesOptions"
+                        option-value="id"
+                        option-label="code"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('entryFilter.params.currencyFk')"
+                        v-model="params.currencyFk"
+                        @update:model-value="searchFn()"
+                        :options="currenciesOptions"
+                        option-value="id"
+                        option-label="name"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
                 </QItemSection>
             </QItem>
             <QItem>
@@ -121,165 +125,62 @@ const entryFilterPanel = ref();
                         rounded
                     />
                 </QItemSection>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.invoiceNumber"
-                        :label="t('params.invoiceNumber')"
-                        is-outlined
-                    />
-                </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.reference"
-                        :label="t('entry.list.tableVisibleColumns.reference')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.agencyModeId')"
-                        v-model="params.agencyModeId"
+                    <VnInputDate
+                        :label="t('entryFilter.params.created')"
+                        v-model="params.created"
                         @update:model-value="searchFn()"
-                        url="AgencyModes"
-                        :fields="['id', 'name']"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.evaNotes"
-                        :label="t('params.evaNotes')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnSelect
-                        :label="t('params.warehouseOutFk')"
-                        v-model="params.warehouseOutFk"
+                    <VnInputDate
+                        :label="t('entryFilter.params.from')"
+                        v-model="params.from"
                         @update:model-value="searchFn()"
-                        url="Warehouses"
-                        :fields="['id', 'name']"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.warehouseInFk')"
-                        v-model="params.warehouseInFk"
-                        @update:model-value="searchFn()"
-                        url="Warehouses"
-                        :fields="['id', 'name']"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    >
-                        <template #option="scope">
-                            <QItem v-bind="scope.itemProps">
-                                <QItemSection>
-                                    <QItemLabel>
-                                        {{ scope.opt?.name }}
-                                    </QItemLabel>
-                                    <QItemLabel caption>
-                                        {{ `#${scope.opt?.id} , ${scope.opt?.nickname}` }}
-                                    </QItemLabel>
-                                </QItemSection>
-                            </QItem>
-                        </template>
-                    </VnSelect>
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.invoiceNumber"
-                        :label="t('params.invoiceNumber')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
-
             <QItem>
                 <QItemSection>
-                    <VnSelect
-                        :label="t('params.entryTypeCode')"
-                        v-model="params.entryTypeCode"
+                    <VnInputDate
+                        :label="t('entryFilter.params.to')"
+                        v-model="params.to"
                         @update:model-value="searchFn()"
-                        url="EntryTypes"
-                        :fields="['code', 'description']"
-                        option-value="code"
-                        option-label="description"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
+                        is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.evaNotes"
-                        :label="t('params.evaNotes')"
-                        is-outlined
+                    <QCheckbox
+                        :label="t('entryFilter.params.isBooked')"
+                        v-model="params.isBooked"
+                        toggle-indeterminate
+                    />
+                </QItemSection>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('entryFilter.params.isConfirmed')"
+                        v-model="params.isConfirmed"
+                        toggle-indeterminate
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('entryFilter.params.isOrdered')"
+                        v-model="params.isOrdered"
+                        toggle-indeterminate
                     />
                 </QItemSection>
             </QItem>
         </template>
     </VnFilterPanel>
 </template>
-
-<i18n>
-en:
-    params:
-        isExcludedFromAvailable: Inventory
-        isOrdered: Ordered
-        isReceived: Received
-        isConfirmed: Confirmed
-        isRaid: Raid
-        landed: Date
-        id: Id
-        supplierFk: Supplier
-        invoiceNumber: Invoice number
-        reference: Ref/Alb/Guide
-        agencyModeId: Agency mode
-        evaNotes: Notes
-        warehouseOutFk: Origin
-        warehouseInFk: Destiny
-        entryTypeCode: Entry type
-        hasToShowDeletedEntries: Show deleted entries
-es:
-    params:
-        isExcludedFromAvailable: Inventario
-        isOrdered: Pedida
-        isConfirmed: Confirmado
-        isReceived: Recibida
-        isRaid: Raid
-        landed: Fecha
-        id: Id
-        supplierFk: Proveedor
-        invoiceNumber: Núm. factura
-        reference: Ref/Alb/Guía
-        agencyModeId: Modo agencia
-        evaNotes: Notas
-        warehouseOutFk: Origen
-        warehouseInFk: Destino
-        entryTypeCode: Tipo de entrada
-        hasToShowDeletedEntries: Mostrar entradas eliminadas
-</i18n>
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 3c96a2302..3172c6d0e 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -1,25 +1,21 @@
 <script setup>
-import axios from 'axios';
-import VnSection from 'src/components/common/VnSection.vue';
 import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useState } from 'src/composables/useState';
-import { onBeforeMount } from 'vue';
-
 import EntryFilter from './EntryFilter.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
+import { toCelsius, toDate } from 'src/filters';
+import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import EntrySummary from './Card/EntrySummary.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
-import { toDate } from 'src/filters';
+import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
+import VnSection from 'src/components/common/VnSection.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-const defaultEntry = ref({});
-const state = useState();
-const user = state.getUser();
 const dataKey = 'EntryList';
 
-const entryQueryFilter = {
+const { viewSummary } = useSummaryDialog();
+const entryFilter = {
     include: [
         {
             relation: 'suppliers',
@@ -44,58 +40,44 @@ const entryQueryFilter = {
 
 const columns = computed(() => [
     {
-        labelAbbreviation: 'Ex',
-        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
-        toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
-        name: 'isExcludedFromAvailable',
-        component: 'checkbox',
-        width: '35px',
+        name: 'status',
+        columnFilter: false,
     },
     {
-        labelAbbreviation: 'Pe',
-        label: t('entry.list.tableVisibleColumns.isOrdered'),
-        toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
-        name: 'isOrdered',
-        component: 'checkbox',
-        width: '35px',
+        align: 'left',
+        label: t('globals.id'),
+        name: 'id',
+        isId: true,
+        chip: {
+            condition: () => true,
+        },
     },
     {
-        labelAbbreviation: 'LE',
-        label: t('entry.list.tableVisibleColumns.isConfirmed'),
-        toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
-        name: 'isConfirmed',
-        component: 'checkbox',
-        width: '35px',
+        align: 'left',
+        label: t('globals.reference'),
+        name: 'reference',
+        isTitle: true,
+        component: 'input',
+        columnField: {
+            component: null,
+        },
+        create: true,
+        cardVisible: true,
     },
     {
-        labelAbbreviation: 'Re',
-        label: t('entry.list.tableVisibleColumns.isReceived'),
-        toolTip: t('entry.list.tableVisibleColumns.isReceived'),
-        name: 'isReceived',
-        component: 'checkbox',
-        width: '35px',
-    },
-    {
-        label: t('entry.list.tableVisibleColumns.landed'),
-        name: 'landed',
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.created'),
+        name: 'created',
+        create: true,
+        cardVisible: true,
         component: 'date',
         columnField: {
             component: null,
         },
-        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
-        width: '105px',
-    },
-    {
-        label: t('globals.id'),
-        name: 'id',
-        isId: true,
-        component: 'number',
-        chip: {
-            condition: () => true,
-        },
-        width: '50px',
+        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.created)),
     },
     {
+        align: 'left',
         label: t('entry.list.tableVisibleColumns.supplierFk'),
         name: 'supplierFk',
         create: true,
@@ -104,213 +86,165 @@ const columns = computed(() => [
         attrs: {
             url: 'suppliers',
             fields: ['id', 'name'],
-            where: { order: 'name DESC' },
+        },
+        columnField: {
+            component: null,
         },
         format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
-        width: '110px',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.invoiceNumber'),
-        name: 'invoiceNumber',
-        component: 'input',
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.reference'),
-        name: 'reference',
-        isTitle: true,
-        component: 'input',
-        columnField: {
-            component: null,
-        },
+        label: t('entry.list.tableVisibleColumns.isBooked'),
+        name: 'isBooked',
         cardVisible: true,
+        create: true,
+        component: 'checkbox',
     },
     {
         align: 'left',
-        label: 'AWB',
-        name: 'awbCode',
-        component: 'input',
-        width: '100px',
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.agencyModeId'),
-        name: 'agencyModeId',
+        label: t('entry.list.tableVisibleColumns.isConfirmed'),
+        name: 'isConfirmed',
         cardVisible: true,
-        component: 'select',
-        attrs: {
-            url: 'agencyModes',
-            fields: ['id', 'name'],
-        },
-        columnField: {
-            component: null,
-        },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyModeName),
+        create: true,
+        component: 'checkbox',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.evaNotes'),
-        name: 'evaNotes',
-        component: 'input',
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.warehouseOutFk'),
-        name: 'warehouseOutFk',
+        label: t('entry.list.tableVisibleColumns.isOrdered'),
+        name: 'isOrdered',
         cardVisible: true,
-        component: 'select',
-        attrs: {
-            url: 'warehouses',
-            fields: ['id', 'name'],
-        },
-        columnField: {
-            component: null,
-        },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseOutName),
-        width: '65px',
+        create: true,
+        component: 'checkbox',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.warehouseInFk'),
-        name: 'warehouseInFk',
-        cardVisible: true,
-        component: 'select',
-        attrs: {
-            url: 'warehouses',
-            fields: ['id', 'name'],
-        },
-        columnField: {
-            component: null,
-        },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseInName),
-        width: '65px',
-    },
-    {
-        align: 'left',
-        labelAbbreviation: t('Type'),
-        label: t('entry.list.tableVisibleColumns.entryTypeDescription'),
-        toolTip: t('entry.list.tableVisibleColumns.entryTypeDescription'),
-        name: 'entryTypeCode',
-        component: 'select',
-        attrs: {
-            url: 'entryTypes',
-            fields: ['code', 'description'],
-            optionValue: 'code',
-            optionLabel: 'description',
-        },
-        width: '65px',
-        format: (row, dashIfEmpty) => dashIfEmpty(row.entryTypeDescription),
-    },
-    {
-        name: 'companyFk',
         label: t('entry.list.tableVisibleColumns.companyFk'),
-        cardVisible: false,
-        visible: false,
-        create: true,
+        name: 'companyFk',
         component: 'select',
         attrs: {
-            optionValue: 'id',
+            url: 'companies',
+            fields: ['id', 'code'],
             optionLabel: 'code',
-            url: 'Companies',
+            optionValue: 'id',
+        },
+        columnField: {
+            component: null,
+        },
+        create: true,
+
+        format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.travelFk'),
+        name: 'travelFk',
+        component: 'select',
+        attrs: {
+            url: 'travels',
+            fields: ['id', 'ref'],
+            optionLabel: 'ref',
+            optionValue: 'id',
+        },
+        columnField: {
+            component: null,
+        },
+        create: true,
+        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.invoiceAmount'),
+        name: 'invoiceAmount',
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'initialTemperature',
+        label: t('entry.basicData.initialTemperature'),
+        field: 'initialTemperature',
+        format: (row) => toCelsius(row.initialTemperature),
+    },
+    {
+        align: 'left',
+        name: 'finalTemperature',
+        label: t('entry.basicData.finalTemperature'),
+        field: 'finalTemperature',
+        format: (row) => toCelsius(row.finalTemperature),
+    },
+    {
+        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
+        name: 'isExcludedFromAvailable',
+        columnFilter: {
+            inWhere: true,
         },
     },
     {
-        name: 'travelFk',
-        label: t('entry.list.tableVisibleColumns.travelFk'),
-        cardVisible: false,
-        visible: false,
-        create: true,
+        align: 'right',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('components.smartCard.viewSummary'),
+                icon: 'preview',
+                action: (row) => viewSummary(row.id, EntrySummary),
+                isPrimary: true,
+            },
+        ],
     },
 ]);
-function getBadgeAttrs(row) {
-    const date = row.landed;
-    let today = Date.vnNew();
-    today.setHours(0, 0, 0, 0);
-    let timeTicket = new Date(date);
-    timeTicket.setHours(0, 0, 0, 0);
-
-    let timeDiff = today - timeTicket;
-
-    if (timeDiff > 0) return { color: 'info', 'text-color': 'black' };
-    if (timeDiff < 0) return { color: 'warning', 'text-color': 'black' };
-    switch (row.entryTypeCode) {
-        case 'regularization':
-        case 'life':
-        case 'internal':
-        case 'inventory':
-            if (!row.isOrdered || !row.isConfirmed)
-                return { color: 'negative', 'text-color': 'black' };
-            break;
-        case 'product':
-        case 'packaging':
-        case 'devaluation':
-        case 'payment':
-        case 'transport':
-            if (
-                row.invoiceAmount === null ||
-                (row.invoiceNumber === null && row.reference === null) ||
-                !row.isOrdered ||
-                !row.isConfirmed
-            )
-                return { color: 'negative', 'text-color': 'black' };
-            break;
-        default:
-            break;
-    }
-    return { color: 'transparent' };
-}
-
-onBeforeMount(async () => {
-    defaultEntry.value = (await axios.get('EntryConfigs/findOne')).data;
-});
 </script>
 
 <template>
     <VnSection
         :data-key="dataKey"
+        :columns="columns"
         prefix="entry"
         url="Entries/filter"
         :array-data-props="{
             url: 'Entries/filter',
-            order: 'landed DESC',
-            userFilter: EntryFilter,
+            order: 'id DESC',
+            userFilter: entryFilter,
         }"
     >
         <template #advanced-menu>
-            <EntryFilter :data-key="dataKey" />
+            <EntryFilter data-key="EntryList" />
         </template>
         <template #body>
             <VnTable
-                v-if="defaultEntry.defaultSupplierFk"
                 ref="tableRef"
                 :data-key="dataKey"
-                url="Entries/filter"
-                :filter="entryQueryFilter"
-                order="landed DESC"
                 :create="{
                     urlCreate: 'Entries',
-                    title: t('Create entry'),
+                    title: t('entry.list.newEntry'),
                     onDataSaved: ({ id }) => tableRef.redirect(id),
-                    formInitialData: {
-                        supplierFk: defaultEntry.defaultSupplierFk,
-                        dated: Date.vnNew(),
-                        companyFk: user?.companyFk,
-                    },
+                    formInitialData: {},
                 }"
                 :columns="columns"
                 redirect="entry"
                 :right-search="false"
             >
-                <template #column-landed="{ row }">
-                    <QBadge
-                        v-if="row?.travelFk"
-                        v-bind="getBadgeAttrs(row)"
-                        class="q-pa-sm"
-                        style="font-size: 14px"
-                    >
-                        {{ toDate(row.landed) }}
-                    </QBadge>
+                <template #column-status="{ row }">
+                    <div class="row q-gutter-xs">
+                        <QIcon
+                            v-if="!!row.isExcludedFromAvailable"
+                            name="vn:inventory"
+                            color="primary"
+                        >
+                            <QTooltip>{{
+                                t(
+                                    'entry.list.tableVisibleColumns.isExcludedFromAvailable',
+                                )
+                            }}</QTooltip>
+                        </QIcon>
+                        <QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
+                            <QTooltip>
+                                {{
+                                    t('globals.raid', {
+                                        daysInForward: row.daysInForward,
+                                    })
+                                }}</QTooltip
+                            >
+                        </QIcon>
+                    </div>
                 </template>
                 <template #column-supplierFk="{ row }">
                     <span class="link" @click.stop>
@@ -318,27 +252,13 @@ onBeforeMount(async () => {
                         <SupplierDescriptorProxy :id="row.supplierFk" />
                     </span>
                 </template>
-                <template #column-create-travelFk="{ data }">
-                    <VnSelectTravelExtended
-                        :data="data"
-                        v-model="data.travelFk"
-                        :onFilterTravelSelected="
-                            (data, result) => (data.travelFk = result)
-                        "
-                        data-cy="entry-travel-select"
-                    />
+                <template #column-travelFk="{ row }">
+                    <span class="link" @click.stop>
+                        {{ row.travelRef }}
+                        <TravelDescriptorProxy :id="row.travelFk" />
+                    </span>
                 </template>
             </VnTable>
         </template>
     </VnSection>
 </template>
-
-<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
-    Create entry: Crear entrada
-    Type: Tipo
-</i18n>
diff --git a/src/pages/Entry/EntryStockBought.vue b/src/pages/Entry/EntryStockBought.vue
index 4bd0fe640..fa0bdc12e 100644
--- a/src/pages/Entry/EntryStockBought.vue
+++ b/src/pages/Entry/EntryStockBought.vue
@@ -34,20 +34,18 @@ const columns = computed(() => [
         label: t('entryStockBought.buyer'),
         isTitle: true,
         component: 'select',
-        isEditable: false,
         cardVisible: true,
         create: true,
         attrs: {
             url: 'Workers/activeWithInheritedRole',
-            fields: ['id', 'name', 'nickname'],
+            fields: ['id', 'name'],
             where: { role: 'buyer' },
             optionFilter: 'firstName',
-            optionLabel: 'nickname',
+            optionLabel: 'name',
             optionValue: 'id',
             useLike: false,
         },
         columnFilter: false,
-        width: '70px',
     },
     {
         align: 'center',
@@ -57,7 +55,6 @@ const columns = computed(() => [
         create: true,
         component: 'number',
         summation: true,
-        width: '50px',
     },
     {
         align: 'center',
@@ -81,7 +78,6 @@ const columns = computed(() => [
         actions: [
             {
                 title: t('entryStockBought.viewMoreDetails'),
-                name: 'searchBtn',
                 icon: 'search',
                 isPrimary: true,
                 action: (row) => {
@@ -95,7 +91,6 @@ const columns = computed(() => [
                 },
             },
         ],
-        'data-cy': 'table-actions',
     },
 ]);
 
@@ -163,7 +158,7 @@ function round(value) {
                 @on-fetch="
                     (data) => {
                         travel = data.find(
-                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh',
+                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh'
                         );
                     }
                 "
@@ -184,7 +179,6 @@ function round(value) {
                         @click="openDialog()"
                         :title="t('entryStockBought.editTravel')"
                         color="primary"
-                        data-cy="edit-travel"
                     />
                 </div>
             </VnRow>
@@ -245,11 +239,10 @@ function round(value) {
                 table-height="80vh"
                 auto-load
                 :column-search="false"
-                :without-header="true"
             >
                 <template #column-workerFk="{ row }">
                     <span class="link" @click.stop>
-                        {{ row?.worker?.user?.nickname }}
+                        {{ row?.worker?.user?.name }}
                         <WorkerDescriptorProxy :id="row?.workerFk" />
                     </span>
                 </template>
@@ -286,11 +279,10 @@ function round(value) {
     justify-content: center;
 }
 .column {
-    min-width: 40%;
-    margin-top: 5%;
     display: flex;
     flex-direction: column;
     align-items: center;
+    min-width: 35%;
 }
 .text-negative {
     color: $negative !important;
diff --git a/src/pages/Entry/EntryStockBoughtDetail.vue b/src/pages/Entry/EntryStockBoughtDetail.vue
index 1a37994d9..812171825 100644
--- a/src/pages/Entry/EntryStockBoughtDetail.vue
+++ b/src/pages/Entry/EntryStockBoughtDetail.vue
@@ -21,7 +21,7 @@ const $props = defineProps({
 const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&dated=${$props.dated}`;
 const columns = [
     {
-        align: 'right',
+        align: 'left',
         label: t('Entry'),
         name: 'entryFk',
         isTitle: true,
@@ -29,7 +29,7 @@ const columns = [
         columnFilter: false,
     },
     {
-        align: 'right',
+        align: 'left',
         name: 'itemFk',
         label: t('Item'),
         columnFilter: false,
@@ -44,21 +44,21 @@ const columns = [
         cardVisible: true,
     },
     {
-        align: 'right',
+        align: 'left',
         name: 'volume',
         label: t('Volume'),
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'right',
+        align: 'left',
         label: t('Packaging'),
         name: 'packagingFk',
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'right',
+        align: 'left',
         label: 'Packing',
         name: 'packing',
         columnFilter: false,
@@ -73,14 +73,12 @@ const columns = [
                 ref="tableRef"
                 data-key="StockBoughtsDetail"
                 :url="customUrl"
-                order="volume DESC"
+                order="itemName DESC"
                 :columns="columns"
                 :right-search="false"
                 :disable-infinite-scroll="true"
                 :disable-option="{ card: true }"
                 :limit="0"
-                :without-header="true"
-                :with-filters="false"
                 auto-load
             >
                 <template #column-entryFk="{ row }">
@@ -101,14 +99,16 @@ const columns = [
 </template>
 <style lang="css" scoped>
 .container {
-    max-width: 100%;
-    width: 50%;
+    max-width: 50vw;
     overflow: auto;
     justify-content: center;
     align-items: center;
     margin: auto;
     background-color: var(--vn-section-color);
-    padding: 2%;
+    padding: 4px;
+}
+.container > div > div > .q-table__top.relative-position.row.items-center {
+    background-color: red !important;
 }
 </style>
 <i18n>
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index 88b16cb03..80f3491a8 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -1,36 +1,21 @@
 entry:
-    lock:
-        title: Lock entry
-        message: This entry has been locked by {userName} for {time} minutes. Do you want to unlock it?
-        success: The entry has been locked successfully
     list:
         newEntry: New entry
         tableVisibleColumns:
-            isExcludedFromAvailable: Exclude from inventory
-            isOrdered: Ordered
-            isConfirmed: Ready to label
-            isReceived: Received
-            isRaid: Raid
-            landed: Date
+            created: Creation
             supplierFk: Supplier
-            reference: Ref/Alb/Guide
-            invoiceNumber: Invoice
-            agencyModeId: Agency
             isBooked: Booked
+            isConfirmed: Confirmed
+            isOrdered: Ordered
             companyFk: Company
-            evaNotes: Notes
-            warehouseOutFk: Origin
-            warehouseInFk: Destiny
-            entryTypeDescription: Entry type
-            invoiceAmount: Import
             travelFk: Travel
-            dated: Dated
+            isExcludedFromAvailable: Inventory
+            invoiceAmount: Import
         inventoryEntry: Inventory entry
     summary:
         commission: Commission
         currency: Currency
         invoiceNumber: Invoice number
-        invoiceAmount: Invoice amount
         ordered: Ordered
         booked: Booked
         excludedFromAvailable: Inventory
@@ -48,7 +33,6 @@ entry:
         buyingValue: Buying value
         import: Import
         pvp: PVP
-        entryType: Entry type
     basicData:
         travel: Travel
         currency: Currency
@@ -85,55 +69,17 @@ entry:
             landing: Landing
             isExcludedFromAvailable: Es inventory
     params:
-        isExcludedFromAvailable: Exclude from inventory
-        isOrdered: Ordered
-        isConfirmed: Ready to label
-        isReceived: Received
-        isIgnored: Ignored
-        isRaid: Raid
-        landed: Date
-        supplierFk: Supplier
-        reference: Ref/Alb/Guide
-        invoiceNumber: Invoice
-        agencyModeId: Agency
-        isBooked: Booked
-        companyFk: Company
-        evaNotes: Notes
-        warehouseOutFk: Origin
-        warehouseInFk: Destiny
-        entryTypeDescription: Entry type
-        invoiceAmount: Import
-        travelFk: Travel
-        dated: Dated
-        itemFk: Item id
-        hex: Color
-        name: Item name
-        size: Size
-        stickers: Stickers
-        packagingFk: Packaging
-        weight: Kg
-        groupingMode: Grouping selector
-        grouping: Grouping
-        quantity: Quantity
-        buyingValue: Buying value
-        price2: Package
-        price3: Box
-        minPrice: Minumum price
-        hasMinPrice: Has minimum price
-        packingOut: Packing out
-        comment: Comment
-        subName: Supplier name
-        tags: Tags
-        company_name: Company name
-        itemTypeFk: Item type
-        workerFk: Worker id
+        toShipped: To
+        fromShipped: From
+        daysOnward: Days onward
+        daysAgo: Days ago
+        warehouseInFk: Warehouse in
     search: Search entries
     searchInfo: You can search by entry reference
     descriptorMenu:
         showEntryReport: Show entry report
 entryFilter:
     params:
-        isExcludedFromAvailable: Exclude from inventory
         invoiceNumber: Invoice number
         travelFk: Travel
         companyFk: Company
@@ -145,16 +91,8 @@ entryFilter:
         isBooked: Booked
         isConfirmed: Confirmed
         isOrdered: Ordered
-        isReceived: Received
         search: General search
         reference: Reference
-        landed: Landed
-        id: Id
-        agencyModeId: Agency
-        evaNotes: Notes
-        warehouseOutFk: Origin
-        warehouseInFk: Destiny
-        entryTypeCode: Entry type
 myEntries:
     id: ID
     landed: Landed
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index 3025d64cb..a5b968016 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -1,36 +1,21 @@
 entry:
-    lock:
-        title: Entrada bloqueada
-        message: Esta entrada ha sido bloqueada por {userName} hace {time} minutos. ¿Quieres desbloquearla?
-        success: La entrada ha sido bloqueada correctamente
     list:
         newEntry: Nueva entrada
         tableVisibleColumns:
-            isExcludedFromAvailable: Excluir del inventario
-            isOrdered: Pedida
-            isConfirmed: Lista para etiquetar
-            isReceived: Recibida
-            isRaid: Redada
-            landed: Fecha
+            created: Creación
             supplierFk: Proveedor
-            invoiceNumber: Nº Factura
-            reference: Ref/Alb/Guía
-            agencyModeId: Agencia
             isBooked: Asentado
+            isConfirmed: Confirmado
+            isOrdered: Pedida
             companyFk: Empresa
             travelFk: Envio
-            evaNotes: Notas
-            warehouseOutFk: Origen
-            warehouseInFk: Destino
-            entryTypeDescription: Tipo entrada
+            isExcludedFromAvailable: Inventario
             invoiceAmount: Importe
-            dated: Fecha
         inventoryEntry: Es inventario
     summary:
         commission: Comisión
         currency: Moneda
         invoiceNumber: Núm. factura
-        invoiceAmount: Importe
         ordered: Pedida
         booked: Contabilizada
         excludedFromAvailable: Inventario
@@ -49,13 +34,12 @@ entry:
         buyingValue: Coste
         import: Importe
         pvp: PVP
-        entryType: Tipo entrada
     basicData:
         travel: Envío
         currency: Moneda
         observation: Observación
         commission: Comisión
-        booked: Contabilizada
+        booked: Asentado
         excludedFromAvailable: Inventario
         initialTemperature: Ini °C
         finalTemperature: Fin °C
@@ -85,70 +69,31 @@ entry:
             packingOut: Embalaje envíos
             landing: Llegada
             isExcludedFromAvailable: Es inventario
-
+    params:
+        toShipped: Hasta
+        fromShipped: Desde
+        warehouseInFk: Alm. entrada
+        daysOnward: Días adelante
+        daysAgo: Días atras
+    descriptorMenu:
+        showEntryReport: Ver informe del pedido
     search: Buscar entradas
     searchInfo: Puedes buscar por referencia de entrada
-    params:
-        isExcludedFromAvailable: Excluir del inventario
-        isOrdered: Pedida
-        isConfirmed: Lista para etiquetar
-        isReceived: Recibida
-        isRaid: Redada
-        isIgnored: Ignorado
-        landed: Fecha
-        supplierFk: Proveedor
-        invoiceNumber: Nº Factura
-        reference: Ref/Alb/Guía
-        agencyModeId: Agencia
-        isBooked: Asentado
-        companyFk: Empresa
-        travelFk: Envio
-        evaNotes: Notas
-        warehouseOutFk: Origen
-        warehouseInFk: Destino
-        entryTypeDescription: Tipo entrada
-        invoiceAmount: Importe
-        dated: Fecha
-        itemFk: Id artículo
-        hex: Color
-        name: Nombre artículo
-        size: Medida
-        stickers: Etiquetas
-        packagingFk: Embalaje
-        weight: Kg
-        groupinMode: Selector de grouping
-        grouping: Grouping
-        quantity: Quantity
-        buyingValue: Precio de compra
-        price2: Paquete
-        price3: Caja
-        minPrice: Precio mínimo
-        hasMinPrice: Tiene precio mínimo
-        packingOut: Packing out
-        comment: Referencia
-        subName: Nombre proveedor
-        tags: Etiquetas
-        company_name: Nombre empresa
-        itemTypeFk: Familia
-        workerFk: Comprador
 entryFilter:
     params:
-        isExcludedFromAvailable: Inventario
-        isOrdered: Pedida
-        isConfirmed: Confirmado
-        isReceived: Recibida
-        isRaid: Raid
-        landed: Fecha
-        id: Id
-        supplierFk: Proveedor
         invoiceNumber: Núm. factura
-        reference: Ref/Alb/Guía
-        agencyModeId: Modo agencia
-        evaNotes: Notas
-        warehouseOutFk: Origen
-        warehouseInFk: Destino
-        entryTypeCode: Tipo de entrada
-        hasToShowDeletedEntries: Mostrar entradas eliminadas
+        travelFk: Envío
+        companyFk: Empresa
+        currencyFk: Moneda
+        supplierFk: Proveedor
+        from: Desde
+        to: Hasta
+        created: Fecha creación
+        isBooked: Asentado
+        isConfirmed: Confirmado
+        isOrdered: Pedida
+        search: Búsqueda general
+        reference: Referencia
 myEntries:
     id: ID
     landed: F. llegada
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index 905ddebb2..c01ec4ab4 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -125,7 +125,7 @@ function deleteFile(dmsFk) {
                 <VnInput
                     clearable
                     clear-icon="close"
-                    :label="t('invoiceIn.supplierRef')"
+                    :label="t('Supplier ref')"
                     v-model="data.supplierRef"
                 />
             </VnRow>
@@ -149,7 +149,6 @@ function deleteFile(dmsFk) {
                     option-value="id"
                     option-label="id"
                     :filter-options="['id', 'name']"
-                    data-cy="UnDeductibleVatSelect"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
@@ -216,7 +215,7 @@ function deleteFile(dmsFk) {
                         v-else
                         icon="add_circle"
                         round
-                        v-shortcut="'+'"
+                        shortcut="+"
                         padding="xs"
                         @click="
                             () => {
@@ -311,6 +310,7 @@ function deleteFile(dmsFk) {
         supplierFk: Supplier
     es:
         supplierFk: Proveedor
+        Supplier ref: Ref. proveedor
         Expedition date: Fecha expedición
         Operation date: Fecha operación
         Undeductible VAT: Iva no deducible
diff --git a/src/pages/InvoiceIn/Card/InvoiceInCard.vue b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
index 34cc26437..8aa35f4d8 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInCard.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
@@ -1,18 +1,47 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import InvoiceInDescriptor from './InvoiceInDescriptor.vue';
-import { onBeforeRouteUpdate } from 'vue-router';
-import { setRectificative } from '../composables/setRectificative';
-import filter from './InvoiceInFilter.js';
 
-onBeforeRouteUpdate(async (to) => await setRectificative(to));
+const filter = {
+    include: [
+        {
+            relation: 'supplier',
+            scope: {
+                include: {
+                    relation: 'contacts',
+                    scope: { where: { email: { neq: null } } },
+                },
+            },
+        },
+        { relation: 'invoiceInDueDay' },
+        { relation: 'company' },
+        { relation: 'currency' },
+        {
+            relation: 'dms',
+            scope: {
+                fields: [
+                    'dmsTypeFk',
+                    'reference',
+                    'hardCopyNumber',
+                    'workerFk',
+                    'description',
+                    'hasFile',
+                    'file',
+                    'created',
+                    'companyFk',
+                    'warehouseFk',
+                ],
+            },
+        },
+    ],
+};
 </script>
 
 <template>
     <VnCardBeta
         data-key="InvoiceIn"
-        url="InvoiceIns"
+        base-url="InvoiceIns"
         :descriptor="InvoiceInDescriptor"
-        :filter="filter"
+        :user-filter="filter"
     />
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index 3843f5bf7..da7bd4426 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -7,7 +7,6 @@ import { toCurrency, toDate } from 'src/filters';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import filter from './InvoiceInFilter.js';
 import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
 
 const $props = defineProps({ id: { type: Number, default: null } });
@@ -17,10 +16,33 @@ const { t } = useI18n();
 const cardDescriptorRef = ref();
 const entityId = computed(() => $props.id || +currentRoute.value.params.id);
 const totalAmount = ref();
-const config = ref();
-const cplusRectificationTypes = ref([]);
-const siiTypeInvoiceIns = ref([]);
-const invoiceCorrectionTypes = ref([]);
+
+const filter = {
+    include: [
+        {
+            relation: 'supplier',
+            scope: {
+                include: {
+                    relation: 'contacts',
+                    scope: {
+                        where: {
+                            email: { neq: null },
+                        },
+                    },
+                },
+            },
+        },
+        {
+            relation: 'invoiceInDueDay',
+        },
+        {
+            relation: 'company',
+        },
+        {
+            relation: 'currency',
+        },
+    ],
+};
 const invoiceInCorrection = reactive({ correcting: [], corrected: null });
 const routes = reactive({
     getSupplier: (id) => {
@@ -90,6 +112,7 @@ async function setInvoiceCorrection(id) {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
+        module="InvoiceIn"
         data-key="InvoiceIn"
         :url="`InvoiceIns/${entityId}`"
         :filter="filter"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
index 8b039ec27..c3ab635c8 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
@@ -186,7 +186,7 @@ const createInvoiceInCorrection = async () => {
                 clickable
                 @click="book(entityId)"
             >
-                <QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
+                <QItemSection>{{ t('invoiceIn.descriptorMenu.toBook') }}</QItemSection>
             </QItem>
         </template>
     </InvoiceInToBook>
@@ -197,7 +197,7 @@ const createInvoiceInCorrection = async () => {
         @click="triggerMenu('unbook')"
     >
         <QItemSection>
-            {{ t('invoiceIn.descriptorMenu.unbook') }}
+            {{ t('invoiceIn.descriptorMenu.toUnbook') }}
         </QItemSection>
     </QItem>
     <QItem
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
index 20cc1cc71..23387ff74 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed, onBeforeMount } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import axios from 'axios';
@@ -11,7 +11,6 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import useNotify from 'src/composables/useNotify.js';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-import { toCurrency } from 'filters/index';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -25,7 +24,7 @@ const invoiceInFormRef = ref();
 const invoiceId = +route.params.id;
 const filter = { where: { invoiceInFk: invoiceId } };
 const areRows = ref(false);
-const totals = ref();
+
 const columns = computed(() => [
     {
         name: 'duedate',
@@ -64,8 +63,6 @@ const columns = computed(() => [
     },
 ]);
 
-const totalAmount = computed(() => getTotal(invoiceInFormRef.value.formData, 'amount'));
-
 const isNotEuro = (code) => code != 'EUR';
 
 async function insert() {
@@ -73,10 +70,6 @@ async function insert() {
     await invoiceInFormRef.value.reload();
     notify(t('globals.dataSaved'), 'positive');
 }
-
-onBeforeMount(async () => {
-    totals.value = (await axios.get(`InvoiceIns/${invoiceId}/getTotals`)).data;
-});
 </script>
 <template>
     <CrudModel
@@ -151,7 +144,7 @@ onBeforeMount(async () => {
                         <QTd />
                         <QTd />
                         <QTd>
-                            {{ toCurrency(totalAmount) }}
+                            {{ getTotal(rows, 'amount', { currency: 'default' }) }}
                         </QTd>
                         <QTd>
                             <template v-if="isNotEuro(invoiceIn.currency.code)">
@@ -229,19 +222,10 @@ onBeforeMount(async () => {
         <QBtn
             color="primary"
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
             size="lg"
             round
-            @click="
-                () => {
-                    if (!areRows) insert();
-                    else
-                        invoiceInFormRef.insert({
-                            amount: (totals.totalTaxableBase - totalAmount).toFixed(2),
-                            invoiceInFk: invoiceId,
-                        });
-                }
-            "
+            @click="!areRows ? insert() : invoiceInFormRef.insert()"
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInFilter.js b/src/pages/InvoiceIn/Card/InvoiceInFilter.js
deleted file mode 100644
index 6df8b5830..000000000
--- a/src/pages/InvoiceIn/Card/InvoiceInFilter.js
+++ /dev/null
@@ -1,33 +0,0 @@
-export default {
-    include: [
-        {
-            relation: 'supplier',
-            scope: {
-                include: {
-                    relation: 'contacts',
-                    scope: { where: { email: { neq: null } } },
-                },
-            },
-        },
-        { relation: 'invoiceInDueDay' },
-        { relation: 'company' },
-        { relation: 'currency' },
-        {
-            relation: 'dms',
-            scope: {
-                fields: [
-                    'dmsTypeFk',
-                    'reference',
-                    'hardCopyNumber',
-                    'workerFk',
-                    'description',
-                    'hasFile',
-                    'file',
-                    'created',
-                    'companyFk',
-                    'warehouseFk',
-                ],
-            },
-        },
-    ],
-};
diff --git a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
index 6f8642313..e529ea6cd 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
@@ -218,7 +218,7 @@ const columns = computed(() => [
         <QBtn
             color="primary"
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
             size="lg"
             round
             @click="invoiceInFormRef.insert()"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index d358601d3..e546638f2 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -193,7 +193,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             <InvoiceIntoBook>
                 <template #content="{ book }">
                     <QBtn
-                        :label="t('Book')"
+                        :label="t('To book')"
                         color="orange-11"
                         text-color="black"
                         @click="book(entityId)"
@@ -224,7 +224,10 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                         </span>
                     </template>
                 </VnLv>
-                <VnLv :label="t('invoiceIn.supplierRef')" :value="entity.supplierRef" />
+                <VnLv
+                    :label="t('invoiceIn.list.supplierRef')"
+                    :value="entity.supplierRef"
+                />
                 <VnLv
                     :label="t('invoiceIn.summary.currency')"
                     :value="entity.currency?.code"
@@ -354,7 +357,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                 entity.totals.totalTaxableBaseForeignValue &&
                                 toCurrency(
                                     entity.totals.totalTaxableBaseForeignValue,
-                                    currency,
+                                    currency
                                 )
                             }}</QTd>
                         </QTr>
@@ -389,7 +392,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                     entity.totals.totalDueDayForeignValue &&
                                     toCurrency(
                                         entity.totals.totalDueDayForeignValue,
-                                        currency,
+                                        currency
                                     )
                                 }}
                             </QTd>
@@ -469,5 +472,5 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
         Search invoice: Buscar factura recibida
         You can search by invoice reference: Puedes buscar por referencia de la factura
         Totals: Totales
-        Book: Contabilizar
+        To book: Contabilizar
 </i18n>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInVat.vue b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
index e77453bc0..f99e060b8 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInVat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed, nextTick } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useArrayData } from 'src/composables/useArrayData';
@@ -25,6 +25,7 @@ const sageTaxTypes = ref([]);
 const sageTransactionTypes = ref([]);
 const rowsSelected = ref([]);
 const invoiceInFormRef = ref();
+const expenseRef = ref();
 
 defineProps({
     actionIcon: {
@@ -96,20 +97,6 @@ const columns = computed(() => [
     },
 ]);
 
-const taxableBaseTotal = computed(() => {
-    return getTotal(invoiceInFormRef.value.formData, 'taxableBase');
-});
-
-const taxRateTotal = computed(() => {
-    return getTotal(invoiceInFormRef.value.formData, null, {
-        cb: taxRate,
-    });
-});
-
-const combinedTotal = computed(() => {
-    return +taxableBaseTotal.value + +taxRateTotal.value;
-});
-
 const filter = {
     fields: [
         'id',
@@ -130,7 +117,7 @@ const isNotEuro = (code) => code != 'EUR';
 function taxRate(invoiceInTax) {
     const sageTaxTypeId = invoiceInTax.taxTypeSageFk;
     const taxRateSelection = sageTaxTypes.value.find(
-        (transaction) => transaction.id == sageTaxTypeId,
+        (transaction) => transaction.id == sageTaxTypeId
     );
     const taxTypeSage = taxRateSelection?.rate ?? 0;
     const taxableBase = invoiceInTax?.taxableBase ?? 0;
@@ -138,26 +125,35 @@ function taxRate(invoiceInTax) {
     return ((taxTypeSage / 100) * taxableBase).toFixed(2);
 }
 
-function autocompleteExpense(evt, row, col, ref) {
+function autocompleteExpense(evt, row, col) {
     const val = evt.target.value;
     if (!val) return;
 
     const param = isNaN(val) ? row[col.model] : val;
     const lookup = expenses.value.find(
-        ({ id }) => id == useAccountShortToStandard(param),
+        ({ id }) => id == useAccountShortToStandard(param)
     );
 
-    ref.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
+    expenseRef.value.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
 }
 
-function setCursor(ref) {
-    nextTick(() => {
-        const select = ref.vnSelectDialogRef
-            ? ref.vnSelectDialogRef.vnSelectRef
-            : ref.vnSelectRef;
-        select.$el.querySelector('input').setSelectionRange(0, 0);
+const taxableBaseTotal = computed(() => {   
+    return getTotal(invoiceInFormRef.value.formData, 'taxableBase', );
+});
+
+const taxRateTotal = computed(() => {
+    return getTotal(invoiceInFormRef.value.formData, null, {
+        cb: taxRate,
     });
-}
+});
+
+
+const combinedTotal = computed(() => {
+    return +taxableBaseTotal.value + +taxRateTotal.value;
+});
+
+
+
 </script>
 <template>
     <FetchData
@@ -195,24 +191,14 @@ function setCursor(ref) {
                 <template #body-cell-expense="{ row, col }">
                     <QTd>
                         <VnSelectDialog
-                            :ref="`expenseRef-${row.$index}`"
+                            ref="expenseRef"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'name']"
                             :tooltip="t('Create a new expense')"
-                            @keydown.tab="
-                                autocompleteExpense(
-                                    $event,
-                                    row,
-                                    col,
-                                    $refs[`expenseRef-${row.$index}`],
-                                )
-                            "
-                            @update:model-value="
-                                setCursor($refs[`expenseRef-${row.$index}`])
-                            "
+                            @keydown.tab="autocompleteExpense($event, row, col)"
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -228,7 +214,7 @@ function setCursor(ref) {
                     </QTd>
                 </template>
                 <template #body-cell-taxablebase="{ row }">
-                    <QTd shrink>
+                    <QTd>
                         <VnInputNumber
                             clear-icon="close"
                             v-model="row.taxableBase"
@@ -239,16 +225,12 @@ function setCursor(ref) {
                 <template #body-cell-sageiva="{ row, col }">
                     <QTd>
                         <VnSelect
-                            :ref="`sageivaRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'vat']"
                             data-cy="vat-sageiva"
-                            @update:model-value="
-                                setCursor($refs[`sageivaRef-${row.$index}`])
-                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -266,15 +248,11 @@ function setCursor(ref) {
                 <template #body-cell-sagetransaction="{ row, col }">
                     <QTd>
                         <VnSelect
-                            :ref="`sagetransactionRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'transaction']"
-                            @update:model-value="
-                                setCursor($refs[`sagetransactionRef-${row.$index}`])
-                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -292,7 +270,7 @@ function setCursor(ref) {
                     </QTd>
                 </template>
                 <template #body-cell-foreignvalue="{ row }">
-                    <QTd shrink>
+                    <QTd>
                         <VnInputNumber
                             :class="{
                                 'no-pointer-events': !isNotEuro(currency),
@@ -305,7 +283,7 @@ function setCursor(ref) {
                                     row.taxableBase = await getExchange(
                                         val,
                                         row.currencyFk,
-                                        invoiceIn.issued,
+                                        invoiceIn.issued
                                     );
                                 }
                             "
@@ -448,7 +426,7 @@ function setCursor(ref) {
             color="primary"
             icon="add"
             size="lg"
-            v-shortcut="'+'"
+            shortcut="+"
             round
             @click="invoiceInFormRef.insert()"
         >
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index 0960d0d6c..e1723e3b1 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -29,7 +29,6 @@ const cols = computed(() => [
         name: 'isBooked',
         label: t('invoiceIn.isBooked'),
         columnFilter: false,
-        component: 'checkbox',
     },
     {
         align: 'left',
@@ -57,7 +56,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'supplierRef',
-        label: t('invoiceIn.supplierRef'),
+        label: t('invoiceIn.list.supplierRef'),
     },
     {
         align: 'left',
@@ -178,7 +177,7 @@ const cols = computed(() => [
                         :required="true"
                     />
                     <VnInput
-                        :label="t('invoiceIn.supplierRef')"
+                        :label="t('invoiceIn.list.supplierRef')"
                         v-model="data.supplierRef"
                     />
                     <VnSelect
diff --git a/src/pages/InvoiceIn/InvoiceInToBook.vue b/src/pages/InvoiceIn/InvoiceInToBook.vue
index 5bdbe197b..95ce8155a 100644
--- a/src/pages/InvoiceIn/InvoiceInToBook.vue
+++ b/src/pages/InvoiceIn/InvoiceInToBook.vue
@@ -4,7 +4,6 @@ import { useQuasar } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import { useArrayData } from 'src/composables/useArrayData';
-import qs from 'qs';
 const { notify, dialog } = useQuasar();
 const { t } = useI18n();
 
@@ -13,51 +12,29 @@ defineExpose({ checkToBook });
 const { store } = useArrayData();
 
 async function checkToBook(id) {
-    let messages = [];
-
-    const hasProblemWithTax = (
-        await axios.get('InvoiceInTaxes/count', {
-            params: {
-                where: JSON.stringify({
-                    invoiceInFk: id,
-                    or: [{ taxTypeSageFk: null }, { transactionTypeSageFk: null }],
-                }),
-            },
-        })
-    ).data?.count;
-
-    if (hasProblemWithTax)
-        messages.push(t('The VAT and Transaction fields have not been informed'));
+    let directBooking = true;
 
     const { data: totals } = await axios.get(`InvoiceIns/${id}/getTotals`);
     const taxableBaseNotEqualDueDay = totals.totalDueDay != totals.totalTaxableBase;
     const vatNotEqualDueDay = totals.totalDueDay != totals.totalVat;
 
-    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay)
-        messages.push(t('The sum of the taxable bases does not match the due dates'));
+    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay) directBooking = false;
 
-    const dueDaysCount = (
-        await axios.get('InvoiceInDueDays/count', {
-            params: {
-                where: JSON.stringify({
-                    invoiceInFk: id,
-                    dueDated: { gte: Date.vnNew() },
-                }),
-            },
-        })
-    ).data?.count;
+    const { data: dueDaysCount } = await axios.get('InvoiceInDueDays/count', {
+        where: {
+            invoiceInFk: id,
+            dueDated: { gte: Date.vnNew() },
+        },
+    });
 
-    if (dueDaysCount) messages.push(t('Some due dates are less than or equal to today'));
+    if (dueDaysCount) directBooking = false;
 
-    if (!messages.length) toBook(id);
-    else
-        dialog({
-            component: VnConfirm,
-            componentProps: {
-                title: t('Are you sure you want to book this invoice?'),
-                message: messages.reduce((acc, msg) => `${acc}<p>${msg}</p>`, ''),
-            },
-        }).onOk(() => toBook(id));
+    if (directBooking) return toBook(id);
+
+    dialog({
+        component: VnConfirm,
+        componentProps: { title: t('Are you sure you want to book this invoice?') },
+    }).onOk(async () => await toBook(id));
 }
 
 async function toBook(id) {
@@ -82,7 +59,4 @@ async function toBook(id) {
 es:
     Are you sure you want to book this invoice?: ¿Estás seguro de querer asentar esta factura?
     It was not able to book the invoice: No se pudo contabilizar la factura
-    Some due dates are less than or equal to today: Algún vencimiento tiene una fecha menor o igual que hoy
-    The sum of the taxable bases does not match the due dates: La suma de las bases imponibles no coincide con la de los vencimientos
-    The VAT and Transaction fields have not been informed: No se han informado los campos de iva y/o transacción
 </i18n>
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index 548e6c201..6b21b316b 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Search incoming invoices by ID or supplier fiscal name
     serial: Serial
     isBooked: Is booked
-    supplierRef: Invoice nº
     list:
         ref: Reference
         supplier: Supplier
+        supplierRef: Supplier ref.
         file: File
         issued: Issued
         dueDated: Due dated
@@ -19,6 +19,8 @@ invoiceIn:
         unbook: Unbook
         delete: Delete
         clone: Clone
+        toBook: To book
+        toUnbook: To unbook
         deleteInvoice: Delete invoice
         invoiceDeleted: invoice deleted
         cloneInvoice: Clone invoice
@@ -68,3 +70,4 @@ invoiceIn:
         isBooked: Is booked
         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 142d95f92..3f27c895c 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
     serial: Serie
     isBooked: Contabilizada
-    supplierRef: Nº factura
     list:
         ref: Referencia
         supplier: Proveedor
+        supplierRef: Ref. proveedor
         issued: F. emisión
         dueDated: F. vencimiento
         file: Fichero
@@ -15,10 +15,12 @@ invoiceIn:
     descriptor:
         ticketList: Listado de tickets
     descriptorMenu:
-        book: Contabilizar
-        unbook: Descontabilizar
+        book: Asentar
+        unbook: Desasentar
         delete: Eliminar
         clone: Clonar
+        toBook: Contabilizar
+        toUnbook: Descontabilizar
         deleteInvoice: Eliminar factura
         invoiceDeleted: Factura eliminada
         cloneInvoice: Clonar factura
@@ -66,3 +68,4 @@ invoiceIn:
         isBooked: Contabilizada
         account: Cuenta contable
         correctingFk: Rectificativa
+
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
index a50c9d247..93e3fe042 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
@@ -1,13 +1,11 @@
 <script setup>
 import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import filter from './InvoiceOutFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="InvoiceOut"
-        url="InvoiceOuts"
-        :filter="filter"
+        base-url="InvoiceOuts"
         :descriptor="InvoiceOutDescriptor"
     />
 </template>
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
index dfaf6c109..209f1531e 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
@@ -8,8 +8,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import VnLv from 'src/components/ui/VnLv.vue';
 import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
 
+import useCardDescription from 'src/composables/useCardDescription';
 import { toCurrency, toDate } from 'src/filters';
-import filter from './InvoiceOutFilter.js';
 
 const $props = defineProps({
     id: {
@@ -26,20 +26,42 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
+const filter = {
+    include: [
+        {
+            relation: 'company',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'name', 'email'],
+            },
+        },
+    ],
+};
+
 const descriptor = ref();
 
 function ticketFilter(invoice) {
     return JSON.stringify({ refFk: invoice.ref });
 }
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.id));
 </script>
 
 <template>
     <CardDescriptor
         ref="descriptor"
+        module="InvoiceOut"
         :url="`InvoiceOuts/${entityId}`"
         :filter="filter"
-        title="ref"
-        data-key="InvoiceOut"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        @on-fetch="setData"
+        data-key="invoiceOutData"
         width="lg-width"
     >
         <template #menu="{ entity, menuRef }">
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutFilter.js b/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
deleted file mode 100644
index 48b20faf6..000000000
--- a/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export default {
-    include: [
-        {
-            relation: 'company',
-            scope: {
-                fields: ['id', 'code'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'name', 'email'],
-            },
-        },
-    ],
-};
diff --git a/src/pages/Item/components/CreateGenusForm.vue b/src/pages/Item/Card/CreateGenusForm.vue
similarity index 100%
rename from src/pages/Item/components/CreateGenusForm.vue
rename to src/pages/Item/Card/CreateGenusForm.vue
diff --git a/src/pages/Item/components/CreateSpecieForm.vue b/src/pages/Item/Card/CreateSpecieForm.vue
similarity index 100%
rename from src/pages/Item/components/CreateSpecieForm.vue
rename to src/pages/Item/Card/CreateSpecieForm.vue
diff --git a/src/pages/Item/Card/ItemBarcode.vue b/src/pages/Item/Card/ItemBarcode.vue
index 590b524cd..6db5943c7 100644
--- a/src/pages/Item/Card/ItemBarcode.vue
+++ b/src/pages/Item/Card/ItemBarcode.vue
@@ -92,7 +92,7 @@ const submit = async (rows) => {
                             class="cursor-pointer fill-icon-on-hover"
                             color="primary"
                             icon="add_circle"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             flat
                         >
                             <QTooltip>
diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index df7e71684..4c96401f3 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -11,7 +11,6 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
 import FilterItemForm from 'src/components/FilterItemForm.vue';
 import CreateIntrastatForm from './CreateIntrastatForm.vue';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -55,8 +54,9 @@ const onIntrastatCreated = (response, formData) => {
         auto-load
     />
     <FormModel
+        :url="`Items/${route.params.id}`"
         :url-update="`Items/${route.params.id}`"
-        model="Item"
+        model="item"
         auto-load
         :clear-store-on-unmount="false"
     >
@@ -209,20 +209,30 @@ const onIntrastatCreated = (response, formData) => {
                 />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <VnCheckbox
-                    v-model="data.isFragile"
-                    :label="t('item.basicData.isFragile')"
-                    :info="t('item.basicData.isFragileTooltip')"
-                    class="q-mr-sm"
-                    size="xs"
-                />
-                <VnCheckbox
-                    v-model="data.isPhotoRequested"
-                    :label="t('item.basicData.isPhotoRequested')"
-                    :info="t('item.basicData.isPhotoRequestedTooltip')"
-                    class="q-mr-sm"
-                    size="xs"
-                />
+                <div>
+                    <QCheckbox
+                        v-model="data.isFragile"
+                        :label="t('item.basicData.isFragile')"
+                        class="q-mr-sm"
+                    />
+                    <QIcon name="info" class="cursor-pointer" size="xs">
+                        <QTooltip max-width="300px">
+                            {{ t('item.basicData.isFragileTooltip') }}
+                        </QTooltip>
+                    </QIcon>
+                </div>
+                <div>
+                    <QCheckbox
+                        v-model="data.isPhotoRequested"
+                        :label="t('item.basicData.isPhotoRequested')"
+                        class="q-mr-sm"
+                    />
+                    <QIcon name="info" class="cursor-pointer" size="xs">
+                        <QTooltip>
+                            {{ t('item.basicData.isPhotoRequestedTooltip') }}
+                        </QTooltip>
+                    </QIcon>
+                </div>
             </VnRow>
             <VnRow>
                 <VnInput
diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index a40d81589..4894d94fc 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -7,8 +7,8 @@ import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
-import CreateGenusForm from '../components/CreateGenusForm.vue';
-import CreateSpecieForm from '../components/CreateSpecieForm.vue';
+import CreateGenusForm from './CreateGenusForm.vue';
+import CreateSpecieForm from './CreateSpecieForm.vue';
 
 const route = useRoute();
 const { t } = useI18n();
diff --git a/src/pages/Item/Card/ItemCard.vue b/src/pages/Item/Card/ItemCard.vue
index 610b77a02..2546982eb 100644
--- a/src/pages/Item/Card/ItemCard.vue
+++ b/src/pages/Item/Card/ItemCard.vue
@@ -5,7 +5,7 @@ import ItemDescriptor from './ItemDescriptor.vue';
 <template>
     <VnCardBeta
         data-key="Item"
-        :url="`Items/${$route.params.id}/getCard`"
+        base-url="Items"
         :descriptor="ItemDescriptor"
     />
 </template>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index a4c58ef4b..c6fee8540 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -7,6 +7,7 @@ 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 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';
@@ -34,10 +35,6 @@ const $props = defineProps({
         type: Number,
         default: null,
     },
-    proxyRender: {
-        type: Boolean,
-        default: false,
-    },
 });
 
 const route = useRoute();
@@ -58,8 +55,10 @@ onMounted(async () => {
     mounted.value = true;
 });
 
+const data = ref(useCardDescription());
 const setData = async (entity) => {
     if (!entity) return;
+    data.value = useCardDescription(entity.name, entity.id);
     await updateStock();
 };
 
@@ -91,7 +90,10 @@ const updateStock = async () => {
 
 <template>
     <CardDescriptor
-        data-key="Item"
+        data-key="ItemData"
+        module="Item"
+        :title="data.title"
+        :subtitle="data.subtitle"
         :summary="$props.summary"
         :url="`Items/${entityId}/getCard`"
         @on-fetch="setData"
@@ -115,7 +117,7 @@ const updateStock = async () => {
                 <template #value>
                     <span class="link">
                         {{ entity.itemType?.worker?.user?.name }}
-                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id ?? NaN" />
+                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id" />
                     </span>
                 </template>
             </VnLv>
@@ -150,7 +152,7 @@ const updateStock = async () => {
             </QCardActions>
         </template>
         <template #actions="{}">
-            <QCardActions class="row justify-center" v-if="proxyRender">
+            <QCardActions class="row justify-center">
                 <QBtn
                     :to="{
                         name: 'ItemDiary',
@@ -163,16 +165,6 @@ const updateStock = async () => {
                 >
                     <QTooltip>{{ t('item.descriptor.itemDiary') }}</QTooltip>
                 </QBtn>
-                <QBtn
-                    :to="{
-                        name: 'ItemLastEntries',
-                    }"
-                    size="md"
-                    icon="vn:regentry"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('item.descriptor.itemLastEntries') }}</QTooltip>
-                </QBtn>
             </QCardActions>
         </template>
     </CardDescriptor>
diff --git a/src/pages/Item/Card/ItemDescriptorProxy.vue b/src/pages/Item/Card/ItemDescriptorProxy.vue
index f686e8221..2ffc9080f 100644
--- a/src/pages/Item/Card/ItemDescriptorProxy.vue
+++ b/src/pages/Item/Card/ItemDescriptorProxy.vue
@@ -4,7 +4,7 @@ import ItemSummary from './ItemSummary.vue';
 
 const $props = defineProps({
     id: {
-        type: [Number, String],
+        type: Number,
         required: true,
     },
     dated: {
@@ -21,8 +21,9 @@ const $props = defineProps({
     },
 });
 </script>
+
 <template>
-    <QPopupProxy style="max-width: 10px">
+    <QPopupProxy>
         <ItemDescriptor
             v-if="$props.id"
             :id="$props.id"
@@ -30,7 +31,6 @@ const $props = defineProps({
             :dated="dated"
             :sale-fk="saleFk"
             :warehouse-fk="warehouseFk"
-            :proxy-render="true"
         />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Item/Card/ItemShelving.vue b/src/pages/Item/Card/ItemShelving.vue
index b29e2a2a5..7ad60c9e0 100644
--- a/src/pages/Item/Card/ItemShelving.vue
+++ b/src/pages/Item/Card/ItemShelving.vue
@@ -110,16 +110,10 @@ const columns = computed(() => [
         attrs: { inWhere: true },
         align: 'left',
     },
-    {
-        label: t('globals.visible'),
-        name: 'stock',
-        attrs: { inWhere: true },
-        align: 'left',
-    },
 ]);
 
 const totalLabels = computed(() =>
-    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2),
+    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2)
 );
 
 const removeLines = async () => {
@@ -163,7 +157,7 @@ watchEffect(selectedRows);
                     openConfirmationModal(
                         t('shelvings.removeConfirmTitle'),
                         t('shelvings.removeConfirmSubtitle'),
-                        removeLines,
+                        removeLines
                     )
                 "
             >
diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index ab26b9cae..5a7d7f818 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -178,7 +178,7 @@ const insertTag = (rows) => {
                             @click="insertTag(rows)"
                             color="primary"
                             icon="add"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             fab
                             data-cy="createNewTag"
                         >
diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index fdfa1d3d1..1c4382fbd 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -65,19 +65,10 @@ const columns = computed(() => [
         name: 'name',
         ...defaultColumnAttrs,
         create: true,
-        columnFilter: {
-            component: 'select',
-            attrs: {
-                url: 'Items',
-                fields: ['id', 'name', 'subName'],
-                optionLabel: 'name',
-                optionValue: 'name',
-                uppercase: false,
-            },
-        },
     },
     {
         label: t('item.fixedPrice.groupingPrice'),
+        field: 'rate2',
         name: 'rate2',
         ...defaultColumnAttrs,
         component: 'input',
@@ -85,6 +76,7 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.packingPrice'),
+        field: 'rate3',
         name: 'rate3',
         ...defaultColumnAttrs,
         component: 'input',
@@ -93,6 +85,7 @@ const columns = computed(() => [
 
     {
         label: t('item.fixedPrice.minPrice'),
+        field: 'minPrice',
         name: 'minPrice',
         ...defaultColumnAttrs,
         component: 'input',
@@ -115,6 +108,7 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.ended'),
+        field: 'ended',
         name: 'ended',
         ...defaultColumnAttrs,
         columnField: {
@@ -130,6 +124,7 @@ const columns = computed(() => [
 
     {
         label: t('globals.warehouse'),
+        field: 'warehouseFk',
         name: 'warehouseFk',
         ...defaultColumnAttrs,
         columnClass: 'shrink',
@@ -420,6 +415,7 @@ function handleOnDataSave({ CrudModelRef }) {
             'row-key': 'id',
             selection: 'multiple',
         }"
+        :use-model="true"
         v-model:selected="rowsSelected"
         :create-as-dialog="false"
         :create="{
diff --git a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
index 475dffd8b..b4032ff8a 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
@@ -40,7 +40,12 @@ const itemPackingTypesOptions = ref([]);
         }"
         auto-load
     />
-    <FormModel :url-update="`ItemTypes/${route.params.id}`" model="ItemType" auto-load>
+    <FormModel
+        :url="`ItemTypes/${route.params.id}`"
+        :url-update="`ItemTypes/${route.params.id}`"
+        model="itemTypeBasicData"
+        auto-load
+    >
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.code" :label="t('itemType.shared.code')" />
diff --git a/src/pages/Item/ItemType/Card/ItemTypeCard.vue b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
index 84e810de5..fa51e428e 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeCard.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
@@ -1,14 +1,12 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ItemTypeDescriptor from 'src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue';
-import filter from './ItemTypeFilter.js';
 </script>
 
 <template>
     <VnCardBeta
-        data-key="ItemType"
-        url="ItemTypes"
-        :filter="filter"
+        data-key="ItemTypeSummary"
+        base-url="ItemTypes"
         :descriptor="ItemTypeDescriptor"
     />
 </template>
diff --git a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
index 725fb30aa..09d3dbce5 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
@@ -1,11 +1,12 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } 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 WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import filter from './ItemTypeFilter.js';
+import useCardDescription from 'src/composables/useCardDescription';
 
 const $props = defineProps({
     id: {
@@ -19,31 +20,46 @@ const $props = defineProps({
 });
 
 const route = useRoute();
+const { t } = useI18n();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
+
+const itemTypeFilter = {
+    include: [
+        { relation: 'worker' },
+        { relation: 'category' },
+        { relation: 'itemPackingType' },
+        { relation: 'temperature' },
+    ],
+};
+
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
+
 <template>
     <CardDescriptor
+        module="ItemType"
         :url="`ItemTypes/${entityId}`"
-        :filter="filter"
-        title="code"
-        data-key="ItemType"
+        :filter="itemTypeFilter"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        data-key="itemTypeDescriptor"
+        @on-fetch="setData"
     >
         <template #body="{ entity }">
-            <VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
-            <VnLv :label="$t('itemType.shared.name')" :value="entity.name" />
-            <VnLv :label="$t('itemType.shared.worker')">
+            <VnLv :label="t('itemType.shared.code')" :value="entity.code" />
+            <VnLv :label="t('itemType.shared.name')" :value="entity.name" />
+            <VnLv :label="t('itemType.shared.worker')">
                 <template #value>
                     <span class="link">{{ entity.worker?.firstName }}</span>
                     <WorkerDescriptorProxy :id="entity.worker?.id" />
                 </template>
             </VnLv>
-            <VnLv
-                :label="$t('itemType.shared.category')"
-                :value="entity.category?.name"
-            />
+            <VnLv :label="t('itemType.shared.category')" :value="entity.category?.name" />
         </template>
     </CardDescriptor>
 </template>
+
diff --git a/src/pages/Item/ItemType/Card/ItemTypeFilter.js b/src/pages/Item/ItemType/Card/ItemTypeFilter.js
deleted file mode 100644
index 5651d368d..000000000
--- a/src/pages/Item/ItemType/Card/ItemTypeFilter.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
-    include: [
-        { relation: 'worker' },
-        { relation: 'category' },
-        { relation: 'itemPackingType' },
-        { relation: 'temperature' },
-    ],
-};
diff --git a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
index 3b63c4b63..9ba774ca4 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
@@ -3,7 +3,7 @@ import { ref, computed, onUpdated } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import filter from './ItemTypeFilter.js';
+
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
@@ -21,6 +21,15 @@ const $props = defineProps({
     },
 });
 
+const itemTypeFilter = {
+    include: [
+        { relation: 'worker' },
+        { relation: 'category' },
+        { relation: 'itemPackingType' },
+        { relation: 'temperature' },
+    ],
+};
+
 const entityId = computed(() => $props.id || route.params.id);
 const summaryRef = ref();
 const itemType = ref();
@@ -34,8 +43,8 @@ async function setItemTypeData(data) {
     <CardSummary
         ref="summaryRef"
         :url="`ItemTypes/${entityId}`"
-        data-key="ItemType"
-        :filter="filter"
+        data-key="ItemTypeSummary"
+        :filter="itemTypeFilter"
         @on-fetch="(data) => setItemTypeData(data)"
         class="full-width"
     >
diff --git a/src/pages/Item/components/ItemProposal.vue b/src/pages/Item/components/ItemProposal.vue
deleted file mode 100644
index d2dbea7b3..000000000
--- a/src/pages/Item/components/ItemProposal.vue
+++ /dev/null
@@ -1,332 +0,0 @@
-<script setup>
-import { ref, computed } from 'vue';
-import { useI18n } from 'vue-i18n';
-import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import { toCurrency } from 'filters/index';
-import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
-import VnTable from 'src/components/VnTable/VnTable.vue';
-import axios from 'axios';
-import notifyResults from 'src/utils/notifyResults';
-import FetchData from 'components/FetchData.vue';
-
-const MATCH = 'match';
-
-const { t } = useI18n();
-const $props = defineProps({
-    itemLack: {
-        type: Object,
-        required: true,
-        default: () => {},
-    },
-    replaceAction: {
-        type: Boolean,
-        required: false,
-        default: false,
-    },
-    sales: {
-        type: Array,
-        required: false,
-        default: () => [],
-    },
-});
-const proposalSelected = ref([]);
-const ticketConfig = ref({});
-const proposalTableRef = ref(null);
-
-const sale = computed(() => $props.sales[0]);
-const saleFk = computed(() => sale.value.saleFk);
-const filter = computed(() => ({
-    itemFk: $props.itemLack.itemFk,
-    sales: saleFk.value,
-}));
-
-const defaultColumnAttrs = {
-    align: 'center',
-    sortable: false,
-};
-const emit = defineEmits(['onDialogClosed', 'itemReplaced']);
-
-const conditionalValuePrice = (price) =>
-    price > 1 + ticketConfig.value.lackAlertPrice / 100 ? 'match' : 'not-match';
-
-const columns = computed(() => [
-    {
-        ...defaultColumnAttrs,
-        label: t('proposal.available'),
-        name: 'available',
-        field: 'available',
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-        columnClass: 'shrink',
-    },
-    {
-        ...defaultColumnAttrs,
-        label: t('proposal.counter'),
-        name: 'counter',
-        field: 'counter',
-        columnClass: 'shrink',
-        style: 'max-width: 75px',
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-    },
-
-    {
-        align: 'left',
-        sortable: true,
-        label: t('proposal.longName'),
-        name: 'longName',
-        field: 'longName',
-        columnClass: 'expand',
-    },
-    {
-        align: 'left',
-        sortable: true,
-        label: t('item.list.color'),
-        name: 'tag5',
-        field: 'value5',
-        columnClass: 'expand',
-    },
-    {
-        align: 'left',
-        sortable: true,
-        label: t('item.list.stems'),
-        name: 'tag6',
-        field: 'value6',
-        columnClass: 'expand',
-    },
-    {
-        align: 'left',
-        sortable: true,
-        label: t('item.list.producer'),
-        name: 'tag7',
-        field: 'value7',
-        columnClass: 'expand',
-    },
-
-    {
-        ...defaultColumnAttrs,
-        label: t('proposal.price2'),
-        name: 'price2',
-        style: 'max-width: 75px',
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-    },
-    {
-        ...defaultColumnAttrs,
-        label: t('proposal.minQuantity'),
-        name: 'minQuantity',
-        field: 'minQuantity',
-        style: 'max-width: 75px',
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-    },
-    {
-        ...defaultColumnAttrs,
-        label: t('proposal.located'),
-        name: 'located',
-        field: 'located',
-    },
-    {
-        align: 'right',
-        label: '',
-        name: 'tableActions',
-        actions: [
-            {
-                title: t('Replace'),
-                icon: 'change_circle',
-                show: (row) => isSelectionAvailable(row),
-                action: change,
-                isPrimary: true,
-            },
-        ],
-    },
-]);
-
-function extractMatchValues(obj) {
-    return Object.keys(obj)
-        .filter((key) => key.startsWith(MATCH))
-        .map((key) => parseInt(key.replace(MATCH, ''), 10));
-}
-const gradientStyle = (value) => {
-    let color = 'white';
-    const perc = parseFloat(value);
-    switch (true) {
-        case perc >= 0 && perc < 33:
-            color = 'primary';
-            break;
-        case perc >= 33 && perc < 66:
-            color = 'warning';
-            break;
-
-        default:
-            color = 'secondary';
-            break;
-    }
-    return color;
-};
-const statusConditionalValue = (row) => {
-    const matches = extractMatchValues(row);
-    const value = matches.reduce((acc, i) => acc + row[`${MATCH}${i}`], 0);
-    return 100 * (value / matches.length);
-};
-
-const isSelectionAvailable = (itemProposal) => {
-    const { price2 } = itemProposal;
-    const salePrice = sale.value.price;
-    const byPrice = (100 * price2) / salePrice > ticketConfig.value.lackAlertPrice;
-    if (byPrice) {
-        return byPrice;
-    }
-    const byQuantity =
-        (100 * itemProposal.available) / Math.abs($props.itemLack.lack) <
-        ticketConfig.value.lackAlertPrice;
-    return byQuantity;
-};
-
-async function change({ itemFk: substitutionFk }) {
-    try {
-        const promises = $props.sales.map(({ saleFk, quantity }) => {
-            const params = {
-                saleFk,
-                substitutionFk,
-                quantity,
-            };
-            return axios.post('Sales/replaceItem', params);
-        });
-        const results = await Promise.allSettled(promises);
-
-        notifyResults(results, 'saleFk');
-        emit('itemReplaced', {
-            type: 'refresh',
-            quantity: quantity.value,
-            itemProposal: proposalSelected.value[0],
-        });
-        proposalSelected.value = [];
-    } catch (error) {
-        console.error(error);
-    }
-}
-
-async function handleTicketConfig(data) {
-    ticketConfig.value = data[0];
-}
-</script>
-<template>
-    <FetchData
-        url="TicketConfigs"
-        :filter="{ fields: ['lackAlertPrice'] }"
-        @on-fetch="handleTicketConfig"
-        auto-load
-    />
-
-    <VnTable
-        v-if="ticketConfig"
-        auto-load
-        data-cy="proposalTable"
-        ref="proposalTableRef"
-        data-key="ItemsGetSimilar"
-        url="Items/getSimilar"
-        :user-filter="filter"
-        :columns="columns"
-        class="full-width q-mt-md"
-        row-key="id"
-        :row-click="change"
-        :is-editable="false"
-        :right-search="false"
-        :without-header="true"
-        :disable-option="{ card: true, table: true }"
-    >
-        <template #column-longName="{ row }">
-            <QTd
-                class="flex"
-                style="max-width: 100%; flex-shrink: 50px; flex-wrap: nowrap"
-            >
-                <div
-                    class="middle full-width"
-                    :class="[`proposal-${gradientStyle(statusConditionalValue(row))}`]"
-                >
-                    <QTooltip> {{ statusConditionalValue(row) }}% </QTooltip>
-                </div>
-                <div style="flex: 2 0 100%; align-content: center">
-                    <div>
-                        <span class="link">{{ row.longName }}</span>
-                        <ItemDescriptorProxy :id="row.id" />
-                    </div>
-                </div>
-            </QTd>
-        </template>
-        <template #column-tag5="{ row }">
-            <span :class="{ match: !row.match5 }">{{ row.value5 }}</span>
-        </template>
-        <template #column-tag6="{ row }">
-            <span :class="{ match: !row.match6 }">{{ row.value6 }}</span>
-        </template>
-        <template #column-tag7="{ row }">
-            <span :class="{ match: !row.match7 }">{{ row.value7 }}</span>
-        </template>
-        <template #column-counter="{ row }">
-            <span
-                :class="{
-                    match: row.counter === 1,
-                    'not-match': row.counter !== 1,
-                }"
-                >{{ row.counter }}</span
-            >
-        </template>
-        <template #column-minQuantity="{ row }">
-            {{ row.minQuantity }}
-        </template>
-        <template #column-price2="{ row }">
-            <div class="flex column items-center content-center">
-                <VnStockValueDisplay :value="(sales[0].price - row.price2) / 100" />
-                <span :class="[conditionalValuePrice(row.price2)]">{{
-                    toCurrency(row.price2)
-                }}</span>
-            </div>
-        </template>
-    </VnTable>
-</template>
-<style lang="scss" scoped>
-@import 'src/css/quasar.variables.scss';
-.middle {
-    float: left;
-    margin-right: 2px;
-    flex: 2 0 5px;
-}
-.match {
-    color: $negative;
-}
-.not-match {
-    color: inherit;
-}
-.proposal-warning {
-    background-color: $warning;
-}
-.proposal-secondary {
-    background-color: $secondary;
-}
-.proposal-primary {
-    background-color: $primary;
-}
-.text {
-    margin: 0.05rem;
-    padding: 1px;
-    border: 1px solid var(--vn-label-color);
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    font-size: smaller;
-}
-</style>
diff --git a/src/pages/Item/components/ItemProposalProxy.vue b/src/pages/Item/components/ItemProposalProxy.vue
deleted file mode 100644
index 7da0ce398..000000000
--- a/src/pages/Item/components/ItemProposalProxy.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<script setup>
-import ItemProposal from './ItemProposal.vue';
-import { useDialogPluginComponent } from 'quasar';
-
-const $props = defineProps({
-    itemLack: {
-        type: Object,
-        required: true,
-        default: () => {},
-    },
-    replaceAction: {
-        type: Boolean,
-        required: false,
-        default: false,
-    },
-    sales: {
-        type: Array,
-        required: false,
-        default: () => [],
-    },
-});
-const { dialogRef } = useDialogPluginComponent();
-const emit = defineEmits([
-    'onDialogClosed',
-    'itemReplaced',
-    ...useDialogPluginComponent.emits,
-]);
-defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
-</script>
-<template>
-    <QDialog ref="dialogRef" transition-show="scale" transition-hide="scale">
-        <QCard class="dialog-width">
-            <QCardSection class="row items-center q-pb-none">
-                <span class="text-h6 text-grey">{{ $t('Item proposal') }}</span>
-                <QSpace />
-                <QBtn icon="close" flat round dense v-close-popup />
-            </QCardSection>
-            <QCardSection>
-                <ItemProposal
-                    v-bind="$props"
-                    @item-replaced="
-                        (data) => {
-                            emit('itemReplaced', data);
-                            dialogRef.hide();
-                        }
-                    "
-                ></ItemProposal
-            ></QCardSection>
-        </QCard>
-    </QDialog>
-</template>
-<style lang="scss" scoped>
-.dialog-width {
-    max-width: $width-lg;
-}
-</style>
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index 9d27fc96e..bc73abb12 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -112,7 +112,6 @@ item:
         available: Available
         warehouseText: 'Calculated on the warehouse of { warehouseName }'
         itemDiary: Item diary
-        itemLastEntries: Last entries
         producer: Producer
         clone:
             title: All its properties will be copied
@@ -131,7 +130,6 @@ item:
         origin: Orig.
         userName: Buyer
         weight: Weight
-        color: Color
         weightByPiece: Weight/stem
         stemMultiplier: Multiplier
         producer: Producer
@@ -217,24 +215,4 @@ item:
         specie: Specie
     search: 'Search item'
     searchInfo: 'You can search by id'
-    regularizeStock: Regularize stock
-itemProposal: Items proposal
-proposal:
-    difference: Difference
-    title: Items proposal
-    itemFk: Item
-    longName: Name
-    subName: Producer
-    value5: value5
-    value6: value6
-    value7: value7
-    value8: value8
-    available: Available
-    minQuantity: minQuantity
-    price2: Price
-    located: Located
-    counter: Counter
-    groupingPrice: Grouping Price
-    itemOldPrice: itemOld Price
-    status: State
-    quantityToReplace: Quanity to replace
+    regularizeStock: Regularize stock
\ No newline at end of file
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index 935f5160b..dd5074f5f 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -118,7 +118,6 @@ item:
         available: Disponible
         warehouseText: 'Calculado sobre el almacén de { warehouseName }'
         itemDiary: Registro de compra-venta
-        itemLastEntries: Últimas entradas
         producer: Productor
         clone:
             title: Todas sus propiedades serán copiadas
@@ -136,7 +135,6 @@ item:
         size: Medida
         origin: Orig.
         weight: Peso
-        color: Color
         weightByPiece: Peso/tallo
         userName: Comprador
         stemMultiplier: Multiplicador
@@ -222,30 +220,5 @@ item:
         achieved: 'Conseguido'
         concept: 'Concepto'
         state: 'Estado'
-itemProposal: Artículos similares
-proposal:
-    substitutionAvailable: Sustitución disponible
-    notSubstitutionAvailableByPrice: Sustitución no disponible, 30% de diferencia por precio o cantidad
-    compatibility: Compatibilidad
-    title: Items de sustitución para los tickets seleccionados
-    itemFk: Item
-    longName: Nombre
-    subName: Productor
-    value5: value5
-    value6: value6
-    value7: value7
-    value8: value8
-    available: Disponible
-    minQuantity: Min. cantidad
-    price2: Precio
-    located: Ubicado
-    counter: Contador
-    difference: Diferencial
-    groupingPrice: Precio Grouping
-    itemOldPrice: Precio itemOld
-    status: Estado
-    quantityToReplace: Cantidad a reemplazar
-    replace: Sustituir
-    replaceAndConfirm: Sustituir y confirmar precio
-search: 'Buscar artículo'
-searchInfo: 'Puedes buscar por id'
+    search: 'Buscar artículo'
+    searchInfo: 'Puedes buscar por id'
diff --git a/src/pages/Monitor/MonitorOrders.vue b/src/pages/Monitor/MonitorOrders.vue
index 873f8abb4..4efab56fb 100644
--- a/src/pages/Monitor/MonitorOrders.vue
+++ b/src/pages/Monitor/MonitorOrders.vue
@@ -157,7 +157,7 @@ const openTab = (id) =>
                         openConfirmationModal(
                             $t('globals.deleteConfirmTitle'),
                             $t('salesOrdersTable.deleteConfirmMessage'),
-                            removeOrders,
+                            removeOrders
                         )
                     "
                 >
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index 496c8761a..21324087c 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -38,7 +38,6 @@ salesTicketsTable:
     payMethod: Pay method
     department: Department
     packing: ITP
-    hasItemLost: Item lost
 searchBar:
     label: Search tickets
     info: Search tickets by id or alias
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index f6a29879f..30afb1904 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -39,7 +39,6 @@ salesTicketsTable:
     payMethod: Método de pago
     department: Departamento
     packing: ITP
-    hasItemLost: Artículo perdido
 searchBar:
     label: Buscar tickets
     info: Buscar tickets por identificador o alias
diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index d1bd48c9e..b91e7d229 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -110,7 +110,7 @@ const getSelectedTagValues = async (tag) => {
             </div>
             <QBtn
                 icon="add_circle"
-                v-shortcut="'+'"
+                shortcut="+"
                 flat
                 class="filter-icon q-mb-md"
                 size="md"
diff --git a/src/pages/Order/Card/OrderBasicData.vue b/src/pages/Order/Card/OrderBasicData.vue
index 9c02d7494..8594a05f4 100644
--- a/src/pages/Order/Card/OrderBasicData.vue
+++ b/src/pages/Order/Card/OrderBasicData.vue
@@ -14,6 +14,7 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const { t } = useI18n();
 const route = useRoute();
 const state = useState();
+const ORDER_MODEL = 'order';
 
 const isNew = Boolean(!route.params.id);
 const clientList = ref([]);
@@ -31,7 +32,7 @@ const fetchAddressList = async (addressId) => {
     });
     addressList.value = data;
     if (addressList.value?.length === 1) {
-        state.get('Order').addressFk = addressList.value[0].id;
+        state.get(ORDER_MODEL).addressFk = addressList.value[0].id;
     }
 };
 
@@ -90,8 +91,9 @@ const onClientChange = async (clientId) => {
     <VnSubToolbar v-if="isNew" />
     <div class="q-pa-md">
         <FormModel
+            :url="`Orders/${route.params.id}`"
             :url-update="`Orders/${route.params.id}/updateBasicData`"
-            model="Order"
+            :model="ORDER_MODEL"
             :filter="orderFilter"
             @on-fetch="fetchOrderDetails"
             auto-load
diff --git a/src/pages/Order/Card/OrderCard.vue b/src/pages/Order/Card/OrderCard.vue
index ad5c73a87..823815f59 100644
--- a/src/pages/Order/Card/OrderCard.vue
+++ b/src/pages/Order/Card/OrderCard.vue
@@ -1,14 +1,12 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
-import filter from './OrderFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Order"
-        url="Orders"
-        :filter="filter"
+        base-url="Orders"
         :descriptor="OrderDescriptor"
     />
 </template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 76e608983..262f503fd 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -184,7 +184,7 @@ function addOrder(value, field, params) {
                         {{
                             t(
                                 categoryList.find((c) => c.id == customTag.value)?.name ||
-                                    '',
+                                    ''
                             )
                         }}
                     </strong>
@@ -296,7 +296,7 @@ function addOrder(value, field, params) {
                     <template #append>
                         <QBtn
                             icon="add_circle"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             flat
                             color="primary"
                             size="md"
diff --git a/src/pages/Order/Card/OrderCatalogItemDialog.vue b/src/pages/Order/Card/OrderCatalogItemDialog.vue
index 766945e4d..77f6a8405 100644
--- a/src/pages/Order/Card/OrderCatalogItemDialog.vue
+++ b/src/pages/Order/Card/OrderCatalogItemDialog.vue
@@ -20,7 +20,7 @@ const props = defineProps({
 });
 const state = useState();
 
-const orderData = computed(() => state.get('Order'));
+const orderData = computed(() => state.get('orderData'));
 
 const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
 const isLoading = ref(false);
@@ -39,11 +39,11 @@ const addToOrder = async () => {
     });
 
     const { data: orderTotal } = await axios.get(
-        `Orders/${Number(route.params.id)}/getTotal`,
+        `Orders/${Number(route.params.id)}/getTotal`
     );
 
     state.set('orderTotal', orderTotal);
-    state.set('Order', {
+    state.set('orderData', {
         ...orderData.value,
         items,
     });
@@ -56,7 +56,7 @@ const canAddToOrder = () => {
     if (canAddToOrder) {
         const excedQuantity = prices.value.reduce(
             (acc, { quantity }) => acc + quantity,
-            0,
+            0
         );
         if (excedQuantity > props.item.available) {
             canAddToOrder = false;
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index 0d18864dc..0d5f0146f 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -4,7 +4,8 @@ import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toCurrency, toDate } from 'src/filters';
 import { useState } from 'src/composables/useState';
-import filter from './OrderFilter.js';
+import 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';
@@ -23,15 +24,44 @@ const $props = defineProps({
 const route = useRoute();
 const state = useState();
 const { t } = useI18n();
+const data = ref(useCardDescription());
 const getTotalRef = ref();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
+const filter = {
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['name'] } },
+        {
+            relation: 'address',
+            scope: { fields: ['nickname'] },
+        },
+        { relation: 'rows', scope: { fields: ['id'] } },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'salesPersonFk',
+                    'name',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                ],
+                include: {
+                    relation: 'salesPersonUser',
+                    scope: { fields: ['id', 'name'] },
+                },
+            },
+        },
+    ],
+};
+
 const setData = (entity) => {
     if (!entity) return;
     getTotalRef.value && getTotalRef.value.fetch();
+    data.value = useCardDescription(entity?.client?.name, entity?.id);
     state.set('orderTotal', total);
 };
 
@@ -57,9 +87,11 @@ const total = ref(0);
         ref="descriptor"
         :url="`Orders/${entityId}`"
         :filter="filter"
-        title="client.name"
+        module="Order"
+        :title="data.title"
+        :subtitle="data.subtitle"
         @on-fetch="setData"
-        data-key="Order"
+        data-key="orderData"
     >
         <template #body="{ entity }">
             <VnLv
diff --git a/src/pages/Order/Card/OrderFilter.js b/src/pages/Order/Card/OrderFilter.js
deleted file mode 100644
index 3e521b92c..000000000
--- a/src/pages/Order/Card/OrderFilter.js
+++ /dev/null
@@ -1,26 +0,0 @@
-export default {
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['name'] } },
-        {
-            relation: 'address',
-            scope: { fields: ['nickname'] },
-        },
-        { relation: 'rows', scope: { fields: ['id'] } },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'salesPersonFk',
-                    'name',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                ],
-                include: {
-                    relation: 'salesPersonUser',
-                    scope: { fields: ['id', 'name'] },
-                },
-            },
-        },
-    ],
-};
diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index 1b864de6f..cf219a244 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -21,7 +21,7 @@ const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
 const quasar = useQuasar();
-const descriptorData = useArrayData('Order');
+const descriptorData = useArrayData('orderData');
 const componentKey = ref(0);
 const tableLinesRef = ref();
 const order = ref();
@@ -238,7 +238,7 @@ watch(
         lineFilter.value.where.orderFk = router.currentRoute.value.params.id;
 
         tableLinesRef.value.reload();
-    },
+    }
 );
 </script>
 
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index a4bdb2881..a289688e4 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -27,7 +27,7 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const summary = ref();
 const quasar = useQuasar();
-const descriptorData = useArrayData('Order');
+const descriptorData = useArrayData('orderData');
 const detailsColumns = ref([
     {
         name: 'item',
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 40990f329..21cb5ed7e 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -71,9 +71,8 @@ const columns = computed(() => [
         format: (row) => row?.name,
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'isConfirmed',
-        component: 'checkbox',
         label: t('module.isConfirmed'),
     },
     {
@@ -96,9 +95,7 @@ const columns = computed(() => [
         columnField: {
             component: null,
         },
-        style: () => {
-            return { color: 'positive' };
-        },
+        style: 'color="positive"',
     },
     {
         align: 'left',
diff --git a/src/pages/Shelving/Parking/Card/ParkingBasicData.vue b/src/pages/Parking/Card/ParkingBasicData.vue
similarity index 68%
rename from src/pages/Shelving/Parking/Card/ParkingBasicData.vue
rename to src/pages/Parking/Card/ParkingBasicData.vue
index 3de358002..550a0684e 100644
--- a/src/pages/Shelving/Parking/Card/ParkingBasicData.vue
+++ b/src/pages/Parking/Card/ParkingBasicData.vue
@@ -1,11 +1,16 @@
 <script setup>
-import { ref } from 'vue';
+import { ref, computed } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
 import VnRow from 'components/ui/VnRow.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import FormModel from 'components/FormModel.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
+const { t } = useI18n();
+const route = useRoute();
+const parkingId = computed(() => route.params?.id || null);
 const sectors = ref([]);
 const sectorFilter = { fields: ['id', 'description'] };
 
@@ -22,21 +27,18 @@ const filter = {
         @on-fetch="(data) => (sectors = data)"
         auto-load
     />
-    <FormModel model="Parking" auto-load>
+    <FormModel :url="`Parkings/${parkingId}`" model="parking" :filter="filter" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <VnInput v-model="data.code" :label="$t('globals.code')" />
-                <VnInput
-                    v-model="data.pickingOrder"
-                    :label="$t('parking.pickingOrder')"
-                />
+                <VnInput v-model="data.code" :label="t('globals.code')" />
+                <VnInput v-model="data.pickingOrder" :label="t('parking.pickingOrder')" />
             </VnRow>
             <VnRow>
                 <VnSelect
                     v-model="data.sectorFk"
                     option-value="id"
                     option-label="description"
-                    :label="$t('parking.sector')"
+                    :label="t('parking.sector')"
                     :options="sectors"
                     use-input
                     input-debounce="0"
diff --git a/src/pages/Shelving/Parking/Card/ParkingCard.vue b/src/pages/Parking/Card/ParkingCard.vue
similarity index 53%
rename from src/pages/Shelving/Parking/Card/ParkingCard.vue
rename to src/pages/Parking/Card/ParkingCard.vue
index b32c1b7d3..1cd2df7b7 100644
--- a/src/pages/Shelving/Parking/Card/ParkingCard.vue
+++ b/src/pages/Parking/Card/ParkingCard.vue
@@ -1,14 +1,12 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import ParkingDescriptor from 'pages/Shelving/Parking/Card/ParkingDescriptor.vue';
-import filter from './ParkingFilter.js';
+import ParkingDescriptor from 'pages/Parking/Card/ParkingDescriptor.vue';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Parking"
-        url="Parkings"
-        :filter="filter"
+        base-url="Parkings"
         :descriptor="ParkingDescriptor"
     />
 </template>
diff --git a/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue b/src/pages/Parking/Card/ParkingDescriptor.vue
similarity index 58%
rename from src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
rename to src/pages/Parking/Card/ParkingDescriptor.vue
index 46c9f8ea0..d36ea16fc 100644
--- a/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
+++ b/src/pages/Parking/Card/ParkingDescriptor.vue
@@ -1,9 +1,10 @@
 <script setup>
 import { computed } from 'vue';
+import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-import filter from './ParkingFilter.js';
+
 const props = defineProps({
     id: {
         type: Number,
@@ -12,11 +13,18 @@ const props = defineProps({
     },
 });
 
+const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => props.id || route.params.id);
+
+const filter = {
+    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
+    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
+};
 </script>
 <template>
     <CardDescriptor
+        module="Parking"
         data-key="Parking"
         :url="`Parkings/${entityId}`"
         title="code"
@@ -24,9 +32,9 @@ const entityId = computed(() => props.id || route.params.id);
         :to-module="{ name: 'ParkingList' }"
     >
         <template #body="{ entity }">
-            <VnLv :label="$t('globals.code')" :value="entity.code" />
-            <VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
-            <VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
+            <VnLv :label="t('globals.code')" :value="entity.code" />
+            <VnLv :label="t('parking.pickingOrder')" :value="entity.pickingOrder" />
+            <VnLv :label="t('parking.sector')" :value="entity.sector?.description" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Shelving/Parking/Card/ParkingLog.vue b/src/pages/Parking/Card/ParkingLog.vue
similarity index 100%
rename from src/pages/Shelving/Parking/Card/ParkingLog.vue
rename to src/pages/Parking/Card/ParkingLog.vue
diff --git a/src/pages/Shelving/Parking/Card/ParkingSummary.vue b/src/pages/Parking/Card/ParkingSummary.vue
similarity index 100%
rename from src/pages/Shelving/Parking/Card/ParkingSummary.vue
rename to src/pages/Parking/Card/ParkingSummary.vue
diff --git a/src/pages/Shelving/Parking/ParkingFilter.vue b/src/pages/Parking/ParkingFilter.vue
similarity index 100%
rename from src/pages/Shelving/Parking/ParkingFilter.vue
rename to src/pages/Parking/ParkingFilter.vue
diff --git a/src/pages/Shelving/Parking/ParkingList.vue b/src/pages/Parking/ParkingList.vue
similarity index 90%
rename from src/pages/Shelving/Parking/ParkingList.vue
rename to src/pages/Parking/ParkingList.vue
index fe6c93ba5..bce87126e 100644
--- a/src/pages/Shelving/Parking/ParkingList.vue
+++ b/src/pages/Parking/ParkingList.vue
@@ -9,7 +9,6 @@ import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import ParkingFilter from './ParkingFilter.vue';
 import ParkingSummary from './Card/ParkingSummary.vue';
-import exprBuilder from './ParkingExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const stateStore = useStateStore();
@@ -24,7 +23,19 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 const filter = {
     fields: ['id', 'sectorFk', 'code', 'pickingOrder'],
 };
+
+function exprBuilder(param, value) {
+    switch (param) {
+        case 'code':
+            return { [param]: { like: `%${value}%` } };
+        case 'sectorFk':
+            return { [param]: value };
+        case 'search':
+            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
+    }
+}
 </script>
+
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Shelving/Parking/locale/en.yml b/src/pages/Parking/locale/en.yml
similarity index 100%
rename from src/pages/Shelving/Parking/locale/en.yml
rename to src/pages/Parking/locale/en.yml
diff --git a/src/pages/Shelving/Parking/locale/es.yml b/src/pages/Parking/locale/es.yml
similarity index 100%
rename from src/pages/Shelving/Parking/locale/es.yml
rename to src/pages/Parking/locale/es.yml
diff --git a/src/pages/Route/Agency/AgencyList.vue b/src/pages/Route/Agency/AgencyList.vue
index 5c2904bf3..4322b9bc8 100644
--- a/src/pages/Route/Agency/AgencyList.vue
+++ b/src/pages/Route/Agency/AgencyList.vue
@@ -51,6 +51,7 @@ const columns = computed(() => [
         name: 'isAnyVolumeAllowed',
         component: 'checkbox',
         cardVisible: true,
+        disable: true,
     },
     {
         align: 'right',
@@ -71,7 +72,7 @@ const columns = computed(() => [
         :data-key
         :columns="columns"
         prefix="agency"
-        :right-filter="true"
+        :right-filter="false"
         :array-data-props="{
             url: 'Agencies',
             order: 'name',
@@ -82,7 +83,6 @@ const columns = computed(() => [
             <VnTable
                 :data-key
                 :columns="columns"
-                is-editable="false"
                 :right-search="false"
                 :use-model="true"
                 redirect="route/agency"
diff --git a/src/pages/Route/Agency/Card/AgencyBasicData.vue b/src/pages/Route/Agency/Card/AgencyBasicData.vue
index 4270b136c..599058b3e 100644
--- a/src/pages/Route/Agency/Card/AgencyBasicData.vue
+++ b/src/pages/Route/Agency/Card/AgencyBasicData.vue
@@ -21,7 +21,7 @@ const warehouses = ref([]);
         @on-fetch="(data) => (warehouses = data)"
         auto-load
     />
-    <FormModel :update-url="`Agencies/${routeId}`" model="Agency" auto-load>
+    <FormModel :url="`Agencies/${routeId}`" model="agency" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.name" :label="t('globals.name')" />
diff --git a/src/pages/Route/Agency/Card/AgencyCard.vue b/src/pages/Route/Agency/Card/AgencyCard.vue
index 7dc31f8ba..35685790a 100644
--- a/src/pages/Route/Agency/Card/AgencyCard.vue
+++ b/src/pages/Route/Agency/Card/AgencyCard.vue
@@ -3,5 +3,5 @@ import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" />
+    <VnCardBeta data-key="Agency" base-url="Agencies" :descriptor="AgencyDescriptor" />
 </template>
diff --git a/src/pages/Route/Agency/Card/AgencyDescriptor.vue b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
index a0472c6c3..b9772037c 100644
--- a/src/pages/Route/Agency/Card/AgencyDescriptor.vue
+++ b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
@@ -22,6 +22,7 @@ const card = computed(() => store.data);
 </script>
 <template>
     <CardDescriptor
+        module="Agency"
         data-key="Agency"
         :url="`Agencies/${entityId}`"
         :title="card?.name"
diff --git a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
index 9a9213868..7cabf396d 100644
--- a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
+++ b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
@@ -88,7 +88,7 @@ async function deleteWorCenter(id) {
         </VnPaginate>
     </div>
     <QPageSticky :offset="[18, 18]">
-        <QBtn @click.stop="dialog.show()" color="primary" fab v-shortcut="'+'" icon="add">
+        <QBtn @click.stop="dialog.show()" color="primary" fab shortcut="+" icon="add">
             <QDialog ref="dialog">
                 <FormModelPopup
                     :title="t('Add work center')"
diff --git a/src/pages/Route/Card/RouteCard.vue b/src/pages/Route/Card/RouteCard.vue
index c178dc6bf..81b6cfa16 100644
--- a/src/pages/Route/Card/RouteCard.vue
+++ b/src/pages/Route/Card/RouteCard.vue
@@ -1,13 +1,12 @@
 <script setup>
 import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
-import filter from './RouteFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Route"
-        url="Routes"
-        :filter="filter"
+        base-url="Routes"
+        custom-url="Routes/filter"
         :descriptor="RouteDescriptor"
     />
 </template>
diff --git a/src/pages/Route/Card/RouteDescriptor.vue b/src/pages/Route/Card/RouteDescriptor.vue
index 503cd1941..68c08b821 100644
--- a/src/pages/Route/Card/RouteDescriptor.vue
+++ b/src/pages/Route/Card/RouteDescriptor.vue
@@ -1,14 +1,13 @@
 <script setup>
 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 'components/ui/VnLv.vue';
+import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDate } from 'src/filters';
 import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
-import filter from './RouteFilter.js';
-import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
-
 const $props = defineProps({
     id: {
         type: Number,
@@ -18,6 +17,7 @@ const $props = defineProps({
 });
 
 const route = useRoute();
+const { t } = useI18n();
 const zone = ref();
 const zoneId = ref();
 const entityId = computed(() => {
@@ -36,31 +36,81 @@ const getZone = async () => {
     const { data: zoneData } = await axios.get(`Zones/${zoneId.value}`);
     zone.value = zoneData.name;
 };
+
+const filter = {
+    fields: [
+        'id',
+        'workerFk',
+        'agencyModeFk',
+        'dated',
+        'm3',
+        'warehouseFk',
+        'description',
+        'vehicleFk',
+        'kmStart',
+        'kmEnd',
+        'started',
+        'finished',
+        'cost',
+        'isOk',
+    ],
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
+        {
+            relation: 'vehicle',
+            scope: { fields: ['id', 'm3'] },
+        },
+        {
+            relation: 'ticket',
+            scope: {
+                fields: ['id', 'name', 'zoneFk'],
+                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
+            },
+        },
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: {
+                        fields: ['id'],
+                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
+                    },
+                },
+            },
+        },
+    ],
+};
 const data = ref(useCardDescription());
 const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 onMounted(async () => {
     getZone();
 });
 </script>
+
 <template>
     <CardDescriptor
+        module="Route"
         :url="`Routes/${entityId}`"
         :filter="filter"
-        :title="null"
-        data-key="Route"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        data-key="routeData"
+        @on-fetch="setData"
         width="lg-width"
     >
         <template #body="{ entity }">
-            <VnLv :label="$t('Date')" :value="toDate(entity?.dated)" />
-            <VnLv :label="$t('Agency')" :value="entity?.agencyMode?.name" />
-            <VnLv :label="$t('Zone')" :value="zone" />
+            <VnLv :label="t('Date')" :value="toDate(entity?.dated)" />
+            <VnLv :label="t('Agency')" :value="entity?.agencyMode?.name" />
+            <VnLv :label="t('Zone')" :value="zone" />
             <VnLv
-                :label="$t('Volume')"
+                :label="t('Volume')"
                 :value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty(
                     entity?.vehicle?.m3,
                 )} m³`"
             />
-            <VnLv :label="$t('Description')" :value="entity?.description" />
+            <VnLv :label="t('Description')" :value="entity?.description" />
         </template>
         <template #menu="{ entity }">
             <RouteDescriptorMenu :route="entity" />
diff --git a/src/pages/Route/Card/RouteFilter.js b/src/pages/Route/Card/RouteFilter.js
deleted file mode 100644
index 90ee71bf7..000000000
--- a/src/pages/Route/Card/RouteFilter.js
+++ /dev/null
@@ -1,39 +0,0 @@
-export default {
-    fields: [
-        'code',
-        'id',
-        'workerFk',
-        'agencyModeFk',
-        'created',
-        'm3',
-        'warehouseFk',
-        'description',
-        'vehicleFk',
-        'kmStart',
-        'kmEnd',
-        'started',
-        'finished',
-        'cost',
-        'isOk',
-    ],
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
-        {
-            relation: 'vehicle',
-            scope: { fields: ['id', 'm3'] },
-        },
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: {
-                        fields: ['id'],
-                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
-                    },
-                },
-            },
-        },
-    ],
-};
diff --git a/src/pages/Route/Card/RouteFilter.vue b/src/pages/Route/Card/RouteFilter.vue
index 21858102b..72bfed1da 100644
--- a/src/pages/Route/Card/RouteFilter.vue
+++ b/src/pages/Route/Card/RouteFilter.vue
@@ -100,7 +100,7 @@ const emit = defineEmits(['search']);
                     <VnSelect
                         :label="t('Vehicle')"
                         v-model="params.vehicleFk"
-                        url="Vehicles/active"
+                        url="Vehicles"
                         sort-by="numberPlate ASC"
                         option-value="id"
                         option-label="numberPlate"
diff --git a/src/pages/Route/Card/RouteForm.vue b/src/pages/Route/Card/RouteForm.vue
index 667204b15..633ff44bc 100644
--- a/src/pages/Route/Card/RouteForm.vue
+++ b/src/pages/Route/Card/RouteForm.vue
@@ -11,7 +11,6 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInput from 'components/common/VnInput.vue';
 import axios from 'axios';
 import VnInputTime from 'components/common/VnInputTime.vue';
-import filter from './RouteFilter.js';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
 
 const { t } = useI18n();
@@ -28,6 +27,52 @@ const defaultInitialData = {
     isOk: false,
 };
 const maxDistance = ref();
+
+const routeFilter = {
+    fields: [
+        'id',
+        'workerFk',
+        'agencyModeFk',
+        'dated',
+        'm3',
+        'warehouseFk',
+        'description',
+        'vehicleFk',
+        'kmStart',
+        'kmEnd',
+        'started',
+        'finished',
+        'cost',
+        'isOk',
+    ],
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
+        {
+            relation: 'vehicle',
+            scope: { fields: ['id', 'm3'] },
+        },
+        {
+            relation: 'ticket',
+            scope: {
+                fields: ['id', 'name', 'zoneFk'],
+                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
+            },
+        },
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: {
+                        fields: ['id'],
+                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
+                    },
+                },
+            },
+        },
+    ],
+};
 const onSave = (data, response) => {
     if (isNew) {
         axios.post(`Routes/${response?.id}/updateWorkCenter`);
@@ -44,10 +89,11 @@ const onSave = (data, response) => {
         sort-by="id ASC"
     />
     <FormModel
+        :url="isNew ? null : `Routes/${route.params?.id}`"
         :url-create="isNew ? 'Routes' : null"
         :observe-form-changes="!isNew"
-        :filter="filter"
-        model="Route"
+        :filter="routeFilter"
+        model="route"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -58,7 +104,7 @@ const onSave = (data, response) => {
                 <VnSelect
                     :label="t('Vehicle')"
                     v-model="data.vehicleFk"
-                    url="Vehicles/active"
+                    url="Vehicles"
                     sort-by="numberPlate ASC"
                     option-value="id"
                     option-label="numberPlate"
diff --git a/src/pages/Route/Roadmap/RoadmapBasicData.vue b/src/pages/Route/Roadmap/RoadmapBasicData.vue
index a9e6059c3..2fe805362 100644
--- a/src/pages/Route/Roadmap/RoadmapBasicData.vue
+++ b/src/pages/Route/Roadmap/RoadmapBasicData.vue
@@ -11,16 +11,17 @@ import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 const { t } = useI18n();
 const router = useRouter();
 
+const filter = { include: [{ relation: 'supplier' }] };
 const onSave = (data, response) => {
     router.push({ name: 'RoadmapSummary', params: { id: response?.id } });
 };
 </script>
 <template>
     <FormModel
-        :update-url="`Roadmaps/${$route.params?.id}`"
         :url="`Roadmaps/${$route.params?.id}`"
         observe-form-changes
-        model="Roadmap"
+        :filter="filter"
+        model="roadmap"
         auto-load
         @on-data-saved="onSave"
     >
diff --git a/src/pages/Route/Roadmap/RoadmapCard.vue b/src/pages/Route/Roadmap/RoadmapCard.vue
index 48ba516a1..0b81de673 100644
--- a/src/pages/Route/Roadmap/RoadmapCard.vue
+++ b/src/pages/Route/Roadmap/RoadmapCard.vue
@@ -3,5 +3,5 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Roadmap" url="Roadmaps" :descriptor="RoadmapDescriptor" />
+    <VnCardBeta data-key="Roadmap" base-url="Roadmaps" :descriptor="RoadmapDescriptor" />
 </template>
diff --git a/src/pages/Route/Roadmap/RoadmapDescriptor.vue b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
index baa864a15..788173688 100644
--- a/src/pages/Route/Roadmap/RoadmapDescriptor.vue
+++ b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
@@ -1,13 +1,13 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
+import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDateHourMin } from 'src/filters';
 import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
 import RoadmapDescriptorMenu from 'pages/Route/Roadmap/RoadmapDescriptorMenu.vue';
-import filter from 'pages/Route/Roadmap/RoadmapFilter.js';
 
 const $props = defineProps({
     id: {
@@ -23,10 +23,22 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
+
+const filter = { include: [{ relation: 'supplier' }] };
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
 
 <template>
-    <CardDescriptor :url="`Roadmaps/${entityId}`" :filter="filter" data-key="Roadmap">
+    <CardDescriptor
+        module="Roadmap"
+        :url="`Roadmaps/${entityId}`"
+        :filter="filter"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        data-key="Roadmap"
+        @on-fetch="setData"
+    >
         <template #body="{ entity }">
             <VnLv :label="t('Roadmap')" :value="entity?.name" />
             <VnLv :label="t('ETD')" :value="toDateHourMin(entity?.etd)" />
diff --git a/src/pages/Route/Roadmap/RoadmapFilter.js b/src/pages/Route/Roadmap/RoadmapFilter.js
deleted file mode 100644
index 0ae890363..000000000
--- a/src/pages/Route/Roadmap/RoadmapFilter.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default {
-    include: [{ relation: 'supplier' }],
-};
diff --git a/src/pages/Route/Roadmap/RoadmapStops.vue b/src/pages/Route/Roadmap/RoadmapStops.vue
index e4085d572..d8215ea49 100644
--- a/src/pages/Route/Roadmap/RoadmapStops.vue
+++ b/src/pages/Route/Roadmap/RoadmapStops.vue
@@ -68,7 +68,7 @@ const updateDefaultStop = (data) => {
                         <QBtn
                             flat
                             icon="add"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             class="cursor-pointer"
                             color="primary"
                             @click="roadmapStopsCrudRef.insert()"
diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue
index 0c1c2b903..1fbb1897d 100644
--- a/src/pages/Route/Roadmap/RoadmapSummary.vue
+++ b/src/pages/Route/Roadmap/RoadmapSummary.vue
@@ -67,6 +67,7 @@ const filter = {
             },
         },
     ],
+    where: { id: entityId },
 };
 </script>
 
@@ -75,7 +76,7 @@ const filter = {
         <CardSummary
             data-key="RoadmapSummary"
             ref="summary"
-            :url="`Roadmaps/${entityId}`"
+            :url="`Roadmaps`"
             :filter="filter"
         >
             <template #header-left>
diff --git a/src/pages/Route/RouteExtendedList.vue b/src/pages/Route/RouteExtendedList.vue
index 46bc1a690..221fc4754 100644
--- a/src/pages/Route/RouteExtendedList.vue
+++ b/src/pages/Route/RouteExtendedList.vue
@@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import { useQuasar } from 'quasar';
-import { dashIfEmpty, toDate, toHour } from 'src/filters';
+import { toDate } from 'src/filters';
 import { useRouter } from 'vue-router';
 import { usePrintService } from 'src/composables/usePrintService';
 
@@ -38,7 +38,7 @@ const routeFilter = {
 };
 const columns = computed(() => [
     {
-        align: 'center',
+        align: 'left',
         name: 'id',
         label: 'Id',
         chip: {
@@ -48,7 +48,7 @@ const columns = computed(() => [
         columnFilter: false,
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'workerFk',
         label: t('route.Worker'),
         create: true,
@@ -68,10 +68,10 @@ const columns = computed(() => [
         },
         useLike: false,
         cardVisible: true,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.workerUserName),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'agencyModeFk',
         label: t('route.Agency'),
         isTitle: true,
@@ -87,17 +87,17 @@ const columns = computed(() => [
             },
         },
         columnClass: 'expand',
-        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyName),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'vehicleFk',
         label: t('route.Vehicle'),
         cardVisible: true,
         create: true,
         component: 'select',
         attrs: {
-            url: 'vehicles/active',
+            url: 'vehicles',
+            fields: ['id', 'numberPlate'],
             optionLabel: 'numberPlate',
             optionFilterValue: 'numberPlate',
             find: {
@@ -108,31 +108,29 @@ const columns = computed(() => [
         columnFilter: {
             inWhere: true,
         },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.vehiclePlateNumber),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'dated',
         label: t('route.Date'),
         columnFilter: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ dated }, dashIfEmpty) =>
-            dated === '0000-00-00' ? dashIfEmpty(null) : toDate(dated),
+        format: ({ date }) => toDate(date),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'from',
         label: t('route.From'),
         visible: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ from }) => toDate(from),
+        format: ({ date }) => toDate(date),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'to',
         label: t('route.To'),
         visible: false,
@@ -149,20 +147,18 @@ const columns = computed(() => [
         columnClass: 'shrink',
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'started',
         label: t('route.hourStarted'),
         component: 'time',
         columnFilter: false,
-        format: ({ started }) => toHour(started),
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'finished',
         label: t('route.hourFinished'),
         component: 'time',
         columnFilter: false,
-        format: ({ finished }) => toHour(finished),
     },
     {
         align: 'center',
@@ -181,7 +177,7 @@ const columns = computed(() => [
         visible: false,
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'description',
         label: t('route.Description'),
         isTitle: true,
@@ -190,7 +186,7 @@ const columns = computed(() => [
         field: 'description',
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'isOk',
         label: t('route.Served'),
         component: 'checkbox',
@@ -304,62 +300,60 @@ const openTicketsDialog = (id) => {
             <RouteFilter data-key="RouteList" />
         </template>
     </RightMenu>
-    <QPage class="q-px-md">
-        <VnTable
-            class="route-list"
-            ref="tableRef"
-            data-key="RouteList"
-            url="Routes/filter"
-            :columns="columns"
-            :right-search="false"
-            :is-editable="true"
-            :filter="routeFilter"
-            redirect="route"
-            :row-click="false"
-            :create="{
-                urlCreate: 'Routes',
-                title: t('route.createRoute'),
-                onDataSaved: ({ id }) => tableRef.redirect(id),
-                formInitialData: {},
-            }"
-            save-url="Routes/crud"
-            :disable-option="{ card: true }"
-            table-height="85vh"
-            v-model:selected="selectedRows"
-            :table="{
-                'row-key': 'id',
-                selection: 'multiple',
-            }"
-        >
-            <template #moreBeforeActions>
-                <QBtn
-                    icon="vn:clone"
-                    color="primary"
-                    class="q-mr-sm"
-                    :disable="!selectedRows?.length"
-                    @click="confirmationDialog = true"
-                >
-                    <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
-                </QBtn>
-                <QBtn
-                    icon="cloud_download"
-                    color="primary"
-                    class="q-mr-sm"
-                    :disable="!selectedRows?.length"
-                    @click="showRouteReport"
-                >
-                    <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
-                </QBtn>
-                <QBtn
-                    icon="check"
-                    color="primary"
-                    class="q-mr-sm"
-                    :disable="!selectedRows?.length"
-                    @click="markAsServed()"
-                >
-                    <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
-                </QBtn>
-            </template>
-        </VnTable>
-    </QPage>
+    <VnTable
+        class="route-list"
+        ref="tableRef"
+        data-key="RouteList"
+        url="Routes/filter"
+        :columns="columns"
+        :right-search="false"
+        :is-editable="true"
+        :filter="routeFilter"
+        redirect="route"
+        :row-click="false"
+        :create="{
+            urlCreate: 'Routes',
+            title: t('route.createRoute'),
+            onDataSaved: ({ id }) => tableRef.redirect(id),
+            formInitialData: {},
+        }"
+        save-url="Routes/crud"
+        :disable-option="{ card: true }"
+        table-height="85vh"
+        v-model:selected="selectedRows"
+        :table="{
+            'row-key': 'id',
+            selection: 'multiple',
+        }"
+    >
+        <template #moreBeforeActions>
+            <QBtn
+                icon="vn:clone"
+                color="primary"
+                class="q-mr-sm"
+                :disable="!selectedRows?.length"
+                @click="confirmationDialog = true"
+            >
+                <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
+            </QBtn>
+            <QBtn
+                icon="cloud_download"
+                color="primary"
+                class="q-mr-sm"
+                :disable="!selectedRows?.length"
+                @click="showRouteReport"
+            >
+                <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
+            </QBtn>
+            <QBtn
+                icon="check"
+                color="primary"
+                class="q-mr-sm"
+                :disable="!selectedRows?.length"
+                @click="markAsServed()"
+            >
+                <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
+            </QBtn>
+        </template>
+    </VnTable>
 </template>
diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue
index 9dad8ba22..bc3227f6c 100644
--- a/src/pages/Route/RouteList.vue
+++ b/src/pages/Route/RouteList.vue
@@ -38,17 +38,6 @@ const columns = computed(() => [
         align: 'left',
         name: 'workerFk',
         label: t('route.Worker'),
-        component: 'select',
-        attrs: {
-            url: 'Workers/activeWithInheritedRole',
-            fields: ['id', 'name'],
-            useLike: false,
-            optionFilter: 'firstName',
-            find: {
-                value: 'workerFk',
-                label: 'workerUserName',
-            },
-        },
         create: true,
         cardVisible: true,
         format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
@@ -59,15 +48,6 @@ const columns = computed(() => [
         name: 'agencyName',
         label: t('route.Agency'),
         cardVisible: true,
-        component: 'select',
-        attrs: {
-            url: 'agencyModes',
-            fields: ['id', 'name'],
-            find: {
-                value: 'agencyModeFk',
-                label: 'agencyName',
-            },
-        },
         create: true,
         columnClass: 'expand',
         columnFilter: false,
@@ -77,17 +57,6 @@ const columns = computed(() => [
         name: 'vehiclePlateNumber',
         label: t('route.Vehicle'),
         cardVisible: true,
-        component: 'select',
-        attrs: {
-            url: 'vehicles',
-            fields: ['id', 'numberPlate'],
-            optionLabel: 'numberPlate',
-            optionFilterValue: 'numberPlate',
-            find: {
-                value: 'vehicleFk',
-                label: 'vehiclePlateNumber',
-            },
-        },
         create: true,
         columnFilter: false,
     },
diff --git a/src/pages/Route/RouteTickets.vue b/src/pages/Route/RouteTickets.vue
index adc7dfdaa..1416f77ce 100644
--- a/src/pages/Route/RouteTickets.vue
+++ b/src/pages/Route/RouteTickets.vue
@@ -120,8 +120,8 @@ const deletePriorities = async () => {
     try {
         await Promise.all(
             selectedRows.value.map((ticket) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: null }),
-            ),
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: null })
+            )
         );
     } finally {
         refreshKey.value++;
@@ -132,8 +132,8 @@ const setOrderedPriority = async () => {
     try {
         await Promise.all(
             ticketList.value.map((ticket, index) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 }),
-            ),
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 })
+            )
         );
     } finally {
         refreshKey.value++;
@@ -162,7 +162,7 @@ const setHighestPriority = async (ticket, ticketList) => {
 const goToBuscaman = async (ticket = null) => {
     await openBuscaman(
         routeEntity.value?.vehicleFk,
-        ticket ? [ticket] : selectedRows.value,
+        ticket ? [ticket] : selectedRows.value
     );
 };
 
@@ -393,13 +393,7 @@ const openSmsDialog = async () => {
             </VnPaginate>
         </div>
         <QPageSticky :offset="[20, 20]">
-            <QBtn
-                fab
-                icon="add"
-                v-shortcut="'+'"
-                color="primary"
-                @click="openTicketsDialog"
-            >
+            <QBtn fab icon="add" shortcut="+" color="primary" @click="openTicketsDialog">
                 <QTooltip>
                     {{ t('Add ticket') }}
                 </QTooltip>
diff --git a/src/pages/Route/Vehicle/Card/VehicleBasicData.vue b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
deleted file mode 100644
index e78bc6edd..000000000
--- a/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
+++ /dev/null
@@ -1,162 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import FormModel from 'components/FormModel.vue';
-import FetchData from 'src/components/FetchData.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import VnRow from 'components/ui/VnRow.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-
-const warehouses = ref([]);
-const companies = ref([]);
-const countries = ref([]);
-const fuelTypes = ref([]);
-const bankPolicies = ref([]);
-const deliveryPoints = ref([]);
-</script>
-<template>
-    <FetchData
-        url="Warehouses"
-        :filter="{ fields: ['id', 'name'] }"
-        @on-fetch="(data) => (warehouses = data)"
-        auto-load
-    />
-    <FetchData
-        url="Companies"
-        :filter="{ fields: ['id', 'code'] }"
-        @on-fetch="(data) => (companies = data)"
-        auto-load
-    />
-    <FetchData
-        url="Countries"
-        :filter="{ fields: ['code'] }"
-        @on-fetch="(data) => (countries = data)"
-        auto-load
-    />
-    <FetchData
-        url="FuelTypes"
-        :filter="{ fields: ['id', 'name'] }"
-        @on-fetch="(data) => (fuelTypes = data)"
-        auto-load
-    />
-    <FetchData
-        url="DeliveryPoints"
-        :filter="{ fields: ['id', 'name'] }"
-        @on-fetch="(data) => (deliveryPoints = data)"
-        auto-load
-    />
-    <FormModel model="Vehicle" :url-update="`Vehicles/${$route.params.id}`">
-        <template #form="{ data }">
-            <VnRow>
-                <VnInput v-model="data.description" :label="$t('globals.description')" />
-                <VnInput v-model="data.numberPlate" :label="$t('vehicle.numberPlate')" />
-            </VnRow>
-            <VnRow>
-                <VnInput
-                    v-model="data.model"
-                    :label="$t('globals.model')"
-                    :required="true"
-                />
-                <VnSelect
-                    url="VehicleTypes"
-                    v-model="data.vehicleTypeFk"
-                    :label="$t('globals.type')"
-                />
-            </VnRow>
-            <VnRow>
-                <VnInput
-                    v-model="data.tradeMark"
-                    :label="$t('vehicle.tradeMark')"
-                    :required="true"
-                />
-                <VnInput v-model="data.chassis" :label="$t('vehicle.chassis')" />
-            </VnRow>
-            <VnRow>
-                <VnSelect
-                    v-model="data.fuelTypeFk"
-                    :label="$t('globals.fuel')"
-                    :options="fuelTypes"
-                />
-                <VnSelect
-                    v-model="data.deliveryPointFk"
-                    :label="$t('globals.deliveryPoint')"
-                    :options="deliveryPoints"
-                />
-            </VnRow>
-            <VnRow>
-                <VnSelect
-                    v-model="data.companyFk"
-                    :label="$t('globals.company')"
-                    :options="companies"
-                    option-label="code"
-                />
-                <VnSelect
-                    v-model="data.warehouseFk"
-                    :label="$t('globals.warehouse')"
-                    :options="warehouses"
-                />
-            </VnRow>
-            <VnRow>
-                <VnSelect
-                    url="Suppliers"
-                    :filter="{ fields: ['id', 'name'] }"
-                    v-model="data.supplierFk"
-                    :label="$t('globals.supplier')"
-                />
-                <VnSelect
-                    url="Suppliers"
-                    :filter="{ fields: ['id', 'name'] }"
-                    v-model="data.supplierCoolerFk"
-                    :label="$t('vehicle.supplierCooler')"
-                />
-            </VnRow>
-            <VnRow>
-                <VnSelect
-                    url="BankPolicies"
-                    :filter="{ fields: ['id', 'ref'] }"
-                    v-model="data.bankPolicyFk"
-                    :label="$t('vehicle.leasing')"
-                    :options="bankPolicies"
-                    option-label="ref"
-                    option-value="id"
-                />
-                <VnInput v-model="data.leasing" :label="$t('vehicle.nLeasing')" />
-            </VnRow>
-            <VnRow>
-                <VnInputNumber v-model="data.import" :label="$t('globals.amount')" />
-                <VnInputNumber
-                    v-model="data.importCooler"
-                    :label="$t('vehicle.amountCooler')"
-                />
-            </VnRow>
-            <VnRow>
-                <VnSelect
-                    url="Ppes"
-                    option-label="id"
-                    v-model="data.ppeFk"
-                    :label="$t('vehicle.ppe')"
-                />
-                <VnSelect
-                    v-model="data.countryCodeFk"
-                    :label="$t('globals.country')"
-                    :options="countries"
-                    option-label="code"
-                    option-value="code"
-                />
-            </VnRow>
-            <VnRow>
-                <VnInput v-model="data.vin" :label="$t('vehicle.vin')" />
-                <span :style="{ 'align-self': $q.screen.gt.xs ? 'end' : 'unset' }">
-                    <QCheckbox
-                        v-model="data.isActive"
-                        :label="$t('vehicle.isActive')"
-                        :false-value="0"
-                        :true-value="1"
-                        dense
-                        class="q-mt-sm"
-                    />
-                </span>
-            </VnRow>
-        </template>
-    </FormModel>
-</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleCard.vue b/src/pages/Route/Vehicle/Card/VehicleCard.vue
deleted file mode 100644
index f59420aa2..000000000
--- a/src/pages/Route/Vehicle/Card/VehicleCard.vue
+++ /dev/null
@@ -1,13 +0,0 @@
-<script setup>
-import VnCardBeta from 'components/common/VnCardBeta.vue';
-import VehicleDescriptor from './VehicleDescriptor.vue';
-import VehicleFilter from '../VehicleFilter.js';
-</script>
-<template>
-    <VnCardBeta
-        data-key="Vehicle"
-        url="Vehicles"
-        :filter="VehicleFilter"
-        :descriptor="VehicleDescriptor"
-    />
-</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
deleted file mode 100644
index d9a2434ab..000000000
--- a/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<script setup>
-import VnLv from 'src/components/ui/VnLv.vue';
-import CardDescriptor from 'components/ui/CardDescriptor.vue';
-import axios from 'axios';
-import useNotify from 'src/composables/useNotify.js';
-
-const { notify } = useNotify();
-</script>
-<template>
-    <CardDescriptor
-        :url="`Vehicles/${$route.params.id}`"
-        data-key="Vehicle"
-        title="numberPlate"
-        :to-module="{ name: 'VehicleList' }"
-    >
-        <template #menu="{ entity }">
-            <QItem
-                data-cy="delete"
-                v-ripple
-                clickable
-                @click="
-                    async () => {
-                        try {
-                            await axios.delete(`Vehicles/${entity.id}`);
-                            notify('vehicle.remove', 'positive');
-                            $router.push({ name: 'VehicleList' });
-                        } catch (e) {
-                            throw e;
-                        }
-                    }
-                "
-            >
-                <QItemSection>
-                    {{ $t('vehicle.delete') }}
-                </QItemSection>
-            </QItem>
-        </template>
-        <template #body="{ entity }">
-            <VnLv :label="$t('vehicle.numberPlate')" :value="entity.numberPlate" />
-            <VnLv :label="$t('vehicle.tradeMark')" :value="entity.tradeMark" />
-            <VnLv :label="$t('globals.model')" :value="entity.model" />
-            <VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
-        </template>
-    </CardDescriptor>
-</template>
-<i18n>
-es:
-    Vehicle removed: Vehículo eliminado
-</i18n>
diff --git a/src/pages/Route/Vehicle/Card/VehicleSummary.vue b/src/pages/Route/Vehicle/Card/VehicleSummary.vue
deleted file mode 100644
index 981870cb2..000000000
--- a/src/pages/Route/Vehicle/Card/VehicleSummary.vue
+++ /dev/null
@@ -1,127 +0,0 @@
-<script setup>
-import { computed } from 'vue';
-import { useRoute } from 'vue-router';
-import CardSummary from 'components/ui/CardSummary.vue';
-import VnLv from 'src/components/ui/VnLv.vue';
-import VnTitle from 'src/components/common/VnTitle.vue';
-import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import VehicleFilter from '../VehicleFilter.js';
-import { downloadFile } from 'src/composables/downloadFile';
-import { dashIfEmpty } from 'src/filters';
-
-const props = defineProps({ id: { type: [Number, String], default: null } });
-
-const route = useRoute();
-const entityId = computed(() => props.id || +route.params.id);
-const links = {
-    'basic-data': `#/vehicle/${entityId.value}/basic-data`,
-    notes: `#/vehicle/${entityId.value}/notes`,
-    dms: `#/vehicle/${entityId.value}/dms`,
-    'invoice-in': `#/vehicle/${entityId.value}/invoice-in`,
-    events: `#/vehicle/${entityId.value}/events`,
-};
-</script>
-<template>
-    <CardSummary data-key="Vehicle" :url="`Vehicles/${entityId}`" :filter="VehicleFilter">
-        <template #header="{ entity }">
-            <div>{{ entity.id }} - {{ entity.numberPlate }}</div>
-        </template>
-        <template #body="{ entity }">
-            <QCard class="vn-one">
-                <QCardSection dense>
-                    <VnTitle
-                        :url="links['basic-data']"
-                        :text="$t('globals.pageTitles.basicData')"
-                    />
-                </QCardSection>
-                <QCardSection content>
-                    <QList dense>
-                        <VnLv
-                            :label="$t('globals.description')"
-                            :value="entity.description"
-                        />
-                        <VnLv
-                            :label="$t('vehicle.tradeMark')"
-                            :value="entity.tradeMark"
-                        />
-                        <VnLv :label="$t('globals.model')" :value="entity.model" />
-                        <VnLv :label="$t('globals.supplier')">
-                            <template #value>
-                                <span class="link">
-                                    {{ entity.supplier?.name }}
-                                    <SupplierDescriptorProxy :id="entity.supplierFk" />
-                                </span>
-                            </template>
-                        </VnLv>
-                        <VnLv :label="$t('vehicle.supplierCooler')">
-                            <template #value>
-                                <span class="link">
-                                    {{ entity.supplierCooler?.name }}
-                                    <SupplierDescriptorProxy
-                                        :id="entity.supplierCoolerFk"
-                                    />
-                                </span>
-                            </template>
-                        </VnLv>
-                        <VnLv :label="$t('vehicle.vin')" :value="entity.vin" />
-                    </QList>
-                    <QList dense>
-                        <VnLv :label="$t('vehicle.chassis')" :value="entity.chassis" />
-                        <VnLv
-                            :label="$t('globals.fuel')"
-                            :value="entity.fuelType?.name"
-                        />
-                        <VnLv :label="$t('vehicle.ppe')" :value="entity.ppeFk" />
-                        <VnLv :label="$t('vehicle.nLeasing')" :value="entity.leasing" />
-                        <VnLv
-                            :label="$t('vehicle.leasing')"
-                            :value="entity.bankPolicy?.ref"
-                        >
-                            <template #value>
-                                <span v-text="dashIfEmpty(entity.bankPolicy?.name)" />
-                                <QBtn
-                                    v-if="entity.bankPolicy?.dmsFk"
-                                    class="q-ml-xs"
-                                    color="primary"
-                                    flat
-                                    dense
-                                    icon="cloud_download"
-                                    @click="downloadFile(entity.bankPolicy?.dmsFk)"
-                                >
-                                    <QTooltip>{{ $t('globals.download') }}</QTooltip>
-                                </QBtn>
-                            </template>
-                        </VnLv>
-                        <VnLv :label="$t('globals.amount')" :value="entity.import" />
-                    </QList>
-                    <QList dense>
-                        <VnLv
-                            :label="$t('globals.warehouse')"
-                            :value="entity.warehouse?.name"
-                        />
-                        <VnLv
-                            :label="$t('globals.company')"
-                            :value="entity.company?.code"
-                        />
-                        <VnLv
-                            :label="$t('globals.deliveryPoint')"
-                            :value="entity.deliveryPoint?.name"
-                        />
-                        <VnLv
-                            :label="$t('globals.country')"
-                            :value="entity.countryCodeFk"
-                        />
-                        <VnLv
-                            :label="$t('vehicle.isKmTruckRate')"
-                            :value="!!entity.isKmTruckRate"
-                        />
-                        <VnLv
-                            :label="$t('vehicle.isActive')"
-                            :value="!!entity.isActive"
-                        />
-                    </QList>
-                </QCardSection>
-            </QCard>
-        </template>
-    </CardSummary>
-</template>
diff --git a/src/pages/Route/Vehicle/VehicleFilter.js b/src/pages/Route/Vehicle/VehicleFilter.js
deleted file mode 100644
index cbf5cc621..000000000
--- a/src/pages/Route/Vehicle/VehicleFilter.js
+++ /dev/null
@@ -1,76 +0,0 @@
-export default {
-    fields: [
-        'id',
-        'description',
-        'isActive',
-        'isKmTruckRate',
-        'warehouseFk',
-        'companyFk',
-        'numberPlate',
-        'chassis',
-        'supplierFk',
-        'supplierCoolerFk',
-        'tradeMark',
-        'fuelTypeFk',
-        'import',
-        'importCooler',
-        'vin',
-        'model',
-        'ppeFk',
-        'countryCodeFk',
-        'leasing',
-        'bankPolicyFk',
-        'vehicleTypeFk',
-        'deliveryPointFk',
-    ],
-    include: [
-        {
-            relation: 'warehouse',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'company',
-            scope: {
-                fields: ['id', 'code'],
-            },
-        },
-        {
-            relation: 'supplier',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'supplierCooler',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'fuelType',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'bankPolicy',
-            scope: {
-                fields: ['id', 'ref', 'dmsFk'],
-            },
-        },
-        {
-            relation: 'ppe',
-            scope: {
-                fields: ['id'],
-            },
-        },
-        {
-            relation: 'deliveryPoint',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-    ],
-};
diff --git a/src/pages/Route/Vehicle/VehicleList.vue b/src/pages/Route/Vehicle/VehicleList.vue
deleted file mode 100644
index e5b945010..000000000
--- a/src/pages/Route/Vehicle/VehicleList.vue
+++ /dev/null
@@ -1,224 +0,0 @@
-<script setup>
-import { ref, computed } from 'vue';
-import { useI18n } from 'vue-i18n';
-import VnTable from 'components/VnTable/VnTable.vue';
-import FetchData from 'src/components/FetchData.vue';
-import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import VehicleSummary from 'src/pages/Route/Vehicle/Card/VehicleSummary.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import VnSection from 'src/components/common/VnSection.vue';
-
-const { t } = useI18n();
-const { viewSummary } = useSummaryDialog();
-const warehouses = ref([]);
-const companies = ref([]);
-const countries = ref([]);
-const vehicleStates = ref([]);
-const vehicleTypes = ref([]);
-
-const columns = computed(() => [
-    {
-        name: 'isActive',
-        columnFilter: false,
-        align: 'center',
-    },
-    {
-        name: 'id',
-        label: t('globals.id'),
-        isId: true,
-        chip: {
-            condition: () => true,
-        },
-    },
-    {
-        name: 'description',
-        label: t('globals.description'),
-    },
-    {
-        name: 'tradeMark',
-        label: t('vehicle.tradeMark'),
-        cardVisible: true,
-    },
-    {
-        name: 'numberPlate',
-        label: t('vehicle.numberPlate'),
-        isTitle: true,
-    },
-    {
-        name: 'vehicleTypeFk',
-        label: t('globals.type'),
-        format: (row) => row.type,
-        columnFilter: {
-            component: 'select',
-            name: 'vehicleTypeFk',
-            options: vehicleTypes.value,
-        },
-        cardVisible: true,
-    },
-    {
-        name: 'vehicleStateFk',
-        label: t('globals.state'),
-        columnFilter: {
-            component: 'select',
-            name: 'vehicleStateFk',
-            optionLabel: 'state',
-            options: vehicleStates.value,
-        },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.state),
-    },
-    {
-        name: 'chassis',
-        label: t('vehicle.chassis'),
-    },
-    {
-        name: 'leasing',
-        label: t('vehicle.leasing'),
-    },
-    {
-        name: 'warehouseFk',
-        label: t('globals.warehouse'),
-        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouse),
-        columnFilter: {
-            component: 'select',
-            name: 'warehouseFk',
-            options: warehouses.value,
-        },
-        cardVisible: true,
-    },
-    {
-        name: 'companyFk',
-        label: t('globals.company'),
-        format: (row, dashIfEmpty) => dashIfEmpty(row.company),
-        columnFilter: {
-            component: 'select',
-            name: 'companyFk',
-            optionLabel: 'code',
-            options: companies.value,
-        },
-    },
-    {
-        name: 'countryCodeFk',
-        label: t('globals.country'),
-        columnFilter: {
-            component: 'select',
-            name: 'countryCodeFk',
-            optionValue: 'code',
-            optionLabel: 'code',
-            options: countries.value,
-        },
-    },
-    {
-        align: 'right',
-        name: 'tableActions',
-        actions: [
-            {
-                title: t('components.smartCard.openSummary'),
-                icon: 'preview',
-                action: (row) => viewSummary(row.id, VehicleSummary),
-            },
-        ],
-    },
-]);
-</script>
-<template>
-    <FetchData
-        url="Warehouses"
-        :filter="{ fields: ['id', 'name'] }"
-        @on-fetch="(data) => (warehouses = data)"
-        auto-load
-    />
-    <FetchData
-        url="Companies"
-        :filter="{ fields: ['id', 'code'] }"
-        @on-fetch="(data) => (companies = data)"
-        auto-load
-    />
-    <FetchData
-        url="Countries"
-        :filter="{ fields: ['name', 'code'] }"
-        @on-fetch="(data) => (countries = data)"
-        auto-load
-    />
-    <FetchData
-        url="VehicleStates"
-        :filter="{ fields: ['id', 'state'] }"
-        @on-fetch="(data) => (vehicleStates = data)"
-        auto-load
-    />
-    <FetchData
-        url="VehicleTypes"
-        :filter="{ fields: ['id', 'name'] }"
-        @on-fetch="(data) => (vehicleTypes = data)"
-        auto-load
-    />
-    <VnSection
-        data-key="VehicleList"
-        :columns="columns"
-        prefix="vehicle"
-        :array-data-props="{
-            url: 'Vehicles/filter',
-        }"
-    >
-        <template #body>
-            <VnTable
-                ref="tableRef"
-                data-key="VehicleList"
-                :columns="columns"
-                redirect="route/vehicle"
-                :create="{
-                    urlCreate: 'Vehicles',
-                    title: t('vehicle.create'),
-                    onDataSaved: ({ id }) => $refs.tableRef.redirect(id),
-                    formInitialData: { isActive: true, isKmTruckRate: false },
-                }"
-                :use-model="true"
-                :right-search="false"
-            >
-                <template #column-isActive="{ row }">
-                    <span>
-                        <QIcon
-                            v-if="!row.isActive"
-                            name="vn:inactive-car"
-                            color="primary"
-                            size="xs"
-                        >
-                            <QTooltip>{{ $t('globals.inactive') }}</QTooltip>
-                        </QIcon>
-                    </span>
-                </template>
-                <template #more-create-dialog="{ data }">
-                    <VnInput
-                        v-model="data.numberPlate"
-                        :label="$t('vehicle.numberPlate')"
-                        :uppercase="true"
-                    />
-                    <VnInput v-model="data.tradeMark" :label="$t('vehicle.tradeMark')" />
-                    <VnInput v-model="data.model" :label="$t('globals.model')" />
-                    <VnSelect
-                        v-model="data.vehicleTypeFk"
-                        :label="$t('globals.type')"
-                        :options="vehicleTypes"
-                    />
-                    <VnSelect
-                        v-model="data.warehouseFk"
-                        :label="$t('globals.warehouse')"
-                        :options="warehouses"
-                    />
-                    <VnSelect
-                        v-model="data.countryCodeFk"
-                        :label="$t('globals.country')"
-                        option-value="code"
-                        option-label="name"
-                        :options="countries"
-                    />
-                    <VnInput
-                        v-model="data.description"
-                        :label="$t('globals.description')"
-                    />
-                    <QCheckbox to v-model="data.isActive" :label="$t('globals.active')" />
-                </template>
-            </VnTable>
-        </template>
-    </VnSection>
-</template>
diff --git a/src/pages/Route/Vehicle/locale/en.yml b/src/pages/Route/Vehicle/locale/en.yml
deleted file mode 100644
index c92022f9d..000000000
--- a/src/pages/Route/Vehicle/locale/en.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-vehicle:
-    tradeMark: Trade Mark
-    numberPlate: Nº Plate
-    chassis: Chassis
-    leasing: Leasing
-    isKmTruckRate: Trailer
-    delete: Delete Vehicle
-    supplierCooler: Supplier Cooler
-    vin: VIN
-    ppe: Ppe
-    isActive: Active
-    nLeasing: Nº Leasing
-    create: Create Vehicle
-    amountCooler: Amount cooler
-    remove: Vehicle removed
-    search: Search Vehicle
-    searchInfo: Search by id or number plate
-    params:
-        vehicleTypeFk: Type
-        vehicleStateFk: State
diff --git a/src/pages/Route/Vehicle/locale/es.yml b/src/pages/Route/Vehicle/locale/es.yml
deleted file mode 100644
index c878f97ac..000000000
--- a/src/pages/Route/Vehicle/locale/es.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-vehicle:
-    tradeMark: Marca
-    numberPlate: Matrícula
-    chassis: Nº de bastidor
-    leasing: Leasing
-    isKmTruckRate: Trailer
-    delete: Eliminar vehículo
-    supplierCooler: Proveedor Frío
-    vin: VIN
-    ppe: Nº Inmovilizado
-    create: Crear vehículo
-    amountCooler: Importe frío
-    isActive: Activo
-    nLeasing: Nº leasing
-    remove: Vehículo eliminado
-    search: Buscar Vehículo
-    searchInfo: Buscar por id o matrícula
-    params:
-        vehicleTypeFk: Tipo
-        vehicleStateFk: Estado
diff --git a/src/pages/Shelving/Card/ShelvingCard.vue b/src/pages/Shelving/Card/ShelvingCard.vue
index 9e0ac8ad2..41a0db33c 100644
--- a/src/pages/Shelving/Card/ShelvingCard.vue
+++ b/src/pages/Shelving/Card/ShelvingCard.vue
@@ -1,14 +1,12 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ShelvingDescriptor from 'pages/Shelving/Card/ShelvingDescriptor.vue';
-import filter from './ShelvingFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Shelving"
-        url="Shelvings"
-        :filter="filter"
+        base-url="Shelvings"
         :descriptor="ShelvingDescriptor"
     />
 </template>
diff --git a/src/pages/Shelving/Card/ShelvingDescriptor.vue b/src/pages/Shelving/Card/ShelvingDescriptor.vue
index 5e618aa7f..b1ff4a8ae 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptor.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptor.vue
@@ -1,12 +1,12 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
+import useCardDescription from 'composables/useCardDescription';
 import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
-import filter from './ShelvingFilter.js';
 
 const $props = defineProps({
     id: {
@@ -22,13 +22,35 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
+
+const filter = {
+    include: [
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: { fields: ['nickname'] },
+                },
+            },
+        },
+        { relation: 'parking' },
+    ],
+};
+const data = ref(useCardDescription());
+const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
+
 <template>
     <CardDescriptor
+        module="Shelving"
         :url="`Shelvings/${entityId}`"
         :filter="filter"
-        title="code"
-        data-key="Shelving"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        data-key="Shelvings"
+        @on-fetch="setData"
     >
         <template #body="{ entity }">
             <VnLv :label="t('globals.code')" :value="entity.code" />
diff --git a/src/pages/Shelving/Card/ShelvingFilter.js b/src/pages/Shelving/Card/ShelvingFilter.js
deleted file mode 100644
index e302e1b9c..000000000
--- a/src/pages/Shelving/Card/ShelvingFilter.js
+++ /dev/null
@@ -1,15 +0,0 @@
-export default {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
diff --git a/src/pages/Shelving/Card/ShelvingForm.vue b/src/pages/Shelving/Card/ShelvingForm.vue
index 078058342..3bbd94a0a 100644
--- a/src/pages/Shelving/Card/ShelvingForm.vue
+++ b/src/pages/Shelving/Card/ShelvingForm.vue
@@ -1,4 +1,5 @@
 <script setup>
+import { useI18n } from 'vue-i18n';
 import { computed } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import VnRow from 'components/ui/VnRow.vue';
@@ -6,8 +7,8 @@ import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
-import filter from './ShelvingFilter.js';
 
+const { t } = useI18n();
 const route = useRoute();
 const router = useRouter();
 const entityId = computed(() => route.params.id ?? null);
@@ -19,6 +20,22 @@ const defaultInitialData = {
     isRecyclable: false,
 };
 
+const shelvingFilter = {
+    include: [
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: { fields: ['nickname'] },
+                },
+            },
+        },
+        { relation: 'parking' },
+    ],
+};
+
 const onSave = (shelving, newShelving) => {
     if (isNew) {
         router.push({ name: 'ShelvingBasicData', params: { id: newShelving?.id } });
@@ -28,10 +45,11 @@ const onSave = (shelving, newShelving) => {
 <template>
     <VnSubToolbar v-if="isNew" />
     <FormModel
+        :url="isNew ? null : `Shelvings/${entityId}`"
         :url-create="isNew ? 'Shelvings' : null"
         :observe-form-changes="!isNew"
-        :filter="filter"
-        model="Shelving"
+        :filter="shelvingFilter"
+        model="shelving"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -40,7 +58,7 @@ const onSave = (shelving, newShelving) => {
             <VnRow>
                 <VnInput
                     v-model="data.code"
-                    :label="$t('globals.code')"
+                    :label="t('globals.code')"
                     :rules="validate('Shelving.code')"
                 />
                 <VnSelect
@@ -50,7 +68,7 @@ const onSave = (shelving, newShelving) => {
                     option-label="code"
                     :filter-options="['id', 'code']"
                     :fields="['id', 'code']"
-                    :label="$t('shelving.list.parking')"
+                    :label="t('shelving.list.parking')"
                     :rules="validate('Shelving.parkingFk')"
                 />
             </VnRow>
@@ -58,12 +76,12 @@ const onSave = (shelving, newShelving) => {
                 <VnInput
                     v-model="data.priority"
                     type="number"
-                    :label="$t('shelving.list.priority')"
+                    :label="t('shelving.list.priority')"
                     :rules="validate('Shelving.priority')"
                 />
                 <QCheckbox
                     v-model="data.isRecyclable"
-                    :label="$t('shelving.summary.recyclable')"
+                    :label="t('shelving.summary.recyclable')"
                     :rules="validate('Shelving.isRecyclable')"
                 />
             </VnRow>
diff --git a/src/pages/Shelving/Card/ShelvingSearchbar.vue b/src/pages/Shelving/Card/ShelvingSearchbar.vue
index 741b11663..bfc8ad4f5 100644
--- a/src/pages/Shelving/Card/ShelvingSearchbar.vue
+++ b/src/pages/Shelving/Card/ShelvingSearchbar.vue
@@ -1,15 +1,15 @@
 <script setup>
 import VnSearchbar from 'components/ui/VnSearchbar.vue';
-import exprBuilder from '../ShelvingExprBuilder.js';
+import {useI18n} from "vue-i18n";
+const { t } = useI18n();
 </script>
 
 <template>
     <VnSearchbar
         data-key="ShelvingList"
         url="Shelvings"
-        :label="$t('Search shelving')"
-        :info="$t('You can search by shelving reference')"
-        :expr-builder="exprBuilder"
+        :label="t('Search shelving')"
+        :info="t('You can search by shelving reference')"
     />
 </template>
 
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index f89ff4d78..39fa4639f 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -1,10 +1,10 @@
 <script setup>
 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 filter from './ShelvingFilter.js';
 import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
 
 const $props = defineProps({
@@ -14,9 +14,25 @@ const $props = defineProps({
     },
 });
 const route = useRoute();
-
+const { t } = useI18n();
 const summary = ref({});
 const entityId = computed(() => $props.id || route.params.id);
+
+const filter = {
+    include: [
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: { fields: ['nickname'] },
+                },
+            },
+        },
+        { relation: 'parking' },
+    ],
+};
 </script>
 
 <template>
@@ -25,7 +41,7 @@ const entityId = computed(() => $props.id || route.params.id);
             ref="summary"
             :url="`Shelvings/${entityId}`"
             :filter="filter"
-            data-key="Shelving"
+            data-key="ShelvingSummary"
         >
             <template #header="{ entity }">
                 <div>{{ entity.code }}</div>
@@ -42,19 +58,16 @@ const entityId = computed(() => $props.id || route.params.id);
                         class="header header-link"
                         :to="{ name: 'ShelvingBasicData', params: { id: entityId } }"
                     >
-                        {{ $t('globals.pageTitles.basicData') }}
+                        {{ t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </RouterLink>
-                    <VnLv :label="$t('globals.code')" :value="entity.code" />
+                    <VnLv :label="t('globals.code')" :value="entity.code" />
                     <VnLv
-                        :label="$t('shelving.list.parking')"
+                        :label="t('shelving.list.parking')"
                         :value="entity.parking?.code"
                     />
-                    <VnLv
-                        :label="$t('shelving.list.priority')"
-                        :value="entity.priority"
-                    />
-                    <VnLv v-if="entity.worker" :label="$t('globals.worker')">
+                    <VnLv :label="t('shelving.list.priority')" :value="entity.priority" />
+                    <VnLv v-if="entity.worker" :label="t('globals.worker')">
                         <template #value>
                             <VnUserLink
                                 :name="entity.worker?.user?.nickname"
@@ -63,7 +76,7 @@ const entityId = computed(() => $props.id || route.params.id);
                         </template>
                     </VnLv>
                     <VnLv
-                        :label="$t('shelving.summary.recyclable')"
+                        :label="t('shelving.summary.recyclable')"
                         :value="entity.isRecyclable"
                     />
                 </QCard>
diff --git a/src/pages/Shelving/Parking/Card/ParkingFilter.js b/src/pages/Shelving/Parking/Card/ParkingFilter.js
deleted file mode 100644
index fd1855c45..000000000
--- a/src/pages/Shelving/Parking/Card/ParkingFilter.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default {
-    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
-    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
-};
diff --git a/src/pages/Shelving/Parking/ParkingExprBuilder.js b/src/pages/Shelving/Parking/ParkingExprBuilder.js
deleted file mode 100644
index 16d2262c8..000000000
--- a/src/pages/Shelving/Parking/ParkingExprBuilder.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export default (param, value) => {
-    switch (param) {
-        case 'code':
-            return { [param]: { like: `%${value}%` } };
-        case 'sectorFk':
-            return { [param]: value };
-        case 'search':
-            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
-    }
-};
diff --git a/src/pages/Shelving/ShelvingExprBuilder.js b/src/pages/Shelving/ShelvingExprBuilder.js
deleted file mode 100644
index b9aad8a71..000000000
--- a/src/pages/Shelving/ShelvingExprBuilder.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export default (param, value) => {
-    switch (param) {
-        case 'search':
-            return { code: { like: `%${value}%` } };
-        case 'parkingFk':
-        case 'userFk':
-        case 'isRecyclable':
-            return { [param]: value };
-    }
-};
diff --git a/src/pages/Shelving/ShelvingList.vue b/src/pages/Shelving/ShelvingList.vue
index 4e0c21100..cf158e76b 100644
--- a/src/pages/Shelving/ShelvingList.vue
+++ b/src/pages/Shelving/ShelvingList.vue
@@ -1,5 +1,6 @@
 <script setup>
 import VnPaginate from 'components/ui/VnPaginate.vue';
+import { useI18n } from 'vue-i18n';
 import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import { useRouter } from 'vue-router';
@@ -7,9 +8,9 @@ import ShelvingFilter from 'pages/Shelving/Card/ShelvingFilter.vue';
 import ShelvingSummary from 'pages/Shelving/Card/ShelvingSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import VnSection from 'src/components/common/VnSection.vue';
-import exprBuilder from './ShelvingExprBuilder.js';
 
 const router = useRouter();
+const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
 const dataKey = 'ShelvingList';
 
@@ -20,6 +21,17 @@ const filter = {
 function navigate(id) {
     router.push({ path: `/shelving/${id}` });
 }
+
+function exprBuilder(param, value) {
+    switch (param) {
+        case 'search':
+            return { code: { like: `%${value}%` } };
+        case 'parkingFk':
+        case 'userFk':
+        case 'isRecyclable':
+            return { [param]: value };
+    }
+}
 </script>
 
 <template>
@@ -50,18 +62,18 @@ function navigate(id) {
                             >
                                 <template #list-items>
                                     <VnLv
-                                        :label="$t('shelving.list.parking')"
-                                        :title-label="$t('shelving.list.parking')"
+                                        :label="t('shelving.list.parking')"
+                                        :title-label="t('shelving.list.parking')"
                                         :value="row.parking?.code"
                                     />
                                     <VnLv
-                                        :label="$t('shelving.list.priority')"
+                                        :label="t('shelving.list.priority')"
                                         :value="row?.priority"
                                     />
                                 </template>
                                 <template #actions>
                                     <QBtn
-                                        :label="$t('components.smartCard.openSummary')"
+                                        :label="t('components.smartCard.openSummary')"
                                         @click.stop="viewSummary(row.id, ShelvingSummary)"
                                         color="primary"
                                     />
@@ -72,9 +84,9 @@ function navigate(id) {
                 </div>
                 <QPageSticky :offset="[20, 20]">
                     <RouterLink :to="{ name: 'ShelvingCreate' }">
-                        <QBtn fab icon="add" color="primary" v-shortcut="'+'" />
+                        <QBtn fab icon="add" color="primary" shortcut="+" />
                         <QTooltip>
-                            {{ $t('shelving.list.newShelving') }}
+                            {{ t('shelving.list.newShelving') }}
                         </QTooltip>
                     </RouterLink>
                 </QPageSticky>
diff --git a/src/pages/Supplier/Card/SupplierAccounts.vue b/src/pages/Supplier/Card/SupplierAccounts.vue
index 365eb67a1..4a6901d1d 100644
--- a/src/pages/Supplier/Card/SupplierAccounts.vue
+++ b/src/pages/Supplier/Card/SupplierAccounts.vue
@@ -71,7 +71,7 @@ function bankEntityFilter(val, update) {
         filteredBankEntitiesOptions.value = bankEntitiesOptions.value.filter(
             (bank) =>
                 bank.bic.toLowerCase().startsWith(needle) ||
-                bank.name.toLowerCase().includes(needle),
+                bank.name.toLowerCase().includes(needle)
         );
     });
 }
@@ -170,7 +170,7 @@ function bankEntityFilter(val, update) {
                             <QIcon name="info" class="cursor-pointer">
                                 <QTooltip>{{
                                     t(
-                                        'Name of the bank account holder if different from the provider',
+                                        'Name of the bank account holder if different from the provider'
                                     )
                                 }}</QTooltip>
                             </QIcon>
@@ -194,7 +194,7 @@ function bankEntityFilter(val, update) {
                     <QBtn
                         flat
                         icon="add"
-                        v-shortcut
+                        shortcut="+"
                         class="cursor-pointer"
                         color="primary"
                         @click="supplierAccountRef.insert()"
diff --git a/src/pages/Supplier/Card/SupplierAddresses.vue b/src/pages/Supplier/Card/SupplierAddresses.vue
index c4c0ab7be..e568962ff 100644
--- a/src/pages/Supplier/Card/SupplierAddresses.vue
+++ b/src/pages/Supplier/Card/SupplierAddresses.vue
@@ -89,7 +89,7 @@ const redirectToUpdateView = (addressData) => {
                 icon="add"
                 color="primary"
                 @click="redirectToCreateView()"
-                v-shortcut="'+'"
+                shortcut="+"
             />
             <QTooltip>
                 {{ t('New address') }}
diff --git a/src/pages/Supplier/Card/SupplierAgencyTerm.vue b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
index ab21f1f76..99b672cc4 100644
--- a/src/pages/Supplier/Card/SupplierAgencyTerm.vue
+++ b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
@@ -114,7 +114,7 @@ const redirectToCreateView = () => {
             icon="add"
             color="primary"
             @click="redirectToCreateView()"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip>
             {{ t('supplier.agencyTerms.addRow') }}
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index 631700a4a..f6c13b7af 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -19,8 +19,9 @@ const companySizes = [
 </script>
 <template>
     <FormModel
+        :url="`Suppliers/${route.params.id}`"
         :url-update="`Suppliers/${route.params.id}`"
-        model="Supplier"
+        model="supplier"
         auto-load
         :clear-store-on-unmount="false"
         @on-data-saved="arrayData.fetch({})"
diff --git a/src/pages/Supplier/Card/SupplierCard.vue b/src/pages/Supplier/Card/SupplierCard.vue
index e30f79f96..594026d18 100644
--- a/src/pages/Supplier/Card/SupplierCard.vue
+++ b/src/pages/Supplier/Card/SupplierCard.vue
@@ -1,13 +1,19 @@
 <script setup>
+import VnCard from 'components/common/VnCard.vue';
 import SupplierDescriptor from './SupplierDescriptor.vue';
-import VnCardBeta from 'src/components/common/VnCardBeta.vue';
-import filter from './SupplierFilter.js';
+import SupplierListFilter from '../SupplierListFilter.vue';
 </script>
 <template>
-    <VnCardBeta
+    <VnCard
         data-key="Supplier"
-        url="Suppliers"
+        base-url="Suppliers"
         :descriptor="SupplierDescriptor"
-        :filter="filter"
+        :filter-panel="SupplierListFilter"
+        search-data-key="SupplierList"
+        :searchbar-props="{
+            url: 'Suppliers/filter',
+            searchUrl: 'table',
+            label: 'Search suppliers',
+        }"
     />
 </template>
diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue
index 718de95dd..8a7021fb3 100644
--- a/src/pages/Supplier/Card/SupplierConsumption.vue
+++ b/src/pages/Supplier/Card/SupplierConsumption.vue
@@ -16,7 +16,6 @@ import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import { useState } from 'src/composables/useState';
 import { useArrayData } from 'composables/useArrayData';
-import RightMenu from 'src/components/common/RightMenu.vue';
 
 const state = useState();
 const stateStore = useStateStore();
@@ -174,59 +173,59 @@ onMounted(async () => {
             </div>
         </div>
     </Teleport>
-    <RightMenu>
-        <template #right-panel>
+    <QPage class="column items-center q-pa-md">
+        <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
             <SupplierConsumptionFilter data-key="SupplierConsumption" />
-        </template>
-    </RightMenu>
-    <QTable
-        :rows="rows"
-        row-key="id"
-        hide-header
-        class="full-width q-mt-md"
-        :no-data-label="t('No results')"
-    >
-        <template #body="{ row }">
-            <QTr>
-                <QTd no-hover>
-                    <span class="label">{{ t('supplier.consumption.entry') }}: </span>
-                    <span>{{ row.id }}</span>
-                </QTd>
-                <QTd no-hover>
-                    <span class="label">{{ t('globals.date') }}: </span>
-                    <span>{{ toDate(row.shipped) }}</span></QTd
-                >
-                <QTd colspan="6" no-hover>
-                    <span class="label">{{ t('globals.reference') }}: </span>
-                    <span>{{ row.invoiceNumber }}</span>
-                </QTd>
-            </QTr>
-            <QTr v-for="(buy, index) in row.buys" :key="index">
-                <QTd no-hover>
-                    <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
-                    <ItemDescriptorProxy :id="buy.itemFk" />
-                </QTd>
+        </Teleport>
+        <QTable
+            :rows="rows"
+            row-key="id"
+            hide-header
+            class="full-width q-mt-md"
+            :no-data-label="t('No results')"
+        >
+            <template #body="{ row }">
+                <QTr>
+                    <QTd no-hover>
+                        <span class="label">{{ t('supplier.consumption.entry') }}: </span>
+                        <span>{{ row.id }}</span>
+                    </QTd>
+                    <QTd no-hover>
+                        <span class="label">{{ t('globals.date') }}: </span>
+                        <span>{{ toDate(row.shipped) }}</span></QTd
+                    >
+                    <QTd colspan="6" no-hover>
+                        <span class="label">{{ t('globals.reference') }}: </span>
+                        <span>{{ row.invoiceNumber }}</span>
+                    </QTd>
+                </QTr>
+                <QTr v-for="(buy, index) in row.buys" :key="index">
+                    <QTd no-hover>
+                        <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
+                        <ItemDescriptorProxy :id="buy.itemFk" />
+                    </QTd>
 
-                <QTd no-hover>
-                    <span>{{ buy.subName }}</span>
-                    <FetchedTags :item="buy" />
-                </QTd>
-                <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
-                <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
-                <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
-            </QTr>
-            <QTr>
-                <QTd colspan="5" no-hover>
-                    <span class="label">{{ t('Total entry') }}: </span>
-                    <span>{{ row.total }} €</span>
-                </QTd>
-                <QTd no-hover>
-                    <span class="label">{{ t('Total stems') }}: </span>
-                    <span>{{ row.quantity }}</span>
-                </QTd>
-            </QTr>
-        </template>
-    </QTable>
+                    <QTd no-hover>
+                        <span>{{ buy.subName }}</span>
+                        <FetchedTags :item="buy" />
+                    </QTd>
+                    <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
+                    <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
+                    <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
+                </QTr>
+                <QTr>
+                    <QTd colspan="5" no-hover>
+                        <span class="label">{{ t('Total entry') }}: </span>
+                        <span>{{ row.total }} €</span>
+                    </QTd>
+                    <QTd no-hover>
+                        <span class="label">{{ t('Total stems') }}: </span>
+                        <span>{{ row.quantity }}</span>
+                    </QTd>
+                </QTr>
+            </template>
+        </QTable>
+    </QPage>
 </template>
 
 <style scoped lang="scss">
diff --git a/src/pages/Supplier/Card/SupplierContacts.vue b/src/pages/Supplier/Card/SupplierContacts.vue
index f96d92ab1..6781c8d34 100644
--- a/src/pages/Supplier/Card/SupplierContacts.vue
+++ b/src/pages/Supplier/Card/SupplierContacts.vue
@@ -78,7 +78,7 @@ const insertRow = () => {
                     <QBtn
                         flat
                         icon="add"
-                        v-shortcut="'+'"
+                        shortcut="+"
                         class="cursor-pointer"
                         color="primary"
                         @click="insertRow()"
diff --git a/src/pages/Supplier/Card/SupplierDescriptor.vue b/src/pages/Supplier/Card/SupplierDescriptor.vue
index 462bdf853..37c9c1cff 100644
--- a/src/pages/Supplier/Card/SupplierDescriptor.vue
+++ b/src/pages/Supplier/Card/SupplierDescriptor.vue
@@ -7,8 +7,8 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
 import { toDateString } from 'src/filters';
+import useCardDescription from 'src/composables/useCardDescription';
 import { getUrl } from 'src/composables/getUrl';
-import filter from './SupplierFilter.js';
 import { useArrayData } from 'src/composables/useArrayData';
 
 const $props = defineProps({
@@ -28,6 +28,42 @@ const { t } = useI18n();
 const url = ref();
 const arrayData = useArrayData();
 
+const filter = {
+    fields: [
+        'id',
+        'name',
+        'nickname',
+        'nif',
+        'payMethodFk',
+        'payDemFk',
+        'payDay',
+        'isActive',
+        'isReal',
+        'isTrucker',
+        'account',
+    ],
+    include: [
+        {
+            relation: 'payMethod',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'payDem',
+            scope: {
+                fields: ['id', 'payDem'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'fi'],
+            },
+        },
+    ],
+};
+
 onMounted(async () => {
     url.value = await getUrl('');
 });
@@ -36,6 +72,11 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
+const data = ref(useCardDescription());
+const setData = (entity) => {
+    data.value = useCardDescription(entity.ref, entity.id);
+};
+
 const supplier = computed(() => arrayData.store.data);
 
 const getEntryQueryParams = (supplier) => {
@@ -62,9 +103,13 @@ const getEntryQueryParams = (supplier) => {
 
 <template>
     <CardDescriptor
+        module="Supplier"
         :url="`Suppliers/${entityId}`"
+        :title="data.title"
+        :subtitle="data.subtitle"
         :filter="filter"
-        data-key="Supplier"
+        @on-fetch="setData"
+        data-key="supplierDescriptor"
         :summary="$props.summary"
     >
         <template #body="{ entity }">
diff --git a/src/pages/Supplier/Card/SupplierFilter.js b/src/pages/Supplier/Card/SupplierFilter.js
deleted file mode 100644
index 3ce5c3de2..000000000
--- a/src/pages/Supplier/Card/SupplierFilter.js
+++ /dev/null
@@ -1,35 +0,0 @@
-export default {
-    fields: [
-        'id',
-        'name',
-        'nickname',
-        'nif',
-        'payMethodFk',
-        'payDemFk',
-        'payDay',
-        'isActive',
-        'isSerious',
-        'isTrucker',
-        'account',
-    ],
-    include: [
-        {
-            relation: 'payMethod',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'payDem',
-            scope: {
-                fields: ['id', 'payDem'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'fi'],
-            },
-        },
-    ],
-};
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index ecee5b76b..e569eb236 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -10,7 +10,6 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
 import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -183,11 +182,18 @@ function handleLocation(data, location) {
                         v-model="data.isTrucker"
                         :label="t('supplier.fiscalData.isTrucker')"
                     />
-                    <VnCheckbox
-                        v-model="data.isVies"
-                        :label="t('globals.isVies')" 
-                        :info="t('whenActivatingIt')" 
-                    />
+                    <div class="row items-center">
+                        <QCheckbox v-model="data.isVies" :label="t('globals.isVies')" />
+                        <QIcon name="info" size="xs" class="cursor-pointer q-ml-sm">
+                            <QTooltip>
+                                {{
+                                    t(
+                                        'When activating it, do not enter the country code in the ID field.'
+                                    )
+                                }}
+                            </QTooltip>
+                        </QIcon>
+                    </div>
                 </div>
             </VnRow>
         </template>
@@ -195,8 +201,6 @@ function handleLocation(data, location) {
 </template>
 
 <i18n>
-en:
-    whenActivatingIt: When activating it, do not enter the country code in the ID field.
 es:
-    whenActivatingIt: Al activarlo, no informar el código del país en el campo nif.
+    When activating it, do not enter the country code in the ID field.: Al activarlo, no informar el código del país en el campo nif
 </i18n>
diff --git a/src/pages/Supplier/SupplierList.vue b/src/pages/Supplier/SupplierList.vue
index 600790745..85cc11857 100644
--- a/src/pages/Supplier/SupplierList.vue
+++ b/src/pages/Supplier/SupplierList.vue
@@ -2,15 +2,14 @@
 import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnTable from 'components/VnTable/VnTable.vue';
-import VnSection from 'src/components/common/VnSection.vue';
+import VnSearchbar from 'components/ui/VnSearchbar.vue';
+import RightMenu from 'src/components/common/RightMenu.vue';
+import SupplierListFilter from './SupplierListFilter.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-const dataKey = 'SupplierList';
-const provincesOptions = ref([]);
+
 const columns = computed(() => [
     {
         align: 'left',
@@ -105,62 +104,38 @@ const columns = computed(() => [
     },
 ]);
 </script>
+
 <template>
-    <FetchData
-        url="Provinces"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
-        @on-fetch="(data) => (provincesOptions = data)"
-        auto-load
-    />
-    <VnSection
-        :data-key="dataKey"
-        :columns="columns"
-        prefix="supplier"
-        :array-data-props="{
-            url: 'Suppliers/filter',
-            order: 'id ASC',
+    <VnSearchbar data-key="SuppliersList" :limit="20" :label="t('Search suppliers')" />
+    <RightMenu>
+        <template #right-panel>
+            <SupplierListFilter data-key="SuppliersList" />
+        </template>
+    </RightMenu>
+    <VnTable
+        ref="tableRef"
+        data-key="SuppliersList"
+        url="Suppliers/filter"
+        redirect="supplier"
+        :create="{
+            urlCreate: 'Suppliers/newSupplier',
+            title: t('Create Supplier'),
+            onDataSaved: ({ id }) => tableRef.redirect(id),
+            formInitialData: {},
+            mapper: (data) => {
+                data.name = data.socialName;
+
+                return data;
+            },
         }"
+        :right-search="false"
+        order="id ASC"
+        :columns="columns"
     >
-        <template #body>
-            <VnTable
-                ref="tableRef"
-                :data-key="dataKey"
-                :create="{
-                    urlCreate: 'Suppliers/newSupplier',
-                    title: t('Create Supplier'),
-                    onDataSaved: ({ id }) => tableRef.redirect(id),
-                    formInitialData: {},
-                    mapper: (data) => {
-                        data.name = data.socialName;
-                        delete data.socialName;
-                        return data;
-                    },
-                }"
-                :columns="columns"
-                redirect="supplier"
-                :right-search="false"
-            >
-                <template #more-create-dialog="{ data }">
-                    <VnInput
-                        :label="t('globals.name')"
-                        v-model="data.socialName"
-                        :uppercase="true"
-                    />
-                </template>
-            </VnTable>
-        </template>
-        <template #moreFilterPanel="{ params, searchFn }">
-            <VnSelect
-                :label="t('globals.params.provinceFk')"
-                v-model="params.provinceFk"
-                @update:model-value="searchFn()"
-                :options="provincesOptions"
-                filled
-                dense
-                class="q-px-sm q-pr-lg"
-            />
-        </template>
-    </VnSection>
+        <template #more-create-dialog="{ data }">
+            <VnInput :label="t('globals.name')" v-model="data.socialName" :uppercase="true" />
+            </template>
+    </VnTable>
 </template>
 
 <i18n>
diff --git a/src/pages/Supplier/SupplierListFilter.vue b/src/pages/Supplier/SupplierListFilter.vue
new file mode 100644
index 000000000..b170a35cc
--- /dev/null
+++ b/src/pages/Supplier/SupplierListFilter.vue
@@ -0,0 +1,122 @@
+<script setup>
+import { ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import FetchData from 'components/FetchData.vue';
+
+const props = defineProps({
+    dataKey: {
+        type: String,
+        required: true,
+    },
+});
+
+const { t } = useI18n();
+
+const provincesOptions = ref([]);
+const countriesOptions = ref([]);
+</script>
+
+<template>
+    <FetchData
+        url="Provinces"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
+        @on-fetch="(data) => (provincesOptions = data)"
+        auto-load
+    />
+    <FetchData
+        url="countries"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
+        @on-fetch="(data) => (countriesOptions = data)"
+        auto-load
+    />
+    <VnFilterPanel
+        :data-key="props.dataKey"
+        :search-button="true"
+        :unremovable-params="['supplierFk']"
+    >
+        <template #tags="{ tag, formatFn }">
+            <div class="q-gutter-x-xs">
+                <strong>{{ t(`params.${tag.label}`) }}: </strong>
+                <span>{{ formatFn(tag.value) }}</span>
+            </div>
+        </template>
+        <template #body="{ params, searchFn }">
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.search"
+                        :label="t('params.search')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.nickname"
+                        :label="t('params.nickname')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput v-model="params.nif" :label="t('params.nif')" is-outlined />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('params.provinceFk')"
+                        v-model="params.provinceFk"
+                        @update:model-value="searchFn()"
+                        :options="provincesOptions"
+                        option-value="id"
+                        option-label="name"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('params.countryFk')"
+                        v-model="params.countryFk"
+                        @update:model-value="searchFn()"
+                        :options="countriesOptions"
+                        option-value="id"
+                        option-label="name"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+        </template>
+    </VnFilterPanel>
+</template>
+
+<i18n>
+en:
+    params:
+        search: General search
+        nickname: Alias
+        nif: Tax number
+        provinceFk: Province
+        countryFk: Country
+es:
+    params:
+        search: Búsqueda general
+        nickname: Alias
+        nif: NIF/CIF
+        provinceFk: Provincia
+        countryFk: País
+</i18n>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
index 055c9a0ff..c6a85c287 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
@@ -9,9 +9,8 @@ import FetchData from 'components/FetchData.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toCurrency } from 'filters/index';
 import { useRole } from 'src/composables/useRole';
-import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
-const haveNegatives = defineModel('have-negatives', { type: Boolean, required: true });
+const haveNegatives = defineModel('haveNegatives', { type: Boolean, required: true });
 const formData = defineModel({ type: Object, required: true });
 
 const stateStore = useStateStore();
@@ -183,19 +182,22 @@ onMounted(async () => {
         </QCard>
         <QCard
             v-if="haveNegatives"
-            class="q-pa-xs q-mb-md q-ma-md color-vn-text"
+            class="q-pa-md q-mb-md q-ma-md color-vn-text"
             bordered
             flat
             style="border-color: black"
         >
             <QCardSection horizontal class="flex row items-center">
-                <VnCheckbox
-                    v-model="formData.withoutNegatives"
+                <QCheckbox
                     :label="t('basicData.withoutNegatives')"
-                    :info="t('basicData.withoutNegativesInfo')"
+                    v-model="formData.withoutNegatives"
                     :toggle-indeterminate="false"
-                    size="xs"
                 />
+                <QIcon name="info" size="xs" class="q-ml-sm">
+                    <QTooltip max-width="350px">
+                        {{ t('basicData.withoutNegativesInfo') }}
+                    </QTooltip>
+                </QIcon>
             </QCardSection>
         </QCard>
     </QDrawer>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index 9d70fea38..cf4481537 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -260,7 +260,7 @@ async function getZone(options) {
         auto-load
     />
     <QForm>
-        <VnRow class="row q-gutter-md q-mb-md no-wrap">
+        <VnRow>
             <VnSelect
                 :label="t('ticketList.client')"
                 v-model="clientId"
@@ -296,7 +296,7 @@ async function getZone(options) {
                 :rules="validate('ticketList.warehouse')"
             />
         </VnRow>
-        <VnRow class="row q-gutter-md q-mb-md no-wrap">
+        <VnRow>
             <VnSelect
                 :label="t('basicData.address')"
                 v-model="addressId"
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index ef2eb75d6..89249b899 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -1,7 +1,7 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, onBeforeMount } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 
 import TicketBasicData from './TicketBasicData.vue';
 import TicketBasicDataForm from './TicketBasicDataForm.vue';
@@ -9,69 +9,104 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
-import { useArrayData } from 'src/composables/useArrayData';
 
 const { notify } = useNotify();
+const route = useRoute();
 const router = useRouter();
 const { t } = useI18n();
 const stepperRef = ref(null);
 const { openConfirmationModal } = useVnConfirm();
 
 const step = ref(1);
-const haveNegatives = ref(true);
+const formData = ref({});
+const initialDataLoaded = ref(false);
+const haveNegatives = ref(false);
 
-const ticket = computed(() => useArrayData('Ticket').store?.data);
+const ticketFilter = {
+    include: [
+        { relation: 'address' },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'salesPersonFk',
+                    'name',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                    'credit',
+                    'email',
+                    'phone',
+                    'mobile',
+                    'hasElectronicInvoice',
+                ],
+                include: {
+                    relation: 'salesPersonUser',
+                    scope: { fields: ['id', 'name'] },
+                },
+            },
+        },
+        { relation: 'invoiceOut' },
+    ],
+};
+
+const getTicketData = async () => {
+    const params = { filter: JSON.stringify(ticketFilter) };
+    const { data } = await axios.get(`tickets/${route.params.id}`, { params });
+    formData.value = data;
+    initialDataLoaded.value = true;
+};
 
 const isFormInvalid = () => {
     return (
-        !ticket.value.clientFk ||
-        !ticket.value.addressFk ||
-        !ticket.value.agencyModeFk ||
-        !ticket.value.companyFk ||
-        !ticket.value.shipped ||
-        !ticket.value.landed ||
-        !ticket.value.zoneFk
+        !formData.value.clientFk ||
+        !formData.value.addressFk ||
+        !formData.value.agencyModeFk ||
+        !formData.value.companyFk ||
+        !formData.value.shipped ||
+        !formData.value.landed ||
+        !formData.value.zoneFk
     );
 };
 
 const getPriceDifference = async () => {
     const params = {
-        landed: ticket.value.landed,
-        addressId: ticket.value.addressFk,
-        agencyModeId: ticket.value.agencyModeFk,
-        zoneId: ticket.value.zoneFk,
-        warehouseId: ticket.value.warehouseFk,
-        shipped: ticket.value.shipped,
+        landed: formData.value.landed,
+        addressId: formData.value.addressFk,
+        agencyModeId: formData.value.agencyModeFk,
+        zoneId: formData.value.zoneFk,
+        warehouseId: formData.value.warehouseFk,
+        shipped: formData.value.shipped,
     };
     const { data } = await axios.post(
-        `tickets/${ticket.value.id}/priceDifference`,
+        `tickets/${formData.value.id}/priceDifference`,
         params
     );
-    ticket.value.sale = data;
+    formData.value.sale = data;
 };
 
 const submit = async () => {
-    if (!ticket.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
+    if (!formData.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
 
     const params = {
-        clientFk: ticket.value.clientFk,
-        nickname: ticket.value.nickname,
-        agencyModeFk: ticket.value.agencyModeFk,
-        addressFk: ticket.value.addressFk,
-        zoneFk: ticket.value.zoneFk,
-        warehouseFk: ticket.value.warehouseFk,
-        companyFk: ticket.value.companyFk,
-        shipped: ticket.value.shipped,
-        landed: ticket.value.landed,
-        isDeleted: ticket.value.isDeleted,
-        option: ticket.value.option,
-        isWithoutNegatives: ticket.value.withoutNegatives,
-        withWarningAccept: ticket.value.withWarningAccept,
+        clientFk: formData.value.clientFk,
+        nickname: formData.value.nickname,
+        agencyModeFk: formData.value.agencyModeFk,
+        addressFk: formData.value.addressFk,
+        zoneFk: formData.value.zoneFk,
+        warehouseFk: formData.value.warehouseFk,
+        companyFk: formData.value.companyFk,
+        shipped: formData.value.shipped,
+        landed: formData.value.landed,
+        isDeleted: formData.value.isDeleted,
+        option: formData.value.option,
+        isWithoutNegatives: formData.value.withoutNegatives,
+        withWarningAccept: formData.value.withWarningAccept,
         keepPrice: false,
     };
 
     const { data } = await axios.post(
-        `tickets/${ticket.value.id}/componentUpdate`,
+        `tickets/${formData.value.id}/componentUpdate`,
         params
     );
 
@@ -83,7 +118,7 @@ const submit = async () => {
 };
 
 const submitWithNegatives = async () => {
-    ticket.value.withWarningAccept = true;
+    formData.value.withWarningAccept = true;
     submit();
 };
 
@@ -95,7 +130,7 @@ const onNextStep = async () => {
         await getPriceDifference();
         stepperRef.value.next();
     } else if (step.value === 2) {
-        if (haveNegatives.value && !ticket.value.withoutNegatives)
+        if (haveNegatives.value && !formData.value.withoutNegatives)
             openConfirmationModal(
                 t('basicData.negativesConfirmTitle'),
                 t('basicData.negativesConfirmMessage'),
@@ -104,10 +139,11 @@ const onNextStep = async () => {
         else submit();
     }
 };
+
+onBeforeMount(async () => await getTicketData());
 </script>
 <template>
     <QStepper
-        v-if="ticket"
         v-model="step"
         ref="stepperRef"
         color="primary"
@@ -119,10 +155,10 @@ const onNextStep = async () => {
         }"
     >
         <QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
-            <TicketBasicDataForm v-model="ticket" />
+            <TicketBasicDataForm v-if="initialDataLoaded" v-model="formData" />
         </QStep>
         <QStep :name="2" :title="t('basicData.priceDifference')">
-            <TicketBasicData v-model="ticket" v-model:have-negatives="haveNegatives" />
+            <TicketBasicData v-model="formData" v-model:have-negatives="haveNegatives" />
         </QStep>
         <template #navigation>
             <QStepperNavigation class="flex justify-between">
diff --git a/src/pages/Ticket/Card/TicketCard.vue b/src/pages/Ticket/Card/TicketCard.vue
index e22d5799a..6886a8e57 100644
--- a/src/pages/Ticket/Card/TicketCard.vue
+++ b/src/pages/Ticket/Card/TicketCard.vue
@@ -1,13 +1,7 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import TicketDescriptor from './TicketDescriptor.vue';
-import filter from './TicketFilter.js';
 </script>
 <template>
-    <VnCardBeta
-        data-key="Ticket"
-        url="Tickets"
-        :descriptor="TicketDescriptor"
-        :filter="filter"
-    />
+    <VnCardBeta data-key="Ticket" base-url="Tickets" :descriptor="TicketDescriptor" />
 </template>
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 5936ffc28..842607e0c 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -19,7 +19,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
 const route = useRoute();
 const { t } = useI18n();
 const salesRef = ref(null);
-const arrayData = useArrayData('Ticket');
+const arrayData = useArrayData('ticketData');
 const { store } = arrayData;
 
 const ticketData = computed(() => store.data);
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index c5f3233b1..c9849d631 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -6,11 +6,9 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
+import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { toDateTimeFormat } from 'src/filters/date';
-import filter from './TicketFilter.js';
-import FetchData from 'src/components/FetchData.vue';
-import TicketProblems from 'src/components/TicketProblems.vue';
 
 const $props = defineProps({
     id: {
@@ -30,24 +28,100 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-const problems = ref({});
+
+const filter = {
+    include: [
+        {
+            relation: 'address',
+            scope: {
+                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'id',
+                    'name',
+                    'salesPersonFk',
+                    'phone',
+                    'mobile',
+                    'email',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                    'hasElectronicInvoice',
+                ],
+                include: [
+                    {
+                        relation: 'user',
+                        scope: {
+                            fields: ['id', 'lang'],
+                        },
+                    },
+                    { relation: 'salesPersonUser' },
+                ],
+            },
+        },
+        {
+            relation: 'ticketState',
+            scope: {
+                include: { relation: 'state' },
+            },
+        },
+        {
+            relation: 'warehouse',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'zone',
+            scope: {
+                fields: [
+                    'agencyModeFk',
+                    'bonus',
+                    'hour',
+                    'id',
+                    'isVolumetric',
+                    'itemMaxSize',
+                    'm3Max',
+                    'name',
+                    'price',
+                    'travelingDays',
+                ],
+            },
+        },
+    ],
+};
+
+const data = ref(useCardDescription());
 
 function ticketFilter(ticket) {
     return JSON.stringify({ clientFk: ticket.clientFk });
 }
+
+const setData = (entity) => {
+    data.value = useCardDescription(entity.ref, entity.id);
+};
 </script>
 
 <template>
-    <FetchData
-        :url="`Tickets/${entityId}/getTicketProblems`"
-        auto-load
-        @on-fetch="(data) => ([problems] = data)"
-    />
     <CardDescriptor
+        module="Ticket"
         :url="`Tickets/${entityId}`"
         :filter="filter"
-        data-key="Ticket"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        @on-fetch="setData"
         :summary="$props.summary"
+        data-key="ticketData"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -93,9 +167,48 @@ function ticketFilter(ticket) {
             <VnLv :label="t('globals.warehouse')" :value="entity.warehouse?.name" />
             <VnLv :label="t('globals.alias')" :value="entity.nickname" />
         </template>
-        <template #icons>
-            <QCardActions class="q-gutter-x-xs">
-                <TicketProblems :row="problems" />
+        <template #icons="{ entity }">
+            <QCardActions class="q-gutter-x-md">
+                <QIcon
+                    v-if="entity.client.isActive == false"
+                    name="vn:disabled"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Client inactive') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="entity.client.isFreezed == true"
+                    name="vn:frozen"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Client Frozen') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="entity?.problem?.includes('hasRisk')"
+                    name="vn:risk"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Client has debt') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="entity.client.isTaxDataChecked == false"
+                    name="vn:no036"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Client not checked') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="entity.isDeleted == true"
+                    name="vn:deletedTicket"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('This ticket is deleted') }}</QTooltip>
+                </QIcon>
             </QCardActions>
         </template>
         <template #actions="{ entity }">
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index f8084ff2f..166e86978 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -40,7 +40,7 @@ const expeditionsFilter = computed(() => ({
     order: ['created DESC'],
 }));
 
-const ticketArrayData = useArrayData('Ticket');
+const ticketArrayData = useArrayData('ticketData');
 const ticketStore = ticketArrayData.store;
 const ticketData = computed(() => ticketStore.data);
 
diff --git a/src/pages/Ticket/Card/TicketFilter.js b/src/pages/Ticket/Card/TicketFilter.js
deleted file mode 100644
index 7846f1658..000000000
--- a/src/pages/Ticket/Card/TicketFilter.js
+++ /dev/null
@@ -1,72 +0,0 @@
-export default {
-    include: [
-        {
-            relation: 'address',
-            scope: {
-                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'id',
-                    'name',
-                    'salesPersonFk',
-                    'phone',
-                    'mobile',
-                    'email',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                    'hasElectronicInvoice',
-                    'credit',
-                ],
-                include: [
-                    {
-                        relation: 'user',
-                        scope: {
-                            fields: ['id', 'lang'],
-                        },
-                    },
-                    { relation: 'salesPersonUser' },
-                ],
-            },
-        },
-        {
-            relation: 'ticketState',
-            scope: {
-                include: { relation: 'state' },
-            },
-        },
-        {
-            relation: 'warehouse',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'zone',
-            scope: {
-                fields: [
-                    'agencyModeFk',
-                    'bonus',
-                    'hour',
-                    'id',
-                    'isVolumetric',
-                    'itemMaxSize',
-                    'm3Max',
-                    'name',
-                    'price',
-                    'travelingDays',
-                ],
-            },
-        },
-    ],
-};
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index feb88bf84..f558b71cc 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -32,7 +32,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketNotesCrudRef.value.reload();
-    },
+    }
 );
 function handleDelete(row) {
     ticketNotesCrudRef.value.remove([row]);
@@ -105,7 +105,7 @@ async function handleSave() {
                     <VnRow v-if="observationTypes.length > rows.length">
                         <QBtn
                             icon="add_circle"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketPackage.vue b/src/pages/Ticket/Card/TicketPackage.vue
index 5fbf4c800..8ebdb4401 100644
--- a/src/pages/Ticket/Card/TicketPackage.vue
+++ b/src/pages/Ticket/Card/TicketPackage.vue
@@ -41,7 +41,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketPackagingsCrudRef.value.reload();
-    },
+    }
 );
 </script>
 
@@ -118,7 +118,7 @@ watch(
                     <VnRow>
                         <QBtn
                             icon="add_circle"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 6f02a2ce6..f5fb50ecf 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -14,7 +14,7 @@ import VnImg from 'src/components/ui/VnImg.vue';
 
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import TicketSaleMoreActions from './TicketSaleMoreActions.vue';
-import TicketTransferProxy from './TicketTransferProxy.vue';
+import TicketTransfer from './TicketTransfer.vue';
 
 import { toCurrency, toPercentage } from 'src/filters';
 import { useArrayData } from 'composables/useArrayData';
@@ -23,7 +23,6 @@ import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
-import TicketProblems from 'src/components/TicketProblems.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 const route = useRoute();
@@ -35,7 +34,7 @@ const editPriceProxyRef = ref(null);
 const editManaProxyRef = ref(null);
 const stateBtnDropdownRef = ref(null);
 const quasar = useQuasar();
-const arrayData = useArrayData('Ticket');
+const arrayData = useArrayData('ticketData');
 const { store } = arrayData;
 const selectedRows = ref([]);
 const hasSelectedRows = computed(() => selectedRows.value.length > 0);
@@ -627,9 +626,8 @@ watch(
                     @click="setTransferParams()"
                     data-cy="ticketSaleTransferBtn"
                 >
-                    <QTooltip>{{ t('ticketSale.transferLines') }}</QTooltip>
-                    <TicketTransferProxy
-                        class="full-width"
+                    <QTooltip>{{ t('Transfer lines') }}</QTooltip>
+                    <TicketTransfer
                         :transfer="transfer"
                         :ticket="store.data"
                         @refresh-data="resetChanges()"
@@ -699,7 +697,53 @@ watch(
         :disabled-attr="isTicketEditable"
     >
         <template #column-statusIcons="{ row }">
-            <TicketProblems :row="row" />
+            <router-link
+                v-if="row.claim?.claimFk"
+                :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
+            >
+                <QIcon color="primary" name="vn:claims" size="xs">
+                    <QTooltip>
+                        {{ t('ticketSale.claim') }}:
+                        {{ row.claim?.claimFk }}
+                    </QTooltip>
+                </QIcon>
+            </router-link>
+            <QIcon v-if="row.visible < 0" color="primary" name="warning" size="xs">
+                <QTooltip>
+                    {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
+                </QTooltip>
+            </QIcon>
+            <QIcon
+                v-if="row.reserved"
+                color="primary"
+                name="vn:reserva"
+                size="xs"
+                data-cy="ticketSaleReservedIcon"
+            >
+                <QTooltip>
+                    {{ t('ticketSale.reserved') }}
+                </QTooltip>
+            </QIcon>
+            <QIcon
+                v-if="row.itemShortage"
+                color="primary"
+                name="vn:unavailable"
+                size="xs"
+            >
+                <QTooltip>
+                    {{ t('ticketSale.noVisible') }}
+                </QTooltip>
+            </QIcon>
+            <QIcon
+                v-if="row.hasComponentLack"
+                color="primary"
+                name="vn:components"
+                size="xs"
+            >
+                <QTooltip>
+                    {{ t('ticketSale.hasComponentLack') }}
+                </QTooltip>
+            </QIcon>
         </template>
         <template #body-cell-picture="{ row }">
             <QTd>
@@ -837,7 +881,7 @@ watch(
             color="primary"
             fab
             icon="add"
-            v-shortcut="'+'"
+            shortcut="+"
             data-cy="ticketSaleAddToBasketBtn"
         />
         <QTooltip class="text-no-wrap">
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 6ce69a6aa..d045eadee 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -40,7 +40,7 @@ watch(
     async () => {
         store.filter = crudModelFilter.value;
         await ticketServiceCrudRef.value.reload();
-    },
+    }
 );
 
 onMounted(async () => await getDefaultTaxClass());
@@ -59,7 +59,7 @@ const createRefund = async () => {
         t('service.createRefundSuccess', {
             ticketId: refundTicket.id,
         }),
-        'positive',
+        'positive'
     );
     router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
 };
@@ -225,7 +225,7 @@ async function handleSave() {
             color="primary"
             icon="add"
             @click="ticketServiceCrudRef.insert()"
-            v-shortcut="'+'"
+            shortcut="+"
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/Ticket/Card/TicketSplit.vue b/src/pages/Ticket/Card/TicketSplit.vue
deleted file mode 100644
index e79057266..000000000
--- a/src/pages/Ticket/Card/TicketSplit.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-
-import VnInputDate from 'src/components/common/VnInputDate.vue';
-import split from './components/split';
-const emit = defineEmits(['ticketTransfered']);
-
-const $props = defineProps({
-    ticket: {
-        type: [Array, Object],
-        default: () => {},
-    },
-});
-
-const splitDate = ref(Date.vnNew());
-
-const splitSelectedRows = async () => {
-    const tickets = Array.isArray($props.ticket) ? $props.ticket : [$props.ticket];
-    await split(tickets, splitDate.value);
-    emit('ticketTransfered', tickets);
-};
-</script>
-
-<template>
-    <VnInputDate class="q-mr-sm" :label="$t('New date')" v-model="splitDate" clearable />
-    <QBtn class="q-mr-sm" color="primary" label="Split" @click="splitSelectedRows"></QBtn>
-</template>
-<style lang="scss">
-.q-table__bottom.row.items-center.q-table__bottom--nodata {
-    border-top: none;
-}
-</style>
-<i18n>
-es:
-    Sales to transfer: Líneas a transferir
-    Destination ticket: Ticket destinatario
-</i18n>
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 5838efa88..8cb518823 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -20,7 +20,6 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
-import TicketProblems from 'src/components/TicketProblems.vue';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -41,7 +40,7 @@ const editableStates = ref([]);
 const ticketUrl = ref();
 const grafanaUrl = 'https://grafana.verdnatura.es';
 const stateBtnDropdownRef = ref();
-const descriptorData = useArrayData('Ticket');
+const descriptorData = useArrayData('ticketData');
 
 onMounted(async () => {
     ticketUrl.value = (await getUrl('ticket/')) + entityId.value + '/';
@@ -321,7 +320,83 @@ onMounted(async () => {
                     <template #body="props">
                         <QTr :props="props">
                             <QTd class="q-gutter-x-xs">
-                                <TicketProblems :row="props.row" />
+                                <QBtn
+                                    flat
+                                    round
+                                    icon="vn:claims"
+                                    v-if="props.row.claim"
+                                    color="primary"
+                                    :to="{
+                                        name: 'ClaimCard',
+                                        params: {
+                                            id: props.row.claim.claimFk,
+                                        },
+                                    }"
+                                >
+                                    <QTooltip>
+                                        {{ t('ticket.summary.claim') }}:
+                                        {{ props.row.claim.claimFk }}
+                                    </QTooltip>
+                                </QBtn>
+                                <QBtn
+                                    flat
+                                    round
+                                    icon="vn:claims"
+                                    v-if="props.row.claimBeginning"
+                                    color="primary"
+                                    :to="{
+                                        name: 'ClaimCard',
+                                        params: {
+                                            id: props.row.claimBeginning.claimFk,
+                                        },
+                                    }"
+                                >
+                                    <QTooltip>
+                                        {{ t('ticket.summary.claim') }}:
+                                        {{ props.row.claimBeginning.claimFk }}
+                                    </QTooltip>
+                                </QBtn>
+                                <QIcon
+                                    name="warning"
+                                    v-show="props.row.visible < 0"
+                                    color="primary"
+                                    size="xs"
+                                >
+                                    <QTooltip>
+                                        {{ t('globals.visible') }}:
+                                        {{ props.row.visible }}
+                                    </QTooltip>
+                                </QIcon>
+                                <QIcon
+                                    name="vn:reserved"
+                                    v-show="props.row.reserved"
+                                    color="primary"
+                                    size="xs"
+                                >
+                                    <QTooltip>
+                                        {{ t('ticket.summary.reserved') }}
+                                    </QTooltip>
+                                </QIcon>
+                                <QIcon
+                                    name="vn:unavailable"
+                                    v-show="props.row.itemShortage"
+                                    color="primary"
+                                    size="xs"
+                                >
+                                    <QTooltip>
+                                        {{ t('ticket.summary.itemShortage') }}
+                                    </QTooltip>
+                                </QIcon>
+                                <QIcon
+                                    name="vn:components"
+                                    v-show="props.row.hasComponentLack"
+                                    color="primary"
+                                    size="xs"
+                                >
+                                    <QTooltip>
+                                        {{ t('ticket.summary.hasComponentLack') }}
+                                    </QTooltip>
+                                </QIcon>
                             </QTd>
                             <QTd>
                                 <QBtn class="link" flat>
diff --git a/src/pages/Ticket/Card/TicketTracking.vue b/src/pages/Ticket/Card/TicketTracking.vue
index acf464fb1..f4b8544d3 100644
--- a/src/pages/Ticket/Card/TicketTracking.vue
+++ b/src/pages/Ticket/Card/TicketTracking.vue
@@ -19,7 +19,7 @@ watch(
     async (val) => {
         paginateFilter.where.ticketFk = val;
         paginateRef.value.fetch();
-    },
+    }
 );
 
 const paginateFilter = reactive({
@@ -119,7 +119,7 @@ const openCreateModal = () => createTrackingDialogRef.value.show();
                 color="primary"
                 fab
                 icon="add"
-                v-shortcut="'+'"
+                shortcut="+"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('tracking.addState') }}
diff --git a/src/pages/Ticket/Card/TicketTransfer.vue b/src/pages/Ticket/Card/TicketTransfer.vue
index ffa964c92..005d74a0e 100644
--- a/src/pages/Ticket/Card/TicketTransfer.vue
+++ b/src/pages/Ticket/Card/TicketTransfer.vue
@@ -1,11 +1,11 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
+
 import VnInput from 'src/components/common/VnInput.vue';
 import TicketTransferForm from './TicketTransferForm.vue';
 
 import { toDateFormat } from 'src/filters/date.js';
-const emit = defineEmits(['ticketTransfered']);
 
 const $props = defineProps({
     mana: {
@@ -21,15 +21,16 @@ const $props = defineProps({
         default: () => {},
     },
     ticket: {
-        type: [Array, Object],
+        type: Object,
         default: () => {},
     },
 });
 
-onMounted(() => (_transfer.value = $props.transfer));
 const { t } = useI18n();
+const QPopupProxyRef = ref(null);
 const transferFormRef = ref(null);
 const _transfer = ref();
+
 const transferLinesColumns = computed(() => [
     {
         label: t('ticketList.id'),
@@ -85,74 +86,76 @@ const handleRowClick = (row) => {
         transferFormRef.value.transferSales(ticketId);
     }
 };
+
+onMounted(() => (_transfer.value = $props.transfer));
 </script>
 
 <template>
-    <QTable
-        :rows="transfer.sales"
-        :columns="transferLinesColumns"
-        :title="t('Sales to transfer')"
-        row-key="id"
-        :pagination="{ rowsPerPage: 0 }"
-        class="full-width q-mt-md"
-        :no-data-label="t('globals.noResults')"
-    >
-        <template #body-cell-quantity="{ row }">
-            <QTd @click.stop>
-                <VnInput
-                    v-model.number="row.quantity"
-                    :clearable="false"
-                    style="max-width: 60px"
-                />
-            </QTd>
-        </template>
-    </QTable>
-    <QSeparator vertical spaced />
-    <QTable
-        v-if="transfer.lastActiveTickets"
-        :rows="transfer.lastActiveTickets"
-        :columns="destinationTicketColumns"
-        :title="t('Destination ticket')"
-        row-key="id"
-        class="full-width q-mt-md"
-        @row-click="(_, row) => handleRowClick(row)"
-        :no-data-label="t('globals.noResults')"
-        :pagination="{ rowsPerPage: 0 }"
-    >
-        <template #body-cell-address="{ row }">
-            <QTd @click.stop>
-                <span>
-                    {{ row.nickname }}
-                    {{ row.name }}
-                    {{ row.street }}
-                    {{ row.postalCode }}
-                    {{ row.city }}
-                </span>
-                <QTooltip>
-                    {{ row.nickname }}
-                    {{ row.name }}
-                    {{ row.street }}
-                    {{ row.postalCode }}
-                    {{ row.city }}
-                </QTooltip>
-            </QTd>
-        </template>
+    <QPopupProxy ref="QPopupProxyRef" data-cy="ticketTransferPopup">
+        <QCard class="q-px-md" style="display: flex; width: 80vw">
+            <QTable
+                :rows="transfer.sales"
+                :columns="transferLinesColumns"
+                :title="t('Sales to transfer')"
+                row-key="id"
+                :pagination="{ rowsPerPage: 0 }"
+                class="full-width q-mt-md"
+                :no-data-label="t('globals.noResults')"
+            >
+                <template #body-cell-quantity="{ row }">
+                    <QTd @click.stop>
+                        <VnInput
+                            v-model.number="row.quantity"
+                            :clearable="false"
+                            style="max-width: 60px"
+                        />
+                    </QTd>
+                </template>
+            </QTable>
+            <QSeparator vertical spaced />
+            <QTable
+                v-if="transfer.lastActiveTickets"
+                :rows="transfer.lastActiveTickets"
+                :columns="destinationTicketColumns"
+                :title="t('Destination ticket')"
+                row-key="id"
+                class="full-width q-mt-md"
+                @row-click="(_, row) => handleRowClick(row)"
+            >
+                <template #body-cell-address="{ row }">
+                    <QTd @click.stop>
+                        <span>
+                            {{ row.nickname }}
+                            {{ row.name }}
+                            {{ row.street }}
+                            {{ row.postalCode }}
+                            {{ row.city }}
+                        </span>
+                        <QTooltip>
+                            {{ row.nickname }}
+                            {{ row.name }}
+                            {{ row.street }}
+                            {{ row.postalCode }}
+                            {{ row.city }}
+                        </QTooltip>
+                    </QTd>
+                </template>
 
-        <template #no-data>
-            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-        </template>
-        <template #bottom>
-            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-        </template>
-    </QTable>
+                <template #no-data>
+                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+                </template>
+                <template #bottom>
+                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+                </template>
+            </QTable>
+        </QCard>
+    </QPopupProxy>
 </template>
-<style lang="scss">
-.q-table__bottom.row.items-center.q-table__bottom--nodata {
-    border-top: none;
-}
-</style>
+
 <i18n>
 es:
     Sales to transfer: Líneas a transferir
     Destination ticket: Ticket destinatario
+    Transfer to ticket: Transferir a ticket
+    New ticket: Nuevo ticket
 </i18n>
diff --git a/src/pages/Ticket/Card/TicketTransferProxy.vue b/src/pages/Ticket/Card/TicketTransferProxy.vue
deleted file mode 100644
index 3f3f018df..000000000
--- a/src/pages/Ticket/Card/TicketTransferProxy.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import TicketTransfer from './TicketTransfer.vue';
-import Split from './TicketSplit.vue';
-const emit = defineEmits(['ticketTransfered']);
-
-const $props = defineProps({
-    mana: {
-        type: Number,
-        default: null,
-    },
-    newPrice: {
-        type: Number,
-        default: 0,
-    },
-    transfer: {
-        type: Object,
-        default: () => {},
-    },
-    ticket: {
-        type: [Array, Object],
-        default: () => {},
-    },
-    split: {
-        type: Boolean,
-        default: false,
-    },
-});
-
-const popupProxyRef = ref(null);
-const splitRef = ref(null);
-const transferRef = ref(null);
-</script>
-
-<template>
-    <QPopupProxy ref="popupProxyRef" data-cy="ticketTransferPopup">
-        <div class="flex row items-center q-ma-lg" v-if="$props.split">
-            <Split
-                ref="splitRef"
-                @splitSelectedRows="splitSelectedRows"
-                :ticket="$props.ticket"
-            />
-        </div>
-
-        <div v-else>
-            <TicketTransfer
-                ref="transferRef"
-                :ticket="$props.ticket"
-                :sales="$props.sales"
-                :transfer="$props.transfer"
-            />
-        </div>
-    </QPopupProxy>
-</template>
diff --git a/src/pages/Ticket/Card/components/split.js b/src/pages/Ticket/Card/components/split.js
deleted file mode 100644
index afa1d5cd6..000000000
--- a/src/pages/Ticket/Card/components/split.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import axios from 'axios';
-import notifyResults from 'src/utils/notifyResults';
-
-export default async function (data, date) {
-    const reducedData = data.reduce((acc, item) => {
-        const existing = acc.find(({ ticketFk }) => ticketFk === item.id);
-        if (existing) {
-            existing.sales.push(item.saleFk);
-        } else {
-            acc.push({ ticketFk: item.id, sales: [item.saleFk], date });
-        }
-        return acc;
-    }, []);
-
-    const promises = reducedData.map((params) => axios.post(`Tickets/split`, params));
-
-    const results = await Promise.allSettled(promises);
-
-    notifyResults(results, 'ticketFk');
-
-    return results;
-}
diff --git a/src/pages/Ticket/Negative/TicketLackDetail.vue b/src/pages/Ticket/Negative/TicketLackDetail.vue
deleted file mode 100644
index dcf835d03..000000000
--- a/src/pages/Ticket/Negative/TicketLackDetail.vue
+++ /dev/null
@@ -1,198 +0,0 @@
-<script setup>
-import { computed, onMounted, onUnmounted, ref } from 'vue';
-import { useI18n } from 'vue-i18n';
-import ChangeQuantityDialog from './components/ChangeQuantityDialog.vue';
-import ChangeStateDialog from './components/ChangeStateDialog.vue';
-import ChangeItemDialog from './components/ChangeItemDialog.vue';
-import TicketTransferProxy from '../Card/TicketTransferProxy.vue';
-import FetchData from 'src/components/FetchData.vue';
-import { useStateStore } from 'stores/useStateStore';
-import { useState } from 'src/composables/useState';
-
-import { useRoute } from 'vue-router';
-import TicketLackTable from './TicketLackTable.vue';
-import VnPopupProxy from 'src/components/common/VnPopupProxy.vue';
-import ItemProposalProxy from 'src/pages/Item/components/ItemProposalProxy.vue';
-
-import { useQuasar } from 'quasar';
-const quasar = useQuasar();
-const { t } = useI18n();
-const editableStates = ref([]);
-const stateStore = useStateStore();
-const tableRef = ref();
-const changeItemDialogRef = ref(null);
-const changeStateDialogRef = ref(null);
-const changeQuantityDialogRef = ref(null);
-const showProposalDialog = ref(false);
-const showChangeQuantityDialog = ref(false);
-const selectedRows = ref([]);
-const route = useRoute();
-onMounted(() => {
-    stateStore.rightDrawer = false;
-});
-onUnmounted(() => {
-    stateStore.rightDrawer = true;
-});
-
-const entityId = computed(() => route.params.id);
-const item = ref({});
-
-const itemProposalSelected = ref(null);
-const reload = async () => {
-    tableRef.value.tableRef.reload();
-};
-defineExpose({ reload });
-const filter = computed(() => ({
-    scopeDays: route.query.days,
-    showType: true,
-    alertLevelCode: 'FREE',
-    date: Date.vnNew(),
-    warehouseFk: useState().getUser().value.warehouseFk,
-}));
-const itemProposalEvt = (data) => {
-    const { itemProposal } = data;
-    itemProposalSelected.value = itemProposal;
-    reload();
-};
-
-function onBuysFetched(data) {
-    Object.assign(item.value, data[0]);
-}
-const showItemProposal = () => {
-    quasar
-        .dialog({
-            component: ItemProposalProxy,
-            componentProps: {
-                itemLack: tableRef.value.itemLack,
-                replaceAction: true,
-                sales: selectedRows.value,
-            },
-        })
-        .onOk(itemProposalEvt);
-};
-</script>
-
-<template>
-    <FetchData
-        url="States/editableStates"
-        @on-fetch="(data) => (editableStates = data)"
-        auto-load
-    />
-    <FetchData
-        :url="`Items/${entityId}/getCard`"
-        :fields="['longName']"
-        @on-fetch="(data) => (item = data)"
-        auto-load
-    />
-    <FetchData
-        :url="`Buys/latestBuysFilter`"
-        :fields="['longName']"
-        :filter="{ where: { 'i.id': entityId } }"
-        @on-fetch="onBuysFetched"
-        auto-load
-    />
-
-    <TicketLackTable
-        ref="tableRef"
-        :filter="filter"
-        @update:selection="({ value }, _) => (selectedRows = value)"
-    >
-        <template #top-right>
-            <QBtnGroup push class="q-mr-lg" style="column-gap: 1px">
-                <QBtn
-                    data-cy="transferLines"
-                    color="primary"
-                    :disable="!(selectedRows.length === 1)"
-                >
-                    <template #default>
-                        <QIcon name="vn:splitline" />
-                        <QIcon name="vn:ticket" />
-
-                        <QTooltip>{{ t('ticketSale.transferLines') }} </QTooltip>
-                        <TicketTransferProxy
-                            ref="transferFormRef"
-                            split="true"
-                            :ticket="selectedRows"
-                            :transfer="{
-                                sales: selectedRows,
-                                lastActiveTickets: selectedRows.map((row) => row.id),
-                            }"
-                            @ticket-transfered="reload"
-                        ></TicketTransferProxy>
-                    </template>
-                </QBtn>
-                <QBtn
-                    color="primary"
-                    @click="showProposalDialog = true"
-                    :disable="selectedRows.length < 1"
-                    data-cy="itemProposal"
-                >
-                    <QIcon
-                        name="import_export"
-                        class="rotate-90"
-                        @click="showItemProposal"
-                    ></QIcon>
-                    <QTooltip bottom anchor="bottom right">
-                        {{ t('itemProposal') }}
-                    </QTooltip>
-                </QBtn>
-                <VnPopupProxy
-                    data-cy="changeItem"
-                    icon="sync"
-                    :disable="selectedRows.length < 1"
-                    :tooltip="t('negative.detail.modal.changeItem.title')"
-                >
-                    <template #extraIcon> <QIcon name="vn:item" /> </template>
-                    <template v-slot="{ popup }">
-                        <ChangeItemDialog
-                            ref="changeItemDialogRef"
-                            @update-item="popup.hide()"
-                            :selected-rows="selectedRows"
-                    /></template>
-                </VnPopupProxy>
-                <VnPopupProxy
-                    data-cy="changeState"
-                    icon="sync"
-                    :disable="selectedRows.length < 1"
-                    :tooltip="t('negative.detail.modal.changeState.title')"
-                >
-                    <template #extraIcon> <QIcon name="vn:eye" /> </template>
-                    <template v-slot="{ popup }">
-                        <ChangeStateDialog
-                            ref="changeStateDialogRef"
-                            @update-state="popup.hide()"
-                            :selected-rows="selectedRows"
-                    /></template>
-                </VnPopupProxy>
-                <VnPopupProxy
-                    data-cy="changeQuantity"
-                    icon="sync"
-                    :disable="selectedRows.length < 1"
-                    :tooltip="t('negative.detail.modal.changeQuantity.title')"
-                    @click="showChangeQuantityDialog = true"
-                >
-                    <template #extraIcon> <QIcon name="exposure" /> </template>
-                    <template v-slot="{ popup }">
-                        <ChangeQuantityDialog
-                            ref="changeQuantityDialogRef"
-                            @update-quantity="popup.hide()"
-                            :selected-rows="selectedRows"
-                    /></template>
-                </VnPopupProxy> </QBtnGroup
-        ></template>
-    </TicketLackTable>
-</template>
-<style lang="scss" scoped>
-.list-enter-active,
-.list-leave-active {
-    transition: all 1s ease;
-}
-.list-enter-from,
-.list-leave-to {
-    opacity: 0;
-    background-color: $primary;
-}
-.q-table.q-table__container > div:first-child {
-    border-radius: unset;
-}
-</style>
diff --git a/src/pages/Ticket/Negative/TicketLackFilter.vue b/src/pages/Ticket/Negative/TicketLackFilter.vue
deleted file mode 100644
index 3762f453d..000000000
--- a/src/pages/Ticket/Negative/TicketLackFilter.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import { useI18n } from 'vue-i18n';
-
-import FetchData from 'components/FetchData.vue';
-import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-const { t } = useI18n();
-const props = defineProps({
-    dataKey: {
-        type: String,
-        required: true,
-    },
-});
-
-const to = Date.vnNew();
-to.setDate(to.getDate() + 1);
-
-const warehouses = ref();
-const categoriesOptions = ref([]);
-const itemTypesRef = ref(null);
-const itemTypesOptions = ref([]);
-
-const itemTypesFilter = {
-    fields: ['id', 'name', 'categoryFk'],
-    include: 'category',
-    order: 'name ASC',
-    where: {},
-};
-const onCategoryChange = async (categoryFk, search) => {
-    if (!categoryFk) {
-        itemTypesFilter.where.categoryFk = null;
-        delete itemTypesFilter.where.categoryFk;
-    } else {
-        itemTypesFilter.where.categoryFk = categoryFk;
-    }
-    search();
-    await itemTypesRef.value.fetch();
-};
-const emit = defineEmits(['set-user-params']);
-
-const setUserParams = (params) => {
-    emit('set-user-params', params);
-};
-</script>
-
-<template>
-    <FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
-    <FetchData
-        url="ItemCategories"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
-        @on-fetch="(data) => (categoriesOptions = data)"
-        auto-load
-    />
-
-    <FetchData
-        ref="itemTypesRef"
-        url="ItemTypes"
-        :filter="itemTypesFilter"
-        @on-fetch="(data) => (itemTypesOptions = data)"
-        auto-load
-    />
-
-    <VnFilterPanel
-        :data-key="props.dataKey"
-        :search-button="true"
-        @set-user-params="setUserParams"
-    >
-        <template #tags="{ tag, formatFn }">
-            <div class="q-gutter-x-xs">
-                <strong>{{ t(`negative.${tag.label}`) }}</strong>
-                <span>{{ formatFn(tag.value) }}</span>
-            </div>
-        </template>
-        <template #body="{ params, searchFn }">
-            <QList dense class="q-gutter-y-sm q-mt-sm">
-                <QItem>
-                    <QItemSection>
-                        <VnInput
-                            v-model="params.days"
-                            :label="t('negative.days')"
-                            dense
-                            is-outlined
-                            type="number"
-                            @update:model-value="
-                                (value) => {
-                                    setUserParams(params);
-                                }
-                            "
-                        />
-                    </QItemSection>
-                </QItem>
-                <QItem>
-                    <QItemSection>
-                        <VnInput
-                            v-model="params.id"
-                            :label="t('negative.id')"
-                            dense
-                            is-outlined
-                        />
-                    </QItemSection>
-                </QItem>
-                <QItem>
-                    <QItemSection>
-                        <VnInput
-                            v-model="params.producer"
-                            :label="t('negative.producer')"
-                            dense
-                            is-outlined
-                        />
-                    </QItemSection>
-                </QItem>
-                <QItem>
-                    <QItemSection>
-                        <VnInput
-                            v-model="params.origen"
-                            :label="t('negative.origen')"
-                            dense
-                            is-outlined
-                        />
-                    </QItemSection> </QItem
-                ><QItem>
-                    <QItemSection v-if="categoriesOptions">
-                        <VnSelect
-                            :label="t('negative.categoryFk')"
-                            v-model="params.categoryFk"
-                            @update:model-value="
-                                ($event) => onCategoryChange($event, searchFn)
-                            "
-                            :options="categoriesOptions"
-                            option-value="id"
-                            option-label="name"
-                            hide-selected
-                            dense
-                            outlined
-                            rounded
-                        /> </QItemSection
-                    ><QItemSection v-else>
-                        <QSkeleton class="full-width" type="QSelect" />
-                    </QItemSection>
-                </QItem>
-                <QItem>
-                    <QItemSection v-if="itemTypesOptions">
-                        <VnSelect
-                            :label="t('negative.type')"
-                            v-model="params.typeFk"
-                            @update:model-value="searchFn()"
-                            :options="itemTypesOptions"
-                            option-value="id"
-                            option-label="name"
-                            hide-selected
-                            dense
-                            outlined
-                            rounded
-                        >
-                            <template #option="scope">
-                                <QItem v-bind="scope.itemProps">
-                                    <QItemSection>
-                                        <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
-                                        <QItemLabel caption>{{
-                                            scope.opt?.category?.name
-                                        }}</QItemLabel>
-                                    </QItemSection>
-                                </QItem>
-                            </template>
-                        </VnSelect> </QItemSection
-                    ><QItemSection v-else>
-                        <QSkeleton class="full-width" type="QSelect" />
-                    </QItemSection>
-                </QItem>
-            </QList>
-        </template>
-    </VnFilterPanel>
-</template>
diff --git a/src/pages/Ticket/Negative/TicketLackList.vue b/src/pages/Ticket/Negative/TicketLackList.vue
deleted file mode 100644
index d1e8b823a..000000000
--- a/src/pages/Ticket/Negative/TicketLackList.vue
+++ /dev/null
@@ -1,227 +0,0 @@
-<script setup>
-import { computed, ref, reactive } from 'vue';
-import { useI18n } from 'vue-i18n';
-import { useStateStore } from 'stores/useStateStore';
-import VnTable from 'components/VnTable/VnTable.vue';
-import { onBeforeMount } from 'vue';
-import { dashIfEmpty, toDate, toHour } from 'src/filters';
-import { useRouter } from 'vue-router';
-import { useState } from 'src/composables/useState';
-import { useRole } from 'src/composables/useRole';
-import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
-import TicketLackFilter from './TicketLackFilter.vue';
-onBeforeMount(() => {
-    stateStore.$state.rightDrawer = true;
-});
-const router = useRouter();
-const stateStore = useStateStore();
-const { t } = useI18n();
-const selectedRows = ref([]);
-const tableRef = ref();
-const filterParams = ref({});
-const negativeParams = reactive({
-    days: useRole().likeAny('buyer') ? 2 : 0,
-    warehouseFk: useState().getUser().value.warehouseFk,
-});
-const redirectToCreateView = ({ itemFk }) => {
-    router.push({
-        name: 'NegativeDetail',
-        params: { id: itemFk },
-        query: { days: filterParams.value.days ?? negativeParams.days },
-    });
-};
-const columns = computed(() => [
-    {
-        name: 'date',
-        align: 'center',
-        label: t('negative.date'),
-        format: ({ timed }) => toDate(timed),
-        sortable: true,
-        cardVisible: true,
-        isId: true,
-        columnFilter: {
-            component: 'date',
-        },
-    },
-    {
-        columnClass: 'shrink',
-        name: 'timed',
-        align: 'center',
-        label: t('negative.timed'),
-        format: ({ timed }) => toHour(timed),
-        sortable: true,
-        cardVisible: true,
-        columnFilter: {
-            component: 'time',
-        },
-    },
-    {
-        name: 'itemFk',
-        align: 'center',
-        label: t('negative.id'),
-        format: ({ itemFk }) => itemFk,
-        sortable: true,
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-    },
-    {
-        name: 'longName',
-        align: 'center',
-        label: t('negative.longName'),
-        field: ({ longName }) => longName,
-
-        sortable: true,
-        headerStyle: 'width: 350px',
-        cardVisible: true,
-        columnClass: 'expand',
-    },
-    {
-        name: 'producer',
-        align: 'center',
-        label: t('negative.supplier'),
-        field: ({ producer }) => dashIfEmpty(producer),
-        sortable: true,
-        columnClass: 'shrink',
-    },
-    {
-        name: 'inkFk',
-        align: 'center',
-        label: t('negative.colour'),
-        field: ({ inkFk }) => inkFk,
-        sortable: true,
-        cardVisible: true,
-    },
-    {
-        name: 'size',
-        align: 'center',
-        label: t('negative.size'),
-        field: ({ size }) => size,
-        sortable: true,
-        cardVisible: true,
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-    },
-    {
-        name: 'category',
-        align: 'center',
-        label: t('negative.origen'),
-        field: ({ category }) => dashIfEmpty(category),
-        sortable: true,
-        cardVisible: true,
-    },
-    {
-        name: 'lack',
-        align: 'center',
-        label: t('negative.lack'),
-        field: ({ lack }) => lack,
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-            columnClass: 'shrink',
-        },
-        sortable: true,
-        headerStyle: 'padding-center: 33px',
-        cardVisible: true,
-    },
-    {
-        name: 'tableActions',
-        align: 'center',
-        actions: [
-            {
-                title: t('Open details'),
-                icon: 'edit',
-                action: redirectToCreateView,
-                isPrimary: true,
-            },
-        ],
-    },
-]);
-
-const setUserParams = (params) => {
-    filterParams.value = params;
-};
-</script>
-
-<template>
-    <RightMenu>
-        <template #right-panel>
-            <TicketLackFilter data-key="NegativeList" @set-user-params="setUserParams" />
-        </template>
-    </RightMenu>
-    {{ filterRef }}
-    <VnTable
-        ref="tableRef"
-        data-key="NegativeList"
-        :url="`Tickets/itemLack`"
-        :order="['itemFk DESC, date DESC, timed DESC']"
-        :user-params="negativeParams"
-        auto-load
-        :columns="columns"
-        default-mode="table"
-        :right-search="false"
-        :is-editable="false"
-        :use-model="true"
-        :map-key="false"
-        :row-click="redirectToCreateView"
-        v-model:selected="selectedRows"
-        :create="false"
-        :crud-model="{
-            disableInfiniteScroll: true,
-        }"
-        :table="{
-            'row-key': 'itemFk',
-            selection: 'multiple',
-        }"
-    >
-        <template #column-itemFk="{ row }">
-            <div
-                style="display: flex; justify-content: space-around; align-items: center"
-            >
-                <span @click.stop>{{ row.itemFk }}</span>
-            </div>
-        </template>
-        <template #column-longName="{ row }">
-            <span class="link" @click.stop>
-                {{ row.longName }}
-                <ItemDescriptorProxy :id="row.itemFk" />
-            </span>
-        </template>
-    </VnTable>
-</template>
-
-<style lang="scss" scoped>
-.list {
-    max-height: 100%;
-    padding: 15px;
-    width: 100%;
-}
-
-.grid-style-transition {
-    transition:
-        transform 0.28s,
-        background-color 0.28s;
-}
-
-#true {
-    background-color: $positive;
-}
-
-#false {
-    background-color: $negative;
-}
-
-div.q-dialog__inner > div {
-    max-width: fit-content !important;
-}
-.q-btn-group > .q-btn-item:not(:first-child) {
-    border-top-left-radius: 0;
-    border-bottom-left-radius: 0;
-}
-</style>
diff --git a/src/pages/Ticket/Negative/TicketLackTable.vue b/src/pages/Ticket/Negative/TicketLackTable.vue
deleted file mode 100644
index 176e8f7ad..000000000
--- a/src/pages/Ticket/Negative/TicketLackTable.vue
+++ /dev/null
@@ -1,356 +0,0 @@
-<script setup>
-import FetchedTags from 'components/ui/FetchedTags.vue';
-import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import { computed, ref, watch } from 'vue';
-import { useI18n } from 'vue-i18n';
-import axios from 'axios';
-import FetchData from 'src/components/FetchData.vue';
-import { toDate, toHour } from 'src/filters';
-import useNotify from 'src/composables/useNotify.js';
-import ZoneDescriptorProxy from 'pages/Zone/Card/ZoneDescriptorProxy.vue';
-import { useRoute } from 'vue-router';
-import VnTable from 'src/components/VnTable/VnTable.vue';
-import TicketDescriptorProxy from '../Card/TicketDescriptorProxy.vue';
-import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
-
-const $props = defineProps({
-    filter: {
-        type: Object,
-        default: () => ({}),
-    },
-});
-
-watch(
-    () => $props.filter,
-    (v) => {
-        filterLack.value.where = v;
-        tableRef.value.reload(filterLack);
-    },
-);
-
-const filterLack = ref({
-    include: [
-        {
-            relation: 'workers',
-            scope: {
-                fields: ['id', 'firstName'],
-            },
-        },
-    ],
-    where: { ...$props.filter },
-    order: 'ts.alertLevelCode ASC',
-});
-
-const selectedRows = ref([]);
-const { t } = useI18n();
-const { notify } = useNotify();
-const entityId = computed(() => route.params.id);
-const item = ref({});
-const route = useRoute();
-const columns = computed(() => [
-    {
-        name: 'status',
-        align: 'center',
-        sortable: false,
-        columnClass: 'shrink',
-        columnFilter: false,
-    },
-    {
-        name: 'ticketFk',
-        label: t('negative.detail.ticketFk'),
-        align: 'center',
-        sortable: true,
-        columnFilter: {
-            component: 'input',
-            type: 'number',
-        },
-    },
-    {
-        name: 'shipped',
-        label: t('negative.detail.shipped'),
-        field: 'shipped',
-        align: 'center',
-        format: ({ shipped }) => toDate(shipped),
-        sortable: true,
-        columnFilter: {
-            component: 'date',
-            columnClass: 'shrink',
-        },
-    },
-    {
-        name: 'minTimed',
-        label: t('negative.detail.theoreticalhour'),
-        field: 'minTimed',
-        align: 'center',
-        sortable: true,
-        component: 'time',
-        columnFilter: {},
-    },
-    {
-        name: 'alertLevelCode',
-        label: t('negative.detail.state'),
-        columnFilter: {
-            name: 'alertLevelCode',
-            component: 'select',
-            attrs: {
-                url: 'AlertLevels',
-                fields: ['name', 'code'],
-                optionLabel: 'code',
-                optionValue: 'code',
-            },
-        },
-        align: 'center',
-        sortable: true,
-    },
-    {
-        name: 'zoneName',
-        label: t('negative.detail.zoneName'),
-        field: 'zoneName',
-        align: 'center',
-        sortable: true,
-    },
-    {
-        name: 'nickname',
-        label: t('negative.detail.nickname'),
-        field: 'nickname',
-        align: 'center',
-        sortable: true,
-    },
-    {
-        name: 'quantity',
-        label: t('negative.detail.quantity'),
-        field: 'quantity',
-        sortable: true,
-        component: 'input',
-        type: 'number',
-    },
-]);
-
-const emit = defineEmits(['update:selection']);
-const itemLack = ref(null);
-const fetchItemLack = ref(null);
-const tableRef = ref(null);
-defineExpose({ tableRef, itemLack });
-watch(selectedRows, () => emit('update:selection', selectedRows));
-const getInputEvents = ({ col, ...rows }) => ({
-    'update:modelValue': () => saveChange(col.name, rows),
-    'keyup.enter': () => saveChange(col.name, rows),
-});
-const saveChange = async (field, { row }) => {
-    try {
-        switch (field) {
-            case 'alertLevelCode':
-                await axios.post(`Tickets/state`, {
-                    ticketFk: row.ticketFk,
-                    code: row[field],
-                });
-                break;
-
-            case 'quantity':
-                await axios.post(`Sales/${row.saleFk}/updateQuantity`, {
-                    quantity: +row.quantity,
-                });
-                break;
-        }
-        notify('globals.dataSaved', 'positive');
-        fetchItemLack.value.fetch();
-    } catch (err) {
-        console.error('Error saving changes', err);
-        f;
-    }
-};
-
-function onBuysFetched(data) {
-    Object.assign(item.value, data[0]);
-}
-</script>
-
-<template>
-    <FetchData
-        ref="fetchItemLack"
-        :url="`Tickets/itemLack`"
-        :params="{ id: entityId }"
-        @on-fetch="(data) => (itemLack = data[0])"
-        auto-load
-    />
-    <FetchData
-        :url="`Items/${entityId}/getCard`"
-        :fields="['longName']"
-        @on-fetch="(data) => (item = data)"
-        auto-load
-    />
-    <FetchData
-        :url="`Buys/latestBuysFilter`"
-        :fields="['longName']"
-        :filter="{ where: { 'i.id': entityId } }"
-        @on-fetch="onBuysFetched"
-        auto-load
-    />
-    <VnTable
-        ref="tableRef"
-        data-key="NegativeItem"
-        :map-key="false"
-        :url="`Tickets/itemLack/${entityId}`"
-        :columns="columns"
-        auto-load
-        :create="false"
-        :create-as-dialog="false"
-        :use-model="true"
-        :filter="filterLack"
-        :order="['ts.alertLevelCode ASC']"
-        :table="{
-            'row-key': 'id',
-            selection: 'multiple',
-        }"
-        dense
-        :is-editable="true"
-        :row-click="false"
-        :right-search="false"
-        :right-search-icon="false"
-        v-model:selected="selectedRows"
-        :disable-option="{ card: true }"
-    >
-        <template #top-left>
-            <div style="display: flex; align-items: center" v-if="itemLack">
-                <!-- <VnImg :id="itemLack.itemFk" class="rounded image-wrapper"></VnImg> -->
-                <div class="flex column" style="align-items: center">
-                    <QBadge
-                        ref="badgeLackRef"
-                        class="q-ml-xs"
-                        text-color="white"
-                        :color="itemLack.lack === 0 ? 'positive' : 'negative'"
-                        :label="itemLack.lack"
-                    />
-                </div>
-                <div class="flex column left" style="align-items: flex-start">
-                    <QBtn flat class="link text-blue">
-                        {{ item?.longName ?? item.name }}
-                        <ItemDescriptorProxy :id="entityId" />
-                        <FetchedTags class="q-ml-md" :item="item" :columns="7" />
-                    </QBtn>
-                </div>
-            </div>
-        </template>
-        <template #top-right>
-            <slot name="top-right" />
-        </template>
-
-        <template #column-status="{ row }">
-            <QTd style="min-width: 150px">
-                <div class="icon-container">
-                    <QIcon
-                        v-if="row.isBasket"
-                        name="vn:basket"
-                        color="primary"
-                        class="cursor-pointer"
-                        size="xs"
-                    >
-                        <QTooltip>{{ t('negative.detail.isBasket') }}</QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasToIgnore"
-                        name="star"
-                        color="primary"
-                        class="cursor-pointer fill-icon"
-                        size="xs"
-                    >
-                        <QTooltip>{{ t('negative.detail.hasToIgnore') }}</QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasObservation"
-                        name="change_circle"
-                        color="primary"
-                        class="cursor-pointer"
-                        size="xs"
-                    >
-                        <QTooltip>{{
-                            t('negative.detail.hasObservation')
-                        }}</QTooltip> </QIcon
-                    ><QIcon
-                        v-if="row.isRookie"
-                        name="vn:Person"
-                        size="xs"
-                        color="primary"
-                        class="cursor-pointer"
-                    >
-                        <QTooltip>{{ t('negative.detail.isRookie') }}</QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.peticionCompra"
-                        name="vn:buyrequest"
-                        size="xs"
-                        color="primary"
-                        class="cursor-pointer"
-                    >
-                        <QTooltip>{{ t('negative.detail.peticionCompra') }}</QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.turno"
-                        name="vn:calendar"
-                        size="xs"
-                        color="primary"
-                        class="cursor-pointer"
-                    >
-                        <QTooltip>{{ t('negative.detail.turno') }}</QTooltip>
-                    </QIcon>
-                </div></QTd
-            >
-        </template>
-        <template #column-nickname="{ row }">
-            <span class="link" @click.stop>
-                {{ row.nickname }}
-                <CustomerDescriptorProxy :id="row.customerId" />
-            </span>
-        </template>
-        <template #column-ticketFk="{ row }">
-            <span class="q-pa-sm link">
-                {{ row.id }}
-                <TicketDescriptorProxy :id="row.id" />
-            </span>
-        </template>
-        <template #column-alertLevelCode="props">
-            <VnSelect
-                url="States/editableStates"
-                auto-load
-                hide-selected
-                option-value="id"
-                option-label="name"
-                v-model="props.row.alertLevelCode"
-                v-on="getInputEvents(props)"
-            />
-        </template>
-
-        <template #column-zoneName="{ row }">
-            <span class="link">{{ row.zoneName }}</span>
-            <ZoneDescriptorProxy :id="row.zoneFk" />
-        </template>
-        <template #column-quantity="props">
-            <VnInputNumber
-                v-model.number="props.row.quantity"
-                v-on="getInputEvents(props)"
-            ></VnInputNumber>
-        </template>
-    </VnTable>
-</template>
-<style lang="scss" scoped>
-.icon-container {
-    display: grid;
-    grid-template-columns: repeat(3, 0.2fr);
-    row-gap: 5px; /* Ajusta el espacio entre los iconos según sea necesario */
-}
-.icon-container > * {
-    width: 100%;
-    height: auto;
-}
-.list-enter-active,
-.list-leave-active {
-    transition: all 1s ease;
-}
-.list-enter-from,
-.list-leave-to {
-    opacity: 0;
-    background-color: $primary;
-}
-</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeItemDialog.vue b/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
deleted file mode 100644
index e419b85c0..000000000
--- a/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import axios from 'axios';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import notifyResults from 'src/utils/notifyResults';
-const emit = defineEmits(['update-item']);
-
-const showChangeItemDialog = ref(false);
-const newItem = ref(null);
-const $props = defineProps({
-    selectedRows: {
-        type: Array,
-        default: () => [],
-    },
-});
-
-const updateItem = async () => {
-    try {
-        showChangeItemDialog.value = true;
-        const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
-            axios.post(`Sales/replaceItem`, {
-                saleFk,
-                substitutionFk: newItem.value,
-                quantity,
-            }),
-        );
-        const result = await Promise.allSettled(rowsToUpdate);
-        notifyResults(result, 'saleFk');
-        emit('update-item', newItem.value);
-    } catch (err) {
-        console.error('Error updating item:', err);
-        return err;
-    }
-};
-</script>
-
-<template>
-    <QCard class="q-pa-sm">
-        <QCardSection class="row items-center justify-center column items-stretch">
-            {{ showChangeItemDialog }}
-            <span>{{ $t('negative.detail.modal.changeItem.title') }}</span>
-            <VnSelect
-                url="Items/WithName"
-                :fields="['id', 'name']"
-                :sort-by="['id DESC']"
-                :options="items"
-                option-label="name"
-                option-value="id"
-                v-model="newItem"
-            >
-            </VnSelect>
-        </QCardSection>
-        <QCardActions align="right">
-            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
-            <QBtn
-                :label="$t('globals.confirm')"
-                color="primary"
-                :disable="!newItem"
-                @click="updateItem"
-                unelevated
-                autofocus
-            /> </QCardActions
-    ></QCard>
-</template>
-
-<style lang="scss" scoped>
-.list {
-    max-height: 100%;
-    padding: 15px;
-    width: 100%;
-}
-
-.grid-style-transition {
-    transition:
-        transform 0.28s,
-        background-color 0.28s;
-}
-
-#true {
-    background-color: $positive;
-}
-
-#false {
-    background-color: $negative;
-}
-
-div.q-dialog__inner > div {
-    max-width: fit-content !important;
-}
-</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue b/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
deleted file mode 100644
index 2e9aac4f0..000000000
--- a/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
+++ /dev/null
@@ -1,84 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import axios from 'axios';
-import VnInput from 'src/components/common/VnInput.vue';
-import notifyResults from 'src/utils/notifyResults';
-
-const showChangeQuantityDialog = ref(false);
-const newQuantity = ref(null);
-const $props = defineProps({
-    selectedRows: {
-        type: Array,
-        default: () => [],
-    },
-});
-const emit = defineEmits(['update-quantity']);
-const updateQuantity = async () => {
-    try {
-        showChangeQuantityDialog.value = true;
-        const rowsToUpdate = $props.selectedRows.map(({ saleFk }) =>
-            axios.post(`Sales/${saleFk}/updateQuantity`, {
-                saleFk,
-                quantity: +newQuantity.value,
-            }),
-        );
-
-        const result = await Promise.allSettled(rowsToUpdate);
-        notifyResults(result, 'saleFk');
-
-        emit('update-quantity', newQuantity.value);
-    } catch (err) {
-        return err;
-    }
-};
-</script>
-
-<template>
-    <QCard class="q-pa-sm">
-        <QCardSection class="row items-center justify-center column items-stretch">
-            <span>{{ $t('negative.detail.modal.changeQuantity.title') }}</span>
-            <VnInput
-                type="number"
-                :min="0"
-                :label="$t('negative.detail.modal.changeQuantity.placeholder')"
-                v-model="newQuantity"
-            />
-        </QCardSection>
-        <QCardActions align="right">
-            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
-            <QBtn
-                :label="$t('globals.confirm')"
-                color="primary"
-                :disable="!newQuantity || newQuantity < 0"
-                @click="updateQuantity"
-                unelevated
-                autofocus
-            /> </QCardActions
-    ></QCard>
-</template>
-
-<style lang="scss" scoped>
-.list {
-    max-height: 100%;
-    padding: 15px;
-    width: 100%;
-}
-
-.grid-style-transition {
-    transition:
-        transform 0.28s,
-        background-color 0.28s;
-}
-
-#true {
-    background-color: $positive;
-}
-
-#false {
-    background-color: $negative;
-}
-
-div.q-dialog__inner > div {
-    max-width: fit-content !important;
-}
-</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeStateDialog.vue b/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
deleted file mode 100644
index 1acc7e0ef..000000000
--- a/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import axios from 'axios';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import FetchData from 'components/FetchData.vue';
-import notifyResults from 'src/utils/notifyResults';
-
-const emit = defineEmits(['update-state']);
-const editableStates = ref([]);
-const showChangeStateDialog = ref(false);
-const newState = ref(null);
-const $props = defineProps({
-    selectedRows: {
-        type: Array,
-        default: () => [],
-    },
-});
-const updateState = async () => {
-    try {
-        showChangeStateDialog.value = true;
-        const rowsToUpdate = $props.selectedRows.map(({ id }) =>
-            axios.post(`Tickets/state`, {
-                ticketFk: id,
-                code: newState.value,
-            }),
-        );
-        const result = await Promise.allSettled(rowsToUpdate);
-        notifyResults(result, 'ticketFk');
-
-        emit('update-state', newState.value);
-    } catch (err) {
-        return err;
-    }
-};
-</script>
-
-<template>
-    <FetchData
-        url="States/editableStates"
-        @on-fetch="(data) => (editableStates = data)"
-        auto-load
-    />
-    <QCard class="q-pa-sm">
-        <QCardSection class="row items-center justify-center column items-stretch">
-            <span>{{ $t('negative.detail.modal.changeState.title') }}</span>
-            <VnSelect
-                :label="$t('negative.detail.modal.changeState.placeholder')"
-                v-model="newState"
-                :options="editableStates"
-                option-label="name"
-                option-value="code"
-            />
-        </QCardSection>
-        <QCardActions align="right">
-            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
-            <QBtn
-                :label="$t('globals.confirm')"
-                color="primary"
-                :disable="!newState"
-                @click="updateState"
-                unelevated
-                autofocus
-            /> </QCardActions
-    ></QCard>
-</template>
-
-<style lang="scss" scoped>
-.list {
-    max-height: 100%;
-    padding: 15px;
-    width: 100%;
-}
-
-.grid-style-transition {
-    transition:
-        transform 0.28s,
-        background-color 0.28s;
-}
-
-#true {
-    background-color: $positive;
-}
-
-#false {
-    background-color: $negative;
-}
-
-div.q-dialog__inner > div {
-    max-width: fit-content !important;
-}
-</style>
diff --git a/src/pages/Ticket/TicketFuture.vue b/src/pages/Ticket/TicketFuture.vue
index 92911cd25..0d216bed4 100644
--- a/src/pages/Ticket/TicketFuture.vue
+++ b/src/pages/Ticket/TicketFuture.vue
@@ -1,22 +1,24 @@
 <script setup>
-import { ref, computed, reactive, watch } from 'vue';
+import { onMounted, ref, computed, reactive } from 'vue';
 import { useI18n } from 'vue-i18n';
 
+import FetchData from 'components/FetchData.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
 import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
-import VnTable from 'src/components/VnTable/VnTable.vue';
 import TicketFutureFilter from './TicketFutureFilter.vue';
 
 import { dashIfEmpty, toCurrency } from 'src/filters';
 import { useVnConfirm } from 'composables/useVnConfirm';
+import { useArrayData } from 'composables/useArrayData';
 import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import useNotify from 'src/composables/useNotify.js';
 import { useState } from 'src/composables/useState';
 import { toDateTimeFormat } from 'src/filters/date.js';
 import axios from 'axios';
-import TicketProblems from 'src/components/TicketProblems.vue';
 
 const state = useState();
 const { t } = useI18n();
@@ -24,126 +26,214 @@ const { openConfirmationModal } = useVnConfirm();
 const { notify } = useNotify();
 const user = state.getUser();
 
+const itemPackingTypesOptions = ref([]);
 const selectedTickets = ref([]);
-const vnTableRef = ref({});
-const originElRef = ref(null);
-const destinationElRef = ref(null);
+
+const exprBuilder = (param, value) => {
+    switch (param) {
+        case 'id':
+            return { id: value };
+        case 'futureId':
+            return { futureId: value };
+        case 'liters':
+            return { liters: value };
+        case 'lines':
+            return { lines: value };
+        case 'iptColFilter':
+            return { ipt: { like: `%${value}%` } };
+        case 'futureIptColFilter':
+            return { futureIpt: { like: `%${value}%` } };
+        case 'totalWithVat':
+            return { totalWithVat: value };
+    }
+};
+
 const userParams = reactive({
     futureScopeDays: Date.vnNew().toISOString(),
     originScopeDays: Date.vnNew().toISOString(),
     warehouseFk: user.value.warehouseFk,
 });
 
+const arrayData = useArrayData('FutureTickets', {
+    url: 'Tickets/getTicketsFuture',
+    userParams: userParams,
+    exprBuilder: exprBuilder,
+});
+const { store } = arrayData;
+
+const params = reactive({
+    futureScopeDays: Date.vnNew(),
+    originScopeDays: Date.vnNew(),
+    warehouseFk: user.value.warehouseFk,
+});
+
+const applyColumnFilter = async (col) => {
+    const paramKey = col.columnFilter?.filterParamKey || col.field;
+    params[paramKey] = col.columnFilter.filterValue;
+    await arrayData.addFilter({ params });
+};
+
+const getInputEvents = (col) => {
+    return col.columnFilter.type === 'select'
+        ? { 'update:modelValue': () => applyColumnFilter(col) }
+        : {
+              'keyup.enter': () => applyColumnFilter(col),
+          };
+};
+
+const tickets = computed(() => store.data);
+
 const ticketColumns = computed(() => [
     {
-        label: '',
+        label: t('futureTickets.problems'),
         name: 'problems',
-        headerClass: 'horizontal-separator',
         align: 'left',
-        columnFilter: false,
+        columnFilter: null,
     },
     {
         label: t('advanceTickets.ticketId'),
-        name: 'id',
+        name: 'ticketId',
         align: 'center',
-        headerClass: 'horizontal-separator',
+        sortable: true,
+        columnFilter: {
+            component: VnInput,
+            type: 'text',
+            filterValue: null,
+            filterParamKey: 'id',
+            event: getInputEvents,
+            attrs: {
+                dense: true,
+            },
+        },
     },
     {
         label: t('futureTickets.shipped'),
         name: 'shipped',
         align: 'left',
-        columnFilter: false,
-        headerClass: 'horizontal-separator',
+        sortable: true,
+        columnFilter: null,
     },
     {
-        align: 'center',
-        class: 'shrink',
         label: t('advanceTickets.ipt'),
         name: 'ipt',
+        field: 'ipt',
+        align: 'left',
+        sortable: true,
         columnFilter: {
-            component: 'select',
+            component: VnSelect,
+            filterParamKey: 'iptColFilter',
+            type: 'select',
+            filterValue: null,
+            event: getInputEvents,
             attrs: {
-                url: 'itemPackingTypes',
-                fields: ['code', 'description'],
-                where: { isActive: true },
-                optionValue: 'code',
-                optionLabel: 'description',
-                inWhere: false,
+                options: itemPackingTypesOptions.value,
+                'option-value': 'code',
+                'option-label': 'description',
+                dense: true,
             },
         },
-        format: (row, dashIfEmpty) => dashIfEmpty(row.ipt),
-        headerClass: 'horizontal-separator',
+        format: (val) => dashIfEmpty(val),
     },
     {
         label: t('ticketList.state'),
         name: 'state',
         align: 'left',
-        columnFilter: false,
-        headerClass: 'horizontal-separator',
+        sortable: true,
+        columnFilter: null,
     },
     {
         label: t('advanceTickets.liters'),
         name: 'liters',
+        field: 'liters',
         align: 'left',
-        headerClass: 'horizontal-separator',
+        sortable: true,
+        columnFilter: {
+            component: VnInput,
+            type: 'text',
+            filterValue: null,
+            event: getInputEvents,
+            attrs: {
+                dense: true,
+            },
+        },
     },
     {
         label: t('advanceTickets.import'),
+        field: 'import',
         name: 'import',
         align: 'left',
-        headerClass: 'horizontal-separator',
-        columnFilter: false,
-        format: (row) => toCurrency(row.totalWithVat),
+        sortable: true,
     },
     {
         label: t('futureTickets.availableLines'),
         name: 'lines',
         field: 'lines',
         align: 'center',
-        headerClass: 'horizontal-separator',
-        format: (row, dashIfEmpty) => dashIfEmpty(row.lines),
+        sortable: true,
+        columnFilter: {
+            component: VnInput,
+            type: 'text',
+            filterValue: null,
+            event: getInputEvents,
+            attrs: {
+                dense: true,
+            },
+        },
+        format: (val) => dashIfEmpty(val),
     },
     {
         label: t('advanceTickets.futureId'),
         name: 'futureId',
-        align: 'center',
-        headerClass: 'horizontal-separator vertical-separator ',
-        columnClass: 'vertical-separator',
+        align: 'left',
+        sortable: true,
+        columnFilter: {
+            component: VnInput,
+            type: 'text',
+            filterValue: null,
+            filterParamKey: 'futureId',
+            event: getInputEvents,
+            attrs: {
+                dense: true,
+            },
+        },
     },
     {
         label: t('futureTickets.futureShipped'),
         name: 'futureShipped',
         align: 'left',
-        headerClass: 'horizontal-separator',
-        columnFilter: false,
-        format: (row) => toDateTimeFormat(row.futureShipped),
+        sortable: true,
+        columnFilter: null,
+        format: (val) => dashIfEmpty(val),
     },
+
     {
-        align: 'center',
         label: t('advanceTickets.futureIpt'),
-        class: 'shrink',
         name: 'futureIpt',
+        field: 'futureIpt',
+        align: 'left',
+        sortable: true,
         columnFilter: {
-            component: 'select',
+            component: VnSelect,
+            filterParamKey: 'futureIptColFilter',
+            type: 'select',
+            filterValue: null,
+            event: getInputEvents,
             attrs: {
-                url: 'itemPackingTypes',
-                fields: ['code', 'description'],
-                where: { isActive: true },
-                optionValue: 'code',
-                optionLabel: 'description',
+                options: itemPackingTypesOptions.value,
+                'option-value': 'code',
+                'option-label': 'description',
+                dense: true,
             },
         },
-        headerClass: 'horizontal-separator',
-        format: (row, dashIfEmpty) => dashIfEmpty(row.futureIpt),
+        format: (val) => dashIfEmpty(val),
     },
     {
         label: t('advanceTickets.futureState'),
         name: 'futureState',
         align: 'right',
-        headerClass: 'horizontal-separator',
-        class: 'expand',
-        columnFilter: false,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.futureState),
+        sortable: true,
+        columnFilter: null,
+        format: (val) => dashIfEmpty(val),
     },
 ]);
 
@@ -168,51 +258,26 @@ const moveTicketsFuture = async () => {
     await axios.post('Tickets/merge', params);
     notify(t('advanceTickets.moveTicketSuccess'), 'positive');
     selectedTickets.value = [];
-    vnTableRef.value.reload();
+    arrayData.fetch({ append: false });
 };
-
-watch(
-    () => vnTableRef.value.tableRef?.$el,
-    ($el) => {
-        if (!$el) return;
-        const head = $el.querySelector('thead');
-        const firstRow = $el.querySelector('thead > tr');
-
-        const newRow = document.createElement('tr');
-        destinationElRef.value = document.createElement('th');
-        originElRef.value = document.createElement('th');
-
-        newRow.classList.add('bg-header');
-        destinationElRef.value.classList.add('text-uppercase', 'color-vn-label');
-        originElRef.value.classList.add('text-uppercase', 'color-vn-label');
-
-        destinationElRef.value.setAttribute('colspan', '7');
-        originElRef.value.setAttribute('colspan', '9');
-
-        originElRef.value.textContent = `${t('advanceTickets.origin')}`;
-        destinationElRef.value.textContent = `${t('advanceTickets.destination')}`;
-
-        newRow.append(destinationElRef.value, originElRef.value);
-        head.insertBefore(newRow, firstRow);
-    },
-    { once: true, inmmediate: true },
-);
-
-watch(
-    () => vnTableRef.value.params,
-    () => {
-        if (originElRef.value && destinationElRef.value) {
-            destinationElRef.value.textContent = `${t('advanceTickets.origin')}`;
-            originElRef.value.textContent = `${t('advanceTickets.destination')}`;
-        }
-    },
-    { deep: true },
-);
+onMounted(async () => {
+    await arrayData.fetch({ append: false });
+});
 </script>
 
 <template>
+    <FetchData
+        url="itemPackingTypes"
+        :filter="{
+            fields: ['code', 'description'],
+            order: 'description ASC',
+            where: { isActive: true },
+        }"
+        auto-load
+        @on-fetch="(data) => (itemPackingTypesOptions = data)"
+    />
     <VnSearchbar
-        data-key="futureTicket"
+        data-key="FutureTickets"
         :label="t('Search ticket')"
         :info="t('futureTickets.searchInfo')"
     />
@@ -228,7 +293,7 @@ watch(
                         t(`futureTickets.moveTicketDialogSubtitle`, {
                             selectedTickets: selectedTickets.length,
                         }),
-                        moveTicketsFuture,
+                        moveTicketsFuture
                     )
                 "
             >
@@ -240,135 +305,235 @@ watch(
     </VnSubToolbar>
     <RightMenu>
         <template #right-panel>
-            <TicketFutureFilter data-key="futureTickets" />
+            <TicketFutureFilter data-key="FutureTickets" />
         </template>
     </RightMenu>
     <QPage class="column items-center q-pa-md">
-        <VnTable
-            data-key="futureTickets"
-            ref="vnTableRef"
-            url="Tickets/getTicketsFuture"
-            search-url="futureTickets"
-            :user-params="userParams"
-            :limit="0"
+        <QTable
+            :rows="tickets"
             :columns="ticketColumns"
-            :table="{
-                'row-key': '$index',
-                selection: 'multiple',
-            }"
+            row-key="id"
+            selection="multiple"
             v-model:selected="selectedTickets"
-            :right-search="false"
-            auto-load
-            :disable-option="{ card: true }"
+            :pagination="{ rowsPerPage: 0 }"
+            :no-data-label="t('globals.noResults')"
+            style="max-width: 99%"
         >
-            <template #column-problems="{ row }">
-                <span class="q-gutter-x-xs">
-                    <QIcon
-                        v-if="row.futureAgencyFk !== row.agencyFk && row.agencyFk"
-                        color="primary"
-                        name="vn:agency-term"
-                        size="xs"
-                        class="q-mr-xs"
+            <template #header="props">
+                <QTr>
+                    <QTh class="horizontal-separator" />
+                    <QTh
+                        class="horizontal-separator text-uppercase color-vn-label"
+                        colspan="8"
+                        translate
                     >
-                        <QTooltip class="column">
-                            <span>
-                                {{
-                                    t('advanceTickets.originAgency', {
-                                        agency: row.futureAgency,
-                                    })
-                                }}
-                            </span>
-                            <span>
-                                {{
-                                    t('advanceTickets.destinationAgency', {
-                                        agency: row.agency,
-                                    })
-                                }}
-                            </span>
+                        {{ t('advanceTickets.origin') }}
+                    </QTh>
+                    <QTh
+                        class="horizontal-separator text-uppercase color-vn-label"
+                        colspan="4"
+                        translate
+                    >
+                        {{ t('advanceTickets.destination') }}
+                    </QTh>
+                </QTr>
+                <QTr>
+                    <QTh>
+                        <QCheckbox v-model="props.selected" />
+                    </QTh>
+                    <QTh
+                        v-for="(col, index) in ticketColumns"
+                        :key="index"
+                        :class="{ 'vertical-separator': col.name === 'futureId' }"
+                    >
+                        {{ col.label }}
+                    </QTh>
+                </QTr>
+            </template>
+            <template #top-row="{ cols }">
+                <QTr>
+                    <QTd />
+                    <QTd
+                        v-for="(col, index) in cols"
+                        :key="index"
+                        style="max-width: 100px"
+                    >
+                        <component
+                            :is="col.columnFilter.component"
+                            v-if="col.columnFilter"
+                            v-model="col.columnFilter.filterValue"
+                            v-bind="col.columnFilter.attrs"
+                            v-on="col.columnFilter.event(col)"
+                            dense
+                        />
+                    </QTd>
+                </QTr>
+            </template>
+            <template #header-cell-availableLines="{ col }">
+                <QTh class="vertical-separator">
+                    {{ col.label }}
+                </QTh>
+            </template>
+            <template #body-cell-problems="{ row }">
+                <QTd class="q-gutter-x-xs">
+                    <QIcon
+                        v-if="row.isTaxDataChecked === 0"
+                        color="primary"
+                        name="vn:no036"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('futureTickets.noVerified') }}
                         </QTooltip>
                     </QIcon>
-                    <TicketProblems :row />
-                </span>
+                    <QIcon
+                        v-if="row.hasTicketRequest"
+                        color="primary"
+                        name="vn:buyrequest"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('futureTickets.purchaseRequest') }}
+                        </QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.itemShortage"
+                        color="primary"
+                        name="vn:unavailable"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('ticketSale.noVisible') }}
+                        </QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.isFreezed"
+                        color="primary"
+                        name="vn:frozen"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('futureTickets.clientFrozen') }}
+                        </QTooltip>
+                    </QIcon>
+                    <QIcon v-if="row.risk" color="primary" name="vn:risk" size="xs">
+                        <QTooltip>
+                            {{ t('futureTickets.risk') }}: {{ row.risk }}
+                        </QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasComponentLack"
+                        color="primary"
+                        name="vn:components"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('futureTickets.componentLack') }}
+                        </QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasRounding"
+                        color="primary"
+                        name="sync_problem"
+                        size="xs"
+                    >
+                        <QTooltip>
+                            {{ t('futureTickets.rounding') }}
+                        </QTooltip>
+                    </QIcon>
+                </QTd>
             </template>
-            <template #column-id="{ row }">
-                <QBtn flat class="link" @click.stop dense>
-                    {{ row.id }}
-                    <TicketDescriptorProxy :id="row.id" />
-                </QBtn>
+            <template #body-cell-ticketId="{ row }">
+                <QTd>
+                    <QBtn flat class="link">
+                        {{ row.id }}
+                        <TicketDescriptorProxy :id="row.id" />
+                    </QBtn>
+                </QTd>
             </template>
-            <template #column-shipped="{ row }">
-                <QBadge
-                    text-color="black"
-                    :color="getDateQBadgeColor(row.shipped)"
-                    class="q-ma-none"
-                >
-                    {{ toDateTimeFormat(row.shipped) }}
-                </QBadge>
+            <template #body-cell-shipped="{ row }">
+                <QTd class="shipped">
+                    <QBadge
+                        text-color="black"
+                        :color="getDateQBadgeColor(row.shipped)"
+                        class="q-ma-none"
+                    >
+                        {{ toDateTimeFormat(row.shipped) }}
+                    </QBadge>
+                </QTd>
             </template>
-            <template #column-state="{ row }">
-                <QBadge
-                    v-if="row.state"
-                    text-color="black"
-                    :color="row.classColor"
-                    class="q-ma-none"
-                    dense
-                >
-                    {{ row.state }}
-                </QBadge>
-                <span v-else> {{ dashIfEmpty(row.state) }}</span>
+            <template #body-cell-state="{ row }">
+                <QTd>
+                    <QBadge
+                        text-color="black"
+                        :color="row.classColor"
+                        class="q-ma-none"
+                        dense
+                    >
+                        {{ row.state }}
+                    </QBadge>
+                </QTd>
             </template>
-            <template #column-import="{ row }">
-                <QBadge
-                    :text-color="
-                        totalPriceColor(row.totalWithVat) === 'warning'
-                            ? 'black'
-                            : 'white'
-                    "
-                    :color="totalPriceColor(row.totalWithVat)"
-                    class="q-ma-none"
-                    dense
-                >
-                    {{ toCurrency(row.totalWithVat || 0) }}
-                </QBadge>
+            <template #body-cell-import="{ row }">
+                <QTd>
+                    <QBadge
+                        :text-color="
+                            totalPriceColor(row.totalWithVat) === 'warning'
+                                ? 'black'
+                                : 'white'
+                        "
+                        :color="totalPriceColor(row.totalWithVat)"
+                        class="q-ma-none"
+                        dense
+                    >
+                        {{ toCurrency(row.totalWithVat || 0) }}
+                    </QBadge>
+                </QTd>
             </template>
-            <template #column-futureId="{ row }">
-                <QBtn flat class="link" @click.stop dense>
-                    {{ row.futureId }}
-                    <TicketDescriptorProxy :id="row.futureId" />
-                </QBtn>
+            <template #body-cell-futureId="{ row }">
+                <QTd class="vertical-separator">
+                    <QBtn flat class="link" dense>
+                        {{ row.futureId }}
+                        <TicketDescriptorProxy :id="row.futureId" />
+                    </QBtn>
+                </QTd>
             </template>
-            <template #column-futureShipped="{ row }">
-                <QBadge
-                    text-color="black"
-                    :color="getDateQBadgeColor(row.futureShipped)"
-                    class="q-ma-none"
-                >
-                    {{ toDateTimeFormat(row.futureShipped) }}
-                </QBadge>
+            <template #body-cell-futureShipped="{ row }">
+                <QTd class="shipped">
+                    <QBadge
+                        text-color="black"
+                        :color="getDateQBadgeColor(row.futureShipped)"
+                        class="q-ma-none"
+                    >
+                        {{ toDateTimeFormat(row.futureShipped) }}
+                    </QBadge>
+                </QTd>
             </template>
-            <template #column-futureState="{ row }">
-                <QBadge
-                    text-color="black"
-                    :color="row.futureClassColor"
-                    class="q-mr-xs"
-                    dense
-                >
-                    {{ row.futureState }}
-                </QBadge>
+            <template #body-cell-futureState="{ row }">
+                <QTd>
+                    <QBadge
+                        text-color="black"
+                        :color="row.futureClassColor"
+                        class="q-ma-none"
+                        dense
+                    >
+                        {{ row.futureState }}
+                    </QBadge>
+                </QTd>
             </template>
-        </VnTable>
+        </QTable>
     </QPage>
 </template>
 
 <style scoped lang="scss">
-:deep(.vertical-separator) {
+.shipped {
+    min-width: 132px;
+}
+.vertical-separator {
     border-left: 4px solid white !important;
 }
 
-:deep(.horizontal-separator) {
-    border-top: 4px solid white !important;
-}
-:deep(.horizontal-bottom-separator) {
+.horizontal-separator {
     border-bottom: 4px solid white !important;
 }
 </style>
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index 64e060a39..d28b0af71 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -12,7 +12,7 @@ import axios from 'axios';
 import { onMounted } from 'vue';
 
 const { t } = useI18n();
-defineProps({
+const props = defineProps({
     dataKey: {
         type: String,
         required: true,
@@ -58,7 +58,7 @@ onMounted(async () => {
         auto-load
     />
     <VnFilterPanel
-        :data-key
+        :data-key="props.dataKey"
         :un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
     >
         <template #tags="{ tag, formatFn }">
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index cdbb22d9b..f11b32c3a 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -23,8 +23,6 @@ ticketSale:
     hasComponentLack: Component lack
     ok: Ok
     more: More
-    transferLines: Transfer lines(no basket)/ Split
-    transferBasket: Some row selected is basket
 advanceTickets:
     preparation: Preparation
     origin: Origin
@@ -190,6 +188,7 @@ ticketList:
     accountPayment: Account payment
     sendDocuware: Set delivered and send delivery note(s) to the tablet
     addPayment: Add payment
+    date: Date
     company: Company
     amount: Amount
     reference: Reference
@@ -203,89 +202,9 @@ ticketList:
     creditCard: Credit card
     transfers: Transfers
     province: Province
+    warehouse: Warehouse
+    hour: Hour
     closure: Closure
     toLines: Go to lines
     addressNickname: Address nickname
     ref: Reference
-    rounding: Rounding
-    noVerifiedData: No verified data
-    purchaseRequest: Purchase request
-    notVisible: Not visible
-    clientFrozen: Client frozen
-    componentLack: Component lack
-negative:
-    hour: Hour
-    id: Id Article
-    longName: Article
-    supplier: Supplier
-    colour: Colour
-    size: Size
-    origen: Origin
-    value: Negative
-    itemFk: Article
-    producer: Producer
-    warehouse: Warehouse
-    warehouseFk: Warehouse
-    category: Category
-    categoryFk: Family
-    type: Type
-    typeFk: Type
-    lack: Negative
-    inkFk: inkFk
-    timed: timed
-    date: Date
-    minTimed: minTimed
-    negativeAction: Negative
-    totalNegative: Total negatives
-    days: Days
-    buttonsUpdate:
-        item: Item
-        state: State
-        quantity: Quantity
-    modalOrigin:
-        title: Update negatives
-        question: Select a state to update
-    modalSplit:
-        title: Confirm split selected
-        question: Select a state to update
-    detail:
-        saleFk: Sale
-        itemFk: Article
-        ticketFk: Ticket
-        code: Code
-        nickname: Alias
-        name: Name
-        zoneName: Agency name
-        shipped: Date
-        theoreticalhour: Theoretical hour
-        agName: Agency
-        quantity: Quantity
-        alertLevelCode: Group state
-        state: State
-        peticionCompra: Ticket request
-        isRookie: Is rookie
-        turno: Turn line
-        isBasket: Basket
-        hasObservation: Has substitution
-        hasToIgnore: VIP
-        modal:
-            changeItem:
-                title: Update item reference
-                placeholder: New item
-            changeState:
-                title: Update tickets state
-                placeholder: New state
-            changeQuantity:
-                title: Update tickets quantity
-                placeholder: New quantity
-            split:
-                title: Are you sure you want to split selected tickets?
-                subTitle: Confirm split action
-            handleSplited:
-                title: Handle splited  tickets
-                subTitle: Confirm date and agency
-    split:
-        ticket: Old ticket
-        newTicket: New ticket
-        status: Result
-        message: Message
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index 75d3c6a2b..945da8367 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -127,8 +127,6 @@ ticketSale:
     ok: Ok
     more: Más
     address: Consignatario
-    transferLines: Transferir líneas(no cesta)/ Separar
-    transferBasket: No disponible para una cesta
     size: Medida
 ticketComponents:
     serie: Serie
@@ -215,84 +213,3 @@ ticketList:
     toLines: Ir a lineas
     addressNickname: Alias consignatario
     ref: Referencia
-negative:
-    hour: Hora
-    id: Id Articulo
-    longName: Articulo
-    supplier: Productor
-    colour: Color
-    size: Medida
-    origen: Origen
-    value: Negativo
-    warehouseFk: Almacen
-    producer: Producer
-    category: Categoría
-    categoryFk: Familia
-    typeFk: Familia
-    warehouse: Almacen
-    lack: Negativo
-    inkFk: Color
-    timed: Hora
-    date: Fecha
-    minTimed: Hora
-    type: Tipo
-    negativeAction: Negativo
-    totalNegative: Total negativos
-    days: Rango de dias
-    buttonsUpdate:
-        item: artículo
-        state: Estado
-        quantity: Cantidad
-    modalOrigin:
-        title: Actualizar negativos
-        question: Seleccione un estado para guardar
-    modalSplit:
-        title: Confirmar acción de split
-        question: Selecciona un estado
-    detail:
-        saleFk: Línea
-        itemFk: Artículo
-        ticketFk: Ticket
-        code: code
-        nickname: Alias
-        name: Nombre
-        zoneName: Agencia
-        shipped: F. envío
-        theoreticalhour: Hora teórica
-        agName: Agencia
-        quantity: Cantidad
-        alertLevelCode: Estado agrupado
-        state: Estado
-        peticionCompra: Petición compra
-        isRookie: Cliente nuevo
-        turno: Linea turno
-        isBasket: Cesta
-        hasObservation: Tiene sustitución
-        hasToIgnore: VIP
-        modal:
-            changeItem:
-                title: Actualizar referencia artículo
-                placeholder: Nuevo articulo
-            changeState:
-                title: Actualizar estado
-                placeholder: Nuevo estado
-            changeQuantity:
-                title: Actualizar cantidad
-                placeholder: Nueva cantidad
-            split:
-                title: ¿Seguro de separar los tickets seleccionados?
-                subTitle: Confirma separar tickets seleccionados
-            handleSplited:
-                title: Gestionar tickets spliteados
-                subTitle: Confir fecha y agencia
-    split:
-        ticket: Ticket viejo
-        newTicket: Ticket nuevo
-        status: Estado
-        message: Mensaje
-    rounding: Redondeo
-    noVerifiedData: Sin datos comprobados
-    purchaseRequest: Petición de compra
-    notVisible: No visible
-    clientFrozen: Cliente congelado
-    componentLack: Faltan componentes
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index b1adc8126..4b9aa28ed 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -9,7 +9,6 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
-import VnInputTime from 'components/common/VnInputTime.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -54,16 +53,7 @@ const warehousesOptionsIn = ref([]);
                 <VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
                 <VnInputDate v-model="data.landed" :label="t('globals.landed')" />
             </VnRow>
-            <VnRow>
-                <VnInputDate
-                    v-model="data.availabled"
-                    :label="t('travel.summary.availabled')" 
-                    />
-                <VnInputTime
-                    v-model="data.availabled"
-                    :label="t('travel.summary.availabledHour')"
-                />
-            </VnRow>
+
             <VnRow>
                 <VnSelect
                     :label="t('globals.warehouseOut')"
@@ -111,3 +101,10 @@ const warehousesOptionsIn = ref([]);
         </template>
     </FormModel>
 </template>
+
+<i18n>
+es:
+    raidDays: El travel se desplaza automáticamente cada día para estar desde hoy al número de días indicado. Si se deja vacio no se moverá
+en:
+    raidDays: The travel adjusts itself daily to match the number of days set, starting from today. If left blank, it won’t move
+</i18n>
diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue
index cb09eafd6..445675b90 100644
--- a/src/pages/Travel/Card/TravelCard.vue
+++ b/src/pages/Travel/Card/TravelCard.vue
@@ -1,13 +1,43 @@
 <script setup>
 import TravelDescriptor from './TravelDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
-import filter from './TravelFilter.js';
+
+const userFilter = {
+    fields: [
+        'id',
+        'ref',
+        'shipped',
+        'landed',
+        'totalEntries',
+        'warehouseInFk',
+        'warehouseOutFk',
+        'cargoSupplierFk',
+        'agencyModeFk',
+        'isRaid',
+        'isDelivered',
+        'isReceived',
+    ],
+    include: [
+        {
+            relation: 'warehouseIn',
+            scope: {
+                fields: ['name'],
+            },
+        },
+        {
+            relation: 'warehouseOut',
+            scope: {
+                fields: ['name'],
+            },
+        },
+    ],
+};
 </script>
 <template>
     <VnCardBeta
         data-key="Travel"
-        url="Travels"
+        base-url="Travels"
         :descriptor="TravelDescriptor"
-        :filter="filter"
+        :user-filter="userFilter"
     />
 </template>
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index 922f89f33..72acf91b8 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -32,6 +32,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
 
 <template>
     <CardDescriptor
+        module="Travel"
         :url="`Travels/${entityId}`"
         :title="data.title"
         :subtitle="data.subtitle"
diff --git a/src/pages/Travel/Card/TravelFilter.js b/src/pages/Travel/Card/TravelFilter.js
index 05436834f..f5f4520fd 100644
--- a/src/pages/Travel/Card/TravelFilter.js
+++ b/src/pages/Travel/Card/TravelFilter.js
@@ -11,7 +11,6 @@ export default {
         'agencyModeFk',
         'isRaid',
         'daysInForward',
-        'availabled',
     ],
     include: [
         {
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 9f9552611..16d42f104 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -10,8 +10,6 @@ import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'
 import FetchData from 'src/components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import { toDate, toCurrency, toCelsius } from 'src/filters';
-import { toDateTimeFormat } from 'src/filters/date.js';
-import { dashIfEmpty } from 'src/filters';
 import axios from 'axios';
 import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
 
@@ -335,12 +333,6 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 <VnLv :label="t('globals.reference')" :value="travel.ref" />
                 <VnLv label="m³" :value="travel.m3" />
                 <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
-                <VnLv
-                    :label="t('travel.summary.availabled')"
-                    :value="
-                        dashIfEmpty(toDateTimeFormat(travel.availabled))
-                    "
-                />
             </QCard>
             <QCard class="full-width">
                 <VnTitle :text="t('travel.summary.entries')" />
diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index 2376bd6d2..2946c8814 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -217,7 +217,7 @@ const removeThermograph = async (id) => {
             icon="add"
             color="primary"
             @click="redirectToThermographForm('create')"
-            v-shortcut="'+'"
+            shortcut="+"
         />
         <QTooltip class="text-no-wrap">
             {{ t('Add thermograph') }}
diff --git a/src/pages/Travel/ExtraCommunityFilter.vue b/src/pages/Travel/ExtraCommunityFilter.vue
index b22574632..b903aeabf 100644
--- a/src/pages/Travel/ExtraCommunityFilter.vue
+++ b/src/pages/Travel/ExtraCommunityFilter.vue
@@ -113,7 +113,7 @@ warehouses();
                         <template #append>
                             <QBtn
                                 icon="add"
-                                v-shortcut="'+'"
+                                shortcut="+"
                                 flat
                                 dense
                                 size="12px"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index b227afcb2..e90c01be2 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -10,9 +10,6 @@ import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import TravelFilter from './TravelFilter.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
 import VnSection from 'src/components/common/VnSection.vue';
-import VnInputTime from 'src/components/common/VnInputTime.vue';
-import VnInputDate from 'src/components/common/VnInputDate.vue';
-import { toDateTimeFormat } from 'src/filters/date';
 
 const { viewSummary } = useSummaryDialog();
 const router = useRouter();
@@ -170,17 +167,6 @@ const columns = computed(() => [
         cardVisible: true,
         create: true,
     },
-    {
-        align: 'left',
-        name: 'availabled',
-        label: t('travel.summary.availabled'),
-        component: 'input',
-        columnClass: 'expand',
-        columnField: {
-            component: null,
-        },
-        format: (row, dashIfEmpty) => dashIfEmpty(toDateTimeFormat(row.availabled)),
-    },
     {
         align: 'right',
         label: '',
@@ -283,16 +269,6 @@ const columns = computed(() => [
                         :class="{ 'is-active': row.isReceived }"
                     />
                 </template>
-                <template #more-create-dialog="{ data }">
-                    <VnInputDate
-                        v-model="data.availabled"
-                        :label="t('travel.summary.availabled')"
-                    />
-                    <VnInputTime
-                        v-model="data.availabled"
-                        :label="t('travel.summary.availabledHour')"
-                    />
-                </template>
                 <template #moreFilterPanel="{ params }">
                     <VnInputNumber
                         :label="t('params.scopeDays')"
diff --git a/src/pages/Wagon/Card/WagonCard.vue b/src/pages/Wagon/Card/WagonCard.vue
index 644a30ffa..ed6c83778 100644
--- a/src/pages/Wagon/Card/WagonCard.vue
+++ b/src/pages/Wagon/Card/WagonCard.vue
@@ -2,5 +2,5 @@
 import VnCard from 'components/common/VnCard.vue';
 </script>
 <template>
-    <VnCard data-key="Wagon" url="Wagons" />
+    <VnCard data-key="Wagon" base-url="Wagons" />
 </template>
diff --git a/src/pages/Wagon/Type/WagonTypeList.vue b/src/pages/Wagon/Type/WagonTypeList.vue
index 4c0b078a7..c0943c58e 100644
--- a/src/pages/Wagon/Type/WagonTypeList.vue
+++ b/src/pages/Wagon/Type/WagonTypeList.vue
@@ -96,13 +96,7 @@ async function remove(row) {
         >
         </VnTable>
         <QPageSticky :offset="[18, 18]">
-            <QBtn
-                @click.stop="dialog.show()"
-                color="primary"
-                fab
-                icon="add"
-                v-shortcut="'+'"
-            >
+            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Create new Wagon type')"
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
index fcf0f0369..6a13e3f39 100644
--- a/src/pages/Worker/Card/WorkerBasicData.vue
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -1,5 +1,6 @@
 <script setup>
-import { ref } from 'vue';
+import { ref, onBeforeMount } from 'vue';
+import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import FetchData from 'components/FetchData.vue';
@@ -10,13 +11,18 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 
 const { t } = useI18n();
-const form = ref();
 const educationLevels = ref([]);
 const countries = ref([]);
 const maritalStatus = [
     { code: 'M', name: t('Married') },
     { code: 'S', name: t('Single') },
 ];
+const advancedSummary = ref({});
+
+onBeforeMount(async () => {
+    advancedSummary.value =
+        (await useAdvancedSummary('Workers', +useRoute().params.id)) ?? {};
+});
 </script>
 <template>
     <FetchData
@@ -32,15 +38,14 @@ const maritalStatus = [
         auto-load
     />
     <FormModel
-        ref="form"
+        :filter="{ where: { id: +$route.params.id } }"
+        url="Workers/summary"
         :url-update="`Workers/${$route.params.id}`"
         auto-load
         model="Worker"
         @on-fetch="
             async (data) => {
-                Object.assign(data, (await useAdvancedSummary('Workers', data.id)) ?? {});
-                await $nextTick();
-                if (form) form.hasChanges = false;
+                Object.assign(data, advancedSummary);
             }
         "
     >
diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue
index df4616011..5ca95a1a4 100644
--- a/src/pages/Worker/Card/WorkerCalendar.vue
+++ b/src/pages/Worker/Card/WorkerCalendar.vue
@@ -1,8 +1,7 @@
 <script setup>
-import { nextTick, ref, watch, computed } from 'vue';
+import { nextTick, ref, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
-import { useAcl } from 'src/composables/useAcl';
 
 import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
 import FetchData from 'components/FetchData.vue';
@@ -10,17 +9,10 @@ import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 import axios from 'axios';
-import VnNotes from 'src/components/ui/VnNotes.vue';
-import { useStateStore } from 'src/stores/useStateStore';
-const stateStore = useStateStore();
 
 const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
-const acl = useAcl();
-const canSeeNotes = computed(() =>
-    acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
-);
 const workerIsFreelance = ref();
 const WorkerFreelanceRef = ref();
 const workerCalendarFilterRef = ref(null);
@@ -34,10 +26,6 @@ const contractHolidays = ref(null);
 const yearHolidays = ref(null);
 const eventsMap = ref({});
 const festiveEventsMap = ref({});
-const saveUrl = ref();
-const body = {
-    workerFk: route.params.id,
-};
 
 const onFetchActiveContract = (data) => {
     if (!data) return;
@@ -79,7 +67,7 @@ const onFetchAbsences = (data) => {
                     name: holidayName,
                     isFestive: true,
                 },
-                true,
+                true
             );
         });
     }
@@ -158,7 +146,7 @@ watch(
     async () => {
         await nextTick();
         await activeContractRef.value.fetch();
-    },
+    }
 );
 watch([year, businessFk], () => refreshData());
 </script>
@@ -193,20 +181,6 @@ watch([year, businessFk], () => refreshData());
             />
         </template>
     </RightMenu>
-    <Teleport to="#st-data" v-if="stateStore.isSubToolbarShown() && canSeeNotes">
-        <VnNotes
-            :just-input="true"
-            :url="`Workers/${route.params.id}/business`"
-            :filter="{ fields: ['id', 'notes', 'workerFk'] }"
-            :save-url="saveUrl"
-            @on-fetch="
-                (data) => {
-                    saveUrl = `Businesses/${data.id}`;
-                }
-            "
-            :body="body"
-        />
-    </Teleport>
     <QPage class="column items-center">
         <QCard v-if="workerIsFreelance">
             <QCardSection class="text-center">
diff --git a/src/pages/Worker/Card/WorkerCalendarFilter.vue b/src/pages/Worker/Card/WorkerCalendarFilter.vue
index 48fc4094b..67b7df907 100644
--- a/src/pages/Worker/Card/WorkerCalendarFilter.vue
+++ b/src/pages/Worker/Card/WorkerCalendarFilter.vue
@@ -180,6 +180,8 @@ const yearList = ref(generateYears());
                     :is-clearable="false"
                 />
             </QItemSection>
+        </QItem>
+        <QItem>
             <QItemSection>
                 <VnSelect
                     :label="t('Contract')"
diff --git a/src/pages/Worker/Card/WorkerCard.vue b/src/pages/Worker/Card/WorkerCard.vue
index 3b7a62025..1ada15a33 100644
--- a/src/pages/Worker/Card/WorkerCard.vue
+++ b/src/pages/Worker/Card/WorkerCard.vue
@@ -3,10 +3,5 @@ import WorkerDescriptor from './WorkerDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta
-        data-key="Worker"
-        url="Workers/summary"
-        :id-in-where="true"
-        :descriptor="WorkerDescriptor"
-    />
+    <VnCardBeta data-key="Worker" custom-url="Workers/summary" :descriptor="WorkerDescriptor" />
 </template>
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index de3f634e2..d87fd4a54 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -10,7 +10,7 @@ import axios from 'axios';
 import VnImg from 'src/components/ui/VnImg.vue';
 import EditPictureForm from 'components/EditPictureForm.vue';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
-import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
 
 const $props = defineProps({
     id: {
@@ -21,7 +21,7 @@ const $props = defineProps({
     dataKey: {
         type: String,
         required: false,
-        default: 'Worker',
+        default: 'workerData',
     },
 });
 const image = ref(null);
@@ -50,8 +50,9 @@ const handlePhotoUpdated = (evt = false) => {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
+        module="Worker"
         :data-key="dataKey"
-        url="Workers/summary"
+        url="Workers/descriptor"
         :filter="{ where: { id: entityId } }"
         title="user.nickname"
         @on-fetch="getIsExcluded"
@@ -151,7 +152,7 @@ const handlePhotoUpdated = (evt = false) => {
                 <QBtn
                     :to="{
                         name: 'AccountCard',
-                        params: { id: entity.user?.id },
+                        params: { id: entity.user.id },
                     }"
                     size="md"
                     icon="face"
diff --git a/src/pages/Worker/Card/WorkerDescriptorProxy.vue b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
index a142570f9..43deb7821 100644
--- a/src/pages/Worker/Card/WorkerDescriptorProxy.vue
+++ b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
@@ -12,6 +12,11 @@ const $props = defineProps({
 
 <template>
     <QPopupProxy>
-        <WorkerDescriptor v-if="$props.id" :id="$props.id" :summary="WorkerSummary" />
+        <WorkerDescriptor
+            v-if="$props.id"
+            :id="$props.id"
+            :summary="WorkerSummary"
+            data-key="workerDescriptorProxy"
+        />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Worker/Card/WorkerFormation.vue b/src/pages/Worker/Card/WorkerFormation.vue
index e8680f7dd..6fd5a4eae 100644
--- a/src/pages/Worker/Card/WorkerFormation.vue
+++ b/src/pages/Worker/Card/WorkerFormation.vue
@@ -94,7 +94,6 @@ const columns = computed(() => [
         align: 'left',
         name: 'hasDiploma',
         label: t('worker.formation.tableVisibleColumns.hasDiploma'),
-        component: 'checkbox',
         create: true,
     },
     {
@@ -119,7 +118,7 @@ const columns = computed(() => [
         :url="`Workers/${entityId}/trainingCourse`"
         :url-create="`Workers/${entityId}/trainingCourse`"
         save-url="TrainingCourses/crud"
-        :user-filter="courseFilter"
+        :filter="courseFilter"
         :create="{
             urlCreate: 'trainingCourses',
             title: t('Create training course'),
diff --git a/src/pages/Worker/Card/WorkerMedical.vue b/src/pages/Worker/Card/WorkerMedical.vue
index c04f6496b..c220df76a 100644
--- a/src/pages/Worker/Card/WorkerMedical.vue
+++ b/src/pages/Worker/Card/WorkerMedical.vue
@@ -3,23 +3,11 @@ import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import VnTable from 'components/VnTable/VnTable.vue';
-import { dashIfEmpty } from 'src/filters';
 const tableRef = ref();
 const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => route.params.id);
 
-const centerFilter = {
-    include: [
-        {
-            relation: 'center',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-    ],
-};
-
 const columns = [
     {
         align: 'left',
@@ -48,9 +36,6 @@ const columns = [
             url: 'medicalCenters',
             fields: ['id', 'name'],
         },
-        format: (row, dashIfEmpty) => {
-            return dashIfEmpty(row.center?.name);
-        },
     },
     {
         align: 'left',
@@ -99,7 +84,6 @@ const columns = [
         ref="tableRef"
         data-key="WorkerMedical"
         :url="`Workers/${entityId}/medicalReview`"
-        :user-filter="centerFilter"
         save-url="MedicalReviews/crud"
         :create="{
             urlCreate: 'medicalReviews',
diff --git a/src/pages/Worker/Card/WorkerOperator.vue b/src/pages/Worker/Card/WorkerOperator.vue
index 6faeefe67..cdacc72c0 100644
--- a/src/pages/Worker/Card/WorkerOperator.vue
+++ b/src/pages/Worker/Card/WorkerOperator.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
-import { ref, computed, watch } from 'vue';
+import { ref, computed } from 'vue';
 import FetchData from 'components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
@@ -19,7 +19,6 @@ const trainsData = ref([]);
 const machinesData = ref([]);
 const route = useRoute();
 const routeId = computed(() => route.params.id);
-const selected = ref([]);
 
 const initialData = computed(() => {
     return {
@@ -42,21 +41,6 @@ async function insert() {
     await axios.post('Operators', initialData.value);
     crudModelRef.value.reload();
 }
-
-watch(
-    () => crudModelRef.value?.formData,
-    (formData) => {
-        if (formData && formData.length) {
-            if (JSON.stringify(selected.value) !== JSON.stringify(formData)) {
-                selected.value = formData;
-            }
-        } else if (selected.value.length > 0) {
-            selected.value = [];
-        }
-    },
-    { immediate: true, deep: true }
-);
-
 </script>
 
 <template>
@@ -83,7 +67,6 @@ watch(
             :data-required="{ workerFk: route.params.id }"
             ref="crudModelRef"
             search-url="operator"
-            :selected="selected"
             auto-load
         >
             <template #body="{ rows }">
diff --git a/src/pages/Worker/Card/WorkerPda.vue b/src/pages/Worker/Card/WorkerPda.vue
index 47e13cf6d..f6cb92aac 100644
--- a/src/pages/Worker/Card/WorkerPda.vue
+++ b/src/pages/Worker/Card/WorkerPda.vue
@@ -101,7 +101,7 @@ function reloadData() {
                                 openConfirmationModal(
                                     t(`Remove PDA`),
                                     t('Do you want to remove this PDA?'),
-                                    () => deallocatePDA(row.deviceProductionFk),
+                                    () => deallocatePDA(row.deviceProductionFk)
                                 )
                             "
                         >
@@ -114,13 +114,7 @@ function reloadData() {
             </template>
         </VnPaginate>
         <QPageSticky :offset="[18, 18]">
-            <QBtn
-                @click.stop="dialog.show()"
-                color="primary"
-                fab
-                icon="add"
-                v-shortcut="'+'"
-            >
+            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Add new device')"
diff --git a/src/pages/Worker/Card/WorkerPit.vue b/src/pages/Worker/Card/WorkerPit.vue
index 40e814452..79cf1a04f 100644
--- a/src/pages/Worker/Card/WorkerPit.vue
+++ b/src/pages/Worker/Card/WorkerPit.vue
@@ -221,7 +221,7 @@ const deleteRelative = async (id) => {
                                 color="primary"
                                 flat
                                 icon="add"
-                                v-shortcut="'+'"
+                                shortcut="+"
                                 style="flex: 0"
                                 data-cy="addRelative"
                             />
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 78c5dfd82..992f6ec71 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -9,7 +9,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
-import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
 
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index 7def6e94c..c580e5202 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -64,17 +64,17 @@ const selectedCalendarDates = ref([]);
 // Date formateada para bindear al componente QDate
 const selectedDateFormatted = ref(toDateString(defaultDate.value));
 
-const arrayData = useArrayData('Worker');
+const arrayData = useArrayData('workerData');
 const acl = useAcl();
 const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear());
 const worker = computed(() => arrayData.store?.data);
 const canSend = computed(() =>
-    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]),
+    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }])
 );
 const canUpdate = computed(() =>
     acl.hasAny([
         { model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' },
-    ]),
+    ])
 );
 const isHimself = computed(() => user.value.id === Number(route.params.id));
 
@@ -100,7 +100,7 @@ const getHeaderFormattedDate = (date) => {
 };
 
 const formattedWeekTotalHours = computed(() =>
-    secondsToHoursMinutes(weekTotalHours.value),
+    secondsToHoursMinutes(weekTotalHours.value)
 );
 
 const onInputChange = async (date) => {
@@ -320,7 +320,7 @@ const getFinishTime = () => {
     today.setHours(0, 0, 0, 0);
 
     let todayInWeek = weekDays.value.find(
-        (day) => day.dated.getTime() === today.getTime(),
+        (day) => day.dated.getTime() === today.getTime()
     );
 
     if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
@@ -472,7 +472,7 @@ onMounted(async () => {
                         openConfirmationModal(
                             t('Send time control email'),
                             t('Are you sure you want to send it?'),
-                            resendEmail,
+                            resendEmail
                         )
                     "
                 >
@@ -561,7 +561,7 @@ onMounted(async () => {
                                 @show-worker-time-form="
                                     showWorkerTimeForm(
                                         { id: hour.id, entryCode: hour.direction },
-                                        'edit',
+                                        'edit'
                                     )
                                 "
                                 class="hour-chip"
@@ -577,7 +577,7 @@ onMounted(async () => {
                             </span>
                             <QBtn
                                 icon="add_circle"
-                                v-shortcut="'+'"
+                                shortcut="+"
                                 flat
                                 color="primary"
                                 class="fill-icon cursor-pointer"
diff --git a/src/pages/Worker/WorkerDepartmentTree.vue b/src/pages/Worker/WorkerDepartmentTree.vue
index 9baf5ee57..9abf4e312 100644
--- a/src/pages/Worker/WorkerDepartmentTree.vue
+++ b/src/pages/Worker/WorkerDepartmentTree.vue
@@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useState } from 'src/composables/useState';
 import { useQuasar } from 'quasar';
-import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
 import CreateDepartmentChild from './CreateDepartmentChild.vue';
 import axios from 'axios';
 import { useRouter } from 'vue-router';
@@ -173,7 +173,7 @@ function handleEvent(type, event, node) {
                             color="primary"
                             flat
                             icon="add"
-                            v-shortcut="'+'"
+                            shortcut="+"
                             class="cursor-pointer"
                             @click.stop="showCreateNodeForm(node.id)"
                         >
diff --git a/src/pages/Zone/Card/ZoneBasicData.vue b/src/pages/Zone/Card/ZoneBasicData.vue
index 03013f011..cbeeff2e9 100644
--- a/src/pages/Zone/Card/ZoneBasicData.vue
+++ b/src/pages/Zone/Card/ZoneBasicData.vue
@@ -1,7 +1,5 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
-import { ref } from 'vue';
-import FetchData from 'components/FetchData.vue';
 import FormModel from 'src/components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
@@ -9,23 +7,10 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
 const { t } = useI18n();
-const validAddresses = ref([]);
-const addresses = ref([]);
-
-const setFilteredAddresses = (data) => {
-    const validIds = new Set(validAddresses.value.map((item) => item.addressFk));
-    addresses.value = data.filter((address) => validIds.has(address.id));
-};
 </script>
 
 <template>
-    <FetchData
-        url="RoadmapAddresses"
-        auto-load
-        @on-fetch="(data) => (validAddresses = data)"
-    />
-    <FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
-    <FormModel auto-load model="Zone">
+    <FormModel :url="`Zones/${$route.params.id}`" auto-load model="zone">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
@@ -33,15 +18,15 @@ const setFilteredAddresses = (data) => {
                     :label="t('Name')"
                     clearable
                     v-model="data.name"
-                    :required="true"
                 />
             </VnRow>
+
             <VnRow>
                 <VnSelect
                     v-model="data.agencyModeFk"
                     :rules="validate('zone.agencyModeFk')"
-                    url="AgencyModes/isActive"
-                    :fields="['id', 'name']"
+                     url="AgencyModes/isActive"
+                     :fields="['id', 'name']"
                     :label="t('Agency')"
                     emit-value
                     map-options
@@ -84,7 +69,7 @@ const setFilteredAddresses = (data) => {
                     type="number"
                     min="0"
                 />
-                <VnInputTime v-model="data.hour" :label="t('Closing')" :required="true" />
+                <VnInputTime v-model="data.hour" :label="t('Closing')" />
             </VnRow>
 
             <VnRow>
@@ -93,7 +78,7 @@ const setFilteredAddresses = (data) => {
                     :label="t('Price')"
                     type="number"
                     min="0"
-                    :required="true"
+                    required="true"
                     clearable
                 />
                 <VnInput
@@ -101,7 +86,7 @@ const setFilteredAddresses = (data) => {
                     :label="t('Price optimum')"
                     type="number"
                     min="0"
-                    :required="true"
+                    required="true"
                     clearable
                 />
             </VnRow>
@@ -118,14 +103,12 @@ const setFilteredAddresses = (data) => {
                     v-model="data.addressFk"
                     option-value="id"
                     option-label="nickname"
-                    :options="addresses"
+                    url="Addresses"
                     :fields="['id', 'nickname']"
                     sort-by="id"
                     hide-selected
                     map-options
                     :rules="validate('data.addressFk')"
-                    :filter-options="['id']"
-                    :where="filterWhere"
                 />
             </VnRow>
             <VnRow>
diff --git a/src/pages/Zone/Card/ZoneCard.vue b/src/pages/Zone/Card/ZoneCard.vue
index 41daff5c0..a470cd5bd 100644
--- a/src/pages/Zone/Card/ZoneCard.vue
+++ b/src/pages/Zone/Card/ZoneCard.vue
@@ -1,12 +1,13 @@
 <script setup>
+import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import { computed } from 'vue';
 
 import VnCard from 'components/common/VnCard.vue';
 import ZoneDescriptor from './ZoneDescriptor.vue';
 import ZoneFilterPanel from '../ZoneFilterPanel.vue';
-import filter from './ZoneFilter.js';
 
+const { t } = useI18n();
 const route = useRoute();
 const routeName = computed(() => route.name);
 
@@ -18,16 +19,15 @@ function notIsLocations(ifIsFalse, ifIsTrue) {
 
 <template>
     <VnCard
-        data-key="Zone"
-        :url="notIsLocations('Zones', undefined)"
+        data-key="zone"
+        :base-url="notIsLocations('Zones', undefined)"
         :descriptor="ZoneDescriptor"
-        :filter="filter"
         :filter-panel="notIsLocations(ZoneFilterPanel, undefined)"
         :search-data-key="notIsLocations('ZoneList', undefined)"
         :searchbar-props="{
             url: notIsLocations('Zones', 'ZoneLocations'),
-            label: notIsLocations($t('list.searchZone'), $t('list.searchLocation')),
-            info: $t('list.searchInfo'),
+            label: notIsLocations(t('list.searchZone'), t('list.searchLocation')),
+            info: t('list.searchInfo'),
             whereFilter: notIsLocations((value) => {
                 return /^\d+$/.test(value)
                     ? { id: value }
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index 27676212e..8355c219e 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -1,14 +1,15 @@
 <script setup>
-import { computed } from 'vue';
+import { ref, computed } 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 { toTimeFormat } from 'src/filters/date';
 import { toCurrency } from 'filters/index';
 
+import useCardDescription from 'src/composables/useCardDescription';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
-import filter from './ZoneFilter.js';
 
 const $props = defineProps({
     id: {
@@ -19,22 +20,49 @@ const $props = defineProps({
 });
 
 const route = useRoute();
+const { t } = useI18n();
+
+const filter = {
+    include: [
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['name', 'id'],
+            },
+        },
+    ],
+};
+
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
+
+const data = ref(useCardDescription());
+const setData = (entity) => {
+    data.value = useCardDescription(entity.ref, entity.id);
+};
 </script>
 
 <template>
-    <CardDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
+    <CardDescriptor
+        module="Zone"
+        :url="`Zones/${entityId}`"
+        :title="data.title"
+        :subtitle="data.subtitle"
+        :filter="filter"
+        @on-fetch="setData"
+        data-key="zoneData"
+    >
         <template #menu="{ entity }">
             <ZoneDescriptorMenuItems :zone="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="$t('list.agency')" :value="entity.agencyMode?.name" />
-            <VnLv :label="$t('zone.closing')" :value="toTimeFormat(entity.hour)" />
-            <VnLv :label="$t('zone.travelingDays')" :value="entity.travelingDays" />
-            <VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
-            <VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
+            <VnLv :label="t('list.agency')" :value="entity.agencyMode.name" />
+            <VnLv :label="t('zone.closing')" :value="toTimeFormat(entity.hour)" />
+            <VnLv :label="t('zone.travelingDays')" :value="entity.travelingDays" />
+            <VnLv :label="t('list.price')" :value="toCurrency(entity.price)" />
+            <VnLv :label="t('zone.bonus')" :value="toCurrency(entity.bonus)" />
         </template>
     </CardDescriptor>
 </template>
+
diff --git a/src/pages/Zone/Card/ZoneEvents.vue b/src/pages/Zone/Card/ZoneEvents.vue
index 1e6debd25..a5806bab9 100644
--- a/src/pages/Zone/Card/ZoneEvents.vue
+++ b/src/pages/Zone/Card/ZoneEvents.vue
@@ -78,13 +78,13 @@ const onZoneEventFormClose = () => {
                         {
                             isNewMode: true,
                         },
-                        true,
+                        true
                     )
                 "
                 color="primary"
                 fab
                 icon="add"
-                v-shortcut="'+'"
+                shortcut="+"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('eventsInclusionForm.addEvent') }}
diff --git a/src/pages/Zone/Card/ZoneFilter.js b/src/pages/Zone/Card/ZoneFilter.js
deleted file mode 100644
index 3298c7c8a..000000000
--- a/src/pages/Zone/Card/ZoneFilter.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export default {
-    include: [
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['name', 'id'],
-            },
-        },
-    ],
-};
diff --git a/src/pages/Zone/Card/ZoneSearchbar.vue b/src/pages/Zone/Card/ZoneSearchbar.vue
index d1188a1e8..f7a59e97f 100644
--- a/src/pages/Zone/Card/ZoneSearchbar.vue
+++ b/src/pages/Zone/Card/ZoneSearchbar.vue
@@ -22,50 +22,15 @@ const exprBuilder = (param, value) => {
             return /^\d+$/.test(value) ? { id: value } : { name: { like: `%${value}%` } };
     }
 };
-
-const tableFilter = {
-    include: [
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'address',
-            scope: {
-                fields: ['id', 'nickname', 'provinceFk', 'postalCode'],
-                include: [
-                    {
-                        relation: 'province',
-                        scope: {
-                            fields: ['id', 'name'],
-                        },
-                    },
-                    {
-                        relation: 'postcode',
-                        scope: {
-                            fields: ['code', 'townFk'],
-                            include: {
-                                relation: 'town',
-                                scope: {
-                                    fields: ['id', 'name'],
-                                },
-                            },
-                        },
-                    },
-                ],
-            },
-        },
-    ],
-};
 </script>
 
 <template>
     <VnSearchbar
         data-key="ZonesList"
         url="Zones"
-        :filter="tableFilter"
+        :filter="{
+            include: { relation: 'agencyMode', scope: { fields: ['name'] } },
+        }"
         :expr-builder="exprBuilder"
         :label="t('list.searchZone')"
         :info="t('list.searchInfo')"
diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
index 5b29b495b..124802633 100644
--- a/src/pages/Zone/Card/ZoneSummary.vue
+++ b/src/pages/Zone/Card/ZoneSummary.vue
@@ -11,7 +11,6 @@ import { getUrl } from 'src/composables/getUrl';
 import { toCurrency } from 'filters/index';
 import { toTimeFormat } from 'src/filters/date';
 import axios from 'axios';
-import filter from './ZoneFilter.js';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
 
 const route = useRoute();
@@ -27,6 +26,19 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const zoneUrl = ref();
 
+const filter = computed(() => {
+    const filter = {
+        include: {
+            relation: 'agencyMode',
+            fields: ['name'],
+        },
+        where: {
+            id: entityId,
+        },
+    };
+    return filter;
+});
+
 const columns = computed(() => [
     {
         label: t('list.name'),
@@ -60,9 +72,9 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="Zone"
+        data-key="ZoneSummary"
         ref="summary"
-        :url="`Zones/${entityId}`"
+        url="Zones/findOne"
         :filter="filter"
     >
         <template #header="{ entity }">
diff --git a/src/pages/Zone/Card/ZoneWarehouses.vue b/src/pages/Zone/Card/ZoneWarehouses.vue
index 165e9c840..c96735697 100644
--- a/src/pages/Zone/Card/ZoneWarehouses.vue
+++ b/src/pages/Zone/Card/ZoneWarehouses.vue
@@ -109,7 +109,7 @@ const openCreateWarehouseForm = () => createWarehouseDialogRef.value.show();
                 icon="add"
                 color="primary"
                 @click="openCreateWarehouseForm()"
-                v-shortcut="'+'"
+                shortcut="+"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Zone/Delivery/ZoneDeliveryList.vue b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
index e3ec8cb2d..975cbdb67 100644
--- a/src/pages/Zone/Delivery/ZoneDeliveryList.vue
+++ b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
+            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
index 7b5c2ddbc..5a7f0bb4c 100644
--- a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
+++ b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
+            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/pages/Zone/ZoneList.vue b/src/pages/Zone/ZoneList.vue
index 4df84e4bd..e4a1774fe 100644
--- a/src/pages/Zone/ZoneList.vue
+++ b/src/pages/Zone/ZoneList.vue
@@ -4,7 +4,7 @@ import { useRouter } from 'vue-router';
 import { computed, ref } from 'vue';
 import axios from 'axios';
 
-import { dashIfEmpty, toCurrency } from 'src/filters';
+import { toCurrency } from 'src/filters';
 import { toTimeFormat } from 'src/filters/date';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import useNotify from 'src/composables/useNotify.js';
@@ -17,6 +17,7 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 import ZoneFilterPanel from './ZoneFilterPanel.vue';
 import ZoneSearchbar from './Card/ZoneSearchbar.vue';
+import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const router = useRouter();
@@ -25,6 +26,7 @@ const { viewSummary } = useSummaryDialog();
 const { openConfirmationModal } = useVnConfirm();
 const tableRef = ref();
 const warehouseOptions = ref([]);
+const validAddresses = ref([]);
 
 const tableFilter = {
     include: [
@@ -129,7 +131,6 @@ const columns = computed(() => [
         label: t('list.addressFk'),
         cardVisible: true,
         columnFilter: false,
-        columnClass: 'expand',
     },
     {
         align: 'right',
@@ -160,18 +161,30 @@ const handleClone = (id) => {
     openConfirmationModal(
         t('list.confirmCloneTitle'),
         t('list.confirmCloneSubtitle'),
-        () => clone(id),
+        () => clone(id)
     );
 };
 
-function formatRow(row) {
-    if (!row?.address) return '-';
-    return dashIfEmpty(`${row?.address?.nickname},
-            ${row?.address?.postcode?.town?.name} (${row?.address?.province?.name})`);
+function showValidAddresses(row) {
+    if (row.addressFk) {
+        const isValid = validAddresses.value.some(
+            (address) => address.addressFk === row.addressFk
+        );
+        if (isValid)
+            return `${row.address?.nickname},
+            ${row.address?.postcode?.town?.name} (${row.address?.province?.name})`;
+        else return '-';
+    }
+    return '-';
 }
 </script>
 
 <template>
+    <FetchData
+        url="RoadmapAddresses"
+        auto-load
+        @on-fetch="(data) => (validAddresses = data)"
+    />
     <ZoneSearchbar />
     <RightMenu>
         <template #right-panel>
@@ -194,7 +207,7 @@ function formatRow(row) {
         :right-search="false"
     >
         <template #column-addressFk="{ row }">
-            {{ dashIfEmpty(formatRow(row)) }}
+            {{ showValidAddresses(row) }}
         </template>
         <template #more-create-dialog="{ data }">
             <VnSelect
diff --git a/src/router/modules/account/aliasCard.js b/src/router/modules/account/aliasCard.js
index a5b00f44b..cbbd31e51 100644
--- a/src/router/modules/account/aliasCard.js
+++ b/src/router/modules/account/aliasCard.js
@@ -3,7 +3,7 @@ export default {
     path: ':id',
     component: () => import('src/pages/Account/Alias/Card/AliasCard.vue'),
     redirect: { name: 'AliasSummary' },
-    meta: { moduleName: 'Alias', menu: ['AliasBasicData', 'AliasUsers'] },
+    meta: { menu: ['AliasBasicData', 'AliasUsers'] },
     children: [
         {
             name: 'AliasSummary',
diff --git a/src/router/modules/account/roleCard.js b/src/router/modules/account/roleCard.js
index f8100071f..c36ce71b9 100644
--- a/src/router/modules/account/roleCard.js
+++ b/src/router/modules/account/roleCard.js
@@ -4,7 +4,6 @@ export default {
     component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
     redirect: { name: 'RoleSummary' },
     meta: {
-        moduleName: 'Role',
         menu: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
     },
     children: [
diff --git a/src/router/modules/entry.js b/src/router/modules/entry.js
index b5656dc5f..f362c7653 100644
--- a/src/router/modules/entry.js
+++ b/src/router/modules/entry.js
@@ -6,7 +6,13 @@ const entryCard = {
     component: () => import('src/pages/Entry/Card/EntryCard.vue'),
     redirect: { name: 'EntrySummary' },
     meta: {
-        menu: ['EntryBasicData', 'EntryBuys', 'EntryNotes', 'EntryDms', 'EntryLog'],
+        menu: [
+            'EntryBasicData',
+            'EntryBuys',
+            'EntryNotes',
+            'EntryDms',
+            'EntryLog',
+        ],
     },
     children: [
         {
@@ -85,7 +91,7 @@ export default {
             'EntryLatestBuys',
             'EntryStockBought',
             'EntryWasteRecalc',
-        ],
+        ]
     },
     component: RouterView,
     redirect: { name: 'EntryMain' },
@@ -97,7 +103,7 @@ export default {
             redirect: { name: 'EntryIndexMain' },
             children: [
                 {
-                    path: '',
+                    path:'',
                     name: 'EntryIndexMain',
                     redirect: { name: 'EntryList' },
                     component: () => import('src/pages/Entry/EntryList.vue'),
@@ -109,7 +115,6 @@ export default {
                                 title: 'list',
                                 icon: 'view_list',
                             },
-                            component: () => import('src/pages/Entry/EntryList.vue'),
                         },
                         entryCard,
                     ],
@@ -122,7 +127,7 @@ export default {
                         icon: 'add',
                     },
                     component: () => import('src/pages/Entry/EntryCreate.vue'),
-                },
+                },                
                 {
                     path: 'my',
                     name: 'MyEntries',
@@ -162,4 +167,4 @@ export default {
             ],
         },
     ],
-};
+};
\ No newline at end of file
diff --git a/src/router/modules/route.js b/src/router/modules/route.js
index 835324d20..946ad3e15 100644
--- a/src/router/modules/route.js
+++ b/src/router/modules/route.js
@@ -160,36 +160,6 @@ const roadmapCard = {
     ],
 };
 
-const vehicleCard = {
-    path: ':id',
-    name: 'VehicleCard',
-    component: () => import('src/pages/Route/Vehicle/Card/VehicleCard.vue'),
-    redirect: { name: 'VehicleSummary' },
-    meta: {
-        menu: ['VehicleBasicData'],
-    },
-    children: [
-        {
-            name: 'VehicleSummary',
-            path: 'summary',
-            meta: {
-                title: 'summary',
-                icon: 'view_list',
-            },
-            component: () => import('src/pages/Route/Vehicle/Card/VehicleSummary.vue'),
-        },
-        {
-            name: 'VehicleBasicData',
-            path: 'basic-data',
-            meta: {
-                title: 'basicData',
-                icon: 'vn:settings',
-            },
-            component: () => import('src/pages/Route/Vehicle/Card/VehicleBasicData.vue'),
-        },
-    ],
-};
-
 export default {
     name: 'Route',
     path: '/route',
@@ -204,7 +174,6 @@ export default {
             'RouteRoadmap',
             'CmrList',
             'AgencyList',
-            'VehicleList',
         ],
     },
     component: RouterView,
@@ -311,27 +280,6 @@ export default {
                         agencyCard,
                     ],
                 },
-                {
-                    path: 'vehicle',
-                    name: 'RouteVehicle',
-                    redirect: { name: 'VehicleList' },
-                    meta: {
-                        title: 'vehicle',
-                        icon: 'directions_car',
-                    },
-                    component: () => import('src/pages/Route/Vehicle/VehicleList.vue'),
-                    children: [
-                        {
-                            path: 'list',
-                            name: 'VehicleList',
-                            meta: {
-                                title: 'vehicleList',
-                                icon: 'directions_car',
-                            },
-                        },
-                        vehicleCard,
-                    ],
-                },
             ],
         },
     ],
diff --git a/src/router/modules/shelving.js b/src/router/modules/shelving.js
index c085dd8dc..55fb04278 100644
--- a/src/router/modules/shelving.js
+++ b/src/router/modules/shelving.js
@@ -3,7 +3,7 @@ import { RouterView } from 'vue-router';
 const parkingCard = {
     name: 'ParkingCard',
     path: ':id',
-    component: () => import('src/pages/Shelving/Parking/Card/ParkingCard.vue'),
+    component: () => import('src/pages/Parking/Card/ParkingCard.vue'),
     redirect: { name: 'ParkingSummary' },
     meta: {
         menu: ['ParkingBasicData', 'ParkingLog'],
@@ -16,7 +16,7 @@ const parkingCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () => import('src/pages/Shelving/Parking/Card/ParkingSummary.vue'),
+            component: () => import('src/pages/Parking/Card/ParkingSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -25,8 +25,7 @@ const parkingCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () =>
-                import('src/pages/Shelving/Parking/Card/ParkingBasicData.vue'),
+            component: () => import('src/pages/Parking/Card/ParkingBasicData.vue'),
         },
         {
             path: 'log',
@@ -35,7 +34,7 @@ const parkingCard = {
                 title: 'log',
                 icon: 'history',
             },
-            component: () => import('src/pages/Shelving/Parking/Card/ParkingLog.vue'),
+            component: () => import('src/pages/Parking/Card/ParkingLog.vue'),
         },
     ],
 };
@@ -128,7 +127,7 @@ export default {
                         title: 'parkingList',
                         icon: 'view_list',
                     },
-                    component: () => import('src/pages/Shelving/Parking/ParkingList.vue'),
+                    component: () => import('src/pages/Parking/ParkingList.vue'),
                     children: [
                         {
                             path: 'list',
diff --git a/src/router/modules/supplier.js b/src/router/modules/supplier.js
index 19763cdf3..4ece4c784 100644
--- a/src/router/modules/supplier.js
+++ b/src/router/modules/supplier.js
@@ -1,12 +1,19 @@
 import { RouterView } from 'vue-router';
 
-const supplierCard = {
-    name: 'SupplierCard',
-    path: ':id',
-    component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
-    redirect: { name: 'SupplierSummary' },
+export default {
+    path: '/supplier',
+    name: 'Supplier',
     meta: {
-        menu: [
+        title: 'suppliers',
+        icon: 'vn:supplier',
+        moduleName: 'Supplier',
+        keyBinding: 'p',
+    },
+    component: RouterView,
+    redirect: { name: 'SupplierMain' },
+    menus: {
+        main: ['SupplierList'],
+        card: [
             'SupplierBasicData',
             'SupplierFiscalData',
             'SupplierBillingData',
@@ -20,165 +27,21 @@ const supplierCard = {
             'SupplierDms',
         ],
     },
-    children: [
-        {
-            name: 'SupplierSummary',
-            path: 'summary',
-            meta: {
-                title: 'summary',
-                icon: 'launch',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierSummary.vue'),
-        },
-        {
-            path: 'basic-data',
-            name: 'SupplierBasicData',
-            meta: {
-                title: 'basicData',
-                icon: 'vn:settings',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierBasicData.vue'),
-        },
-        {
-            path: 'fiscal-data',
-            name: 'SupplierFiscalData',
-            meta: {
-                title: 'fiscalData',
-                icon: 'vn:dfiscales',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
-        },
-        {
-            path: 'billing-data',
-            name: 'SupplierBillingData',
-            meta: {
-                title: 'billingData',
-                icon: 'vn:payment',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierBillingData.vue'),
-        },
-        {
-            path: 'log',
-            name: 'SupplierLog',
-            meta: {
-                title: 'log',
-                icon: 'vn:History',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
-        },
-        {
-            path: 'account',
-            name: 'SupplierAccounts',
-            meta: {
-                title: 'accounts',
-                icon: 'vn:credit',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierAccounts.vue'),
-        },
-        {
-            path: 'contact',
-            name: 'SupplierContacts',
-            meta: {
-                title: 'contacts',
-                icon: 'contact_phone',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierContacts.vue'),
-        },
-        {
-            path: 'address',
-            name: 'SupplierAddresses',
-            meta: {
-                title: 'addresses',
-                icon: 'vn:delivery',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierAddresses.vue'),
-        },
-        {
-            path: 'address/create',
-            name: 'SupplierAddressesCreate',
-            component: () =>
-                import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
-        },
-        {
-            path: 'balance',
-            name: 'SupplierBalance',
-            meta: {
-                title: 'balance',
-                icon: 'balance',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierBalance.vue'),
-        },
-        {
-            path: 'consumption',
-            name: 'SupplierConsumption',
-            meta: {
-                title: 'consumption',
-                icon: 'show_chart',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierConsumption.vue'),
-        },
-        {
-            path: 'agency-term',
-            name: 'SupplierAgencyTerm',
-            meta: {
-                title: 'agencyTerm',
-                icon: 'vn:agency-term',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
-        },
-        {
-            path: 'dms',
-            name: 'SupplierDms',
-            meta: {
-                title: 'dms',
-                icon: 'smb_share',
-            },
-            component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
-        },
-        {
-            path: 'agency-term/create',
-            name: 'SupplierAgencyTermCreate',
-            component: () =>
-                import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
-        },
-    ],
-};
-
-export default {
-    name: 'Supplier',
-    path: '/supplier',
-    meta: {
-        title: 'suppliers',
-        icon: 'vn:supplier',
-        moduleName: 'Supplier',
-        keyBinding: 'p',
-        menu: ['SupplierList'],
-    },
-    component: RouterView,
-    redirect: { name: 'SupplierMain' },
     children: [
         {
             path: '',
             name: 'SupplierMain',
             component: () => import('src/components/common/VnModule.vue'),
-            redirect: { name: 'SupplierIndexMain' },
+            redirect: { name: 'SupplierList' },
             children: [
                 {
-                    path: '',
-                    name: 'SupplierIndexMain',
-                    redirect: { name: 'SupplierList' },
+                    path: 'list',
+                    name: 'SupplierList',
+                    meta: {
+                        title: 'list',
+                        icon: 'view_list',
+                    },
                     component: () => import('src/pages/Supplier/SupplierList.vue'),
-                    children: [
-                        {
-                            path: 'list',
-                            name: 'SupplierList',
-                            meta: {
-                                title: 'list',
-                                icon: 'view_list',
-                            },
-                        },
-                        supplierCard,
-                    ],
                 },
                 {
                     path: 'create',
@@ -191,5 +54,143 @@ export default {
                 },
             ],
         },
+        {
+            name: 'SupplierCard',
+            path: ':id',
+            component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
+            redirect: { name: 'SupplierSummary' },
+            children: [
+                {
+                    name: 'SupplierSummary',
+                    path: 'summary',
+                    meta: {
+                        title: 'summary',
+                        icon: 'launch',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierSummary.vue'),
+                },
+                {
+                    path: 'basic-data',
+                    name: 'SupplierBasicData',
+                    meta: {
+                        title: 'basicData',
+                        icon: 'vn:settings',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierBasicData.vue'),
+                },
+                {
+                    path: 'fiscal-data',
+                    name: 'SupplierFiscalData',
+                    meta: {
+                        title: 'fiscalData',
+                        icon: 'vn:dfiscales',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
+                },
+                {
+                    path: 'billing-data',
+                    name: 'SupplierBillingData',
+                    meta: {
+                        title: 'billingData',
+                        icon: 'vn:payment',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierBillingData.vue'),
+                },
+                {
+                    path: 'log',
+                    name: 'SupplierLog',
+                    meta: {
+                        title: 'log',
+                        icon: 'vn:History',
+                    },
+                    component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
+                },
+                {
+                    path: 'account',
+                    name: 'SupplierAccounts',
+                    meta: {
+                        title: 'accounts',
+                        icon: 'vn:credit',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierAccounts.vue'),
+                },
+                {
+                    path: 'contact',
+                    name: 'SupplierContacts',
+                    meta: {
+                        title: 'contacts',
+                        icon: 'contact_phone',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierContacts.vue'),
+                },
+                {
+                    path: 'address',
+                    name: 'SupplierAddresses',
+                    meta: {
+                        title: 'addresses',
+                        icon: 'vn:delivery',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierAddresses.vue'),
+                },
+                {
+                    path: 'address/create',
+                    name: 'SupplierAddressesCreate',
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
+                },
+                {
+                    path: 'balance',
+                    name: 'SupplierBalance',
+                    meta: {
+                        title: 'balance',
+                        icon: 'balance',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierBalance.vue'),
+                },
+                {
+                    path: 'consumption',
+                    name: 'SupplierConsumption',
+                    meta: {
+                        title: 'consumption',
+                        icon: 'show_chart',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierConsumption.vue'),
+                },
+                {
+                    path: 'agency-term',
+                    name: 'SupplierAgencyTerm',
+                    meta: {
+                        title: 'agencyTerm',
+                        icon: 'vn:agency-term',
+                    },
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
+                },
+                {
+                    path: 'dms',
+                    name: 'SupplierDms',
+                    meta: {
+                        title: 'dms',
+                        icon: 'smb_share',
+                    },
+                    component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
+                },
+                {
+                    path: 'agency-term/create',
+                    name: 'SupplierAgencyTermCreate',
+                    component: () =>
+                        import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
+                },
+            ],
+        },
     ],
 };
diff --git a/src/router/modules/ticket.js b/src/router/modules/ticket.js
index bfcb78787..e5b423f64 100644
--- a/src/router/modules/ticket.js
+++ b/src/router/modules/ticket.js
@@ -192,13 +192,7 @@ export default {
         icon: 'vn:ticket',
         moduleName: 'Ticket',
         keyBinding: 't',
-        menu: [
-            'TicketList',
-            'TicketAdvance',
-            'TicketWeekly',
-            'TicketFuture',
-            'TicketNegative',
-        ],
+        menu: ['TicketList', 'TicketAdvance', 'TicketWeekly', 'TicketFuture'],
     },
     component: RouterView,
     redirect: { name: 'TicketMain' },
@@ -235,32 +229,6 @@ export default {
                     },
                     component: () => import('src/pages/Ticket/TicketCreate.vue'),
                 },
-                {
-                    path: 'negative',
-                    redirect: { name: 'TicketNegative' },
-                    children: [
-                        {
-                            name: 'TicketNegative',
-                            meta: {
-                                title: 'negative',
-                                icon: 'exposure',
-                            },
-                            component: () =>
-                                import('src/pages/Ticket/Negative/TicketLackList.vue'),
-                            path: '',
-                        },
-                        {
-                            name: 'NegativeDetail',
-                            path: ':id',
-                            meta: {
-                                title: 'summary',
-                                icon: 'launch',
-                            },
-                            component: () =>
-                                import('src/pages/Ticket/Negative/TicketLackDetail.vue'),
-                        },
-                    ],
-                },
                 {
                     path: 'weekly',
                     name: 'TicketWeekly',
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index 3eb95a96e..1d013c596 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -201,10 +201,9 @@ const workerCard = {
 const departmentCard = {
     name: 'DepartmentCard',
     path: ':id',
-    component: () => import('src/pages/Worker/Department/Card/DepartmentCard.vue'),
+    component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
     redirect: { name: 'DepartmentSummary' },
     meta: {
-        moduleName: 'Department',
         menu: ['DepartmentBasicData'],
     },
     children: [
@@ -215,8 +214,7 @@ const departmentCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () =>
-                import('src/pages/Worker/Department/Card/DepartmentSummary.vue'),
+            component: () => import('src/pages/Department/Card/DepartmentSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -225,8 +223,7 @@ const departmentCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () =>
-                import('src/pages/Worker/Department/Card/DepartmentBasicData.vue'),
+            component: () => import('src/pages/Department/Card/DepartmentBasicData.vue'),
         },
     ],
 };
diff --git a/src/stores/__tests__/useNavigationStore.spec.js b/src/stores/__tests__/useNavigationStore.spec.js
deleted file mode 100644
index c5df6157e..000000000
--- a/src/stores/__tests__/useNavigationStore.spec.js
+++ /dev/null
@@ -1,153 +0,0 @@
-import { setActivePinia, createPinia } from 'pinia';
-import { describe, beforeEach, afterEach, it, expect, vi, beforeAll } from 'vitest';
-import { useNavigationStore } from '../useNavigationStore';
-import axios from 'axios';
-
-let store;
-
-vi.mock('src/router/modules', () => [
-    { name: 'Item', meta: {} },
-    { name: 'Shelving', meta: {} },
-    { name: 'Order', meta: {} },
-]);
-
-vi.mock('src/filters', () => ({
-    toLowerCamel: vi.fn((name) => name.toLowerCase()),
-}));
-
-const modulesMock = [
-    {
-        name: 'Item',
-        children: null,
-        title: 'globals.pageTitles.undefined',
-        icon: undefined,
-        module: 'item',
-        isPinned: true,
-    },
-    {
-        name: 'Shelving',
-        children: null,
-        title: 'globals.pageTitles.undefined',
-        icon: undefined,
-        module: 'shelving',
-        isPinned: false,
-    },
-    {
-        name: 'Order',
-        children: null,
-        title: 'globals.pageTitles.undefined',
-        icon: undefined,
-        module: 'order',
-        isPinned: false,
-    },
-];
-
-const pinnedModulesMock = [
-    {
-        name: 'Item',
-        children: null,
-        title: 'globals.pageTitles.undefined',
-        icon: undefined,
-        module: 'item',
-        isPinned: true,
-    },
-];
-
-describe('useNavigationStore', () => {
-    beforeEach(() => {
-        setActivePinia(createPinia());
-        vi.spyOn(axios, 'get').mockResolvedValue({ data: true });
-        store = useNavigationStore();
-        store.getModules = vi.fn().mockReturnValue({
-            value: modulesMock,
-        });
-        store.getPinnedModules = vi.fn().mockReturnValue({
-            value: pinnedModulesMock,
-        });
-    });
-    afterEach(() => {
-        vi.clearAllMocks();
-    });
-
-    it('should return modules with correct structure', () => {
-        const store = useNavigationStore();
-        const modules = store.getModules();
-
-        expect(modules.value).toEqual(modulesMock);
-    });
-
-    it('should return pinned modules', () => {
-        const store = useNavigationStore();
-        const pinnedModules = store.getPinnedModules();
-
-        expect(pinnedModules.value).toEqual(pinnedModulesMock);
-    });
-
-    it('should toggle pinned modules', () => {
-        const store = useNavigationStore();
-
-        store.togglePinned('item');
-        store.togglePinned('shelving');
-        expect(store.pinnedModules).toEqual(['item', 'shelving']);
-
-        store.togglePinned('item');
-        expect(store.pinnedModules).toEqual(['shelving']);
-    });
-
-    it('should fetch pinned modules', async () => {
-        vi.spyOn(axios, 'get').mockResolvedValue({
-            data: [{ id: 1, workerFk: 9, moduleFk: 'order', position: 1 }],
-        });
-        const store = useNavigationStore();
-        await store.fetchPinned();
-
-        expect(store.pinnedModules).toEqual(['order']);
-    });
-
-    it('should add menu item correctly', () => {
-        const store = useNavigationStore();
-        const module = 'customer';
-        const parent = [];
-        const route = {
-            name: 'customer',
-            title: 'Customer',
-            icon: 'customer',
-            meta: {
-                keyBinding: 'ctrl+shift+c',
-                name: 'customer',
-                title: 'Customer',
-                icon: 'customer',
-                menu: 'customer',
-                menuChildren: [{ name: 'customer', title: 'Customer', icon: 'customer' }],
-            },
-        };
-
-        const result = store.addMenuItem(module, route, parent);
-        const expectedItem = {
-            children: [
-                {
-                    icon: 'customer',
-                    name: 'customer',
-                    title: 'globals.pageTitles.Customer',
-                },
-            ],
-            icon: 'customer',
-            keyBinding: 'ctrl+shift+c',
-            name: 'customer',
-            title: 'globals.pageTitles.Customer',
-        };
-        expect(result).toEqual(expectedItem);
-        expect(parent.length).toBe(1);
-        expect(parent).toEqual([expectedItem]);
-    });
-
-    it('should not add menu item if condition is not met', () => {
-        const store = useNavigationStore();
-        const module = 'testModule';
-        const route = { meta: { hidden: true, menuchildren: {} } };
-        const parent = [];
-        const result = store.addMenuItem(module, route, parent);
-        expect(result).toBeUndefined();
-        expect(parent.length).toBe(0);
-    });
-});
diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js
index b3996d1e3..8d62fdb4a 100644
--- a/src/stores/useArrayDataStore.js
+++ b/src/stores/useArrayDataStore.js
@@ -19,7 +19,6 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
         page: 1,
         mapKey: 'id',
         keepData: false,
-        oneRecord: false,
     };
 
     function get(key) {
diff --git a/src/utils/notifyResults.js b/src/utils/notifyResults.js
deleted file mode 100644
index e87ad6c6f..000000000
--- a/src/utils/notifyResults.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Notify } from 'quasar';
-
-export default function (results, key) {
-    results.forEach((result, index) => {
-        if (result.status === 'fulfilled') {
-            const data = JSON.parse(result.value.config.data);
-            Notify.create({
-                type: 'positive',
-                message: `Operación (${index + 1}) ${data[key]} completada con éxito.`,
-            });
-        } else {
-            const data = JSON.parse(result.reason.config.data);
-            Notify.create({
-                type: 'negative',
-                message: `Operación (${index + 1}) ${data[key]} fallida: ${result.reason.message}`,
-            });
-        }
-    });
-}
diff --git a/test/cypress/integration/Order/orderCatalog.spec.js b/test/cypress/integration/Order/orderCatalog.spec.js
index 1770a6b56..cffc47f91 100644
--- a/test/cypress/integration/Order/orderCatalog.spec.js
+++ b/test/cypress/integration/Order/orderCatalog.spec.js
@@ -45,6 +45,7 @@ describe('OrderCatalog', () => {
         ).type('{enter}');
         cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
         cy.dataCy('catalogFilterValueDialogBtn').last().click();
+        cy.get('[data-cy="catalogFilterValueDialogTagSelect"]').click();
         cy.selectOption("[data-cy='catalogFilterValueDialogTagSelect']", 'Tallos');
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').focus();
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').type('2');
diff --git a/test/cypress/integration/entry/entryList.spec.js b/test/cypress/integration/entry/entryList.spec.js
deleted file mode 100644
index 4f99f0cb6..000000000
--- a/test/cypress/integration/entry/entryList.spec.js
+++ /dev/null
@@ -1,224 +0,0 @@
-describe('Entry', () => {
-    beforeEach(() => {
-        cy.viewport(1920, 1080);
-        cy.login('buyer');
-        cy.visit(`/#/entry/list`);
-    });
-
-    it('Filter deleted entries and other fields', () => {
-        createEntry();
-        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
-        cy.waitForElement('[data-cy="entry-buys"]');
-        deleteEntry();
-        cy.typeSearchbar('{enter}');
-        cy.get('span[title="Date"]').click().click();
-        cy.typeSearchbar('{enter}');
-        cy.url().should('include', 'order');
-        cy.get('td[data-row-index="0"][data-col-field="landed"]').should(
-            'have.text',
-            '-',
-        );
-    });
-
-    it('Create entry, modify travel and add buys', () => {
-        createEntryAndBuy();
-        cy.get('a[data-cy="EntryBasicData-menu-item"]').click();
-        selectTravel('two');
-        cy.saveCard();
-        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
-        deleteEntry();
-    });
-
-    it('Clone entry and recalculate rates', () => {
-        createEntry();
-
-        cy.waitForElement('[data-cy="entry-buys"]');
-
-        cy.url().then((previousUrl) => {
-            cy.get('[data-cy="descriptor-more-opts"]').click();
-            cy.get('div[data-cy="clone-entry"]').should('be.visible').click();
-
-            cy.get('.q-notification__message').eq(1).should('have.text', 'Entry cloned');
-
-            cy.url()
-                .should('not.eq', previousUrl)
-                .then(() => {
-                    cy.waitForElement('[data-cy="entry-buys"]');
-
-                    cy.get('[data-cy="descriptor-more-opts"]').click();
-                    cy.get('div[data-cy="recalculate-rates"]').click();
-
-                    cy.get('.q-notification__message')
-                        .eq(2)
-                        .should('have.text', 'Entry prices recalculated');
-
-                    cy.get('[data-cy="descriptor-more-opts"]').click();
-                    deleteEntry();
-
-                    cy.log(previousUrl);
-
-                    cy.visit(previousUrl);
-
-                    cy.waitForElement('[data-cy="entry-buys"]');
-                    deleteEntry();
-                });
-        });
-    });
-
-    it('Should notify when entry is lock by another user', () => {
-        const checkLockMessage = () => {
-            cy.get('[data-cy="entry-lock-confirm"]').should('be.visible');
-            cy.get('[data-cy="VnConfirm_message"] > span').should(
-                'contain.text',
-                'This entry has been locked by buyerNick',
-            );
-        };
-
-        createEntry();
-        goToEntryBuys();
-        cy.get('.q-notification__message')
-            .eq(1)
-            .should('have.text', 'The entry has been locked successfully');
-
-        cy.login('logistic');
-        cy.reload();
-        checkLockMessage();
-        cy.get('[data-cy="VnConfirm_cancel"]').click();
-        cy.url().should('include', 'summary');
-
-        goToEntryBuys();
-        checkLockMessage();
-        cy.get('[data-cy="VnConfirm_confirm"]').click();
-        cy.url().should('include', 'buys');
-
-        deleteEntry();
-    });
-
-    it('Edit buys and use toolbar actions', () => {
-        const COLORS = {
-            negative: 'rgb(251, 82, 82)',
-            positive: 'rgb(200, 228, 132)',
-            enabled: 'rgb(255, 255, 255)',
-            disable: 'rgb(168, 168, 168)',
-        };
-
-        const selectCell = (field, row = 0) =>
-            cy.get(`td[data-col-field="${field}"][data-row-index="${row}"]`);
-        const selectSpan = (field, row = 0) => selectCell(field, row).find('div > span');
-        const selectButton = (cySelector) => cy.get(`button[data-cy="${cySelector}"]`);
-        const clickAndType = (field, value, row = 0) => {
-            selectCell(field, row).click().type(`${value}{esc}`);
-        };
-        const checkText = (field, expectedText, row = 0) =>
-            selectCell(field, row).should('have.text', expectedText);
-        const checkColor = (field, expectedColor, row = 0) =>
-            selectSpan(field, row).should('have.css', 'color', expectedColor);
-
-        createEntryAndBuy();
-
-        selectCell('isIgnored').click().click().type('{esc}');
-        checkText('isIgnored', 'close');
-
-        clickAndType('stickers', '1');
-        checkText('stickers', '0/01');
-        checkText('quantity', '1');
-        checkText('amount', '50.00');
-        clickAndType('packing', '2');
-        checkText('packing', '12');
-        checkText('weight', '12.0');
-        checkText('quantity', '12');
-        checkText('amount', '600.00');
-        checkColor('packing', COLORS.enabled);
-
-        selectCell('groupingMode').click().click().click();
-        checkColor('packing', COLORS.disable);
-        checkColor('grouping', COLORS.enabled);
-
-        selectCell('buyingValue').click().clear().type('{backspace}{backspace}1');
-        checkText('amount', '12.00');
-        checkColor('minPrice', COLORS.disable);
-
-        selectCell('hasMinPrice').click().click();
-        checkColor('minPrice', COLORS.enabled);
-        selectCell('hasMinPrice').click();
-
-        cy.saveCard();
-        cy.get('span[data-cy="footer-stickers"]').should('have.text', '1');
-        cy.get('.q-notification__message').contains('Data saved');
-
-        selectButton('change-quantity-sign').should('be.disabled');
-        selectButton('check-buy-amount').should('be.disabled');
-        cy.get('tr.cursor-pointer > .q-table--col-auto-width > .q-checkbox').click();
-        selectButton('change-quantity-sign').should('be.enabled');
-        selectButton('check-buy-amount').should('be.enabled');
-
-        selectButton('change-quantity-sign').click();
-        selectButton('set-negative-quantity').click();
-        checkText('quantity', '-12');
-        selectButton('set-positive-quantity').click();
-        checkText('quantity', '12');
-        checkColor('amount', COLORS.disable);
-
-        selectButton('check-buy-amount').click();
-        selectButton('uncheck-amount').click();
-        checkColor('amount', COLORS.disable);
-
-        selectButton('check-amount').click();
-        checkColor('amount', COLORS.positive);
-        cy.saveCard();
-
-        cy.get('span[data-cy="footer-amount"]').should(
-            'have.css',
-            'color',
-            COLORS.positive,
-        );
-
-        deleteEntry();
-    });
-
-    function goToEntryBuys() {
-        const entryBuySelector = 'a[data-cy="EntryBuys-menu-item"]';
-        cy.get(entryBuySelector).should('be.visible');
-        cy.waitForElement('[data-cy="entry-buys"]');
-        cy.get(entryBuySelector).click();
-    }
-
-    function deleteEntry() {
-        cy.get('[data-cy="descriptor-more-opts"]').click();
-        cy.waitForElement('div[data-cy="delete-entry"]');
-        cy.get('div[data-cy="delete-entry"]').should('be.visible').click();
-        cy.url().should('include', 'list');
-    }
-
-    function createEntryAndBuy() {
-        createEntry();
-        createBuy();
-    }
-
-    function createEntry() {
-        cy.get('button[data-cy="vnTableCreateBtn"]').click();
-        selectTravel('one');
-        cy.get('button[data-cy="FormModelPopup_save"]').click();
-        cy.url().should('include', 'summary');
-        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
-    }
-
-    function selectTravel(warehouse) {
-        cy.get('i[data-cy="Travel_icon"]').click();
-        cy.get('input[data-cy="Warehouse Out_select"]').type(warehouse);
-        cy.get('div[role="listbox"] > div > div[role="option"]').eq(0).click();
-        cy.get('button[data-cy="save-filter-travel-form"]').click();
-        cy.get('tr').eq(1).click();
-    }
-
-    function createBuy() {
-        cy.get('a[data-cy="EntryBuys-menu-item"]').click();
-        cy.get('a[data-cy="EntryBuys-menu-item"]').click();
-        cy.get('button[data-cy="vnTableCreateBtn"]').click();
-
-        cy.get('input[data-cy="itemFk-create-popup"]').type('1');
-        cy.get('div[role="listbox"] > div > div[role="option"]').eq(0).click();
-        cy.get('input[data-cy="Grouping mode_select"]').should('have.value', 'packing');
-        cy.get('button[data-cy="FormModelPopup_save"]').click();
-    }
-});
diff --git a/test/cypress/integration/entry/stockBought.spec.js b/test/cypress/integration/entry/stockBought.spec.js
index bc36156b4..078ad19cc 100644
--- a/test/cypress/integration/entry/stockBought.spec.js
+++ b/test/cypress/integration/entry/stockBought.spec.js
@@ -6,7 +6,6 @@ describe('EntryStockBought', () => {
     });
     it('Should edit the reserved space', () => {
         cy.get('.q-field__native.q-placeholder').should('have.value', '01/01/2001');
-        cy.get('[data-col-field="reserve"][data-row-index="0"]').click();
         cy.get('input[name="reserve"]').type('10{enter}');
         cy.get('button[title="Save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data saved');
@@ -16,35 +15,25 @@ describe('EntryStockBought', () => {
         cy.get('input[aria-label="Reserve"]').type('1');
         cy.get('input[aria-label="Date"]').eq(1).clear();
         cy.get('input[aria-label="Date"]').eq(1).type('01-01');
-        cy.get('input[aria-label="Buyer"]').type('buyerBossNick');
-        cy.get('div[role="listbox"] > div > div[role="option"]')
-            .eq(0)
-            .should('be.visible')
-            .click();
-
-        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.get('input[aria-label="Buyer"]').type('buyerboss{downarrow}{enter}');
         cy.get('.q-notification__message').should('have.text', 'Data created');
-
-        cy.get('[data-col-field="reserve"][data-row-index="1"]').click().clear();
-        cy.get('[data-cy="searchBtn"]').eq(1).click();
-        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata')
-            .should('have.text', 'warningNo data available')
-            .type('{esc}');
-        cy.get('[data-col-field="reserve"][data-row-index="1"]')
-            .click()
-            .type('{backspace}{enter}');
-        cy.get('[data-cy="crudModelDefaultSaveBtn"]').should('be.enabled').click();
-        cy.get('.q-notification__message').eq(1).should('have.text', 'Data saved');
     });
     it('Should check detail for the buyer', () => {
-        cy.get('[data-cy="searchBtn"]').eq(0).click();
+        cy.get(':nth-child(1) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
         cy.get('tBody > tr').eq(1).its('length').should('eq', 1);
     });
-
+    it('Should check detail for the buyerBoss and had no content', () => {
+        cy.get(':nth-child(2) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
+        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata').should(
+            'have.text',
+            'warningNo data available'
+        );
+    });
     it('Should edit travel m3 and refresh', () => {
-        cy.get('[data-cy="edit-travel"]').should('be.visible').click();
-        cy.get('input[aria-label="m3"]').clear().type('60');
-        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.get('.vn-row > div > .q-btn > .q-btn__content > .q-icon').click();
+        cy.get('input[aria-label="m3"]').clear();
+        cy.get('input[aria-label="m3"]').type('60');
+        cy.get('.q-mt-lg > .q-btn--standard > .q-btn__content > .block').click();
         cy.get('.vn-row > div > :nth-child(2)').should('have.text', '60');
     });
 });
diff --git a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
index 11ca1bb59..2016fca6d 100644
--- a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
@@ -1,9 +1,9 @@
 /// <reference types="cypress" />
 describe('InvoiceInBasicData', () => {
+    const formInputs = '.q-form > .q-card input';
     const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
+    const documentBtns = '[data-cy="dms-buttons"] button';
     const dialogInputs = '.q-dialog input';
-    const resetBtn = '.q-btn-group--push > .q-btn--flat';
-    const getDocumentBtns = (opt) => `[data-cy="dms-buttons"]  > :nth-child(${opt})`;
 
     beforeEach(() => {
         cy.login('developer');
@@ -11,16 +11,13 @@ describe('InvoiceInBasicData', () => {
     });
 
     it('should edit the provideer and supplier ref', () => {
-        cy.dataCy('UnDeductibleVatSelect').type('4751000000');
-        cy.get('.q-menu .q-item').contains('4751000000').click();
-        cy.get(resetBtn).click();
-
-        cy.waitForElement('#formModel').within(() => {
-            cy.dataCy('vnSupplierSelect').type('Bros nick');
-        })
-        cy.get('.q-menu .q-item').contains('Bros nick').click();
+        cy.selectOption(firstFormSelect, 'Bros');
+        cy.get('[title="Reset"]').click();
+        cy.get(formInputs).eq(1).type('{selectall}4739');
         cy.saveCard();
-        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Bros nick');
+
+        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Plants nick');
+        cy.get(formInputs).eq(1).invoke('val').should('eq', '4739');
     });
 
     it('should edit, remove and create the dms data', () => {
@@ -28,18 +25,18 @@ describe('InvoiceInBasicData', () => {
         const secondInput = "I don't know what posting here!";
 
         //edit
-        cy.get(getDocumentBtns(2)).click();
+        cy.get(documentBtns).eq(1).click();
         cy.get(dialogInputs).eq(0).type(`{selectall}${firtsInput}`);
         cy.get('textarea').type(`{selectall}${secondInput}`);
         cy.get('[data-cy="FormModelPopup_save"]').click();
-        cy.get(getDocumentBtns(2)).click();
+        cy.get(documentBtns).eq(1).click();
         cy.get(dialogInputs).eq(0).invoke('val').should('eq', firtsInput);
         cy.get('textarea').invoke('val').should('eq', secondInput);
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
 
         //remove
-        cy.get(getDocumentBtns(3)).click();
+        cy.get(documentBtns).eq(2).click();
         cy.get('[data-cy="VnConfirm_confirm"]').click();
         cy.checkNotification('Data saved');
 
@@ -49,7 +46,7 @@ describe('InvoiceInBasicData', () => {
             'test/cypress/fixtures/image.jpg',
             {
                 force: true,
-            },
+            }
         );
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
diff --git a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
index 1e7ce1003..f8b403a45 100644
--- a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
@@ -36,7 +36,7 @@ describe('InvoiceInVat', () => {
         cy.get(dialogInputs).eq(0).type(randomInt);
         cy.get(dialogInputs).eq(1).type('This is a dummy expense');
 
-        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.get('button[type="submit"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data created');
     });
 });
diff --git a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
index 02b7fbb43..5f629df0b 100644
--- a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
+++ b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
@@ -7,7 +7,9 @@ describe('InvoiceOut negative bases', () => {
     });
 
     it('should filter and download as CSV', () => {
-        cy.get('input[name="ticketFk"]').type('23{enter}');
+        cy.get(
+            ':nth-child(7) > .full-width > :nth-child(1) > .column > div.q-px-xs > .q-field > .q-field__inner > .q-field__control'
+        ).type('23{enter}');
         cy.get('#subToolbar > .q-btn').click();
         cy.checkNotification('CSV downloaded successfully');
     });
diff --git a/test/cypress/integration/item/ItemProposal.spec.js b/test/cypress/integration/item/ItemProposal.spec.js
deleted file mode 100644
index b3ba9f676..000000000
--- a/test/cypress/integration/item/ItemProposal.spec.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/// <reference types="cypress" />
-describe('ItemProposal', () => {
-    beforeEach(() => {
-        const ticketId = 1;
-
-        cy.login('developer');
-        cy.visit(`/#/ticket/${ticketId}/summary`);
-    });
-
-    describe('Handle item proposal selected', () => {});
-});
diff --git a/test/cypress/integration/item/itemTag.spec.js b/test/cypress/integration/item/itemTag.spec.js
index 425eaffe6..17423bc51 100644
--- a/test/cypress/integration/item/itemTag.spec.js
+++ b/test/cypress/integration/item/itemTag.spec.js
@@ -16,7 +16,10 @@ describe('Item tag', () => {
         cy.dataCy(newTag).should('be.visible').click().type('Genero{enter}');
         cy.dataCy('tagGeneroValue').eq(1).should('be.visible');
         cy.dataCy(saveBtn).click();
-        cy.checkNotification("The tag or priority can't be repeated for an item");
+        cy.get('.q-notification__message').should(
+            'have.text',
+            "The tag or priority can't be repeated for an item",
+        );
     });
 
     it('should add a new tag', () => {
diff --git a/test/cypress/integration/parking/parkingBasicData.spec.js b/test/cypress/integration/parking/parkingBasicData.spec.js
index f64f23ec8..0d130d335 100644
--- a/test/cypress/integration/parking/parkingBasicData.spec.js
+++ b/test/cypress/integration/parking/parkingBasicData.spec.js
@@ -13,11 +13,11 @@ describe('ParkingBasicData', () => {
         cy.get(sectorOpt).click();
 
         cy.get(codeInput).eq(0).clear();
-        cy.get(codeInput).eq(0).type('900-001');
+        cy.get(codeInput).eq(0).type(123);
 
         cy.saveCard();
 
         cy.get(sectorSelect).should('have.value', 'Second sector');
-        cy.get(codeInput).should('have.value', '900-001');
+        cy.get(codeInput).should('have.value', 123);
     });
 });
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 82ec6626d..e28caea7c 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -15,7 +15,6 @@ describe('AgencyWorkCenter', () => {
 
         // expect error when duplicate
         cy.get(createButton).click();
-        cy.selectOption(workCenterCombobox, 'workCenterOne');
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('This workCenter is already assigned to this agency');
         cy.get('[data-cy="FormModelPopup_cancel"]').click();
diff --git a/test/cypress/integration/route/routeList.spec.js b/test/cypress/integration/route/routeList.spec.js
index 976ce7352..4da43ce8e 100644
--- a/test/cypress/integration/route/routeList.spec.js
+++ b/test/cypress/integration/route/routeList.spec.js
@@ -4,6 +4,9 @@ describe('Route', () => {
         cy.login('developer');
         cy.visit(`/#/route/extended-list`);
     });
+    const getVnSelect =
+        '> :nth-child(1) > .column > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
+    const getRowColumn = (row, column) => `:nth-child(${row}) > :nth-child(${column})`;
 
     it('Route list create route', () => {
         cy.addBtnClick();
@@ -14,23 +17,15 @@ describe('Route', () => {
 
     it('Route list search and edit', () => {
         cy.get('#searchbar input').type('{enter}');
-        cy.get('[data-col-field="description"][data-row-index="0"]')
-            .click()
-            .type('routeTestOne{enter}');
+        cy.get('input[name="description"]').type('routeTestOne{enter}');
         cy.get('.q-table tr')
             .its('length')
             .then((rowCount) => {
                 expect(rowCount).to.be.greaterThan(0);
             });
-        cy.get('[data-col-field="workerFk"][data-row-index="0"]')
-            .click()
-            .type('{downArrow}{enter}');
-        cy.get('[data-col-field="agencyModeFk"][data-row-index="0"]')
-            .click()
-            .type('{downArrow}{enter}');
-        cy.get('[data-col-field="vehicleFk"][data-row-index="0"]')
-            .click()
-            .type('{downArrow}{enter}');
+        cy.get(getRowColumn(1, 3) + getVnSelect).type('{downArrow}{enter}');
+        cy.get(getRowColumn(1, 4) + getVnSelect).type('{downArrow}{enter}');
+        cy.get(getRowColumn(1, 5) + getVnSelect).type('{downArrow}{enter}');
         cy.get('button[title="Save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data saved');
     });
diff --git a/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
deleted file mode 100644
index 64b9ca0a0..000000000
--- a/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
+++ /dev/null
@@ -1,13 +0,0 @@
-describe('Vehicle', () => {
-    beforeEach(() => {
-        cy.viewport(1920, 1080);
-        cy.login('deliveryAssistant');
-        cy.visit(`/#/route/vehicle/7`);
-    });
-
-    it('should delete a vehicle', () => {
-        cy.openActionsDescriptor();
-        cy.get('[data-cy="delete"]').click();
-        cy.checkNotification('Vehicle removed');
-    });
-});
diff --git a/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js b/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
deleted file mode 100644
index 9ea1cff63..000000000
--- a/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/// <reference types="cypress" />
-describe('Ticket Lack detail', () => {
-    beforeEach(() => {
-        cy.login('developer');
-        cy.intercept('GET', /\/api\/Tickets\/itemLack\/5.*$/, {
-            statusCode: 200,
-            body: [
-                {
-                    saleFk: 33,
-                    code: 'OK',
-                    ticketFk: 142,
-                    nickname: 'Malibu Point',
-                    shipped: '2000-12-31T23:00:00.000Z',
-                    hour: 0,
-                    quantity: 50,
-                    agName: 'Super-Man delivery',
-                    alertLevel: 0,
-                    stateName: 'OK',
-                    stateId: 3,
-                    itemFk: 5,
-                    price: 1.79,
-                    alertLevelCode: 'FREE',
-                    zoneFk: 9,
-                    zoneName: 'Zone superMan',
-                    theoreticalhour: '2011-11-01T22:59:00.000Z',
-                    isRookie: 1,
-                    turno: 1,
-                    peticionCompra: 1,
-                    hasObservation: 1,
-                    hasToIgnore: 1,
-                    isBasket: 1,
-                    minTimed: 0,
-                    customerId: 1104,
-                    customerName: 'Tony Stark',
-                    observationTypeCode: 'administrative',
-                },
-            ],
-        }).as('getItemLack');
-
-        cy.visit('/#/ticket/negative/5');
-        cy.wait('@getItemLack');
-    });
-    describe('Table actions', () => {
-        it.skip('should display only one row in the lack list', () => {
-            cy.location('href').should('contain', '#/ticket/negative/5');
-
-            cy.get('[data-cy="changeItem"]').should('be.disabled');
-            cy.get('[data-cy="changeState"]').should('be.disabled');
-            cy.get('[data-cy="changeQuantity"]').should('be.disabled');
-            cy.get('[data-cy="itemProposal"]').should('be.disabled');
-            cy.get('[data-cy="transferLines"]').should('be.disabled');
-            cy.get('tr.cursor-pointer > :nth-child(1)').click();
-            cy.get('[data-cy="changeItem"]').should('be.enabled');
-            cy.get('[data-cy="changeState"]').should('be.enabled');
-            cy.get('[data-cy="changeQuantity"]').should('be.enabled');
-            cy.get('[data-cy="itemProposal"]').should('be.enabled');
-            cy.get('[data-cy="transferLines"]').should('be.enabled');
-        });
-    });
-    describe('Item proposal', () => {
-        beforeEach(() => {
-            cy.get('tr.cursor-pointer > :nth-child(1)').click();
-
-            cy.intercept('GET', /\/api\/Items\/getSimilar\?.*$/, {
-                statusCode: 200,
-                body: [
-                    {
-                        id: 1,
-                        longName: 'Ranged weapon longbow 50cm',
-                        subName: 'Stark Industries',
-                        tag5: 'Color',
-                        value5: 'Brown',
-                        match5: 0,
-                        match6: 0,
-                        match7: 0,
-                        match8: 1,
-                        tag6: 'Categoria',
-                        value6: '+1 precission',
-                        tag7: 'Tallos',
-                        value7: '1',
-                        tag8: null,
-                        value8: null,
-                        available: 20,
-                        calc_id: 6,
-                        counter: 0,
-                        minQuantity: 1,
-                        visible: null,
-                        price2: 1,
-                    },
-                    {
-                        id: 2,
-                        longName: 'Ranged weapon longbow 100cm',
-                        subName: 'Stark Industries',
-                        tag5: 'Color',
-                        value5: 'Brown',
-                        match5: 0,
-                        match6: 1,
-                        match7: 0,
-                        match8: 1,
-                        tag6: 'Categoria',
-                        value6: '+1 precission',
-                        tag7: 'Tallos',
-                        value7: '1',
-                        tag8: null,
-                        value8: null,
-                        available: 50,
-                        calc_id: 6,
-                        counter: 1,
-                        minQuantity: 5,
-                        visible: null,
-                        price2: 10,
-                    },
-                    {
-                        id: 3,
-                        longName: 'Ranged weapon longbow 200cm',
-                        subName: 'Stark Industries',
-                        tag5: 'Color',
-                        value5: 'Brown',
-                        match5: 1,
-                        match6: 1,
-                        match7: 1,
-                        match8: 1,
-                        tag6: 'Categoria',
-                        value6: '+1 precission',
-                        tag7: 'Tallos',
-                        value7: '1',
-                        tag8: null,
-                        value8: null,
-                        available: 185,
-                        calc_id: 6,
-                        counter: 10,
-                        minQuantity: 10,
-                        visible: null,
-                        price2: 100,
-                    },
-                ],
-            }).as('getItemGetSimilar');
-            cy.get('[data-cy="itemProposal"]').click();
-            cy.wait('@getItemGetSimilar');
-        });
-        describe('Replace item if', () => {
-            it.only('Quantity is less than available', () => {
-                cy.get(':nth-child(1) > .text-right  > .q-btn').click();
-            });
-        });
-    });
-});
diff --git a/test/cypress/integration/ticket/negative/TicketLackList.spec.js b/test/cypress/integration/ticket/negative/TicketLackList.spec.js
deleted file mode 100644
index 01ab4f621..000000000
--- a/test/cypress/integration/ticket/negative/TicketLackList.spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/// <reference types="cypress" />
-describe('Ticket Lack list', () => {
-    beforeEach(() => {
-        cy.login('developer');
-        cy.intercept('GET', /Tickets\/itemLack\?.*$/, {
-            statusCode: 200,
-            body: [
-                {
-                    itemFk: 5,
-                    longName: 'Ranged weapon pistol 9mm',
-                    warehouseFk: 1,
-                    producer: null,
-                    size: 15,
-                    category: null,
-                    warehouse: 'Warehouse One',
-                    lack: -50,
-                    inkFk: 'SLV',
-                    timed: '2025-01-25T22:59:00.000Z',
-                    minTimed: '23:59',
-                    originFk: 'Holand',
-                },
-            ],
-        }).as('getLack');
-
-        cy.visit('/#/ticket/negative');
-    });
-
-    describe('Table actions', () => {
-        it('should display only one row in the lack list', () => {
-            cy.wait('@getLack', { timeout: 10000 });
-
-            cy.get('.q-virtual-scroll__content > :nth-child(1) > .sticky').click();
-            cy.location('href').should('contain', '#/ticket/negative/5');
-        });
-    });
-});
diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js
index 593021e6e..2984a4ee4 100644
--- a/test/cypress/integration/ticket/ticketList.spec.js
+++ b/test/cypress/integration/ticket/ticketList.spec.js
@@ -53,29 +53,4 @@ describe('TicketList', () => {
         cy.checkNotification('Data created');
         cy.url().should('match', /\/ticket\/\d+\/summary/);
     });
-
-    it('should show the corerct problems', () => {
-        cy.intercept('GET', '**/api/Tickets/filter*', (req) => {
-            req.headers['cache-control'] = 'no-cache';
-            req.headers['pragma'] = 'no-cache';
-            req.headers['expires'] = '0';
-
-            req.on('response', (res) => {
-                delete res.headers['if-none-match'];
-                delete res.headers['if-modified-since'];
-            });
-        }).as('ticket');
-
-        cy.get('[data-cy="Warehouse_select"]').type('Warehouse Five');
-        cy.get('.q-menu .q-item').contains('Warehouse Five').click();
-        cy.wait('@ticket').then((interception) => {
-            const data = interception.response.body[1];
-            expect(data.hasComponentLack).to.equal(1);
-            expect(data.isTooLittle).to.equal(1);
-            expect(data.hasItemShortage).to.equal(1);
-        });
-        cy.get('.icon-components').should('exist');
-        cy.get('.icon-unavailable').should('exist');
-        cy.get('.icon-isTooLittle').should('exist');
-    });
 });
diff --git a/test/cypress/integration/vnComponent/VnShortcut.spec.js b/test/cypress/integration/vnComponent/VnShortcut.spec.js
index e08c44635..b49b4e964 100644
--- a/test/cypress/integration/vnComponent/VnShortcut.spec.js
+++ b/test/cypress/integration/vnComponent/VnShortcut.spec.js
@@ -28,17 +28,6 @@ describe('VnShortcuts', () => {
             });
 
             cy.url().should('include', module);
-            if (['monitor', 'claim'].includes(module)) {
-                return;
-            }
-            cy.waitForElement('.q-page').should('exist');
-            cy.dataCy('vnTableCreateBtn').should('exist');
-            cy.get('.q-page').trigger('keydown', {
-                ctrlKey: true,
-                altKey: true,
-                key: '+',
-            });
-            cy.get('#formModel').should('exist');
         });
     }
 });
diff --git a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
index 2cd43984a..343c1c127 100644
--- a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
+++ b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
@@ -9,7 +9,7 @@ describe('WagonTypeCreate', () => {
     it('should create a new wagon type and then delete it', () => {
         cy.get('.q-page-sticky > div > .q-btn').click();
         cy.get('input').first().type('Example for testing');
-        cy.get('[data-cy="FormModelPopup_save"]').click();
+        cy.get('button[type="submit"]').click();
         cy.get('[title="Remove"] > .q-btn__content > .q-icon').first().click();
     });
 });
diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js
index 70ded3f79..95a075fb3 100644
--- a/test/cypress/integration/zone/zoneBasicData.spec.js
+++ b/test/cypress/integration/zone/zoneBasicData.spec.js
@@ -1,6 +1,5 @@
 describe('ZoneBasicData', () => {
     const priceBasicData = '[data-cy="Price_input"]';
-    const saveBtn = '.q-btn-group > .q-btn--standard';
 
     beforeEach(() => {
         cy.viewport(1280, 720);
@@ -9,27 +8,20 @@ describe('ZoneBasicData', () => {
     });
 
     it('should throw an error if the name is empty', () => {
-        cy.intercept('GET', /\/api\/Zones\/4./).as('zone');
-
-        cy.wait('@zone').then(() => {
-            cy.get('[data-cy="zone-basic-data-name"] input').type(
-                '{selectall}{backspace}',
-            );
-        });
-
-        cy.get(saveBtn).click();
+        cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
+        cy.get('.q-btn-group > .q-btn--standard').click();
         cy.checkNotification("can't be blank");
     });
 
     it('should throw an error if the price is empty', () => {
         cy.get(priceBasicData).clear();
-        cy.get(saveBtn).click();
+        cy.get('.q-btn-group > .q-btn--standard').click();
         cy.checkNotification('cannot be blank');
     });
 
     it("should edit the basicData's zone", () => {
         cy.get('.q-card > :nth-child(1)').type(' modified');
-        cy.get(saveBtn).click();
+        cy.get('.q-btn-group > .q-btn--standard').click();
         cy.checkNotification('Data saved');
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index aa4a1219e..2c93fbf84 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -87,55 +87,36 @@ Cypress.Commands.add('getValue', (selector) => {
 });
 
 // Fill Inputs
-Cypress.Commands.add('selectOption', (selector, option, timeout = 2500) => {
+Cypress.Commands.add('selectOption', (selector, option, timeout = 5000) => {
     cy.waitForElement(selector, timeout);
-
-    cy.get(selector, { timeout })
-        .should('exist')
-        .should('be.visible')
-        .click()
-        .then(($el) => {
-            cy.wrap($el.is('input') ? $el : $el.find('input'))
-                .invoke('attr', 'aria-controls')
-                .then((ariaControl) => selectItem(selector, option, ariaControl));
+    cy.get(selector).click();
+    cy.get(selector).invoke('data', 'url').as('dataUrl');
+    cy.get(selector)
+        .clear()
+        .type(option)
+        .then(() => {
+            cy.get('.q-menu', { timeout })
+                .should('be.visible') // Asegurarse de que el menú está visible
+                .and('exist') // Verificar que el menú existe
+                .then(() => {
+                    cy.get('@dataUrl').then((url) => {
+                        if (url) {
+                            // Esperar a que el menú no esté visible (desaparezca)
+                            cy.get('.q-menu').should('not.be.visible');
+                            // Ahora esperar a que el menú vuelva a aparecer
+                            cy.get('.q-menu').should('be.visible').and('exist');
+                        }
+                    });
+                });
         });
+
+    // Finalmente, seleccionar la opción deseada
+    cy.get('.q-menu:visible') // Asegurarse de que estamos dentro del menú visible
+        .find('.q-item') // Encontrar los elementos de las opciones
+        .contains(option) // Verificar que existe una opción que contenga el texto deseado
+        .click(); // Hacer clic en la opción
 });
 
-function selectItem(selector, option, ariaControl, hasWrite = true) {
-    if (!hasWrite) cy.wait(100);
-
-    getItems(ariaControl).then((items) => {
-        const matchingItem = items
-            .toArray()
-            .find((item) => item.innerText.includes(option));
-        if (matchingItem) return cy.wrap(matchingItem).click();
-
-        if (hasWrite) cy.get(selector).clear().type(option, { delay: 0 });
-        return selectItem(selector, option, ariaControl, false);
-    });
-}
-
-function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) {
-    // Se intenta obtener la lista de opciones del desplegable de manera recursiva
-    return cy
-        .get('#' + ariaControl, { timeout })
-        .should('exist')
-        .find('.q-item')
-        .should('exist')
-        .then(($items) => {
-            if (!$items?.length || $items.first().text().trim() === '') {
-                if (Cypress._.now() - startTime > timeout) {
-                    throw new Error(
-                        `getItems: Tiempo de espera (${timeout}ms) excedido.`,
-                    );
-                }
-                return getItems(ariaControl, startTime, timeout);
-            }
-
-            return cy.wrap($items);
-        });
-}
-
 Cypress.Commands.add('countSelectOptions', (selector, option) => {
     cy.waitForElement(selector);
     cy.get(selector).click({ force: true });
diff --git a/test/cypress/support/waitUntil.js b/test/cypress/support/waitUntil.js
index 359f8643f..5fb47a2d8 100644
--- a/test/cypress/support/waitUntil.js
+++ b/test/cypress/support/waitUntil.js
@@ -1,7 +1,7 @@
 const waitUntil = (subject, checkFunction, originalOptions = {}) => {
     if (!(checkFunction instanceof Function)) {
         throw new Error(
-            '`checkFunction` parameter should be a function. Found: ' + checkFunction,
+            '`checkFunction` parameter should be a function. Found: ' + checkFunction
         );
     }
 

From 2655e0a8e595eafeea219d30452c95f0fbd9e1f5 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 22:46:27 +0100
Subject: [PATCH 22/28] fix: mana axios deacoplate

---
 src/pages/Ticket/Card/TicketEditMana.vue      | 65 +++++++++++--------
 src/pages/Ticket/Card/TicketSale.vue          | 21 ------
 .../Ticket/Card/TicketSaleMoreActions.vue     |  5 --
 3 files changed, 37 insertions(+), 54 deletions(-)

diff --git a/src/pages/Ticket/Card/TicketEditMana.vue b/src/pages/Ticket/Card/TicketEditMana.vue
index c1bc2639b..ff40a6592 100644
--- a/src/pages/Ticket/Card/TicketEditMana.vue
+++ b/src/pages/Ticket/Card/TicketEditMana.vue
@@ -1,32 +1,26 @@
 <script setup>
-import { ref } from 'vue';
+import axios from 'axios';
 import { useI18n } from 'vue-i18n';
+import { computed, ref } from 'vue';
+import { useRoute } from 'vue-router';
 import { toCurrency } from 'src/filters';
 import VnUsesMana from 'components/ui/VnUsesMana.vue';
 
 const $props = defineProps({
-    mana: {
-        type: Number,
-        default: null,
-    },
     newPrice: {
         type: Number,
         default: 0,
     },
-    usesMana: {
-        type: Boolean,
-        default: false,
-    },
-    manaCode: {
-        type: String,
-        default: 'mana',
-    },
     sale: {
         type: Object,
         default: null,
     },
 });
 
+const route = useRoute();
+const mana = ref(null);
+const usesMana = ref(false);
+
 const emit = defineEmits(['save', 'cancel']);
 
 const { t } = useI18n();
@@ -38,32 +32,47 @@ const save = (sale = $props.sale) => {
     QPopupProxyRef.value.hide();
 };
 
+const getMana = async () => {
+    const { data } = await axios.get(`Tickets/${route.params.id}/getSalesPersonMana`);
+    mana.value = data;
+    await getUsesMana();
+};
+
+const getUsesMana = async () => {
+    const { data } = await axios.get('Sales/usesMana');
+    usesMana.value = data;
+};
+
 const cancel = () => {
     emit('cancel');
     QPopupProxyRef.value.hide();
 };
+const hasMana = computed(() => typeof mana.value === 'number');
 defineExpose({ save });
 </script>
 
 <template>
-    <QPopupProxy ref="QPopupProxyRef" data-cy="ticketEditManaProxy">
+    <QPopupProxy
+        ref="QPopupProxyRef"
+        @before-show="getMana"
+        data-cy="ticketEditManaProxy"
+    >
         <div class="container">
-            <QSpinner v-if="typeof mana === 'number' && mana" color="primary" size="md" />
-            <div v-else>
-                <div class="header">Mana: {{ toCurrency(mana) }}</div>
-                <div class="q-pa-md">
-                    <slot :popup="QPopupProxyRef" />
-                    <div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
-                        <VnUsesMana :mana-code="manaCode" />
-                    </div>
-                    <div v-if="newPrice" class="column items-center q-mt-lg">
-                        <span class="text-primary">{{ t('New price') }}</span>
-                        <span class="text-subtitle1">
-                            {{ toCurrency($props.newPrice) }}
-                        </span>
-                    </div>
+            <div class="header">Mana: {{ toCurrency(mana) }}</div>
+            <QSpinner v-if="!hasMana" color="primary" size="md" />
+            <div class="q-pa-md" v-else>
+                <slot :popup="QPopupProxyRef" />
+                <div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
+                    <VnUsesMana :mana-code="manaCode" />
+                </div>
+                <div v-if="newPrice" class="column items-center q-mt-lg">
+                    <span class="text-primary">{{ t('New price') }}</span>
+                    <span class="text-subtitle1">
+                        {{ toCurrency($props.newPrice) }}
+                    </span>
                 </div>
             </div>
+
             <div class="row">
                 <QBtn
                     color="primary"
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index f5fb50ecf..076e06dea 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -44,7 +44,6 @@ const isTicketEditable = ref(false);
 const sales = ref([]);
 const editableStatesOptions = ref([]);
 const selectedSales = ref([]);
-const mana = ref(null);
 const manaCode = ref('mana');
 const ticketState = computed(() => store.data?.ticketState?.state?.code);
 const transfer = ref({
@@ -258,18 +257,6 @@ const DEFAULT_EDIT = {
     oldQuantity: null,
 };
 const edit = ref({ ...DEFAULT_EDIT });
-const usesMana = ref(null);
-
-const getUsesMana = async () => {
-    const { data } = await axios.get('Sales/usesMana');
-    usesMana.value = data;
-};
-
-const getMana = async () => {
-    const { data } = await axios.get(`Tickets/${route.params.id}/getSalesPersonMana`);
-    mana.value = data;
-    await getUsesMana();
-};
 
 const selectedValidSales = computed(() => {
     if (!sales.value) return;
@@ -277,7 +264,6 @@ const selectedValidSales = computed(() => {
 });
 
 const onOpenEditPricePopover = async (sale) => {
-    await getMana();
     edit.value = {
         sale: JSON.parse(JSON.stringify(sale)),
         price: sale.price,
@@ -285,7 +271,6 @@ const onOpenEditPricePopover = async (sale) => {
 };
 
 const onOpenEditDiscountPopover = async (sale) => {
-    await getMana();
     if (isLocked.value) return;
     if (sale) {
         edit.value = {
@@ -306,7 +291,6 @@ const changePrice = async (sale) => {
             await confirmUpdate(() => updatePrice(sale, newPrice));
         } else updatePrice(sale, newPrice);
     }
-    await getMana();
 };
 const updatePrice = async (sale, newPrice) => {
     await axios.post(`Sales/${sale.id}/updatePrice`, { newPrice });
@@ -599,9 +583,7 @@ watch(
                     :is-ticket-editable="isTicketEditable"
                     :sales="selectedValidSales"
                     :disable="!hasSelectedRows"
-                    :mana="mana"
                     :ticket-config="ticketConfig"
-                    @get-mana="getMana()"
                     @update-discounts="updateDiscounts"
                     @refresh-table="resetChanges"
                 />
@@ -829,7 +811,6 @@ watch(
                 </QBtn>
                 <TicketEditManaProxy
                     ref="editPriceProxyRef"
-                    :mana="mana"
                     :sale="row"
                     :new-price="getNewPrice"
                     @save="changePrice"
@@ -852,10 +833,8 @@ watch(
 
                 <TicketEditManaProxy
                     ref="editManaProxyRef"
-                    :mana="mana"
                     :sale="row"
                     :new-price="getNewPrice"
-                    :uses-mana="usesMana"
                     :mana-code="manaCode"
                     @save="changeDiscount"
                 >
diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 8b5537edc..840b62507 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -34,10 +34,6 @@ const props = defineProps({
         type: Array,
         default: () => [],
     },
-    mana: {
-        type: Number,
-        default: null,
-    },
     ticketConfig: {
         type: Array,
         default: () => [],
@@ -220,7 +216,6 @@ const createRefund = async (withWarehouse) => {
                 <TicketEditManaProxy
                     ref="editManaProxyRef"
                     :sale="row"
-                    :mana="props.mana"
                     @save="changeMultipleDiscount"
                 >
                     <VnInput

From e44d6a291515c7e045397836307718d62eb04d7c Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 22:48:48 +0100
Subject: [PATCH 23/28] test: remove test

---
 .../Card/__tests__/TicketEditMana.spec.js     | 56 -------------------
 1 file changed, 56 deletions(-)
 delete mode 100644 src/pages/Ticket/Card/__tests__/TicketEditMana.spec.js

diff --git a/src/pages/Ticket/Card/__tests__/TicketEditMana.spec.js b/src/pages/Ticket/Card/__tests__/TicketEditMana.spec.js
deleted file mode 100644
index f685d4ef0..000000000
--- a/src/pages/Ticket/Card/__tests__/TicketEditMana.spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
-
-import { createI18n } from 'vue-i18n';
-import TicketEditMana from 'src/pages/Ticket/Card/TicketEditMana.vue';
-import { createWrapper } from 'app/test/vitest/helper';
-
-describe('TicketEditMana', () => {
-    let vm;
-    let wrapper;
-    function generateWrapper(props = {}) {
-        wrapper = createWrapper(TicketEditMana, {
-            props,
-        });
-        wrapper = wrapper.wrapper;
-        vm = wrapper.vm;
-    }
-    afterEach(() => {
-        vi.clearAllMocks();
-    });
-
-    describe('mana prop tests', async () => {
-        it('should show spinner when mana is null', async () => {
-            generateWrapper({ mana: null });
-            await vm.$nextTick();
-            expect(vm.hasMana).toBe(false);
-        });
-
-        it('should show spinner when mana is undefined', async () => {
-            generateWrapper({ mana: undefined });
-            expect(typeof undefined === 'number').toBe(false);
-            await vm.$nextTick();
-            expect(vm.hasMana).toBe(false);
-        });
-
-        it('should display negative mana value', async () => {
-            generateWrapper({ mana: -1000 });
-            expect(typeof -1000 === 'number').toBe(true);
-            await vm.$nextTick();
-            expect(vm.hasMana).toBe(true);
-        });
-
-        it('should display zero mana value', async () => {
-            generateWrapper({ mana: 0 });
-            expect(typeof 0 === 'number').toBe(true);
-            await vm.$nextTick();
-            expect(vm.hasMana).toBe(true);
-        });
-
-        it('should display positive mana value', async () => {
-            generateWrapper({ mana: 1000 });
-            expect(typeof 1000 === 'number').toBe(true);
-            await vm.$nextTick();
-            expect(vm.hasMana).toBe(true);
-        });
-    });
-});

From 56f8657bbad6bda28b591b95c027a0330bbe0672 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 24 Feb 2025 22:58:57 +0100
Subject: [PATCH 24/28] fix: maxium calls exceed

---
 .../Customer/components/CustomerNewPayment.vue      | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/pages/Customer/components/CustomerNewPayment.vue b/src/pages/Customer/components/CustomerNewPayment.vue
index c2c38b55a..25e403991 100644
--- a/src/pages/Customer/components/CustomerNewPayment.vue
+++ b/src/pages/Customer/components/CustomerNewPayment.vue
@@ -77,24 +77,23 @@ onBeforeMount(() => {
 function setPaymentType(accounting) {
     if (!accounting) return;
     accountingType.value = accounting.accountingType;
-
     initialData.description = [];
     initialData.payed = Date.vnNew();
     isCash.value = accountingType.value.code == 'cash';
     viewReceipt.value = isCash.value;
     if (accountingType.value.daysInFuture)
         initialData.payed.setDate(
-            initialData.payed.getDate() + accountingType.value.daysInFuture
+            initialData.payed.getDate() + accountingType.value.daysInFuture,
         );
     maxAmount.value = accountingType.value && accountingType.value.maxAmount;
-
     if (accountingType.value.code == 'compensation')
         return (initialData.description = '');
-    if (accountingType.value.receiptDescription)
-        initialData.description.push(accountingType.value.receiptDescription);
-    if (initialData.description) initialData.description.push(initialData.description);
 
-    initialData.description = initialData.description.join(', ');
+    let descriptions = [];
+    if (accountingType.value.receiptDescription)
+        descriptions.push(accountingType.value.receiptDescription);
+    if (initialData.description) descriptions.push(initialData.description);
+    initialData.description = descriptions.join(', ');
 }
 
 const calculateFromAmount = (event) => {

From f2eedce55f518d3b23b36d09da1044c4d2347550 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 25 Feb 2025 08:01:10 +0100
Subject: [PATCH 25/28] fix: merge test to dev

---
 src/pages/Zone/ZoneList.vue | 52 +++++++------------------------------
 1 file changed, 10 insertions(+), 42 deletions(-)

diff --git a/src/pages/Zone/ZoneList.vue b/src/pages/Zone/ZoneList.vue
index 6fe3649ed..4df84e4bd 100644
--- a/src/pages/Zone/ZoneList.vue
+++ b/src/pages/Zone/ZoneList.vue
@@ -4,7 +4,7 @@ import { useRouter } from 'vue-router';
 import { computed, ref } from 'vue';
 import axios from 'axios';
 
-import { toCurrency } from 'src/filters';
+import { dashIfEmpty, toCurrency } from 'src/filters';
 import { toTimeFormat } from 'src/filters/date';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import useNotify from 'src/composables/useNotify.js';
@@ -17,7 +17,6 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 import ZoneFilterPanel from './ZoneFilterPanel.vue';
 import ZoneSearchbar from './Card/ZoneSearchbar.vue';
-import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const router = useRouter();
@@ -26,7 +25,6 @@ const { viewSummary } = useSummaryDialog();
 const { openConfirmationModal } = useVnConfirm();
 const tableRef = ref();
 const warehouseOptions = ref([]);
-const validAddresses = ref([]);
 
 const tableFilter = {
     include: [
@@ -67,6 +65,7 @@ const tableFilter = {
 
 const columns = computed(() => [
     {
+        align: 'left',
         name: 'id',
         label: t('list.id'),
         chip: {
@@ -76,8 +75,6 @@ const columns = computed(() => [
         columnFilter: {
             inWhere: true,
         },
-        columnClass: 'shrink-column',
-        component: 'number',
     },
     {
         align: 'left',
@@ -109,6 +106,7 @@ const columns = computed(() => [
         format: (row, dashIfEmpty) => dashIfEmpty(row?.agencyMode?.name),
     },
     {
+        align: 'left',
         name: 'price',
         label: t('list.price'),
         cardVisible: true,
@@ -116,11 +114,9 @@ const columns = computed(() => [
         columnFilter: {
             inWhere: true,
         },
-        columnClass: 'shrink-column',
-        component: 'number',
     },
     {
-        align: 'center',
+        align: 'left',
         name: 'hour',
         label: t('list.close'),
         cardVisible: true,
@@ -133,6 +129,7 @@ const columns = computed(() => [
         label: t('list.addressFk'),
         cardVisible: true,
         columnFilter: false,
+        columnClass: 'expand',
     },
     {
         align: 'right',
@@ -167,26 +164,14 @@ const handleClone = (id) => {
     );
 };
 
-function showValidAddresses(row) {
-    if (row.addressFk) {
-        const isValid = validAddresses.value.some(
-            (address) => address.addressFk === row.addressFk,
-        );
-        if (isValid)
-            return `${row.address?.nickname},
-            ${row.address?.postcode?.town?.name} (${row.address?.province?.name})`;
-        else return '-';
-    }
-    return '-';
+function formatRow(row) {
+    if (!row?.address) return '-';
+    return dashIfEmpty(`${row?.address?.nickname},
+            ${row?.address?.postcode?.town?.name} (${row?.address?.province?.name})`);
 }
 </script>
 
 <template>
-    <FetchData
-        url="RoadmapAddresses"
-        auto-load
-        @on-fetch="(data) => (validAddresses = data)"
-    />
     <ZoneSearchbar />
     <RightMenu>
         <template #right-panel>
@@ -209,7 +194,7 @@ function showValidAddresses(row) {
         :right-search="false"
     >
         <template #column-addressFk="{ row }">
-            {{ showValidAddresses(row) }}
+            {{ dashIfEmpty(formatRow(row)) }}
         </template>
         <template #more-create-dialog="{ data }">
             <VnSelect
@@ -261,20 +246,3 @@ es:
     Search zone: Buscar zona
     You can search zones by id or name: Puedes buscar zonas por id o nombre
 </i18n>
-
-<style lang="scss" scoped>
-.table-container {
-    display: flex;
-    justify-content: center;
-}
-.column {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    min-width: 70%;
-}
-
-:deep(.shrink-column) {
-    width: 8%;
-}
-</style>

From b9b5bd4c8ad4adde3079816cdd0d5c9be071a0d7 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 25 Feb 2025 09:40:46 +0100
Subject: [PATCH 26/28] Revert "revert
 1015acefb7e400be2d8b5958dba69b4d98276b34"

This reverts commit 223a1ea4490ea6ad2a00c60297fd3c74cd713338.
---
 cypress.config.js                             |    4 +-
 package.json                                  |  144 +-
 quasar.config.js                              |    1 -
 src/boot/defaults/constants.js                |    2 +
 src/boot/keyShortcut.js                       |   17 +-
 src/boot/qformMixin.js                        |   23 +-
 src/boot/quasar.js                            |    1 +
 src/components/CreateBankEntityForm.vue       |    2 +-
 src/components/CrudModel.vue                  |   16 +-
 src/components/FilterTravelForm.vue           |    4 +-
 src/components/FormModel.vue                  |   46 +-
 src/components/FormModelPopup.vue             |   50 +-
 src/components/ItemsFilterPanel.vue           |    4 +-
 src/components/LeftMenu.vue                   |   67 +-
 src/components/LeftMenuItem.vue               |    1 +
 src/components/RefundInvoiceForm.vue          |   15 +-
 src/components/TicketProblems.vue             |   82 +-
 src/components/TransferInvoiceForm.vue        |   15 +-
 src/components/VnTable/VnColumn.vue           |   51 +-
 src/components/VnTable/VnFilter.vue           |   58 +-
 src/components/VnTable/VnOrder.vue            |  101 +-
 src/components/VnTable/VnTable.vue            |  573 ++++++--
 src/components/VnTable/VnTableFilter.vue      |   57 +-
 src/components/VnTable/VnVisibleColumn.vue    |   19 +-
 src/components/__tests__/FormModel.spec.js    |   12 +-
 src/components/__tests__/Leftmenu.spec.js     |  376 ++++-
 src/components/__tests__/UserPanel.spec.js    |  100 +-
 src/components/common/VnCard.vue              |   39 +-
 src/components/common/VnCardBeta.vue          |   61 +-
 src/components/common/VnCheckbox.vue          |   43 +
 src/components/common/VnColor.vue             |   32 +
 src/components/common/VnComponent.vue         |    6 +-
 src/components/common/VnDmsList.vue           |   12 +-
 src/components/common/VnInput.vue             |   22 +-
 src/components/common/VnInputDate.vue         |    8 +-
 src/components/common/VnInputNumber.vue       |    2 +
 src/components/common/VnPopupProxy.vue        |   38 +
 src/components/common/VnSection.vue           |    9 +-
 src/components/common/VnSelect.vue            |   22 +-
 src/components/common/VnSelectCache.vue       |    4 +-
 src/components/common/VnSelectDialog.vue      |    2 -
 src/components/common/VnSelectSupplier.vue    |    6 +-
 .../common/VnSelectTravelExtended.vue         |   50 +
 .../common/__tests__/VnNotes.spec.js          |  151 +-
 src/components/ui/CardDescriptor.vue          |   52 +-
 src/components/ui/CardSummary.vue             |   14 +-
 src/components/ui/SkeletonDescriptor.vue      |   65 +-
 src/components/ui/VnConfirm.vue               |    3 +-
 src/components/ui/VnFilterPanel.vue           |   16 +-
 src/components/ui/VnMoreOptions.vue           |    2 +-
 src/components/ui/VnNotes.vue                 |   94 +-
 src/components/ui/VnStockValueDisplay.vue     |   41 +
 src/components/ui/VnSubToolbar.vue            |   11 +-
 .../ui/__tests__/CardSummary.spec.js          |   14 +-
 .../__tests__/useArrayData.spec.js            |   29 +-
 src/composables/checkEntryLock.js             |   65 +
 src/composables/getColAlign.js                |   22 +
 src/composables/useArrayData.js               |   13 +-
 src/composables/useRole.js                    |   10 +
 src/css/app.scss                              |   28 +-
 src/css/quasar.variables.scss                 |    6 +-
 src/filters/toDate.js                         |   11 +-
 src/i18n/locale/en.yml                        |  117 ++
 src/i18n/locale/es.yml                        |  225 ++-
 src/layouts/MainLayout.vue                    |    2 +-
 src/layouts/OutLayout.vue                     |    5 +-
 src/pages/Account/AccountAliasList.vue        |   10 +-
 src/pages/Account/AccountExprBuilder.js       |   18 +
 src/pages/Account/AccountList.vue             |   26 +-
 src/pages/Account/Alias/AliasExprBuilder.js   |    8 +
 src/pages/Account/Alias/Card/AliasCard.vue    |   10 +-
 .../Account/Alias/Card/AliasDescriptor.vue    |   11 +-
 src/pages/Account/Alias/Card/AliasSummary.vue |   19 +-
 src/pages/Account/Card/AccountBasicData.vue   |   38 +-
 src/pages/Account/Card/AccountCard.vue        |   10 +-
 src/pages/Account/Card/AccountDescriptor.vue  |   43 +-
 .../Account/Card/AccountDescriptorMenu.vue    |   27 +-
 src/pages/Account/Card/AccountFilter.js       |    3 +
 src/pages/Account/Card/AccountMailAlias.vue   |    7 +-
 src/pages/Account/Card/AccountSummary.vue     |   41 +-
 src/pages/Account/Role/AccountRoles.vue       |   18 +-
 src/pages/Account/Role/Card/RoleBasicData.vue |   14 +-
 src/pages/Account/Role/Card/RoleCard.vue      |    7 +-
 .../Account/Role/Card/RoleDescriptor.vue      |   16 +-
 src/pages/Account/Role/Card/RoleSummary.vue   |   23 +-
 src/pages/Account/Role/Card/SubRoles.vue      |    6 +-
 src/pages/Account/Role/RoleExprBuilder.js     |   16 +
 src/pages/Claim/Card/ClaimBasicData.vue       |    1 -
 src/pages/Claim/Card/ClaimCard.vue            |    9 +-
 src/pages/Claim/Card/ClaimDescriptor.vue      |   17 +-
 src/pages/Claim/Card/ClaimLines.vue           |    8 +-
 src/pages/Claim/Card/ClaimNotes.vue           |    3 +-
 src/pages/Claim/Card/ClaimPhoto.vue           |    4 +-
 src/pages/Claim/ClaimList.vue                 |    2 +-
 src/pages/Customer/Card/CustomerAddress.vue   |    8 +-
 src/pages/Customer/Card/CustomerBalance.vue   |    4 +-
 src/pages/Customer/Card/CustomerBasicData.vue |    4 +-
 .../Customer/Card/CustomerBillingData.vue     |    2 +-
 src/pages/Customer/Card/CustomerCard.vue      |    4 +-
 .../Customer/Card/CustomerConsumption.vue     |   95 +-
 src/pages/Customer/Card/CustomerContacts.vue  |    2 +-
 .../Customer/Card/CustomerCreditContracts.vue |    2 +-
 .../Customer/Card/CustomerDescriptor.vue      |   42 +-
 .../Customer/Card/CustomerDescriptorMenu.vue  |   17 +
 .../Customer/Card/CustomerFileManagement.vue  |    2 +-
 .../Customer/Card/CustomerFiscalData.vue      |   32 +-
 src/pages/Customer/Card/CustomerNotes.vue     |    1 +
 src/pages/Customer/Card/CustomerSamples.vue   |    2 +-
 src/pages/Customer/Card/CustomerWebAccess.vue |    2 +-
 src/pages/Customer/CustomerFilter.vue         |    6 +-
 src/pages/Customer/CustomerList.vue           |    4 +-
 .../Customer/Defaulter/CustomerDefaulter.vue  |    2 +-
 .../components/CustomerAddressEdit.vue        |    4 +-
 .../components/CustomerNewPayment.vue         |    6 +-
 .../components/CustomerSamplesCreate.vue      |    9 +-
 src/pages/Customer/locale/en.yml              |    3 +
 src/pages/Customer/locale/es.yml              |    3 +
 src/pages/Entry/Card/EntryBasicData.vue       |   63 +-
 src/pages/Entry/Card/EntryBuys.vue            | 1232 +++++++++++------
 src/pages/Entry/Card/EntryCard.vue            |    6 +-
 src/pages/Entry/Card/EntryDescriptor.vue      |  158 ++-
 src/pages/Entry/Card/EntryFilter.js           |   17 +-
 src/pages/Entry/Card/EntryNotes.vue           |    4 +-
 src/pages/Entry/Card/EntrySummary.vue         |  388 ++----
 src/pages/Entry/EntryFilter.vue               |  257 ++--
 src/pages/Entry/EntryList.vue                 |  368 +++--
 src/pages/Entry/EntryStockBought.vue          |   18 +-
 src/pages/Entry/EntryStockBoughtDetail.vue    |   22 +-
 src/pages/Entry/locale/en.yml                 |   84 +-
 src/pages/Entry/locale/es.yml                 |  107 +-
 .../InvoiceIn/Card/InvoiceInBasicData.vue     |    6 +-
 src/pages/InvoiceIn/Card/InvoiceInCard.vue    |   41 +-
 .../InvoiceIn/Card/InvoiceInDescriptor.vue    |   33 +-
 .../Card/InvoiceInDescriptorMenu.vue          |    4 +-
 src/pages/InvoiceIn/Card/InvoiceInDueDay.vue  |   26 +-
 src/pages/InvoiceIn/Card/InvoiceInFilter.js   |   33 +
 .../InvoiceIn/Card/InvoiceInIntrastat.vue     |    2 +-
 src/pages/InvoiceIn/Card/InvoiceInSummary.vue |   13 +-
 src/pages/InvoiceIn/Card/InvoiceInVat.vue     |   78 +-
 src/pages/InvoiceIn/InvoiceInList.vue         |    5 +-
 src/pages/InvoiceIn/InvoiceInToBook.vue       |   56 +-
 src/pages/InvoiceIn/locale/en.yml             |    5 +-
 src/pages/InvoiceIn/locale/es.yml             |    9 +-
 src/pages/InvoiceOut/Card/InvoiceOutCard.vue  |    4 +-
 .../InvoiceOut/Card/InvoiceOutDescriptor.vue  |   28 +-
 src/pages/InvoiceOut/Card/InvoiceOutFilter.js |   16 +
 src/pages/Item/Card/ItemBarcode.vue           |    2 +-
 src/pages/Item/Card/ItemBasicData.vue         |   42 +-
 src/pages/Item/Card/ItemBotanical.vue         |    4 +-
 src/pages/Item/Card/ItemCard.vue              |    2 +-
 src/pages/Item/Card/ItemDescriptor.vue        |   26 +-
 src/pages/Item/Card/ItemDescriptorProxy.vue   |    6 +-
 src/pages/Item/Card/ItemShelving.vue          |   10 +-
 src/pages/Item/Card/ItemTags.vue              |    2 +-
 src/pages/Item/ItemFixedPrice.vue             |   16 +-
 .../Item/ItemType/Card/ItemTypeBasicData.vue  |    7 +-
 src/pages/Item/ItemType/Card/ItemTypeCard.vue |    6 +-
 .../Item/ItemType/Card/ItemTypeDescriptor.vue |   40 +-
 .../Item/ItemType/Card/ItemTypeFilter.js      |    8 +
 .../Item/ItemType/Card/ItemTypeSummary.vue    |   15 +-
 .../{Card => components}/CreateGenusForm.vue  |    0
 .../{Card => components}/CreateSpecieForm.vue |    0
 src/pages/Item/components/ItemProposal.vue    |  332 +++++
 .../Item/components/ItemProposalProxy.vue     |   56 +
 src/pages/Item/locale/en.yml                  |   24 +-
 src/pages/Item/locale/es.yml                  |   31 +-
 src/pages/Monitor/MonitorOrders.vue           |    2 +-
 src/pages/Monitor/locale/en.yml               |    1 +
 src/pages/Monitor/locale/es.yml               |    1 +
 .../Order/Card/CatalogFilterValueDialog.vue   |    2 +-
 src/pages/Order/Card/OrderBasicData.vue       |    6 +-
 src/pages/Order/Card/OrderCard.vue            |    4 +-
 src/pages/Order/Card/OrderCatalogFilter.vue   |    4 +-
 .../Order/Card/OrderCatalogItemDialog.vue     |    8 +-
 src/pages/Order/Card/OrderDescriptor.vue      |   38 +-
 src/pages/Order/Card/OrderFilter.js           |   26 +
 src/pages/Order/Card/OrderLines.vue           |    4 +-
 src/pages/Order/Card/OrderSummary.vue         |    2 +-
 src/pages/Order/OrderList.vue                 |    7 +-
 src/pages/Route/Agency/AgencyList.vue         |    4 +-
 .../Route/Agency/Card/AgencyBasicData.vue     |    2 +-
 src/pages/Route/Agency/Card/AgencyCard.vue    |    2 +-
 .../Route/Agency/Card/AgencyDescriptor.vue    |    1 -
 .../Route/Agency/Card/AgencyWorkcenter.vue    |    2 +-
 src/pages/Route/Card/RouteCard.vue            |    5 +-
 src/pages/Route/Card/RouteDescriptor.vue      |   70 +-
 src/pages/Route/Card/RouteFilter.js           |   39 +
 src/pages/Route/Card/RouteFilter.vue          |    2 +-
 src/pages/Route/Card/RouteForm.vue            |   54 +-
 src/pages/Route/Roadmap/RoadmapBasicData.vue  |    5 +-
 src/pages/Route/Roadmap/RoadmapCard.vue       |    2 +-
 src/pages/Route/Roadmap/RoadmapDescriptor.vue |   18 +-
 src/pages/Route/Roadmap/RoadmapFilter.js      |    3 +
 src/pages/Route/Roadmap/RoadmapStops.vue      |    2 +-
 src/pages/Route/Roadmap/RoadmapSummary.vue    |    3 +-
 src/pages/Route/RouteExtendedList.vue         |  152 +-
 src/pages/Route/RouteList.vue                 |   31 +
 src/pages/Route/RouteTickets.vue              |   18 +-
 .../Route/Vehicle/Card/VehicleBasicData.vue   |  162 +++
 src/pages/Route/Vehicle/Card/VehicleCard.vue  |   13 +
 .../Route/Vehicle/Card/VehicleDescriptor.vue  |   49 +
 .../Route/Vehicle/Card/VehicleSummary.vue     |  127 ++
 src/pages/Route/Vehicle/VehicleFilter.js      |   76 +
 src/pages/Route/Vehicle/VehicleList.vue       |  224 +++
 src/pages/Route/Vehicle/locale/en.yml         |   20 +
 src/pages/Route/Vehicle/locale/es.yml         |   20 +
 src/pages/Shelving/Card/ShelvingCard.vue      |    4 +-
 .../Shelving/Card/ShelvingDescriptor.vue      |   30 +-
 src/pages/Shelving/Card/ShelvingFilter.js     |   15 +
 src/pages/Shelving/Card/ShelvingForm.vue      |   32 +-
 src/pages/Shelving/Card/ShelvingSearchbar.vue |    8 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |   37 +-
 .../Parking/Card/ParkingBasicData.vue         |   18 +-
 .../Parking/Card/ParkingCard.vue              |    6 +-
 .../Parking/Card/ParkingDescriptor.vue        |   16 +-
 .../Shelving/Parking/Card/ParkingFilter.js    |    4 +
 .../Parking/Card/ParkingLog.vue               |    0
 .../Parking/Card/ParkingSummary.vue           |    0
 .../Shelving/Parking/ParkingExprBuilder.js    |   10 +
 .../{ => Shelving}/Parking/ParkingFilter.vue  |    0
 .../{ => Shelving}/Parking/ParkingList.vue    |   13 +-
 .../{ => Shelving}/Parking/locale/en.yml      |    0
 .../{ => Shelving}/Parking/locale/es.yml      |    0
 src/pages/Shelving/ShelvingExprBuilder.js     |   10 +
 src/pages/Shelving/ShelvingList.vue           |   26 +-
 src/pages/Supplier/Card/SupplierAccounts.vue  |    6 +-
 src/pages/Supplier/Card/SupplierAddresses.vue |    2 +-
 .../Supplier/Card/SupplierAgencyTerm.vue      |    2 +-
 src/pages/Supplier/Card/SupplierBasicData.vue |    3 +-
 src/pages/Supplier/Card/SupplierCard.vue      |   16 +-
 .../Supplier/Card/SupplierConsumption.vue     |  103 +-
 src/pages/Supplier/Card/SupplierContacts.vue  |    2 +-
 .../Supplier/Card/SupplierDescriptor.vue      |   49 +-
 src/pages/Supplier/Card/SupplierFilter.js     |   35 +
 .../Supplier/Card/SupplierFiscalData.vue      |   22 +-
 src/pages/Supplier/SupplierList.vue           |   91 +-
 src/pages/Supplier/SupplierListFilter.vue     |  122 --
 .../Ticket/Card/BasicData/TicketBasicData.vue |   16 +-
 .../Card/BasicData/TicketBasicDataForm.vue    |    4 +-
 .../Card/BasicData/TicketBasicDataView.vue    |  116 +-
 src/pages/Ticket/Card/TicketCard.vue          |    8 +-
 src/pages/Ticket/Card/TicketComponents.vue    |    2 +-
 src/pages/Ticket/Card/TicketDescriptor.vue    |  139 +-
 src/pages/Ticket/Card/TicketExpedition.vue    |    2 +-
 src/pages/Ticket/Card/TicketFilter.js         |   72 +
 src/pages/Ticket/Card/TicketNotes.vue         |    4 +-
 src/pages/Ticket/Card/TicketPackage.vue       |    4 +-
 src/pages/Ticket/Card/TicketSale.vue          |   60 +-
 src/pages/Ticket/Card/TicketService.vue       |    6 +-
 src/pages/Ticket/Card/TicketSplit.vue         |   37 +
 src/pages/Ticket/Card/TicketSummary.vue       |   81 +-
 src/pages/Ticket/Card/TicketTracking.vue      |    4 +-
 src/pages/Ticket/Card/TicketTransfer.vue      |  131 +-
 src/pages/Ticket/Card/TicketTransferProxy.vue |   54 +
 src/pages/Ticket/Card/components/split.js     |   22 +
 .../Ticket/Negative/TicketLackDetail.vue      |  198 +++
 .../Ticket/Negative/TicketLackFilter.vue      |  175 +++
 src/pages/Ticket/Negative/TicketLackList.vue  |  227 +++
 src/pages/Ticket/Negative/TicketLackTable.vue |  356 +++++
 .../Negative/components/ChangeItemDialog.vue  |   90 ++
 .../components/ChangeQuantityDialog.vue       |   84 ++
 .../Negative/components/ChangeStateDialog.vue |   91 ++
 src/pages/Ticket/TicketFuture.vue             |  555 +++-----
 src/pages/Ticket/TicketFutureFilter.vue       |    4 +-
 src/pages/Ticket/locale/en.yml                |   87 +-
 src/pages/Ticket/locale/es.yml                |   83 ++
 src/pages/Travel/Card/TravelBasicData.vue     |   19 +-
 src/pages/Travel/Card/TravelCard.vue          |   36 +-
 src/pages/Travel/Card/TravelDescriptor.vue    |    1 -
 src/pages/Travel/Card/TravelFilter.js         |    1 +
 src/pages/Travel/Card/TravelSummary.vue       |    8 +
 src/pages/Travel/Card/TravelThermographs.vue  |    2 +-
 src/pages/Travel/ExtraCommunityFilter.vue     |    2 +-
 src/pages/Travel/TravelList.vue               |   24 +
 src/pages/Wagon/Card/WagonCard.vue            |    2 +-
 src/pages/Wagon/Type/WagonTypeList.vue        |    8 +-
 src/pages/Worker/Card/WorkerBasicData.vue     |   17 +-
 src/pages/Worker/Card/WorkerCalendar.vue      |   32 +-
 .../Worker/Card/WorkerCalendarFilter.vue      |    2 -
 src/pages/Worker/Card/WorkerCard.vue          |    7 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |    9 +-
 .../Worker/Card/WorkerDescriptorProxy.vue     |    7 +-
 src/pages/Worker/Card/WorkerFormation.vue     |    3 +-
 src/pages/Worker/Card/WorkerMedical.vue       |   16 +
 src/pages/Worker/Card/WorkerOperator.vue      |   19 +-
 src/pages/Worker/Card/WorkerPda.vue           |   10 +-
 src/pages/Worker/Card/WorkerPit.vue           |    2 +-
 src/pages/Worker/Card/WorkerSummary.vue       |    2 +-
 src/pages/Worker/Card/WorkerTimeControl.vue   |   16 +-
 .../Department/Card/DepartmentBasicData.vue   |   35 +-
 .../Department/Card/DepartmentCard.vue        |    4 +-
 .../Department/Card/DepartmentDescriptor.vue  |   23 +-
 .../Card/DepartmentDescriptorProxy.vue        |    0
 .../Department/Card/DepartmentSummary.vue     |    2 +-
 .../Card/DepartmentSummaryDialog.vue          |    0
 src/pages/Worker/WorkerDepartmentTree.vue     |    4 +-
 src/pages/Zone/Card/ZoneBasicData.vue         |   33 +-
 src/pages/Zone/Card/ZoneCard.vue              |   12 +-
 src/pages/Zone/Card/ZoneDescriptor.vue        |   44 +-
 src/pages/Zone/Card/ZoneEvents.vue            |    4 +-
 src/pages/Zone/Card/ZoneFilter.js             |   10 +
 src/pages/Zone/Card/ZoneSearchbar.vue         |   41 +-
 src/pages/Zone/Card/ZoneSummary.vue           |   18 +-
 src/pages/Zone/Card/ZoneWarehouses.vue        |    2 +-
 src/pages/Zone/Delivery/ZoneDeliveryList.vue  |    2 +-
 src/pages/Zone/Upcoming/ZoneUpcomingList.vue  |    2 +-
 src/pages/Zone/ZoneList.vue                   |   29 +-
 src/router/modules/account/aliasCard.js       |    2 +-
 src/router/modules/account/roleCard.js        |    1 +
 src/router/modules/entry.js                   |   17 +-
 src/router/modules/route.js                   |   52 +
 src/router/modules/shelving.js                |   11 +-
 src/router/modules/supplier.js                |  315 +++--
 src/router/modules/ticket.js                  |   34 +-
 src/router/modules/worker.js                  |    9 +-
 .../__tests__/useNavigationStore.spec.js      |  153 ++
 src/stores/useArrayDataStore.js               |    1 +
 src/utils/notifyResults.js                    |   19 +
 .../integration/Order/orderCatalog.spec.js    |    1 -
 .../integration/entry/entryList.spec.js       |  224 +++
 .../integration/entry/stockBought.spec.js     |   37 +-
 .../invoiceIn/invoiceInBasicData.spec.js      |   27 +-
 .../invoiceIn/invoiceInVat.spec.js            |    2 +-
 .../invoiceOutNegativeBases.spec.js           |    4 +-
 .../integration/item/ItemProposal.spec.js     |   11 +
 test/cypress/integration/item/itemTag.spec.js |    5 +-
 .../parking/parkingBasicData.spec.js          |    4 +-
 .../route/agency/agencyWorkCenter.spec.js     |    1 +
 .../integration/route/routeList.spec.js       |   19 +-
 .../route/vehicle/vehicleDescriptor.spec.js   |   13 +
 .../ticket/negative/TicketLackDetail.spec.js  |  147 ++
 .../ticket/negative/TicketLackList.spec.js    |   36 +
 .../integration/ticket/ticketList.spec.js     |   25 +
 .../vnComponent/VnShortcut.spec.js            |   11 +
 .../wagon/wagonType/wagonTypeCreate.spec.js   |    2 +-
 .../integration/zone/zoneBasicData.spec.js    |   16 +-
 test/cypress/support/commands.js              |   71 +-
 test/cypress/support/waitUntil.js             |    2 +-
 338 files changed, 9584 insertions(+), 4379 deletions(-)
 create mode 100644 src/boot/defaults/constants.js
 create mode 100644 src/components/common/VnCheckbox.vue
 create mode 100644 src/components/common/VnColor.vue
 create mode 100644 src/components/common/VnPopupProxy.vue
 create mode 100644 src/components/common/VnSelectTravelExtended.vue
 create mode 100644 src/components/ui/VnStockValueDisplay.vue
 create mode 100644 src/composables/checkEntryLock.js
 create mode 100644 src/composables/getColAlign.js
 create mode 100644 src/pages/Account/AccountExprBuilder.js
 create mode 100644 src/pages/Account/Alias/AliasExprBuilder.js
 create mode 100644 src/pages/Account/Card/AccountFilter.js
 create mode 100644 src/pages/Account/Role/RoleExprBuilder.js
 create mode 100644 src/pages/InvoiceIn/Card/InvoiceInFilter.js
 create mode 100644 src/pages/InvoiceOut/Card/InvoiceOutFilter.js
 create mode 100644 src/pages/Item/ItemType/Card/ItemTypeFilter.js
 rename src/pages/Item/{Card => components}/CreateGenusForm.vue (100%)
 rename src/pages/Item/{Card => components}/CreateSpecieForm.vue (100%)
 create mode 100644 src/pages/Item/components/ItemProposal.vue
 create mode 100644 src/pages/Item/components/ItemProposalProxy.vue
 create mode 100644 src/pages/Order/Card/OrderFilter.js
 create mode 100644 src/pages/Route/Card/RouteFilter.js
 create mode 100644 src/pages/Route/Roadmap/RoadmapFilter.js
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleBasicData.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleCard.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleSummary.vue
 create mode 100644 src/pages/Route/Vehicle/VehicleFilter.js
 create mode 100644 src/pages/Route/Vehicle/VehicleList.vue
 create mode 100644 src/pages/Route/Vehicle/locale/en.yml
 create mode 100644 src/pages/Route/Vehicle/locale/es.yml
 create mode 100644 src/pages/Shelving/Card/ShelvingFilter.js
 rename src/pages/{ => Shelving}/Parking/Card/ParkingBasicData.vue (68%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingCard.vue (53%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingDescriptor.vue (58%)
 create mode 100644 src/pages/Shelving/Parking/Card/ParkingFilter.js
 rename src/pages/{ => Shelving}/Parking/Card/ParkingLog.vue (100%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingSummary.vue (100%)
 create mode 100644 src/pages/Shelving/Parking/ParkingExprBuilder.js
 rename src/pages/{ => Shelving}/Parking/ParkingFilter.vue (100%)
 rename src/pages/{ => Shelving}/Parking/ParkingList.vue (90%)
 rename src/pages/{ => Shelving}/Parking/locale/en.yml (100%)
 rename src/pages/{ => Shelving}/Parking/locale/es.yml (100%)
 create mode 100644 src/pages/Shelving/ShelvingExprBuilder.js
 create mode 100644 src/pages/Supplier/Card/SupplierFilter.js
 delete mode 100644 src/pages/Supplier/SupplierListFilter.vue
 create mode 100644 src/pages/Ticket/Card/TicketFilter.js
 create mode 100644 src/pages/Ticket/Card/TicketSplit.vue
 create mode 100644 src/pages/Ticket/Card/TicketTransferProxy.vue
 create mode 100644 src/pages/Ticket/Card/components/split.js
 create mode 100644 src/pages/Ticket/Negative/TicketLackDetail.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackFilter.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackList.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackTable.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeItemDialog.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeStateDialog.vue
 rename src/pages/{ => Worker}/Department/Card/DepartmentBasicData.vue (73%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentCard.vue (70%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentDescriptor.vue (84%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentDescriptorProxy.vue (100%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentSummary.vue (99%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentSummaryDialog.vue (100%)
 create mode 100644 src/pages/Zone/Card/ZoneFilter.js
 create mode 100644 src/stores/__tests__/useNavigationStore.spec.js
 create mode 100644 src/utils/notifyResults.js
 create mode 100644 test/cypress/integration/entry/entryList.spec.js
 create mode 100644 test/cypress/integration/item/ItemProposal.spec.js
 create mode 100644 test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
 create mode 100644 test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
 create mode 100644 test/cypress/integration/ticket/negative/TicketLackList.spec.js

diff --git a/cypress.config.js b/cypress.config.js
index 1924144f6..a9e27fcfd 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -14,8 +14,8 @@ export default defineConfig({
         downloadsFolder: 'test/cypress/downloads',
         video: false,
         specPattern: 'test/cypress/integration/**/*.spec.js',
-        experimentalRunAllSpecs: true,
-        watchForFileChanges: true,
+        experimentalRunAllSpecs: false,
+        watchForFileChanges: false,
         reporter: 'cypress-mochawesome-reporter',
         reporterOptions: {
             charts: true,
diff --git a/package.json b/package.json
index 17f39cad7..d23ed0ced 100644
--- a/package.json
+++ b/package.json
@@ -1,74 +1,74 @@
 {
-  "name": "salix-front",
-  "version": "25.06.0",
-  "description": "Salix frontend",
-  "productName": "Salix",
-  "author": "Verdnatura",
-  "private": true,
-  "packageManager": "pnpm@8.15.1",
-  "type": "module",
-  "scripts": {
-    "resetDatabase": "cd ../salix && gulp docker",
-    "lint": "eslint --ext .js,.vue ./",
-    "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
-    "test:e2e": "cypress open",
-    "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
-    "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
-    "test:unit": "vitest",
-    "test:unit:ci": "vitest run",
-    "commitlint": "commitlint --edit",
-    "prepare": "npx husky install",
-    "addReferenceTag": "node .husky/addReferenceTag.js",
-    "docs:dev": "vitepress dev docs",
-    "docs:build": "vitepress build docs",
-    "docs:preview": "vitepress preview docs"
-  },
-  "dependencies": {
-    "@quasar/cli": "^2.4.1",
-    "@quasar/extras": "^1.16.16",
-    "axios": "^1.4.0",
-    "chromium": "^3.0.3",
-    "croppie": "^2.6.5",
-    "moment": "^2.30.1",
-    "pinia": "^2.1.3",
-    "quasar": "^2.17.7",
-    "validator": "^13.9.0",
-    "vue": "^3.5.13",
-    "vue-i18n": "^9.3.0",
-    "vue-router": "^4.2.5"
-  },
-  "devDependencies": {
-    "@commitlint/cli": "^19.2.1",
-    "@commitlint/config-conventional": "^19.1.0",
-    "@intlify/unplugin-vue-i18n": "^0.8.2",
-    "@pinia/testing": "^0.1.2",
-    "@quasar/app-vite": "^2.0.8",
-    "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
-    "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
-    "@vue/test-utils": "^2.4.4",
-    "autoprefixer": "^10.4.14",
-    "cypress": "^13.6.6",
-    "cypress-mochawesome-reporter": "^3.8.2",
-    "eslint": "^9.18.0",
-    "eslint-config-prettier": "^10.0.1",
-    "eslint-plugin-cypress": "^4.1.0",
-    "eslint-plugin-vue": "^9.32.0",
-    "husky": "^8.0.0",
-    "postcss": "^8.4.23",
-    "prettier": "^3.4.2",
-    "sass": "^1.83.4",
-    "vitepress": "^1.6.3",
-    "vitest": "^0.34.0"
-  },
-  "engines": {
-    "node": "^20 || ^18 || ^16",
-    "npm": ">= 8.1.2",
-    "yarn": ">= 1.21.1",
-    "bun": ">= 1.0.25"
-  },
-  "overrides": {
-    "@vitejs/plugin-vue": "^5.2.1",
-    "vite": "^6.0.11",
-    "vitest": "^0.31.1"
-  }
+    "name": "salix-front",
+    "version": "25.08.0",
+    "description": "Salix frontend",
+    "productName": "Salix",
+    "author": "Verdnatura",
+    "private": true,
+    "packageManager": "pnpm@8.15.1",
+    "type": "module",
+    "scripts": {
+        "resetDatabase": "cd ../salix && gulp docker",
+        "lint": "eslint --ext .js,.vue ./",
+        "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
+        "test:e2e": "cypress open",
+        "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
+        "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+        "test:unit": "vitest",
+        "test:unit:ci": "vitest run",
+        "commitlint": "commitlint --edit",
+        "prepare": "npx husky install",
+        "addReferenceTag": "node .husky/addReferenceTag.js",
+        "docs:dev": "vitepress dev docs",
+        "docs:build": "vitepress build docs",
+        "docs:preview": "vitepress preview docs"
+    },
+    "dependencies": {
+        "@quasar/cli": "^2.4.1",
+        "@quasar/extras": "^1.16.16",
+        "axios": "^1.4.0",
+        "chromium": "^3.0.3",
+        "croppie": "^2.6.5",
+        "moment": "^2.30.1",
+        "pinia": "^2.1.3",
+        "quasar": "^2.17.7",
+        "validator": "^13.9.0",
+        "vue": "^3.5.13",
+        "vue-i18n": "^9.3.0",
+        "vue-router": "^4.2.5"
+    },
+    "devDependencies": {
+        "@commitlint/cli": "^19.2.1",
+        "@commitlint/config-conventional": "^19.1.0",
+        "@intlify/unplugin-vue-i18n": "^0.8.2",
+        "@pinia/testing": "^0.1.2",
+        "@quasar/app-vite": "^2.0.8",
+        "@quasar/quasar-app-extension-qcalendar": "^4.0.2",
+        "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
+        "@vue/test-utils": "^2.4.4",
+        "autoprefixer": "^10.4.14",
+        "cypress": "^13.6.6",
+        "cypress-mochawesome-reporter": "^3.8.2",
+        "eslint": "^9.18.0",
+        "eslint-config-prettier": "^10.0.1",
+        "eslint-plugin-cypress": "^4.1.0",
+        "eslint-plugin-vue": "^9.32.0",
+        "husky": "^8.0.0",
+        "postcss": "^8.4.23",
+        "prettier": "^3.4.2",
+        "sass": "^1.83.4",
+        "vitepress": "^1.6.3",
+        "vitest": "^0.34.0"
+    },
+    "engines": {
+        "node": "^20 || ^18 || ^16",
+        "npm": ">= 8.1.2",
+        "yarn": ">= 1.21.1",
+        "bun": ">= 1.0.25"
+    },
+    "overrides": {
+        "@vitejs/plugin-vue": "^5.2.1",
+        "vite": "^6.0.11",
+        "vitest": "^0.31.1"
+    }
 }
\ No newline at end of file
diff --git a/quasar.config.js b/quasar.config.js
index 6d545c026..9467c92af 100644
--- a/quasar.config.js
+++ b/quasar.config.js
@@ -30,7 +30,6 @@ export default configure(function (/* ctx */) {
         // --> boot files are part of "main.js"
         // https://v2.quasar.dev/quasar-cli/boot-files
         boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'],
-
         // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
         css: ['app.scss'],
 
diff --git a/src/boot/defaults/constants.js b/src/boot/defaults/constants.js
new file mode 100644
index 000000000..c96ceb2d1
--- /dev/null
+++ b/src/boot/defaults/constants.js
@@ -0,0 +1,2 @@
+export const langs = ['en', 'es'];
+export const decimalPlaces = 2;
diff --git a/src/boot/keyShortcut.js b/src/boot/keyShortcut.js
index 5afb5b74a..6da06c8bf 100644
--- a/src/boot/keyShortcut.js
+++ b/src/boot/keyShortcut.js
@@ -1,6 +1,6 @@
 export default {
-    mounted: function (el, binding) {
-        const shortcut = binding.value ?? '+';
+    mounted(el, binding) {
+        const shortcut = binding.value || '+';
 
         const { key, ctrl, alt, callback } =
             typeof shortcut === 'string'
@@ -8,25 +8,24 @@ export default {
                       key: shortcut,
                       ctrl: true,
                       alt: true,
-                      callback: () =>
-                          document
-                              .querySelector(`button[shortcut="${shortcut}"]`)
-                              ?.click(),
+                      callback: () => el?.click(),
                   }
                 : binding.value;
 
+        if (!el.hasAttribute('shortcut')) {
+            el.setAttribute('shortcut', key);
+        }
+
         const handleKeydown = (event) => {
             if (event.key === key && (!ctrl || event.ctrlKey) && (!alt || event.altKey)) {
                 callback();
             }
         };
 
-        // Attach the event listener to the window
         window.addEventListener('keydown', handleKeydown);
-
         el._handleKeydown = handleKeydown;
     },
-    unmounted: function (el) {
+    unmounted(el) {
         if (el._handleKeydown) {
             window.removeEventListener('keydown', el._handleKeydown);
         }
diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js
index 97d80c670..182c51e47 100644
--- a/src/boot/qformMixin.js
+++ b/src/boot/qformMixin.js
@@ -9,19 +9,19 @@ export default {
         if (!form) return;
         try {
             const inputsFormCard = form.querySelectorAll(
-                `input:not([disabled]):not([type="checkbox"])`
+                `input:not([disabled]):not([type="checkbox"])`,
             );
             if (inputsFormCard.length) {
                 focusFirstInput(inputsFormCard[0]);
             }
             const textareas = document.querySelectorAll(
-                'textarea:not([disabled]), [contenteditable]:not([disabled])'
+                'textarea:not([disabled]), [contenteditable]:not([disabled])',
             );
             if (textareas.length) {
                 focusFirstInput(textareas[textareas.length - 1]);
             }
             const inputs = document.querySelectorAll(
-                'form#formModel input:not([disabled]):not([type="checkbox"])'
+                'form#formModel input:not([disabled]):not([type="checkbox"])',
             );
             const input = inputs[0];
             if (!input) return;
@@ -30,22 +30,5 @@ export default {
         } catch (error) {
             console.error(error);
         }
-        form.addEventListener('keyup', function (evt) {
-            if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
-                const input = evt.target;
-                if (input.type == 'textarea' && evt.shiftKey) {
-                    evt.preventDefault();
-                    let { selectionStart, selectionEnd } = input;
-                    input.value =
-                        input.value.substring(0, selectionStart) +
-                        '\n' +
-                        input.value.substring(selectionEnd);
-                    selectionStart = selectionEnd = selectionStart + 1;
-                    return;
-                }
-                evt.preventDefault();
-                that.onSubmit();
-            }
-        });
     },
 };
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 547517682..a8c397b83 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -51,4 +51,5 @@ export default boot(({ app }) => {
 
         await useCau(response, message);
     };
+    app.provide('app', app);
 });
diff --git a/src/components/CreateBankEntityForm.vue b/src/components/CreateBankEntityForm.vue
index 2da3aa994..7c4b94a6a 100644
--- a/src/components/CreateBankEntityForm.vue
+++ b/src/components/CreateBankEntityForm.vue
@@ -14,7 +14,7 @@ const { t } = useI18n();
 const bicInputRef = ref(null);
 const state = useState();
 
-const customer = computed(() => state.get('customer'));
+const customer = computed(() => state.get('Customer'));
 
 const countriesFilter = {
     fields: ['id', 'name', 'code'],
diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue
index d569dfda1..93a2ac96a 100644
--- a/src/components/CrudModel.vue
+++ b/src/components/CrudModel.vue
@@ -64,6 +64,10 @@ const $props = defineProps({
         type: Function,
         default: null,
     },
+    beforeSaveFn: {
+        type: Function,
+        default: null,
+    },
     goTo: {
         type: String,
         default: '',
@@ -176,7 +180,11 @@ async function saveChanges(data) {
         hasChanges.value = false;
         return;
     }
-    const changes = data || getChanges();
+    let changes = data || getChanges();
+    if ($props.beforeSaveFn) {
+        changes = await $props.beforeSaveFn(changes, getChanges);
+    }
+
     try {
         await axios.post($props.saveUrl || $props.url + '/crud', changes);
     } finally {
@@ -229,12 +237,12 @@ async function remove(data) {
                 componentProps: {
                     title: t('globals.confirmDeletion'),
                     message: t('globals.confirmDeletionMessage'),
-                    newData,
+                    data: { deletes: ids },
                     ids,
+                    promise: saveChanges,
                 },
             })
             .onOk(async () => {
-                await saveChanges({ deletes: ids });
                 newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
                 fetch(newData);
             });
@@ -374,6 +382,8 @@ watch(formUrl, async () => {
                 @click="onSubmit"
                 :disable="!hasChanges"
                 :title="t('globals.save')"
+                v-shortcut="'s'"
+                shortcut="s"
                 data-cy="crudModelDefaultSaveBtn"
             />
             <slot name="moreAfterActions" />
diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue
index 4d43c3810..765d97763 100644
--- a/src/components/FilterTravelForm.vue
+++ b/src/components/FilterTravelForm.vue
@@ -181,6 +181,7 @@ const selectTravel = ({ id }) => {
                     color="primary"
                     :disabled="isLoading"
                     :loading="isLoading"
+                    data-cy="save-filter-travel-form"
                 />
             </div>
             <QTable
@@ -191,9 +192,10 @@ const selectTravel = ({ id }) => {
                 :no-data-label="t('Enter a new search')"
                 class="q-mt-lg"
                 @row-click="(_, row) => selectTravel(row)"
+                data-cy="table-filter-travel-form"
             >
                 <template #body-cell-id="{ row }">
-                    <QTd auto-width @click.stop>
+                    <QTd auto-width @click.stop data-cy="travelFk-travel-form">
                         <QBtn flat color="blue">{{ row.id }}</QBtn>
                         <TravelDescriptorProxy :id="row.id" />
                     </QTd>
diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 3842ff947..04ef13d45 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue';
+import { onMounted, onUnmounted, computed, ref, watch, nextTick, useAttrs } from 'vue';
 import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -22,6 +22,7 @@ const { validate } = useValidator();
 const { notify } = useNotify();
 const route = useRoute();
 const myForm = ref(null);
+const attrs = useAttrs();
 const $props = defineProps({
     url: {
         type: String,
@@ -84,7 +85,7 @@ const $props = defineProps({
     },
     reload: {
         type: Boolean,
-        default: false,
+        default: true,
     },
     defaultTrim: {
         type: Boolean,
@@ -105,15 +106,15 @@ const isLoading = ref(false);
 // Si elegimos observar los cambios del form significa que inicialmente las actions estaran deshabilitadas
 const isResetting = ref(false);
 const hasChanges = ref(!$props.observeFormChanges);
-const originalData = ref({});
-const formData = computed(() => state.get(modelValue));
+const originalData = computed(() => state.get(modelValue));
+const formData = ref();
 const defaultButtons = computed(() => ({
     save: {
         dataCy: 'saveDefaultBtn',
         color: 'primary',
         icon: 'save',
         label: 'globals.save',
-        click: () => myForm.value.submit(),
+        click: async () => await save(),
         type: 'submit',
     },
     reset: {
@@ -127,8 +128,6 @@ const defaultButtons = computed(() => ({
 }));
 
 onMounted(async () => {
-    originalData.value = JSON.parse(JSON.stringify($props.formInitialData ?? {}));
-
     nextTick(() => (componentIsRendered.value = true));
 
     // Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla
@@ -160,10 +159,18 @@ if (!$props.url)
         (val) => updateAndEmit('onFetch', { val }),
     );
 
+watch(
+    originalData,
+    (val) => {
+        if (val) formData.value = JSON.parse(JSON.stringify(val));
+    },
+    { immediate: true },
+);
+
 watch(
     () => [$props.url, $props.filter],
     async () => {
-        originalData.value = null;
+        state.set(modelValue, null);
         reset();
         await fetch();
     },
@@ -198,7 +205,6 @@ async function fetch() {
         updateAndEmit('onFetch', { val: data });
     } catch (e) {
         state.set(modelValue, {});
-        originalData.value = {};
         throw e;
     }
 }
@@ -241,6 +247,7 @@ async function saveAndGo() {
 }
 
 function reset() {
+    formData.value = JSON.parse(JSON.stringify(originalData.value));
     updateAndEmit('onFetch', { val: originalData.value });
     if ($props.observeFormChanges) {
         hasChanges.value = false;
@@ -265,7 +272,6 @@ function filter(value, update, filterOptions) {
 
 function updateAndEmit(evt, { val, res, old } = { val: null, res: null, old: null }) {
     state.set(modelValue, val);
-    originalData.value = val && JSON.parse(JSON.stringify(val));
     if (!$props.url) arrayData.store.data = val;
 
     emit(evt, state.get(modelValue), res, old);
@@ -279,6 +285,22 @@ function trimData(data) {
     return data;
 }
 
+async function onKeyup(evt) {
+    if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
+        const input = evt.target;
+        if (input.type == 'textarea' && evt.shiftKey) {
+            let { selectionStart, selectionEnd } = input;
+            input.value =
+                input.value.substring(0, selectionStart) +
+                '\n' +
+                input.value.substring(selectionEnd);
+            selectionStart = selectionEnd = selectionStart + 1;
+            return;
+        }
+        await save();
+    }
+}
+
 defineExpose({
     save,
     isLoading,
@@ -293,12 +315,12 @@ defineExpose({
         <QForm
             ref="myForm"
             v-if="formData"
-            @submit="save"
+            @submit.prevent
+            @keyup.prevent="onKeyup"
             @reset="reset"
             class="q-pa-md"
             :style="maxWidth ? 'max-width: ' + maxWidth : ''"
             id="formModel"
-            :prevent-submit="$attrs['prevent-submit']"
         >
             <QCard>
                 <slot
diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index afdc6efca..85943e91e 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -1,12 +1,13 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, useAttrs, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
 
 import FormModel from 'components/FormModel.vue';
 
 const emit = defineEmits(['onDataSaved', 'onDataCanceled']);
 
-defineProps({
+const props = defineProps({
     title: {
         type: String,
         default: '',
@@ -15,23 +16,41 @@ defineProps({
         type: String,
         default: '',
     },
+    showSaveAndContinueBtn: {
+        type: Boolean,
+        default: false,
+    },
 });
 
 const { t } = useI18n();
-
+const attrs = useAttrs();
+const state = useState();
 const formModelRef = ref(null);
 const closeButton = ref(null);
+const isSaveAndContinue = ref(props.showSaveAndContinueBtn);
+const isLoading = computed(() => formModelRef.value?.isLoading);
+const reset = computed(() => formModelRef.value?.reset);
 
-const onDataSaved = (formData, requestResponse) => {
-    if (closeButton.value) closeButton.value.click();
+const onDataSaved = async (formData, requestResponse) => {
+    if (!isSaveAndContinue.value) closeButton.value?.click();
+    if (isSaveAndContinue.value) {
+        await nextTick();
+        state.set(attrs.model, attrs.formInitialData);
+    }
+    isSaveAndContinue.value = props.showSaveAndContinueBtn;
     emit('onDataSaved', formData, requestResponse);
 };
 
-const isLoading = computed(() => formModelRef.value?.isLoading);
+const onClick = async (saveAndContinue) => {
+    isSaveAndContinue.value = saveAndContinue;
+    await formModelRef.value.save();
+};
 
 defineExpose({
     isLoading,
     onDataSaved,
+    isSaveAndContinue,
+    reset,
 });
 </script>
 
@@ -59,15 +78,16 @@ defineExpose({
                     flat
                     :disabled="isLoading"
                     :loading="isLoading"
-                    @click="emit('onDataCanceled')"
-                    v-close-popup
                     data-cy="FormModelPopup_cancel"
+                    v-close-popup
                     z-max
+                    @click="emit('onDataCanceled')"
                 />
                 <QBtn
+                    :flat="showSaveAndContinueBtn"
                     :label="t('globals.save')"
                     :title="t('globals.save')"
-                    type="submit"
+                    @click="onClick(false)"
                     color="primary"
                     class="q-ml-sm"
                     :disabled="isLoading"
@@ -75,6 +95,18 @@ defineExpose({
                     data-cy="FormModelPopup_save"
                     z-max
                 />
+                <QBtn
+                    v-if="showSaveAndContinueBtn"
+                    :label="t('globals.isSaveAndContinue')"
+                    :title="t('globals.isSaveAndContinue')"
+                    color="primary"
+                    class="q-ml-sm"
+                    :disabled="isLoading"
+                    :loading="isLoading"
+                    data-cy="FormModelPopup_isSaveAndContinue"
+                    z-max
+                    @click="onClick(true)"
+                />
             </div>
         </template>
     </FormModel>
diff --git a/src/components/ItemsFilterPanel.vue b/src/components/ItemsFilterPanel.vue
index 36123b834..f73753a6b 100644
--- a/src/components/ItemsFilterPanel.vue
+++ b/src/components/ItemsFilterPanel.vue
@@ -281,7 +281,7 @@ const setCategoryList = (data) => {
             <QItem class="q-mt-lg">
                 <QBtn
                     icon="add_circle"
-                    shortcut="+"
+                    v-shortcut="'+'"
                     flat
                     class="fill-icon-on-hover q-px-xs"
                     color="primary"
@@ -327,7 +327,6 @@ en:
         active: Is active
         visible: Is visible
         floramondo: Is floramondo
-        salesPersonFk: Buyer
         categoryFk: Category
 
 es:
@@ -338,7 +337,6 @@ es:
         active: Activo
         visible: Visible
         floramondo: Floramondo
-        salesPersonFk: Comprador
         categoryFk: Categoría
     Plant: Planta natural
     Flower: Flor fresca
diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 644f831d4..9a9949499 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -41,7 +41,6 @@ const filteredItems = computed(() => {
         return locale.includes(normalizedSearch);
     });
 });
-
 const filteredPinnedModules = computed(() => {
     if (!search.value) return pinnedModules.value;
     const normalizedSearch = search.value
@@ -72,7 +71,7 @@ watch(
         items.value = [];
         getRoutes();
     },
-    { deep: true }
+    { deep: true },
 );
 
 function findMatches(search, item) {
@@ -104,33 +103,40 @@ function addChildren(module, route, parent) {
 }
 
 function getRoutes() {
-    if (props.source === 'main') {
-        const modules = Object.assign([], navigation.getModules().value);
-
-        for (const item of modules) {
-            const moduleDef = routes.find(
-                (route) => toLowerCamel(route.name) === item.module
-            );
-            if (!moduleDef) continue;
-            item.children = [];
-
-            addChildren(item.module, moduleDef, item.children);
-        }
-
-        items.value = modules;
+    const handleRoutes = {
+        main: getMainRoutes,
+        card: getCardRoutes,
+    };
+    try {
+        handleRoutes[props.source]();
+    } catch (error) {
+        throw new Error(`Method is not defined`);
     }
+}
+function getMainRoutes() {
+    const modules = Object.assign([], navigation.getModules().value);
 
-    if (props.source === 'card') {
-        const currentRoute = route.matched[1];
-        const currentModule = toLowerCamel(currentRoute.name);
-        let moduleDef = routes.find(
-            (route) => toLowerCamel(route.name) === currentModule
+    for (const item of modules) {
+        const moduleDef = routes.find(
+            (route) => toLowerCamel(route.name) === item.module,
         );
+        if (!moduleDef) continue;
+        item.children = [];
 
-        if (!moduleDef) return;
-        if (!moduleDef?.menus) moduleDef = betaGetRoutes();
-        addChildren(currentModule, moduleDef, items.value);
+        addChildren(item.module, moduleDef, item.children);
     }
+
+    items.value = modules;
+}
+
+function getCardRoutes() {
+    const currentRoute = route.matched[1];
+    const currentModule = toLowerCamel(currentRoute.name);
+    let moduleDef = routes.find((route) => toLowerCamel(route.name) === currentModule);
+
+    if (!moduleDef) return;
+    if (!moduleDef?.menus) moduleDef = betaGetRoutes();
+    addChildren(currentModule, moduleDef, items.value);
 }
 
 function betaGetRoutes() {
@@ -223,9 +229,16 @@ const searchModule = () => {
                 </template>
                 <template v-for="(item, index) in filteredItems" :key="item.name">
                     <template
-                        v-if="search ||item.children && !filteredPinnedModules.has(item.name)"
+                        v-if="
+                            search ||
+                            (item.children && !filteredPinnedModules.has(item.name))
+                        "
                     >
-                        <LeftMenuItem :item="item" group="modules" :class="search && index === 0 ? 'searched' : ''">
+                        <LeftMenuItem
+                            :item="item"
+                            group="modules"
+                            :class="search && index === 0 ? 'searched' : ''"
+                        >
                             <template #side>
                                 <QBtn
                                     v-if="item.isPinned === true"
@@ -342,7 +355,7 @@ const searchModule = () => {
 .header {
     color: var(--vn-label-color);
 }
-.searched{
+.searched {
     background-color: var(--vn-section-hover-color);
 }
 </style>
diff --git a/src/components/LeftMenuItem.vue b/src/components/LeftMenuItem.vue
index a3112b17f..c0cee44fe 100644
--- a/src/components/LeftMenuItem.vue
+++ b/src/components/LeftMenuItem.vue
@@ -26,6 +26,7 @@ const itemComputed = computed(() => {
         :to="{ name: itemComputed.name }"
         clickable
         v-ripple
+        :data-cy="`${itemComputed.name}-menu-item`"
     >
         <QItemSection avatar v-if="itemComputed.icon">
             <QIcon :name="itemComputed.icon" />
diff --git a/src/components/RefundInvoiceForm.vue b/src/components/RefundInvoiceForm.vue
index 590acede0..6dcb8b390 100644
--- a/src/components/RefundInvoiceForm.vue
+++ b/src/components/RefundInvoiceForm.vue
@@ -9,6 +9,7 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -131,15 +132,11 @@ const refund = async () => {
                         :required="true"
                     /> </VnRow
                 ><VnRow>
-                    <div>
-                        <QCheckbox
-                            :label="t('Inherit warehouse')"
-                            v-model="invoiceParams.inheritWarehouse"
-                        />
-                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                            <QTooltip>{{ t('Inherit warehouse tooltip') }}</QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="invoiceParams.inheritWarehouse"
+                        :label="t('Inherit warehouse')"
+                        :info="t('Inherit warehouse tooltip')"
+                    />
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue
index 934b13a1c..783f2556f 100644
--- a/src/components/TicketProblems.vue
+++ b/src/components/TicketProblems.vue
@@ -4,26 +4,21 @@ import { toCurrency } from 'src/filters';
 defineProps({ row: { type: Object, required: true } });
 </script>
 <template>
-    <span>
-        <QIcon
-            v-if="row.isTaxDataChecked === 0"
-            name="vn:no036"
-            color="primary"
-            size="xs"
+    <span class="q-gutter-x-xs">
+        <router-link
+            v-if="row.claim?.claimFk"
+            :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
+            class="link"
         >
-            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.hasTicketRequest" name="vn:buyrequest" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.itemShortage" name="vn:unavailable" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.isFreezed" name="vn:frozen" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
-        </QIcon>
+            <QIcon name="vn:claims" size="xs">
+                <QTooltip>
+                    {{ t('ticketSale.claim') }}:
+                    {{ row.claim?.claimFk }}
+                </QTooltip>
+            </QIcon>
+        </router-link>
         <QIcon
-            v-if="row.risk"
+            v-if="row?.risk"
             name="vn:risk"
             :color="row.hasHighRisk ? 'negative' : 'primary'"
             size="xs"
@@ -33,10 +28,57 @@ defineProps({ row: { type: Object, required: true } });
                 {{ toCurrency(row.risk - row.credit) }}
             </QTooltip>
         </QIcon>
-        <QIcon v-if="row.hasComponentLack" name="vn:components" color="primary" size="xs">
+        <QIcon
+            v-if="row?.hasComponentLack"
+            name="vn:components"
+            color="primary"
+            size="xs"
+        >
             <QTooltip>{{ $t('salesTicketsTable.componentLack') }}</QTooltip>
         </QIcon>
-        <QIcon v-if="row.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
+        <QIcon v-if="row?.hasItemDelay" color="primary" size="xs" name="vn:hasItemDelay">
+            <QTooltip>
+                {{ $t('ticket.summary.hasItemDelay') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.hasItemLost" color="primary" size="xs" name="vn:hasItemLost">
+            <QTooltip>
+                {{ $t('salesTicketsTable.hasItemLost') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.hasItemShortage"
+            name="vn:unavailable"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.hasRounding" color="primary" name="sync_problem" size="xs">
+            <QTooltip>
+                {{ $t('ticketList.rounding') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.hasTicketRequest"
+            name="vn:buyrequest"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.isTaxDataChecked !== 0"
+            name="vn:no036"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.isFreezed" name="vn:frozen" color="primary" size="xs">
+            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
             <QTooltip>{{ $t('salesTicketsTable.tooLittle') }}</QTooltip>
         </QIcon>
     </span>
diff --git a/src/components/TransferInvoiceForm.vue b/src/components/TransferInvoiceForm.vue
index aa71070d6..c4ef1454a 100644
--- a/src/components/TransferInvoiceForm.vue
+++ b/src/components/TransferInvoiceForm.vue
@@ -10,6 +10,7 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import VnCheckbox from './common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -186,15 +187,11 @@ const makeInvoice = async () => {
                     />
                 </VnRow>
                 <VnRow>
-                    <div>
-                        <QCheckbox
-                            :label="t('Bill destination client')"
-                            v-model="checked"
-                        />
-                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                            <QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="checked"
+                        :label="t('Bill destination client')"
+                        :info="t('transferInvoiceInfo')"
+                    />
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/VnTable/VnColumn.vue b/src/components/VnTable/VnColumn.vue
index 9e9bfad69..d0e245388 100644
--- a/src/components/VnTable/VnColumn.vue
+++ b/src/components/VnTable/VnColumn.vue
@@ -1,9 +1,8 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QIcon, QCheckbox } from 'quasar';
+import { QIcon, QToggle } from 'quasar';
 import { dashIfEmpty } from 'src/filters';
 
-/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnSelectCache from 'components/common/VnSelectCache.vue';
 import VnInput from 'components/common/VnInput.vue';
@@ -12,8 +11,11 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
 import VnComponent from 'components/common/VnComponent.vue';
 import VnUserLink from 'components/ui/VnUserLink.vue';
+import VnSelectEnum from '../common/VnSelectEnum.vue';
+import VnCheckbox from '../common/VnCheckbox.vue';
 
 const model = defineModel(undefined, { required: true });
+const emit = defineEmits(['blur']);
 const $props = defineProps({
     column: {
         type: Object,
@@ -39,10 +41,18 @@ const $props = defineProps({
         type: Object,
         default: null,
     },
+    autofocus: {
+        type: Boolean,
+        default: false,
+    },
     showLabel: {
         type: Boolean,
         default: null,
     },
+    eventHandlers: {
+        type: Object,
+        default: null,
+    },
 });
 
 const defaultSelect = {
@@ -99,7 +109,8 @@ const defaultComponents = {
         },
     },
     checkbox: {
-        component: markRaw(QCheckbox),
+        ref: 'checkbox',
+        component: markRaw(VnCheckbox),
         attrs: ({ model }) => {
             const defaultAttrs = {
                 disable: !$props.isEditable,
@@ -115,6 +126,10 @@ const defaultComponents = {
         },
         forceAttrs: {
             label: $props.showLabel && $props.column.label,
+            autofocus: true,
+        },
+        events: {
+            blur: () => emit('blur'),
         },
     },
     select: {
@@ -125,12 +140,19 @@ const defaultComponents = {
         component: markRaw(VnSelect),
         ...defaultSelect,
     },
+    selectEnum: {
+        component: markRaw(VnSelectEnum),
+        ...defaultSelect,
+    },
     icon: {
         component: markRaw(QIcon),
     },
     userLink: {
         component: markRaw(VnUserLink),
     },
+    toggle: {
+        component: markRaw(QToggle),
+    },
 };
 
 const value = computed(() => {
@@ -160,7 +182,28 @@ const col = computed(() => {
     return newColumn;
 });
 
-const components = computed(() => $props.components ?? defaultComponents);
+const components = computed(() => {
+    const sourceComponents = $props.components ?? defaultComponents;
+
+    return Object.keys(sourceComponents).reduce((acc, key) => {
+        const component = sourceComponents[key];
+
+        if (!component || typeof component !== 'object') {
+            acc[key] = component;
+            return acc;
+        }
+
+        acc[key] = {
+            ...component,
+            attrs: {
+                ...(component.attrs || {}),
+                autofocus: $props.autofocus,
+            },
+            event: { ...component?.event, ...$props?.eventHandlers },
+        };
+        return acc;
+    }, {});
+});
 </script>
 <template>
     <div class="row no-wrap">
diff --git a/src/components/VnTable/VnFilter.vue b/src/components/VnTable/VnFilter.vue
index 426f5c716..0de3834ea 100644
--- a/src/components/VnTable/VnFilter.vue
+++ b/src/components/VnTable/VnFilter.vue
@@ -1,14 +1,12 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QCheckbox } from 'quasar';
+import { QCheckbox, QToggle } from 'quasar';
 import { useArrayData } from 'composables/useArrayData';
-
-/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnInput from 'components/common/VnInput.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
-import VnTableColumn from 'components/VnTable/VnColumn.vue';
+import VnColumn from 'components/VnTable/VnColumn.vue';
 
 const $props = defineProps({
     column: {
@@ -27,6 +25,10 @@ const $props = defineProps({
         type: String,
         default: 'table',
     },
+    customClass: {
+        type: String,
+        default: '',
+    },
 });
 
 defineExpose({ addFilter, props: $props });
@@ -34,7 +36,7 @@ defineExpose({ addFilter, props: $props });
 const model = defineModel(undefined, { required: true });
 const arrayData = useArrayData(
     $props.dataKey,
-    $props.searchUrl ? { searchUrl: $props.searchUrl } : null
+    $props.searchUrl ? { searchUrl: $props.searchUrl } : null,
 );
 const columnFilter = computed(() => $props.column?.columnFilter);
 
@@ -46,19 +48,18 @@ const enterEvent = {
 
 const defaultAttrs = {
     filled: !$props.showTitle,
-    class: 'q-px-xs q-pb-xs q-pt-none fit',
     dense: true,
 };
 
 const forceAttrs = {
-    label: $props.showTitle ? '' : columnFilter.value?.label ?? $props.column.label,
+    label: $props.showTitle ? '' : (columnFilter.value?.label ?? $props.column.label),
 };
 
 const selectComponent = {
     component: markRaw(VnSelect),
     event: updateEvent,
     attrs: {
-        class: 'q-px-sm q-pb-xs q-pt-none fit',
+        class: `q-pt-none fit ${$props.customClass}`,
         dense: true,
         filled: !$props.showTitle,
     },
@@ -109,14 +110,24 @@ const components = {
         component: markRaw(QCheckbox),
         event: updateEvent,
         attrs: {
-            dense: true,
-            class: $props.showTitle ? 'q-py-sm q-mt-md' : 'q-px-md q-py-xs fit',
+            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
             'toggle-indeterminate': true,
+            size: 'sm',
         },
         forceAttrs,
     },
     select: selectComponent,
     rawSelect: selectComponent,
+    toggle: {
+        component: markRaw(QToggle),
+        event: updateEvent,
+        attrs: {
+            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
+            'toggle-indeterminate': true,
+            size: 'sm',
+        },
+        forceAttrs,
+    },
 };
 
 async function addFilter(value, name) {
@@ -132,19 +143,8 @@ async function addFilter(value, name) {
     await arrayData.addFilter({ params: { [field]: value } });
 }
 
-function alignRow() {
-    switch ($props.column.align) {
-        case 'left':
-            return 'justify-start items-start';
-        case 'right':
-            return 'justify-end items-end';
-        default:
-            return 'flex-center';
-    }
-}
-
 const showFilter = computed(
-    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions'
+    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions',
 );
 
 const onTabPressed = async () => {
@@ -152,13 +152,8 @@ const onTabPressed = async () => {
 };
 </script>
 <template>
-    <div
-        v-if="showFilter"
-        class="full-width"
-        :class="alignRow()"
-        style="max-height: 45px; overflow: hidden"
-    >
-        <VnTableColumn
+    <div v-if="showFilter" class="full-width" style="overflow: hidden">
+        <VnColumn
             :column="$props.column"
             default="input"
             v-model="model"
@@ -168,3 +163,8 @@ const onTabPressed = async () => {
         />
     </div>
 </template>
+<style lang="scss" scoped>
+label.vn-label-padding > .q-field__inner > .q-field__control {
+    padding: inherit !important;
+}
+</style>
diff --git a/src/components/VnTable/VnOrder.vue b/src/components/VnTable/VnOrder.vue
index 8ffdfe2bc..47ed9acf4 100644
--- a/src/components/VnTable/VnOrder.vue
+++ b/src/components/VnTable/VnOrder.vue
@@ -23,6 +23,10 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    align: {
+        type: String,
+        default: 'end',
+    },
 });
 const hover = ref();
 const arrayData = useArrayData($props.dataKey, { searchUrl: $props.searchUrl });
@@ -41,55 +45,78 @@ async function orderBy(name, direction) {
             break;
     }
     if (!direction) return await arrayData.deleteOrder(name);
+
     await arrayData.addOrder(name, direction);
 }
 
 defineExpose({ orderBy });
+
+function textAlignToFlex(textAlign) {
+    return `justify-content: ${
+        {
+            'text-center': 'center',
+            'text-left': 'start',
+            'text-right': 'end',
+        }[textAlign] || 'start'
+    };`;
+}
 </script>
 <template>
     <div
         @mouseenter="hover = true"
         @mouseleave="hover = false"
         @click="orderBy(name, model?.direction)"
-        class="row items-center no-wrap cursor-pointer"
+        class="items-center no-wrap cursor-pointer title"
+        :style="textAlignToFlex(align)"
     >
         <span :title="label">{{ label }}</span>
-        <QChip
-            v-if="name"
-            :label="!vertical ? model?.index : ''"
-            :icon="
-                (model?.index || hover) && !vertical
-                    ? model?.direction == 'DESC'
-                        ? 'arrow_downward'
-                        : 'arrow_upward'
-                    : undefined
-            "
-            :size="vertical ? '' : 'sm'"
-            :class="[
-                model?.index ? 'color-vn-text' : 'bg-transparent',
-                vertical ? 'q-px-none' : '',
-            ]"
-            class="no-box-shadow"
-            :clickable="true"
-            style="min-width: 40px"
-        >
-            <div
-                class="column flex-center"
-                v-if="vertical"
-                :style="!model?.index && 'color: #5d5d5d'"
+        <div v-if="name && model?.index">
+            <QChip
+                :label="!vertical ? model?.index : ''"
+                :icon="
+                    (model?.index || hover) && !vertical
+                        ? model?.direction == 'DESC'
+                            ? 'arrow_downward'
+                            : 'arrow_upward'
+                        : undefined
+                "
+                :size="vertical ? '' : 'sm'"
+                :class="[
+                    model?.index ? 'color-vn-text' : 'bg-transparent',
+                    vertical ? 'q-px-none' : '',
+                ]"
+                class="no-box-shadow"
+                :clickable="true"
+                style="min-width: 40px; max-height: 30px"
             >
-                {{ model?.index }}
-                <QIcon
-                    :name="
-                        model?.index
-                            ? model?.direction == 'DESC'
-                                ? 'arrow_downward'
-                                : 'arrow_upward'
-                            : 'swap_vert'
-                    "
-                    size="xs"
-                />
-            </div>
-        </QChip>
+                <div
+                    class="column flex-center"
+                    v-if="vertical"
+                    :style="!model?.index && 'color: #5d5d5d'"
+                >
+                    {{ model?.index }}
+                    <QIcon
+                        :name="
+                            model?.index
+                                ? model?.direction == 'DESC'
+                                    ? 'arrow_downward'
+                                    : 'arrow_upward'
+                                : 'swap_vert'
+                        "
+                        size="xs"
+                    />
+                </div>
+            </QChip>
+        </div>
     </div>
 </template>
+<style lang="scss" scoped>
+.title {
+    display: flex;
+    align-items: center;
+    height: 30px;
+    width: 100%;
+    color: var(--vn-label-color);
+    white-space: nowrap;
+}
+</style>
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 6e5f9fef4..7ff56860f 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -1,22 +1,38 @@
 <script setup>
-import { ref, onBeforeMount, onMounted, computed, watch, useAttrs } from 'vue';
+import {
+    ref,
+    onBeforeMount,
+    onMounted,
+    onUnmounted,
+    computed,
+    watch,
+    h,
+    render,
+    inject,
+    useAttrs,
+    nextTick,
+} from 'vue';
+import { useArrayData } from 'src/composables/useArrayData';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
-import { useQuasar } from 'quasar';
+import { useQuasar, date } from 'quasar';
 import { useStateStore } from 'stores/useStateStore';
 import { useFilterParams } from 'src/composables/useFilterParams';
+import { dashIfEmpty, toDate } from 'src/filters';
 
 import CrudModel from 'src/components/CrudModel.vue';
 import FormModelPopup from 'components/FormModelPopup.vue';
 
-import VnTableColumn from 'components/VnTable/VnColumn.vue';
+import VnColumn from 'components/VnTable/VnColumn.vue';
 import VnFilter from 'components/VnTable/VnFilter.vue';
 import VnTableChip from 'components/VnTable/VnChip.vue';
 import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
 import VnTableFilter from './VnTableFilter.vue';
+import { getColAlign } from 'src/composables/getColAlign';
 
+const arrayData = useArrayData(useAttrs()['data-key']);
 const $props = defineProps({
     columns: {
         type: Array,
@@ -42,10 +58,6 @@ const $props = defineProps({
         type: [Function, Boolean],
         default: null,
     },
-    rowCtrlClick: {
-        type: [Function, Boolean],
-        default: null,
-    },
     redirect: {
         type: String,
         default: null,
@@ -114,7 +126,19 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    withFilters: {
+        type: Boolean,
+        default: true,
+    },
+    overlay: {
+        type: Boolean,
+        default: false,
+    },
+    createComplement: {
+        type: Object,
+    },
 });
+
 const { t } = useI18n();
 const stateStore = useStateStore();
 const route = useRoute();
@@ -132,10 +156,18 @@ const showForm = ref(false);
 const splittedColumns = ref({ columns: [] });
 const columnsVisibilitySkipped = ref();
 const createForm = ref();
+const createRef = ref(null);
 const tableRef = ref();
 const params = ref(useFilterParams($attrs['data-key']).params);
 const orders = ref(useFilterParams($attrs['data-key']).orders);
+const app = inject('app');
 
+const editingRow = ref(null);
+const editingField = ref(null);
+const isTableMode = computed(() => mode.value == TABLE_MODE);
+const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
+const selectRegex = /select/;
+const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
 const tableModes = [
     {
         icon: 'view_column',
@@ -156,7 +188,8 @@ onBeforeMount(() => {
     hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
 });
 
-onMounted(() => {
+onMounted(async () => {
+    if ($props.isEditable) document.addEventListener('click', clickHandler);
     mode.value =
         quasar.platform.is.mobile && !$props.disableOption?.card
             ? CARD_MODE
@@ -178,14 +211,25 @@ onMounted(() => {
     }
 });
 
+onUnmounted(async () => {
+    if ($props.isEditable) document.removeEventListener('click', clickHandler);
+});
+
 watch(
     () => $props.columns,
     (value) => splitColumns(value),
     { immediate: true },
 );
 
-const isTableMode = computed(() => mode.value == TABLE_MODE);
-const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
+defineExpose({
+    create: createForm,
+    reload,
+    redirect: redirectFn,
+    selected,
+    CrudModelRef,
+    params,
+    tableRef,
+});
 
 function splitColumns(columns) {
     splittedColumns.value = {
@@ -231,16 +275,6 @@ const rowClickFunction = computed(() => {
     return () => {};
 });
 
-const rowCtrlClickFunction = computed(() => {
-    if ($props.rowCtrlClick != undefined) return $props.rowCtrlClick;
-    if ($props.redirect)
-        return (evt, { id }) => {
-            stopEventPropagation(evt);
-            window.open(`/#/${$props.redirect}/${id}`, '_blank');
-        };
-    return () => {};
-});
-
 function redirectFn(id) {
     router.push({ path: `/${$props.redirect}/${id}` });
 }
@@ -262,21 +296,6 @@ function columnName(col) {
     return name;
 }
 
-function getColAlign(col) {
-    return 'text-' + (col.align ?? 'left');
-}
-
-const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
-defineExpose({
-    create: createForm,
-    reload,
-    redirect: redirectFn,
-    selected,
-    CrudModelRef,
-    params,
-    tableRef,
-});
-
 function handleOnDataSaved(_) {
     if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
     else $props.create.onDataSaved(_);
@@ -305,6 +324,237 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
     }
 }
 
+function isEditableColumn(column) {
+    const isEditableCol = column?.isEditable ?? true;
+    const isVisible = column?.visible ?? true;
+    const hasComponent = column?.component;
+
+    return $props.isEditable && isVisible && hasComponent && isEditableCol;
+}
+
+function hasEditableFormat(column) {
+    if (isEditableColumn(column)) return 'editable-text';
+}
+
+const clickHandler = async (event) => {
+    const clickedElement = event.target.closest('td');
+
+    const isDateElement = event.target.closest('.q-date');
+    const isTimeElement = event.target.closest('.q-time');
+    const isQselectDropDown = event.target.closest('.q-select__dropdown-icon');
+
+    if (isDateElement || isTimeElement || isQselectDropDown) return;
+
+    if (clickedElement === null) {
+        await destroyInput(editingRow.value, editingField.value);
+        return;
+    }
+    const rowIndex = clickedElement.getAttribute('data-row-index');
+    const colField = clickedElement.getAttribute('data-col-field');
+    const column = $props.columns.find((col) => col.name === colField);
+
+    if (editingRow.value !== null && editingField.value !== null) {
+        if (editingRow.value == rowIndex && editingField.value == colField) return;
+
+        await destroyInput(editingRow.value, editingField.value);
+    }
+
+    if (isEditableColumn(column)) {
+        await renderInput(Number(rowIndex), colField, clickedElement);
+    }
+};
+
+async function handleTabKey(event, rowIndex, colField) {
+    if (editingRow.value == rowIndex && editingField.value == colField)
+        await destroyInput(editingRow.value, editingField.value);
+
+    const direction = event.shiftKey ? -1 : 1;
+    const { nextRowIndex, nextColumnName } = await handleTabNavigation(
+        rowIndex,
+        colField,
+        direction,
+    );
+
+    if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return;
+
+    event.preventDefault();
+    await renderInput(nextRowIndex, nextColumnName, null);
+}
+
+async function renderInput(rowId, field, clickedElement) {
+    editingField.value = field;
+    editingRow.value = rowId;
+
+    const originalColumn = $props.columns.find((col) => col.name === field);
+    const column = { ...originalColumn, ...{ label: '' } };
+    const row = CrudModelRef.value.formData[rowId];
+    const oldValue = CrudModelRef.value.formData[rowId][column?.name];
+
+    if (!clickedElement)
+        clickedElement = document.querySelector(
+            `[data-row-index="${rowId}"][data-col-field="${field}"]`,
+        );
+
+    Array.from(clickedElement.childNodes).forEach((child) => {
+        child.style.visibility = 'hidden';
+        child.style.position = 'relative';
+    });
+
+    const isSelect = selectRegex.test(column?.component);
+    if (isSelect) column.attrs = { ...column.attrs, 'emit-value': false };
+
+    const node = h(VnColumn, {
+        row: row,
+        class: 'temp-input',
+        column: column,
+        modelValue: row[column.name],
+        componentProp: 'columnField',
+        autofocus: true,
+        focusOnMount: true,
+        eventHandlers: {
+            'update:modelValue': async (value) => {
+                if (isSelect && value) {
+                    row[column.name] = value[column.attrs?.optionValue ?? 'id'];
+                    row[column?.name + 'TextValue'] =
+                        value[column.attrs?.optionLabel ?? 'name'];
+                    await column?.cellEvent?.['update:modelValue']?.(
+                        value,
+                        oldValue,
+                        row,
+                    );
+                } else row[column.name] = value;
+                await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
+            },
+            keyup: async (event) => {
+                if (event.key === 'Enter')
+                    await destroyInput(rowIndex, field, clickedElement);
+            },
+            keydown: async (event) => {
+                switch (event.key) {
+                    case 'Tab':
+                        await handleTabKey(event, rowId, field);
+                        event.stopPropagation();
+                        break;
+                    case 'Escape':
+                        await destroyInput(rowId, field, clickedElement);
+                        break;
+                    default:
+                        break;
+                }
+            },
+            click: (event) => {
+                column?.cellEvent?.['click']?.(event, row);
+            },
+        },
+    });
+
+    node.appContext = app._context;
+    render(node, clickedElement);
+
+    if (['toggle'].includes(column?.component))
+        node.el?.querySelector('span > div').focus();
+
+    if (['checkbox', undefined].includes(column?.component))
+        node.el?.querySelector('span > div > div').focus();
+}
+
+async function destroyInput(rowIndex, field, clickedElement) {
+    if (!clickedElement)
+        clickedElement = document.querySelector(
+            `[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
+        );
+    if (clickedElement) {
+        await nextTick();
+        render(null, clickedElement);
+        Array.from(clickedElement.childNodes).forEach((child) => {
+            child.style.visibility = 'visible';
+            child.style.position = '';
+        });
+    }
+    if (editingRow.value !== rowIndex || editingField.value !== field) return;
+    editingRow.value = null;
+    editingField.value = null;
+}
+
+async function handleTabNavigation(rowIndex, colName, direction) {
+    const columns = $props.columns;
+    const totalColumns = columns.length;
+    let currentColumnIndex = columns.findIndex((col) => col.name === colName);
+
+    let iterations = 0;
+    let newColumnIndex = currentColumnIndex;
+
+    do {
+        iterations++;
+        newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns;
+
+        if (isEditableColumn(columns[newColumnIndex])) break;
+    } while (iterations < totalColumns);
+
+    if (iterations >= totalColumns + 1) return;
+
+    if (direction === 1 && newColumnIndex <= currentColumnIndex) {
+        rowIndex++;
+    } else if (direction === -1 && newColumnIndex >= currentColumnIndex) {
+        rowIndex--;
+    }
+    return { nextRowIndex: rowIndex, nextColumnName: columns[newColumnIndex].name };
+}
+
+function getCheckboxIcon(value) {
+    switch (typeof value) {
+        case 'boolean':
+            return value ? 'check' : 'close';
+        case 'number':
+            return value === 0 ? 'close' : 'check';
+        case 'undefined':
+            return 'indeterminate_check_box';
+        default:
+            return 'indeterminate_check_box';
+    }
+}
+
+function getToggleIcon(value) {
+    if (value === null) return 'help_outline';
+    return value ? 'toggle_on' : 'toggle_off';
+}
+
+function formatColumnValue(col, row, dashIfEmpty) {
+    if (col?.format || row[col?.name + 'TextValue']) {
+        if (selectRegex.test(col?.component) && row[col?.name + 'TextValue']) {
+            return dashIfEmpty(row[col?.name + 'TextValue']);
+        } else {
+            return col.format(row, dashIfEmpty);
+        }
+    }
+
+    if (col?.component === 'date') return dashIfEmpty(toDate(row[col?.name]));
+
+    if (col?.component === 'time')
+        return row[col?.name] >= 5
+            ? dashIfEmpty(date.formatDate(new Date(row[col?.name]), 'HH:mm'))
+            : row[col?.name];
+
+    if (selectRegex.test(col?.component) && $props.isEditable) {
+        const { find, url } = col.attrs;
+        const urlRelation = url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
+
+        if (col?.attrs.options) {
+            const find = col?.attrs.options.find((option) => option.id === row[col.name]);
+            if (!col.attrs?.optionLabel || !find) return dashIfEmpty(row[col?.name]);
+            return dashIfEmpty(find[col.attrs?.optionLabel ?? 'name']);
+        }
+
+        if (typeof row[urlRelation] == 'object') {
+            if (typeof find == 'object')
+                return dashIfEmpty(row[urlRelation][find?.label ?? 'name']);
+
+            return dashIfEmpty(row[urlRelation][col?.attrs.optionLabel ?? 'name']);
+        }
+        if (typeof row[urlRelation] == 'string') return dashIfEmpty(row[urlRelation]);
+    }
+    return dashIfEmpty(row[col?.name]);
+}
 function cardClick(_, row) {
     if ($props.redirect) router.push({ path: `/${$props.redirect}/${row.id}` });
 }
@@ -315,7 +565,7 @@ function cardClick(_, row) {
         v-model="stateStore.rightDrawer"
         side="right"
         :width="256"
-        show-if-above
+        :overlay="$props.overlay"
     >
         <QScrollArea class="fit">
             <VnTableFilter
@@ -336,7 +586,7 @@ function cardClick(_, row) {
     <CrudModel
         v-bind="$attrs"
         :class="$attrs['class'] ?? 'q-px-md'"
-        :limit="$attrs['limit'] ?? 20"
+        :limit="$attrs['limit'] ?? 100"
         ref="CrudModelRef"
         @on-fetch="(...args) => emit('onFetch', ...args)"
         :search-url="searchUrl"
@@ -352,8 +602,12 @@ function cardClick(_, row) {
             <QTable
                 ref="tableRef"
                 v-bind="table"
-                class="vnTable"
-                :class="{ 'last-row-sticky': $props.footer }"
+                :class="[
+                    'vnTable',
+                    table ? 'selection-cell' : '',
+                    $props.footer ? 'last-row-sticky' : '',
+                ]"
+                wrap-cells
                 :columns="splittedColumns.columns"
                 :rows="rows"
                 v-model:selected="selected"
@@ -367,11 +621,13 @@ function cardClick(_, row) {
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
                 @update:selected="emit('update:selected', $event)"
                 @selection="(details) => handleSelection(details, rows)"
+                :hide-selected-banner="true"
             >
                 <template #top-left v-if="!$props.withoutHeader">
-                    <slot name="top-left"></slot>
+                    <slot name="top-left"> </slot>
                 </template>
                 <template #top-right v-if="!$props.withoutHeader">
+                    <slot name="top-right"></slot>
                     <VnVisibleColumn
                         v-if="isTableMode"
                         v-model="splittedColumns.columns"
@@ -385,6 +641,7 @@ function cardClick(_, row) {
                         dense
                         :options="tableModes.filter((mode) => !mode.disable)"
                     />
+
                     <QBtn
                         v-if="showRightIcon"
                         icon="filter_alt"
@@ -396,32 +653,39 @@ function cardClick(_, row) {
                 <template #header-cell="{ col }">
                     <QTh
                         v-if="col.visible ?? true"
-                        :style="col.headerStyle"
-                        :class="col.headerClass"
+                        v-bind:class="col.headerClass"
+                        class="body-cell"
+                        :style="col?.width ? `max-width: ${col?.width}` : ''"
                     >
                         <div
-                            class="column ellipsis"
-                            :class="`text-${col?.align ?? 'left'}`"
-                            :style="$props.columnSearch ? 'height: 75px' : ''"
+                            class="no-padding"
+                            :style="[
+                                withFilters && $props.columnSearch ? 'height: 75px' : '',
+                            ]"
                         >
-                            <div class="row items-center no-wrap" style="height: 30px">
+                            <div style="height: 30px">
                                 <QTooltip v-if="col.toolTip">{{ col.toolTip }}</QTooltip>
                                 <VnTableOrder
                                     v-model="orders[col.orderBy ?? col.name]"
                                     :name="col.orderBy ?? col.name"
-                                    :label="col?.label"
+                                    :label="col?.labelAbbreviation ?? col?.label"
                                     :data-key="$attrs['data-key']"
                                     :search-url="searchUrl"
+                                    :align="getColAlign(col)"
                                 />
                             </div>
                             <VnFilter
-                                v-if="$props.columnSearch"
+                                v-if="
+                                    $props.columnSearch &&
+                                    col.columnSearch !== false &&
+                                    withFilters
+                                "
                                 :column="col"
                                 :show-title="true"
                                 :data-key="$attrs['data-key']"
                                 v-model="params[columnName(col)]"
                                 :search-url="searchUrl"
-                                class="full-width"
+                                customClass="header-filter"
                             />
                         </div>
                     </QTh>
@@ -439,32 +703,67 @@ function cardClick(_, row) {
                     </QTd>
                 </template>
                 <template #body-cell="{ col, row, rowIndex }">
-                    <!-- Columns -->
                     <QTd
-                        auto-width
-                        class="no-margin"
-                        :class="[getColAlign(col), col.columnClass]"
-                        :style="col.style"
+                        class="no-margin q-px-xs"
                         v-if="col.visible ?? true"
-                        @click.ctrl="
-                            ($event) =>
-                                rowCtrlClickFunction && rowCtrlClickFunction($event, row)
-                        "
+                        :style="{
+                            'max-width': col?.width ?? false,
+                            position: 'relative',
+                        }"
+                        :class="[
+                            col.columnClass,
+                            'body-cell no-margin no-padding',
+                            getColAlign(col),
+                        ]"
+                        :data-row-index="rowIndex"
+                        :data-col-field="col?.name"
                     >
-                        <slot
-                            :name="`column-${col.name}`"
-                            :col="col"
-                            :row="row"
-                            :row-index="rowIndex"
+                        <div
+                            class="no-padding no-margin peter"
+                            style="
+                                overflow: hidden;
+                                text-overflow: ellipsis;
+                                white-space: nowrap;
+                            "
                         >
-                            <VnTableColumn
-                                :column="col"
+                            <slot
+                                :name="`column-${col.name}`"
+                                :col="col"
                                 :row="row"
-                                :is-editable="col.isEditable ?? isEditable"
-                                v-model="row[col.name]"
-                                component-prop="columnField"
-                            />
-                        </slot>
+                                :row-index="rowIndex"
+                            >
+                                <QIcon
+                                    v-if="col?.component === 'toggle'"
+                                    :name="
+                                        col?.getIcon
+                                            ? col.getIcon(row[col?.name])
+                                            : getToggleIcon(row[col?.name])
+                                    "
+                                    style="color: var(--vn-text-color)"
+                                    :class="hasEditableFormat(col)"
+                                    size="14px"
+                                />
+                                <QIcon
+                                    v-else-if="col?.component === 'checkbox'"
+                                    :name="getCheckboxIcon(row[col?.name])"
+                                    style="color: var(--vn-text-color)"
+                                    :class="hasEditableFormat(col)"
+                                    size="14px"
+                                />
+                                <span
+                                    v-else
+                                    :class="hasEditableFormat(col)"
+                                    :style="
+                                        typeof col?.style == 'function'
+                                            ? col.style(row)
+                                            : col?.style
+                                    "
+                                    style="bottom: 0"
+                                >
+                                    {{ formatColumnValue(col, row, dashIfEmpty) }}
+                                </span>
+                            </slot>
+                        </div>
                     </QTd>
                 </template>
                 <template #body-cell-tableActions="{ col, row }">
@@ -485,7 +784,7 @@ function cardClick(_, row) {
                             flat
                             dense
                             :class="
-                                btn.isPrimary ? 'text-primary-light' : 'color-vn-text '
+                                btn.isPrimary ? 'text-primary-light' : 'color-vn-label'
                             "
                             :style="`visibility: ${
                                 ((btn.show && btn.show(row)) ?? true)
@@ -493,6 +792,7 @@ function cardClick(_, row) {
                                     : 'hidden'
                             }`"
                             @click="btn.action(row)"
+                            :data-cy="btn?.name ?? `tableAction-${index}`"
                         />
                     </QTd>
                 </template>
@@ -541,7 +841,7 @@ function cardClick(_, row) {
                                 </QCardSection>
                                 <!-- Fields -->
                                 <QCardSection
-                                    class="q-pl-sm q-pr-lg q-py-xs"
+                                    class="q-pl-sm q-py-xs"
                                     :class="$props.cardClass"
                                 >
                                     <div
@@ -562,7 +862,7 @@ function cardClick(_, row) {
                                                         :row="row"
                                                         :row-index="index"
                                                     >
-                                                        <VnTableColumn
+                                                        <VnColumn
                                                             :column="col"
                                                             :row="row"
                                                             :is-editable="false"
@@ -589,12 +889,12 @@ function cardClick(_, row) {
                                     :title="btn.title"
                                     :icon="btn.icon"
                                     class="q-pa-xs"
-                                    flat
                                     :class="
                                         btn.isPrimary
                                             ? 'text-primary-light'
-                                            : 'color-vn-text '
+                                            : 'color-vn-label'
                                     "
+                                    flat
                                     @click="btn.action(row)"
                                 />
                             </QCardSection>
@@ -602,14 +902,17 @@ function cardClick(_, row) {
                     </component>
                 </template>
                 <template #bottom-row="{ cols }" v-if="$props.footer">
-                    <QTr v-if="rows.length" style="height: 30px">
+                    <QTr v-if="rows.length" style="height: 45px">
+                        <QTh v-if="table.selection" />
                         <QTh
                             v-for="col of cols.filter((cols) => cols.visible ?? true)"
                             :key="col?.id"
-                            class="text-center"
                             :class="getColAlign(col)"
                         >
-                            <slot :name="`column-footer-${col.name}`" />
+                            <slot
+                                :name="`column-footer-${col.name}`"
+                                :isEditableColumn="isEditableColumn(col)"
+                            />
                         </QTh>
                     </QTr>
                 </template>
@@ -628,7 +931,7 @@ function cardClick(_, row) {
                     size="md"
                     round
                     flat
-                    shortcut="+"
+                    v-shortcut="'+'"
                     :disabled="!disabledAttr"
                 />
                 <QTooltip>
@@ -646,39 +949,52 @@ function cardClick(_, row) {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             data-cy="vnTableCreateBtn"
         />
         <QTooltip self="top right">
             {{ createForm?.title }}
         </QTooltip>
     </QPageSticky>
-    <QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
+    <QDialog
+        v-model="showForm"
+        transition-show="scale"
+        transition-hide="scale"
+        :full-width="createComplement?.isFullWidth ?? false"
+        data-cy="vn-table-create-dialog"
+    >
         <FormModelPopup
+            ref="createRef"
             v-bind="createForm"
             :model="$attrs['data-key'] + 'Create'"
             @on-data-saved="(_, res) => createForm.onDataSaved(res)"
         >
             <template #form-inputs="{ data }">
-                <div class="grid-create">
-                    <slot
-                        v-for="column of splittedColumns.create"
-                        :key="column.name"
-                        :name="`column-create-${column.name}`"
-                        :data="data"
-                        :column-name="column.name"
-                        :label="column.label"
-                    >
-                        <VnTableColumn
-                            :column="column"
-                            :row="{}"
-                            default="input"
-                            v-model="data[column.name]"
-                            :show-label="true"
-                            component-prop="columnCreate"
-                        />
-                    </slot>
-                    <slot name="more-create-dialog" :data="data" />
+                <div :style="createComplement?.containerStyle">
+                    <div>
+                        <slot name="previous-create-dialog" :data="data" />
+                    </div>
+                    <div class="grid-create" :style="createComplement?.columnGridStyle">
+                        <slot
+                            v-for="column of splittedColumns.create"
+                            :key="column.name"
+                            :name="`column-create-${column.name}`"
+                            :data="data"
+                            :column-name="column.name"
+                            :label="column.label"
+                        >
+                            <VnColumn
+                                :column="column"
+                                :row="{}"
+                                default="input"
+                                v-model="data[column.name]"
+                                :show-label="true"
+                                component-prop="columnCreate"
+                                :data-cy="`${column.name}-create-popup`"
+                            />
+                        </slot>
+                        <slot name="more-create-dialog" :data="data" />
+                    </div>
                 </div>
             </template>
         </FormModelPopup>
@@ -696,6 +1012,42 @@ es:
 </i18n>
 
 <style lang="scss">
+.selection-cell {
+    table td:first-child {
+        padding: 0px;
+    }
+}
+.side-padding {
+    padding-left: 1px;
+    padding-right: 1px;
+}
+.editable-text:hover {
+    border-bottom: 1px dashed var(--q-primary);
+    @extend .side-padding;
+}
+.editable-text {
+    border-bottom: 1px dashed var(--vn-label-color);
+    @extend .side-padding;
+}
+.cell-input {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding-top: 0px !important;
+}
+.q-field--labeled .q-field__native,
+.q-field--labeled .q-field__prefix,
+.q-field--labeled .q-field__suffix {
+    padding-top: 20px;
+}
+
+.body-cell {
+    padding-left: 4px !important;
+    padding-right: 4px !important;
+    position: relative;
+}
 .bg-chip-secondary {
     background-color: var(--vn-page-color);
     color: var(--vn-text-color);
@@ -712,8 +1064,8 @@ es:
 
 .grid-three {
     display: grid;
-    grid-template-columns: repeat(auto-fit, minmax(350px, max-content));
-    max-width: 100%;
+    grid-template-columns: repeat(auto-fit, minmax(300px, max-content));
+    width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -721,7 +1073,6 @@ es:
 .grid-create {
     display: grid;
     grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
-    max-width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -737,7 +1088,9 @@ es:
         }
     }
 }
-
+.q-table tbody tr td {
+    position: relative;
+}
 .q-table {
     th {
         padding: 0;
@@ -786,6 +1139,7 @@ es:
 .vn-label-value {
     display: flex;
     flex-direction: row;
+    align-items: center;
     color: var(--vn-text-color);
     .value {
         overflow: hidden;
@@ -837,4 +1191,15 @@ es:
 .q-table__middle.q-virtual-scroll.q-virtual-scroll--vertical.scroll {
     background-color: var(--vn-section-color);
 }
+.temp-input {
+    top: 0;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    display: flex;
+}
+
+label.header-filter > .q-field__inner > .q-field__control {
+    padding: inherit;
+}
 </style>
diff --git a/src/components/VnTable/VnTableFilter.vue b/src/components/VnTable/VnTableFilter.vue
index 732605ce5..79b903e54 100644
--- a/src/components/VnTable/VnTableFilter.vue
+++ b/src/components/VnTable/VnTableFilter.vue
@@ -27,31 +27,36 @@ function columnName(col) {
 </script>
 <template>
     <VnFilterPanel v-bind="$attrs" :search-button="true" :disable-submit-event="true">
-        <template #body="{ params, orders }">
+        <template #body="{ params, orders, searchFn }">
             <div
-                class="row no-wrap flex-center"
+                class="container"
                 v-for="col of columns.filter((c) => c.columnFilter ?? true)"
                 :key="col.id"
             >
-                <VnFilter
-                    ref="tableFilterRef"
-                    :column="col"
-                    :data-key="$attrs['data-key']"
-                    v-model="params[columnName(col)]"
-                    :search-url="searchUrl"
-                />
-                <VnTableOrder
-                    v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
-                    v-model="orders[col.orderBy ?? col.name]"
-                    :name="col.orderBy ?? col.name"
-                    :data-key="$attrs['data-key']"
-                    :search-url="searchUrl"
-                    :vertical="true"
-                />
+                <div class="filter">
+                    <VnFilter
+                        ref="tableFilterRef"
+                        :column="col"
+                        :data-key="$attrs['data-key']"
+                        v-model="params[columnName(col)]"
+                        :search-url="searchUrl"
+                    />
+                </div>
+                <div class="order">
+                    <VnTableOrder
+                        v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
+                        v-model="orders[col.orderBy ?? col.name]"
+                        :name="col.orderBy ?? col.name"
+                        :data-key="$attrs['data-key']"
+                        :search-url="searchUrl"
+                        :vertical="true"
+                    />
+                </div>
             </div>
             <slot
                 name="moreFilterPanel"
                 :params="params"
+                :search-fn="searchFn"
                 :orders="orders"
                 :columns="columns"
             />
@@ -67,3 +72,21 @@ function columnName(col) {
         </template>
     </VnFilterPanel>
 </template>
+<style lang="scss" scoped>
+.container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 45px;
+    gap: 10px;
+}
+
+.filter {
+    width: 70%;
+    height: 40px;
+    text-align: center;
+}
+.order {
+    width: 10%;
+}
+</style>
diff --git a/src/components/VnTable/VnVisibleColumn.vue b/src/components/VnTable/VnVisibleColumn.vue
index dad950d73..6d15c585e 100644
--- a/src/components/VnTable/VnVisibleColumn.vue
+++ b/src/components/VnTable/VnVisibleColumn.vue
@@ -32,16 +32,21 @@ const areAllChecksMarked = computed(() => {
 
 function setUserConfigViewData(data, isLocal) {
     if (!data) return;
-    // Importante: El name de las columnas de la tabla debe conincidir con el name de las variables que devuelve la view config
     if (!isLocal) localColumns.value = [];
-    // Array to Object
+
     const skippeds = $props.skip.reduce((a, v) => ({ ...a, [v]: v }), {});
 
     for (let column of columns.value) {
-        const { label, name } = column;
+        const { label, name, labelAbbreviation } = column;
         if (skippeds[name]) continue;
         column.visible = data[name] ?? true;
-        if (!isLocal) localColumns.value.push({ name, label, visible: column.visible });
+        if (!isLocal)
+            localColumns.value.push({
+                name,
+                label,
+                labelAbbreviation,
+                visible: column.visible,
+            });
     }
 }
 
@@ -152,7 +157,11 @@ onMounted(async () => {
                     <QCheckbox
                         v-for="col in localColumns"
                         :key="col.name"
-                        :label="col.label ?? col.name"
+                        :label="
+                            col?.labelAbbreviation
+                                ? col.labelAbbreviation + ` (${col.label ?? col.name})`
+                                : (col.label ?? col.name)
+                        "
                         v-model="col.visible"
                     />
                 </div>
diff --git a/src/components/__tests__/FormModel.spec.js b/src/components/__tests__/FormModel.spec.js
index e35684bc3..3dce04374 100644
--- a/src/components/__tests__/FormModel.spec.js
+++ b/src/components/__tests__/FormModel.spec.js
@@ -57,6 +57,7 @@ describe('FormModel', () => {
             vm.state.set(model, formInitialData);
             expect(vm.hasChanges).toBe(false);
 
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             expect(vm.hasChanges).toBe(true);
@@ -93,9 +94,13 @@ describe('FormModel', () => {
 
         it('should call axios.patch with the right data', async () => {
             const spy = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
-            const { vm } = mount({ propsData: { url, model, formInitialData } });
-            vm.formData.mockKey = 'newVal';
+            const { vm } = mount({ propsData: { url, model } });
+
+            vm.formData = {};
             await vm.$nextTick();
+            vm.formData = { mockKey: 'newVal' };
+            await vm.$nextTick();
+
             await vm.save();
             expect(spy).toHaveBeenCalled();
             vm.formData.mockKey = 'mockVal';
@@ -106,6 +111,7 @@ describe('FormModel', () => {
             const { vm } = mount({
                 propsData: { url, model, formInitialData, urlCreate: 'mockUrlCreate' },
             });
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
@@ -119,7 +125,7 @@ describe('FormModel', () => {
             });
             const spyPatch = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
             const spySaveFn = vi.spyOn(vm.$props, 'saveFn');
-
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
diff --git a/src/components/__tests__/Leftmenu.spec.js b/src/components/__tests__/Leftmenu.spec.js
index 10d9d66fb..4ab8b527f 100644
--- a/src/components/__tests__/Leftmenu.spec.js
+++ b/src/components/__tests__/Leftmenu.spec.js
@@ -1,9 +1,12 @@
-import { vi, describe, expect, it, beforeAll } from 'vitest';
+import { vi, describe, expect, it, beforeAll, beforeEach, afterEach } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import Leftmenu from 'components/LeftMenu.vue';
-
+import * as vueRouter from 'vue-router';
 import { useNavigationStore } from 'src/stores/useNavigationStore';
 
+let vm;
+let navigation;
+
 vi.mock('src/router/modules', () => ({
     default: [
         {
@@ -21,6 +24,16 @@ vi.mock('src/router/modules', () => ({
                 {
                     path: '',
                     name: 'CustomerMain',
+                    meta: {
+                        menu: 'Customer',
+                        menuChildren: [
+                            {
+                                name: 'CustomerCreditContracts',
+                                title: 'creditContracts',
+                                icon: 'vn:solunion',
+                            },
+                        ],
+                    },
                     children: [
                         {
                             path: 'list',
@@ -28,6 +41,13 @@ vi.mock('src/router/modules', () => ({
                             meta: {
                                 title: 'list',
                                 icon: 'view_list',
+                                menuChildren: [
+                                    {
+                                        name: 'CustomerCreditContracts',
+                                        title: 'creditContracts',
+                                        icon: 'vn:solunion',
+                                    },
+                                ],
                             },
                         },
                         {
@@ -44,51 +64,325 @@ vi.mock('src/router/modules', () => ({
         },
     ],
 }));
-
-describe('Leftmenu', () => {
-    let vm;
-    let navigation;
-    beforeAll(() => {
-        vi.spyOn(axios, 'get').mockResolvedValue({
-            data: [],
-        });
-
-        vm = createWrapper(Leftmenu, {
-            propsData: {
-                source: 'main',
+vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
+    matched: [
+        {
+            path: '/',
+            redirect: {
+                name: 'Dashboard',
             },
-        }).vm;
-
-        navigation = useNavigationStore();
-        navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
-        navigation.getModules = vi.fn().mockReturnValue({
-            value: [
+            name: 'Main',
+            meta: {},
+            props: {
+                default: false,
+            },
+            children: [
                 {
-                    name: 'customer',
-                    title: 'customer.pageTitles.customers',
-                    icon: 'vn:customer',
-                    module: 'customer',
+                    path: '/dashboard',
+                    name: 'Dashboard',
+                    meta: {
+                        title: 'dashboard',
+                        icon: 'dashboard',
+                    },
                 },
             ],
+        },
+        {
+            path: '/customer',
+            redirect: {
+                name: 'CustomerMain',
+            },
+            name: 'Customer',
+            meta: {
+                title: 'customers',
+                icon: 'vn:client',
+                moduleName: 'Customer',
+                keyBinding: 'c',
+                menu: 'customer',
+            },
+        },
+    ],
+    query: {},
+    params: {},
+    meta: { moduleName: 'mockName' },
+    path: 'mockName/1',
+    name: 'Customer',
+});
+function mount(source = 'main') {
+    vi.spyOn(axios, 'get').mockResolvedValue({
+        data: [],
+    });
+    const wrapper = createWrapper(Leftmenu, {
+        propsData: {
+            source,
+        },
+    });
+
+    navigation = useNavigationStore();
+    navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
+    navigation.getModules = vi.fn().mockReturnValue({
+        value: [
+            {
+                name: 'customer',
+                title: 'customer.pageTitles.customers',
+                icon: 'vn:customer',
+                module: 'customer',
+            },
+        ],
+    });
+    return wrapper;
+}
+
+describe('getRoutes', () => {
+    afterEach(() => vi.clearAllMocks());
+    const getRoutes = vi.fn().mockImplementation((props, getMethodA, getMethodB) => {
+        const handleRoutes = {
+            methodA: getMethodA,
+            methodB: getMethodB,
+        };
+        try {
+            handleRoutes[props.source]();
+        } catch (error) {
+            throw Error('Method not defined');
+        }
+    });
+
+    const getMethodA = vi.fn();
+    const getMethodB = vi.fn();
+    const fn = (props) => getRoutes(props, getMethodA, getMethodB);
+
+    it('should call getMethodB when source is card', () => {
+        let props = { source: 'methodB' };
+        fn(props);
+
+        expect(getMethodB).toHaveBeenCalled();
+        expect(getMethodA).not.toHaveBeenCalled();
+    });
+    it('should call getMethodA when source is main', () => {
+        let props = { source: 'methodA' };
+        fn(props);
+
+        expect(getMethodA).toHaveBeenCalled();
+        expect(getMethodB).not.toHaveBeenCalled();
+    });
+
+    it('should call getMethodA when source is not exists or undefined', () => {
+        let props = { source: 'methodC' };
+        expect(() => fn(props)).toThrowError('Method not defined');
+
+        expect(getMethodA).not.toHaveBeenCalled();
+        expect(getMethodB).not.toHaveBeenCalled();
+    });
+});
+
+describe('Leftmenu as card', () => {
+    beforeAll(() => {
+        vm = mount('card').vm;
+    });
+
+    it('should get routes for card source', async () => {
+        vm.getRoutes();
+    });
+});
+describe('Leftmenu as main', () => {
+    beforeEach(() => {
+        vm = mount().vm;
+    });
+
+    it('should initialize with default props', () => {
+        expect(vm.source).toBe('main');
+    });
+
+    it('should filter items based on search input', async () => {
+        vm.search = 'cust';
+        await vm.$nextTick();
+        expect(vm.filteredItems[0].name).toEqual('customer');
+        expect(vm.filteredItems[0].module).toEqual('customer');
+    });
+    it('should filter items based on search input', async () => {
+        vm.search = 'Rou';
+        await vm.$nextTick();
+        expect(vm.filteredItems).toEqual([]);
+    });
+
+    it('should return pinned items', () => {
+        vm.items = [
+            { name: 'Item 1', isPinned: false },
+            { name: 'Item 2', isPinned: true },
+        ];
+        expect(vm.pinnedModules).toEqual(
+            new Map([['Item 2', { name: 'Item 2', isPinned: true }]]),
+        );
+    });
+
+    it('should find matches in routes', () => {
+        const search = 'child1';
+        const item = {
+            children: [
+                { name: 'child1', children: [] },
+                { name: 'child2', children: [] },
+            ],
+        };
+        const matches = vm.findMatches(search, item);
+        expect(matches).toEqual([{ name: 'child1', children: [] }]);
+    });
+    it('should not proceed if event is already prevented', async () => {
+        const item = { module: 'testModule', isPinned: false };
+        const event = {
+            preventDefault: vi.fn(),
+            stopPropagation: vi.fn(),
+            defaultPrevented: true,
+        };
+
+        await vm.togglePinned(item, event);
+
+        expect(event.preventDefault).not.toHaveBeenCalled();
+        expect(event.stopPropagation).not.toHaveBeenCalled();
+    });
+
+    it('should call quasar.notify with success message', async () => {
+        const item = { module: 'testModule', isPinned: false };
+        const event = {
+            preventDefault: vi.fn(),
+            stopPropagation: vi.fn(),
+            defaultPrevented: false,
+        };
+        const response = { data: { id: 1 } };
+
+        vi.spyOn(axios, 'post').mockResolvedValue(response);
+        vi.spyOn(vm.quasar, 'notify');
+
+        await vm.togglePinned(item, event);
+
+        expect(vm.quasar.notify).toHaveBeenCalledWith({
+            message: 'Data saved',
+            type: 'positive',
         });
     });
 
-    it('should return a proper formated object with two child items', async () => {
-        const expectedMenuItem = [
-            {
-                children: null,
-                name: 'CustomerList',
-                title: 'globals.pageTitles.list',
-                icon: 'view_list',
-            },
-            {
-                children: null,
-                name: 'CustomerCreate',
-                title: 'globals.pageTitles.createCustomer',
-                icon: 'vn:addperson',
-            },
-        ];
-        const firstMenuItem = vm.items[0];
-        expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
+    it('should handle a single matched route with a menu', () => {
+        const route = {
+            matched: [{ meta: { menu: 'customer' } }],
+        };
+
+        const result = vm.betaGetRoutes();
+
+        expect(result.meta.menu).toEqual(route.matched[0].meta.menu);
+    });
+    it('should get routes for main source', () => {
+        vm.props.source = 'main';
+        vm.getRoutes();
+        expect(navigation.getModules).toHaveBeenCalled();
+    });
+
+    it('should find direct child matches', () => {
+        const search = 'child1';
+        const item = {
+            children: [{ name: 'child1' }, { name: 'child2' }],
+        };
+        const result = vm.findMatches(search, item);
+        expect(result).toEqual([{ name: 'child1' }]);
+    });
+
+    it('should find nested child matches', () => {
+        const search = 'child3';
+        const item = {
+            children: [
+                { name: 'child1' },
+                {
+                    name: 'child2',
+                    children: [{ name: 'child3' }],
+                },
+            ],
+        };
+        const result = vm.findMatches(search, item);
+        expect(result).toEqual([{ name: 'child3' }]);
+    });
+});
+
+describe('normalize', () => {
+    beforeAll(() => {
+        vm = mount('card').vm;
+    });
+    it('should normalize and lowercase text', () => {
+        const input = 'ÁÉÍÓÚáéíóú';
+        const expected = 'aeiouaeiou';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle empty string', () => {
+        const input = '';
+        const expected = '';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle text without diacritics', () => {
+        const input = 'hello';
+        const expected = 'hello';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle mixed text', () => {
+        const input = 'Héllo Wórld!';
+        const expected = 'hello world!';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+});
+
+describe('addChildren', () => {
+    const module = 'testModule';
+    beforeEach(() => {
+        vm = mount().vm;
+        vi.clearAllMocks();
+    });
+
+    it('should add menu items to parent if matches are found', () => {
+        const parent = 'testParent';
+        const route = {
+            meta: {
+                menu: 'testMenu',
+            },
+            children: [{ name: 'child1' }, { name: 'child2' }],
+        };
+        vm.addChildren(module, route, parent);
+
+        expect(navigation.addMenuItem).toHaveBeenCalled();
+    });
+
+    it('should handle routes with no meta menu', () => {
+        const route = {
+            meta: {},
+            menus: {},
+        };
+
+        const parent = [];
+
+        vm.addChildren(module, route, parent);
+        expect(navigation.addMenuItem).toHaveBeenCalled();
+    });
+
+    it('should handle empty parent array', () => {
+        const parent = [];
+        const route = {
+            meta: {
+                menu: 'child11',
+            },
+            children: [
+                {
+                    name: 'child1',
+                    meta: {
+                        menuChildren: [
+                            {
+                                name: 'CustomerCreditContracts',
+                                title: 'creditContracts',
+                                icon: 'vn:solunion',
+                            },
+                        ],
+                    },
+                },
+            ],
+        };
+        vm.addChildren(module, route, parent);
+        expect(navigation.addMenuItem).toHaveBeenCalled();
     });
 });
diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js
index ac20f911e..9e449745a 100644
--- a/src/components/__tests__/UserPanel.spec.js
+++ b/src/components/__tests__/UserPanel.spec.js
@@ -1,61 +1,65 @@
-import { vi, describe, expect, it, beforeEach, beforeAll, afterEach } from 'vitest';
+import { vi, describe, expect, it, beforeEach, afterEach } from 'vitest';
 import { createWrapper } from 'app/test/vitest/helper';
 import UserPanel from 'src/components/UserPanel.vue';
 import axios from 'axios';
 import { useState } from 'src/composables/useState';
 
+vi.mock('src/utils/quasarLang', () => ({
+  default: vi.fn(),
+}));
+
 describe('UserPanel', () => {
-    let wrapper;
-    let vm;
-    let state;
+  let wrapper;
+  let vm;
+  let state;
 
-    beforeEach(() => {
-        wrapper = createWrapper(UserPanel, {});
-        state = useState();
-        state.setUser({
-            id: 115,
-            name: 'itmanagement',
-            nickname: 'itManagementNick',
-            lang: 'en',
-            darkMode: false,
-            companyFk: 442,
-            warehouseFk: 1,
-        });
-        wrapper = wrapper.wrapper;
-        vm = wrapper.vm;
+  beforeEach(() => {
+    wrapper = createWrapper(UserPanel, {});
+    state = useState();
+    state.setUser({
+      id: 115,
+      name: 'itmanagement',
+      nickname: 'itManagementNick',
+      lang: 'en',
+      darkMode: false,
+      companyFk: 442,
+      warehouseFk: 1,
     });
+    wrapper = wrapper.wrapper;
+    vm = wrapper.vm;
+  });
 
-    afterEach(() => {
-        vi.clearAllMocks();
-    });
+  afterEach(() => {
+    vi.clearAllMocks();
+  });
 
-    it('should fetch warehouses data on mounted', async () => {
-        const fetchData = wrapper.findComponent({ name: 'FetchData' });
-        expect(fetchData.props('url')).toBe('Warehouses');
-        expect(fetchData.props('autoLoad')).toBe(true);
-    });
+  it('should fetch warehouses data on mounted', async () => {
+    const fetchData = wrapper.findComponent({ name: 'FetchData' });
+    expect(fetchData.props('url')).toBe('Warehouses');
+    expect(fetchData.props('autoLoad')).toBe(true);
+  });
 
-    it('should toggle dark mode correctly and update preferences', async () => {
-        await vm.saveDarkMode(true);
-        expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
-        expect(vm.user.darkMode).toBe(true);
-        vm.updatePreferences();
-        expect(vm.darkMode).toBe(true);
-    });
+  it('should toggle dark mode correctly and update preferences', async () => {
+    await vm.saveDarkMode(true);
+    expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
+    expect(vm.user.darkMode).toBe(true);
+    await vm.updatePreferences();
+    expect(vm.darkMode).toBe(true);
+  });
 
-    it('should change user language and update preferences', async () => {
-        const userLanguage = 'es';
-        await vm.saveLanguage(userLanguage);
-        expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
-        expect(vm.user.lang).toBe(userLanguage);
-        vm.updatePreferences();
-        expect(vm.locale).toBe(userLanguage);
-    });
+  it('should change user language and update preferences', async () => {
+    const userLanguage = 'es';
+    await vm.saveLanguage(userLanguage);
+    expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
+    expect(vm.user.lang).toBe(userLanguage);
+    await vm.updatePreferences();
+    expect(vm.locale).toBe(userLanguage);
+  });
 
-    it('should update user data', async () => {
-        const key = 'name';
-        const value = 'itboss';
-        await vm.saveUserData(key, value);
-        expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
-    });
-});
+  it('should update user data', async () => {
+    const key = 'name';
+    const value = 'itboss';
+    await vm.saveUserData(key, value);
+    expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
+  });
+});
\ No newline at end of file
diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue
index 0d80f43ce..44002c22a 100644
--- a/src/components/common/VnCard.vue
+++ b/src/components/common/VnCard.vue
@@ -10,11 +10,11 @@ import LeftMenu from 'components/LeftMenu.vue';
 import RightMenu from 'components/common/RightMenu.vue';
 const props = defineProps({
     dataKey: { type: String, required: true },
-    baseUrl: { type: String, default: undefined },
-    customUrl: { type: String, default: undefined },
+    url: { type: String, default: undefined },
     filter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
+    idInWhere: { type: Boolean, default: false },
     searchDataKey: { type: String, default: undefined },
     searchbarProps: { type: Object, default: undefined },
     redirectOnError: { type: Boolean, default: false },
@@ -23,25 +23,20 @@ const props = defineProps({
 const stateStore = useStateStore();
 const route = useRoute();
 const router = useRouter();
-const url = computed(() => {
-    if (props.baseUrl) {
-        return `${props.baseUrl}/${route.params.id}`;
-    }
-    return props.customUrl;
-});
 const searchRightDataKey = computed(() => {
     if (!props.searchDataKey) return route.name;
     return props.searchDataKey;
 });
+
 const arrayData = useArrayData(props.dataKey, {
-    url: url.value,
-    filter: props.filter,
+    url: props.url,
+    userFilter: props.filter,
+    oneRecord: true,
 });
 
 onBeforeMount(async () => {
     try {
-        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
-        await arrayData.fetch({ append: false, updateRouter: false });
+        await fetch(route.params.id);
     } catch {
         const { matched: matches } = router.currentRoute.value;
         const { path } = matches.at(-1);
@@ -49,13 +44,17 @@ onBeforeMount(async () => {
     }
 });
 
-if (props.baseUrl) {
-    onBeforeRouteUpdate(async (to, from) => {
-        if (to.params.id !== from.params.id) {
-            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
-            await arrayData.fetch({ append: false, updateRouter: false });
-        }
-    });
+onBeforeRouteUpdate(async (to, from) => {
+    const id = to.params.id;
+    if (id !== from.params.id) await fetch(id, true);
+});
+
+async function fetch(id, append = false) {
+    const regex = /\/(\d+)/;
+    if (props.idInWhere) arrayData.store.filter.where = { id };
+    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
+    else arrayData.store.url = props.url.replace(regex, `/${id}`);
+    await arrayData.fetch({ append, updateRouter: false });
 }
 </script>
 <template>
@@ -83,7 +82,7 @@ if (props.baseUrl) {
         <QPage>
             <VnSubToolbar />
             <div :class="[useCardSize(), $attrs.class]">
-                <RouterView :key="route.path" />
+                <RouterView :key="$route.path" />
             </div>
         </QPage>
     </QPageContainer>
diff --git a/src/components/common/VnCardBeta.vue b/src/components/common/VnCardBeta.vue
index f237a300c..7c82316dc 100644
--- a/src/components/common/VnCardBeta.vue
+++ b/src/components/common/VnCardBeta.vue
@@ -1,6 +1,6 @@
 <script setup>
-import { onBeforeMount, computed } from 'vue';
-import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
+import { onBeforeMount } from 'vue';
+import { useRouter, onBeforeRouteUpdate } from 'vue-router';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useStateStore } from 'stores/useStateStore';
 import useCardSize from 'src/composables/useCardSize';
@@ -9,10 +9,9 @@ import VnSubToolbar from '../ui/VnSubToolbar.vue';
 
 const props = defineProps({
     dataKey: { type: String, required: true },
-    baseUrl: { type: String, default: undefined },
-    customUrl: { type: String, default: undefined },
+    url: { type: String, default: undefined },
+    idInWhere: { type: Boolean, default: false },
     filter: { type: Object, default: () => {} },
-    userFilter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
     searchDataKey: { type: String, default: undefined },
@@ -21,46 +20,42 @@ const props = defineProps({
 });
 
 const stateStore = useStateStore();
-const route = useRoute();
 const router = useRouter();
-const url = computed(() => {
-    if (props.baseUrl) {
-        return `${props.baseUrl}/${route.params.id}`;
-    }
-    return props.customUrl;
-});
-
 const arrayData = useArrayData(props.dataKey, {
-    url: url.value,
-    filter: props.filter,
-    userFilter: props.userFilter,
+    url: props.url,
+    userFilter: props.filter,
+    oneRecord: true,
 });
 
 onBeforeMount(async () => {
+    const route = router.currentRoute.value;
     try {
-        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
-        await arrayData.fetch({ append: false, updateRouter: false });
+        await fetch(route.params.id);
     } catch {
-        const { matched: matches } = router.currentRoute.value;
+        const { matched: matches } = route;
         const { path } = matches.at(-1);
         router.push({ path: path.replace(/:id.*/, '') });
     }
 });
 
-if (props.baseUrl) {
-    onBeforeRouteUpdate(async (to, from) => {
-        if (hasRouteParam(to.params)) {
-            const { matched } = router.currentRoute.value;
-            const { name } = matched.at(-3);
-            if (name) {
-                router.push({ name, params: to.params });
-            }
+onBeforeRouteUpdate(async (to, from) => {
+    if (hasRouteParam(to.params)) {
+        const { matched } = router.currentRoute.value;
+        const { name } = matched.at(-3);
+        if (name) {
+            router.push({ name, params: to.params });
         }
-        if (to.params.id !== from.params.id) {
-            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
-            await arrayData.fetch({ append: false, updateRouter: false });
-        }
-    });
+    }
+    const id = to.params.id;
+    if (id !== from.params.id) await fetch(id, true);
+});
+
+async function fetch(id, append = false) {
+    const regex = /\/(\d+)/;
+    if (props.idInWhere) arrayData.store.filter.where = { id };
+    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
+    else arrayData.store.url = props.url.replace(regex, `/${id}`);
+    await arrayData.fetch({ append, updateRouter: false });
 }
 function hasRouteParam(params, valueToCheck = ':addressId') {
     return Object.values(params).includes(valueToCheck);
@@ -74,6 +69,6 @@ function hasRouteParam(params, valueToCheck = ':addressId') {
     </Teleport>
     <VnSubToolbar />
     <div :class="[useCardSize(), $attrs.class]">
-        <RouterView :key="route.path" />
+        <RouterView :key="$route.path" />
     </div>
 </template>
diff --git a/src/components/common/VnCheckbox.vue b/src/components/common/VnCheckbox.vue
new file mode 100644
index 000000000..27131d45e
--- /dev/null
+++ b/src/components/common/VnCheckbox.vue
@@ -0,0 +1,43 @@
+<script setup>
+import { computed } from 'vue';
+
+const model = defineModel({ type: [Number, Boolean] });
+const $props = defineProps({
+    info: {
+        type: String,
+        default: null,
+    },
+});
+
+const checkboxModel = computed({
+    get() {
+        if (typeof model.value === 'number') {
+            return model.value !== 0;
+        }
+        return model.value;
+    },
+    set(value) {
+        if (typeof model.value === 'number') {
+            model.value = value ? 1 : 0;
+        } else {
+            model.value = value;
+        }
+    },
+});
+</script>
+<template>
+    <div>
+        <QCheckbox v-bind="$attrs" v-on="$attrs" v-model="checkboxModel" />
+        <QIcon
+            v-if="info"
+            v-bind="$attrs"
+            class="cursor-info q-ml-sm"
+            name="info"
+            size="sm"
+        >
+            <QTooltip>
+                {{ info }}
+            </QTooltip>
+        </QIcon>
+    </div>
+</template>
diff --git a/src/components/common/VnColor.vue b/src/components/common/VnColor.vue
new file mode 100644
index 000000000..8a5a787b0
--- /dev/null
+++ b/src/components/common/VnColor.vue
@@ -0,0 +1,32 @@
+<script setup>
+const $props = defineProps({
+    colors: {
+        type: String,
+        default: '{"value": []}',
+    },
+});
+
+const colorArray = JSON.parse($props.colors)?.value;
+const maxHeight = 30;
+const colorHeight = maxHeight / colorArray?.length;
+</script>
+<template>
+    <div v-if="colors" class="color-div" :style="{ height: `${maxHeight}px` }">
+        <div
+            v-for="(color, index) in colorArray"
+            :key="index"
+            :style="{
+                backgroundColor: `#${color}`,
+                height: `${colorHeight}px`,
+            }"
+        >
+            &nbsp;
+        </div>
+    </div>
+</template>
+<style scoped>
+.color-div {
+    display: flex;
+    flex-direction: column;
+}
+</style>
diff --git a/src/components/common/VnComponent.vue b/src/components/common/VnComponent.vue
index 580bcf348..a9e1c8cff 100644
--- a/src/components/common/VnComponent.vue
+++ b/src/components/common/VnComponent.vue
@@ -17,6 +17,8 @@ const $props = defineProps({
     },
 });
 
+const emit = defineEmits(['blur']);
+
 const componentArray = computed(() => {
     if (typeof $props.prop === 'object') return [$props.prop];
     return $props.prop;
@@ -46,7 +48,8 @@ function toValueAttrs(attrs) {
     <span
         v-for="toComponent of componentArray"
         :key="toComponent.name"
-        class="column flex-center fit"
+        class="column fit"
+        :class="toComponent?.component == 'checkbox' ? 'flex-center' : ''"
     >
         <component
             v-if="toComponent?.component"
@@ -54,6 +57,7 @@ function toValueAttrs(attrs) {
             v-bind="mix(toComponent).attrs"
             v-on="mix(toComponent).event ?? {}"
             v-model="model"
+            @blur="emit('blur')"
         />
     </span>
 </template>
diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue
index 36c87bab0..424781a26 100644
--- a/src/components/common/VnDmsList.vue
+++ b/src/components/common/VnDmsList.vue
@@ -17,7 +17,7 @@ import { useSession } from 'src/composables/useSession';
 const route = useRoute();
 const quasar = useQuasar();
 const { t } = useI18n();
-const rows = ref();
+const rows = ref([]);
 const dmsRef = ref();
 const formDialog = ref({});
 const token = useSession().getTokenMultimedia();
@@ -389,6 +389,14 @@ defineExpose({
                     </div>
                 </template>
             </QTable>
+            <div 
+                v-else 
+                class="info-row q-pa-md text-center"
+            >
+                <h5>
+                    {{ t('No data to display') }}
+                </h5>
+            </div>
         </template>
     </VnPaginate>
     <QDialog v-model="formDialog.show">
@@ -405,7 +413,7 @@ defineExpose({
             fab
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut
             @click="showFormDialog()"
             class="fill-icon"
         >
diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 78f08a479..aeb4a31fd 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -11,6 +11,7 @@ const emit = defineEmits([
     'update:options',
     'keyup.enter',
     'remove',
+    'blur',
 ]);
 
 const $props = defineProps({
@@ -136,6 +137,7 @@ const handleUppercase = () => {
             :type="$attrs.type"
             :class="{ required: isRequired }"
             @keyup.enter="emit('keyup.enter')"
+            @blur="emit('blur')"
             @keydown="handleKeydown"
             :clearable="false"
             :rules="mixinRules"
@@ -143,7 +145,7 @@ const handleUppercase = () => {
             hide-bottom-space
             :data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
         >
-            <template #prepend>
+            <template #prepend v-if="$slots.prepend">
                 <slot name="prepend" />
             </template>
             <template #append>
@@ -168,11 +170,11 @@ const handleUppercase = () => {
                         }
                     "
                 ></QIcon>
-                
+
                 <QIcon
                     name="match_case"
                     size="xs"
-                    v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
+                    v-if="!$attrs.disabled && !$attrs.readonly && $props.uppercase"
                     @click="handleUppercase"
                     class="uppercase-icon"
                 >
@@ -180,7 +182,7 @@ const handleUppercase = () => {
                         {{ t('Convert to uppercase') }}
                     </QTooltip>
                 </QIcon>
-                
+
                 <slot name="append" v-if="$slots.append && !$attrs.disabled" />
                 <QIcon v-if="info" name="info">
                     <QTooltip max-width="350px">
@@ -194,13 +196,15 @@ const handleUppercase = () => {
 
 <style>
 .uppercase-icon {
-  transition: color 0.3s, transform 0.2s;
-  cursor: pointer;
+    transition:
+        color 0.3s,
+        transform 0.2s;
+    cursor: pointer;
 }
 
 .uppercase-icon:hover {
-  color: #ed9937;
-  transform: scale(1.2);
+    color: #ed9937;
+    transform: scale(1.2);
 }
 </style>
 <i18n>
@@ -214,4 +218,4 @@ const handleUppercase = () => {
         maxLength: El valor excede los {value} carácteres
         inputMax: Debe ser menor a {value}
         Convert to uppercase: Convertir a mayúsculas
-</i18n>
\ No newline at end of file
+</i18n>
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index a8888aad8..73c825e1e 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -42,7 +42,7 @@ const formattedDate = computed({
                 if (value.at(2) == '/') value = value.split('/').reverse().join('/');
                 value = date.formatDate(
                     new Date(value).toISOString(),
-                    'YYYY-MM-DDTHH:mm:ss.SSSZ'
+                    'YYYY-MM-DDTHH:mm:ss.SSSZ',
                 );
             }
             const [year, month, day] = value.split('-').map((e) => parseInt(e));
@@ -55,7 +55,7 @@ const formattedDate = computed({
                     orgDate.getHours(),
                     orgDate.getMinutes(),
                     orgDate.getSeconds(),
-                    orgDate.getMilliseconds()
+                    orgDate.getMilliseconds(),
                 );
             }
         }
@@ -64,7 +64,7 @@ const formattedDate = computed({
 });
 
 const popupDate = computed(() =>
-    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
+    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value,
 );
 onMounted(() => {
     // fix quasar bug
@@ -73,7 +73,7 @@ onMounted(() => {
 watch(
     () => model.value,
     (val) => (formattedDate.value = val),
-    { immediate: true }
+    { immediate: true },
 );
 
 const styleAttrs = computed(() => {
diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue
index 165cfae3d..274f78b21 100644
--- a/src/components/common/VnInputNumber.vue
+++ b/src/components/common/VnInputNumber.vue
@@ -8,6 +8,7 @@ defineProps({
 });
 
 const model = defineModel({ type: [Number, String] });
+const emit = defineEmits(['blur']);
 </script>
 <template>
     <VnInput
@@ -24,5 +25,6 @@ const model = defineModel({ type: [Number, String] });
                     model = parseFloat(val).toFixed(decimalPlaces);
             }
         "
+        @blur="emit('blur')"
     />
 </template>
diff --git a/src/components/common/VnPopupProxy.vue b/src/components/common/VnPopupProxy.vue
new file mode 100644
index 000000000..f386bfff8
--- /dev/null
+++ b/src/components/common/VnPopupProxy.vue
@@ -0,0 +1,38 @@
+<script setup>
+import { ref } from 'vue';
+
+defineProps({
+    label: {
+        type: String,
+        default: '',
+    },
+    icon: {
+        type: String,
+        required: true,
+        default: null,
+    },
+    color: {
+        type: String,
+        default: 'primary',
+    },
+    tooltip: {
+        type: String,
+        default: null,
+    },
+});
+const popupProxyRef = ref(null);
+</script>
+
+<template>
+    <QBtn :color="$props.color" :icon="$props.icon" :label="$t($props.label)">
+        <template #default>
+            <slot name="extraIcon"></slot>
+            <QPopupProxy ref="popupProxyRef" style="max-width: none">
+                <QCard>
+                    <slot :popup="popupProxyRef"></slot>
+                </QCard>
+            </QPopupProxy>
+            <QTooltip>{{ $t($props.tooltip) }}</QTooltip>
+        </template>
+    </QBtn>
+</template>
diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
index ef65b841f..4bd17124f 100644
--- a/src/components/common/VnSection.vue
+++ b/src/components/common/VnSection.vue
@@ -106,7 +106,14 @@ function checkIsMain() {
                     :data-key="dataKey"
                     :array-data="arrayData"
                     :columns="columns"
-                />
+                >
+                    <template #moreFilterPanel="{ params, orders, searchFn }">
+                        <slot
+                            name="moreFilterPanel"
+                            v-bind="{ params, orders, searchFn }"
+                        />
+                    </template>
+                </VnTableFilter>
             </slot>
         </template>
     </RightAdvancedMenu>
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 95fe80a69..339f90e0e 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -10,7 +10,12 @@ const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 const $attrs = useAttrs();
 const { t } = useI18n();
 
-const { isRequired, requiredFieldRule } = useRequired($attrs);
+const isRequired = computed(() => {
+    return useRequired($attrs).isRequired;
+});
+const requiredFieldRule = computed(() => {
+    return useRequired($attrs).requiredFieldRule;
+});
 
 const $props = defineProps({
     modelValue: {
@@ -166,7 +171,8 @@ onMounted(() => {
 });
 
 const arrayDataKey =
-    $props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label);
+    $props.dataKey ??
+    ($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
 
 const arrayData = useArrayData(arrayDataKey, {
     url: $props.url,
@@ -215,7 +221,7 @@ async function fetchFilter(val) {
         optionFilterValue.value ??
         (new RegExp(/\d/g).test(val)
             ? optionValue.value
-            : optionFilter.value ?? optionLabel.value);
+            : (optionFilter.value ?? optionLabel.value));
 
     let defaultWhere = {};
     if ($props.filterOptions.length) {
@@ -234,7 +240,7 @@ async function fetchFilter(val) {
 
     const { data } = await arrayData.applyFilter(
         { filter: filterOptions },
-        { updateRouter: false }
+        { updateRouter: false },
     );
     setOptions(data);
     return data;
@@ -267,7 +273,7 @@ async function filterHandler(val, update) {
                 ref.setOptionIndex(-1);
                 ref.moveOptionSelection(1, true);
             }
-        }
+        },
     );
 }
 
@@ -303,7 +309,7 @@ function handleKeyDown(event) {
         if (inputValue) {
             const matchingOption = myOptions.value.find(
                 (option) =>
-                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase()
+                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase(),
             );
 
             if (matchingOption) {
@@ -315,11 +321,11 @@ function handleKeyDown(event) {
         }
 
         const focusableElements = document.querySelectorAll(
-            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])'
+            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])',
         );
         const currentIndex = Array.prototype.indexOf.call(
             focusableElements,
-            event.target
+            event.target,
         );
         if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) {
             focusableElements[currentIndex + 1].focus();
diff --git a/src/components/common/VnSelectCache.vue b/src/components/common/VnSelectCache.vue
index 29cf22dc5..f0f3357f6 100644
--- a/src/components/common/VnSelectCache.vue
+++ b/src/components/common/VnSelectCache.vue
@@ -14,7 +14,7 @@ const $props = defineProps({
     },
 });
 const options = ref([]);
-
+const emit = defineEmits(['blur']);
 onBeforeMount(async () => {
     const { url, optionValue, optionLabel } = useAttrs();
     const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
@@ -35,5 +35,5 @@ onBeforeMount(async () => {
 });
 </script>
 <template>
-    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" />
+    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" @blur="emit('blur')" />
 </template>
diff --git a/src/components/common/VnSelectDialog.vue b/src/components/common/VnSelectDialog.vue
index a4cd0011d..41730b217 100644
--- a/src/components/common/VnSelectDialog.vue
+++ b/src/components/common/VnSelectDialog.vue
@@ -37,7 +37,6 @@ const isAllowedToCreate = computed(() => {
 
 defineExpose({ vnSelectDialogRef: select });
 </script>
-
 <template>
     <VnSelect
         ref="select"
@@ -67,7 +66,6 @@ defineExpose({ vnSelectDialogRef: select });
         </template>
     </VnSelect>
 </template>
-
 <style lang="scss" scoped>
 .default-icon {
     cursor: pointer;
diff --git a/src/components/common/VnSelectSupplier.vue b/src/components/common/VnSelectSupplier.vue
index f86db4f2d..5b52ae75b 100644
--- a/src/components/common/VnSelectSupplier.vue
+++ b/src/components/common/VnSelectSupplier.vue
@@ -1,9 +1,7 @@
 <script setup>
-import { computed } from 'vue';
 import VnSelect from 'components/common/VnSelect.vue';
 
 const model = defineModel({ type: [String, Number, Object] });
-const url = 'Suppliers';
 </script>
 
 <template>
@@ -11,11 +9,13 @@ const url = 'Suppliers';
         :label="$t('globals.supplier')"
         v-bind="$attrs"
         v-model="model"
-        :url="url"
+        url="Suppliers"
         option-value="id"
         option-label="nickname"
         :fields="['id', 'name', 'nickname', 'nif']"
+        :filter-options="['id', 'name', 'nickname', 'nif']"
         sort-by="name ASC"
+        data-cy="vnSupplierSelect"
     >
         <template #option="scope">
             <QItem v-bind="scope.itemProps">
diff --git a/src/components/common/VnSelectTravelExtended.vue b/src/components/common/VnSelectTravelExtended.vue
new file mode 100644
index 000000000..46538f5f9
--- /dev/null
+++ b/src/components/common/VnSelectTravelExtended.vue
@@ -0,0 +1,50 @@
+<script setup>
+import VnSelectDialog from './VnSelectDialog.vue';
+import FilterTravelForm from 'src/components/FilterTravelForm.vue';
+import { useI18n } from 'vue-i18n';
+import { toDate } from 'src/filters';
+const { t } = useI18n();
+
+const $props = defineProps({
+    data: {
+        type: Object,
+        required: true,
+    },
+    onFilterTravelSelected: {
+        type: Function,
+        required: true,
+    },
+});
+</script>
+<template>
+    <VnSelectDialog
+        :label="t('entry.basicData.travel')"
+        v-bind="$attrs"
+        url="Travels/filter"
+        :fields="['id', 'warehouseInName']"
+        option-value="id"
+        option-label="warehouseInName"
+        map-options
+        hide-selected
+        :required="true"
+        action-icon="filter_alt"
+        :roles-allowed-to-create="['buyer']"
+    >
+        <template #form>
+            <FilterTravelForm @travel-selected="onFilterTravelSelected(data, $event)" />
+        </template>
+        <template #option="scope">
+            <QItem v-bind="scope.itemProps">
+                <QItemSection>
+                    <QItemLabel>
+                        {{ scope.opt?.agencyModeName }} -
+                        {{ scope.opt?.warehouseInName }}
+                        ({{ toDate(scope.opt?.shipped) }}) →
+                        {{ scope.opt?.warehouseOutName }}
+                        ({{ toDate(scope.opt?.landed) }})
+                    </QItemLabel>
+                </QItemSection>
+            </QItem>
+        </template>
+    </VnSelectDialog>
+</template>
diff --git a/src/components/common/__tests__/VnNotes.spec.js b/src/components/common/__tests__/VnNotes.spec.js
index 8f24a7f14..2603bf03c 100644
--- a/src/components/common/__tests__/VnNotes.spec.js
+++ b/src/components/common/__tests__/VnNotes.spec.js
@@ -1,51 +1,78 @@
-import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
+import {
+    describe,
+    it,
+    expect,
+    vi,
+    beforeAll,
+    afterEach,
+    beforeEach,
+    afterAll,
+} from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import VnNotes from 'src/components/ui/VnNotes.vue';
+import vnDate from 'src/boot/vnDate';
 
 describe('VnNotes', () => {
     let vm;
     let wrapper;
     let spyFetch;
     let postMock;
-    let expectedBody;
-    const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
-
-    function generateExpectedBody() {
-        expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
-    }
-
-    async function setTestParams(text, observationType, type){
-        vm.newNote.text = text;
-        vm.newNote.observationTypeFk = observationType;
-        wrapper.setProps({ selectType: type });
-    }
-
-    beforeAll(async () => {        
-        vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
-
+    let patchMock;
+    let expectedInsertBody;
+    let expectedUpdateBody;
+    const defaultOptions = {
+        url: '/test',
+        body: { name: 'Tony', lastName: 'Stark' },
+        selectType: false,
+        saveUrl: null,
+        justInput: false,
+    };
+    function generateWrapper(
+        options = defaultOptions,
+        text = null,
+        observationType = null,
+    ) {
+        vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
         wrapper = createWrapper(VnNotes, {
-            propsData: {
-                url: '/test',
-                body: { name: 'Tony', lastName: 'Stark' },
-            }
+            propsData: options,
         });
         wrapper = wrapper.wrapper;
         vm = wrapper.vm;
-    });
+        vm.newNote.text = text;
+        vm.newNote.observationTypeFk = observationType;
+    }
+
+    function createSpyFetch() {
+        spyFetch = vi.spyOn(vm.$refs.vnPaginateRef, 'fetch');
+    }
+
+    function generateExpectedBody() {
+        expectedInsertBody = {
+            ...vm.$props.body,
+            ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk },
+        };
+        expectedUpdateBody = { ...vm.$props.body, ...{ notes: vm.newNote.text } };
+    }
 
     beforeEach(() => {
-        postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
-        spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
+        postMock = vi.spyOn(axios, 'post');
+        patchMock = vi.spyOn(axios, 'patch');
     });
 
     afterEach(() => {
         vi.clearAllMocks();
-        expectedBody = {};
+        expectedInsertBody = {};
+        expectedUpdateBody = {};
+    });
+
+    afterAll(() => {
+        vi.restoreAllMocks();
     });
 
     describe('insert', () => {
-        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
-            await setTestParams( null, null, true );
+        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is null', async () => {
+            generateWrapper({ selectType: true });
+            createSpyFetch();
 
             await vm.insert();
 
@@ -53,8 +80,9 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
-            await setTestParams( "", null, false );
+        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is empty', async () => {
+            generateWrapper(null, '');
+            createSpyFetch();
 
             await vm.insert();
 
@@ -62,8 +90,9 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
-            await setTestParams( "Test Note", null, true );
+        it('should not call axios.post and vnPaginateRef.fetch when observationTypeFk is null and selectType is true', async () => {
+            generateWrapper({ selectType: true }, 'Test Note');
+            createSpyFetch();
 
             await vm.insert();
 
@@ -71,37 +100,57 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
-            await setTestParams( "Test Note", null, false );
-
+        it('should call axios.post and vnPaginateRef.fetch when observationTypeFk is missing and selectType is false', async () => {
+            generateWrapper(null, 'Test Note');
+            createSpyFetch();
             generateExpectedBody();
 
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
-            expect(spyFetch).toHaveBeenCalled();
-        });
-
-        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {            
-            await setTestParams( "Test Note", 1, false );
-
-            generateExpectedBody();
-
-            await vm.insert();
-
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
             expect(spyFetch).toHaveBeenCalled();
         });
 
         it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
-            await setTestParams( "Test Note", 1, true );
-
+            generateWrapper({ selectType: true }, 'Test Note', 1);
+            createSpyFetch();
             generateExpectedBody();
-            
+
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
             expect(spyFetch).toHaveBeenCalled();
         });
     });
-});
\ No newline at end of file
+
+    describe('update', () => {
+        it('should call axios.patch with saveUrl when saveUrl is set and justInput is true', async () => {
+            generateWrapper({
+                url: '/business',
+                justInput: true,
+                saveUrl: '/saveUrlTest',
+            });
+            generateExpectedBody();
+
+            await vm.update();
+
+            expect(patchMock).toHaveBeenCalledWith(vm.$props.saveUrl, expectedUpdateBody);
+        });
+
+        it('should call axios.patch with url when saveUrl is not set and justInput is true', async () => {
+            generateWrapper({
+                url: '/business',
+                body: { workerFk: 1110 },
+                justInput: true,
+            });
+            generateExpectedBody();
+
+            await vm.update();
+
+            expect(patchMock).toHaveBeenCalledWith(
+                `${vm.$props.url}/${vm.$props.body.workerFk}`,
+                expectedUpdateBody,
+            );
+        });
+    });
+});
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index 43dc15e9b..e6e7e6fa0 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 { useClipboard } from 'src/composables/useClipboard';
 import VnMoreOptions from './VnMoreOptions.vue';
 
 const $props = defineProps({
@@ -29,10 +30,6 @@ const $props = defineProps({
         type: String,
         default: null,
     },
-    module: {
-        type: String,
-        default: null,
-    },
     summary: {
         type: Object,
         default: null,
@@ -46,6 +43,7 @@ const $props = defineProps({
 const state = useState();
 const route = useRoute();
 const { t } = useI18n();
+const { copyText } = useClipboard();
 const { viewSummary } = useSummaryDialog();
 let arrayData;
 let store;
@@ -57,12 +55,13 @@ defineExpose({ getData });
 onBeforeMount(async () => {
     arrayData = useArrayData($props.dataKey, {
         url: $props.url,
-        filter: $props.filter,
+        userFilter: $props.filter,
         skip: 0,
+        oneRecord: true,
     });
     store = arrayData.store;
     entity = computed(() => {
-        const data = (Array.isArray(store.data) ? store.data[0] : store.data) ?? {};
+        const data = store.data ?? {};
         if (data) emit('onFetch', data);
         return data;
     });
@@ -73,7 +72,7 @@ onBeforeMount(async () => {
         () => [$props.url, $props.filter],
         async () => {
             if (!isSameDataKey.value) await getData();
-        }
+        },
     );
 });
 
@@ -84,7 +83,7 @@ async function getData() {
     try {
         const { data } = await arrayData.fetch({ append: false, updateRouter: false });
         state.set($props.dataKey, data);
-        emit('onFetch', Array.isArray(data) ? data[0] : data);
+        emit('onFetch', data);
     } finally {
         isLoading.value = false;
     }
@@ -102,13 +101,21 @@ function getValueFromPath(path) {
     return current;
 }
 
+function copyIdText(id) {
+    copyText(id, {
+        component: {
+            copyValue: id,
+        },
+    });
+}
+
 const emit = defineEmits(['onFetch']);
 
 const iconModule = computed(() => route.matched[1].meta.icon);
 const toModule = computed(() =>
     route.matched[1].path.split('/').length > 2
         ? route.matched[1].redirect
-        : route.matched[1].children[0].redirect
+        : route.matched[1].children[0].redirect,
 );
 </script>
 
@@ -147,7 +154,9 @@ const toModule = computed(() =>
                         {{ t('components.smartCard.openSummary') }}
                     </QTooltip>
                 </QBtn>
-                <RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }">
+                <RouterLink
+                    :to="{ name: `${dataKey}Summary`, params: { id: entity.id } }"
+                >
                     <QBtn
                         class="link"
                         color="white"
@@ -183,9 +192,22 @@ const toModule = computed(() =>
                             </slot>
                         </div>
                     </QItemLabel>
-                    <QItem dense>
+                    <QItem>
                         <QItemLabel class="subtitle" caption>
                             #{{ getValueFromPath(subtitle) ?? entity.id }}
+                            <QBtn
+                                round
+                                flat
+                                dense
+                                size="sm"
+                                icon="content_copy"
+                                color="primary"
+                                @click.stop="copyIdText(entity.id)"
+                            >
+                                <QTooltip>
+                                    {{ t('globals.copyId') }}
+                                </QTooltip>
+                            </QBtn>
                         </QItemLabel>
                     </QItem>
                 </QList>
@@ -293,3 +315,11 @@ const toModule = computed(() =>
     }
 }
 </style>
+<i18n>
+    en:
+        globals:
+            copyId: Copy ID
+    es:
+        globals:
+            copyId: Copiar ID
+</i18n>
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index c815b8e16..6a61994c1 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -40,9 +40,10 @@ const arrayData = useArrayData(props.dataKey, {
     filter: props.filter,
     userFilter: props.userFilter,
     skip: 0,
+    oneRecord: true,
 });
 const { store } = arrayData;
-const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
+const entity = computed(() => store.data);
 const isLoading = ref(false);
 
 defineExpose({
@@ -61,7 +62,7 @@ async function fetch() {
     store.filter = props.filter ?? {};
     isLoading.value = true;
     const { data } = await arrayData.fetch({ append: false, updateRouter: false });
-    emit('onFetch', Array.isArray(data) ? data[0] : data);
+    emit('onFetch', data);
     isLoading.value = false;
 }
 </script>
@@ -208,4 +209,13 @@ async function fetch() {
 .summaryHeader {
     color: $white;
 }
+
+.cardSummary :deep(.q-card__section[content]) {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 0;
+    > * {
+        flex: 1;
+    }
+}
 </style>
diff --git a/src/components/ui/SkeletonDescriptor.vue b/src/components/ui/SkeletonDescriptor.vue
index 9679751f5..f9188221a 100644
--- a/src/components/ui/SkeletonDescriptor.vue
+++ b/src/components/ui/SkeletonDescriptor.vue
@@ -1,53 +1,32 @@
+<script setup>
+defineProps({
+    hasImage: {
+        type: Boolean,
+        default: false,
+    },
+});
+</script>
 <template>
-    <div id="descriptor-skeleton">
+    <div id="descriptor-skeleton" class="bg-vn-page">
         <div class="row justify-between q-pa-sm">
-            <QSkeleton square size="40px" />
-            <QSkeleton square size="40px" />
-            <QSkeleton square height="40px" width="20px" />
+            <QSkeleton square size="30px" v-for="i in 3" :key="i" />
         </div>
-        <div class="col justify-between q-pa-sm q-gutter-y-xs">
-            <QSkeleton square height="40px" width="150px" />
-            <QSkeleton square height="30px" width="70px" />
+        <div class="q-pa-xs" v-if="hasImage">
+            <QSkeleton square height="200px" width="100%" />
         </div>
-        <div class="col q-pl-sm q-pa-sm q-mb-md">
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
+        <div class="col justify-between q-pa-md q-gutter-y-xs">
+            <QSkeleton square height="25px" width="150px" />
+            <QSkeleton square height="15px" width="70px" />
+        </div>
+        <div class="q-pl-sm q-pa-sm q-mb-md">
+            <div class="row q-gutter-x-sm q-pa-none q-ma-none" v-for="i in 5" :key="i">
+                <QSkeleton type="text" square height="20px" width="30%" />
+                <QSkeleton type="text" square height="20px" width="60%" />
             </div>
         </div>
 
-        <QCardActions>
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
+        <QCardActions class="q-gutter-x-sm justify-between">
+            <QSkeleton size="40px" v-for="i in 5" :key="i" />
         </QCardActions>
     </div>
 </template>
-
-<style lang="scss" scoped>
-#descriptor-skeleton .q-card__actions {
-    justify-content: space-between;
-}
-</style>
diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index a02b56bdb..c6f539879 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -82,7 +82,7 @@ function cancel() {
                     @click="cancel()"
                 />
             </QCardSection>
-            <QCardSection class="q-pb-none">
+            <QCardSection class="q-pb-none" data-cy="VnConfirm_message">
                 <span v-if="message !== false" v-html="message" />
             </QCardSection>
             <QCardSection class="row items-center q-pt-none">
@@ -95,6 +95,7 @@ function cancel() {
                     :disable="isLoading"
                     flat
                     @click="cancel()"
+                    data-cy="VnConfirm_cancel"
                 />
                 <QBtn
                     :label="t('globals.confirm')"
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 93f069cc6..d6b525dc8 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -114,7 +114,7 @@ async function clearFilters() {
         arrayData.resetPagination();
         // Filtrar los params no removibles
         const removableFilters = Object.keys(userParams.value).filter((param) =>
-            $props.unremovableParams.includes(param)
+            $props.unremovableParams.includes(param),
         );
         const newParams = {};
         // Conservar solo los params que no son removibles
@@ -162,13 +162,13 @@ const formatTags = (tags) => {
 
 const tags = computed(() => {
     const filteredTags = tagsList.value.filter(
-        (tag) => !($props.customTags || []).includes(tag.label)
+        (tag) => !($props.customTags || []).includes(tag.label),
     );
     return formatTags(filteredTags);
 });
 
 const customTags = computed(() =>
-    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
+    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label)),
 );
 
 async function remove(key) {
@@ -188,10 +188,13 @@ function formatValue(value) {
 const getLocale = (label) => {
     const param = label.split('.').at(-1);
     const globalLocale = `globals.params.${param}`;
+    const moduleName = route.meta.moduleName;
+    const moduleLocale = `${moduleName.toLowerCase()}.${param}`;
     if (te(globalLocale)) return t(globalLocale);
-    else if (te(t(`params.${param}`)));
+    else if (te(moduleLocale)) return t(moduleLocale);
     else {
-        const camelCaseModuleName = route.meta.moduleName.charAt(0).toLowerCase() + route.meta.moduleName.slice(1);    
+        const camelCaseModuleName =
+            moduleName.charAt(0).toLowerCase() + moduleName.slice(1);
         return t(`${camelCaseModuleName}.params.${param}`);
     }
 };
@@ -290,6 +293,9 @@ const getLocale = (label) => {
     />
 </template>
 <style scoped lang="scss">
+.q-field__label.no-pointer-events.absolute.ellipsis {
+    margin-left: 6px !important;
+}
 .list {
     width: 256px;
 }
diff --git a/src/components/ui/VnMoreOptions.vue b/src/components/ui/VnMoreOptions.vue
index 39e84be2b..8a1c7a0f2 100644
--- a/src/components/ui/VnMoreOptions.vue
+++ b/src/components/ui/VnMoreOptions.vue
@@ -11,7 +11,7 @@
         <QTooltip>
             {{ $t('components.cardDescriptor.moreOptions') }}
         </QTooltip>
-        <QMenu ref="menuRef">
+        <QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
             <QList>
                 <slot name="menu" :menu-ref="$refs.menuRef" />
             </QList>
diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index 1690a94ba..ec6289a67 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { ref, reactive } from 'vue';
+import { ref, reactive, useAttrs, computed } from 'vue';
 import { onBeforeRouteLeave } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -16,12 +16,27 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FetchData from 'components/FetchData.vue';
 import VnInput from 'components/common/VnInput.vue';
 
+const emit = defineEmits(['onFetch']);
+
+const originalAttrs = useAttrs();
+
+const $attrs = computed(() => {
+    const { style, ...rest } = originalAttrs;
+    return rest;
+});
+
+const isRequired = computed(() => {
+    return Object.keys($attrs).includes('required')
+});
+
 const $props = defineProps({
     url: { type: String, default: null },
+    saveUrl: {type: String, default: null},
     filter: { type: Object, default: () => {} },
     body: { type: Object, default: () => {} },
     addNote: { type: Boolean, default: false },
     selectType: { type: Boolean, default: false },
+    justInput: { type: Boolean, default: false },
 });
 
 const { t } = useI18n();
@@ -29,6 +44,13 @@ const quasar = useQuasar();
 const newNote = reactive({ text: null, observationTypeFk: null });
 const observationTypes = ref([]);
 const vnPaginateRef = ref();
+let originalText;
+
+function handleClick(e) {
+    if (e.shiftKey && e.key === 'Enter') return;
+    if ($props.justInput) confirmAndUpdate();
+    else insert();
+}
 
 async function insert() {
     if (!newNote.text || ($props.selectType && !newNote.observationTypeFk)) return;
@@ -41,8 +63,36 @@ async function insert() {
     await axios.post($props.url, newBody);
     await vnPaginateRef.value.fetch();
 }
+
+function confirmAndUpdate() {
+    if(!newNote.text && originalText)
+        quasar
+            .dialog({
+                component: VnConfirm,
+                componentProps: {
+                    title: t('New note is empty'),
+                    message: t('Are you sure remove this note?'),
+                },
+            })
+            .onOk(update)
+            .onCancel(() => {
+                newNote.text = originalText;
+            });
+    else update();
+}
+
+async function update() {
+    originalText = newNote.text;
+    const body = $props.body;
+    const newBody = {
+        ...body,
+        ...{ notes: newNote.text },
+    };
+    await axios.patch(`${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, newBody);
+}
+
 onBeforeRouteLeave((to, from, next) => {
-    if (newNote.text)
+    if ((newNote.text && !$props.justInput) || (newNote.text !== originalText) && $props.justInput)
         quasar.dialog({
             component: VnConfirm,
             componentProps: {
@@ -53,6 +103,13 @@ onBeforeRouteLeave((to, from, next) => {
         });
     else next();
 });
+
+function fetchData([ data ]) {
+    newNote.text = data?.notes;
+    originalText = data?.notes;
+    emit('onFetch', data);
+}
+
 </script>
 <template>
     <FetchData
@@ -62,8 +119,19 @@ onBeforeRouteLeave((to, from, next) => {
         auto-load
         @on-fetch="(data) => (observationTypes = data)"
     />
-    <QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
-        <QCardSection horizontal>
+    <FetchData
+        v-if="justInput"
+        :url="url"
+        :filter="filter"
+        @on-fetch="fetchData"
+        auto-load
+    />
+    <QCard 
+        class="q-pa-xs q-mb-lg full-width" 
+        :class="{ 'just-input': $props.justInput }"
+        v-if="$props.addNote || $props.justInput"
+    >
+        <QCardSection horizontal v-if="!$props.justInput">
             {{ t('New note') }}
         </QCardSection>
         <QCardSection class="q-px-xs q-my-none q-py-none">
@@ -75,19 +143,19 @@ onBeforeRouteLeave((to, from, next) => {
                     v-model="newNote.observationTypeFk"
                     option-label="description"
                     style="flex: 0.15"
-                    :required="true"
+                    :required="isRequired"
                     @keyup.enter.stop="insert"
                 />
                 <VnInput
                     v-model.trim="newNote.text"
                     type="textarea"
-                    :label="t('Add note here...')"
+                    :label="$props.justInput && newNote.text ? '' : t('Add note here...')"
                     filled
                     size="lg"
                     autogrow
-                    @keyup.enter.stop="insert"
+                    @keyup.enter.stop="handleClick"
+                    :required="isRequired"
                     clearable
-                    :required="true"
                 >
                     <template #append>
                         <QBtn
@@ -95,7 +163,7 @@ onBeforeRouteLeave((to, from, next) => {
                             icon="save"
                             color="primary"
                             flat
-                            @click="insert"
+                            @click="handleClick"
                             class="q-mb-xs"
                             dense
                             data-cy="saveNote"
@@ -106,6 +174,7 @@ onBeforeRouteLeave((to, from, next) => {
         </QCardSection>
     </QCard>
     <VnPaginate
+        v-if="!$props.justInput"
         :data-key="$props.url"
         :url="$props.url"
         order="created DESC"
@@ -198,6 +267,11 @@ onBeforeRouteLeave((to, from, next) => {
         }
     }
 }
+.just-input {
+    padding-right: 18px;
+    margin-bottom: 2px;
+    box-shadow: none;
+}
 </style>
 <i18n>
     es:
@@ -205,4 +279,6 @@ onBeforeRouteLeave((to, from, next) => {
         New note: Nueva nota
         Save (Enter): Guardar (Intro)
         Observation type: Tipo de observación
+        New note is empty: La nueva nota esta vacia
+        Are you sure remove this note?: Estas seguro de quitar esta nota?
 </i18n>
diff --git a/src/components/ui/VnStockValueDisplay.vue b/src/components/ui/VnStockValueDisplay.vue
new file mode 100644
index 000000000..d8f43323b
--- /dev/null
+++ b/src/components/ui/VnStockValueDisplay.vue
@@ -0,0 +1,41 @@
+<script setup>
+import { toPercentage } from 'filters/index';
+
+import { computed } from 'vue';
+
+const props = defineProps({
+    value: {
+        type: Number,
+        required: true,
+    },
+});
+
+const valueClass = computed(() =>
+    props.value === 0 ? 'neutral' : props.value > 0 ? 'positive' : 'negative',
+);
+const iconName = computed(() =>
+    props.value === 0 ? 'equal' : props.value > 0 ? 'arrow_upward' : 'arrow_downward',
+);
+const formattedValue = computed(() => props.value);
+</script>
+<template>
+    <span :class="valueClass">
+        <QIcon :name="iconName" size="sm" class="value-icon" />
+        {{ toPercentage(formattedValue) }}
+    </span>
+</template>
+
+<style lang="scss" scoped>
+.positive {
+    color: $secondary;
+}
+.negative {
+    color: $negative;
+}
+.neutral {
+    color: $primary;
+}
+.value-icon {
+    margin-right: 4px;
+}
+</style>
diff --git a/src/components/ui/VnSubToolbar.vue b/src/components/ui/VnSubToolbar.vue
index 5ded4be00..8d4126d1d 100644
--- a/src/components/ui/VnSubToolbar.vue
+++ b/src/components/ui/VnSubToolbar.vue
@@ -19,23 +19,26 @@ onMounted(() => {
     const observer = new MutationObserver(
         () =>
             (hasContent.value =
-                actions.value?.childNodes?.length + data.value?.childNodes?.length)
+                actions.value?.childNodes?.length + data.value?.childNodes?.length),
     );
     if (actions.value) observer.observe(actions.value, opts);
     if (data.value) observer.observe(data.value, opts);
 });
 
-onBeforeUnmount(() => stateStore.toggleSubToolbar());
+const actionsChildCount = () => !!actions.value?.childNodes?.length;
+
+onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
 </script>
 
 <template>
     <QToolbar
         id="subToolbar"
-        class="justify-end sticky"
         v-show="hasContent || $slots['st-actions'] || $slots['st-data']"
+        class="justify-end sticky"
     >
         <slot name="st-data">
-            <div id="st-data"></div>
+            <div id="st-data" :class="{ 'full-width': !actionsChildCount() }">
+            </div>
         </slot>
         <QSpace />
         <slot name="st-actions">
diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index 411ebf9bb..2f7f90882 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -51,16 +51,6 @@ describe('CardSummary', () => {
         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 newUrl = 'CardSummary/35';
         const newKey = 'cardSummaryKey/35';
@@ -72,7 +62,7 @@ describe('CardSummary', () => {
         expect(vm.store.filter).toEqual({ key: newKey });
     });
 
-    it('should return true if route path ends with /summary' , () => {
+    it('should return true if route path ends with /summary', () => {
         expect(vm.isSummary).toBe(true);
     });
-});
\ No newline at end of file
+});
diff --git a/src/composables/__tests__/useArrayData.spec.js b/src/composables/__tests__/useArrayData.spec.js
index d4c5d0949..a610ba9eb 100644
--- a/src/composables/__tests__/useArrayData.spec.js
+++ b/src/composables/__tests__/useArrayData.spec.js
@@ -16,7 +16,7 @@ describe('useArrayData', () => {
         vi.clearAllMocks();
     });
 
-    it('should fetch and repalce url with new params', async () => {
+    it('should fetch and replace url with new params', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
@@ -33,11 +33,11 @@ describe('useArrayData', () => {
         });
         expect(routerReplace.path).toEqual('mockSection/list');
         expect(JSON.parse(routerReplace.query.params)).toEqual(
-            expect.objectContaining(params)
+            expect.objectContaining(params),
         );
     });
 
-    it('Should get data and send new URL without keeping parameters, if there is only one record', async () => {
+    it('should get data and send new URL without keeping parameters, if there is only one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl', navigate: {} });
@@ -56,7 +56,7 @@ describe('useArrayData', () => {
         expect(routerPush.query).toBeUndefined();
     });
 
-    it('Should get data and send new URL keeping parameters, if you have more than one record', async () => {
+    it('should get data and send new URL keeping parameters, if you have more than one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }, { id: 2 }] });
 
         vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
@@ -95,4 +95,25 @@ describe('useArrayData', () => {
         expect(routerPush.path).toEqual('mockName/');
         expect(routerPush.query.params).toBeDefined();
     });
+
+    it('should return one record', async () => {
+        vi.spyOn(axios, 'get').mockReturnValueOnce({
+            data: [
+                { id: 1, name: 'Entity 1' },
+                { id: 2, name: 'Entity 2' },
+            ],
+        });
+        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
+        await arrayData.fetch({});
+
+        expect(arrayData.store.data).toEqual({ id: 1, name: 'Entity 1' });
+    });
+
+    it('should handle empty data gracefully if has to return one record', async () => {
+        vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
+        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
+        await arrayData.fetch({});
+
+        expect(arrayData.store.data).toBeUndefined();
+    });
 });
diff --git a/src/composables/checkEntryLock.js b/src/composables/checkEntryLock.js
new file mode 100644
index 000000000..f964dea27
--- /dev/null
+++ b/src/composables/checkEntryLock.js
@@ -0,0 +1,65 @@
+import { useQuasar } from 'quasar';
+import { useI18n } from 'vue-i18n';
+import { useRouter } from 'vue-router';
+import axios from 'axios';
+import VnConfirm from 'components/ui/VnConfirm.vue';
+
+export async function checkEntryLock(entryFk, userFk) {
+    const { t } = useI18n();
+    const quasar = useQuasar();
+    const { push } = useRouter();
+    const { data } = await axios.get(`Entries/${entryFk}`, {
+        params: {
+            filter: JSON.stringify({
+                fields: ['id', 'locked', 'lockerUserFk'],
+                include: { relation: 'user', scope: { fields: ['id', 'nickname'] } },
+            }),
+        },
+    });
+    const entryConfig = await axios.get('EntryConfigs/findOne');
+
+    if (data?.lockerUserFk && data?.locked) {
+        const now = new Date(Date.vnNow()).getTime();
+        const lockedTime = new Date(data.locked).getTime();
+        const timeDiff = (now - lockedTime) / 1000;
+        const isMaxTimeLockExceeded = entryConfig.data.maxLockTime > timeDiff;
+
+        if (data?.lockerUserFk !== userFk && isMaxTimeLockExceeded) {
+            quasar
+                .dialog({
+                    component: VnConfirm,
+                    componentProps: {
+                        'data-cy': 'entry-lock-confirm',
+                        title: t('entry.lock.title'),
+                        message: t('entry.lock.message', {
+                            userName: data?.user?.nickname,
+                            time: timeDiff / 60,
+                        }),
+                    },
+                })
+                .onOk(
+                    async () =>
+                        await axios.patch(`Entries/${entryFk}`, {
+                            locked: Date.vnNow(),
+                            lockerUserFk: userFk,
+                        }),
+                )
+                .onCancel(() => {
+                    push({ path: `summary` });
+                });
+        }
+    } else {
+        await axios
+            .patch(`Entries/${entryFk}`, {
+                locked: Date.vnNow(),
+                lockerUserFk: userFk,
+            })
+            .then(
+                quasar.notify({
+                    message: t('entry.lock.success'),
+                    color: 'positive',
+                    group: false,
+                }),
+            );
+    }
+}
diff --git a/src/composables/getColAlign.js b/src/composables/getColAlign.js
new file mode 100644
index 000000000..a930fd7d8
--- /dev/null
+++ b/src/composables/getColAlign.js
@@ -0,0 +1,22 @@
+export function getColAlign(col) {
+    let align;
+    switch (col.component) {
+        case 'time':
+        case 'date':
+        case 'select':
+            align = 'left';
+            break;
+        case 'number':
+            align = 'right';
+            break;
+        case 'checkbox':
+            align = 'center';
+            break;
+        default:
+            align = col?.align;
+    }
+
+    if (/^is[A-Z]/.test(col.name) || /^has[A-Z]/.test(col.name)) align = 'center';
+
+    return 'text-' + (align ?? 'center');
+}
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index bd3cecf08..fcc61972a 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -57,6 +57,7 @@ export function useArrayData(key, userOptions) {
             'navigate',
             'mapKey',
             'keepData',
+            'oneRecord',
         ];
         if (typeof userOptions === 'object') {
             for (const option in userOptions) {
@@ -112,7 +113,11 @@ export function useArrayData(key, userOptions) {
         store.isLoading = false;
         canceller = null;
 
-        processData(response.data, { map: !!store.mapKey, append });
+        processData(response.data, {
+            map: !!store.mapKey,
+            append,
+            oneRecord: store.oneRecord,
+        });
 
         return response;
     }
@@ -314,7 +319,11 @@ export function useArrayData(key, userOptions) {
         return { params, limit };
     }
 
-    function processData(data, { map = true, append = true }) {
+    function processData(data, { map = true, append = true, oneRecord = false }) {
+        if (oneRecord) {
+            store.data = Array.isArray(data) ? data[0] : data;
+            return;
+        }
         if (!append) {
             store.data = [];
             store.map = new Map();
diff --git a/src/composables/useRole.js b/src/composables/useRole.js
index 3ec65dd0a..ff54b409c 100644
--- a/src/composables/useRole.js
+++ b/src/composables/useRole.js
@@ -27,6 +27,15 @@ export function useRole() {
 
         return false;
     }
+    function likeAny(roles) {
+        const roleStore = state.getRoles();
+        for (const role of roles) {
+            if (!roleStore.value.findIndex((rs) => rs.startsWith(role)) !== -1)
+                return true;
+        }
+
+        return false;
+    }
     function isEmployee() {
         return hasAny(['employee']);
     }
@@ -35,6 +44,7 @@ export function useRole() {
         isEmployee,
         fetch,
         hasAny,
+        likeAny,
         state,
     };
 }
diff --git a/src/css/app.scss b/src/css/app.scss
index 7296b079f..0c5dc97fa 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -21,7 +21,10 @@ body.body--light {
     .q-header .q-toolbar {
         color: var(--vn-text-color);
     }
+
+    --vn-color-negative: $negative;
 }
+
 body.body--dark {
     --vn-header-color: #5d5d5d;
     --vn-page-color: #222;
@@ -37,6 +40,8 @@ body.body--dark {
     --vn-text-color-contrast: black;
 
     background-color: var(--vn-page-color);
+
+    --vn-color-negative: $negative;
 }
 
 a {
@@ -75,7 +80,6 @@ a {
     text-decoration: underline;
 }
 
-// Removes chrome autofill background
 input:-webkit-autofill,
 select:-webkit-autofill {
     color: var(--vn-text-color);
@@ -149,11 +153,6 @@ select:-webkit-autofill {
     cursor: pointer;
 }
 
-.vn-table-separation-row {
-    height: 16px !important;
-    background-color: var(--vn-section-color) !important;
-}
-
 /* Estilo para el asterisco en campos requeridos */
 .q-field.required .q-field__label:after {
     content: ' *';
@@ -212,6 +211,10 @@ select:-webkit-autofill {
     justify-content: center;
 }
 
+.q-card__section[dense] {
+    padding: 0;
+}
+
 input[type='number'] {
     -moz-appearance: textfield;
 }
@@ -226,10 +229,12 @@ input::-webkit-inner-spin-button {
     max-width: 100%;
 }
 
-.q-table__container {
-    /* ===== Scrollbar CSS ===== /
-    / Firefox */
+.remove-bg {
+    filter: brightness(1.1);
+    mix-blend-mode: multiply;
+}
 
+.q-table__container {
     * {
         scrollbar-width: auto;
         scrollbar-color: var(--vn-label-color) transparent;
@@ -270,8 +275,6 @@ input::-webkit-inner-spin-button {
             font-size: 11pt;
         }
         td {
-            font-size: 11pt;
-            border-top: 1px solid var(--vn-page-color);
             border-collapse: collapse;
         }
     }
@@ -315,9 +318,6 @@ input::-webkit-inner-spin-button {
     max-width: fit-content;
 }
 
-.row > .column:has(.q-checkbox) {
-    max-width: fit-content;
-}
 .q-field__inner {
     .q-field__control {
         min-height: auto !important;
diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss
index d6e992437..22c6d2b56 100644
--- a/src/css/quasar.variables.scss
+++ b/src/css/quasar.variables.scss
@@ -13,7 +13,7 @@
 // Tip: Use the "Theme Builder" on Quasar's documentation website.
 // Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors
 $primary: #ec8916;
-$secondary: $primary;
+$secondary: #89be34;
 $positive: #c8e484;
 $negative: #fb5252;
 $info: #84d0e2;
@@ -30,7 +30,9 @@ $color-spacer: #7979794d;
 $border-thin-light: 1px solid $color-spacer-light;
 $primary-light: #f5b351;
 $dark-shadow-color: black;
-$layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d;
+$layout-shadow-dark:
+    0 0 10px 2px #00000033,
+    0 0px 10px #0000003d;
 $spacing-md: 16px;
 $color-font-secondary: #777;
 $width-xs: 400px;
diff --git a/src/filters/toDate.js b/src/filters/toDate.js
index 8fe8f3836..002797af5 100644
--- a/src/filters/toDate.js
+++ b/src/filters/toDate.js
@@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
 export default function (value, options = {}) {
     if (!value) return;
 
+    if (!isValidDate(value)) return null;
+
     if (!options.dateStyle && !options.timeStyle) {
         options.day = '2-digit';
         options.month = '2-digit';
@@ -10,7 +12,12 @@ export default function (value, options = {}) {
     }
 
     const { locale } = useI18n();
-    const date = new Date(value);
+    const newDate = new Date(value);
 
-    return new Intl.DateTimeFormat(locale.value, options).format(date);
+    return new Intl.DateTimeFormat(locale.value, options).format(newDate);
+}
+// handle 0000-00-00
+function isValidDate(date) {
+    const parsedDate = new Date(date);
+    return parsedDate instanceof Date && !isNaN(parsedDate.getTime());
 }
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 7d0f3e0b2..9a60e9da1 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -33,6 +33,7 @@ globals:
     reset: Reset
     close: Close
     cancel: Cancel
+    isSaveAndContinue: Save and continue
     clone: Clone
     confirm: Confirm
     assign: Assign
@@ -156,6 +157,7 @@ globals:
     changeState: Change state
     raid: 'Raid {daysInForward} days'
     isVies: Vies
+    noData: No data available
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -168,6 +170,7 @@ globals:
         workCenters: Work centers
         modes: Modes
         zones: Zones
+        negative: Negative
         zonesList: List
         deliveryDays: Delivery days
         upcomingDeliveries: Upcoming deliveries
@@ -175,6 +178,7 @@ globals:
         alias: Alias
         aliasUsers: Users
         subRoles: Subroles
+        myAccount: Mi cuenta
         inheritedRoles: Inherited Roles
         customers: Customers
         customerCreate: New customer
@@ -333,10 +337,13 @@ globals:
         wasteRecalc: Waste recaclulate
         operator: Operator
         parking: Parking
+        vehicleList: Vehicles
+        vehicle: Vehicle
     unsavedPopup:
         title: Unsaved changes will be lost
         subtitle: Are you sure exit without saving?
     params:
+        description: Description
         clientFk: Client id
         salesPersonFk: Sales person
         warehouseFk: Warehouse
@@ -359,7 +366,13 @@ globals:
         correctingFk: Rectificative
         daysOnward: Days onward
         countryFk: Country
+        countryCodeFk: Country
         companyFk: Company
+    model: Model
+    fuel: Fuel
+    active: Active
+    inactive: Inactive
+    deliveryPoint: Delivery point
 errors:
     statusUnauthorized: Access denied
     statusInternalServerError: An internal server error has ocurred
@@ -398,6 +411,106 @@ cau:
     subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
     inputLabel: Explain why this error should not appear
     askPrivileges: Ask for privileges
+entry:
+    list:
+        newEntry: New entry
+        tableVisibleColumns:
+            isExcludedFromAvailable: Exclude from inventory
+            isOrdered: Ordered
+            isConfirmed: Ready to label
+            isReceived: Received
+            isRaid: Raid
+            landed: Date
+            supplierFk: Supplier
+            reference: Ref/Alb/Guide
+            invoiceNumber: Invoice
+            agencyModeId: Agency
+            isBooked: Booked
+            companyFk: Company
+            evaNotes: Notes
+            warehouseOutFk: Origin
+            warehouseInFk: Destiny
+            entryTypeDescription: Entry type
+            invoiceAmount: Import
+            travelFk: Travel
+    summary:
+        invoiceAmount: Amount
+        commission: Commission
+        currency: Currency
+        invoiceNumber: Invoice number
+        ordered: Ordered
+        booked: Booked
+        excludedFromAvailable: Inventory
+        travelReference: Reference
+        travelAgency: Agency
+        travelShipped: Shipped
+        travelDelivered: Delivered
+        travelLanded: Landed
+        travelReceived: Received
+        buys: Buys
+        stickers: Stickers
+        package: Package
+        packing: Pack.
+        grouping: Group.
+        buyingValue: Buying value
+        import: Import
+        pvp: PVP
+    basicData:
+        travel: Travel
+        currency: Currency
+        commission: Commission
+        observation: Observation
+        booked: Booked
+        excludedFromAvailable: Inventory
+    buys:
+        observations: Observations
+        packagingFk: Box
+        color: Color
+        printedStickers: Printed stickers
+    notes:
+        observationType: Observation type
+    latestBuys:
+        tableVisibleColumns:
+            image: Picture
+            itemFk: Item ID
+            weightByPiece: Weight/Piece
+            isActive: Active
+            family: Family
+            entryFk: Entry
+            freightValue: Freight value
+            comissionValue: Commission value
+            packageValue: Package value
+            isIgnored: Is ignored
+            price2: Grouping
+            price3: Packing
+            minPrice: Min
+            ektFk: Ekt
+            packingOut: Package out
+            landing: Landing
+            isExcludedFromAvailable: Exclude from inventory
+            isRaid: Raid
+            invoiceNumber: Invoice
+            reference: Ref/Alb/Guide
+    params:
+        isExcludedFromAvailable: Excluir del inventario
+        isOrdered: Pedida
+        isConfirmed: Lista para etiquetar
+        isReceived: Recibida
+        isRaid: Redada
+        landed: Fecha
+        supplierFk: Proveedor
+        invoiceNumber: Nº Factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Agencia
+        isBooked: Asentado
+        companyFk: Empresa
+        travelFk: Envio
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeDescription: Tipo entrada
+        invoiceAmount: Importe
+        dated: Fecha
 ticket:
     params:
         ticketFk: Ticket ID
@@ -627,6 +740,8 @@ wagon:
         name: Name
 
 supplier:
+    search: Search supplier
+    searchInfo: Search supplier by id or name
     list:
         payMethod: Pay method
         account: Account
@@ -716,6 +831,8 @@ travel:
         CloneTravelAndEntries: Clone travel and his entries
         deleteTravel: Delete travel
         AddEntry: Add entry
+        availabled: Availabled
+        availabledHour: Availabled hour
         thermographs: Thermographs
         hb: HB
     basicData:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 7ca9e4b4c..846c442ea 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -33,9 +33,11 @@ globals:
     reset: Restaurar
     close: Cerrar
     cancel: Cancelar
+    isSaveAndContinue: Guardar y continuar
     clone: Clonar
     confirm: Confirmar
     assign: Asignar
+    replace: Sustituir
     back: Volver
     yes: Si
     no: No
@@ -48,6 +50,7 @@ globals:
     rowRemoved: Fila eliminada
     pleaseWait: Por favor espera...
     noPinnedModules: No has fijado ningún módulo
+    split: Split
     enterToConfirm: Pulsa Enter para confirmar
     summary:
         basicData: Datos básicos
@@ -56,8 +59,8 @@ globals:
     today: Hoy
     yesterday: Ayer
     dateFormat: es-ES
-    microsip: Abrir en MicroSIP
     noSelectedRows: No tienes ninguna línea seleccionada
+    microsip: Abrir en MicroSIP
     downloadCSVSuccess: Descarga de CSV exitosa
     reference: Referencia
     agency: Agencia
@@ -77,8 +80,10 @@ globals:
     requiredField: Campo obligatorio
     class: clase
     type: Tipo
-    reason: motivo
+    reason: Motivo
+    removeSelection: Eliminar selección
     noResults: Sin resultados
+    results: resultados
     system: Sistema
     notificationSent: Notificación enviada
     warehouse: Almacén
@@ -156,6 +161,7 @@ globals:
     changeState: Cambiar estado
     raid: 'Redada {daysInForward} días'
     isVies: Vies
+    noData: Datos no disponibles
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -167,6 +173,7 @@ globals:
         agency: Agencia
         workCenters: Centros de trabajo
         modes: Modos
+        negative: Tickets negativos
         zones: Zonas
         zonesList: Listado
         deliveryDays: Días de entrega
@@ -287,9 +294,9 @@ globals:
         buyRequest: Peticiones de compra
         wasteBreakdown: Deglose de mermas
         itemCreate: Nuevo artículo
-        tax: 'IVA'
-        botanical: 'Botánico'
-        barcode: 'Código de barras'
+        tax: IVA
+        botanical: Botánico
+        barcode: Código de barras
         itemTypeCreate: Nueva familia
         family: Familia
         lastEntries: Últimas entradas
@@ -333,10 +340,13 @@ globals:
         wasteRecalc: Recalcular mermas
         operator: Operario
         parking: Parking
+        vehicleList: Vehículos
+        vehicle: Vehículo
     unsavedPopup:
         title: Los cambios que no haya guardado se perderán
         subtitle: ¿Seguro que quiere salir sin guardar?
     params:
+        description: Descripción
         clientFk: Id cliente
         salesPersonFk: Comercial
         warehouseFk: Almacén
@@ -350,13 +360,14 @@ globals:
         from: Desde
         to: Hasta
         supplierFk: Proveedor
-        supplierRef: Ref. proveedor
+        supplierRef: Nº factura
         serial: Serie
         amount: Importe
         awbCode: AWB
         daysOnward: Días adelante
         packing: ITP
         countryFk: País
+        countryCodeFk: País
         companyFk: Empresa
 errors:
     statusUnauthorized: Acceso denegado
@@ -394,6 +405,87 @@ cau:
     subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
     inputLabel: Explique el motivo por el que no deberia aparecer este fallo
     askPrivileges: Solicitar permisos
+entry:
+    list:
+        newEntry: Nueva entrada
+        tableVisibleColumns:
+            isExcludedFromAvailable: Excluir del inventario
+            isOrdered: Pedida
+            isConfirmed: Lista para etiquetar
+            isReceived: Recibida
+            isRaid: Redada
+            landed: Fecha
+            supplierFk: Proveedor
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
+            agencyModeId: Agencia
+            isBooked: Asentado
+            companyFk: Empresa
+            travelFk: Envio
+            evaNotes: Notas
+            warehouseOutFk: Origen
+            warehouseInFk: Destino
+            entryTypeDescription: Tipo entrada
+            invoiceAmount: Importe
+    summary:
+        invoiceAmount: Importe
+        commission: Comisión
+        currency: Moneda
+        invoiceNumber: Núm. factura
+        ordered: Pedida
+        booked: Contabilizada
+        excludedFromAvailable: Inventario
+        travelReference: Referencia
+        travelAgency: Agencia
+        travelShipped: F. envio
+        travelWarehouseOut: Alm. salida
+        travelDelivered: Enviada
+        travelLanded: F. entrega
+        travelReceived: Recibida
+        buys: Compras
+        stickers: Etiquetas
+        package: Embalaje
+        packing: Pack.
+        grouping: Group.
+        buyingValue: Coste
+        import: Importe
+        pvp: PVP
+    basicData:
+        travel: Envío
+        currency: Moneda
+        observation: Observación
+        commission: Comisión
+        booked: Asentado
+        excludedFromAvailable: Inventario
+    buys:
+        observations: Observaciónes
+        packagingFk: Embalaje
+        color: Color
+        printedStickers: Etiquetas impresas
+    notes:
+        observationType: Tipo de observación
+    latestBuys:
+        tableVisibleColumns:
+            image: Foto
+            itemFk: Id Artículo
+            weightByPiece: Peso (gramos)/tallo
+            isActive: Activo
+            family: Familia
+            entryFk: Entrada
+            freightValue: Porte
+            comissionValue: Comisión
+            packageValue: Embalaje
+            isIgnored: Ignorado
+            price2: Grouping
+            price3: Packing
+            minPrice: Min
+            ektFk: Ekt
+            packingOut: Embalaje envíos
+            landing: Llegada
+            isExcludedFromAvailable: Excluir del inventario
+            isRaid: Redada
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
 ticket:
     params:
         ticketFk: ID de ticket
@@ -407,6 +499,38 @@ ticket:
         freightItemName: Nombre
         packageItemName: Embalaje
         longName: Descripción
+    pageTitles:
+        tickets: Tickets
+        list: Listado
+        ticketCreate: Nuevo ticket
+        summary: Resumen
+        basicData: Datos básicos
+        boxing: Encajado
+        sms: Sms
+        notes: Notas
+        sale: Lineas del pedido
+        dms: Gestión documental
+        negative: Tickets negativos
+        volume: Volumen
+        observation: Notas
+        ticketAdvance: Adelantar tickets
+        futureTickets: Tickets a futuro
+        expedition: Expedición
+        purchaseRequest: Petición de compra
+        weeklyTickets: Tickets programados
+        saleTracking: Líneas preparadas
+        services: Servicios
+        tracking: Estados
+        components: Componentes
+        pictures: Fotos
+        packages: Bultos
+    list:
+        nickname: Alias
+        state: Estado
+        shipped: Enviado
+        landed: Entregado
+        salesPerson: Comercial
+        total: Total
     card:
         customerId: ID cliente
         customerCard: Ficha del cliente
@@ -453,15 +577,11 @@ ticket:
         consigneeStreet: Dirección
     create:
         address: Dirección
-order:
-    field:
-        salesPersonFk: Comercial
-    form:
-        clientFk: Cliente
-        addressFk: Dirección
-        agencyModeFk: Agencia
-    list:
-        newOrder: Nuevo Pedido
+invoiceOut:
+    card:
+        issued: Fecha emisión
+        customerCard: Ficha del cliente
+        ticketList: Listado de tickets
     summary:
         issued: Fecha
         dued: Fecha límite
@@ -472,6 +592,71 @@ order:
         fee: Cuota
         tickets: Tickets
         totalWithVat: Importe
+    globalInvoices:
+        errors:
+            chooseValidClient: Selecciona un cliente válido
+            chooseValidCompany: Selecciona una empresa válida
+            chooseValidPrinter: Selecciona una impresora válida
+            chooseValidSerialType: Selecciona una tipo de serie válida
+            fillDates: La fecha de la factura y la fecha máxima deben estar completas
+            invoiceDateLessThanMaxDate: La fecha de la factura no puede ser menor que la fecha máxima
+            invoiceWithFutureDate: Existe una factura con una fecha futura
+            noTicketsToInvoice: No existen tickets para facturar
+            criticalInvoiceError: Error crítico en la facturación proceso detenido
+            invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
+        table:
+            addressId: Id dirección
+            streetAddress: Dirección fiscal
+        statusCard:
+            percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
+            pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
+    negativeBases:
+        clientId: Id cliente
+        base: Base
+        active: Activo
+        hasToInvoice: Facturar
+        verifiedData: Datos comprobados
+        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
+        priority: Prioridad
+        newShelving: Nuevo Carro
+    summary:
+        recyclable: Reciclable
+parking:
+    pickingOrder: Orden de recogida
+    row: Fila
+    column: Columna
+    searchBar:
+        info: Puedes buscar por código de parking
+        label: Buscar parking...
 department:
     chat: Chat
     bossDepartment: Jefe de departamento
@@ -632,8 +817,8 @@ wagon:
         volumeNotEmpty: El volumen no puede estar vacío
         typeNotEmpty: El tipo no puede estar vacío
         maxTrays: Has alcanzado el número máximo de bandejas
-        minHeightBetweenTrays: 'La distancia mínima entre bandejas es '
-        maxWagonHeight: 'La altura máxima del vagón es '
+        minHeightBetweenTrays: La distancia mínima entre bandejas es
+        maxWagonHeight: La altura máxima del vagón es
         uncompleteTrays: Hay bandejas sin completar
     params:
         label: Etiqueta
@@ -641,6 +826,8 @@ wagon:
         volume: Volumen
         name: Nombre
 supplier:
+    search: Buscar proveedor
+    searchInfo: Buscar proveedor por id o nombre
     list:
         payMethod: Método de pago
         account: Cuenta
@@ -731,6 +918,8 @@ travel:
         deleteTravel: Eliminar envío
         AddEntry: Añadir entrada
         thermographs: Termógrafos
+        availabled: F. Disponible
+        availabledHour: Hora Disponible
         hb: HB
     basicData:
         daysInForward: Desplazamiento automatico (redada)
@@ -779,7 +968,7 @@ components:
     cardDescriptor:
         mainList: Listado principal
         summary: Resumen
-        moreOptions: 'Más opciones'
+        moreOptions: Más opciones
     leftMenu:
         addToPinned: Añadir a fijados
         removeFromPinned: Eliminar de fijados
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 2a84e5aa1..3ad1c79bc 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -2,7 +2,7 @@
 import Navbar from 'src/components/NavBar.vue';
 </script>
 <template>
-    <QLayout view="hHh LpR fFf" v-shortcut>
+    <QLayout view="hHh LpR fFf">
         <Navbar />
         <RouterView></RouterView>
         <QFooter v-if="$q.platform.is.mobile"></QFooter>
diff --git a/src/layouts/OutLayout.vue b/src/layouts/OutLayout.vue
index 4ccc6bf9e..eba57c198 100644
--- a/src/layouts/OutLayout.vue
+++ b/src/layouts/OutLayout.vue
@@ -1,12 +1,12 @@
 <script setup>
 import { Dark, Quasar } from 'quasar';
-import { computed } from 'vue';
+import { computed, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { localeEquivalence } from 'src/i18n/index';
 import quasarLang from 'src/utils/quasarLang';
+import { langs } from 'src/boot/defaults/constants.js';
 
 const { t, locale } = useI18n();
-
 const userLocale = computed({
     get() {
         return locale.value;
@@ -28,7 +28,6 @@ const darkMode = computed({
         Dark.set(value);
     },
 });
-const langs = ['en', 'es'];
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountAliasList.vue b/src/pages/Account/AccountAliasList.vue
index f6016fb6c..19682286c 100644
--- a/src/pages/Account/AccountAliasList.vue
+++ b/src/pages/Account/AccountAliasList.vue
@@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n';
 import { ref, computed } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnSection from 'src/components/common/VnSection.vue';
+import exprBuilder from './Alias/AliasExprBuilder';
 
 const tableRef = ref();
 const { t } = useI18n();
@@ -31,15 +32,6 @@ const columns = computed(() => [
         create: true,
     },
 ]);
-
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : { alias: { like: `%${value}%` } };
-    }
-};
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountExprBuilder.js b/src/pages/Account/AccountExprBuilder.js
new file mode 100644
index 000000000..6497a9d30
--- /dev/null
+++ b/src/pages/Account/AccountExprBuilder.js
@@ -0,0 +1,18 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'nickname':
+            return { [param]: { like: `%${value}%` } };
+        case 'roleFk':
+            return { [param]: value };
+    }
+};
diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue
index ea8daba0d..976af1d19 100644
--- a/src/pages/Account/AccountList.vue
+++ b/src/pages/Account/AccountList.vue
@@ -4,15 +4,16 @@ import { computed, ref } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import AccountSummary from './Card/AccountSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import exprBuilder from './AccountExprBuilder.js';
+import filter from './Card/AccountFilter.js';
 import VnSection from 'src/components/common/VnSection.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
-const filter = {
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
+const tableRef = ref();
+
 const dataKey = 'AccountList';
 const roles = ref([]);
 const columns = computed(() => [
@@ -117,25 +118,6 @@ const columns = computed(() => [
         ],
     },
 ]);
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'nickname':
-            return { [param]: { like: `%${value}%` } };
-        case 'roleFk':
-            return { [param]: value };
-    }
-}
 </script>
 <template>
     <FetchData url="VnRoles" @on-fetch="(data) => (roles = data)" auto-load />
diff --git a/src/pages/Account/Alias/AliasExprBuilder.js b/src/pages/Account/Alias/AliasExprBuilder.js
new file mode 100644
index 000000000..f7a5a104c
--- /dev/null
+++ b/src/pages/Account/Alias/AliasExprBuilder.js
@@ -0,0 +1,8 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : { alias: { like: `%${value}%` } };
+    }
+};
diff --git a/src/pages/Account/Alias/Card/AliasCard.vue b/src/pages/Account/Alias/Card/AliasCard.vue
index 3a814edc0..f37bd7d0f 100644
--- a/src/pages/Account/Alias/Card/AliasCard.vue
+++ b/src/pages/Account/Alias/Card/AliasCard.vue
@@ -1,21 +1,13 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AliasDescriptor from './AliasDescriptor.vue';
-const { t } = useI18n();
 </script>
 
 <template>
     <VnCardBeta
         data-key="Alias"
-        base-url="MailAliases"
+        url="MailAliases"
         :descriptor="AliasDescriptor"
         search-data-key="AccountAliasList"
-        :searchbar-props="{
-            url: 'MailAliases',
-            info: t('mailAlias.searchInfo'),
-            label: t('mailAlias.search'),
-            searchUrl: 'table',
-        }"
     />
 </template>
diff --git a/src/pages/Account/Alias/Card/AliasDescriptor.vue b/src/pages/Account/Alias/Card/AliasDescriptor.vue
index 2e01fad01..671ef7fbc 100644
--- a/src/pages/Account/Alias/Card/AliasDescriptor.vue
+++ b/src/pages/Account/Alias/Card/AliasDescriptor.vue
@@ -7,7 +7,6 @@ import { useQuasar } from 'quasar';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 
@@ -29,9 +28,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.alias, entity.id));
-
 const removeAlias = () => {
     quasar
         .dialog({
@@ -55,11 +51,8 @@ const removeAlias = () => {
     <CardDescriptor
         ref="descriptor"
         :url="`MailAliases/${entityId}`"
-        module="Alias"
-        @on-fetch="setData"
-        data-key="aliasData"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        data-key="Alias"
+        title="alias"
     >
         <template #menu>
             <QItem v-ripple clickable @click="removeAlias()">
diff --git a/src/pages/Account/Alias/Card/AliasSummary.vue b/src/pages/Account/Alias/Card/AliasSummary.vue
index 1f76fe7c2..b4b9abd25 100644
--- a/src/pages/Account/Alias/Card/AliasSummary.vue
+++ b/src/pages/Account/Alias/Card/AliasSummary.vue
@@ -1,13 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
-import { useArrayData } from 'src/composables/useArrayData';
-
 const route = useRoute();
 const { t } = useI18n();
 
@@ -18,20 +16,15 @@ const $props = defineProps({
     },
 });
 
-const { store } = useArrayData('Alias');
-const alias = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
 </script>
 
 <template>
-    <CardSummary
-        ref="summary"
-        :url="`MailAliases/${entityId}`"
-        @on-fetch="(data) => (alias = data)"
-        data-key="MailAliasesSummary"
-    >
-        <template #header> {{ alias.id }} - {{ alias.alias }} </template>
-        <template #body>
+    <CardSummary ref="summary" :url="`MailAliases/${entityId}`" data-key="Alias">
+        <template #header="{ entity: alias }">
+            {{ alias.id }} - {{ alias.alias }}
+        </template>
+        <template #body="{ entity: alias }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
diff --git a/src/pages/Account/Card/AccountBasicData.vue b/src/pages/Account/Card/AccountBasicData.vue
index e6c9da6fe..393f9eb80 100644
--- a/src/pages/Account/Card/AccountBasicData.vue
+++ b/src/pages/Account/Card/AccountBasicData.vue
@@ -1,46 +1,20 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
 import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-import { ref, watch } from 'vue';
-
-const route = useRoute();
-const { t } = useI18n();
-const formModelRef = ref(null);
-
-const accountFilter = {
-    where: { id: route.params.id },
-    fields: ['id', 'email', 'nickname', 'name', 'accountStateFk', 'packages', 'pickup'],
-    include: [],
-};
-
-watch(
-    () => route.params.id,
-    () => formModelRef.value.reset()
-);
 </script>
 <template>
-    <FormModel
-        ref="formModelRef"
-        url="VnUsers/preview"
-        :url-update="`VnUsers/${route.params.id}/update-user`"
-        :filter="accountFilter"
-        model="Accounts"
-        auto-load
-        @on-data-saved="formModelRef.fetch()"
-    >
+    <FormModel :url-update="`VnUsers/${$route.params.id}/update-user`" model="Account">
         <template #form="{ data }">
             <div class="q-gutter-y-sm">
-                <VnInput v-model="data.name" :label="t('account.card.nickname')" />
-                <VnInput v-model="data.nickname" :label="t('account.card.alias')" />
-                <VnInput v-model="data.email" :label="t('globals.params.email')" />
+                <VnInput v-model="data.name" :label="$t('account.card.nickname')" />
+                <VnInput v-model="data.nickname" :label="$t('account.card.alias')" />
+                <VnInput v-model="data.email" :label="$t('globals.params.email')" />
                 <VnSelect
                     url="Languages"
                     v-model="data.lang"
-                    :label="t('account.card.lang')"
+                    :label="$t('account.card.lang')"
                     option-value="code"
                     option-label="code"
                 />
@@ -49,7 +23,7 @@ watch(
                     table="user"
                     column="twoFactor"
                     v-model="data.twoFactor"
-                    :label="t('account.card.twoFactor')"
+                    :label="$t('account.card.twoFactor')"
                     option-value="code"
                     option-label="code"
                 />
diff --git a/src/pages/Account/Card/AccountCard.vue b/src/pages/Account/Card/AccountCard.vue
index 35ff7e732..a5037e301 100644
--- a/src/pages/Account/Card/AccountCard.vue
+++ b/src/pages/Account/Card/AccountCard.vue
@@ -1,8 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AccountDescriptor from './AccountDescriptor.vue';
+import filter from './AccountFilter.js';
 </script>
-
 <template>
-    <VnCardBeta data-key="AccountId" :descriptor="AccountDescriptor" />
+    <VnCardBeta
+        url="VnUsers/preview"
+        :id-in-where="true"
+        data-key="Account"
+        :descriptor="AccountDescriptor"
+        :filter="filter"
+    />
 </template>
diff --git a/src/pages/Account/Card/AccountDescriptor.vue b/src/pages/Account/Card/AccountDescriptor.vue
index 4e5328de6..49328fe87 100644
--- a/src/pages/Account/Card/AccountDescriptor.vue
+++ b/src/pages/Account/Card/AccountDescriptor.vue
@@ -1,36 +1,18 @@
 <script setup>
 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 VnImg from 'src/components/ui/VnImg.vue';
+import filter from './AccountFilter.js';
 import useHasAccount from 'src/composables/useHasAccount.js';
 
-const $props = defineProps({
-    id: {
-        type: Number,
-        required: false,
-        default: null,
-    },
-});
+const $props = defineProps({ id: { type: Number, default: null } });
 
 const route = useRoute();
-const { t } = useI18n();
-const entityId = computed(() => {
-    return $props.id || route.params.id;
-});
-const data = ref(useCardDescription());
+const entityId = computed(() => $props.id || route.params.id);
 const hasAccount = ref();
-const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
-
-const filter = {
-    where: { id: entityId },
-    fields: ['id', 'nickname', 'name', 'role'],
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
 
 onMounted(async () => {
     hasAccount.value = await useHasAccount(entityId.value);
@@ -41,12 +23,9 @@ onMounted(async () => {
     <CardDescriptor
         ref="descriptor"
         :url="`VnUsers/preview`"
-        :filter="filter"
-        module="Account"
-        @on-fetch="setData"
-        data-key="AccountId"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        :filter="{ ...filter, where: { id: entityId } }"
+        data-key="Account"
+        title="nickname"
     >
         <template #menu>
             <AccountDescriptorMenu :entity-id="entityId" />
@@ -62,7 +41,7 @@ onMounted(async () => {
                                 <QIcon name="vn:claims" />
                             </div>
                             <div class="text-grey-5" style="opacity: 0.4">
-                                {{ t('account.imageNotFound') }}
+                                {{ $t('account.imageNotFound') }}
                             </div>
                         </div>
                     </div>
@@ -70,8 +49,8 @@ onMounted(async () => {
             </VnImg>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('account.card.nickname')" :value="entity.name" />
-            <VnLv :label="t('account.card.role')" :value="entity.role.name" />
+            <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
+            <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
         </template>
         <template #actions="{ entity }">
             <QCardActions class="q-gutter-x-md">
@@ -84,7 +63,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
+                    <QTooltip>{{ $t('account.card.deactivated') }}</QTooltip>
                 </QIcon>
                 <QIcon
                     color="primary"
@@ -95,7 +74,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ t('account.card.enabled') }}</QTooltip>
+                    <QTooltip>{{ $t('account.card.enabled') }}</QTooltip>
                 </QIcon>
             </QCardActions>
         </template>
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 961323d3a..30584c61f 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -12,6 +12,7 @@ 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';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     hasAccount: {
@@ -29,7 +30,7 @@ const router = useRouter();
 const state = useState();
 const user = state.getUser();
 const { notify } = useQuasar();
-const account = computed(() => useArrayData('AccountId').store.data[0]);
+const account = computed(() => useArrayData('Account').store.data[0]);
 account.value.hasAccount = hasAccount.value;
 const entityId = computed(() => +route.params.id);
 const hasitManagementAccess = ref();
@@ -124,18 +125,14 @@ onMounted(() => {
         :promise="sync"
     >
         <template #customHTML>
-            {{ shouldSyncPassword }}
-            <QCheckbox
-                :label="t('account.card.actions.sync.checkbox')"
+            <VnCheckbox
                 v-model="shouldSyncPassword"
-                class="full-width"
+                :label="t('account.card.actions.sync.checkbox')"
+                :info="t('account.card.actions.sync.tooltip')"
                 clearable
                 clear-icon="close"
-            >
-                <QIcon style="padding-left: 10px" color="primary" name="info" size="sm">
-                    <QTooltip>{{ t('account.card.actions.sync.tooltip') }}</QTooltip>
-                </QIcon></QCheckbox
-            >
+                color="primary"
+            />
             <VnInputPassword
                 v-if="shouldSyncPassword"
                 :label="t('login.password')"
@@ -155,7 +152,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => deleteAccount()
+                () => deleteAccount(),
             )
         "
     >
@@ -174,7 +171,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.enableAccount.title'),
                 t('account.card.actions.enableAccount.subtitle'),
-                () => updateStatusAccount(true)
+                () => updateStatusAccount(true),
             )
         "
     >
@@ -188,7 +185,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => updateStatusAccount(false)
+                () => updateStatusAccount(false),
             )
         "
     >
@@ -203,7 +200,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.activateUser.title'),
                 t('account.card.actions.activateUser.title'),
-                () => updateStatusUser(true)
+                () => updateStatusUser(true),
             )
         "
     >
@@ -217,7 +214,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.deactivateUser.title'),
                 t('account.card.actions.deactivateUser.title'),
-                () => updateStatusUser(false)
+                () => updateStatusUser(false),
             )
         "
     >
diff --git a/src/pages/Account/Card/AccountFilter.js b/src/pages/Account/Card/AccountFilter.js
new file mode 100644
index 000000000..017876564
--- /dev/null
+++ b/src/pages/Account/Card/AccountFilter.js
@@ -0,0 +1,3 @@
+export default {
+    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
+};
diff --git a/src/pages/Account/Card/AccountMailAlias.vue b/src/pages/Account/Card/AccountMailAlias.vue
index ef1707cf2..7a060cff1 100644
--- a/src/pages/Account/Card/AccountMailAlias.vue
+++ b/src/pages/Account/Card/AccountMailAlias.vue
@@ -86,7 +86,7 @@ watch(
     () => route.params.id,
     () => {
         getAccountData();
-    }
+    },
 );
 
 onMounted(async () => await getAccountData(false));
@@ -130,7 +130,8 @@ onMounted(async () => await getAccountData(false));
                                             openConfirmationModal(
                                                 t('User will be removed from alias'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () => deleteMailAlias(row, rows, rowIndex)
+                                                () =>
+                                                    deleteMailAlias(row, rows, rowIndex),
                                             )
                                         "
                                     >
@@ -157,7 +158,7 @@ onMounted(async () => await getAccountData(false));
                 icon="add"
                 color="primary"
                 @click="openCreateMailAliasForm()"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Account/Card/AccountSummary.vue b/src/pages/Account/Card/AccountSummary.vue
index ca17c7975..f7a16e8c3 100644
--- a/src/pages/Account/Card/AccountSummary.vue
+++ b/src/pages/Account/Card/AccountSummary.vue
@@ -1,58 +1,41 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
-
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-
-import { useArrayData } from 'src/composables/useArrayData';
+import filter from './AccountFilter.js';
 import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
 
+const $props = defineProps({ id: { type: Number, default: 0 } });
+
 const route = useRoute();
-const { t } = useI18n();
-
-const $props = defineProps({
-    id: {
-        type: Number,
-        default: 0,
-    },
-});
-const { store } = useArrayData('Account');
-const account = ref(store.data);
-
 const entityId = computed(() => $props.id || route.params.id);
-const filter = {
-    where: { id: entityId },
-    fields: ['id', 'nickname', 'name', 'role'],
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
 </script>
 
 <template>
     <CardSummary
-        data-key="AccountId"
+        data-key="Account"
+        ref="AccountSummary"
         url="VnUsers/preview"
         :filter="filter"
-        @on-fetch="(data) => (account = data)"
     >
-        <template #header>{{ account.id }} - {{ account.nickname }}</template>
-        <template #menu="">
+        <template #header="{ entity }">{{ entity.id }} - {{ entity.nickname }}</template>
+        <template #menu>
             <AccountDescriptorMenu :entity-id="entityId" />
         </template>
-        <template #body>
+        <template #body="{ entity }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
                         :to="{ name: 'AccountBasicData', params: { id: entityId } }"
                         class="header header-link"
                     >
-                        {{ t('globals.pageTitles.basicData') }}
+                        {{ $t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </router-link>
                 </QCardSection>
-                <VnLv :label="t('account.card.nickname')" :value="account.name" />
-                <VnLv :label="t('account.card.role')" :value="account.role.name" />
+                <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
+                <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/AccountRoles.vue b/src/pages/Account/Role/AccountRoles.vue
index 3c3d6b243..02f5400c6 100644
--- a/src/pages/Account/Role/AccountRoles.vue
+++ b/src/pages/Account/Role/AccountRoles.vue
@@ -5,6 +5,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
 import { useRoute } from 'vue-router';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import RoleSummary from './Card/RoleSummary.vue';
+import exprBuilder from './RoleExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const route = useRoute();
@@ -66,24 +67,7 @@ const columns = computed(() => [
         ],
     },
 ]);
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'description':
-            return { [param]: { like: `%${value}%` } };
-    }
-};
 </script>
-
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Account/Role/Card/RoleBasicData.vue b/src/pages/Account/Role/Card/RoleBasicData.vue
index 1de9ff387..de70b0fb6 100644
--- a/src/pages/Account/Role/Card/RoleBasicData.vue
+++ b/src/pages/Account/Role/Card/RoleBasicData.vue
@@ -1,24 +1,16 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-const route = useRoute();
-const { t } = useI18n();
 </script>
 <template>
-    <FormModel :url="`VnRoles/${route.params.id}`" model="VnRole" auto-load>
+    <FormModel model="Role" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <div class="col">
-                    <VnInput v-model="data.name" :label="t('globals.name')" />
-                </div>
+                <VnInput v-model="data.name" :label="$t('globals.name')" />
             </VnRow>
             <VnRow>
-                <div class="col">
-                    <VnInput v-model="data.description" :label="t('role.description')" />
-                </div>
+                <VnInput v-model="data.description" :label="$t('role.description')" />
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/Account/Role/Card/RoleCard.vue b/src/pages/Account/Role/Card/RoleCard.vue
index 7664deca8..ef5b9db04 100644
--- a/src/pages/Account/Role/Card/RoleCard.vue
+++ b/src/pages/Account/Role/Card/RoleCard.vue
@@ -3,5 +3,10 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoleDescriptor from './RoleDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Role" :descriptor="RoleDescriptor" />
+    <VnCardBeta
+        url="VnRoles"
+        data-key="Role"
+        :id-in-where="true"
+        :descriptor="RoleDescriptor"
+    />
 </template>
diff --git a/src/pages/Account/Role/Card/RoleDescriptor.vue b/src/pages/Account/Role/Card/RoleDescriptor.vue
index 0a555346d..517517af0 100644
--- a/src/pages/Account/Role/Card/RoleDescriptor.vue
+++ b/src/pages/Account/Role/Card/RoleDescriptor.vue
@@ -1,10 +1,9 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 const $props = defineProps({
@@ -26,11 +25,6 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.name, entity.id));
-const filter = {
-    where: { id: entityId },
-};
 const removeRole = async () => {
     await axios.delete(`VnRoles/${entityId.value}`);
     notify(t('Role removed'), 'positive');
@@ -39,13 +33,9 @@ const removeRole = async () => {
 
 <template>
     <CardDescriptor
-        :url="`VnRoles/${entityId}`"
-        :filter="filter"
-        module="Role"
-        @on-fetch="setData"
+        url="VnRoles"
+        :filter="{ where: { id: entityId } }"
         data-key="Role"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :summary="$props.summary"
     >
         <template #menu>
diff --git a/src/pages/Account/Role/Card/RoleSummary.vue b/src/pages/Account/Role/Card/RoleSummary.vue
index f0daa77fb..410f90b17 100644
--- a/src/pages/Account/Role/Card/RoleSummary.vue
+++ b/src/pages/Account/Role/Card/RoleSummary.vue
@@ -1,10 +1,9 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import { useArrayData } from 'src/composables/useArrayData';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -16,24 +15,18 @@ const $props = defineProps({
     },
 });
 
-const { store } = useArrayData('Role');
-const role = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
-const filter = {
-    where: { id: entityId },
-};
 </script>
 
 <template>
     <CardSummary
         ref="summary"
-        :url="`VnRoles/${entityId}`"
-        :filter="filter"
-        @on-fetch="(data) => (role = data)"
+        url="VnRoles"
+        :filter="{ where: { id: entityId } }"
         data-key="Role"
     >
-        <template #header> {{ role.id }} - {{ role.name }} </template>
-        <template #body>
+        <template #header="{ entity }"> {{ entity.id }} - {{ entity.name }} </template>
+        <template #body="{ entity }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <a
@@ -44,9 +37,9 @@ const filter = {
                         <QIcon name="open_in_new" />
                     </a>
                 </QCardSection>
-                <VnLv :label="t('role.id')" :value="role.id" />
-                <VnLv :label="t('globals.name')" :value="role.name" />
-                <VnLv :label="t('role.description')" :value="role.description" />
+                <VnLv :label="t('role.id')" :value="entity.id" />
+                <VnLv :label="t('globals.name')" :value="entity.name" />
+                <VnLv :label="t('role.description')" :value="entity.description" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/Card/SubRoles.vue b/src/pages/Account/Role/Card/SubRoles.vue
index 0077f12b0..99cf5e8f0 100644
--- a/src/pages/Account/Role/Card/SubRoles.vue
+++ b/src/pages/Account/Role/Card/SubRoles.vue
@@ -63,7 +63,7 @@ watch(
         store.url = urlPath.value;
         store.filter = filter.value;
         fetchSubRoles();
-    }
+    },
 );
 
 const fetchSubRoles = () => paginateRef.value.fetch();
@@ -109,7 +109,7 @@ const redirectToRoleSummary = (id) =>
                                             openConfirmationModal(
                                                 t('El rol va a ser eliminado'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () => deleteSubRole(row, rows, rowIndex)
+                                                () => deleteSubRole(row, rows, rowIndex),
                                             )
                                         "
                                     >
@@ -131,7 +131,7 @@ const redirectToRoleSummary = (id) =>
             <QBtn
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
                 color="primary"
                 @click="openCreateSubRoleForm()"
             >
diff --git a/src/pages/Account/Role/RoleExprBuilder.js b/src/pages/Account/Role/RoleExprBuilder.js
new file mode 100644
index 000000000..cc4fab399
--- /dev/null
+++ b/src/pages/Account/Role/RoleExprBuilder.js
@@ -0,0 +1,16 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'description':
+            return { [param]: { like: `%${value}%` } };
+    }
+};
diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue
index 63b0b7c0d..67034da1a 100644
--- a/src/pages/Claim/Card/ClaimBasicData.vue
+++ b/src/pages/Claim/Card/ClaimBasicData.vue
@@ -28,7 +28,6 @@ const workersOptions = ref([]);
         model="Claim"
         :url-update="`Claims/updateClaim/${route.params.id}`"
         auto-load
-        :reload="true"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Claim/Card/ClaimCard.vue b/src/pages/Claim/Card/ClaimCard.vue
index e1e000815..05f3b53a8 100644
--- a/src/pages/Claim/Card/ClaimCard.vue
+++ b/src/pages/Claim/Card/ClaimCard.vue
@@ -4,10 +4,11 @@ import ClaimDescriptor from './ClaimDescriptor.vue';
 import filter from './ClaimFilter.js';
 </script>
 <template>
-    <VnCardBeta 
-        data-key="Claim" 
-        base-url="Claims" 
-        :descriptor="ClaimDescriptor" 
+    <VnCardBeta
+        data-key="Claim"
+        url="Claims"
+        :descriptor="ClaimDescriptor"
+        search-data-key="ClaimList"
         :filter="filter"
     />
 </template>
diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue
index 02b63dd8e..4551c58fe 100644
--- a/src/pages/Claim/Card/ClaimDescriptor.vue
+++ b/src/pages/Claim/Card/ClaimDescriptor.vue
@@ -3,12 +3,10 @@ import { ref, computed, onMounted } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toDateHourMinSec, toPercentage } from 'src/filters';
-import { useState } from 'src/composables/useState';
 import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
 import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { getUrl } from 'src/composables/getUrl';
 import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
@@ -23,7 +21,6 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const state = useState();
 const { t } = useI18n();
 const salixUrl = ref();
 const entityId = computed(() => {
@@ -39,12 +36,7 @@ const STATE_COLOR = {
 function stateColor(code) {
     return STATE_COLOR[code];
 }
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    if (!entity) return;
-    data.value = useCardDescription(entity?.client?.name, entity.id);
-    state.set('ClaimDescriptor', entity);
-};
+
 onMounted(async () => {
     salixUrl.value = await getUrl('');
 });
@@ -54,9 +46,7 @@ onMounted(async () => {
     <CardDescriptor
         :url="`Claims/${entityId}`"
         :filter="filter"
-        module="Claim"
         title="client.name"
-        @on-fetch="setData"
         data-key="Claim"
     >
         <template #menu="{ entity }">
@@ -95,7 +85,7 @@ onMounted(async () => {
                     />
                 </template>
             </VnLv>
-            <VnLv :label="t('claim.zone')">
+            <VnLv v-if="entity.ticket?.zone?.id" :label="t('claim.zone')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticket?.zone?.name }}
@@ -107,11 +97,10 @@ onMounted(async () => {
                 :label="t('claim.province')"
                 :value="entity.ticket?.address?.province?.name"
             />
-            <VnLv :label="t('claim.ticketId')">
+            <VnLv v-if="entity.ticketFk" :label="t('claim.ticketId')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticketFk }}
-
                         <TicketDescriptorProxy :id="entity.ticketFk" />
                     </span>
                 </template>
diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue
index 33fadd020..dee03b95d 100644
--- a/src/pages/Claim/Card/ClaimLines.vue
+++ b/src/pages/Claim/Card/ClaimLines.vue
@@ -317,7 +317,13 @@ async function saveWhenHasChanges() {
     </div>
 
     <QPageSticky position="bottom-right" :offset="[25, 25]">
-        <QBtn fab color="primary" shortcut="+" icon="add" @click="showImportDialog()" />
+        <QBtn
+            fab
+            color="primary"
+            v-shortcut="'+'"
+            icon="add"
+            @click="showImportDialog()"
+        />
     </QPageSticky>
 </template>
 
diff --git a/src/pages/Claim/Card/ClaimNotes.vue b/src/pages/Claim/Card/ClaimNotes.vue
index 134ee33ab..cc6e33779 100644
--- a/src/pages/Claim/Card/ClaimNotes.vue
+++ b/src/pages/Claim/Card/ClaimNotes.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed } from 'vue';
+import { computed, useAttrs } from 'vue';
 import { useRoute } from 'vue-router';
 import { useState } from 'src/composables/useState';
 import VnNotes from 'src/components/ui/VnNotes.vue';
@@ -7,6 +7,7 @@ import VnNotes from 'src/components/ui/VnNotes.vue';
 const route = useRoute();
 const state = useState();
 const user = state.getUser();
+const $attrs = useAttrs();
 
 const $props = defineProps({
     id: { type: [Number, String], default: null },
diff --git a/src/pages/Claim/Card/ClaimPhoto.vue b/src/pages/Claim/Card/ClaimPhoto.vue
index d4321d8eb..d4acc9bbe 100644
--- a/src/pages/Claim/Card/ClaimPhoto.vue
+++ b/src/pages/Claim/Card/ClaimPhoto.vue
@@ -61,7 +61,7 @@ watch(
     () => {
         claimDmsFilter.value.where.id = router.currentRoute.value.params.id;
         claimDmsRef.value.fetch();
-    }
+    },
 );
 
 function openDialog(dmsId) {
@@ -248,7 +248,7 @@ function onDrag() {
             <QBtn
                 fab
                 @click="inputFile.nativeEl.click()"
-                shortcut="+"
+                v-shortcut="'+'"
                 icon="add"
                 color="primary"
             >
diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue
index 63fd035da..41d0c5598 100644
--- a/src/pages/Claim/ClaimList.vue
+++ b/src/pages/Claim/ClaimList.vue
@@ -132,7 +132,7 @@ const STATE_COLOR = {
         prefix="claim"
         :array-data-props="{
             url: 'Claims/filter',
-            order: ['cs.priority ASC', 'created ASC'],
+            order: 'cs.priority ASC, created ASC',
         }"
     >
         <template #advanced-menu>
diff --git a/src/pages/Customer/Card/CustomerAddress.vue b/src/pages/Customer/Card/CustomerAddress.vue
index 1b0d1dde1..f1799d0cc 100644
--- a/src/pages/Customer/Card/CustomerAddress.vue
+++ b/src/pages/Customer/Card/CustomerAddress.vue
@@ -61,7 +61,7 @@ watch(
     (newValue) => {
         if (!newValue) return;
         getClientData(newValue);
-    }
+    },
 );
 
 const getClientData = async (id) => {
@@ -137,7 +137,7 @@ const toCustomerAddressEdit = (addressId) => {
                         <QIcon
                             :style="{
                                 'font-variation-settings': `'FILL' ${isDefaultAddress(
-                                    item
+                                    item,
                                 )}`,
                             }"
                             color="primary"
@@ -150,7 +150,7 @@ const toCustomerAddressEdit = (addressId) => {
                                     t(
                                         isDefaultAddress(item)
                                             ? 'Default address'
-                                            : 'Set as default'
+                                            : 'Set as default',
                                     )
                                 }}
                             </QTooltip>
@@ -216,7 +216,7 @@ const toCustomerAddressEdit = (addressId) => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New consignee') }}
diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue
index 04ef5f882..11db92eab 100644
--- a/src/pages/Customer/Card/CustomerBalance.vue
+++ b/src/pages/Customer/Card/CustomerBalance.vue
@@ -158,7 +158,7 @@ const columns = computed(() => [
                     openConfirmationModal(
                         t('Send compensation'),
                         t('Do you want to report compensation to the client by mail?'),
-                        () => sendEmail(`Receipts/${id}/balance-compensation-email`)
+                        () => sendEmail(`Receipts/${id}/balance-compensation-email`),
                     ),
             },
         ],
@@ -291,7 +291,7 @@ const showBalancePdf = ({ id }) => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New payment') }}
diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue
index e9a349e0b..36ec4763e 100644
--- a/src/pages/Customer/Card/CustomerBasicData.vue
+++ b/src/pages/Customer/Card/CustomerBasicData.vue
@@ -54,10 +54,10 @@ function onBeforeSave(formData, originalData) {
         auto-load
     />
     <FormModel
-        :url="`Clients/${route.params.id}`"
+        :url-update="`Clients/${route.params.id}`"
         auto-load
-        model="customer"
         :mapper="onBeforeSave"
+        model="Customer"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Customer/Card/CustomerBillingData.vue b/src/pages/Customer/Card/CustomerBillingData.vue
index f1e78d9e5..cc894d01e 100644
--- a/src/pages/Customer/Card/CustomerBillingData.vue
+++ b/src/pages/Customer/Card/CustomerBillingData.vue
@@ -27,7 +27,7 @@ const getBankEntities = (data, formData) => {
 </script>
 
 <template>
-    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="customer">
+    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="Customer">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnSelect
diff --git a/src/pages/Customer/Card/CustomerCard.vue b/src/pages/Customer/Card/CustomerCard.vue
index f46884834..75fcb98fa 100644
--- a/src/pages/Customer/Card/CustomerCard.vue
+++ b/src/pages/Customer/Card/CustomerCard.vue
@@ -5,8 +5,8 @@ import CustomerDescriptor from './CustomerDescriptor.vue';
 
 <template>
     <VnCardBeta
-        data-key="Client"
-        base-url="Clients"
+        data-key="Customer"
+        :url="`Clients/${$route.params.id}/getCard`"
         :descriptor="CustomerDescriptor"
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerConsumption.vue b/src/pages/Customer/Card/CustomerConsumption.vue
index f0d8dea47..f3949bb32 100644
--- a/src/pages/Customer/Card/CustomerConsumption.vue
+++ b/src/pages/Customer/Card/CustomerConsumption.vue
@@ -61,6 +61,23 @@ const columns = computed(() => [
         columnFilter: false,
         cardVisible: true,
     },
+    {
+        align: 'left',
+        name: 'buyerId',
+        label: t('customer.params.buyerId'),
+        component: 'select',
+        attrs: {
+            url: 'TicketRequests/getItemTypeWorker',
+            optionLabel: 'nickname',
+            optionValue: 'id',
+
+            fields: ['id', 'nickname'],
+            sortBy: ['nickname ASC'],
+            optionFilter: 'firstName',
+        },
+        cardVisible: false,
+        visible: false,
+    },
     {
         name: 'description',
         align: 'left',
@@ -74,6 +91,7 @@ const columns = computed(() => [
         name: 'quantity',
         label: t('globals.quantity'),
         cardVisible: true,
+        visible: true,
         columnFilter: {
             inWhere: true,
         },
@@ -119,7 +137,7 @@ const openSendEmailDialog = async () => {
     openConfirmationModal(
         t('The consumption report will be sent'),
         t('Please, confirm'),
-        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email })
+        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email }),
     );
 };
 const sendCampaignMetricsEmail = ({ address }) => {
@@ -138,11 +156,11 @@ const updateDateParams = (value, params) => {
     const campaign = campaignList.value.find((c) => c.id === value);
     if (!campaign) return;
 
-    const { dated, previousDays, scopeDays } = campaign;
-    const _date = new Date(dated);
-    const [from, to] = dateRange(_date);
-    params.from = new Date(from.setDate(from.getDate() - previousDays)).toISOString();
-    params.to = new Date(to.setDate(to.getDate() + scopeDays)).toISOString();
+    const { dated, scopeDays } = campaign;
+    const from = new Date(dated);
+    from.setDate(from.getDate() - scopeDays);
+    params.from = from;
+    params.to = dated;
     return params;
 };
 </script>
@@ -152,7 +170,7 @@ const updateDateParams = (value, params) => {
         v-if="campaignList"
         data-key="CustomerConsumption"
         url="Clients/consumption"
-        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"        
+        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"
         :filter="{ where: { clientFk: route.params.id } }"
         :columns="columns"
         search-url="consumption"
@@ -200,29 +218,60 @@ const updateDateParams = (value, params) => {
             <div v-if="row.subName" class="subName">
                 {{ row.subName }}
             </div>
-            <FetchedTags :item="row" :max-length="3" />
+            <FetchedTags :item="row" />
         </template>
         <template #moreFilterPanel="{ params }">
             <div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
+                <VnSelect
+                    :filled="true"
+                    class="q-px-sm q-pt-none fit"
+                    url="ItemTypes"
+                    v-model="params.typeId"
+                    :label="t('item.list.typeName')"
+                    :fields="['id', 'name', 'categoryFk']"
+                    :include="'category'"
+                    :sortBy="'name ASC'"
+                    dense
+                >
+                    <template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                <QItemLabel caption>{{
+                                    scope.opt?.category?.name
+                                }}</QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelect>
+                <VnSelect
+                    :filled="true"
+                    class="q-px-sm q-pt-none fit"
+                    url="ItemCategories"
+                    v-model="params.categoryId"
+                    :label="t('item.list.category')"
+                    :fields="['id', 'name']"
+                    :sortBy="'name ASC'"
+                    dense
+                />
                 <VnSelect
                     v-model="params.campaign"
                     :options="campaignList"
                     :label="t('globals.campaign')"
                     :filled="true"
                     class="q-px-sm q-pt-none fit"
-                    dense
-                    option-label="code"
+                    :option-label="(opt) => t(opt.code)"
+                    :fields="['id', 'code', 'dated', 'scopeDays']"
                     @update:model-value="(data) => updateDateParams(data, params)"
+                    dense
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
                             <QItemSection>
-                                <QItemLabel>
-                                    {{ scope.opt?.code }}
-                                    {{
-                                        new Date(scope.opt?.dated).getFullYear()
-                                    }}</QItemLabel
-                                >
+                                <QItemLabel> {{ t(scope.opt?.code) }} </QItemLabel>
+                                <QItemLabel caption>
+                                    {{ new Date(scope.opt?.dated).getFullYear() }}
+                                </QItemLabel>
                             </QItemSection>
                         </QItem>
                     </template>
@@ -247,7 +296,21 @@ const updateDateParams = (value, params) => {
 </template>
 
 <i18n>
+en:
+
+    valentinesDay: Valentine's Day
+    mothersDay: Mother's Day
+    allSaints: All Saints' Day
+    frenchMothersDay: Mother's Day in France
 es:
     Enter a new search: Introduce una nueva búsqueda
     Group by items: Agrupar por artículos
+    valentinesDay: Día de San Valentín
+    mothersDay: Día de la Madre
+    allSaints: Día de Todos los Santos
+    frenchMothersDay: (Francia) Día de la Madre
+    Campaign consumption: Consumo campaña
+    Campaign: Campaña
+    From: Desde
+    To: Hasta
 </i18n>
diff --git a/src/pages/Customer/Card/CustomerContacts.vue b/src/pages/Customer/Card/CustomerContacts.vue
index c420f650e..d03f71244 100644
--- a/src/pages/Customer/Card/CustomerContacts.vue
+++ b/src/pages/Customer/Card/CustomerContacts.vue
@@ -62,7 +62,7 @@ const customerContactsRef = ref(null);
                                 color="primary"
                                 flat
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                             >
                                 <QTooltip>
                                     {{ t('Add contact') }}
diff --git a/src/pages/Customer/Card/CustomerCreditContracts.vue b/src/pages/Customer/Card/CustomerCreditContracts.vue
index 7dc53db72..a49faeb8d 100644
--- a/src/pages/Customer/Card/CustomerCreditContracts.vue
+++ b/src/pages/Customer/Card/CustomerCreditContracts.vue
@@ -195,7 +195,7 @@ const updateData = () => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New contract') }}
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index d7a8a59a1..89f9d9449 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { onMounted, ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
@@ -11,6 +11,15 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
+import { useState } from 'src/composables/useState';
+const state = useState();
+
+const customer = ref();
+
+onMounted(async () => {
+    customer.value = state.get('Customer');
+    if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
+});
 
 const customerDebt = ref();
 const customerCredit = ref();
@@ -46,13 +55,10 @@ const debtWarning = computed(() => {
 
 <template>
     <CardDescriptor
-        module="Customer"
         :url="`Clients/${entityId}/getCard`"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
         :summary="$props.summary"
-        data-key="customer"
+        data-key="Customer"
+        @on-fetch="setData"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -61,7 +67,7 @@ const debtWarning = computed(() => {
         <template #body="{ entity }">
             <VnLv
                 :label="t('customer.summary.payMethod')"
-                :value="entity.payMethod.name"
+                :value="entity.payMethod?.name"
             />
 
             <VnLv
@@ -90,7 +96,7 @@ const debtWarning = computed(() => {
             </VnLv>
             <VnLv
                 :label="t('customer.extendedList.tableVisibleColumns.businessTypeFk')"
-                :value="entity.businessType.description"
+                :value="entity.businessType?.description"
             />
         </template>
         <template #icons="{ entity }">
@@ -103,7 +109,21 @@ const debtWarning = computed(() => {
                 >
                     <QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
                 </QIcon>
-                <QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
+
+                <QIcon
+                    v-if="entity?.substitutionAllowed"
+                    name="help"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Allowed substitution') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="customer?.isFreezed"
+                    name="vn:frozen"
+                    size="xs"
+                    color="primary"
+                >
                     <QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
                 </QIcon>
                 <QIcon
@@ -143,13 +163,13 @@ const debtWarning = computed(() => {
                         <br />
                         {{
                             t('unpaidDated', {
-                                dated: toDate(customer.unpaid.dated),
+                                dated: toDate(customer.unpaid?.dated),
                             })
                         }}
                         <br />
                         {{
                             t('unpaidAmount', {
-                                amount: toCurrency(customer.unpaid.amount),
+                                amount: toCurrency(customer.unpaid?.amount),
                             })
                         }}
                     </QTooltip>
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index fb78eab69..aea45721c 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -61,6 +61,16 @@ const openCreateForm = (type) => {
         .join('&');
     useOpenURL(`/#/${type}/list?${params}`);
 };
+const updateSubstitutionAllowed = async () => {
+    try {
+        await axios.patch(`Clients/${route.params.id}`, {
+            substitutionAllowed: !$props.customer.substitutionAllowed,
+        });
+        notify('globals.notificationSent', 'positive');
+    } catch (error) {
+        notify(error.message, 'positive');
+    }
+};
 </script>
 
 <template>
@@ -69,6 +79,13 @@ const openCreateForm = (type) => {
             {{ t('globals.pageTitles.createTicket') }}
         </QItemSection>
     </QItem>
+    <QItem v-ripple clickable>
+        <QItemSection @click="updateSubstitutionAllowed()">{{
+            $props.customer.substitutionAllowed
+                ? t('Disable substitution')
+                : t('Allow substitution')
+        }}</QItemSection>
+    </QItem>
     <QItem v-ripple clickable>
         <QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
     </QItem>
diff --git a/src/pages/Customer/Card/CustomerFileManagement.vue b/src/pages/Customer/Card/CustomerFileManagement.vue
index 134d8dbd6..b565db6e7 100644
--- a/src/pages/Customer/Card/CustomerFileManagement.vue
+++ b/src/pages/Customer/Card/CustomerFileManagement.vue
@@ -236,7 +236,7 @@ const toCustomerFileManagementCreate = () => {
             @click.stop="toCustomerFileManagementCreate()"
             color="primary"
             fab
-            shortcut="+"
+            v-shortcut="'+'"
             icon="add"
         />
         <QTooltip>
diff --git a/src/pages/Customer/Card/CustomerFiscalData.vue b/src/pages/Customer/Card/CustomerFiscalData.vue
index ceeb70bb6..93909eb9c 100644
--- a/src/pages/Customer/Card/CustomerFiscalData.vue
+++ b/src/pages/Customer/Card/CustomerFiscalData.vue
@@ -12,6 +12,7 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 import { getDifferences, getUpdatedValues } from 'src/filters';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 
@@ -73,7 +74,7 @@ async function acceptPropagate({ isEqualizated }) {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateFiscalData`"
         auto-load
-        model="customer"
+        model="Customer"
         :mapper="onBeforeSave"
         observe-form-changes
         @on-data-saved="checkEtChanges"
@@ -151,14 +152,11 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
             <VnRow>
                 <QCheckbox :label="t('Has to invoice')" v-model="data.hasToInvoice" />
-                <div>
-                    <QCheckbox :label="t('globals.isVies')" v-model="data.isVies" />
-                    <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                        <QTooltip>
-                            {{ t('whenActivatingIt') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isVies"
+                    :label="t('globals.isVies')"
+                    :info="t('whenActivatingIt')"
+                />
             </VnRow>
 
             <VnRow>
@@ -170,17 +168,11 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
 
             <VnRow>
-                <div>
-                    <QCheckbox
-                        :label="t('Is equalizated')"
-                        v-model="data.isEqualizated"
-                    />
-                    <QIcon class="cursor-info q-ml-sm" name="info" size="sm">
-                        <QTooltip>
-                            {{ t('inOrderToInvoice') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isEqualizated"
+                    :label="t('Is equalizated')"
+                    :info="t('inOrderToInvoice')"
+                />
                 <QCheckbox :label="t('Daily invoice')" v-model="data.hasDailyInvoice" />
             </VnRow>
 
diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue
index b85174696..189b59904 100644
--- a/src/pages/Customer/Card/CustomerNotes.vue
+++ b/src/pages/Customer/Card/CustomerNotes.vue
@@ -23,5 +23,6 @@ const noteFilter = computed(() => {
         :body="{ clientFk: route.params.id }"
         style="overflow-y: auto"
         :select-type="true"
+        required
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerSamples.vue b/src/pages/Customer/Card/CustomerSamples.vue
index f12691112..19a7f8759 100644
--- a/src/pages/Customer/Card/CustomerSamples.vue
+++ b/src/pages/Customer/Card/CustomerSamples.vue
@@ -104,7 +104,7 @@ const tableRef = ref();
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('Send sample') }}
diff --git a/src/pages/Customer/Card/CustomerWebAccess.vue b/src/pages/Customer/Card/CustomerWebAccess.vue
index 3c4106846..809f10918 100644
--- a/src/pages/Customer/Card/CustomerWebAccess.vue
+++ b/src/pages/Customer/Card/CustomerWebAccess.vue
@@ -27,7 +27,7 @@ async function hasCustomerRole() {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateUser`"
         :filter="filter"
-        model="customer"
+        model="Customer"
         :mapper="
             ({ account }) => {
                 const { name, email, active } = account;
diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index 9b883daad..1c5a08304 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -51,11 +51,7 @@ const exprBuilder = (param, value) => {
             </QItem>
             <QItem class="q-mb-sm">
                 <QItemSection>
-                    <VnInput
-                        :label="t('globals.name')"
-                        v-model="params.name"
-                        is-outlined
-                    />
+                    <VnInput :label="t('Name')" v-model="params.name" is-outlined />
                 </QItemSection>
             </QItem>
             <QItem class="q-mb-sm">
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 2f2dd5978..0bfca7910 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -274,6 +274,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'isActive',
         label: t('customer.summary.isActive'),
+        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => !value,
@@ -312,6 +313,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'isFreezed',
         label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
+        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => value,
@@ -429,7 +431,7 @@ function handleLocation(data, location) {
             <VnTable
                 ref="tableRef"
                 :data-key="dataKey"
-                url="Clients/filter"
+                url="Clients/extendedListFilter"
                 :create="{
                     urlCreate: 'Clients/createWithUser',
                     title: t('globals.pageTitles.customerCreate'),
diff --git a/src/pages/Customer/Defaulter/CustomerDefaulter.vue b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
index eca2ad596..dc4ac9162 100644
--- a/src/pages/Customer/Defaulter/CustomerDefaulter.vue
+++ b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
@@ -9,7 +9,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import CustomerDefaulterAddObservation from './CustomerDefaulterAddObservation.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 
diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue
index d650bbbda..f852c160a 100644
--- a/src/pages/Customer/components/CustomerAddressEdit.vue
+++ b/src/pages/Customer/components/CustomerAddressEdit.vue
@@ -233,7 +233,7 @@ function handleLocation(data, location) {
                             postcode: data.postalCode,
                             city: data.city,
                             province: data.province,
-                            country: data.province.country,
+                            country: data.province?.country,
                         }"
                         @update:model-value="(location) => handleLocation(data, location)"
                     ></VnLocation>
@@ -336,7 +336,7 @@ function handleLocation(data, location) {
                 class="cursor-pointer add-icon q-mt-md"
                 flat
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>
                     {{ t('Add note') }}
diff --git a/src/pages/Customer/components/CustomerNewPayment.vue b/src/pages/Customer/components/CustomerNewPayment.vue
index c2c38b55a..8f61bac89 100644
--- a/src/pages/Customer/components/CustomerNewPayment.vue
+++ b/src/pages/Customer/components/CustomerNewPayment.vue
@@ -84,7 +84,7 @@ function setPaymentType(accounting) {
     viewReceipt.value = isCash.value;
     if (accountingType.value.daysInFuture)
         initialData.payed.setDate(
-            initialData.payed.getDate() + accountingType.value.daysInFuture
+            initialData.payed.getDate() + accountingType.value.daysInFuture,
         );
     maxAmount.value = accountingType.value && accountingType.value.maxAmount;
 
@@ -114,7 +114,7 @@ function onBeforeSave(data) {
     if (isCash.value && shouldSendEmail.value && !data.email)
         return notify(t('There is no assigned email for this client'), 'negative');
 
-    data.bankFk = data.bankFk.id;
+    data.bankFk = data.bankFk?.id;
     return data;
 }
 
@@ -189,7 +189,7 @@ async function getAmountPaid() {
             :url-create="urlCreate"
             :mapper="onBeforeSave"
             @on-data-saved="onDataSaved"
-            :prevent-submit="true"
+            prevent-submit
         >
             <template #form="{ data, validate }">
                 <span ref="closeButton" class="row justify-end close-icon" v-close-popup>
diff --git a/src/pages/Customer/components/CustomerSamplesCreate.vue b/src/pages/Customer/components/CustomerSamplesCreate.vue
index 754693672..1294a5d25 100644
--- a/src/pages/Customer/components/CustomerSamplesCreate.vue
+++ b/src/pages/Customer/components/CustomerSamplesCreate.vue
@@ -18,6 +18,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import CustomerSamplesPreview from 'src/pages/Customer/components/CustomerSamplesPreview.vue';
 import FormPopup from 'src/components/FormPopup.vue';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const { dialogRef, onDialogOK } = useDialogPluginComponent();
 
@@ -39,7 +40,7 @@ const optionsSamplesVisible = ref([]);
 const sampleType = ref({ hasPreview: false });
 const initialData = reactive({});
 const entityId = computed(() => route.params.id);
-const customer = computed(() => state.get('customer'));
+const customer = computed(() => useArrayData('Customer').store?.data);
 const filterEmailUsers = { where: { userFk: user.value.id } };
 const filterClientsAddresses = {
     include: [
@@ -65,9 +66,9 @@ const filterSamplesVisible = {
 defineEmits(['confirm', ...useDialogPluginComponent.emits]);
 
 onBeforeMount(async () => {
-    initialData.clientFk = customer.value.id;
-    initialData.recipient = customer.value.email;
-    initialData.recipientId = customer.value.id;
+    initialData.clientFk = customer.value?.id;
+    initialData.recipient = customer.value?.email;
+    initialData.recipientId = customer.value?.id;
 });
 
 const setEmailUser = (data) => {
diff --git a/src/pages/Customer/locale/en.yml b/src/pages/Customer/locale/en.yml
index 118f04a31..b6d495335 100644
--- a/src/pages/Customer/locale/en.yml
+++ b/src/pages/Customer/locale/en.yml
@@ -107,6 +107,9 @@ customer:
         defaulterSinced: Defaulted Since
         hasRecovery: Has Recovery
         socialName: Social name
+        typeId: Type
+        buyerId: Buyer
+        categoryId: Category
         city: City
         phone: Phone
         postcode: Postcode
diff --git a/src/pages/Customer/locale/es.yml b/src/pages/Customer/locale/es.yml
index 7c33ffee8..f50d049da 100644
--- a/src/pages/Customer/locale/es.yml
+++ b/src/pages/Customer/locale/es.yml
@@ -108,6 +108,9 @@ customer:
         hasRecovery: Tiene recobro
         socialName: Razón social
         campaign: Campaña
+        typeId: Familia
+        buyerId: Comprador
+        categoryId: Reino
         city: Ciudad
         phone: Teléfono
         postcode: Código postal
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index 689eea686..6462ed24a 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -1,30 +1,32 @@
 <script setup>
-import { ref } from 'vue';
+import { onMounted, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useRole } from 'src/composables/useRole';
+import { useState } from 'src/composables/useState';
+import { checkEntryLock } from 'src/composables/checkEntryLock';
 import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
-import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
-import FilterTravelForm from 'src/components/FilterTravelForm.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-import { toDate } from 'src/filters';
+import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
 import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 
 const route = useRoute();
 const { t } = useI18n();
 const { hasAny } = useRole();
 const isAdministrative = () => hasAny(['administrative']);
+const state = useState();
+const user = state.getUser().fn();
 
 const companiesOptions = ref([]);
 const currenciesOptions = ref([]);
 
-const onFilterTravelSelected = (formData, id) => {
-    formData.travelFk = id;
-};
+onMounted(() => {
+    checkEntryLock(route.params.id, user.id);
+});
 </script>
 
 <template>
@@ -52,46 +54,24 @@ const onFilterTravelSelected = (formData, id) => {
     >
         <template #form="{ data }">
             <VnRow>
+                <VnSelectTravelExtended
+                    :data="data"
+                    v-model="data.travelFk"
+                    :onFilterTravelSelected="(data, result) => (data.travelFk = result)"
+                />
                 <VnSelectSupplier
                     v-model="data.supplierFk"
                     hide-selected
                     :required="true"
-                    map-options
                 />
-                <VnSelectDialog
-                    :label="t('entry.basicData.travel')"
-                    v-model="data.travelFk"
-                    url="Travels/filter"
-                    :fields="['id', 'warehouseInName']"
-                    option-value="id"
-                    option-label="warehouseInName"
-                    map-options
-                    hide-selected
-                    :required="true"
-                    action-icon="filter_alt"
-                >
-                    <template #form>
-                        <FilterTravelForm
-                            @travel-selected="onFilterTravelSelected(data, $event)"
-                        />
-                    </template>
-                    <template #option="scope">
-                        <QItem v-bind="scope.itemProps">
-                            <QItemSection>
-                                <QItemLabel>
-                                    {{ scope.opt?.agencyModeName }} -
-                                    {{ scope.opt?.warehouseInName }}
-                                    ({{ toDate(scope.opt?.shipped) }}) →
-                                    {{ scope.opt?.warehouseOutName }}
-                                    ({{ toDate(scope.opt?.landed) }})
-                                </QItemLabel>
-                            </QItemSection>
-                        </QItem>
-                    </template>
-                </VnSelectDialog>
             </VnRow>
             <VnRow>
                 <VnInput v-model="data.reference" :label="t('globals.reference')" />
+                <VnInputNumber
+                    v-model="data.invoiceAmount"
+                    :label="t('entry.summary.invoiceAmount')"
+                    :positive="false"
+                />
             </VnRow>
             <VnRow>
                 <VnInput
@@ -113,8 +93,7 @@ const onFilterTravelSelected = (formData, id) => {
                 <VnInputNumber
                     :label="t('entry.summary.commission')"
                     v-model="data.commission"
-                    step="1"
-                    autofocus
+                    :step="1"
                     :positive="false"
                 />
                 <VnSelect
@@ -161,7 +140,7 @@ const onFilterTravelSelected = (formData, id) => {
                     :label="t('entry.summary.excludedFromAvailable')"
                 />
                 <QCheckbox
-                    v-if="isAdministrative()"
+                    :disable="!isAdministrative()"
                     v-model="data.isBooked"
                     :label="t('entry.basicData.booked')"
                 />
diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue
index 6194ce5b8..81578c609 100644
--- a/src/pages/Entry/Card/EntryBuys.vue
+++ b/src/pages/Entry/Card/EntryBuys.vue
@@ -1,478 +1,806 @@
 <script setup>
-import { ref, computed } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
+import { useStateStore } from 'stores/useStateStore';
+import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { QBtn } from 'quasar';
+import { onMounted, ref } from 'vue';
 
-import VnPaginate from 'src/components/ui/VnPaginate.vue';
-import VnSelect from 'components/common/VnSelect.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import FetchedTags from 'components/ui/FetchedTags.vue';
-import VnConfirm from 'components/ui/VnConfirm.vue';
+import { useState } from 'src/composables/useState';
+
+import FetchData from 'src/components/FetchData.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
-
-import { useQuasar } from 'quasar';
-import { toCurrency } from 'src/filters';
+import FetchedTags from 'src/components/ui/FetchedTags.vue';
+import VnColor from 'src/components/common/VnColor.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
 import axios from 'axios';
-import useNotify from 'src/composables/useNotify.js';
+import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
+import { checkEntryLock } from 'src/composables/checkEntryLock';
 
-const quasar = useQuasar();
-const route = useRoute();
-const router = useRouter();
-const { t } = useI18n();
-const { notify } = useNotify();
-
-const rowsSelected = ref([]);
-const entryBuysPaginateRef = ref(null);
-const originalRowDataCopy = ref(null);
-
-const getInputEvents = (colField, props) => {
-    return colField === 'packagingFk'
-        ? { 'update:modelValue': () => saveChange(colField, props) }
-        : {
-              'keyup.enter': () => saveChange(colField, props),
-              blur: () => saveChange(colField, props),
-          };
-};
-
-const tableColumnComponents = computed(() => ({
-    item: {
-        component: QBtn,
-        props: {
-            color: 'primary',
-            flat: true,
-        },
-        event: () => ({}),
+const $props = defineProps({
+    id: {
+        type: Number,
+        default: null,
     },
-    quantity: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
+    editableMode: {
+        type: Boolean,
+        default: true,
     },
-    packagingFk: {
-        component: VnSelect,
-        props: {
-            'option-value': 'id',
-            'option-label': 'id',
-            'emit-value': true,
-            'map-options': true,
-            'use-input': true,
-            'hide-selected': true,
-            url: 'Packagings',
-            fields: ['id'],
-            where: { freightItemFk: true },
-            'sort-by': 'id ASC',
-            dense: true,
-        },
-        event: getInputEvents,
+    tableHeight: {
+        type: String,
+        default: null,
     },
-    stickers: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    printedStickers: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    weight: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    packing: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    grouping: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    buyingValue: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    price2: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    price3: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    import: {
-        component: 'span',
-        props: {},
-        event: () => ({}),
-    },
-}));
-
-const entriesTableColumns = computed(() => {
-    return [
-        {
-            label: t('globals.item'),
-            field: 'itemFk',
-            name: 'item',
-            align: 'left',
-        },
-        {
-            label: t('globals.quantity'),
-            field: 'quantity',
-            name: 'quantity',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.package'),
-            field: 'packagingFk',
-            name: 'packagingFk',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.stickers'),
-            field: 'stickers',
-            name: 'stickers',
-            align: 'left',
-        },
-        {
-            label: t('entry.buys.printedStickers'),
-            field: 'printedStickers',
-            name: 'printedStickers',
-            align: 'left',
-        },
-        {
-            label: t('globals.weight'),
-            field: 'weight',
-            name: 'weight',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.packing'),
-            field: 'packing',
-            name: 'packing',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.grouping'),
-            field: 'grouping',
-            name: 'grouping',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.buyingValue'),
-            field: 'buyingValue',
-            name: 'buyingValue',
-            align: 'left',
-            format: (value) => toCurrency(value),
-        },
-        {
-            label: t('item.fixedPrice.groupingPrice'),
-            field: 'price2',
-            name: 'price2',
-            align: 'left',
-        },
-        {
-            label: t('item.fixedPrice.packingPrice'),
-            field: 'price3',
-            name: 'price3',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.import'),
-            name: 'import',
-            align: 'left',
-            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
-        },
-    ];
 });
 
-const copyOriginalRowsData = (rows) => {
-    originalRowDataCopy.value = JSON.parse(JSON.stringify(rows));
-};
-
-const saveChange = async (field, { rowIndex, row }) => {
-    if (originalRowDataCopy.value[rowIndex][field] == row[field]) return;
-    await axios.patch(`Buys/${row.id}`, row);
-    originalRowDataCopy.value[rowIndex][field] = row[field];
-};
-
-const openRemoveDialog = async () => {
-    quasar
-        .dialog({
-            component: VnConfirm,
-            componentProps: {
-                title: t('Confirm deletion'),
-                message: t(
-                    `Are you sure you want to delete this buy${
-                        rowsSelected.value.length > 1 ? 's' : ''
-                    }?`
-                ),
-                data: rowsSelected.value,
+const state = useState();
+const user = state.getUser().fn();
+const stateStore = useStateStore();
+const { t } = useI18n();
+const route = useRoute();
+const selectedRows = ref([]);
+const entityId = ref($props.id ?? route.params.id);
+const entryBuysRef = ref();
+const footerFetchDataRef = ref();
+const footer = ref({});
+const columns = [
+    {
+        align: 'center',
+        labelAbbreviation: 'NV',
+        label: t('Ignore'),
+        toolTip: t('Ignored for available'),
+        name: 'isIgnored',
+        component: 'checkbox',
+        attrs: {
+            toggleIndeterminate: false,
+        },
+        create: true,
+        width: '25px',
+    },
+    {
+        label: t('Buyer'),
+        name: 'workerFk',
+        component: 'select',
+        attrs: {
+            url: 'Workers/search',
+            fields: ['id', 'nickname'],
+            optionLabel: 'nickname',
+            optionValue: 'id',
+        },
+        visible: false,
+    },
+    {
+        label: t('Family'),
+        name: 'itemTypeFk',
+        component: 'select',
+        attrs: {
+            url: 'itemTypes',
+            fields: ['id', 'name'],
+            optionLabel: 'name',
+            optionValue: 'id',
+        },
+        visible: false,
+    },
+    {
+        name: 'id',
+        isId: true,
+        visible: false,
+        isEditable: false,
+        columnFilter: false,
+    },
+    {
+        name: 'entryFk',
+        isId: true,
+        visible: false,
+        isEditable: false,
+        disable: true,
+        create: true,
+        columnFilter: false,
+    },
+    {
+        align: 'center',
+        label: 'Id',
+        name: 'itemFk',
+        component: 'number',
+        isEditable: false,
+        width: '35px',
+    },
+    {
+        labelAbbreviation: '',
+        label: 'Color',
+        name: 'hex',
+        columnSearch: false,
+        isEditable: false,
+        width: '9px',
+        component: 'select',
+        attrs: {
+            url: 'Inks',
+            fields: ['id', 'name'],
+        },
+    },
+    {
+        align: 'center',
+        label: t('Article'),
+        name: 'name',
+        component: 'select',
+        attrs: {
+            url: 'Items',
+            fields: ['id', 'name'],
+            optionLabel: 'name',
+            optionValue: 'id',
+        },
+        width: '85px',
+        isEditable: false,
+    },
+    {
+        align: 'center',
+        label: t('Article'),
+        name: 'itemFk',
+        visible: false,
+        create: true,
+        columnFilter: false,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Siz.'),
+        label: t('Size'),
+        toolTip: t('Size'),
+        component: 'number',
+        name: 'size',
+        width: '35px',
+        isEditable: false,
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Sti.'),
+        label: t('Stickers'),
+        toolTip: t('Printed Stickers/Stickers'),
+        name: 'stickers',
+        component: 'input',
+        create: true,
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['quantity'] = value * row['packing'];
+                row['amount'] = row['quantity'] * row['buyingValue'];
             },
-        })
-        .onOk(async () => {
-            await deleteBuys();
-            const notifyMessage = t(
-                `Buy${rowsSelected.value.length > 1 ? 's' : ''} deleted`
-            );
-            notify(notifyMessage, 'positive');
-        });
-};
+        },
+        width: '35px',
+    },
+    {
+        align: 'center',
+        label: t('Bucket'),
+        name: 'packagingFk',
+        component: 'select',
+        attrs: {
+            url: 'packagings',
+            fields: ['id'],
+            optionLabel: 'id',
+            optionValue: 'id',
+        },
+        create: true,
+        width: '40px',
+    },
+    {
+        align: 'center',
+        label: 'Kg',
+        name: 'weight',
+        component: 'number',
+        create: true,
+        width: '35px',
+        format: (row) => parseFloat(row['weight']).toFixed(1),
+    },
+    {
+        labelAbbreviation: 'P',
+        label: 'Packing',
+        toolTip: 'Packing',
+        name: 'packing',
+        component: 'number',
+        create: true,
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                const oldPacking = oldValue === 1 || oldValue === null ? 1 : oldValue;
+                row['weight'] = (row['weight'] * value) / oldPacking;
+                row['quantity'] = row['stickers'] * value;
+                row['amount'] = row['quantity'] * row['buyingValue'];
+            },
+        },
+        width: '30px',
+        style: (row) => {
+            if (row.groupingMode === 'grouping')
+                return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'GM',
+        label: t('Grouping selector'),
+        toolTip: t('Grouping selector'),
+        name: 'groupingMode',
+        component: 'toggle',
+        attrs: {
+            'toggle-indeterminate': true,
+            trueValue: 'grouping',
+            falseValue: 'packing',
+            indeterminateValue: null,
+        },
+        size: 'xs',
+        width: '25px',
+        create: true,
+        rightFilter: false,
+        getIcon: (value) => {
+            switch (value) {
+                case 'grouping':
+                    return 'toggle_on';
+                case 'packing':
+                    return 'toggle_off';
+                default:
+                    return 'minimize';
+            }
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'G',
+        label: 'Grouping',
+        toolTip: 'Grouping',
+        name: 'grouping',
+        component: 'number',
+        width: '30px',
+        create: true,
+        style: (row) => {
+            if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        label: t('Quantity'),
+        name: 'quantity',
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['amount'] = value * row['buyingValue'];
+            },
+        },
+        width: '45px',
+        create: true,
+        style: getQuantityStyle,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Cost'),
+        label: t('Buying value'),
+        toolTip: t('Buying value'),
+        name: 'buyingValue',
+        create: true,
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['amount'] = row['quantity'] * value;
+            },
+        },
+        width: '45px',
+        format: (row) => parseFloat(row['buyingValue']).toFixed(3),
+    },
+    {
+        align: 'center',
+        label: t('Amount'),
+        name: 'amount',
+        width: '45px',
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        isEditable: false,
+        format: (row) => parseFloat(row['amount']).toFixed(2),
+        style: getAmountStyle,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Pack.'),
+        label: t('Package'),
+        toolTip: t('Package'),
+        name: 'price2',
+        component: 'number',
+        width: '35px',
+        create: true,
+        format: (row) => parseFloat(row['price2']).toFixed(2),
+    },
+    {
+        align: 'center',
+        label: t('Box'),
+        name: 'price3',
+        component: 'number',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['price2'] = row['price2'] * (value / oldValue);
+            },
+        },
+        width: '35px',
+        create: true,
+        format: (row) => parseFloat(row['price3']).toFixed(2),
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'CM',
+        label: t('Check min price'),
+        toolTip: t('Check min price'),
+        name: 'hasMinPrice',
+        attrs: {
+            toggleIndeterminate: false,
+        },
+        component: 'checkbox',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                await axios.patch(`Items/${row['itemFk']}`, {
+                    hasMinPrice: value,
+                });
+            },
+        },
+        width: '25px',
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Min.',
+        label: t('Minimum price'),
+        toolTip: t('Minimum price'),
+        name: 'minPrice',
+        component: 'number',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                await axios.patch(`Items/${row['itemFk']}`, {
+                    minPrice: value,
+                });
+            },
+        },
+        width: '35px',
+        style: (row) => {
+            if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
+        },
+        format: (row) => parseFloat(row['minPrice']).toFixed(2),
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('P.Sen'),
+        label: t('Packing sent'),
+        toolTip: t('Packing sent'),
+        name: 'packingOut',
+        component: 'number',
+        isEditable: false,
+        width: '40px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Com.'),
+        label: t('Comment'),
+        toolTip: t('Comment'),
+        name: 'comment',
+        component: 'input',
+        isEditable: false,
+        width: '50px',
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Prod.',
+        label: t('Producer'),
+        toolTip: t('Producer'),
+        name: 'subName',
+        isEditable: false,
+        width: '45px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        label: t('Tags'),
+        name: 'tags',
+        width: '125px',
+        columnSearch: false,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Comp.',
+        label: t('Company'),
+        toolTip: t('Company'),
+        name: 'company_name',
+        component: 'input',
+        isEditable: false,
+        width: '35px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+];
 
-const deleteBuys = async () => {
-    await axios.post('Buys/deleteBuys', { buys: rowsSelected.value });
-    entryBuysPaginateRef.value.fetch();
-};
+function getQuantityStyle(row) {
+    if (row?.quantity !== row?.stickers * row?.packing)
+        return { color: 'var(--q-negative)' };
+}
+function getAmountStyle(row) {
+    if (row?.isChecked) return { color: 'var(--q-positive)' };
+    return { color: 'var(--vn-label-color)' };
+}
 
-const importBuys = () => {
-    router.push({ name: 'EntryBuysImport' });
-};
+async function beforeSave(data, getChanges) {
+    try {
+        const changes = data.updates;
+        if (!changes) return data;
+        const patchPromises = [];
 
-const toggleGroupingMode = async (buy, mode) => {
-    const groupingMode = mode === 'grouping' ? mode : 'packing';
-    const newGroupingMode = buy.groupingMode === groupingMode ? null : groupingMode;
-    const params = {
-        groupingMode: newGroupingMode,
-    };
-    await axios.patch(`Buys/${buy.id}`, params);
-    buy.groupingMode = newGroupingMode;
-};
+        for (const change of changes) {
+            let patchData = {};
 
-const lockIconType = (groupingMode, mode) => {
-    if (mode === 'packing') {
-        return groupingMode === 'packing' ? 'lock' : 'lock_open';
-    } else {
-        return groupingMode === 'grouping' ? 'lock' : 'lock_open';
+            if ('hasMinPrice' in change.data) {
+                patchData.hasMinPrice = change.data?.hasMinPrice;
+                delete change.data.hasMinPrice;
+            }
+            if ('minPrice' in change.data) {
+                patchData.minPrice = change.data?.minPrice;
+                delete change.data.minPrice;
+            }
+
+            if (Object.keys(patchData).length > 0) {
+                const promise = axios
+                    .get('Buys/findOne', {
+                        params: {
+                            filter: {
+                                fields: ['itemFk'],
+                                where: { id: change.where.id },
+                            },
+                        },
+                    })
+                    .then((buy) => {
+                        return axios.patch(`Items/${buy.data.itemFk}`, patchData);
+                    })
+                    .catch((error) => {
+                        console.error('Error processing change: ', change, error);
+                    });
+
+                patchPromises.push(promise);
+            }
+        }
+
+        await Promise.all(patchPromises);
+
+        data.updates = changes.filter((change) => Object.keys(change.data).length > 0);
+
+        return data;
+    } catch (error) {
+        console.error('Error in beforeSave:', error);
+        throw error;
     }
-};
+}
+
+function invertQuantitySign(rows, sign) {
+    for (const row of rows) {
+        if (sign > 0) row.quantity = Math.abs(row.quantity);
+        else if (row.quantity > 0) row.quantity = -row.quantity;
+    }
+}
+function setIsChecked(rows, value) {
+    for (const row of rows) {
+        row.isChecked = value;
+    }
+    footerFetchDataRef.value.fetch();
+}
+
+async function setBuyUltimate(itemFk, data) {
+    if (!itemFk) return;
+    const buyUltimate = await axios.get(`Entries/getBuyUltimate`, {
+        params: {
+            itemFk,
+            warehouseFk: user.warehouseFk,
+            date: Date.vnNew(),
+        },
+    });
+    const buyUltimateData = buyUltimate.data[0];
+
+    const allowedKeys = columns
+        .filter((col) => col.create === true)
+        .map((col) => col.name);
+
+    allowedKeys.forEach((key) => {
+        if (buyUltimateData.hasOwnProperty(key) && key !== 'entryFk') {
+            if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
+        }
+    });
+}
+
+onMounted(() => {
+    stateStore.rightDrawer = false;
+    if ($props.editableMode) checkEntryLock(entityId.value, user.id);
+});
 </script>
-
 <template>
-    <VnSubToolbar>
-        <template #st-actions>
-            <QBtnGroup push style="column-gap: 10px">
-                <slot name="moreBeforeActions" />
-                <QBtn
-                    :label="t('globals.remove')"
-                    color="primary"
-                    icon="delete"
-                    flat
-                    @click="openRemoveDialog()"
-                    :disable="!rowsSelected?.length"
-                    :title="t('globals.remove')"
-                />
-            </QBtnGroup>
-        </template>
-    </VnSubToolbar>
-    <VnPaginate
-        ref="entryBuysPaginateRef"
-        data-key="EntryBuys"
-        :url="`Entries/${route.params.id}/getBuys`"
-        @on-fetch="copyOriginalRowsData($event)"
-        auto-load
-    >
-        <template #body="{ rows }">
-            <QTable
-                :rows="rows"
-                :columns="entriesTableColumns"
-                selection="multiple"
-                row-key="id"
-                class="full-width q-mt-md"
-                :grid="$q.screen.lt.md"
-                v-model:selected="rowsSelected"
-                :no-data-label="t('globals.noResults')"
+    <Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown() && editableMode">
+        <QBtnGroup push style="column-gap: 1px">
+            <QBtnDropdown
+                label="+/-"
+                color="primary"
+                flat
+                :title="t('Invert quantity value')"
+                :disable="!selectedRows.length"
+                data-cy="change-quantity-sign"
             >
-                <template #body="props">
-                    <QTr>
-                        <QTd>
-                            <QCheckbox v-model="props.selected" />
-                        </QTd>
-                        <QTd
-                            v-for="col in props.cols"
-                            :key="col.name"
-                            style="max-width: 100px"
-                        >
-                            <component
-                                :is="tableColumnComponents[col.name].component"
-                                v-bind="tableColumnComponents[col.name].props"
-                                v-model="props.row[col.field]"
-                                v-on="
-                                    tableColumnComponents[col.name].event(
-                                        col.field,
-                                        props
-                                    )
-                                "
+                <QList>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                flat
+                                @click="invertQuantitySign(selectedRows, -1)"
+                                data-cy="set-negative-quantity"
                             >
-                                <template
-                                    v-if="
-                                        col.name === 'grouping' || col.name === 'packing'
-                                    "
-                                    #append
-                                >
-                                    <QBtn
-                                        :icon="
-                                            lockIconType(props.row.groupingMode, col.name)
-                                        "
-                                        @click="toggleGroupingMode(props.row, col.name)"
-                                        class="cursor-pointer"
-                                        size="sm"
-                                        flat
-                                        dense
-                                        unelevated
-                                        push
-                                        :style="{
-                                            'font-variation-settings': `'FILL' ${
-                                                lockIconType(
-                                                    props.row.groupingMode,
-                                                    col.name
-                                                ) === 'lock'
-                                                    ? 1
-                                                    : 0
-                                            }`,
-                                        }"
-                                    />
-                                </template>
-                                <template
-                                    v-if="col.name === 'item' || col.name === 'import'"
-                                >
-                                    {{ col.value }}
-                                </template>
-                                <ItemDescriptorProxy
-                                    v-if="col.name === 'item'"
-                                    :id="props.row.item.id"
-                                />
-                            </component>
-                        </QTd>
-                    </QTr>
-                    <QTr no-hover class="full-width infoRow" style="column-span: all">
-                        <QTd />
-                        <QTd cols>
-                            <span>{{ props.row.item.itemType.code }}</span>
-                        </QTd>
-                        <QTd>
-                            <span>{{ props.row.item.size }}</span>
-                        </QTd>
-                        <QTd>
-                            <span>{{ toCurrency(props.row.item.minPrice) }}</span>
-                        </QTd>
-                        <QTd colspan="7">
-                            <span>{{ props.row.item.concept }}</span>
-                            <span v-if="props.row.item.subName" class="subName">
-                                {{ props.row.item.subName }}
-                            </span>
-                            <FetchedTags :item="props.row.item" />
-                        </QTd>
-                    </QTr>
-                </template>
-                <template #item="props">
-                    <div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
-                        <QCard bordered flat>
-                            <QCardSection>
-                                <QCheckbox v-model="props.selected" dense />
-                            </QCardSection>
-                            <QSeparator />
-                            <QList dense>
-                                <QItem v-for="col in props.cols" :key="col.name">
-                                    <component
-                                        :is="tableColumnComponents[col.name].component"
-                                        v-bind="tableColumnComponents[col.name].props"
-                                        v-model="props.row[col.field]"
-                                        v-on="
-                                            tableColumnComponents[col.name].event(
-                                                col.field,
-                                                props
-                                            )
-                                        "
-                                        class="full-width"
-                                    >
-                                        <template
-                                            v-if="
-                                                col.name === 'item' ||
-                                                col.name === 'import'
-                                            "
-                                        >
-                                            {{ col.label + ': ' + col.value }}
-                                        </template>
-                                    </component>
-                                </QItem>
-                            </QList>
-                        </QCard>
-                    </div>
-                </template>
-            </QTable>
+                                <span style="font-size: large">-</span>
+                            </QBtn>
+                        </QItemSection>
+                    </QItem>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                flat
+                                @click="invertQuantitySign(selectedRows, 1)"
+                                data-cy="set-positive-quantity"
+                            >
+                                <span style="font-size: large">+</span>
+                            </QBtn>
+                        </QItemSection>
+                    </QItem>
+                </QList>
+            </QBtnDropdown>
+            <QBtnDropdown
+                icon="price_check"
+                color="primary"
+                flat
+                :title="t('Check buy amount')"
+                :disable="!selectedRows.length"
+                data-cy="check-buy-amount"
+            >
+                <QList>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                size="sm"
+                                icon="check"
+                                flat
+                                @click="setIsChecked(selectedRows, true)"
+                                data-cy="check-amount"
+                            />
+                        </QItemSection>
+                    </QItem>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                size="sm"
+                                icon="close"
+                                flat
+                                @click="setIsChecked(selectedRows, false)"
+                                data-cy="uncheck-amount"
+                            />
+                        </QItemSection>
+                    </QItem>
+                </QList>
+            </QBtnDropdown>
+        </QBtnGroup>
+    </Teleport>
+    <FetchData
+        ref="footerFetchDataRef"
+        :url="`Entries/${entityId}/getBuyList`"
+        :params="{ groupBy: 'GROUP BY b.entryFk' }"
+        @on-fetch="(data) => (footer = data[0])"
+        auto-load
+    />
+    <VnTable
+        ref="entryBuysRef"
+        data-key="EntryBuys"
+        :url="`Entries/${entityId}/getBuyList`"
+        save-url="Buys/crud"
+        :disable-option="{ card: true }"
+        v-model:selected="selectedRows"
+        @on-fetch="() => footerFetchDataRef.fetch()"
+        :table="
+            editableMode
+                ? {
+                      'row-key': 'id',
+                      selection: 'multiple',
+                  }
+                : {}
+        "
+        :create="
+            editableMode
+                ? {
+                      urlCreate: 'Buys',
+                      title: t('Create buy'),
+                      onDataSaved: () => {
+                          entryBuysRef.reload();
+                      },
+                      formInitialData: { entryFk: entityId, isIgnored: false },
+                      showSaveAndContinueBtn: true,
+                  }
+                : null
+        "
+        :create-complement="{
+            isFullWidth: true,
+            containerStyle: {
+                display: 'flex',
+                'flex-wrap': 'wrap',
+                gap: '16px',
+                position: 'relative',
+                height: '450px',
+            },
+            columnGridStyle: {
+                'max-width': '50%',
+                flex: 1,
+                'margin-right': '30px',
+            },
+        }"
+        :is-editable="editableMode"
+        :without-header="!editableMode"
+        :with-filters="editableMode"
+        :right-search="true"
+        :right-search-icon="true"
+        :row-click="false"
+        :columns="columns"
+        :beforeSaveFn="beforeSave"
+        class="buyList"
+        :table-height="$props.tableHeight ?? '84vh'"
+        auto-load
+        footer
+        data-cy="entry-buys"
+    >
+        <template #column-hex="{ row }">
+            <VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
         </template>
-    </VnPaginate>
-
-    <QPageSticky :offset="[20, 20]">
-        <QBtn fab icon="upload" color="primary" @click="importBuys()" />
-        <QTooltip class="text-no-wrap">
-            {{ t('Import buys') }}
-        </QTooltip>
-    </QPageSticky>
+        <template #column-name="{ row }">
+            <span class="link">
+                {{ row?.name }}
+                <ItemDescriptorProxy :id="row?.itemFk" />
+            </span>
+        </template>
+        <template #column-tags="{ row }">
+            <FetchedTags :item="row" :columns="3" />
+        </template>
+        <template #column-stickers="{ row }">
+            <span :class="editableMode ? 'editable-text' : ''">
+                <span style="color: var(--vn-label-color)">
+                    {{ row.printedStickers }}
+                </span>
+                <span>/{{ row.stickers }}</span>
+            </span>
+        </template>
+        <template #column-footer-stickers>
+            <div>
+                <span style="color: var(--vn-label-color)">
+                    {{ footer?.printedStickers }}</span
+                >
+                <span>/</span>
+                <span data-cy="footer-stickers">{{ footer?.stickers }}</span>
+            </div>
+        </template>
+        <template #column-footer-weight>
+            {{ footer?.weight }}
+        </template>
+        <template #column-footer-quantity>
+            <span :style="getQuantityStyle(footer)" data-cy="footer-quantity">
+                {{ footer?.quantity }}
+            </span>
+        </template>
+        <template #column-footer-amount>
+            <span :style="getAmountStyle(footer)" data-cy="footer-amount">
+                {{ footer?.amount }}
+            </span>
+        </template>
+        <template #column-create-itemFk="{ data }">
+            <VnSelect
+                url="Items/search"
+                v-model="data.itemFk"
+                :label="t('Article')"
+                :fields="['id', 'name', 'size', 'producerName']"
+                :filter-options="['id', 'name', 'size', 'producerName']"
+                option-label="name"
+                option-value="id"
+                @update:modelValue="
+                    async (value) => {
+                        await setBuyUltimate(value, data);
+                    }
+                "
+                :required="true"
+                data-cy="itemFk-create-popup"
+                sort-by="nickname DESC"
+            >
+                <template #option="scope">
+                    <QItem v-bind="scope.itemProps">
+                        <QItemSection>
+                            <QItemLabel>
+                                {{ scope.opt.name }}
+                            </QItemLabel>
+                            <QItemLabel caption>
+                                #{{ scope.opt.id }}, {{ scope.opt?.size }},
+                                {{ scope.opt?.producerName }}
+                            </QItemLabel>
+                        </QItemSection>
+                    </QItem>
+                </template>
+            </VnSelect>
+        </template>
+        <template #column-create-groupingMode="{ data }">
+            <VnSelectEnum
+                :label="t('Grouping mode')"
+                v-model="data.groupingMode"
+                schema="vn"
+                table="buy"
+                column="groupingMode"
+                option-value="groupingMode"
+                option-label="groupingMode"
+            />
+        </template>
+        <template #previous-create-dialog="{ data }">
+            <div
+                style="position: absolute"
+                :class="{ 'centered-container': !data.itemFk }"
+            >
+                <ItemDescriptor :id="data.itemFk" v-if="data.itemFk" />
+                <div v-else>
+                    <span>{{ t('globals.noData') }}</span>
+                </div>
+            </div>
+        </template>
+    </VnTable>
 </template>
-
-<style lang="scss" scoped>
-.q-table--horizontal-separator tbody tr:nth-child(odd) > td {
-    border-bottom-width: 0px;
-    border-top-width: 2px;
-    border-color: var(--vn-text-color);
-}
-.infoRow > td {
-    color: var(--vn-label-color);
-}
-</style>
-
 <i18n>
 es:
-    Import buys: Importar compras
-    Buy deleted: Compra eliminada
-    Buys deleted: Compras eliminadas
-    Confirm deletion: Confirmar eliminación
-    Are you sure you want to delete this buy?: Seguro que quieres eliminar esta compra?
-    Are you sure you want to delete this buys?: Seguro que quieres eliminar estas compras?
+    Article: Artículo
+    Siz.: Med.
+    Size: Medida
+    Sti.: Eti.
+    Bucket: Cubo
+    Quantity: Cantidad
+    Amount: Importe
+    Pack.: Paq.
+    Package: Paquete
+    Box: Caja
+    P.Sen: P.Env
+    Packing sent: Packing envíos
+    Com.: Ref.
+    Comment: Referencia
+    Minimum price: Precio mínimo
+    Stickers: Etiquetas
+    Printed Stickers/Stickers: Etiquetas impresas/Etiquetas
+    Cost: Cost.
+    Buying value: Coste
+    Producer: Productor
+    Company: Compañia
+    Tags: Etiquetas
+    Grouping mode: Modo de agrupación
+    C.min: P.min
+    Ignore: Ignorar
+    Ignored for available: Ignorado para disponible
+    Grouping selector: Selector de grouping
+    Check min price: Marcar precio mínimo
+    Create buy: Crear compra
+    Invert quantity value: Invertir valor de cantidad
+    Check buy amount: Marcar como correcta la cantidad de compra
 </i18n>
+<style lang="scss" scoped>
+.centered-container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    position: absolute;
+    width: 40%;
+    height: 100%;
+}
+</style>
diff --git a/src/pages/Entry/Card/EntryCard.vue b/src/pages/Entry/Card/EntryCard.vue
index e00623a21..be82289f4 100644
--- a/src/pages/Entry/Card/EntryCard.vue
+++ b/src/pages/Entry/Card/EntryCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import EntryDescriptor from './EntryDescriptor.vue';
-import filter from './EntryFilter.js'
+import filter from './EntryFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Entry"
-        base-url="Entries"
+        url="Entries"
         :descriptor="EntryDescriptor"
-        :user-filter="filter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index 19d13e51a..69b300cb2 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -1,12 +1,19 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
-import { useRoute } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import CardDescriptor from 'components/ui/CardDescriptor.vue';
-import VnLv from 'src/components/ui/VnLv.vue';
 import { toDate } from 'src/filters';
 import { getUrl } from 'src/composables/getUrl';
-import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
+import { useQuasar } from 'quasar';
+import { usePrintService } from 'composables/usePrintService';
+import CardDescriptor from 'components/ui/CardDescriptor.vue';
+import VnLv from 'src/components/ui/VnLv.vue';
+import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
+import axios from 'axios';
+
+const quasar = useQuasar();
+const { push } = useRouter();
+const { openReport } = usePrintService();
 
 const $props = defineProps({
     id: {
@@ -83,12 +90,63 @@ const getEntryRedirectionFilter = (entry) => {
         to,
     });
 };
+
+function showEntryReport() {
+    openReport(`Entries/${entityId.value}/entry-order-pdf`);
+}
+
+function showNotification(type, message) {
+    quasar.notify({
+        type: type,
+        message: t(message),
+    });
+}
+
+async function recalculateRates(entity) {
+    try {
+        const entryConfig = await axios.get('EntryConfigs/findOne');
+        if (entryConfig.data?.inventorySupplierFk === entity.supplierFk) {
+            showNotification(
+                'negative',
+                'Cannot recalculate prices because this is an inventory entry',
+            );
+            return;
+        }
+
+        await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);
+        showNotification('positive', 'Entry prices recalculated');
+    } catch (error) {
+        showNotification('negative', 'Failed to recalculate rates');
+        console.error(error);
+    }
+}
+
+async function cloneEntry() {
+    try {
+        const response = await axios.post(`Entries/${entityId.value}/cloneEntry`);
+        push({ path: `/entry/${response.data}` });
+        showNotification('positive', 'Entry cloned');
+    } catch (error) {
+        showNotification('negative', 'Failed to clone entry');
+        console.error(error);
+    }
+}
+
+async function deleteEntry() {
+    try {
+        await axios.post(`Entries/${entityId.value}/deleteEntry`);
+        push({ path: `/entry/list` });
+        showNotification('positive', 'Entry deleted');
+    } catch (error) {
+        showNotification('negative', 'Failed to delete entry');
+        console.error(error);
+    }
+}
 </script>
 
 <template>
     <CardDescriptor
         ref="entryDescriptorRef"
-        module="Entry"
         :url="`Entries/${entityId}`"
         :userFilter="entryFilter"
         title="supplier.nickname"
@@ -96,15 +154,56 @@ const getEntryRedirectionFilter = (entry) => {
         width="lg-width"
     >
         <template #menu="{ entity }">
-            <EntryDescriptorMenu :id="entity.id" />
+            <QItem
+                v-ripple
+                clickable
+                @click="showEntryReport(entity)"
+                data-cy="show-entry-report"
+            >
+                <QItemSection>{{ t('Show entry report') }}</QItemSection>
+            </QItem>
+            <QItem
+                v-ripple
+                clickable
+                @click="recalculateRates(entity)"
+                data-cy="recalculate-rates"
+            >
+                <QItemSection>{{ t('Recalculate rates') }}</QItemSection>
+            </QItem>
+            <QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry">
+                <QItemSection>{{ t('Clone') }}</QItemSection>
+            </QItem>
+            <QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry">
+                <QItemSection>{{ t('Delete') }}</QItemSection>
+            </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
-            <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
-            <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
+            <VnLv :label="t('Travel')">
+                <template #value>
+                    <span class="link" v-if="entity?.travelFk">
+                        {{ entity.travel?.agency?.name }}
+                        {{ entity.travel?.warehouseOut?.code }} &rarr;
+                        {{ entity.travel?.warehouseIn?.code }}
+                        <TravelDescriptorProxy :id="entity?.travelFk" />
+                    </span>
+                </template>
+            </VnLv>
             <VnLv
-                :label="t('globals.warehouseOut')"
-                :value="entity.travel?.warehouseOut?.name"
+                :label="t('entry.summary.travelShipped')"
+                :value="toDate(entity.travel?.shipped)"
+            />
+            <VnLv
+                :label="t('entry.summary.travelLanded')"
+                :value="toDate(entity.travel?.landed)"
+            />
+            <VnLv :label="t('entry.summary.currency')" :value="entity?.currency?.code" />
+            <VnLv
+                :label="t('entry.summary.invoiceAmount')"
+                :value="entity?.invoiceAmount"
+            />
+            <VnLv
+                :label="t('entry.summary.entryType')"
+                :value="entity?.entryType?.description"
             />
         </template>
         <template #icons="{ entity }">
@@ -131,6 +230,14 @@ const getEntryRedirectionFilter = (entry) => {
                         }}</QTooltip
                     >
                 </QIcon>
+                <QIcon
+                    v-if="!entity?.travelFk"
+                    name="vn:deletedTicket"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('This entry is deleted') }}</QTooltip>
+                </QIcon>
             </QCardActions>
         </template>
         <template #actions="{ entity }">
@@ -143,21 +250,6 @@ const getEntryRedirectionFilter = (entry) => {
                 >
                     <QTooltip>{{ t('Supplier card') }}</QTooltip>
                 </QBtn>
-                <QBtn
-                    :to="{
-                        name: 'TravelMain',
-                        query: {
-                            params: JSON.stringify({
-                                agencyModeFk: entity.travel?.agencyModeFk,
-                            }),
-                        },
-                    }"
-                    size="md"
-                    icon="local_airport"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('All travels with current agency') }}</QTooltip>
-                </QBtn>
                 <QBtn
                     :to="{
                         name: 'EntryMain',
@@ -177,10 +269,24 @@ const getEntryRedirectionFilter = (entry) => {
 </template>
 <i18n>
 es:
+    Travel: Envío
     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
     Inventory entry: Es inventario
     Virtual entry: Es una redada
+    shipped: Enviado
+    landed: Recibido
+    This entry is deleted: Esta entrada está eliminada
+    Cannot recalculate prices because this is an inventory entry: No se pueden recalcular los precios porque es una entrada de inventario
+    Entry deleted: Entrada eliminada
+    Entry cloned: Entrada clonada
+    Entry prices recalculated: Precios de la entrada recalculados
+    Failed to recalculate rates: No se pudieron recalcular las tarifas
+    Failed to clone entry: No se pudo clonar la entrada
+    Failed to delete entry: No se pudo eliminar la entrada
+    Recalculate rates: Recalcular tarifas
+    Clone: Clonar
+    Delete: Eliminar
 </i18n>
diff --git a/src/pages/Entry/Card/EntryFilter.js b/src/pages/Entry/Card/EntryFilter.js
index 3ff62cf27..d9fd1c2be 100644
--- a/src/pages/Entry/Card/EntryFilter.js
+++ b/src/pages/Entry/Card/EntryFilter.js
@@ -9,6 +9,7 @@ export default {
                     'shipped',
                     'agencyModeFk',
                     'warehouseOutFk',
+                    'warehouseInFk',
                     'daysInForward',
                 ],
                 include: [
@@ -21,13 +22,13 @@ export default {
                     {
                         relation: 'warehouseOut',
                         scope: {
-                            fields: ['name'],
+                            fields: ['name', 'code'],
                         },
                     },
                     {
                         relation: 'warehouseIn',
                         scope: {
-                            fields: ['name'],
+                            fields: ['name', 'code'],
                         },
                     },
                 ],
@@ -39,5 +40,17 @@ export default {
                 fields: ['id', 'nickname'],
             },
         },
+        {
+            relation: 'currency',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'entryType',
+            scope: {
+                fields: ['code', 'description'],
+            },
+        },
     ],
 };
diff --git a/src/pages/Entry/Card/EntryNotes.vue b/src/pages/Entry/Card/EntryNotes.vue
index 55cac0437..459c3b069 100644
--- a/src/pages/Entry/Card/EntryNotes.vue
+++ b/src/pages/Entry/Card/EntryNotes.vue
@@ -17,7 +17,7 @@ const selected = ref([]);
 
 const sortEntryObservationOptions = (data) => {
     entryObservationsOptions.value = [...data].sort((a, b) =>
-        a.description.localeCompare(b.description)
+        a.description.localeCompare(b.description),
     );
 };
 
@@ -142,7 +142,7 @@ const columns = computed(() => [
             fab
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             @click="entryObservationsRef.insert()"
         />
     </QPageSticky>
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index 8c46fb6e6..c40e2ba46 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -2,19 +2,17 @@
 import { onMounted, ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
+import { toDate } from 'src/filters';
+import { getUrl } from 'src/composables/getUrl';
+import axios from 'axios';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-
-import { toDate, toCurrency, toCelsius } from 'src/filters';
-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 EntryBuys from './EntryBuys.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
+import VnToSummary from 'src/components/ui/VnToSummary.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -33,117 +31,6 @@ const entry = ref();
 const entryBuys = ref([]);
 const entryUrl = ref();
 
-onMounted(async () => {
-    entryUrl.value = (await getUrl('entry/')) + entityId.value;
-});
-
-const tableColumnComponents = {
-    quantity: {
-        component: () => 'span',
-        props: () => {},
-    },
-    stickers: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    packagingFk: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    weight: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    packing: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    grouping: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    buyingValue: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    amount: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    pvp: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-};
-
-const entriesTableColumns = computed(() => {
-    return [
-        {
-            label: t('globals.quantity'),
-            field: 'quantity',
-            name: 'quantity',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.stickers'),
-            field: 'stickers',
-            name: 'stickers',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.package'),
-            field: 'packagingFk',
-            name: 'packagingFk',
-            align: 'left',
-        },
-        {
-            label: t('globals.weight'),
-            field: 'weight',
-            name: 'weight',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.packing'),
-            field: 'packing',
-            name: 'packing',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.grouping'),
-            field: 'grouping',
-            name: 'grouping',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.buyingValue'),
-            field: 'buyingValue',
-            name: 'buyingValue',
-            align: 'left',
-            format: (value) => toCurrency(value),
-        },
-        {
-            label: t('entry.summary.import'),
-            name: 'amount',
-            align: 'left',
-            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
-        },
-        {
-            label: t('entry.summary.pvp'),
-            name: 'pvp',
-            align: 'left',
-            format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
-        },
-    ];
-});
-
 async function setEntryData(data) {
     if (data) entry.value = data;
     await fetchEntryBuys();
@@ -153,14 +40,18 @@ const fetchEntryBuys = async () => {
     const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
     if (data) entryBuys.value = data;
 };
-</script>
 
+onMounted(async () => {
+    entryUrl.value = (await getUrl('entry/')) + entityId.value;
+});
+</script>
 <template>
     <CardSummary
         ref="summaryRef"
         :url="`Entries/${entityId}/getEntry`"
         @on-fetch="(data) => setEntryData(data)"
         data-key="EntrySummary"
+        data-cy="entry-summary"
     >
         <template #header-left>
             <VnToSummary
@@ -173,159 +64,154 @@ 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
                     :url="`#/entry/${entityId}/basic-data`"
                     :text="t('globals.summary.basicData')"
                 />
-                <VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
-                <VnLv
-                    :label="t('entry.summary.currency')"
-                    :value="entry.currency?.name"
-                />
-                <VnLv :label="t('globals.company')" :value="entry.company.code" />
-                <VnLv :label="t('globals.reference')" :value="entry.reference" />
-                <VnLv
-                    :label="t('entry.summary.invoiceNumber')"
-                    :value="entry.invoiceNumber"
-                />
-                <VnLv
-                    :label="t('entry.basicData.initialTemperature')"
-                    :value="toCelsius(entry.initialTemperature)"
-                />
-                <VnLv
-                    :label="t('entry.basicData.finalTemperature')"
-                    :value="toCelsius(entry.finalTemperature)"
-                />
+                <div class="card-group">
+                    <div class="card-content">
+                        <VnLv
+                            :label="t('entry.summary.commission')"
+                            :value="entry?.commission"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.currency')"
+                            :value="entry?.currency?.name"
+                        />
+                        <VnLv
+                            :label="t('globals.company')"
+                            :value="entry?.company?.code"
+                        />
+                        <VnLv :label="t('globals.reference')" :value="entry?.reference" />
+                        <VnLv
+                            :label="t('entry.summary.invoiceNumber')"
+                            :value="entry?.invoiceNumber"
+                        />
+                    </div>
+                    <div class="card-content">
+                        <VnCheckbox
+                            :label="t('entry.summary.ordered')"
+                            v-model="entry.isOrdered"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('globals.confirmed')"
+                            v-model="entry.isConfirmed"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.booked')"
+                            v-model="entry.isBooked"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.excludedFromAvailable')"
+                            v-model="entry.isExcludedFromAvailable"
+                            :disable="true"
+                            size="xs"
+                        />
+                    </div>
+                </div>
             </QCard>
-            <QCard class="vn-one">
+            <QCard class="vn-one" v-if="entry?.travelFk">
                 <VnTitle
-                    :url="`#/entry/${entityId}/basic-data`"
-                    :text="t('globals.summary.basicData')"
+                    :url="`#/travel/${entry.travel.id}/summary`"
+                    :text="t('Travel')"
                 />
-                <VnLv :label="t('entry.summary.travelReference')">
-                    <template #value>
-                        <span class="link">
-                            {{ entry.travel.ref }}
-                            <TravelDescriptorProxy :id="entry.travel.id" />
-                        </span>
-                    </template>
-                </VnLv>
-                <VnLv
-                    :label="t('entry.summary.travelAgency')"
-                    :value="entry.travel.agency?.name"
-                />
-                <VnLv
-                    :label="t('globals.shipped')"
-                    :value="toDate(entry.travel.shipped)"
-                />
-                <VnLv
-                    :label="t('globals.warehouseOut')"
-                    :value="entry.travel.warehouseOut?.name"
-                />
-                <VnLv
-                    :label="t('entry.summary.travelDelivered')"
-                    :value="entry.travel.isDelivered"
-                />
-                <VnLv :label="t('globals.landed')" :value="toDate(entry.travel.landed)" />
-                <VnLv
-                    :label="t('globals.warehouseIn')"
-                    :value="entry.travel.warehouseIn?.name"
-                />
-                <VnLv
-                    :label="t('entry.summary.travelReceived')"
-                    :value="entry.travel.isReceived"
-                />
-            </QCard>
-            <QCard class="vn-one">
-                <VnTitle :url="`#/travel/${entityId}/summary`" :text="t('Travel data')" />
-                <VnRow class="block">
-                    <VnLv :label="t('entry.summary.ordered')" :value="entry.isOrdered" />
-                    <VnLv :label="t('globals.confirmed')" :value="entry.isConfirmed" />
-                    <VnLv :label="t('entry.summary.booked')" :value="entry.isBooked" />
-                    <VnLv
-                        :label="t('entry.summary.excludedFromAvailable')"
-                        :value="entry.isExcludedFromAvailable"
-                    />
-                </VnRow>
+                <div class="card-group">
+                    <div class="card-content">
+                        <VnLv :label="t('entry.summary.travelReference')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entry.travel.ref }}
+                                    <TravelDescriptorProxy :id="entry.travel.id" />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv
+                            :label="t('entry.summary.travelAgency')"
+                            :value="entry.travel.agency?.name"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.travelShipped')"
+                            :value="toDate(entry.travel.shipped)"
+                        />
+                        <VnLv
+                            :label="t('globals.warehouseOut')"
+                            :value="entry.travel.warehouseOut?.name"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.travelLanded')"
+                            :value="toDate(entry.travel.landed)"
+                        />
+                        <VnLv
+                            :label="t('globals.warehouseIn')"
+                            :value="entry.travel.warehouseIn?.name"
+                        />
+                    </div>
+                    <div class="card-content">
+                        <VnCheckbox
+                            :label="t('entry.summary.travelDelivered')"
+                            v-model="entry.travel.isDelivered"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.travelReceived')"
+                            v-model="entry.travel.isReceived"
+                            :disable="true"
+                            size="xs"
+                        />
+                    </div>
+                </div>
             </QCard>
             <QCard class="vn-max">
                 <VnTitle
                     :url="`#/entry/${entityId}/buys`"
                     :text="t('entry.summary.buys')"
                 />
-                <QTable
-                    :rows="entryBuys"
-                    :columns="entriesTableColumns"
-                    row-key="index"
-                    class="full-width q-mt-md"
-                    :no-data-label="t('globals.noResults')"
-                >
-                    <template #body="{ cols, row, rowIndex }">
-                        <QTr no-hover>
-                            <QTd v-for="col in cols" :key="col?.name">
-                                <component
-                                    :is="tableColumnComponents[col?.name].component()"
-                                    v-bind="tableColumnComponents[col?.name].props()"
-                                    @click="tableColumnComponents[col?.name].event()"
-                                    class="col-content"
-                                >
-                                    <template
-                                        v-if="
-                                            col?.name !== 'observation' &&
-                                            col?.name !== 'isConfirmed'
-                                        "
-                                        >{{ col.value }}</template
-                                    >
-                                    <QTooltip v-if="col.toolTip">{{
-                                        col.toolTip
-                                    }}</QTooltip>
-                                </component>
-                            </QTd>
-                        </QTr>
-                        <QTr no-hover>
-                            <QTd>
-                                <span>{{ row.item.itemType.code }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ row.item.id }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ row.item.size }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ toCurrency(row.item.minPrice) }}</span>
-                            </QTd>
-                            <QTd colspan="6">
-                                <span>{{ row.item.concept }}</span>
-                                <span v-if="row.item.subName" class="subName">
-                                    {{ row.item.subName }}
-                                </span>
-                                <FetchedTags :item="row.item" />
-                            </QTd>
-                        </QTr>
-                        <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
-                        <QTr v-if="rowIndex !== entryBuys.length - 1">
-                            <QTd colspan="10" class="vn-table-separation-row" />
-                        </QTr>
-                    </template>
-                </QTable>
+                <EntryBuys
+                    v-if="entityId"
+                    :id="Number(entityId)"
+                    :editable-mode="false"
+                    table-height="49vh"
+                />
             </QCard>
         </template>
     </CardSummary>
 </template>
-
 <style lang="scss" scoped>
-.separation-row {
-    background-color: var(--vn-section-color) !important;
+.card-group {
+    display: flex;
+    flex-direction: column;
+}
+
+.card-content {
+    display: flex;
+    flex-direction: column;
+    text-overflow: ellipsis;
+    > div {
+        max-height: 24px;
+    }
+}
+
+@media (min-width: 1010px) {
+    .card-group {
+        flex-direction: row;
+    }
+    .card-content {
+        flex: 1;
+        margin-right: 16px;
+    }
 }
 </style>
-
 <i18n>
 es:
-    Travel data: Datos envío
+    Travel: Envío
+    InvoiceIn data: Datos factura
 </i18n>
diff --git a/src/pages/Entry/EntryFilter.vue b/src/pages/Entry/EntryFilter.vue
index 0f632c0ef..8c60918a8 100644
--- a/src/pages/Entry/EntryFilter.vue
+++ b/src/pages/Entry/EntryFilter.vue
@@ -19,6 +19,7 @@ const props = defineProps({
 
 const currenciesOptions = ref([]);
 const companiesOptions = ref([]);
+const entryFilterPanel = ref();
 </script>
 
 <template>
@@ -38,7 +39,7 @@ const companiesOptions = ref([]);
         @on-fetch="(data) => (currenciesOptions = data)"
         auto-load
     />
-    <VnFilterPanel :data-key="props.dataKey" :search-button="true">
+    <VnFilterPanel ref="entryFilterPanel" :data-key="props.dataKey" :search-button="true">
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">
                 <strong>{{ t(`entryFilter.params.${tag.label}`) }}: </strong>
@@ -48,70 +49,65 @@ const companiesOptions = ref([]);
         <template #body="{ params, searchFn }">
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.search"
-                        :label="t('entryFilter.params.search')"
-                        is-outlined
-                    />
+                    <QCheckbox
+                        :label="t('params.isExcludedFromAvailable')"
+                        v-model="params.isExcludedFromAvailable"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('params.isExcludedFromAvailable') }}
+                        </QTooltip>
+                    </QCheckbox>
+                </QItemSection>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('params.isOrdered')"
+                        v-model="params.isOrdered"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isOrdered') }}
+                        </QTooltip>
+                    </QCheckbox>
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.reference"
-                        :label="t('entryFilter.params.reference')"
-                        is-outlined
-                    />
+                    <QCheckbox
+                        :label="t('params.isReceived')"
+                        v-model="params.isReceived"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isReceived') }}
+                        </QTooltip>
+                    </QCheckbox>
+                </QItemSection>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('entry.list.tableVisibleColumns.isConfirmed')"
+                        v-model="params.isConfirmed"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isConfirmed') }}
+                        </QTooltip>
+                    </QCheckbox>
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.invoiceNumber"
-                        :label="t('entryFilter.params.invoiceNumber')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.travelFk"
-                        :label="t('entryFilter.params.travelFk')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('entryFilter.params.companyFk')"
-                        v-model="params.companyFk"
+                    <VnInputDate
+                        :label="t('params.landed')"
+                        v-model="params.landed"
                         @update:model-value="searchFn()"
-                        :options="companiesOptions"
-                        option-value="id"
-                        option-label="code"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
+                        is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnSelect
-                        :label="t('entryFilter.params.currencyFk')"
-                        v-model="params.currencyFk"
-                        @update:model-value="searchFn()"
-                        :options="currenciesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
+                    <VnInput v-model="params.id" label="Id" is-outlined />
                 </QItemSection>
             </QItem>
             <QItem>
@@ -125,62 +121,165 @@ const companiesOptions = ref([]);
                         rounded
                     />
                 </QItemSection>
-            </QItem>
-            <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.created')"
-                        v-model="params.created"
-                        @update:model-value="searchFn()"
+                    <VnInput
+                        v-model="params.invoiceNumber"
+                        :label="t('params.invoiceNumber')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.from')"
-                        v-model="params.from"
-                        @update:model-value="searchFn()"
+                    <VnInput
+                        v-model="params.reference"
+                        :label="t('entry.list.tableVisibleColumns.reference')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.to')"
-                        v-model="params.to"
+                    <VnSelect
+                        :label="t('params.agencyModeId')"
+                        v-model="params.agencyModeId"
                         @update:model-value="searchFn()"
+                        url="AgencyModes"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.evaNotes"
+                        :label="t('params.evaNotes')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isBooked')"
-                        v-model="params.isBooked"
-                        toggle-indeterminate
-                    />
-                </QItemSection>
-                <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isConfirmed')"
-                        v-model="params.isConfirmed"
-                        toggle-indeterminate
+                    <VnSelect
+                        :label="t('params.warehouseOutFk')"
+                        v-model="params.warehouseOutFk"
+                        @update:model-value="searchFn()"
+                        url="Warehouses"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isOrdered')"
-                        v-model="params.isOrdered"
-                        toggle-indeterminate
+                    <VnSelect
+                        :label="t('params.warehouseInFk')"
+                        v-model="params.warehouseInFk"
+                        @update:model-value="searchFn()"
+                        url="Warehouses"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    >
+                        <template #option="scope">
+                            <QItem v-bind="scope.itemProps">
+                                <QItemSection>
+                                    <QItemLabel>
+                                        {{ scope.opt?.name }}
+                                    </QItemLabel>
+                                    <QItemLabel caption>
+                                        {{ `#${scope.opt?.id} , ${scope.opt?.nickname}` }}
+                                    </QItemLabel>
+                                </QItemSection>
+                            </QItem>
+                        </template>
+                    </VnSelect>
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.invoiceNumber"
+                        :label="t('params.invoiceNumber')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('params.entryTypeCode')"
+                        v-model="params.entryTypeCode"
+                        @update:model-value="searchFn()"
+                        url="EntryTypes"
+                        :fields="['code', 'description']"
+                        option-value="code"
+                        option-label="description"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.evaNotes"
+                        :label="t('params.evaNotes')"
+                        is-outlined
                     />
                 </QItemSection>
             </QItem>
         </template>
     </VnFilterPanel>
 </template>
+
+<i18n>
+en:
+    params:
+        isExcludedFromAvailable: Inventory
+        isOrdered: Ordered
+        isReceived: Received
+        isConfirmed: Confirmed
+        isRaid: Raid
+        landed: Date
+        id: Id
+        supplierFk: Supplier
+        invoiceNumber: Invoice number
+        reference: Ref/Alb/Guide
+        agencyModeId: Agency mode
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeCode: Entry type
+        hasToShowDeletedEntries: Show deleted entries
+es:
+    params:
+        isExcludedFromAvailable: Inventario
+        isOrdered: Pedida
+        isConfirmed: Confirmado
+        isReceived: Recibida
+        isRaid: Raid
+        landed: Fecha
+        id: Id
+        supplierFk: Proveedor
+        invoiceNumber: Núm. factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Modo agencia
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeCode: Tipo de entrada
+        hasToShowDeletedEntries: Mostrar entradas eliminadas
+</i18n>
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 3172c6d0e..3c96a2302 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -1,21 +1,25 @@
 <script setup>
+import axios from 'axios';
+import VnSection from 'src/components/common/VnSection.vue';
 import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
+import { onBeforeMount } from 'vue';
+
 import EntryFilter from './EntryFilter.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
-import { toCelsius, toDate } from 'src/filters';
-import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import EntrySummary from './Card/EntrySummary.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-import VnSection from 'src/components/common/VnSection.vue';
+import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
+import { toDate } from 'src/filters';
 
 const { t } = useI18n();
 const tableRef = ref();
+const defaultEntry = ref({});
+const state = useState();
+const user = state.getUser();
 const dataKey = 'EntryList';
 
-const { viewSummary } = useSummaryDialog();
-const entryFilter = {
+const entryQueryFilter = {
     include: [
         {
             relation: 'suppliers',
@@ -40,44 +44,58 @@ const entryFilter = {
 
 const columns = computed(() => [
     {
-        name: 'status',
-        columnFilter: false,
+        labelAbbreviation: 'Ex',
+        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
+        toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
+        name: 'isExcludedFromAvailable',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('globals.id'),
-        name: 'id',
-        isId: true,
-        chip: {
-            condition: () => true,
-        },
+        labelAbbreviation: 'Pe',
+        label: t('entry.list.tableVisibleColumns.isOrdered'),
+        toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
+        name: 'isOrdered',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('globals.reference'),
-        name: 'reference',
-        isTitle: true,
-        component: 'input',
-        columnField: {
-            component: null,
-        },
-        create: true,
-        cardVisible: true,
+        labelAbbreviation: 'LE',
+        label: t('entry.list.tableVisibleColumns.isConfirmed'),
+        toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
+        name: 'isConfirmed',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.created'),
-        name: 'created',
-        create: true,
-        cardVisible: true,
+        labelAbbreviation: 'Re',
+        label: t('entry.list.tableVisibleColumns.isReceived'),
+        toolTip: t('entry.list.tableVisibleColumns.isReceived'),
+        name: 'isReceived',
+        component: 'checkbox',
+        width: '35px',
+    },
+    {
+        label: t('entry.list.tableVisibleColumns.landed'),
+        name: 'landed',
         component: 'date',
         columnField: {
             component: null,
         },
-        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.created)),
+        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
+        width: '105px',
+    },
+    {
+        label: t('globals.id'),
+        name: 'id',
+        isId: true,
+        component: 'number',
+        chip: {
+            condition: () => true,
+        },
+        width: '50px',
     },
     {
-        align: 'left',
         label: t('entry.list.tableVisibleColumns.supplierFk'),
         name: 'supplierFk',
         create: true,
@@ -86,165 +104,213 @@ const columns = computed(() => [
         attrs: {
             url: 'suppliers',
             fields: ['id', 'name'],
-        },
-        columnField: {
-            component: null,
+            where: { order: 'name DESC' },
         },
         format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
+        width: '110px',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isBooked'),
-        name: 'isBooked',
+        label: t('entry.list.tableVisibleColumns.invoiceNumber'),
+        name: 'invoiceNumber',
+        component: 'input',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.reference'),
+        name: 'reference',
+        isTitle: true,
+        component: 'input',
+        columnField: {
+            component: null,
+        },
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isConfirmed'),
-        name: 'isConfirmed',
+        label: 'AWB',
+        name: 'awbCode',
+        component: 'input',
+        width: '100px',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.agencyModeId'),
+        name: 'agencyModeId',
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
+        component: 'select',
+        attrs: {
+            url: 'agencyModes',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyModeName),
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isOrdered'),
-        name: 'isOrdered',
+        label: t('entry.list.tableVisibleColumns.evaNotes'),
+        name: 'evaNotes',
+        component: 'input',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.warehouseOutFk'),
+        name: 'warehouseOutFk',
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
+        component: 'select',
+        attrs: {
+            url: 'warehouses',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseOutName),
+        width: '65px',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.companyFk'),
+        label: t('entry.list.tableVisibleColumns.warehouseInFk'),
+        name: 'warehouseInFk',
+        cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'warehouses',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseInName),
+        width: '65px',
+    },
+    {
+        align: 'left',
+        labelAbbreviation: t('Type'),
+        label: t('entry.list.tableVisibleColumns.entryTypeDescription'),
+        toolTip: t('entry.list.tableVisibleColumns.entryTypeDescription'),
+        name: 'entryTypeCode',
+        component: 'select',
+        attrs: {
+            url: 'entryTypes',
+            fields: ['code', 'description'],
+            optionValue: 'code',
+            optionLabel: 'description',
+        },
+        width: '65px',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.entryTypeDescription),
+    },
+    {
         name: 'companyFk',
+        label: t('entry.list.tableVisibleColumns.companyFk'),
+        cardVisible: false,
+        visible: false,
+        create: true,
         component: 'select',
         attrs: {
-            url: 'companies',
-            fields: ['id', 'code'],
+            optionValue: 'id',
             optionLabel: 'code',
-            optionValue: 'id',
+            url: 'Companies',
         },
-        columnField: {
-            component: null,
-        },
-        create: true,
-
-        format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
     },
     {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.travelFk'),
         name: 'travelFk',
-        component: 'select',
-        attrs: {
-            url: 'travels',
-            fields: ['id', 'ref'],
-            optionLabel: 'ref',
-            optionValue: 'id',
-        },
-        columnField: {
-            component: null,
-        },
+        label: t('entry.list.tableVisibleColumns.travelFk'),
+        cardVisible: false,
+        visible: false,
         create: true,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.invoiceAmount'),
-        name: 'invoiceAmount',
-        cardVisible: true,
-    },
-    {
-        align: 'left',
-        name: 'initialTemperature',
-        label: t('entry.basicData.initialTemperature'),
-        field: 'initialTemperature',
-        format: (row) => toCelsius(row.initialTemperature),
-    },
-    {
-        align: 'left',
-        name: 'finalTemperature',
-        label: t('entry.basicData.finalTemperature'),
-        field: 'finalTemperature',
-        format: (row) => toCelsius(row.finalTemperature),
-    },
-    {
-        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
-        name: 'isExcludedFromAvailable',
-        columnFilter: {
-            inWhere: true,
-        },
-    },
-    {
-        align: 'right',
-        name: 'tableActions',
-        actions: [
-            {
-                title: t('components.smartCard.viewSummary'),
-                icon: 'preview',
-                action: (row) => viewSummary(row.id, EntrySummary),
-                isPrimary: true,
-            },
-        ],
     },
 ]);
+function getBadgeAttrs(row) {
+    const date = row.landed;
+    let today = Date.vnNew();
+    today.setHours(0, 0, 0, 0);
+    let timeTicket = new Date(date);
+    timeTicket.setHours(0, 0, 0, 0);
+
+    let timeDiff = today - timeTicket;
+
+    if (timeDiff > 0) return { color: 'info', 'text-color': 'black' };
+    if (timeDiff < 0) return { color: 'warning', 'text-color': 'black' };
+    switch (row.entryTypeCode) {
+        case 'regularization':
+        case 'life':
+        case 'internal':
+        case 'inventory':
+            if (!row.isOrdered || !row.isConfirmed)
+                return { color: 'negative', 'text-color': 'black' };
+            break;
+        case 'product':
+        case 'packaging':
+        case 'devaluation':
+        case 'payment':
+        case 'transport':
+            if (
+                row.invoiceAmount === null ||
+                (row.invoiceNumber === null && row.reference === null) ||
+                !row.isOrdered ||
+                !row.isConfirmed
+            )
+                return { color: 'negative', 'text-color': 'black' };
+            break;
+        default:
+            break;
+    }
+    return { color: 'transparent' };
+}
+
+onBeforeMount(async () => {
+    defaultEntry.value = (await axios.get('EntryConfigs/findOne')).data;
+});
 </script>
 
 <template>
     <VnSection
         :data-key="dataKey"
-        :columns="columns"
         prefix="entry"
         url="Entries/filter"
         :array-data-props="{
             url: 'Entries/filter',
-            order: 'id DESC',
-            userFilter: entryFilter,
+            order: 'landed DESC',
+            userFilter: EntryFilter,
         }"
     >
         <template #advanced-menu>
-            <EntryFilter data-key="EntryList" />
+            <EntryFilter :data-key="dataKey" />
         </template>
         <template #body>
             <VnTable
+                v-if="defaultEntry.defaultSupplierFk"
                 ref="tableRef"
                 :data-key="dataKey"
+                url="Entries/filter"
+                :filter="entryQueryFilter"
+                order="landed DESC"
                 :create="{
                     urlCreate: 'Entries',
-                    title: t('entry.list.newEntry'),
+                    title: t('Create entry'),
                     onDataSaved: ({ id }) => tableRef.redirect(id),
-                    formInitialData: {},
+                    formInitialData: {
+                        supplierFk: defaultEntry.defaultSupplierFk,
+                        dated: Date.vnNew(),
+                        companyFk: user?.companyFk,
+                    },
                 }"
                 :columns="columns"
                 redirect="entry"
                 :right-search="false"
             >
-                <template #column-status="{ row }">
-                    <div class="row q-gutter-xs">
-                        <QIcon
-                            v-if="!!row.isExcludedFromAvailable"
-                            name="vn:inventory"
-                            color="primary"
-                        >
-                            <QTooltip>{{
-                                t(
-                                    'entry.list.tableVisibleColumns.isExcludedFromAvailable',
-                                )
-                            }}</QTooltip>
-                        </QIcon>
-                        <QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
-                            <QTooltip>
-                                {{
-                                    t('globals.raid', {
-                                        daysInForward: row.daysInForward,
-                                    })
-                                }}</QTooltip
-                            >
-                        </QIcon>
-                    </div>
+                <template #column-landed="{ row }">
+                    <QBadge
+                        v-if="row?.travelFk"
+                        v-bind="getBadgeAttrs(row)"
+                        class="q-pa-sm"
+                        style="font-size: 14px"
+                    >
+                        {{ toDate(row.landed) }}
+                    </QBadge>
                 </template>
                 <template #column-supplierFk="{ row }">
                     <span class="link" @click.stop>
@@ -252,13 +318,27 @@ const columns = computed(() => [
                         <SupplierDescriptorProxy :id="row.supplierFk" />
                     </span>
                 </template>
-                <template #column-travelFk="{ row }">
-                    <span class="link" @click.stop>
-                        {{ row.travelRef }}
-                        <TravelDescriptorProxy :id="row.travelFk" />
-                    </span>
+                <template #column-create-travelFk="{ data }">
+                    <VnSelectTravelExtended
+                        :data="data"
+                        v-model="data.travelFk"
+                        :onFilterTravelSelected="
+                            (data, result) => (data.travelFk = result)
+                        "
+                        data-cy="entry-travel-select"
+                    />
                 </template>
             </VnTable>
         </template>
     </VnSection>
 </template>
+
+<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
+    Create entry: Crear entrada
+    Type: Tipo
+</i18n>
diff --git a/src/pages/Entry/EntryStockBought.vue b/src/pages/Entry/EntryStockBought.vue
index fa0bdc12e..4bd0fe640 100644
--- a/src/pages/Entry/EntryStockBought.vue
+++ b/src/pages/Entry/EntryStockBought.vue
@@ -34,18 +34,20 @@ const columns = computed(() => [
         label: t('entryStockBought.buyer'),
         isTitle: true,
         component: 'select',
+        isEditable: false,
         cardVisible: true,
         create: true,
         attrs: {
             url: 'Workers/activeWithInheritedRole',
-            fields: ['id', 'name'],
+            fields: ['id', 'name', 'nickname'],
             where: { role: 'buyer' },
             optionFilter: 'firstName',
-            optionLabel: 'name',
+            optionLabel: 'nickname',
             optionValue: 'id',
             useLike: false,
         },
         columnFilter: false,
+        width: '70px',
     },
     {
         align: 'center',
@@ -55,6 +57,7 @@ const columns = computed(() => [
         create: true,
         component: 'number',
         summation: true,
+        width: '50px',
     },
     {
         align: 'center',
@@ -78,6 +81,7 @@ const columns = computed(() => [
         actions: [
             {
                 title: t('entryStockBought.viewMoreDetails'),
+                name: 'searchBtn',
                 icon: 'search',
                 isPrimary: true,
                 action: (row) => {
@@ -91,6 +95,7 @@ const columns = computed(() => [
                 },
             },
         ],
+        'data-cy': 'table-actions',
     },
 ]);
 
@@ -158,7 +163,7 @@ function round(value) {
                 @on-fetch="
                     (data) => {
                         travel = data.find(
-                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh'
+                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh',
                         );
                     }
                 "
@@ -179,6 +184,7 @@ function round(value) {
                         @click="openDialog()"
                         :title="t('entryStockBought.editTravel')"
                         color="primary"
+                        data-cy="edit-travel"
                     />
                 </div>
             </VnRow>
@@ -239,10 +245,11 @@ function round(value) {
                 table-height="80vh"
                 auto-load
                 :column-search="false"
+                :without-header="true"
             >
                 <template #column-workerFk="{ row }">
                     <span class="link" @click.stop>
-                        {{ row?.worker?.user?.name }}
+                        {{ row?.worker?.user?.nickname }}
                         <WorkerDescriptorProxy :id="row?.workerFk" />
                     </span>
                 </template>
@@ -279,10 +286,11 @@ function round(value) {
     justify-content: center;
 }
 .column {
+    min-width: 40%;
+    margin-top: 5%;
     display: flex;
     flex-direction: column;
     align-items: center;
-    min-width: 35%;
 }
 .text-negative {
     color: $negative !important;
diff --git a/src/pages/Entry/EntryStockBoughtDetail.vue b/src/pages/Entry/EntryStockBoughtDetail.vue
index 812171825..1a37994d9 100644
--- a/src/pages/Entry/EntryStockBoughtDetail.vue
+++ b/src/pages/Entry/EntryStockBoughtDetail.vue
@@ -21,7 +21,7 @@ const $props = defineProps({
 const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&dated=${$props.dated}`;
 const columns = [
     {
-        align: 'left',
+        align: 'right',
         label: t('Entry'),
         name: 'entryFk',
         isTitle: true,
@@ -29,7 +29,7 @@ const columns = [
         columnFilter: false,
     },
     {
-        align: 'left',
+        align: 'right',
         name: 'itemFk',
         label: t('Item'),
         columnFilter: false,
@@ -44,21 +44,21 @@ const columns = [
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         name: 'volume',
         label: t('Volume'),
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         label: t('Packaging'),
         name: 'packagingFk',
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         label: 'Packing',
         name: 'packing',
         columnFilter: false,
@@ -73,12 +73,14 @@ const columns = [
                 ref="tableRef"
                 data-key="StockBoughtsDetail"
                 :url="customUrl"
-                order="itemName DESC"
+                order="volume DESC"
                 :columns="columns"
                 :right-search="false"
                 :disable-infinite-scroll="true"
                 :disable-option="{ card: true }"
                 :limit="0"
+                :without-header="true"
+                :with-filters="false"
                 auto-load
             >
                 <template #column-entryFk="{ row }">
@@ -99,16 +101,14 @@ const columns = [
 </template>
 <style lang="css" scoped>
 .container {
-    max-width: 50vw;
+    max-width: 100%;
+    width: 50%;
     overflow: auto;
     justify-content: center;
     align-items: center;
     margin: auto;
     background-color: var(--vn-section-color);
-    padding: 4px;
-}
-.container > div > div > .q-table__top.relative-position.row.items-center {
-    background-color: red !important;
+    padding: 2%;
 }
 </style>
 <i18n>
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index 80f3491a8..88b16cb03 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -1,21 +1,36 @@
 entry:
+    lock:
+        title: Lock entry
+        message: This entry has been locked by {userName} for {time} minutes. Do you want to unlock it?
+        success: The entry has been locked successfully
     list:
         newEntry: New entry
         tableVisibleColumns:
-            created: Creation
-            supplierFk: Supplier
-            isBooked: Booked
-            isConfirmed: Confirmed
+            isExcludedFromAvailable: Exclude from inventory
             isOrdered: Ordered
+            isConfirmed: Ready to label
+            isReceived: Received
+            isRaid: Raid
+            landed: Date
+            supplierFk: Supplier
+            reference: Ref/Alb/Guide
+            invoiceNumber: Invoice
+            agencyModeId: Agency
+            isBooked: Booked
             companyFk: Company
-            travelFk: Travel
-            isExcludedFromAvailable: Inventory
+            evaNotes: Notes
+            warehouseOutFk: Origin
+            warehouseInFk: Destiny
+            entryTypeDescription: Entry type
             invoiceAmount: Import
+            travelFk: Travel
+            dated: Dated
         inventoryEntry: Inventory entry
     summary:
         commission: Commission
         currency: Currency
         invoiceNumber: Invoice number
+        invoiceAmount: Invoice amount
         ordered: Ordered
         booked: Booked
         excludedFromAvailable: Inventory
@@ -33,6 +48,7 @@ entry:
         buyingValue: Buying value
         import: Import
         pvp: PVP
+        entryType: Entry type
     basicData:
         travel: Travel
         currency: Currency
@@ -69,17 +85,55 @@ entry:
             landing: Landing
             isExcludedFromAvailable: Es inventory
     params:
-        toShipped: To
-        fromShipped: From
-        daysOnward: Days onward
-        daysAgo: Days ago
-        warehouseInFk: Warehouse in
+        isExcludedFromAvailable: Exclude from inventory
+        isOrdered: Ordered
+        isConfirmed: Ready to label
+        isReceived: Received
+        isIgnored: Ignored
+        isRaid: Raid
+        landed: Date
+        supplierFk: Supplier
+        reference: Ref/Alb/Guide
+        invoiceNumber: Invoice
+        agencyModeId: Agency
+        isBooked: Booked
+        companyFk: Company
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeDescription: Entry type
+        invoiceAmount: Import
+        travelFk: Travel
+        dated: Dated
+        itemFk: Item id
+        hex: Color
+        name: Item name
+        size: Size
+        stickers: Stickers
+        packagingFk: Packaging
+        weight: Kg
+        groupingMode: Grouping selector
+        grouping: Grouping
+        quantity: Quantity
+        buyingValue: Buying value
+        price2: Package
+        price3: Box
+        minPrice: Minumum price
+        hasMinPrice: Has minimum price
+        packingOut: Packing out
+        comment: Comment
+        subName: Supplier name
+        tags: Tags
+        company_name: Company name
+        itemTypeFk: Item type
+        workerFk: Worker id
     search: Search entries
     searchInfo: You can search by entry reference
     descriptorMenu:
         showEntryReport: Show entry report
 entryFilter:
     params:
+        isExcludedFromAvailable: Exclude from inventory
         invoiceNumber: Invoice number
         travelFk: Travel
         companyFk: Company
@@ -91,8 +145,16 @@ entryFilter:
         isBooked: Booked
         isConfirmed: Confirmed
         isOrdered: Ordered
+        isReceived: Received
         search: General search
         reference: Reference
+        landed: Landed
+        id: Id
+        agencyModeId: Agency
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeCode: Entry type
 myEntries:
     id: ID
     landed: Landed
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index a5b968016..3025d64cb 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -1,21 +1,36 @@
 entry:
+    lock:
+        title: Entrada bloqueada
+        message: Esta entrada ha sido bloqueada por {userName} hace {time} minutos. ¿Quieres desbloquearla?
+        success: La entrada ha sido bloqueada correctamente
     list:
         newEntry: Nueva entrada
         tableVisibleColumns:
-            created: Creación
-            supplierFk: Proveedor
-            isBooked: Asentado
-            isConfirmed: Confirmado
+            isExcludedFromAvailable: Excluir del inventario
             isOrdered: Pedida
+            isConfirmed: Lista para etiquetar
+            isReceived: Recibida
+            isRaid: Redada
+            landed: Fecha
+            supplierFk: Proveedor
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
+            agencyModeId: Agencia
+            isBooked: Asentado
             companyFk: Empresa
             travelFk: Envio
-            isExcludedFromAvailable: Inventario
+            evaNotes: Notas
+            warehouseOutFk: Origen
+            warehouseInFk: Destino
+            entryTypeDescription: Tipo entrada
             invoiceAmount: Importe
+            dated: Fecha
         inventoryEntry: Es inventario
     summary:
         commission: Comisión
         currency: Moneda
         invoiceNumber: Núm. factura
+        invoiceAmount: Importe
         ordered: Pedida
         booked: Contabilizada
         excludedFromAvailable: Inventario
@@ -34,12 +49,13 @@ entry:
         buyingValue: Coste
         import: Importe
         pvp: PVP
+        entryType: Tipo entrada
     basicData:
         travel: Envío
         currency: Moneda
         observation: Observación
         commission: Comisión
-        booked: Asentado
+        booked: Contabilizada
         excludedFromAvailable: Inventario
         initialTemperature: Ini °C
         finalTemperature: Fin °C
@@ -69,31 +85,70 @@ entry:
             packingOut: Embalaje envíos
             landing: Llegada
             isExcludedFromAvailable: Es inventario
-    params:
-        toShipped: Hasta
-        fromShipped: Desde
-        warehouseInFk: Alm. entrada
-        daysOnward: Días adelante
-        daysAgo: Días atras
-    descriptorMenu:
-        showEntryReport: Ver informe del pedido
+
     search: Buscar entradas
     searchInfo: Puedes buscar por referencia de entrada
+    params:
+        isExcludedFromAvailable: Excluir del inventario
+        isOrdered: Pedida
+        isConfirmed: Lista para etiquetar
+        isReceived: Recibida
+        isRaid: Redada
+        isIgnored: Ignorado
+        landed: Fecha
+        supplierFk: Proveedor
+        invoiceNumber: Nº Factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Agencia
+        isBooked: Asentado
+        companyFk: Empresa
+        travelFk: Envio
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeDescription: Tipo entrada
+        invoiceAmount: Importe
+        dated: Fecha
+        itemFk: Id artículo
+        hex: Color
+        name: Nombre artículo
+        size: Medida
+        stickers: Etiquetas
+        packagingFk: Embalaje
+        weight: Kg
+        groupinMode: Selector de grouping
+        grouping: Grouping
+        quantity: Quantity
+        buyingValue: Precio de compra
+        price2: Paquete
+        price3: Caja
+        minPrice: Precio mínimo
+        hasMinPrice: Tiene precio mínimo
+        packingOut: Packing out
+        comment: Referencia
+        subName: Nombre proveedor
+        tags: Etiquetas
+        company_name: Nombre empresa
+        itemTypeFk: Familia
+        workerFk: Comprador
 entryFilter:
     params:
-        invoiceNumber: Núm. factura
-        travelFk: Envío
-        companyFk: Empresa
-        currencyFk: Moneda
-        supplierFk: Proveedor
-        from: Desde
-        to: Hasta
-        created: Fecha creación
-        isBooked: Asentado
-        isConfirmed: Confirmado
+        isExcludedFromAvailable: Inventario
         isOrdered: Pedida
-        search: Búsqueda general
-        reference: Referencia
+        isConfirmed: Confirmado
+        isReceived: Recibida
+        isRaid: Raid
+        landed: Fecha
+        id: Id
+        supplierFk: Proveedor
+        invoiceNumber: Núm. factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Modo agencia
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeCode: Tipo de entrada
+        hasToShowDeletedEntries: Mostrar entradas eliminadas
 myEntries:
     id: ID
     landed: F. llegada
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index c01ec4ab4..905ddebb2 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -125,7 +125,7 @@ function deleteFile(dmsFk) {
                 <VnInput
                     clearable
                     clear-icon="close"
-                    :label="t('Supplier ref')"
+                    :label="t('invoiceIn.supplierRef')"
                     v-model="data.supplierRef"
                 />
             </VnRow>
@@ -149,6 +149,7 @@ function deleteFile(dmsFk) {
                     option-value="id"
                     option-label="id"
                     :filter-options="['id', 'name']"
+                    data-cy="UnDeductibleVatSelect"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
@@ -215,7 +216,7 @@ function deleteFile(dmsFk) {
                         v-else
                         icon="add_circle"
                         round
-                        shortcut="+"
+                        v-shortcut="'+'"
                         padding="xs"
                         @click="
                             () => {
@@ -310,7 +311,6 @@ function deleteFile(dmsFk) {
         supplierFk: Supplier
     es:
         supplierFk: Proveedor
-        Supplier ref: Ref. proveedor
         Expedition date: Fecha expedición
         Operation date: Fecha operación
         Undeductible VAT: Iva no deducible
diff --git a/src/pages/InvoiceIn/Card/InvoiceInCard.vue b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
index 8aa35f4d8..34cc26437 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInCard.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
@@ -1,47 +1,18 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import InvoiceInDescriptor from './InvoiceInDescriptor.vue';
+import { onBeforeRouteUpdate } from 'vue-router';
+import { setRectificative } from '../composables/setRectificative';
+import filter from './InvoiceInFilter.js';
 
-const filter = {
-    include: [
-        {
-            relation: 'supplier',
-            scope: {
-                include: {
-                    relation: 'contacts',
-                    scope: { where: { email: { neq: null } } },
-                },
-            },
-        },
-        { relation: 'invoiceInDueDay' },
-        { relation: 'company' },
-        { relation: 'currency' },
-        {
-            relation: 'dms',
-            scope: {
-                fields: [
-                    'dmsTypeFk',
-                    'reference',
-                    'hardCopyNumber',
-                    'workerFk',
-                    'description',
-                    'hasFile',
-                    'file',
-                    'created',
-                    'companyFk',
-                    'warehouseFk',
-                ],
-            },
-        },
-    ],
-};
+onBeforeRouteUpdate(async (to) => await setRectificative(to));
 </script>
 
 <template>
     <VnCardBeta
         data-key="InvoiceIn"
-        base-url="InvoiceIns"
+        url="InvoiceIns"
         :descriptor="InvoiceInDescriptor"
-        :user-filter="filter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index da7bd4426..3843f5bf7 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -7,6 +7,7 @@ import { toCurrency, toDate } from 'src/filters';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
+import filter from './InvoiceInFilter.js';
 import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
 
 const $props = defineProps({ id: { type: Number, default: null } });
@@ -16,33 +17,10 @@ const { t } = useI18n();
 const cardDescriptorRef = ref();
 const entityId = computed(() => $props.id || +currentRoute.value.params.id);
 const totalAmount = ref();
-
-const filter = {
-    include: [
-        {
-            relation: 'supplier',
-            scope: {
-                include: {
-                    relation: 'contacts',
-                    scope: {
-                        where: {
-                            email: { neq: null },
-                        },
-                    },
-                },
-            },
-        },
-        {
-            relation: 'invoiceInDueDay',
-        },
-        {
-            relation: 'company',
-        },
-        {
-            relation: 'currency',
-        },
-    ],
-};
+const config = ref();
+const cplusRectificationTypes = ref([]);
+const siiTypeInvoiceIns = ref([]);
+const invoiceCorrectionTypes = ref([]);
 const invoiceInCorrection = reactive({ correcting: [], corrected: null });
 const routes = reactive({
     getSupplier: (id) => {
@@ -112,7 +90,6 @@ async function setInvoiceCorrection(id) {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
-        module="InvoiceIn"
         data-key="InvoiceIn"
         :url="`InvoiceIns/${entityId}`"
         :filter="filter"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
index c3ab635c8..8b039ec27 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
@@ -186,7 +186,7 @@ const createInvoiceInCorrection = async () => {
                 clickable
                 @click="book(entityId)"
             >
-                <QItemSection>{{ t('invoiceIn.descriptorMenu.toBook') }}</QItemSection>
+                <QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
             </QItem>
         </template>
     </InvoiceInToBook>
@@ -197,7 +197,7 @@ const createInvoiceInCorrection = async () => {
         @click="triggerMenu('unbook')"
     >
         <QItemSection>
-            {{ t('invoiceIn.descriptorMenu.toUnbook') }}
+            {{ t('invoiceIn.descriptorMenu.unbook') }}
         </QItemSection>
     </QItem>
     <QItem
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
index 23387ff74..20cc1cc71 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, onBeforeMount } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import axios from 'axios';
@@ -11,6 +11,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import useNotify from 'src/composables/useNotify.js';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+import { toCurrency } from 'filters/index';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -24,7 +25,7 @@ const invoiceInFormRef = ref();
 const invoiceId = +route.params.id;
 const filter = { where: { invoiceInFk: invoiceId } };
 const areRows = ref(false);
-
+const totals = ref();
 const columns = computed(() => [
     {
         name: 'duedate',
@@ -63,6 +64,8 @@ const columns = computed(() => [
     },
 ]);
 
+const totalAmount = computed(() => getTotal(invoiceInFormRef.value.formData, 'amount'));
+
 const isNotEuro = (code) => code != 'EUR';
 
 async function insert() {
@@ -70,6 +73,10 @@ async function insert() {
     await invoiceInFormRef.value.reload();
     notify(t('globals.dataSaved'), 'positive');
 }
+
+onBeforeMount(async () => {
+    totals.value = (await axios.get(`InvoiceIns/${invoiceId}/getTotals`)).data;
+});
 </script>
 <template>
     <CrudModel
@@ -144,7 +151,7 @@ async function insert() {
                         <QTd />
                         <QTd />
                         <QTd>
-                            {{ getTotal(rows, 'amount', { currency: 'default' }) }}
+                            {{ toCurrency(totalAmount) }}
                         </QTd>
                         <QTd>
                             <template v-if="isNotEuro(invoiceIn.currency.code)">
@@ -222,10 +229,19 @@ async function insert() {
         <QBtn
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             size="lg"
             round
-            @click="!areRows ? insert() : invoiceInFormRef.insert()"
+            @click="
+                () => {
+                    if (!areRows) insert();
+                    else
+                        invoiceInFormRef.insert({
+                            amount: (totals.totalTaxableBase - totalAmount).toFixed(2),
+                            invoiceInFk: invoiceId,
+                        });
+                }
+            "
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInFilter.js b/src/pages/InvoiceIn/Card/InvoiceInFilter.js
new file mode 100644
index 000000000..6df8b5830
--- /dev/null
+++ b/src/pages/InvoiceIn/Card/InvoiceInFilter.js
@@ -0,0 +1,33 @@
+export default {
+    include: [
+        {
+            relation: 'supplier',
+            scope: {
+                include: {
+                    relation: 'contacts',
+                    scope: { where: { email: { neq: null } } },
+                },
+            },
+        },
+        { relation: 'invoiceInDueDay' },
+        { relation: 'company' },
+        { relation: 'currency' },
+        {
+            relation: 'dms',
+            scope: {
+                fields: [
+                    'dmsTypeFk',
+                    'reference',
+                    'hardCopyNumber',
+                    'workerFk',
+                    'description',
+                    'hasFile',
+                    'file',
+                    'created',
+                    'companyFk',
+                    'warehouseFk',
+                ],
+            },
+        },
+    ],
+};
diff --git a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
index e529ea6cd..6f8642313 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
@@ -218,7 +218,7 @@ const columns = computed(() => [
         <QBtn
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             size="lg"
             round
             @click="invoiceInFormRef.insert()"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index e546638f2..d358601d3 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -193,7 +193,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             <InvoiceIntoBook>
                 <template #content="{ book }">
                     <QBtn
-                        :label="t('To book')"
+                        :label="t('Book')"
                         color="orange-11"
                         text-color="black"
                         @click="book(entityId)"
@@ -224,10 +224,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                         </span>
                     </template>
                 </VnLv>
-                <VnLv
-                    :label="t('invoiceIn.list.supplierRef')"
-                    :value="entity.supplierRef"
-                />
+                <VnLv :label="t('invoiceIn.supplierRef')" :value="entity.supplierRef" />
                 <VnLv
                     :label="t('invoiceIn.summary.currency')"
                     :value="entity.currency?.code"
@@ -357,7 +354,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                 entity.totals.totalTaxableBaseForeignValue &&
                                 toCurrency(
                                     entity.totals.totalTaxableBaseForeignValue,
-                                    currency
+                                    currency,
                                 )
                             }}</QTd>
                         </QTr>
@@ -392,7 +389,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                     entity.totals.totalDueDayForeignValue &&
                                     toCurrency(
                                         entity.totals.totalDueDayForeignValue,
-                                        currency
+                                        currency,
                                     )
                                 }}
                             </QTd>
@@ -472,5 +469,5 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
         Search invoice: Buscar factura recibida
         You can search by invoice reference: Puedes buscar por referencia de la factura
         Totals: Totales
-        To book: Contabilizar
+        Book: Contabilizar
 </i18n>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInVat.vue b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
index f99e060b8..e77453bc0 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInVat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, nextTick } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useArrayData } from 'src/composables/useArrayData';
@@ -25,7 +25,6 @@ const sageTaxTypes = ref([]);
 const sageTransactionTypes = ref([]);
 const rowsSelected = ref([]);
 const invoiceInFormRef = ref();
-const expenseRef = ref();
 
 defineProps({
     actionIcon: {
@@ -97,6 +96,20 @@ const columns = computed(() => [
     },
 ]);
 
+const taxableBaseTotal = computed(() => {
+    return getTotal(invoiceInFormRef.value.formData, 'taxableBase');
+});
+
+const taxRateTotal = computed(() => {
+    return getTotal(invoiceInFormRef.value.formData, null, {
+        cb: taxRate,
+    });
+});
+
+const combinedTotal = computed(() => {
+    return +taxableBaseTotal.value + +taxRateTotal.value;
+});
+
 const filter = {
     fields: [
         'id',
@@ -117,7 +130,7 @@ const isNotEuro = (code) => code != 'EUR';
 function taxRate(invoiceInTax) {
     const sageTaxTypeId = invoiceInTax.taxTypeSageFk;
     const taxRateSelection = sageTaxTypes.value.find(
-        (transaction) => transaction.id == sageTaxTypeId
+        (transaction) => transaction.id == sageTaxTypeId,
     );
     const taxTypeSage = taxRateSelection?.rate ?? 0;
     const taxableBase = invoiceInTax?.taxableBase ?? 0;
@@ -125,35 +138,26 @@ function taxRate(invoiceInTax) {
     return ((taxTypeSage / 100) * taxableBase).toFixed(2);
 }
 
-function autocompleteExpense(evt, row, col) {
+function autocompleteExpense(evt, row, col, ref) {
     const val = evt.target.value;
     if (!val) return;
 
     const param = isNaN(val) ? row[col.model] : val;
     const lookup = expenses.value.find(
-        ({ id }) => id == useAccountShortToStandard(param)
+        ({ id }) => id == useAccountShortToStandard(param),
     );
 
-    expenseRef.value.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
+    ref.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
 }
 
-const taxableBaseTotal = computed(() => {   
-    return getTotal(invoiceInFormRef.value.formData, 'taxableBase', );
-});
-
-const taxRateTotal = computed(() => {
-    return getTotal(invoiceInFormRef.value.formData, null, {
-        cb: taxRate,
+function setCursor(ref) {
+    nextTick(() => {
+        const select = ref.vnSelectDialogRef
+            ? ref.vnSelectDialogRef.vnSelectRef
+            : ref.vnSelectRef;
+        select.$el.querySelector('input').setSelectionRange(0, 0);
     });
-});
-
-
-const combinedTotal = computed(() => {
-    return +taxableBaseTotal.value + +taxRateTotal.value;
-});
-
-
-
+}
 </script>
 <template>
     <FetchData
@@ -191,14 +195,24 @@ const combinedTotal = computed(() => {
                 <template #body-cell-expense="{ row, col }">
                     <QTd>
                         <VnSelectDialog
-                            ref="expenseRef"
+                            :ref="`expenseRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'name']"
                             :tooltip="t('Create a new expense')"
-                            @keydown.tab="autocompleteExpense($event, row, col)"
+                            @keydown.tab="
+                                autocompleteExpense(
+                                    $event,
+                                    row,
+                                    col,
+                                    $refs[`expenseRef-${row.$index}`],
+                                )
+                            "
+                            @update:model-value="
+                                setCursor($refs[`expenseRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -214,7 +228,7 @@ const combinedTotal = computed(() => {
                     </QTd>
                 </template>
                 <template #body-cell-taxablebase="{ row }">
-                    <QTd>
+                    <QTd shrink>
                         <VnInputNumber
                             clear-icon="close"
                             v-model="row.taxableBase"
@@ -225,12 +239,16 @@ const combinedTotal = computed(() => {
                 <template #body-cell-sageiva="{ row, col }">
                     <QTd>
                         <VnSelect
+                            :ref="`sageivaRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'vat']"
                             data-cy="vat-sageiva"
+                            @update:model-value="
+                                setCursor($refs[`sageivaRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -248,11 +266,15 @@ const combinedTotal = computed(() => {
                 <template #body-cell-sagetransaction="{ row, col }">
                     <QTd>
                         <VnSelect
+                            :ref="`sagetransactionRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'transaction']"
+                            @update:model-value="
+                                setCursor($refs[`sagetransactionRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -270,7 +292,7 @@ const combinedTotal = computed(() => {
                     </QTd>
                 </template>
                 <template #body-cell-foreignvalue="{ row }">
-                    <QTd>
+                    <QTd shrink>
                         <VnInputNumber
                             :class="{
                                 'no-pointer-events': !isNotEuro(currency),
@@ -283,7 +305,7 @@ const combinedTotal = computed(() => {
                                     row.taxableBase = await getExchange(
                                         val,
                                         row.currencyFk,
-                                        invoiceIn.issued
+                                        invoiceIn.issued,
                                     );
                                 }
                             "
@@ -426,7 +448,7 @@ const combinedTotal = computed(() => {
             color="primary"
             icon="add"
             size="lg"
-            shortcut="+"
+            v-shortcut="'+'"
             round
             @click="invoiceInFormRef.insert()"
         >
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index e1723e3b1..0960d0d6c 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -29,6 +29,7 @@ const cols = computed(() => [
         name: 'isBooked',
         label: t('invoiceIn.isBooked'),
         columnFilter: false,
+        component: 'checkbox',
     },
     {
         align: 'left',
@@ -56,7 +57,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'supplierRef',
-        label: t('invoiceIn.list.supplierRef'),
+        label: t('invoiceIn.supplierRef'),
     },
     {
         align: 'left',
@@ -177,7 +178,7 @@ const cols = computed(() => [
                         :required="true"
                     />
                     <VnInput
-                        :label="t('invoiceIn.list.supplierRef')"
+                        :label="t('invoiceIn.supplierRef')"
                         v-model="data.supplierRef"
                     />
                     <VnSelect
diff --git a/src/pages/InvoiceIn/InvoiceInToBook.vue b/src/pages/InvoiceIn/InvoiceInToBook.vue
index 95ce8155a..5bdbe197b 100644
--- a/src/pages/InvoiceIn/InvoiceInToBook.vue
+++ b/src/pages/InvoiceIn/InvoiceInToBook.vue
@@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import { useArrayData } from 'src/composables/useArrayData';
+import qs from 'qs';
 const { notify, dialog } = useQuasar();
 const { t } = useI18n();
 
@@ -12,29 +13,51 @@ defineExpose({ checkToBook });
 const { store } = useArrayData();
 
 async function checkToBook(id) {
-    let directBooking = true;
+    let messages = [];
+
+    const hasProblemWithTax = (
+        await axios.get('InvoiceInTaxes/count', {
+            params: {
+                where: JSON.stringify({
+                    invoiceInFk: id,
+                    or: [{ taxTypeSageFk: null }, { transactionTypeSageFk: null }],
+                }),
+            },
+        })
+    ).data?.count;
+
+    if (hasProblemWithTax)
+        messages.push(t('The VAT and Transaction fields have not been informed'));
 
     const { data: totals } = await axios.get(`InvoiceIns/${id}/getTotals`);
     const taxableBaseNotEqualDueDay = totals.totalDueDay != totals.totalTaxableBase;
     const vatNotEqualDueDay = totals.totalDueDay != totals.totalVat;
 
-    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay) directBooking = false;
+    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay)
+        messages.push(t('The sum of the taxable bases does not match the due dates'));
 
-    const { data: dueDaysCount } = await axios.get('InvoiceInDueDays/count', {
-        where: {
-            invoiceInFk: id,
-            dueDated: { gte: Date.vnNew() },
-        },
-    });
+    const dueDaysCount = (
+        await axios.get('InvoiceInDueDays/count', {
+            params: {
+                where: JSON.stringify({
+                    invoiceInFk: id,
+                    dueDated: { gte: Date.vnNew() },
+                }),
+            },
+        })
+    ).data?.count;
 
-    if (dueDaysCount) directBooking = false;
+    if (dueDaysCount) messages.push(t('Some due dates are less than or equal to today'));
 
-    if (directBooking) return toBook(id);
-
-    dialog({
-        component: VnConfirm,
-        componentProps: { title: t('Are you sure you want to book this invoice?') },
-    }).onOk(async () => await toBook(id));
+    if (!messages.length) toBook(id);
+    else
+        dialog({
+            component: VnConfirm,
+            componentProps: {
+                title: t('Are you sure you want to book this invoice?'),
+                message: messages.reduce((acc, msg) => `${acc}<p>${msg}</p>`, ''),
+            },
+        }).onOk(() => toBook(id));
 }
 
 async function toBook(id) {
@@ -59,4 +82,7 @@ async function toBook(id) {
 es:
     Are you sure you want to book this invoice?: ¿Estás seguro de querer asentar esta factura?
     It was not able to book the invoice: No se pudo contabilizar la factura
+    Some due dates are less than or equal to today: Algún vencimiento tiene una fecha menor o igual que hoy
+    The sum of the taxable bases does not match the due dates: La suma de las bases imponibles no coincide con la de los vencimientos
+    The VAT and Transaction fields have not been informed: No se han informado los campos de iva y/o transacción
 </i18n>
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index 6b21b316b..548e6c201 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Search incoming invoices by ID or supplier fiscal name
     serial: Serial
     isBooked: Is booked
+    supplierRef: Invoice nº
     list:
         ref: Reference
         supplier: Supplier
-        supplierRef: Supplier ref.
         file: File
         issued: Issued
         dueDated: Due dated
@@ -19,8 +19,6 @@ invoiceIn:
         unbook: Unbook
         delete: Delete
         clone: Clone
-        toBook: To book
-        toUnbook: To unbook
         deleteInvoice: Delete invoice
         invoiceDeleted: invoice deleted
         cloneInvoice: Clone invoice
@@ -70,4 +68,3 @@ invoiceIn:
         isBooked: Is booked
         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 3f27c895c..142d95f92 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
     serial: Serie
     isBooked: Contabilizada
+    supplierRef: Nº factura
     list:
         ref: Referencia
         supplier: Proveedor
-        supplierRef: Ref. proveedor
         issued: F. emisión
         dueDated: F. vencimiento
         file: Fichero
@@ -15,12 +15,10 @@ invoiceIn:
     descriptor:
         ticketList: Listado de tickets
     descriptorMenu:
-        book: Asentar
-        unbook: Desasentar
+        book: Contabilizar
+        unbook: Descontabilizar
         delete: Eliminar
         clone: Clonar
-        toBook: Contabilizar
-        toUnbook: Descontabilizar
         deleteInvoice: Eliminar factura
         invoiceDeleted: Factura eliminada
         cloneInvoice: Clonar factura
@@ -68,4 +66,3 @@ invoiceIn:
         isBooked: Contabilizada
         account: Cuenta contable
         correctingFk: Rectificativa
-
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
index 93e3fe042..a50c9d247 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
@@ -1,11 +1,13 @@
 <script setup>
 import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
+import filter from './InvoiceOutFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="InvoiceOut"
-        base-url="InvoiceOuts"
+        url="InvoiceOuts"
+        :filter="filter"
         :descriptor="InvoiceOutDescriptor"
     />
 </template>
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
index 209f1531e..dfaf6c109 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
@@ -8,8 +8,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import VnLv from 'src/components/ui/VnLv.vue';
 import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import { toCurrency, toDate } from 'src/filters';
+import filter from './InvoiceOutFilter.js';
 
 const $props = defineProps({
     id: {
@@ -26,42 +26,20 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const filter = {
-    include: [
-        {
-            relation: 'company',
-            scope: {
-                fields: ['id', 'code'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'name', 'email'],
-            },
-        },
-    ],
-};
-
 const descriptor = ref();
 
 function ticketFilter(invoice) {
     return JSON.stringify({ refFk: invoice.ref });
 }
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.id));
 </script>
 
 <template>
     <CardDescriptor
         ref="descriptor"
-        module="InvoiceOut"
         :url="`InvoiceOuts/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
-        data-key="invoiceOutData"
+        title="ref"
+        data-key="InvoiceOut"
         width="lg-width"
     >
         <template #menu="{ entity, menuRef }">
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutFilter.js b/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
new file mode 100644
index 000000000..48b20faf6
--- /dev/null
+++ b/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
@@ -0,0 +1,16 @@
+export default {
+    include: [
+        {
+            relation: 'company',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'name', 'email'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Item/Card/ItemBarcode.vue b/src/pages/Item/Card/ItemBarcode.vue
index 6db5943c7..590b524cd 100644
--- a/src/pages/Item/Card/ItemBarcode.vue
+++ b/src/pages/Item/Card/ItemBarcode.vue
@@ -92,7 +92,7 @@ const submit = async (rows) => {
                             class="cursor-pointer fill-icon-on-hover"
                             color="primary"
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                         >
                             <QTooltip>
diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index 4c96401f3..df7e71684 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -11,6 +11,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
 import FilterItemForm from 'src/components/FilterItemForm.vue';
 import CreateIntrastatForm from './CreateIntrastatForm.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -54,9 +55,8 @@ const onIntrastatCreated = (response, formData) => {
         auto-load
     />
     <FormModel
-        :url="`Items/${route.params.id}`"
         :url-update="`Items/${route.params.id}`"
-        model="item"
+        model="Item"
         auto-load
         :clear-store-on-unmount="false"
     >
@@ -209,30 +209,20 @@ const onIntrastatCreated = (response, formData) => {
                 />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <div>
-                    <QCheckbox
-                        v-model="data.isFragile"
-                        :label="t('item.basicData.isFragile')"
-                        class="q-mr-sm"
-                    />
-                    <QIcon name="info" class="cursor-pointer" size="xs">
-                        <QTooltip max-width="300px">
-                            {{ t('item.basicData.isFragileTooltip') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
-                <div>
-                    <QCheckbox
-                        v-model="data.isPhotoRequested"
-                        :label="t('item.basicData.isPhotoRequested')"
-                        class="q-mr-sm"
-                    />
-                    <QIcon name="info" class="cursor-pointer" size="xs">
-                        <QTooltip>
-                            {{ t('item.basicData.isPhotoRequestedTooltip') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isFragile"
+                    :label="t('item.basicData.isFragile')"
+                    :info="t('item.basicData.isFragileTooltip')"
+                    class="q-mr-sm"
+                    size="xs"
+                />
+                <VnCheckbox
+                    v-model="data.isPhotoRequested"
+                    :label="t('item.basicData.isPhotoRequested')"
+                    :info="t('item.basicData.isPhotoRequestedTooltip')"
+                    class="q-mr-sm"
+                    size="xs"
+                />
             </VnRow>
             <VnRow>
                 <VnInput
diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index 4894d94fc..a40d81589 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -7,8 +7,8 @@ import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
-import CreateGenusForm from './CreateGenusForm.vue';
-import CreateSpecieForm from './CreateSpecieForm.vue';
+import CreateGenusForm from '../components/CreateGenusForm.vue';
+import CreateSpecieForm from '../components/CreateSpecieForm.vue';
 
 const route = useRoute();
 const { t } = useI18n();
diff --git a/src/pages/Item/Card/ItemCard.vue b/src/pages/Item/Card/ItemCard.vue
index 2546982eb..610b77a02 100644
--- a/src/pages/Item/Card/ItemCard.vue
+++ b/src/pages/Item/Card/ItemCard.vue
@@ -5,7 +5,7 @@ import ItemDescriptor from './ItemDescriptor.vue';
 <template>
     <VnCardBeta
         data-key="Item"
-        base-url="Items"
+        :url="`Items/${$route.params.id}/getCard`"
         :descriptor="ItemDescriptor"
     />
 </template>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index c6fee8540..a4c58ef4b 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -7,7 +7,6 @@ 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 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';
@@ -35,6 +34,10 @@ const $props = defineProps({
         type: Number,
         default: null,
     },
+    proxyRender: {
+        type: Boolean,
+        default: false,
+    },
 });
 
 const route = useRoute();
@@ -55,10 +58,8 @@ onMounted(async () => {
     mounted.value = true;
 });
 
-const data = ref(useCardDescription());
 const setData = async (entity) => {
     if (!entity) return;
-    data.value = useCardDescription(entity.name, entity.id);
     await updateStock();
 };
 
@@ -90,10 +91,7 @@ const updateStock = async () => {
 
 <template>
     <CardDescriptor
-        data-key="ItemData"
-        module="Item"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        data-key="Item"
         :summary="$props.summary"
         :url="`Items/${entityId}/getCard`"
         @on-fetch="setData"
@@ -117,7 +115,7 @@ const updateStock = async () => {
                 <template #value>
                     <span class="link">
                         {{ entity.itemType?.worker?.user?.name }}
-                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id" />
+                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id ?? NaN" />
                     </span>
                 </template>
             </VnLv>
@@ -152,7 +150,7 @@ const updateStock = async () => {
             </QCardActions>
         </template>
         <template #actions="{}">
-            <QCardActions class="row justify-center">
+            <QCardActions class="row justify-center" v-if="proxyRender">
                 <QBtn
                     :to="{
                         name: 'ItemDiary',
@@ -165,6 +163,16 @@ const updateStock = async () => {
                 >
                     <QTooltip>{{ t('item.descriptor.itemDiary') }}</QTooltip>
                 </QBtn>
+                <QBtn
+                    :to="{
+                        name: 'ItemLastEntries',
+                    }"
+                    size="md"
+                    icon="vn:regentry"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('item.descriptor.itemLastEntries') }}</QTooltip>
+                </QBtn>
             </QCardActions>
         </template>
     </CardDescriptor>
diff --git a/src/pages/Item/Card/ItemDescriptorProxy.vue b/src/pages/Item/Card/ItemDescriptorProxy.vue
index 2ffc9080f..f686e8221 100644
--- a/src/pages/Item/Card/ItemDescriptorProxy.vue
+++ b/src/pages/Item/Card/ItemDescriptorProxy.vue
@@ -4,7 +4,7 @@ import ItemSummary from './ItemSummary.vue';
 
 const $props = defineProps({
     id: {
-        type: Number,
+        type: [Number, String],
         required: true,
     },
     dated: {
@@ -21,9 +21,8 @@ const $props = defineProps({
     },
 });
 </script>
-
 <template>
-    <QPopupProxy>
+    <QPopupProxy style="max-width: 10px">
         <ItemDescriptor
             v-if="$props.id"
             :id="$props.id"
@@ -31,6 +30,7 @@ const $props = defineProps({
             :dated="dated"
             :sale-fk="saleFk"
             :warehouse-fk="warehouseFk"
+            :proxy-render="true"
         />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Item/Card/ItemShelving.vue b/src/pages/Item/Card/ItemShelving.vue
index 7ad60c9e0..b29e2a2a5 100644
--- a/src/pages/Item/Card/ItemShelving.vue
+++ b/src/pages/Item/Card/ItemShelving.vue
@@ -110,10 +110,16 @@ const columns = computed(() => [
         attrs: { inWhere: true },
         align: 'left',
     },
+    {
+        label: t('globals.visible'),
+        name: 'stock',
+        attrs: { inWhere: true },
+        align: 'left',
+    },
 ]);
 
 const totalLabels = computed(() =>
-    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2)
+    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2),
 );
 
 const removeLines = async () => {
@@ -157,7 +163,7 @@ watchEffect(selectedRows);
                     openConfirmationModal(
                         t('shelvings.removeConfirmTitle'),
                         t('shelvings.removeConfirmSubtitle'),
-                        removeLines
+                        removeLines,
                     )
                 "
             >
diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index 5a7d7f818..ab26b9cae 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -178,7 +178,7 @@ const insertTag = (rows) => {
                             @click="insertTag(rows)"
                             color="primary"
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             fab
                             data-cy="createNewTag"
                         >
diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 1c4382fbd..fdfa1d3d1 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -65,10 +65,19 @@ const columns = computed(() => [
         name: 'name',
         ...defaultColumnAttrs,
         create: true,
+        columnFilter: {
+            component: 'select',
+            attrs: {
+                url: 'Items',
+                fields: ['id', 'name', 'subName'],
+                optionLabel: 'name',
+                optionValue: 'name',
+                uppercase: false,
+            },
+        },
     },
     {
         label: t('item.fixedPrice.groupingPrice'),
-        field: 'rate2',
         name: 'rate2',
         ...defaultColumnAttrs,
         component: 'input',
@@ -76,7 +85,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.packingPrice'),
-        field: 'rate3',
         name: 'rate3',
         ...defaultColumnAttrs,
         component: 'input',
@@ -85,7 +93,6 @@ const columns = computed(() => [
 
     {
         label: t('item.fixedPrice.minPrice'),
-        field: 'minPrice',
         name: 'minPrice',
         ...defaultColumnAttrs,
         component: 'input',
@@ -108,7 +115,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.ended'),
-        field: 'ended',
         name: 'ended',
         ...defaultColumnAttrs,
         columnField: {
@@ -124,7 +130,6 @@ const columns = computed(() => [
 
     {
         label: t('globals.warehouse'),
-        field: 'warehouseFk',
         name: 'warehouseFk',
         ...defaultColumnAttrs,
         columnClass: 'shrink',
@@ -415,7 +420,6 @@ function handleOnDataSave({ CrudModelRef }) {
             'row-key': 'id',
             selection: 'multiple',
         }"
-        :use-model="true"
         v-model:selected="rowsSelected"
         :create-as-dialog="false"
         :create="{
diff --git a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
index b4032ff8a..475dffd8b 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
@@ -40,12 +40,7 @@ const itemPackingTypesOptions = ref([]);
         }"
         auto-load
     />
-    <FormModel
-        :url="`ItemTypes/${route.params.id}`"
-        :url-update="`ItemTypes/${route.params.id}`"
-        model="itemTypeBasicData"
-        auto-load
-    >
+    <FormModel :url-update="`ItemTypes/${route.params.id}`" model="ItemType" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.code" :label="t('itemType.shared.code')" />
diff --git a/src/pages/Item/ItemType/Card/ItemTypeCard.vue b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
index fa51e428e..84e810de5 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeCard.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ItemTypeDescriptor from 'src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue';
+import filter from './ItemTypeFilter.js';
 </script>
 
 <template>
     <VnCardBeta
-        data-key="ItemTypeSummary"
-        base-url="ItemTypes"
+        data-key="ItemType"
+        url="ItemTypes"
+        :filter="filter"
         :descriptor="ItemTypeDescriptor"
     />
 </template>
diff --git a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
index 09d3dbce5..725fb30aa 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
@@ -1,12 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import useCardDescription from 'src/composables/useCardDescription';
+import filter from './ItemTypeFilter.js';
 
 const $props = defineProps({
     id: {
@@ -20,46 +19,31 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const itemTypeFilter = {
-    include: [
-        { relation: 'worker' },
-        { relation: 'category' },
-        { relation: 'itemPackingType' },
-        { relation: 'temperature' },
-    ],
-};
-
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
-
 <template>
     <CardDescriptor
-        module="ItemType"
         :url="`ItemTypes/${entityId}`"
-        :filter="itemTypeFilter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="itemTypeDescriptor"
-        @on-fetch="setData"
+        :filter="filter"
+        title="code"
+        data-key="ItemType"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('itemType.shared.code')" :value="entity.code" />
-            <VnLv :label="t('itemType.shared.name')" :value="entity.name" />
-            <VnLv :label="t('itemType.shared.worker')">
+            <VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
+            <VnLv :label="$t('itemType.shared.name')" :value="entity.name" />
+            <VnLv :label="$t('itemType.shared.worker')">
                 <template #value>
                     <span class="link">{{ entity.worker?.firstName }}</span>
                     <WorkerDescriptorProxy :id="entity.worker?.id" />
                 </template>
             </VnLv>
-            <VnLv :label="t('itemType.shared.category')" :value="entity.category?.name" />
+            <VnLv
+                :label="$t('itemType.shared.category')"
+                :value="entity.category?.name"
+            />
         </template>
     </CardDescriptor>
 </template>
-
diff --git a/src/pages/Item/ItemType/Card/ItemTypeFilter.js b/src/pages/Item/ItemType/Card/ItemTypeFilter.js
new file mode 100644
index 000000000..5651d368d
--- /dev/null
+++ b/src/pages/Item/ItemType/Card/ItemTypeFilter.js
@@ -0,0 +1,8 @@
+export default {
+    include: [
+        { relation: 'worker' },
+        { relation: 'category' },
+        { relation: 'itemPackingType' },
+        { relation: 'temperature' },
+    ],
+};
diff --git a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
index 9ba774ca4..3b63c4b63 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
@@ -3,7 +3,7 @@ import { ref, computed, onUpdated } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-
+import filter from './ItemTypeFilter.js';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
@@ -21,15 +21,6 @@ const $props = defineProps({
     },
 });
 
-const itemTypeFilter = {
-    include: [
-        { relation: 'worker' },
-        { relation: 'category' },
-        { relation: 'itemPackingType' },
-        { relation: 'temperature' },
-    ],
-};
-
 const entityId = computed(() => $props.id || route.params.id);
 const summaryRef = ref();
 const itemType = ref();
@@ -43,8 +34,8 @@ async function setItemTypeData(data) {
     <CardSummary
         ref="summaryRef"
         :url="`ItemTypes/${entityId}`"
-        data-key="ItemTypeSummary"
-        :filter="itemTypeFilter"
+        data-key="ItemType"
+        :filter="filter"
         @on-fetch="(data) => setItemTypeData(data)"
         class="full-width"
     >
diff --git a/src/pages/Item/Card/CreateGenusForm.vue b/src/pages/Item/components/CreateGenusForm.vue
similarity index 100%
rename from src/pages/Item/Card/CreateGenusForm.vue
rename to src/pages/Item/components/CreateGenusForm.vue
diff --git a/src/pages/Item/Card/CreateSpecieForm.vue b/src/pages/Item/components/CreateSpecieForm.vue
similarity index 100%
rename from src/pages/Item/Card/CreateSpecieForm.vue
rename to src/pages/Item/components/CreateSpecieForm.vue
diff --git a/src/pages/Item/components/ItemProposal.vue b/src/pages/Item/components/ItemProposal.vue
new file mode 100644
index 000000000..d2dbea7b3
--- /dev/null
+++ b/src/pages/Item/components/ItemProposal.vue
@@ -0,0 +1,332 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import { toCurrency } from 'filters/index';
+import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+import axios from 'axios';
+import notifyResults from 'src/utils/notifyResults';
+import FetchData from 'components/FetchData.vue';
+
+const MATCH = 'match';
+
+const { t } = useI18n();
+const $props = defineProps({
+    itemLack: {
+        type: Object,
+        required: true,
+        default: () => {},
+    },
+    replaceAction: {
+        type: Boolean,
+        required: false,
+        default: false,
+    },
+    sales: {
+        type: Array,
+        required: false,
+        default: () => [],
+    },
+});
+const proposalSelected = ref([]);
+const ticketConfig = ref({});
+const proposalTableRef = ref(null);
+
+const sale = computed(() => $props.sales[0]);
+const saleFk = computed(() => sale.value.saleFk);
+const filter = computed(() => ({
+    itemFk: $props.itemLack.itemFk,
+    sales: saleFk.value,
+}));
+
+const defaultColumnAttrs = {
+    align: 'center',
+    sortable: false,
+};
+const emit = defineEmits(['onDialogClosed', 'itemReplaced']);
+
+const conditionalValuePrice = (price) =>
+    price > 1 + ticketConfig.value.lackAlertPrice / 100 ? 'match' : 'not-match';
+
+const columns = computed(() => [
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.available'),
+        name: 'available',
+        field: 'available',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+        columnClass: 'shrink',
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.counter'),
+        name: 'counter',
+        field: 'counter',
+        columnClass: 'shrink',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+
+    {
+        align: 'left',
+        sortable: true,
+        label: t('proposal.longName'),
+        name: 'longName',
+        field: 'longName',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.color'),
+        name: 'tag5',
+        field: 'value5',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.stems'),
+        name: 'tag6',
+        field: 'value6',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.producer'),
+        name: 'tag7',
+        field: 'value7',
+        columnClass: 'expand',
+    },
+
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.price2'),
+        name: 'price2',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.minQuantity'),
+        name: 'minQuantity',
+        field: 'minQuantity',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.located'),
+        name: 'located',
+        field: 'located',
+    },
+    {
+        align: 'right',
+        label: '',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('Replace'),
+                icon: 'change_circle',
+                show: (row) => isSelectionAvailable(row),
+                action: change,
+                isPrimary: true,
+            },
+        ],
+    },
+]);
+
+function extractMatchValues(obj) {
+    return Object.keys(obj)
+        .filter((key) => key.startsWith(MATCH))
+        .map((key) => parseInt(key.replace(MATCH, ''), 10));
+}
+const gradientStyle = (value) => {
+    let color = 'white';
+    const perc = parseFloat(value);
+    switch (true) {
+        case perc >= 0 && perc < 33:
+            color = 'primary';
+            break;
+        case perc >= 33 && perc < 66:
+            color = 'warning';
+            break;
+
+        default:
+            color = 'secondary';
+            break;
+    }
+    return color;
+};
+const statusConditionalValue = (row) => {
+    const matches = extractMatchValues(row);
+    const value = matches.reduce((acc, i) => acc + row[`${MATCH}${i}`], 0);
+    return 100 * (value / matches.length);
+};
+
+const isSelectionAvailable = (itemProposal) => {
+    const { price2 } = itemProposal;
+    const salePrice = sale.value.price;
+    const byPrice = (100 * price2) / salePrice > ticketConfig.value.lackAlertPrice;
+    if (byPrice) {
+        return byPrice;
+    }
+    const byQuantity =
+        (100 * itemProposal.available) / Math.abs($props.itemLack.lack) <
+        ticketConfig.value.lackAlertPrice;
+    return byQuantity;
+};
+
+async function change({ itemFk: substitutionFk }) {
+    try {
+        const promises = $props.sales.map(({ saleFk, quantity }) => {
+            const params = {
+                saleFk,
+                substitutionFk,
+                quantity,
+            };
+            return axios.post('Sales/replaceItem', params);
+        });
+        const results = await Promise.allSettled(promises);
+
+        notifyResults(results, 'saleFk');
+        emit('itemReplaced', {
+            type: 'refresh',
+            quantity: quantity.value,
+            itemProposal: proposalSelected.value[0],
+        });
+        proposalSelected.value = [];
+    } catch (error) {
+        console.error(error);
+    }
+}
+
+async function handleTicketConfig(data) {
+    ticketConfig.value = data[0];
+}
+</script>
+<template>
+    <FetchData
+        url="TicketConfigs"
+        :filter="{ fields: ['lackAlertPrice'] }"
+        @on-fetch="handleTicketConfig"
+        auto-load
+    />
+
+    <VnTable
+        v-if="ticketConfig"
+        auto-load
+        data-cy="proposalTable"
+        ref="proposalTableRef"
+        data-key="ItemsGetSimilar"
+        url="Items/getSimilar"
+        :user-filter="filter"
+        :columns="columns"
+        class="full-width q-mt-md"
+        row-key="id"
+        :row-click="change"
+        :is-editable="false"
+        :right-search="false"
+        :without-header="true"
+        :disable-option="{ card: true, table: true }"
+    >
+        <template #column-longName="{ row }">
+            <QTd
+                class="flex"
+                style="max-width: 100%; flex-shrink: 50px; flex-wrap: nowrap"
+            >
+                <div
+                    class="middle full-width"
+                    :class="[`proposal-${gradientStyle(statusConditionalValue(row))}`]"
+                >
+                    <QTooltip> {{ statusConditionalValue(row) }}% </QTooltip>
+                </div>
+                <div style="flex: 2 0 100%; align-content: center">
+                    <div>
+                        <span class="link">{{ row.longName }}</span>
+                        <ItemDescriptorProxy :id="row.id" />
+                    </div>
+                </div>
+            </QTd>
+        </template>
+        <template #column-tag5="{ row }">
+            <span :class="{ match: !row.match5 }">{{ row.value5 }}</span>
+        </template>
+        <template #column-tag6="{ row }">
+            <span :class="{ match: !row.match6 }">{{ row.value6 }}</span>
+        </template>
+        <template #column-tag7="{ row }">
+            <span :class="{ match: !row.match7 }">{{ row.value7 }}</span>
+        </template>
+        <template #column-counter="{ row }">
+            <span
+                :class="{
+                    match: row.counter === 1,
+                    'not-match': row.counter !== 1,
+                }"
+                >{{ row.counter }}</span
+            >
+        </template>
+        <template #column-minQuantity="{ row }">
+            {{ row.minQuantity }}
+        </template>
+        <template #column-price2="{ row }">
+            <div class="flex column items-center content-center">
+                <VnStockValueDisplay :value="(sales[0].price - row.price2) / 100" />
+                <span :class="[conditionalValuePrice(row.price2)]">{{
+                    toCurrency(row.price2)
+                }}</span>
+            </div>
+        </template>
+    </VnTable>
+</template>
+<style lang="scss" scoped>
+@import 'src/css/quasar.variables.scss';
+.middle {
+    float: left;
+    margin-right: 2px;
+    flex: 2 0 5px;
+}
+.match {
+    color: $negative;
+}
+.not-match {
+    color: inherit;
+}
+.proposal-warning {
+    background-color: $warning;
+}
+.proposal-secondary {
+    background-color: $secondary;
+}
+.proposal-primary {
+    background-color: $primary;
+}
+.text {
+    margin: 0.05rem;
+    padding: 1px;
+    border: 1px solid var(--vn-label-color);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: smaller;
+}
+</style>
diff --git a/src/pages/Item/components/ItemProposalProxy.vue b/src/pages/Item/components/ItemProposalProxy.vue
new file mode 100644
index 000000000..7da0ce398
--- /dev/null
+++ b/src/pages/Item/components/ItemProposalProxy.vue
@@ -0,0 +1,56 @@
+<script setup>
+import ItemProposal from './ItemProposal.vue';
+import { useDialogPluginComponent } from 'quasar';
+
+const $props = defineProps({
+    itemLack: {
+        type: Object,
+        required: true,
+        default: () => {},
+    },
+    replaceAction: {
+        type: Boolean,
+        required: false,
+        default: false,
+    },
+    sales: {
+        type: Array,
+        required: false,
+        default: () => [],
+    },
+});
+const { dialogRef } = useDialogPluginComponent();
+const emit = defineEmits([
+    'onDialogClosed',
+    'itemReplaced',
+    ...useDialogPluginComponent.emits,
+]);
+defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
+</script>
+<template>
+    <QDialog ref="dialogRef" transition-show="scale" transition-hide="scale">
+        <QCard class="dialog-width">
+            <QCardSection class="row items-center q-pb-none">
+                <span class="text-h6 text-grey">{{ $t('Item proposal') }}</span>
+                <QSpace />
+                <QBtn icon="close" flat round dense v-close-popup />
+            </QCardSection>
+            <QCardSection>
+                <ItemProposal
+                    v-bind="$props"
+                    @item-replaced="
+                        (data) => {
+                            emit('itemReplaced', data);
+                            dialogRef.hide();
+                        }
+                    "
+                ></ItemProposal
+            ></QCardSection>
+        </QCard>
+    </QDialog>
+</template>
+<style lang="scss" scoped>
+.dialog-width {
+    max-width: $width-lg;
+}
+</style>
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index bc73abb12..9d27fc96e 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -112,6 +112,7 @@ item:
         available: Available
         warehouseText: 'Calculated on the warehouse of { warehouseName }'
         itemDiary: Item diary
+        itemLastEntries: Last entries
         producer: Producer
         clone:
             title: All its properties will be copied
@@ -130,6 +131,7 @@ item:
         origin: Orig.
         userName: Buyer
         weight: Weight
+        color: Color
         weightByPiece: Weight/stem
         stemMultiplier: Multiplier
         producer: Producer
@@ -215,4 +217,24 @@ item:
         specie: Specie
     search: 'Search item'
     searchInfo: 'You can search by id'
-    regularizeStock: Regularize stock
\ No newline at end of file
+    regularizeStock: Regularize stock
+itemProposal: Items proposal
+proposal:
+    difference: Difference
+    title: Items proposal
+    itemFk: Item
+    longName: Name
+    subName: Producer
+    value5: value5
+    value6: value6
+    value7: value7
+    value8: value8
+    available: Available
+    minQuantity: minQuantity
+    price2: Price
+    located: Located
+    counter: Counter
+    groupingPrice: Grouping Price
+    itemOldPrice: itemOld Price
+    status: State
+    quantityToReplace: Quanity to replace
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index dd5074f5f..935f5160b 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -118,6 +118,7 @@ item:
         available: Disponible
         warehouseText: 'Calculado sobre el almacén de { warehouseName }'
         itemDiary: Registro de compra-venta
+        itemLastEntries: Últimas entradas
         producer: Productor
         clone:
             title: Todas sus propiedades serán copiadas
@@ -135,6 +136,7 @@ item:
         size: Medida
         origin: Orig.
         weight: Peso
+        color: Color
         weightByPiece: Peso/tallo
         userName: Comprador
         stemMultiplier: Multiplicador
@@ -220,5 +222,30 @@ item:
         achieved: 'Conseguido'
         concept: 'Concepto'
         state: 'Estado'
-    search: 'Buscar artículo'
-    searchInfo: 'Puedes buscar por id'
+itemProposal: Artículos similares
+proposal:
+    substitutionAvailable: Sustitución disponible
+    notSubstitutionAvailableByPrice: Sustitución no disponible, 30% de diferencia por precio o cantidad
+    compatibility: Compatibilidad
+    title: Items de sustitución para los tickets seleccionados
+    itemFk: Item
+    longName: Nombre
+    subName: Productor
+    value5: value5
+    value6: value6
+    value7: value7
+    value8: value8
+    available: Disponible
+    minQuantity: Min. cantidad
+    price2: Precio
+    located: Ubicado
+    counter: Contador
+    difference: Diferencial
+    groupingPrice: Precio Grouping
+    itemOldPrice: Precio itemOld
+    status: Estado
+    quantityToReplace: Cantidad a reemplazar
+    replace: Sustituir
+    replaceAndConfirm: Sustituir y confirmar precio
+search: 'Buscar artículo'
+searchInfo: 'Puedes buscar por id'
diff --git a/src/pages/Monitor/MonitorOrders.vue b/src/pages/Monitor/MonitorOrders.vue
index 4efab56fb..873f8abb4 100644
--- a/src/pages/Monitor/MonitorOrders.vue
+++ b/src/pages/Monitor/MonitorOrders.vue
@@ -157,7 +157,7 @@ const openTab = (id) =>
                         openConfirmationModal(
                             $t('globals.deleteConfirmTitle'),
                             $t('salesOrdersTable.deleteConfirmMessage'),
-                            removeOrders
+                            removeOrders,
                         )
                     "
                 >
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index 21324087c..496c8761a 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -38,6 +38,7 @@ salesTicketsTable:
     payMethod: Pay method
     department: Department
     packing: ITP
+    hasItemLost: Item lost
 searchBar:
     label: Search tickets
     info: Search tickets by id or alias
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index 30afb1904..f6a29879f 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -39,6 +39,7 @@ salesTicketsTable:
     payMethod: Método de pago
     department: Departamento
     packing: ITP
+    hasItemLost: Artículo perdido
 searchBar:
     label: Buscar tickets
     info: Buscar tickets por identificador o alias
diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index b91e7d229..d1bd48c9e 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -110,7 +110,7 @@ const getSelectedTagValues = async (tag) => {
             </div>
             <QBtn
                 icon="add_circle"
-                shortcut="+"
+                v-shortcut="'+'"
                 flat
                 class="filter-icon q-mb-md"
                 size="md"
diff --git a/src/pages/Order/Card/OrderBasicData.vue b/src/pages/Order/Card/OrderBasicData.vue
index 8594a05f4..9c02d7494 100644
--- a/src/pages/Order/Card/OrderBasicData.vue
+++ b/src/pages/Order/Card/OrderBasicData.vue
@@ -14,7 +14,6 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const { t } = useI18n();
 const route = useRoute();
 const state = useState();
-const ORDER_MODEL = 'order';
 
 const isNew = Boolean(!route.params.id);
 const clientList = ref([]);
@@ -32,7 +31,7 @@ const fetchAddressList = async (addressId) => {
     });
     addressList.value = data;
     if (addressList.value?.length === 1) {
-        state.get(ORDER_MODEL).addressFk = addressList.value[0].id;
+        state.get('Order').addressFk = addressList.value[0].id;
     }
 };
 
@@ -91,9 +90,8 @@ const onClientChange = async (clientId) => {
     <VnSubToolbar v-if="isNew" />
     <div class="q-pa-md">
         <FormModel
-            :url="`Orders/${route.params.id}`"
             :url-update="`Orders/${route.params.id}/updateBasicData`"
-            :model="ORDER_MODEL"
+            model="Order"
             :filter="orderFilter"
             @on-fetch="fetchOrderDetails"
             auto-load
diff --git a/src/pages/Order/Card/OrderCard.vue b/src/pages/Order/Card/OrderCard.vue
index 823815f59..ad5c73a87 100644
--- a/src/pages/Order/Card/OrderCard.vue
+++ b/src/pages/Order/Card/OrderCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
+import filter from './OrderFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Order"
-        base-url="Orders"
+        url="Orders"
+        :filter="filter"
         :descriptor="OrderDescriptor"
     />
 </template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 262f503fd..76e608983 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -184,7 +184,7 @@ function addOrder(value, field, params) {
                         {{
                             t(
                                 categoryList.find((c) => c.id == customTag.value)?.name ||
-                                    ''
+                                    '',
                             )
                         }}
                     </strong>
@@ -296,7 +296,7 @@ function addOrder(value, field, params) {
                     <template #append>
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             color="primary"
                             size="md"
diff --git a/src/pages/Order/Card/OrderCatalogItemDialog.vue b/src/pages/Order/Card/OrderCatalogItemDialog.vue
index 77f6a8405..766945e4d 100644
--- a/src/pages/Order/Card/OrderCatalogItemDialog.vue
+++ b/src/pages/Order/Card/OrderCatalogItemDialog.vue
@@ -20,7 +20,7 @@ const props = defineProps({
 });
 const state = useState();
 
-const orderData = computed(() => state.get('orderData'));
+const orderData = computed(() => state.get('Order'));
 
 const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
 const isLoading = ref(false);
@@ -39,11 +39,11 @@ const addToOrder = async () => {
     });
 
     const { data: orderTotal } = await axios.get(
-        `Orders/${Number(route.params.id)}/getTotal`
+        `Orders/${Number(route.params.id)}/getTotal`,
     );
 
     state.set('orderTotal', orderTotal);
-    state.set('orderData', {
+    state.set('Order', {
         ...orderData.value,
         items,
     });
@@ -56,7 +56,7 @@ const canAddToOrder = () => {
     if (canAddToOrder) {
         const excedQuantity = prices.value.reduce(
             (acc, { quantity }) => acc + quantity,
-            0
+            0,
         );
         if (excedQuantity > props.item.available) {
             canAddToOrder = false;
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index 0d5f0146f..0d18864dc 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -4,8 +4,7 @@ import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toCurrency, toDate } from 'src/filters';
 import { useState } from 'src/composables/useState';
-import useCardDescription from 'src/composables/useCardDescription';
-
+import filter from './OrderFilter.js';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import FetchData from 'components/FetchData.vue';
@@ -24,44 +23,15 @@ const $props = defineProps({
 const route = useRoute();
 const state = useState();
 const { t } = useI18n();
-const data = ref(useCardDescription());
 const getTotalRef = ref();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const filter = {
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['name'] } },
-        {
-            relation: 'address',
-            scope: { fields: ['nickname'] },
-        },
-        { relation: 'rows', scope: { fields: ['id'] } },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'salesPersonFk',
-                    'name',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                ],
-                include: {
-                    relation: 'salesPersonUser',
-                    scope: { fields: ['id', 'name'] },
-                },
-            },
-        },
-    ],
-};
-
 const setData = (entity) => {
     if (!entity) return;
     getTotalRef.value && getTotalRef.value.fetch();
-    data.value = useCardDescription(entity?.client?.name, entity?.id);
     state.set('orderTotal', total);
 };
 
@@ -87,11 +57,9 @@ const total = ref(0);
         ref="descriptor"
         :url="`Orders/${entityId}`"
         :filter="filter"
-        module="Order"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        title="client.name"
         @on-fetch="setData"
-        data-key="orderData"
+        data-key="Order"
     >
         <template #body="{ entity }">
             <VnLv
diff --git a/src/pages/Order/Card/OrderFilter.js b/src/pages/Order/Card/OrderFilter.js
new file mode 100644
index 000000000..3e521b92c
--- /dev/null
+++ b/src/pages/Order/Card/OrderFilter.js
@@ -0,0 +1,26 @@
+export default {
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['name'] } },
+        {
+            relation: 'address',
+            scope: { fields: ['nickname'] },
+        },
+        { relation: 'rows', scope: { fields: ['id'] } },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'salesPersonFk',
+                    'name',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                ],
+                include: {
+                    relation: 'salesPersonUser',
+                    scope: { fields: ['id', 'name'] },
+                },
+            },
+        },
+    ],
+};
diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index cf219a244..1b864de6f 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -21,7 +21,7 @@ const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
 const quasar = useQuasar();
-const descriptorData = useArrayData('orderData');
+const descriptorData = useArrayData('Order');
 const componentKey = ref(0);
 const tableLinesRef = ref();
 const order = ref();
@@ -238,7 +238,7 @@ watch(
         lineFilter.value.where.orderFk = router.currentRoute.value.params.id;
 
         tableLinesRef.value.reload();
-    }
+    },
 );
 </script>
 
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index a289688e4..a4bdb2881 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -27,7 +27,7 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const summary = ref();
 const quasar = useQuasar();
-const descriptorData = useArrayData('orderData');
+const descriptorData = useArrayData('Order');
 const detailsColumns = ref([
     {
         name: 'item',
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 21cb5ed7e..40990f329 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -71,8 +71,9 @@ const columns = computed(() => [
         format: (row) => row?.name,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'isConfirmed',
+        component: 'checkbox',
         label: t('module.isConfirmed'),
     },
     {
@@ -95,7 +96,9 @@ const columns = computed(() => [
         columnField: {
             component: null,
         },
-        style: 'color="positive"',
+        style: () => {
+            return { color: 'positive' };
+        },
     },
     {
         align: 'left',
diff --git a/src/pages/Route/Agency/AgencyList.vue b/src/pages/Route/Agency/AgencyList.vue
index 4322b9bc8..5c2904bf3 100644
--- a/src/pages/Route/Agency/AgencyList.vue
+++ b/src/pages/Route/Agency/AgencyList.vue
@@ -51,7 +51,6 @@ const columns = computed(() => [
         name: 'isAnyVolumeAllowed',
         component: 'checkbox',
         cardVisible: true,
-        disable: true,
     },
     {
         align: 'right',
@@ -72,7 +71,7 @@ const columns = computed(() => [
         :data-key
         :columns="columns"
         prefix="agency"
-        :right-filter="false"
+        :right-filter="true"
         :array-data-props="{
             url: 'Agencies',
             order: 'name',
@@ -83,6 +82,7 @@ const columns = computed(() => [
             <VnTable
                 :data-key
                 :columns="columns"
+                is-editable="false"
                 :right-search="false"
                 :use-model="true"
                 redirect="route/agency"
diff --git a/src/pages/Route/Agency/Card/AgencyBasicData.vue b/src/pages/Route/Agency/Card/AgencyBasicData.vue
index 599058b3e..4270b136c 100644
--- a/src/pages/Route/Agency/Card/AgencyBasicData.vue
+++ b/src/pages/Route/Agency/Card/AgencyBasicData.vue
@@ -21,7 +21,7 @@ const warehouses = ref([]);
         @on-fetch="(data) => (warehouses = data)"
         auto-load
     />
-    <FormModel :url="`Agencies/${routeId}`" model="agency" auto-load>
+    <FormModel :update-url="`Agencies/${routeId}`" model="Agency" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.name" :label="t('globals.name')" />
diff --git a/src/pages/Route/Agency/Card/AgencyCard.vue b/src/pages/Route/Agency/Card/AgencyCard.vue
index 35685790a..7dc31f8ba 100644
--- a/src/pages/Route/Agency/Card/AgencyCard.vue
+++ b/src/pages/Route/Agency/Card/AgencyCard.vue
@@ -3,5 +3,5 @@ import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Agency" base-url="Agencies" :descriptor="AgencyDescriptor" />
+    <VnCardBeta data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" />
 </template>
diff --git a/src/pages/Route/Agency/Card/AgencyDescriptor.vue b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
index b9772037c..a0472c6c3 100644
--- a/src/pages/Route/Agency/Card/AgencyDescriptor.vue
+++ b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
@@ -22,7 +22,6 @@ const card = computed(() => store.data);
 </script>
 <template>
     <CardDescriptor
-        module="Agency"
         data-key="Agency"
         :url="`Agencies/${entityId}`"
         :title="card?.name"
diff --git a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
index 7cabf396d..9a9213868 100644
--- a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
+++ b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
@@ -88,7 +88,7 @@ async function deleteWorCenter(id) {
         </VnPaginate>
     </div>
     <QPageSticky :offset="[18, 18]">
-        <QBtn @click.stop="dialog.show()" color="primary" fab shortcut="+" icon="add">
+        <QBtn @click.stop="dialog.show()" color="primary" fab v-shortcut="'+'" icon="add">
             <QDialog ref="dialog">
                 <FormModelPopup
                     :title="t('Add work center')"
diff --git a/src/pages/Route/Card/RouteCard.vue b/src/pages/Route/Card/RouteCard.vue
index 81b6cfa16..c178dc6bf 100644
--- a/src/pages/Route/Card/RouteCard.vue
+++ b/src/pages/Route/Card/RouteCard.vue
@@ -1,12 +1,13 @@
 <script setup>
 import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
+import filter from './RouteFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Route"
-        base-url="Routes"
-        custom-url="Routes/filter"
+        url="Routes"
+        :filter="filter"
         :descriptor="RouteDescriptor"
     />
 </template>
diff --git a/src/pages/Route/Card/RouteDescriptor.vue b/src/pages/Route/Card/RouteDescriptor.vue
index 68c08b821..503cd1941 100644
--- a/src/pages/Route/Card/RouteDescriptor.vue
+++ b/src/pages/Route/Card/RouteDescriptor.vue
@@ -1,13 +1,14 @@
 <script setup>
 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 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDate } from 'src/filters';
 import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
+import filter from './RouteFilter.js';
+import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
+
 const $props = defineProps({
     id: {
         type: Number,
@@ -17,7 +18,6 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
 const zone = ref();
 const zoneId = ref();
 const entityId = computed(() => {
@@ -36,81 +36,31 @@ const getZone = async () => {
     const { data: zoneData } = await axios.get(`Zones/${zoneId.value}`);
     zone.value = zoneData.name;
 };
-
-const filter = {
-    fields: [
-        'id',
-        'workerFk',
-        'agencyModeFk',
-        'dated',
-        'm3',
-        'warehouseFk',
-        'description',
-        'vehicleFk',
-        'kmStart',
-        'kmEnd',
-        'started',
-        'finished',
-        'cost',
-        'isOk',
-    ],
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
-        {
-            relation: 'vehicle',
-            scope: { fields: ['id', 'm3'] },
-        },
-        {
-            relation: 'ticket',
-            scope: {
-                fields: ['id', 'name', 'zoneFk'],
-                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
-            },
-        },
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: {
-                        fields: ['id'],
-                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
-                    },
-                },
-            },
-        },
-    ],
-};
 const data = ref(useCardDescription());
 const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 onMounted(async () => {
     getZone();
 });
 </script>
-
 <template>
     <CardDescriptor
-        module="Route"
         :url="`Routes/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="routeData"
-        @on-fetch="setData"
+        :title="null"
+        data-key="Route"
         width="lg-width"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('Date')" :value="toDate(entity?.dated)" />
-            <VnLv :label="t('Agency')" :value="entity?.agencyMode?.name" />
-            <VnLv :label="t('Zone')" :value="zone" />
+            <VnLv :label="$t('Date')" :value="toDate(entity?.dated)" />
+            <VnLv :label="$t('Agency')" :value="entity?.agencyMode?.name" />
+            <VnLv :label="$t('Zone')" :value="zone" />
             <VnLv
-                :label="t('Volume')"
+                :label="$t('Volume')"
                 :value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty(
                     entity?.vehicle?.m3,
                 )} m³`"
             />
-            <VnLv :label="t('Description')" :value="entity?.description" />
+            <VnLv :label="$t('Description')" :value="entity?.description" />
         </template>
         <template #menu="{ entity }">
             <RouteDescriptorMenu :route="entity" />
diff --git a/src/pages/Route/Card/RouteFilter.js b/src/pages/Route/Card/RouteFilter.js
new file mode 100644
index 000000000..90ee71bf7
--- /dev/null
+++ b/src/pages/Route/Card/RouteFilter.js
@@ -0,0 +1,39 @@
+export default {
+    fields: [
+        'code',
+        'id',
+        'workerFk',
+        'agencyModeFk',
+        'created',
+        'm3',
+        'warehouseFk',
+        'description',
+        'vehicleFk',
+        'kmStart',
+        'kmEnd',
+        'started',
+        'finished',
+        'cost',
+        'isOk',
+    ],
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
+        {
+            relation: 'vehicle',
+            scope: { fields: ['id', 'm3'] },
+        },
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: {
+                        fields: ['id'],
+                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
+                    },
+                },
+            },
+        },
+    ],
+};
diff --git a/src/pages/Route/Card/RouteFilter.vue b/src/pages/Route/Card/RouteFilter.vue
index 72bfed1da..21858102b 100644
--- a/src/pages/Route/Card/RouteFilter.vue
+++ b/src/pages/Route/Card/RouteFilter.vue
@@ -100,7 +100,7 @@ const emit = defineEmits(['search']);
                     <VnSelect
                         :label="t('Vehicle')"
                         v-model="params.vehicleFk"
-                        url="Vehicles"
+                        url="Vehicles/active"
                         sort-by="numberPlate ASC"
                         option-value="id"
                         option-label="numberPlate"
diff --git a/src/pages/Route/Card/RouteForm.vue b/src/pages/Route/Card/RouteForm.vue
index 633ff44bc..667204b15 100644
--- a/src/pages/Route/Card/RouteForm.vue
+++ b/src/pages/Route/Card/RouteForm.vue
@@ -11,6 +11,7 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInput from 'components/common/VnInput.vue';
 import axios from 'axios';
 import VnInputTime from 'components/common/VnInputTime.vue';
+import filter from './RouteFilter.js';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
 
 const { t } = useI18n();
@@ -27,52 +28,6 @@ const defaultInitialData = {
     isOk: false,
 };
 const maxDistance = ref();
-
-const routeFilter = {
-    fields: [
-        'id',
-        'workerFk',
-        'agencyModeFk',
-        'dated',
-        'm3',
-        'warehouseFk',
-        'description',
-        'vehicleFk',
-        'kmStart',
-        'kmEnd',
-        'started',
-        'finished',
-        'cost',
-        'isOk',
-    ],
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
-        {
-            relation: 'vehicle',
-            scope: { fields: ['id', 'm3'] },
-        },
-        {
-            relation: 'ticket',
-            scope: {
-                fields: ['id', 'name', 'zoneFk'],
-                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
-            },
-        },
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: {
-                        fields: ['id'],
-                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
-                    },
-                },
-            },
-        },
-    ],
-};
 const onSave = (data, response) => {
     if (isNew) {
         axios.post(`Routes/${response?.id}/updateWorkCenter`);
@@ -89,11 +44,10 @@ const onSave = (data, response) => {
         sort-by="id ASC"
     />
     <FormModel
-        :url="isNew ? null : `Routes/${route.params?.id}`"
         :url-create="isNew ? 'Routes' : null"
         :observe-form-changes="!isNew"
-        :filter="routeFilter"
-        model="route"
+        :filter="filter"
+        model="Route"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -104,7 +58,7 @@ const onSave = (data, response) => {
                 <VnSelect
                     :label="t('Vehicle')"
                     v-model="data.vehicleFk"
-                    url="Vehicles"
+                    url="Vehicles/active"
                     sort-by="numberPlate ASC"
                     option-value="id"
                     option-label="numberPlate"
diff --git a/src/pages/Route/Roadmap/RoadmapBasicData.vue b/src/pages/Route/Roadmap/RoadmapBasicData.vue
index 2fe805362..a9e6059c3 100644
--- a/src/pages/Route/Roadmap/RoadmapBasicData.vue
+++ b/src/pages/Route/Roadmap/RoadmapBasicData.vue
@@ -11,17 +11,16 @@ import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 const { t } = useI18n();
 const router = useRouter();
 
-const filter = { include: [{ relation: 'supplier' }] };
 const onSave = (data, response) => {
     router.push({ name: 'RoadmapSummary', params: { id: response?.id } });
 };
 </script>
 <template>
     <FormModel
+        :update-url="`Roadmaps/${$route.params?.id}`"
         :url="`Roadmaps/${$route.params?.id}`"
         observe-form-changes
-        :filter="filter"
-        model="roadmap"
+        model="Roadmap"
         auto-load
         @on-data-saved="onSave"
     >
diff --git a/src/pages/Route/Roadmap/RoadmapCard.vue b/src/pages/Route/Roadmap/RoadmapCard.vue
index 0b81de673..48ba516a1 100644
--- a/src/pages/Route/Roadmap/RoadmapCard.vue
+++ b/src/pages/Route/Roadmap/RoadmapCard.vue
@@ -3,5 +3,5 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Roadmap" base-url="Roadmaps" :descriptor="RoadmapDescriptor" />
+    <VnCardBeta data-key="Roadmap" url="Roadmaps" :descriptor="RoadmapDescriptor" />
 </template>
diff --git a/src/pages/Route/Roadmap/RoadmapDescriptor.vue b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
index 788173688..baa864a15 100644
--- a/src/pages/Route/Roadmap/RoadmapDescriptor.vue
+++ b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
@@ -1,13 +1,13 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDateHourMin } from 'src/filters';
 import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
 import RoadmapDescriptorMenu from 'pages/Route/Roadmap/RoadmapDescriptorMenu.vue';
+import filter from 'pages/Route/Roadmap/RoadmapFilter.js';
 
 const $props = defineProps({
     id: {
@@ -23,22 +23,10 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = { include: [{ relation: 'supplier' }] };
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
 
 <template>
-    <CardDescriptor
-        module="Roadmap"
-        :url="`Roadmaps/${entityId}`"
-        :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="Roadmap"
-        @on-fetch="setData"
-    >
+    <CardDescriptor :url="`Roadmaps/${entityId}`" :filter="filter" data-key="Roadmap">
         <template #body="{ entity }">
             <VnLv :label="t('Roadmap')" :value="entity?.name" />
             <VnLv :label="t('ETD')" :value="toDateHourMin(entity?.etd)" />
diff --git a/src/pages/Route/Roadmap/RoadmapFilter.js b/src/pages/Route/Roadmap/RoadmapFilter.js
new file mode 100644
index 000000000..0ae890363
--- /dev/null
+++ b/src/pages/Route/Roadmap/RoadmapFilter.js
@@ -0,0 +1,3 @@
+export default {
+    include: [{ relation: 'supplier' }],
+};
diff --git a/src/pages/Route/Roadmap/RoadmapStops.vue b/src/pages/Route/Roadmap/RoadmapStops.vue
index d8215ea49..e4085d572 100644
--- a/src/pages/Route/Roadmap/RoadmapStops.vue
+++ b/src/pages/Route/Roadmap/RoadmapStops.vue
@@ -68,7 +68,7 @@ const updateDefaultStop = (data) => {
                         <QBtn
                             flat
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             class="cursor-pointer"
                             color="primary"
                             @click="roadmapStopsCrudRef.insert()"
diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue
index 1fbb1897d..0c1c2b903 100644
--- a/src/pages/Route/Roadmap/RoadmapSummary.vue
+++ b/src/pages/Route/Roadmap/RoadmapSummary.vue
@@ -67,7 +67,6 @@ const filter = {
             },
         },
     ],
-    where: { id: entityId },
 };
 </script>
 
@@ -76,7 +75,7 @@ const filter = {
         <CardSummary
             data-key="RoadmapSummary"
             ref="summary"
-            :url="`Roadmaps`"
+            :url="`Roadmaps/${entityId}`"
             :filter="filter"
         >
             <template #header-left>
diff --git a/src/pages/Route/RouteExtendedList.vue b/src/pages/Route/RouteExtendedList.vue
index 221fc4754..46bc1a690 100644
--- a/src/pages/Route/RouteExtendedList.vue
+++ b/src/pages/Route/RouteExtendedList.vue
@@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import { useQuasar } from 'quasar';
-import { toDate } from 'src/filters';
+import { dashIfEmpty, toDate, toHour } from 'src/filters';
 import { useRouter } from 'vue-router';
 import { usePrintService } from 'src/composables/usePrintService';
 
@@ -38,7 +38,7 @@ const routeFilter = {
 };
 const columns = computed(() => [
     {
-        align: 'left',
+        align: 'center',
         name: 'id',
         label: 'Id',
         chip: {
@@ -48,7 +48,7 @@ const columns = computed(() => [
         columnFilter: false,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'workerFk',
         label: t('route.Worker'),
         create: true,
@@ -68,10 +68,10 @@ const columns = computed(() => [
         },
         useLike: false,
         cardVisible: true,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.workerUserName),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'agencyModeFk',
         label: t('route.Agency'),
         isTitle: true,
@@ -87,17 +87,17 @@ const columns = computed(() => [
             },
         },
         columnClass: 'expand',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyName),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'vehicleFk',
         label: t('route.Vehicle'),
         cardVisible: true,
         create: true,
         component: 'select',
         attrs: {
-            url: 'vehicles',
-            fields: ['id', 'numberPlate'],
+            url: 'vehicles/active',
             optionLabel: 'numberPlate',
             optionFilterValue: 'numberPlate',
             find: {
@@ -108,29 +108,31 @@ const columns = computed(() => [
         columnFilter: {
             inWhere: true,
         },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.vehiclePlateNumber),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'dated',
         label: t('route.Date'),
         columnFilter: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ date }) => toDate(date),
+        format: ({ dated }, dashIfEmpty) =>
+            dated === '0000-00-00' ? dashIfEmpty(null) : toDate(dated),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'from',
         label: t('route.From'),
         visible: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ date }) => toDate(date),
+        format: ({ from }) => toDate(from),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'to',
         label: t('route.To'),
         visible: false,
@@ -147,18 +149,20 @@ const columns = computed(() => [
         columnClass: 'shrink',
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'started',
         label: t('route.hourStarted'),
         component: 'time',
         columnFilter: false,
+        format: ({ started }) => toHour(started),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'finished',
         label: t('route.hourFinished'),
         component: 'time',
         columnFilter: false,
+        format: ({ finished }) => toHour(finished),
     },
     {
         align: 'center',
@@ -177,7 +181,7 @@ const columns = computed(() => [
         visible: false,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'description',
         label: t('route.Description'),
         isTitle: true,
@@ -186,7 +190,7 @@ const columns = computed(() => [
         field: 'description',
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'isOk',
         label: t('route.Served'),
         component: 'checkbox',
@@ -300,60 +304,62 @@ const openTicketsDialog = (id) => {
             <RouteFilter data-key="RouteList" />
         </template>
     </RightMenu>
-    <VnTable
-        class="route-list"
-        ref="tableRef"
-        data-key="RouteList"
-        url="Routes/filter"
-        :columns="columns"
-        :right-search="false"
-        :is-editable="true"
-        :filter="routeFilter"
-        redirect="route"
-        :row-click="false"
-        :create="{
-            urlCreate: 'Routes',
-            title: t('route.createRoute'),
-            onDataSaved: ({ id }) => tableRef.redirect(id),
-            formInitialData: {},
-        }"
-        save-url="Routes/crud"
-        :disable-option="{ card: true }"
-        table-height="85vh"
-        v-model:selected="selectedRows"
-        :table="{
-            'row-key': 'id',
-            selection: 'multiple',
-        }"
-    >
-        <template #moreBeforeActions>
-            <QBtn
-                icon="vn:clone"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="confirmationDialog = true"
-            >
-                <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
-            </QBtn>
-            <QBtn
-                icon="cloud_download"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="showRouteReport"
-            >
-                <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
-            </QBtn>
-            <QBtn
-                icon="check"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="markAsServed()"
-            >
-                <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
-            </QBtn>
-        </template>
-    </VnTable>
+    <QPage class="q-px-md">
+        <VnTable
+            class="route-list"
+            ref="tableRef"
+            data-key="RouteList"
+            url="Routes/filter"
+            :columns="columns"
+            :right-search="false"
+            :is-editable="true"
+            :filter="routeFilter"
+            redirect="route"
+            :row-click="false"
+            :create="{
+                urlCreate: 'Routes',
+                title: t('route.createRoute'),
+                onDataSaved: ({ id }) => tableRef.redirect(id),
+                formInitialData: {},
+            }"
+            save-url="Routes/crud"
+            :disable-option="{ card: true }"
+            table-height="85vh"
+            v-model:selected="selectedRows"
+            :table="{
+                'row-key': 'id',
+                selection: 'multiple',
+            }"
+        >
+            <template #moreBeforeActions>
+                <QBtn
+                    icon="vn:clone"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="confirmationDialog = true"
+                >
+                    <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
+                </QBtn>
+                <QBtn
+                    icon="cloud_download"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="showRouteReport"
+                >
+                    <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
+                </QBtn>
+                <QBtn
+                    icon="check"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="markAsServed()"
+                >
+                    <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
+                </QBtn>
+            </template>
+        </VnTable>
+    </QPage>
 </template>
diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue
index bc3227f6c..9dad8ba22 100644
--- a/src/pages/Route/RouteList.vue
+++ b/src/pages/Route/RouteList.vue
@@ -38,6 +38,17 @@ const columns = computed(() => [
         align: 'left',
         name: 'workerFk',
         label: t('route.Worker'),
+        component: 'select',
+        attrs: {
+            url: 'Workers/activeWithInheritedRole',
+            fields: ['id', 'name'],
+            useLike: false,
+            optionFilter: 'firstName',
+            find: {
+                value: 'workerFk',
+                label: 'workerUserName',
+            },
+        },
         create: true,
         cardVisible: true,
         format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
@@ -48,6 +59,15 @@ const columns = computed(() => [
         name: 'agencyName',
         label: t('route.Agency'),
         cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'agencyModes',
+            fields: ['id', 'name'],
+            find: {
+                value: 'agencyModeFk',
+                label: 'agencyName',
+            },
+        },
         create: true,
         columnClass: 'expand',
         columnFilter: false,
@@ -57,6 +77,17 @@ const columns = computed(() => [
         name: 'vehiclePlateNumber',
         label: t('route.Vehicle'),
         cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'vehicles',
+            fields: ['id', 'numberPlate'],
+            optionLabel: 'numberPlate',
+            optionFilterValue: 'numberPlate',
+            find: {
+                value: 'vehicleFk',
+                label: 'vehiclePlateNumber',
+            },
+        },
         create: true,
         columnFilter: false,
     },
diff --git a/src/pages/Route/RouteTickets.vue b/src/pages/Route/RouteTickets.vue
index 1416f77ce..adc7dfdaa 100644
--- a/src/pages/Route/RouteTickets.vue
+++ b/src/pages/Route/RouteTickets.vue
@@ -120,8 +120,8 @@ const deletePriorities = async () => {
     try {
         await Promise.all(
             selectedRows.value.map((ticket) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: null })
-            )
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: null }),
+            ),
         );
     } finally {
         refreshKey.value++;
@@ -132,8 +132,8 @@ const setOrderedPriority = async () => {
     try {
         await Promise.all(
             ticketList.value.map((ticket, index) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 })
-            )
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 }),
+            ),
         );
     } finally {
         refreshKey.value++;
@@ -162,7 +162,7 @@ const setHighestPriority = async (ticket, ticketList) => {
 const goToBuscaman = async (ticket = null) => {
     await openBuscaman(
         routeEntity.value?.vehicleFk,
-        ticket ? [ticket] : selectedRows.value
+        ticket ? [ticket] : selectedRows.value,
     );
 };
 
@@ -393,7 +393,13 @@ const openSmsDialog = async () => {
             </VnPaginate>
         </div>
         <QPageSticky :offset="[20, 20]">
-            <QBtn fab icon="add" shortcut="+" color="primary" @click="openTicketsDialog">
+            <QBtn
+                fab
+                icon="add"
+                v-shortcut="'+'"
+                color="primary"
+                @click="openTicketsDialog"
+            >
                 <QTooltip>
                     {{ t('Add ticket') }}
                 </QTooltip>
diff --git a/src/pages/Route/Vehicle/Card/VehicleBasicData.vue b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
new file mode 100644
index 000000000..e78bc6edd
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
@@ -0,0 +1,162 @@
+<script setup>
+import { ref } from 'vue';
+import FormModel from 'components/FormModel.vue';
+import FetchData from 'src/components/FetchData.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnRow from 'components/ui/VnRow.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+
+const warehouses = ref([]);
+const companies = ref([]);
+const countries = ref([]);
+const fuelTypes = ref([]);
+const bankPolicies = ref([]);
+const deliveryPoints = ref([]);
+</script>
+<template>
+    <FetchData
+        url="Warehouses"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (warehouses = data)"
+        auto-load
+    />
+    <FetchData
+        url="Companies"
+        :filter="{ fields: ['id', 'code'] }"
+        @on-fetch="(data) => (companies = data)"
+        auto-load
+    />
+    <FetchData
+        url="Countries"
+        :filter="{ fields: ['code'] }"
+        @on-fetch="(data) => (countries = data)"
+        auto-load
+    />
+    <FetchData
+        url="FuelTypes"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (fuelTypes = data)"
+        auto-load
+    />
+    <FetchData
+        url="DeliveryPoints"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (deliveryPoints = data)"
+        auto-load
+    />
+    <FormModel model="Vehicle" :url-update="`Vehicles/${$route.params.id}`">
+        <template #form="{ data }">
+            <VnRow>
+                <VnInput v-model="data.description" :label="$t('globals.description')" />
+                <VnInput v-model="data.numberPlate" :label="$t('vehicle.numberPlate')" />
+            </VnRow>
+            <VnRow>
+                <VnInput
+                    v-model="data.model"
+                    :label="$t('globals.model')"
+                    :required="true"
+                />
+                <VnSelect
+                    url="VehicleTypes"
+                    v-model="data.vehicleTypeFk"
+                    :label="$t('globals.type')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnInput
+                    v-model="data.tradeMark"
+                    :label="$t('vehicle.tradeMark')"
+                    :required="true"
+                />
+                <VnInput v-model="data.chassis" :label="$t('vehicle.chassis')" />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    v-model="data.fuelTypeFk"
+                    :label="$t('globals.fuel')"
+                    :options="fuelTypes"
+                />
+                <VnSelect
+                    v-model="data.deliveryPointFk"
+                    :label="$t('globals.deliveryPoint')"
+                    :options="deliveryPoints"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    v-model="data.companyFk"
+                    :label="$t('globals.company')"
+                    :options="companies"
+                    option-label="code"
+                />
+                <VnSelect
+                    v-model="data.warehouseFk"
+                    :label="$t('globals.warehouse')"
+                    :options="warehouses"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="Suppliers"
+                    :filter="{ fields: ['id', 'name'] }"
+                    v-model="data.supplierFk"
+                    :label="$t('globals.supplier')"
+                />
+                <VnSelect
+                    url="Suppliers"
+                    :filter="{ fields: ['id', 'name'] }"
+                    v-model="data.supplierCoolerFk"
+                    :label="$t('vehicle.supplierCooler')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="BankPolicies"
+                    :filter="{ fields: ['id', 'ref'] }"
+                    v-model="data.bankPolicyFk"
+                    :label="$t('vehicle.leasing')"
+                    :options="bankPolicies"
+                    option-label="ref"
+                    option-value="id"
+                />
+                <VnInput v-model="data.leasing" :label="$t('vehicle.nLeasing')" />
+            </VnRow>
+            <VnRow>
+                <VnInputNumber v-model="data.import" :label="$t('globals.amount')" />
+                <VnInputNumber
+                    v-model="data.importCooler"
+                    :label="$t('vehicle.amountCooler')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="Ppes"
+                    option-label="id"
+                    v-model="data.ppeFk"
+                    :label="$t('vehicle.ppe')"
+                />
+                <VnSelect
+                    v-model="data.countryCodeFk"
+                    :label="$t('globals.country')"
+                    :options="countries"
+                    option-label="code"
+                    option-value="code"
+                />
+            </VnRow>
+            <VnRow>
+                <VnInput v-model="data.vin" :label="$t('vehicle.vin')" />
+                <span :style="{ 'align-self': $q.screen.gt.xs ? 'end' : 'unset' }">
+                    <QCheckbox
+                        v-model="data.isActive"
+                        :label="$t('vehicle.isActive')"
+                        :false-value="0"
+                        :true-value="1"
+                        dense
+                        class="q-mt-sm"
+                    />
+                </span>
+            </VnRow>
+        </template>
+    </FormModel>
+</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleCard.vue b/src/pages/Route/Vehicle/Card/VehicleCard.vue
new file mode 100644
index 000000000..f59420aa2
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleCard.vue
@@ -0,0 +1,13 @@
+<script setup>
+import VnCardBeta from 'components/common/VnCardBeta.vue';
+import VehicleDescriptor from './VehicleDescriptor.vue';
+import VehicleFilter from '../VehicleFilter.js';
+</script>
+<template>
+    <VnCardBeta
+        data-key="Vehicle"
+        url="Vehicles"
+        :filter="VehicleFilter"
+        :descriptor="VehicleDescriptor"
+    />
+</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
new file mode 100644
index 000000000..d9a2434ab
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
@@ -0,0 +1,49 @@
+<script setup>
+import VnLv from 'src/components/ui/VnLv.vue';
+import CardDescriptor from 'components/ui/CardDescriptor.vue';
+import axios from 'axios';
+import useNotify from 'src/composables/useNotify.js';
+
+const { notify } = useNotify();
+</script>
+<template>
+    <CardDescriptor
+        :url="`Vehicles/${$route.params.id}`"
+        data-key="Vehicle"
+        title="numberPlate"
+        :to-module="{ name: 'VehicleList' }"
+    >
+        <template #menu="{ entity }">
+            <QItem
+                data-cy="delete"
+                v-ripple
+                clickable
+                @click="
+                    async () => {
+                        try {
+                            await axios.delete(`Vehicles/${entity.id}`);
+                            notify('vehicle.remove', 'positive');
+                            $router.push({ name: 'VehicleList' });
+                        } catch (e) {
+                            throw e;
+                        }
+                    }
+                "
+            >
+                <QItemSection>
+                    {{ $t('vehicle.delete') }}
+                </QItemSection>
+            </QItem>
+        </template>
+        <template #body="{ entity }">
+            <VnLv :label="$t('vehicle.numberPlate')" :value="entity.numberPlate" />
+            <VnLv :label="$t('vehicle.tradeMark')" :value="entity.tradeMark" />
+            <VnLv :label="$t('globals.model')" :value="entity.model" />
+            <VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
+        </template>
+    </CardDescriptor>
+</template>
+<i18n>
+es:
+    Vehicle removed: Vehículo eliminado
+</i18n>
diff --git a/src/pages/Route/Vehicle/Card/VehicleSummary.vue b/src/pages/Route/Vehicle/Card/VehicleSummary.vue
new file mode 100644
index 000000000..981870cb2
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleSummary.vue
@@ -0,0 +1,127 @@
+<script setup>
+import { computed } from 'vue';
+import { useRoute } from 'vue-router';
+import CardSummary from 'components/ui/CardSummary.vue';
+import VnLv from 'src/components/ui/VnLv.vue';
+import VnTitle from 'src/components/common/VnTitle.vue';
+import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
+import VehicleFilter from '../VehicleFilter.js';
+import { downloadFile } from 'src/composables/downloadFile';
+import { dashIfEmpty } from 'src/filters';
+
+const props = defineProps({ id: { type: [Number, String], default: null } });
+
+const route = useRoute();
+const entityId = computed(() => props.id || +route.params.id);
+const links = {
+    'basic-data': `#/vehicle/${entityId.value}/basic-data`,
+    notes: `#/vehicle/${entityId.value}/notes`,
+    dms: `#/vehicle/${entityId.value}/dms`,
+    'invoice-in': `#/vehicle/${entityId.value}/invoice-in`,
+    events: `#/vehicle/${entityId.value}/events`,
+};
+</script>
+<template>
+    <CardSummary data-key="Vehicle" :url="`Vehicles/${entityId}`" :filter="VehicleFilter">
+        <template #header="{ entity }">
+            <div>{{ entity.id }} - {{ entity.numberPlate }}</div>
+        </template>
+        <template #body="{ entity }">
+            <QCard class="vn-one">
+                <QCardSection dense>
+                    <VnTitle
+                        :url="links['basic-data']"
+                        :text="$t('globals.pageTitles.basicData')"
+                    />
+                </QCardSection>
+                <QCardSection content>
+                    <QList dense>
+                        <VnLv
+                            :label="$t('globals.description')"
+                            :value="entity.description"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.tradeMark')"
+                            :value="entity.tradeMark"
+                        />
+                        <VnLv :label="$t('globals.model')" :value="entity.model" />
+                        <VnLv :label="$t('globals.supplier')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entity.supplier?.name }}
+                                    <SupplierDescriptorProxy :id="entity.supplierFk" />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('vehicle.supplierCooler')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entity.supplierCooler?.name }}
+                                    <SupplierDescriptorProxy
+                                        :id="entity.supplierCoolerFk"
+                                    />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('vehicle.vin')" :value="entity.vin" />
+                    </QList>
+                    <QList dense>
+                        <VnLv :label="$t('vehicle.chassis')" :value="entity.chassis" />
+                        <VnLv
+                            :label="$t('globals.fuel')"
+                            :value="entity.fuelType?.name"
+                        />
+                        <VnLv :label="$t('vehicle.ppe')" :value="entity.ppeFk" />
+                        <VnLv :label="$t('vehicle.nLeasing')" :value="entity.leasing" />
+                        <VnLv
+                            :label="$t('vehicle.leasing')"
+                            :value="entity.bankPolicy?.ref"
+                        >
+                            <template #value>
+                                <span v-text="dashIfEmpty(entity.bankPolicy?.name)" />
+                                <QBtn
+                                    v-if="entity.bankPolicy?.dmsFk"
+                                    class="q-ml-xs"
+                                    color="primary"
+                                    flat
+                                    dense
+                                    icon="cloud_download"
+                                    @click="downloadFile(entity.bankPolicy?.dmsFk)"
+                                >
+                                    <QTooltip>{{ $t('globals.download') }}</QTooltip>
+                                </QBtn>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('globals.amount')" :value="entity.import" />
+                    </QList>
+                    <QList dense>
+                        <VnLv
+                            :label="$t('globals.warehouse')"
+                            :value="entity.warehouse?.name"
+                        />
+                        <VnLv
+                            :label="$t('globals.company')"
+                            :value="entity.company?.code"
+                        />
+                        <VnLv
+                            :label="$t('globals.deliveryPoint')"
+                            :value="entity.deliveryPoint?.name"
+                        />
+                        <VnLv
+                            :label="$t('globals.country')"
+                            :value="entity.countryCodeFk"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.isKmTruckRate')"
+                            :value="!!entity.isKmTruckRate"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.isActive')"
+                            :value="!!entity.isActive"
+                        />
+                    </QList>
+                </QCardSection>
+            </QCard>
+        </template>
+    </CardSummary>
+</template>
diff --git a/src/pages/Route/Vehicle/VehicleFilter.js b/src/pages/Route/Vehicle/VehicleFilter.js
new file mode 100644
index 000000000..cbf5cc621
--- /dev/null
+++ b/src/pages/Route/Vehicle/VehicleFilter.js
@@ -0,0 +1,76 @@
+export default {
+    fields: [
+        'id',
+        'description',
+        'isActive',
+        'isKmTruckRate',
+        'warehouseFk',
+        'companyFk',
+        'numberPlate',
+        'chassis',
+        'supplierFk',
+        'supplierCoolerFk',
+        'tradeMark',
+        'fuelTypeFk',
+        'import',
+        'importCooler',
+        'vin',
+        'model',
+        'ppeFk',
+        'countryCodeFk',
+        'leasing',
+        'bankPolicyFk',
+        'vehicleTypeFk',
+        'deliveryPointFk',
+    ],
+    include: [
+        {
+            relation: 'warehouse',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'company',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'supplier',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'supplierCooler',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'fuelType',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'bankPolicy',
+            scope: {
+                fields: ['id', 'ref', 'dmsFk'],
+            },
+        },
+        {
+            relation: 'ppe',
+            scope: {
+                fields: ['id'],
+            },
+        },
+        {
+            relation: 'deliveryPoint',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Route/Vehicle/VehicleList.vue b/src/pages/Route/Vehicle/VehicleList.vue
new file mode 100644
index 000000000..e5b945010
--- /dev/null
+++ b/src/pages/Route/Vehicle/VehicleList.vue
@@ -0,0 +1,224 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+import VnTable from 'components/VnTable/VnTable.vue';
+import FetchData from 'src/components/FetchData.vue';
+import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import VehicleSummary from 'src/pages/Route/Vehicle/Card/VehicleSummary.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnSection from 'src/components/common/VnSection.vue';
+
+const { t } = useI18n();
+const { viewSummary } = useSummaryDialog();
+const warehouses = ref([]);
+const companies = ref([]);
+const countries = ref([]);
+const vehicleStates = ref([]);
+const vehicleTypes = ref([]);
+
+const columns = computed(() => [
+    {
+        name: 'isActive',
+        columnFilter: false,
+        align: 'center',
+    },
+    {
+        name: 'id',
+        label: t('globals.id'),
+        isId: true,
+        chip: {
+            condition: () => true,
+        },
+    },
+    {
+        name: 'description',
+        label: t('globals.description'),
+    },
+    {
+        name: 'tradeMark',
+        label: t('vehicle.tradeMark'),
+        cardVisible: true,
+    },
+    {
+        name: 'numberPlate',
+        label: t('vehicle.numberPlate'),
+        isTitle: true,
+    },
+    {
+        name: 'vehicleTypeFk',
+        label: t('globals.type'),
+        format: (row) => row.type,
+        columnFilter: {
+            component: 'select',
+            name: 'vehicleTypeFk',
+            options: vehicleTypes.value,
+        },
+        cardVisible: true,
+    },
+    {
+        name: 'vehicleStateFk',
+        label: t('globals.state'),
+        columnFilter: {
+            component: 'select',
+            name: 'vehicleStateFk',
+            optionLabel: 'state',
+            options: vehicleStates.value,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.state),
+    },
+    {
+        name: 'chassis',
+        label: t('vehicle.chassis'),
+    },
+    {
+        name: 'leasing',
+        label: t('vehicle.leasing'),
+    },
+    {
+        name: 'warehouseFk',
+        label: t('globals.warehouse'),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouse),
+        columnFilter: {
+            component: 'select',
+            name: 'warehouseFk',
+            options: warehouses.value,
+        },
+        cardVisible: true,
+    },
+    {
+        name: 'companyFk',
+        label: t('globals.company'),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.company),
+        columnFilter: {
+            component: 'select',
+            name: 'companyFk',
+            optionLabel: 'code',
+            options: companies.value,
+        },
+    },
+    {
+        name: 'countryCodeFk',
+        label: t('globals.country'),
+        columnFilter: {
+            component: 'select',
+            name: 'countryCodeFk',
+            optionValue: 'code',
+            optionLabel: 'code',
+            options: countries.value,
+        },
+    },
+    {
+        align: 'right',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('components.smartCard.openSummary'),
+                icon: 'preview',
+                action: (row) => viewSummary(row.id, VehicleSummary),
+            },
+        ],
+    },
+]);
+</script>
+<template>
+    <FetchData
+        url="Warehouses"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (warehouses = data)"
+        auto-load
+    />
+    <FetchData
+        url="Companies"
+        :filter="{ fields: ['id', 'code'] }"
+        @on-fetch="(data) => (companies = data)"
+        auto-load
+    />
+    <FetchData
+        url="Countries"
+        :filter="{ fields: ['name', 'code'] }"
+        @on-fetch="(data) => (countries = data)"
+        auto-load
+    />
+    <FetchData
+        url="VehicleStates"
+        :filter="{ fields: ['id', 'state'] }"
+        @on-fetch="(data) => (vehicleStates = data)"
+        auto-load
+    />
+    <FetchData
+        url="VehicleTypes"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (vehicleTypes = data)"
+        auto-load
+    />
+    <VnSection
+        data-key="VehicleList"
+        :columns="columns"
+        prefix="vehicle"
+        :array-data-props="{
+            url: 'Vehicles/filter',
+        }"
+    >
+        <template #body>
+            <VnTable
+                ref="tableRef"
+                data-key="VehicleList"
+                :columns="columns"
+                redirect="route/vehicle"
+                :create="{
+                    urlCreate: 'Vehicles',
+                    title: t('vehicle.create'),
+                    onDataSaved: ({ id }) => $refs.tableRef.redirect(id),
+                    formInitialData: { isActive: true, isKmTruckRate: false },
+                }"
+                :use-model="true"
+                :right-search="false"
+            >
+                <template #column-isActive="{ row }">
+                    <span>
+                        <QIcon
+                            v-if="!row.isActive"
+                            name="vn:inactive-car"
+                            color="primary"
+                            size="xs"
+                        >
+                            <QTooltip>{{ $t('globals.inactive') }}</QTooltip>
+                        </QIcon>
+                    </span>
+                </template>
+                <template #more-create-dialog="{ data }">
+                    <VnInput
+                        v-model="data.numberPlate"
+                        :label="$t('vehicle.numberPlate')"
+                        :uppercase="true"
+                    />
+                    <VnInput v-model="data.tradeMark" :label="$t('vehicle.tradeMark')" />
+                    <VnInput v-model="data.model" :label="$t('globals.model')" />
+                    <VnSelect
+                        v-model="data.vehicleTypeFk"
+                        :label="$t('globals.type')"
+                        :options="vehicleTypes"
+                    />
+                    <VnSelect
+                        v-model="data.warehouseFk"
+                        :label="$t('globals.warehouse')"
+                        :options="warehouses"
+                    />
+                    <VnSelect
+                        v-model="data.countryCodeFk"
+                        :label="$t('globals.country')"
+                        option-value="code"
+                        option-label="name"
+                        :options="countries"
+                    />
+                    <VnInput
+                        v-model="data.description"
+                        :label="$t('globals.description')"
+                    />
+                    <QCheckbox to v-model="data.isActive" :label="$t('globals.active')" />
+                </template>
+            </VnTable>
+        </template>
+    </VnSection>
+</template>
diff --git a/src/pages/Route/Vehicle/locale/en.yml b/src/pages/Route/Vehicle/locale/en.yml
new file mode 100644
index 000000000..c92022f9d
--- /dev/null
+++ b/src/pages/Route/Vehicle/locale/en.yml
@@ -0,0 +1,20 @@
+vehicle:
+    tradeMark: Trade Mark
+    numberPlate: Nº Plate
+    chassis: Chassis
+    leasing: Leasing
+    isKmTruckRate: Trailer
+    delete: Delete Vehicle
+    supplierCooler: Supplier Cooler
+    vin: VIN
+    ppe: Ppe
+    isActive: Active
+    nLeasing: Nº Leasing
+    create: Create Vehicle
+    amountCooler: Amount cooler
+    remove: Vehicle removed
+    search: Search Vehicle
+    searchInfo: Search by id or number plate
+    params:
+        vehicleTypeFk: Type
+        vehicleStateFk: State
diff --git a/src/pages/Route/Vehicle/locale/es.yml b/src/pages/Route/Vehicle/locale/es.yml
new file mode 100644
index 000000000..c878f97ac
--- /dev/null
+++ b/src/pages/Route/Vehicle/locale/es.yml
@@ -0,0 +1,20 @@
+vehicle:
+    tradeMark: Marca
+    numberPlate: Matrícula
+    chassis: Nº de bastidor
+    leasing: Leasing
+    isKmTruckRate: Trailer
+    delete: Eliminar vehículo
+    supplierCooler: Proveedor Frío
+    vin: VIN
+    ppe: Nº Inmovilizado
+    create: Crear vehículo
+    amountCooler: Importe frío
+    isActive: Activo
+    nLeasing: Nº leasing
+    remove: Vehículo eliminado
+    search: Buscar Vehículo
+    searchInfo: Buscar por id o matrícula
+    params:
+        vehicleTypeFk: Tipo
+        vehicleStateFk: Estado
diff --git a/src/pages/Shelving/Card/ShelvingCard.vue b/src/pages/Shelving/Card/ShelvingCard.vue
index 41a0db33c..9e0ac8ad2 100644
--- a/src/pages/Shelving/Card/ShelvingCard.vue
+++ b/src/pages/Shelving/Card/ShelvingCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ShelvingDescriptor from 'pages/Shelving/Card/ShelvingDescriptor.vue';
+import filter from './ShelvingFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Shelving"
-        base-url="Shelvings"
+        url="Shelvings"
+        :filter="filter"
         :descriptor="ShelvingDescriptor"
     />
 </template>
diff --git a/src/pages/Shelving/Card/ShelvingDescriptor.vue b/src/pages/Shelving/Card/ShelvingDescriptor.vue
index b1ff4a8ae..5e618aa7f 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptor.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptor.vue
@@ -1,12 +1,12 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
+import filter from './ShelvingFilter.js';
 
 const $props = defineProps({
     id: {
@@ -22,35 +22,13 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
-
 <template>
     <CardDescriptor
-        module="Shelving"
         :url="`Shelvings/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="Shelvings"
-        @on-fetch="setData"
+        title="code"
+        data-key="Shelving"
     >
         <template #body="{ entity }">
             <VnLv :label="t('globals.code')" :value="entity.code" />
diff --git a/src/pages/Shelving/Card/ShelvingFilter.js b/src/pages/Shelving/Card/ShelvingFilter.js
new file mode 100644
index 000000000..e302e1b9c
--- /dev/null
+++ b/src/pages/Shelving/Card/ShelvingFilter.js
@@ -0,0 +1,15 @@
+export default {
+    include: [
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: { fields: ['nickname'] },
+                },
+            },
+        },
+        { relation: 'parking' },
+    ],
+};
diff --git a/src/pages/Shelving/Card/ShelvingForm.vue b/src/pages/Shelving/Card/ShelvingForm.vue
index 3bbd94a0a..078058342 100644
--- a/src/pages/Shelving/Card/ShelvingForm.vue
+++ b/src/pages/Shelving/Card/ShelvingForm.vue
@@ -1,5 +1,4 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import { computed } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import VnRow from 'components/ui/VnRow.vue';
@@ -7,8 +6,8 @@ import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import filter from './ShelvingFilter.js';
 
-const { t } = useI18n();
 const route = useRoute();
 const router = useRouter();
 const entityId = computed(() => route.params.id ?? null);
@@ -20,22 +19,6 @@ const defaultInitialData = {
     isRecyclable: false,
 };
 
-const shelvingFilter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
-
 const onSave = (shelving, newShelving) => {
     if (isNew) {
         router.push({ name: 'ShelvingBasicData', params: { id: newShelving?.id } });
@@ -45,11 +28,10 @@ const onSave = (shelving, newShelving) => {
 <template>
     <VnSubToolbar v-if="isNew" />
     <FormModel
-        :url="isNew ? null : `Shelvings/${entityId}`"
         :url-create="isNew ? 'Shelvings' : null"
         :observe-form-changes="!isNew"
-        :filter="shelvingFilter"
-        model="shelving"
+        :filter="filter"
+        model="Shelving"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -58,7 +40,7 @@ const onSave = (shelving, newShelving) => {
             <VnRow>
                 <VnInput
                     v-model="data.code"
-                    :label="t('globals.code')"
+                    :label="$t('globals.code')"
                     :rules="validate('Shelving.code')"
                 />
                 <VnSelect
@@ -68,7 +50,7 @@ const onSave = (shelving, newShelving) => {
                     option-label="code"
                     :filter-options="['id', 'code']"
                     :fields="['id', 'code']"
-                    :label="t('shelving.list.parking')"
+                    :label="$t('shelving.list.parking')"
                     :rules="validate('Shelving.parkingFk')"
                 />
             </VnRow>
@@ -76,12 +58,12 @@ const onSave = (shelving, newShelving) => {
                 <VnInput
                     v-model="data.priority"
                     type="number"
-                    :label="t('shelving.list.priority')"
+                    :label="$t('shelving.list.priority')"
                     :rules="validate('Shelving.priority')"
                 />
                 <QCheckbox
                     v-model="data.isRecyclable"
-                    :label="t('shelving.summary.recyclable')"
+                    :label="$t('shelving.summary.recyclable')"
                     :rules="validate('Shelving.isRecyclable')"
                 />
             </VnRow>
diff --git a/src/pages/Shelving/Card/ShelvingSearchbar.vue b/src/pages/Shelving/Card/ShelvingSearchbar.vue
index bfc8ad4f5..741b11663 100644
--- a/src/pages/Shelving/Card/ShelvingSearchbar.vue
+++ b/src/pages/Shelving/Card/ShelvingSearchbar.vue
@@ -1,15 +1,15 @@
 <script setup>
 import VnSearchbar from 'components/ui/VnSearchbar.vue';
-import {useI18n} from "vue-i18n";
-const { t } = useI18n();
+import exprBuilder from '../ShelvingExprBuilder.js';
 </script>
 
 <template>
     <VnSearchbar
         data-key="ShelvingList"
         url="Shelvings"
-        :label="t('Search shelving')"
-        :info="t('You can search by shelving reference')"
+        :label="$t('Search shelving')"
+        :info="$t('You can search by shelving reference')"
+        :expr-builder="exprBuilder"
     />
 </template>
 
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index 39fa4639f..f89ff4d78 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -1,10 +1,10 @@
 <script setup>
 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 filter from './ShelvingFilter.js';
 import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
 
 const $props = defineProps({
@@ -14,25 +14,9 @@ const $props = defineProps({
     },
 });
 const route = useRoute();
-const { t } = useI18n();
+
 const summary = ref({});
 const entityId = computed(() => $props.id || route.params.id);
-
-const filter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
 </script>
 
 <template>
@@ -41,7 +25,7 @@ const filter = {
             ref="summary"
             :url="`Shelvings/${entityId}`"
             :filter="filter"
-            data-key="ShelvingSummary"
+            data-key="Shelving"
         >
             <template #header="{ entity }">
                 <div>{{ entity.code }}</div>
@@ -58,16 +42,19 @@ const filter = {
                         class="header header-link"
                         :to="{ name: 'ShelvingBasicData', params: { id: entityId } }"
                     >
-                        {{ t('globals.pageTitles.basicData') }}
+                        {{ $t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </RouterLink>
-                    <VnLv :label="t('globals.code')" :value="entity.code" />
+                    <VnLv :label="$t('globals.code')" :value="entity.code" />
                     <VnLv
-                        :label="t('shelving.list.parking')"
+                        :label="$t('shelving.list.parking')"
                         :value="entity.parking?.code"
                     />
-                    <VnLv :label="t('shelving.list.priority')" :value="entity.priority" />
-                    <VnLv v-if="entity.worker" :label="t('globals.worker')">
+                    <VnLv
+                        :label="$t('shelving.list.priority')"
+                        :value="entity.priority"
+                    />
+                    <VnLv v-if="entity.worker" :label="$t('globals.worker')">
                         <template #value>
                             <VnUserLink
                                 :name="entity.worker?.user?.nickname"
@@ -76,7 +63,7 @@ const filter = {
                         </template>
                     </VnLv>
                     <VnLv
-                        :label="t('shelving.summary.recyclable')"
+                        :label="$t('shelving.summary.recyclable')"
                         :value="entity.isRecyclable"
                     />
                 </QCard>
diff --git a/src/pages/Parking/Card/ParkingBasicData.vue b/src/pages/Shelving/Parking/Card/ParkingBasicData.vue
similarity index 68%
rename from src/pages/Parking/Card/ParkingBasicData.vue
rename to src/pages/Shelving/Parking/Card/ParkingBasicData.vue
index 550a0684e..3de358002 100644
--- a/src/pages/Parking/Card/ParkingBasicData.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingBasicData.vue
@@ -1,16 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
+import { ref } from 'vue';
 import VnRow from 'components/ui/VnRow.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import FormModel from 'components/FormModel.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
-const { t } = useI18n();
-const route = useRoute();
-const parkingId = computed(() => route.params?.id || null);
 const sectors = ref([]);
 const sectorFilter = { fields: ['id', 'description'] };
 
@@ -27,18 +22,21 @@ const filter = {
         @on-fetch="(data) => (sectors = data)"
         auto-load
     />
-    <FormModel :url="`Parkings/${parkingId}`" model="parking" :filter="filter" auto-load>
+    <FormModel model="Parking" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <VnInput v-model="data.code" :label="t('globals.code')" />
-                <VnInput v-model="data.pickingOrder" :label="t('parking.pickingOrder')" />
+                <VnInput v-model="data.code" :label="$t('globals.code')" />
+                <VnInput
+                    v-model="data.pickingOrder"
+                    :label="$t('parking.pickingOrder')"
+                />
             </VnRow>
             <VnRow>
                 <VnSelect
                     v-model="data.sectorFk"
                     option-value="id"
                     option-label="description"
-                    :label="t('parking.sector')"
+                    :label="$t('parking.sector')"
                     :options="sectors"
                     use-input
                     input-debounce="0"
diff --git a/src/pages/Parking/Card/ParkingCard.vue b/src/pages/Shelving/Parking/Card/ParkingCard.vue
similarity index 53%
rename from src/pages/Parking/Card/ParkingCard.vue
rename to src/pages/Shelving/Parking/Card/ParkingCard.vue
index 1cd2df7b7..b32c1b7d3 100644
--- a/src/pages/Parking/Card/ParkingCard.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import ParkingDescriptor from 'pages/Parking/Card/ParkingDescriptor.vue';
+import ParkingDescriptor from 'pages/Shelving/Parking/Card/ParkingDescriptor.vue';
+import filter from './ParkingFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Parking"
-        base-url="Parkings"
+        url="Parkings"
+        :filter="filter"
         :descriptor="ParkingDescriptor"
     />
 </template>
diff --git a/src/pages/Parking/Card/ParkingDescriptor.vue b/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
similarity index 58%
rename from src/pages/Parking/Card/ParkingDescriptor.vue
rename to src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
index d36ea16fc..46c9f8ea0 100644
--- a/src/pages/Parking/Card/ParkingDescriptor.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
@@ -1,10 +1,9 @@
 <script setup>
 import { computed } from 'vue';
-import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-
+import filter from './ParkingFilter.js';
 const props = defineProps({
     id: {
         type: Number,
@@ -13,18 +12,11 @@ const props = defineProps({
     },
 });
 
-const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => props.id || route.params.id);
-
-const filter = {
-    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
-    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
-};
 </script>
 <template>
     <CardDescriptor
-        module="Parking"
         data-key="Parking"
         :url="`Parkings/${entityId}`"
         title="code"
@@ -32,9 +24,9 @@ const filter = {
         :to-module="{ name: 'ParkingList' }"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('globals.code')" :value="entity.code" />
-            <VnLv :label="t('parking.pickingOrder')" :value="entity.pickingOrder" />
-            <VnLv :label="t('parking.sector')" :value="entity.sector?.description" />
+            <VnLv :label="$t('globals.code')" :value="entity.code" />
+            <VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
+            <VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Shelving/Parking/Card/ParkingFilter.js b/src/pages/Shelving/Parking/Card/ParkingFilter.js
new file mode 100644
index 000000000..fd1855c45
--- /dev/null
+++ b/src/pages/Shelving/Parking/Card/ParkingFilter.js
@@ -0,0 +1,4 @@
+export default {
+    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
+    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
+};
diff --git a/src/pages/Parking/Card/ParkingLog.vue b/src/pages/Shelving/Parking/Card/ParkingLog.vue
similarity index 100%
rename from src/pages/Parking/Card/ParkingLog.vue
rename to src/pages/Shelving/Parking/Card/ParkingLog.vue
diff --git a/src/pages/Parking/Card/ParkingSummary.vue b/src/pages/Shelving/Parking/Card/ParkingSummary.vue
similarity index 100%
rename from src/pages/Parking/Card/ParkingSummary.vue
rename to src/pages/Shelving/Parking/Card/ParkingSummary.vue
diff --git a/src/pages/Shelving/Parking/ParkingExprBuilder.js b/src/pages/Shelving/Parking/ParkingExprBuilder.js
new file mode 100644
index 000000000..16d2262c8
--- /dev/null
+++ b/src/pages/Shelving/Parking/ParkingExprBuilder.js
@@ -0,0 +1,10 @@
+export default (param, value) => {
+    switch (param) {
+        case 'code':
+            return { [param]: { like: `%${value}%` } };
+        case 'sectorFk':
+            return { [param]: value };
+        case 'search':
+            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
+    }
+};
diff --git a/src/pages/Parking/ParkingFilter.vue b/src/pages/Shelving/Parking/ParkingFilter.vue
similarity index 100%
rename from src/pages/Parking/ParkingFilter.vue
rename to src/pages/Shelving/Parking/ParkingFilter.vue
diff --git a/src/pages/Parking/ParkingList.vue b/src/pages/Shelving/Parking/ParkingList.vue
similarity index 90%
rename from src/pages/Parking/ParkingList.vue
rename to src/pages/Shelving/Parking/ParkingList.vue
index bce87126e..fe6c93ba5 100644
--- a/src/pages/Parking/ParkingList.vue
+++ b/src/pages/Shelving/Parking/ParkingList.vue
@@ -9,6 +9,7 @@ import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import ParkingFilter from './ParkingFilter.vue';
 import ParkingSummary from './Card/ParkingSummary.vue';
+import exprBuilder from './ParkingExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const stateStore = useStateStore();
@@ -23,19 +24,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 const filter = {
     fields: ['id', 'sectorFk', 'code', 'pickingOrder'],
 };
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'code':
-            return { [param]: { like: `%${value}%` } };
-        case 'sectorFk':
-            return { [param]: value };
-        case 'search':
-            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
-    }
-}
 </script>
-
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Parking/locale/en.yml b/src/pages/Shelving/Parking/locale/en.yml
similarity index 100%
rename from src/pages/Parking/locale/en.yml
rename to src/pages/Shelving/Parking/locale/en.yml
diff --git a/src/pages/Parking/locale/es.yml b/src/pages/Shelving/Parking/locale/es.yml
similarity index 100%
rename from src/pages/Parking/locale/es.yml
rename to src/pages/Shelving/Parking/locale/es.yml
diff --git a/src/pages/Shelving/ShelvingExprBuilder.js b/src/pages/Shelving/ShelvingExprBuilder.js
new file mode 100644
index 000000000..b9aad8a71
--- /dev/null
+++ b/src/pages/Shelving/ShelvingExprBuilder.js
@@ -0,0 +1,10 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return { code: { like: `%${value}%` } };
+        case 'parkingFk':
+        case 'userFk':
+        case 'isRecyclable':
+            return { [param]: value };
+    }
+};
diff --git a/src/pages/Shelving/ShelvingList.vue b/src/pages/Shelving/ShelvingList.vue
index cf158e76b..4e0c21100 100644
--- a/src/pages/Shelving/ShelvingList.vue
+++ b/src/pages/Shelving/ShelvingList.vue
@@ -1,6 +1,5 @@
 <script setup>
 import VnPaginate from 'components/ui/VnPaginate.vue';
-import { useI18n } from 'vue-i18n';
 import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import { useRouter } from 'vue-router';
@@ -8,9 +7,9 @@ import ShelvingFilter from 'pages/Shelving/Card/ShelvingFilter.vue';
 import ShelvingSummary from 'pages/Shelving/Card/ShelvingSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import VnSection from 'src/components/common/VnSection.vue';
+import exprBuilder from './ShelvingExprBuilder.js';
 
 const router = useRouter();
-const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
 const dataKey = 'ShelvingList';
 
@@ -21,17 +20,6 @@ const filter = {
 function navigate(id) {
     router.push({ path: `/shelving/${id}` });
 }
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'search':
-            return { code: { like: `%${value}%` } };
-        case 'parkingFk':
-        case 'userFk':
-        case 'isRecyclable':
-            return { [param]: value };
-    }
-}
 </script>
 
 <template>
@@ -62,18 +50,18 @@ function exprBuilder(param, value) {
                             >
                                 <template #list-items>
                                     <VnLv
-                                        :label="t('shelving.list.parking')"
-                                        :title-label="t('shelving.list.parking')"
+                                        :label="$t('shelving.list.parking')"
+                                        :title-label="$t('shelving.list.parking')"
                                         :value="row.parking?.code"
                                     />
                                     <VnLv
-                                        :label="t('shelving.list.priority')"
+                                        :label="$t('shelving.list.priority')"
                                         :value="row?.priority"
                                     />
                                 </template>
                                 <template #actions>
                                     <QBtn
-                                        :label="t('components.smartCard.openSummary')"
+                                        :label="$t('components.smartCard.openSummary')"
                                         @click.stop="viewSummary(row.id, ShelvingSummary)"
                                         color="primary"
                                     />
@@ -84,9 +72,9 @@ function exprBuilder(param, value) {
                 </div>
                 <QPageSticky :offset="[20, 20]">
                     <RouterLink :to="{ name: 'ShelvingCreate' }">
-                        <QBtn fab icon="add" color="primary" shortcut="+" />
+                        <QBtn fab icon="add" color="primary" v-shortcut="'+'" />
                         <QTooltip>
-                            {{ t('shelving.list.newShelving') }}
+                            {{ $t('shelving.list.newShelving') }}
                         </QTooltip>
                     </RouterLink>
                 </QPageSticky>
diff --git a/src/pages/Supplier/Card/SupplierAccounts.vue b/src/pages/Supplier/Card/SupplierAccounts.vue
index 4a6901d1d..365eb67a1 100644
--- a/src/pages/Supplier/Card/SupplierAccounts.vue
+++ b/src/pages/Supplier/Card/SupplierAccounts.vue
@@ -71,7 +71,7 @@ function bankEntityFilter(val, update) {
         filteredBankEntitiesOptions.value = bankEntitiesOptions.value.filter(
             (bank) =>
                 bank.bic.toLowerCase().startsWith(needle) ||
-                bank.name.toLowerCase().includes(needle)
+                bank.name.toLowerCase().includes(needle),
         );
     });
 }
@@ -170,7 +170,7 @@ function bankEntityFilter(val, update) {
                             <QIcon name="info" class="cursor-pointer">
                                 <QTooltip>{{
                                     t(
-                                        'Name of the bank account holder if different from the provider'
+                                        'Name of the bank account holder if different from the provider',
                                     )
                                 }}</QTooltip>
                             </QIcon>
@@ -194,7 +194,7 @@ function bankEntityFilter(val, update) {
                     <QBtn
                         flat
                         icon="add"
-                        shortcut="+"
+                        v-shortcut
                         class="cursor-pointer"
                         color="primary"
                         @click="supplierAccountRef.insert()"
diff --git a/src/pages/Supplier/Card/SupplierAddresses.vue b/src/pages/Supplier/Card/SupplierAddresses.vue
index e568962ff..c4c0ab7be 100644
--- a/src/pages/Supplier/Card/SupplierAddresses.vue
+++ b/src/pages/Supplier/Card/SupplierAddresses.vue
@@ -89,7 +89,7 @@ const redirectToUpdateView = (addressData) => {
                 icon="add"
                 color="primary"
                 @click="redirectToCreateView()"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip>
                 {{ t('New address') }}
diff --git a/src/pages/Supplier/Card/SupplierAgencyTerm.vue b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
index 99b672cc4..ab21f1f76 100644
--- a/src/pages/Supplier/Card/SupplierAgencyTerm.vue
+++ b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
@@ -114,7 +114,7 @@ const redirectToCreateView = () => {
             icon="add"
             color="primary"
             @click="redirectToCreateView()"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('supplier.agencyTerms.addRow') }}
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index f6c13b7af..631700a4a 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -19,9 +19,8 @@ const companySizes = [
 </script>
 <template>
     <FormModel
-        :url="`Suppliers/${route.params.id}`"
         :url-update="`Suppliers/${route.params.id}`"
-        model="supplier"
+        model="Supplier"
         auto-load
         :clear-store-on-unmount="false"
         @on-data-saved="arrayData.fetch({})"
diff --git a/src/pages/Supplier/Card/SupplierCard.vue b/src/pages/Supplier/Card/SupplierCard.vue
index 594026d18..e30f79f96 100644
--- a/src/pages/Supplier/Card/SupplierCard.vue
+++ b/src/pages/Supplier/Card/SupplierCard.vue
@@ -1,19 +1,13 @@
 <script setup>
-import VnCard from 'components/common/VnCard.vue';
 import SupplierDescriptor from './SupplierDescriptor.vue';
-import SupplierListFilter from '../SupplierListFilter.vue';
+import VnCardBeta from 'src/components/common/VnCardBeta.vue';
+import filter from './SupplierFilter.js';
 </script>
 <template>
-    <VnCard
+    <VnCardBeta
         data-key="Supplier"
-        base-url="Suppliers"
+        url="Suppliers"
         :descriptor="SupplierDescriptor"
-        :filter-panel="SupplierListFilter"
-        search-data-key="SupplierList"
-        :searchbar-props="{
-            url: 'Suppliers/filter',
-            searchUrl: 'table',
-            label: 'Search suppliers',
-        }"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue
index 8a7021fb3..718de95dd 100644
--- a/src/pages/Supplier/Card/SupplierConsumption.vue
+++ b/src/pages/Supplier/Card/SupplierConsumption.vue
@@ -16,6 +16,7 @@ import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import { useState } from 'src/composables/useState';
 import { useArrayData } from 'composables/useArrayData';
+import RightMenu from 'src/components/common/RightMenu.vue';
 
 const state = useState();
 const stateStore = useStateStore();
@@ -173,59 +174,59 @@ onMounted(async () => {
             </div>
         </div>
     </Teleport>
-    <QPage class="column items-center q-pa-md">
-        <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
+    <RightMenu>
+        <template #right-panel>
             <SupplierConsumptionFilter data-key="SupplierConsumption" />
-        </Teleport>
-        <QTable
-            :rows="rows"
-            row-key="id"
-            hide-header
-            class="full-width q-mt-md"
-            :no-data-label="t('No results')"
-        >
-            <template #body="{ row }">
-                <QTr>
-                    <QTd no-hover>
-                        <span class="label">{{ t('supplier.consumption.entry') }}: </span>
-                        <span>{{ row.id }}</span>
-                    </QTd>
-                    <QTd no-hover>
-                        <span class="label">{{ t('globals.date') }}: </span>
-                        <span>{{ toDate(row.shipped) }}</span></QTd
-                    >
-                    <QTd colspan="6" no-hover>
-                        <span class="label">{{ t('globals.reference') }}: </span>
-                        <span>{{ row.invoiceNumber }}</span>
-                    </QTd>
-                </QTr>
-                <QTr v-for="(buy, index) in row.buys" :key="index">
-                    <QTd no-hover>
-                        <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
-                        <ItemDescriptorProxy :id="buy.itemFk" />
-                    </QTd>
+        </template>
+    </RightMenu>
+    <QTable
+        :rows="rows"
+        row-key="id"
+        hide-header
+        class="full-width q-mt-md"
+        :no-data-label="t('No results')"
+    >
+        <template #body="{ row }">
+            <QTr>
+                <QTd no-hover>
+                    <span class="label">{{ t('supplier.consumption.entry') }}: </span>
+                    <span>{{ row.id }}</span>
+                </QTd>
+                <QTd no-hover>
+                    <span class="label">{{ t('globals.date') }}: </span>
+                    <span>{{ toDate(row.shipped) }}</span></QTd
+                >
+                <QTd colspan="6" no-hover>
+                    <span class="label">{{ t('globals.reference') }}: </span>
+                    <span>{{ row.invoiceNumber }}</span>
+                </QTd>
+            </QTr>
+            <QTr v-for="(buy, index) in row.buys" :key="index">
+                <QTd no-hover>
+                    <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
+                    <ItemDescriptorProxy :id="buy.itemFk" />
+                </QTd>
 
-                    <QTd no-hover>
-                        <span>{{ buy.subName }}</span>
-                        <FetchedTags :item="buy" />
-                    </QTd>
-                    <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
-                    <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
-                    <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
-                </QTr>
-                <QTr>
-                    <QTd colspan="5" no-hover>
-                        <span class="label">{{ t('Total entry') }}: </span>
-                        <span>{{ row.total }} €</span>
-                    </QTd>
-                    <QTd no-hover>
-                        <span class="label">{{ t('Total stems') }}: </span>
-                        <span>{{ row.quantity }}</span>
-                    </QTd>
-                </QTr>
-            </template>
-        </QTable>
-    </QPage>
+                <QTd no-hover>
+                    <span>{{ buy.subName }}</span>
+                    <FetchedTags :item="buy" />
+                </QTd>
+                <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
+                <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
+                <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
+            </QTr>
+            <QTr>
+                <QTd colspan="5" no-hover>
+                    <span class="label">{{ t('Total entry') }}: </span>
+                    <span>{{ row.total }} €</span>
+                </QTd>
+                <QTd no-hover>
+                    <span class="label">{{ t('Total stems') }}: </span>
+                    <span>{{ row.quantity }}</span>
+                </QTd>
+            </QTr>
+        </template>
+    </QTable>
 </template>
 
 <style scoped lang="scss">
diff --git a/src/pages/Supplier/Card/SupplierContacts.vue b/src/pages/Supplier/Card/SupplierContacts.vue
index 6781c8d34..f96d92ab1 100644
--- a/src/pages/Supplier/Card/SupplierContacts.vue
+++ b/src/pages/Supplier/Card/SupplierContacts.vue
@@ -78,7 +78,7 @@ const insertRow = () => {
                     <QBtn
                         flat
                         icon="add"
-                        shortcut="+"
+                        v-shortcut="'+'"
                         class="cursor-pointer"
                         color="primary"
                         @click="insertRow()"
diff --git a/src/pages/Supplier/Card/SupplierDescriptor.vue b/src/pages/Supplier/Card/SupplierDescriptor.vue
index 37c9c1cff..462bdf853 100644
--- a/src/pages/Supplier/Card/SupplierDescriptor.vue
+++ b/src/pages/Supplier/Card/SupplierDescriptor.vue
@@ -7,8 +7,8 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
 import { toDateString } from 'src/filters';
-import useCardDescription from 'src/composables/useCardDescription';
 import { getUrl } from 'src/composables/getUrl';
+import filter from './SupplierFilter.js';
 import { useArrayData } from 'src/composables/useArrayData';
 
 const $props = defineProps({
@@ -28,42 +28,6 @@ const { t } = useI18n();
 const url = ref();
 const arrayData = useArrayData();
 
-const filter = {
-    fields: [
-        'id',
-        'name',
-        'nickname',
-        'nif',
-        'payMethodFk',
-        'payDemFk',
-        'payDay',
-        'isActive',
-        'isReal',
-        'isTrucker',
-        'account',
-    ],
-    include: [
-        {
-            relation: 'payMethod',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'payDem',
-            scope: {
-                fields: ['id', 'payDem'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'fi'],
-            },
-        },
-    ],
-};
-
 onMounted(async () => {
     url.value = await getUrl('');
 });
@@ -72,11 +36,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
-
 const supplier = computed(() => arrayData.store.data);
 
 const getEntryQueryParams = (supplier) => {
@@ -103,13 +62,9 @@ const getEntryQueryParams = (supplier) => {
 
 <template>
     <CardDescriptor
-        module="Supplier"
         :url="`Suppliers/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :filter="filter"
-        @on-fetch="setData"
-        data-key="supplierDescriptor"
+        data-key="Supplier"
         :summary="$props.summary"
     >
         <template #body="{ entity }">
diff --git a/src/pages/Supplier/Card/SupplierFilter.js b/src/pages/Supplier/Card/SupplierFilter.js
new file mode 100644
index 000000000..3ce5c3de2
--- /dev/null
+++ b/src/pages/Supplier/Card/SupplierFilter.js
@@ -0,0 +1,35 @@
+export default {
+    fields: [
+        'id',
+        'name',
+        'nickname',
+        'nif',
+        'payMethodFk',
+        'payDemFk',
+        'payDay',
+        'isActive',
+        'isSerious',
+        'isTrucker',
+        'account',
+    ],
+    include: [
+        {
+            relation: 'payMethod',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'payDem',
+            scope: {
+                fields: ['id', 'payDem'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'fi'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index e569eb236..ecee5b76b 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -10,6 +10,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
 import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -182,18 +183,11 @@ function handleLocation(data, location) {
                         v-model="data.isTrucker"
                         :label="t('supplier.fiscalData.isTrucker')"
                     />
-                    <div class="row items-center">
-                        <QCheckbox v-model="data.isVies" :label="t('globals.isVies')" />
-                        <QIcon name="info" size="xs" class="cursor-pointer q-ml-sm">
-                            <QTooltip>
-                                {{
-                                    t(
-                                        'When activating it, do not enter the country code in the ID field.'
-                                    )
-                                }}
-                            </QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="data.isVies"
+                        :label="t('globals.isVies')" 
+                        :info="t('whenActivatingIt')" 
+                    />
                 </div>
             </VnRow>
         </template>
@@ -201,6 +195,8 @@ function handleLocation(data, location) {
 </template>
 
 <i18n>
+en:
+    whenActivatingIt: When activating it, do not enter the country code in the ID field.
 es:
-    When activating it, do not enter the country code in the ID field.: Al activarlo, no informar el código del país en el campo nif
+    whenActivatingIt: Al activarlo, no informar el código del país en el campo nif.
 </i18n>
diff --git a/src/pages/Supplier/SupplierList.vue b/src/pages/Supplier/SupplierList.vue
index 85cc11857..600790745 100644
--- a/src/pages/Supplier/SupplierList.vue
+++ b/src/pages/Supplier/SupplierList.vue
@@ -2,14 +2,15 @@
 import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnTable from 'components/VnTable/VnTable.vue';
-import VnSearchbar from 'components/ui/VnSearchbar.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
-import SupplierListFilter from './SupplierListFilter.vue';
+import VnSection from 'src/components/common/VnSection.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-
+const dataKey = 'SupplierList';
+const provincesOptions = ref([]);
 const columns = computed(() => [
     {
         align: 'left',
@@ -104,38 +105,62 @@ const columns = computed(() => [
     },
 ]);
 </script>
-
 <template>
-    <VnSearchbar data-key="SuppliersList" :limit="20" :label="t('Search suppliers')" />
-    <RightMenu>
-        <template #right-panel>
-            <SupplierListFilter data-key="SuppliersList" />
-        </template>
-    </RightMenu>
-    <VnTable
-        ref="tableRef"
-        data-key="SuppliersList"
-        url="Suppliers/filter"
-        redirect="supplier"
-        :create="{
-            urlCreate: 'Suppliers/newSupplier',
-            title: t('Create Supplier'),
-            onDataSaved: ({ id }) => tableRef.redirect(id),
-            formInitialData: {},
-            mapper: (data) => {
-                data.name = data.socialName;
-
-                return data;
-            },
-        }"
-        :right-search="false"
-        order="id ASC"
+    <FetchData
+        url="Provinces"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
+        @on-fetch="(data) => (provincesOptions = data)"
+        auto-load
+    />
+    <VnSection
+        :data-key="dataKey"
         :columns="columns"
+        prefix="supplier"
+        :array-data-props="{
+            url: 'Suppliers/filter',
+            order: 'id ASC',
+        }"
     >
-        <template #more-create-dialog="{ data }">
-            <VnInput :label="t('globals.name')" v-model="data.socialName" :uppercase="true" />
-            </template>
-    </VnTable>
+        <template #body>
+            <VnTable
+                ref="tableRef"
+                :data-key="dataKey"
+                :create="{
+                    urlCreate: 'Suppliers/newSupplier',
+                    title: t('Create Supplier'),
+                    onDataSaved: ({ id }) => tableRef.redirect(id),
+                    formInitialData: {},
+                    mapper: (data) => {
+                        data.name = data.socialName;
+                        delete data.socialName;
+                        return data;
+                    },
+                }"
+                :columns="columns"
+                redirect="supplier"
+                :right-search="false"
+            >
+                <template #more-create-dialog="{ data }">
+                    <VnInput
+                        :label="t('globals.name')"
+                        v-model="data.socialName"
+                        :uppercase="true"
+                    />
+                </template>
+            </VnTable>
+        </template>
+        <template #moreFilterPanel="{ params, searchFn }">
+            <VnSelect
+                :label="t('globals.params.provinceFk')"
+                v-model="params.provinceFk"
+                @update:model-value="searchFn()"
+                :options="provincesOptions"
+                filled
+                dense
+                class="q-px-sm q-pr-lg"
+            />
+        </template>
+    </VnSection>
 </template>
 
 <i18n>
diff --git a/src/pages/Supplier/SupplierListFilter.vue b/src/pages/Supplier/SupplierListFilter.vue
deleted file mode 100644
index b170a35cc..000000000
--- a/src/pages/Supplier/SupplierListFilter.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import { useI18n } from 'vue-i18n';
-
-import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import FetchData from 'components/FetchData.vue';
-
-const props = defineProps({
-    dataKey: {
-        type: String,
-        required: true,
-    },
-});
-
-const { t } = useI18n();
-
-const provincesOptions = ref([]);
-const countriesOptions = ref([]);
-</script>
-
-<template>
-    <FetchData
-        url="Provinces"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
-        @on-fetch="(data) => (provincesOptions = data)"
-        auto-load
-    />
-    <FetchData
-        url="countries"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
-        @on-fetch="(data) => (countriesOptions = data)"
-        auto-load
-    />
-    <VnFilterPanel
-        :data-key="props.dataKey"
-        :search-button="true"
-        :unremovable-params="['supplierFk']"
-    >
-        <template #tags="{ tag, formatFn }">
-            <div class="q-gutter-x-xs">
-                <strong>{{ t(`params.${tag.label}`) }}: </strong>
-                <span>{{ formatFn(tag.value) }}</span>
-            </div>
-        </template>
-        <template #body="{ params, searchFn }">
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.search"
-                        :label="t('params.search')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.nickname"
-                        :label="t('params.nickname')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput v-model="params.nif" :label="t('params.nif')" is-outlined />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.provinceFk')"
-                        v-model="params.provinceFk"
-                        @update:model-value="searchFn()"
-                        :options="provincesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.countryFk')"
-                        v-model="params.countryFk"
-                        @update:model-value="searchFn()"
-                        :options="countriesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-        </template>
-    </VnFilterPanel>
-</template>
-
-<i18n>
-en:
-    params:
-        search: General search
-        nickname: Alias
-        nif: Tax number
-        provinceFk: Province
-        countryFk: Country
-es:
-    params:
-        search: Búsqueda general
-        nickname: Alias
-        nif: NIF/CIF
-        provinceFk: Provincia
-        countryFk: País
-</i18n>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
index c6a85c287..055c9a0ff 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
@@ -9,8 +9,9 @@ import FetchData from 'components/FetchData.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toCurrency } from 'filters/index';
 import { useRole } from 'src/composables/useRole';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
-const haveNegatives = defineModel('haveNegatives', { type: Boolean, required: true });
+const haveNegatives = defineModel('have-negatives', { type: Boolean, required: true });
 const formData = defineModel({ type: Object, required: true });
 
 const stateStore = useStateStore();
@@ -182,22 +183,19 @@ onMounted(async () => {
         </QCard>
         <QCard
             v-if="haveNegatives"
-            class="q-pa-md q-mb-md q-ma-md color-vn-text"
+            class="q-pa-xs q-mb-md q-ma-md color-vn-text"
             bordered
             flat
             style="border-color: black"
         >
             <QCardSection horizontal class="flex row items-center">
-                <QCheckbox
-                    :label="t('basicData.withoutNegatives')"
+                <VnCheckbox
                     v-model="formData.withoutNegatives"
+                    :label="t('basicData.withoutNegatives')"
+                    :info="t('basicData.withoutNegativesInfo')"
                     :toggle-indeterminate="false"
+                    size="xs"
                 />
-                <QIcon name="info" size="xs" class="q-ml-sm">
-                    <QTooltip max-width="350px">
-                        {{ t('basicData.withoutNegativesInfo') }}
-                    </QTooltip>
-                </QIcon>
             </QCardSection>
         </QCard>
     </QDrawer>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index cf4481537..9d70fea38 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -260,7 +260,7 @@ async function getZone(options) {
         auto-load
     />
     <QForm>
-        <VnRow>
+        <VnRow class="row q-gutter-md q-mb-md no-wrap">
             <VnSelect
                 :label="t('ticketList.client')"
                 v-model="clientId"
@@ -296,7 +296,7 @@ async function getZone(options) {
                 :rules="validate('ticketList.warehouse')"
             />
         </VnRow>
-        <VnRow>
+        <VnRow class="row q-gutter-md q-mb-md no-wrap">
             <VnSelect
                 :label="t('basicData.address')"
                 v-model="addressId"
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index 89249b899..ef2eb75d6 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -1,7 +1,7 @@
 <script setup>
-import { ref, onBeforeMount } from 'vue';
+import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRoute, useRouter } from 'vue-router';
+import { useRouter } from 'vue-router';
 
 import TicketBasicData from './TicketBasicData.vue';
 import TicketBasicDataForm from './TicketBasicDataForm.vue';
@@ -9,104 +9,69 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const { notify } = useNotify();
-const route = useRoute();
 const router = useRouter();
 const { t } = useI18n();
 const stepperRef = ref(null);
 const { openConfirmationModal } = useVnConfirm();
 
 const step = ref(1);
-const formData = ref({});
-const initialDataLoaded = ref(false);
-const haveNegatives = ref(false);
+const haveNegatives = ref(true);
 
-const ticketFilter = {
-    include: [
-        { relation: 'address' },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'salesPersonFk',
-                    'name',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                    'credit',
-                    'email',
-                    'phone',
-                    'mobile',
-                    'hasElectronicInvoice',
-                ],
-                include: {
-                    relation: 'salesPersonUser',
-                    scope: { fields: ['id', 'name'] },
-                },
-            },
-        },
-        { relation: 'invoiceOut' },
-    ],
-};
-
-const getTicketData = async () => {
-    const params = { filter: JSON.stringify(ticketFilter) };
-    const { data } = await axios.get(`tickets/${route.params.id}`, { params });
-    formData.value = data;
-    initialDataLoaded.value = true;
-};
+const ticket = computed(() => useArrayData('Ticket').store?.data);
 
 const isFormInvalid = () => {
     return (
-        !formData.value.clientFk ||
-        !formData.value.addressFk ||
-        !formData.value.agencyModeFk ||
-        !formData.value.companyFk ||
-        !formData.value.shipped ||
-        !formData.value.landed ||
-        !formData.value.zoneFk
+        !ticket.value.clientFk ||
+        !ticket.value.addressFk ||
+        !ticket.value.agencyModeFk ||
+        !ticket.value.companyFk ||
+        !ticket.value.shipped ||
+        !ticket.value.landed ||
+        !ticket.value.zoneFk
     );
 };
 
 const getPriceDifference = async () => {
     const params = {
-        landed: formData.value.landed,
-        addressId: formData.value.addressFk,
-        agencyModeId: formData.value.agencyModeFk,
-        zoneId: formData.value.zoneFk,
-        warehouseId: formData.value.warehouseFk,
-        shipped: formData.value.shipped,
+        landed: ticket.value.landed,
+        addressId: ticket.value.addressFk,
+        agencyModeId: ticket.value.agencyModeFk,
+        zoneId: ticket.value.zoneFk,
+        warehouseId: ticket.value.warehouseFk,
+        shipped: ticket.value.shipped,
     };
     const { data } = await axios.post(
-        `tickets/${formData.value.id}/priceDifference`,
+        `tickets/${ticket.value.id}/priceDifference`,
         params
     );
-    formData.value.sale = data;
+    ticket.value.sale = data;
 };
 
 const submit = async () => {
-    if (!formData.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
+    if (!ticket.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
 
     const params = {
-        clientFk: formData.value.clientFk,
-        nickname: formData.value.nickname,
-        agencyModeFk: formData.value.agencyModeFk,
-        addressFk: formData.value.addressFk,
-        zoneFk: formData.value.zoneFk,
-        warehouseFk: formData.value.warehouseFk,
-        companyFk: formData.value.companyFk,
-        shipped: formData.value.shipped,
-        landed: formData.value.landed,
-        isDeleted: formData.value.isDeleted,
-        option: formData.value.option,
-        isWithoutNegatives: formData.value.withoutNegatives,
-        withWarningAccept: formData.value.withWarningAccept,
+        clientFk: ticket.value.clientFk,
+        nickname: ticket.value.nickname,
+        agencyModeFk: ticket.value.agencyModeFk,
+        addressFk: ticket.value.addressFk,
+        zoneFk: ticket.value.zoneFk,
+        warehouseFk: ticket.value.warehouseFk,
+        companyFk: ticket.value.companyFk,
+        shipped: ticket.value.shipped,
+        landed: ticket.value.landed,
+        isDeleted: ticket.value.isDeleted,
+        option: ticket.value.option,
+        isWithoutNegatives: ticket.value.withoutNegatives,
+        withWarningAccept: ticket.value.withWarningAccept,
         keepPrice: false,
     };
 
     const { data } = await axios.post(
-        `tickets/${formData.value.id}/componentUpdate`,
+        `tickets/${ticket.value.id}/componentUpdate`,
         params
     );
 
@@ -118,7 +83,7 @@ const submit = async () => {
 };
 
 const submitWithNegatives = async () => {
-    formData.value.withWarningAccept = true;
+    ticket.value.withWarningAccept = true;
     submit();
 };
 
@@ -130,7 +95,7 @@ const onNextStep = async () => {
         await getPriceDifference();
         stepperRef.value.next();
     } else if (step.value === 2) {
-        if (haveNegatives.value && !formData.value.withoutNegatives)
+        if (haveNegatives.value && !ticket.value.withoutNegatives)
             openConfirmationModal(
                 t('basicData.negativesConfirmTitle'),
                 t('basicData.negativesConfirmMessage'),
@@ -139,11 +104,10 @@ const onNextStep = async () => {
         else submit();
     }
 };
-
-onBeforeMount(async () => await getTicketData());
 </script>
 <template>
     <QStepper
+        v-if="ticket"
         v-model="step"
         ref="stepperRef"
         color="primary"
@@ -155,10 +119,10 @@ onBeforeMount(async () => await getTicketData());
         }"
     >
         <QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
-            <TicketBasicDataForm v-if="initialDataLoaded" v-model="formData" />
+            <TicketBasicDataForm v-model="ticket" />
         </QStep>
         <QStep :name="2" :title="t('basicData.priceDifference')">
-            <TicketBasicData v-model="formData" v-model:have-negatives="haveNegatives" />
+            <TicketBasicData v-model="ticket" v-model:have-negatives="haveNegatives" />
         </QStep>
         <template #navigation>
             <QStepperNavigation class="flex justify-between">
diff --git a/src/pages/Ticket/Card/TicketCard.vue b/src/pages/Ticket/Card/TicketCard.vue
index 6886a8e57..e22d5799a 100644
--- a/src/pages/Ticket/Card/TicketCard.vue
+++ b/src/pages/Ticket/Card/TicketCard.vue
@@ -1,7 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import TicketDescriptor from './TicketDescriptor.vue';
+import filter from './TicketFilter.js';
 </script>
 <template>
-    <VnCardBeta data-key="Ticket" base-url="Tickets" :descriptor="TicketDescriptor" />
+    <VnCardBeta
+        data-key="Ticket"
+        url="Tickets"
+        :descriptor="TicketDescriptor"
+        :filter="filter"
+    />
 </template>
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 842607e0c..5936ffc28 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -19,7 +19,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
 const route = useRoute();
 const { t } = useI18n();
 const salesRef = ref(null);
-const arrayData = useArrayData('ticketData');
+const arrayData = useArrayData('Ticket');
 const { store } = arrayData;
 
 const ticketData = computed(() => store.data);
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index c9849d631..c5f3233b1 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -6,9 +6,11 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { toDateTimeFormat } from 'src/filters/date';
+import filter from './TicketFilter.js';
+import FetchData from 'src/components/FetchData.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const $props = defineProps({
     id: {
@@ -28,100 +30,24 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = {
-    include: [
-        {
-            relation: 'address',
-            scope: {
-                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'id',
-                    'name',
-                    'salesPersonFk',
-                    'phone',
-                    'mobile',
-                    'email',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                    'hasElectronicInvoice',
-                ],
-                include: [
-                    {
-                        relation: 'user',
-                        scope: {
-                            fields: ['id', 'lang'],
-                        },
-                    },
-                    { relation: 'salesPersonUser' },
-                ],
-            },
-        },
-        {
-            relation: 'ticketState',
-            scope: {
-                include: { relation: 'state' },
-            },
-        },
-        {
-            relation: 'warehouse',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'zone',
-            scope: {
-                fields: [
-                    'agencyModeFk',
-                    'bonus',
-                    'hour',
-                    'id',
-                    'isVolumetric',
-                    'itemMaxSize',
-                    'm3Max',
-                    'name',
-                    'price',
-                    'travelingDays',
-                ],
-            },
-        },
-    ],
-};
-
-const data = ref(useCardDescription());
+const problems = ref({});
 
 function ticketFilter(ticket) {
     return JSON.stringify({ clientFk: ticket.clientFk });
 }
-
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
 </script>
 
 <template>
+    <FetchData
+        :url="`Tickets/${entityId}/getTicketProblems`"
+        auto-load
+        @on-fetch="(data) => ([problems] = data)"
+    />
     <CardDescriptor
-        module="Ticket"
         :url="`Tickets/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
+        data-key="Ticket"
         :summary="$props.summary"
-        data-key="ticketData"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -167,48 +93,9 @@ const setData = (entity) => {
             <VnLv :label="t('globals.warehouse')" :value="entity.warehouse?.name" />
             <VnLv :label="t('globals.alias')" :value="entity.nickname" />
         </template>
-        <template #icons="{ entity }">
-            <QCardActions class="q-gutter-x-md">
-                <QIcon
-                    v-if="entity.client.isActive == false"
-                    name="vn:disabled"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client inactive') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.client.isFreezed == true"
-                    name="vn:frozen"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client Frozen') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity?.problem?.includes('hasRisk')"
-                    name="vn:risk"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client has debt') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.client.isTaxDataChecked == false"
-                    name="vn:no036"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client not checked') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.isDeleted == true"
-                    name="vn:deletedTicket"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('This ticket is deleted') }}</QTooltip>
-                </QIcon>
+        <template #icons>
+            <QCardActions class="q-gutter-x-xs">
+                <TicketProblems :row="problems" />
             </QCardActions>
         </template>
         <template #actions="{ entity }">
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index 166e86978..f8084ff2f 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -40,7 +40,7 @@ const expeditionsFilter = computed(() => ({
     order: ['created DESC'],
 }));
 
-const ticketArrayData = useArrayData('ticketData');
+const ticketArrayData = useArrayData('Ticket');
 const ticketStore = ticketArrayData.store;
 const ticketData = computed(() => ticketStore.data);
 
diff --git a/src/pages/Ticket/Card/TicketFilter.js b/src/pages/Ticket/Card/TicketFilter.js
new file mode 100644
index 000000000..7846f1658
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketFilter.js
@@ -0,0 +1,72 @@
+export default {
+    include: [
+        {
+            relation: 'address',
+            scope: {
+                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'id',
+                    'name',
+                    'salesPersonFk',
+                    'phone',
+                    'mobile',
+                    'email',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                    'hasElectronicInvoice',
+                    'credit',
+                ],
+                include: [
+                    {
+                        relation: 'user',
+                        scope: {
+                            fields: ['id', 'lang'],
+                        },
+                    },
+                    { relation: 'salesPersonUser' },
+                ],
+            },
+        },
+        {
+            relation: 'ticketState',
+            scope: {
+                include: { relation: 'state' },
+            },
+        },
+        {
+            relation: 'warehouse',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'zone',
+            scope: {
+                fields: [
+                    'agencyModeFk',
+                    'bonus',
+                    'hour',
+                    'id',
+                    'isVolumetric',
+                    'itemMaxSize',
+                    'm3Max',
+                    'name',
+                    'price',
+                    'travelingDays',
+                ],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index f558b71cc..feb88bf84 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -32,7 +32,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketNotesCrudRef.value.reload();
-    }
+    },
 );
 function handleDelete(row) {
     ticketNotesCrudRef.value.remove([row]);
@@ -105,7 +105,7 @@ async function handleSave() {
                     <VnRow v-if="observationTypes.length > rows.length">
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketPackage.vue b/src/pages/Ticket/Card/TicketPackage.vue
index 8ebdb4401..5fbf4c800 100644
--- a/src/pages/Ticket/Card/TicketPackage.vue
+++ b/src/pages/Ticket/Card/TicketPackage.vue
@@ -41,7 +41,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketPackagingsCrudRef.value.reload();
-    }
+    },
 );
 </script>
 
@@ -118,7 +118,7 @@ watch(
                     <VnRow>
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index f5fb50ecf..6f02a2ce6 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -14,7 +14,7 @@ import VnImg from 'src/components/ui/VnImg.vue';
 
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import TicketSaleMoreActions from './TicketSaleMoreActions.vue';
-import TicketTransfer from './TicketTransfer.vue';
+import TicketTransferProxy from './TicketTransferProxy.vue';
 
 import { toCurrency, toPercentage } from 'src/filters';
 import { useArrayData } from 'composables/useArrayData';
@@ -23,6 +23,7 @@ import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 const route = useRoute();
@@ -34,7 +35,7 @@ const editPriceProxyRef = ref(null);
 const editManaProxyRef = ref(null);
 const stateBtnDropdownRef = ref(null);
 const quasar = useQuasar();
-const arrayData = useArrayData('ticketData');
+const arrayData = useArrayData('Ticket');
 const { store } = arrayData;
 const selectedRows = ref([]);
 const hasSelectedRows = computed(() => selectedRows.value.length > 0);
@@ -626,8 +627,9 @@ watch(
                     @click="setTransferParams()"
                     data-cy="ticketSaleTransferBtn"
                 >
-                    <QTooltip>{{ t('Transfer lines') }}</QTooltip>
-                    <TicketTransfer
+                    <QTooltip>{{ t('ticketSale.transferLines') }}</QTooltip>
+                    <TicketTransferProxy
+                        class="full-width"
                         :transfer="transfer"
                         :ticket="store.data"
                         @refresh-data="resetChanges()"
@@ -697,53 +699,7 @@ watch(
         :disabled-attr="isTicketEditable"
     >
         <template #column-statusIcons="{ row }">
-            <router-link
-                v-if="row.claim?.claimFk"
-                :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
-            >
-                <QIcon color="primary" name="vn:claims" size="xs">
-                    <QTooltip>
-                        {{ t('ticketSale.claim') }}:
-                        {{ row.claim?.claimFk }}
-                    </QTooltip>
-                </QIcon>
-            </router-link>
-            <QIcon v-if="row.visible < 0" color="primary" name="warning" size="xs">
-                <QTooltip>
-                    {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.reserved"
-                color="primary"
-                name="vn:reserva"
-                size="xs"
-                data-cy="ticketSaleReservedIcon"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.reserved') }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.itemShortage"
-                color="primary"
-                name="vn:unavailable"
-                size="xs"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.noVisible') }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.hasComponentLack"
-                color="primary"
-                name="vn:components"
-                size="xs"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.hasComponentLack') }}
-                </QTooltip>
-            </QIcon>
+            <TicketProblems :row="row" />
         </template>
         <template #body-cell-picture="{ row }">
             <QTd>
@@ -881,7 +837,7 @@ watch(
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             data-cy="ticketSaleAddToBasketBtn"
         />
         <QTooltip class="text-no-wrap">
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index d045eadee..6ce69a6aa 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -40,7 +40,7 @@ watch(
     async () => {
         store.filter = crudModelFilter.value;
         await ticketServiceCrudRef.value.reload();
-    }
+    },
 );
 
 onMounted(async () => await getDefaultTaxClass());
@@ -59,7 +59,7 @@ const createRefund = async () => {
         t('service.createRefundSuccess', {
             ticketId: refundTicket.id,
         }),
-        'positive'
+        'positive',
     );
     router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
 };
@@ -225,7 +225,7 @@ async function handleSave() {
             color="primary"
             icon="add"
             @click="ticketServiceCrudRef.insert()"
-            shortcut="+"
+            v-shortcut="'+'"
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/Ticket/Card/TicketSplit.vue b/src/pages/Ticket/Card/TicketSplit.vue
new file mode 100644
index 000000000..e79057266
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketSplit.vue
@@ -0,0 +1,37 @@
+<script setup>
+import { ref } from 'vue';
+
+import VnInputDate from 'src/components/common/VnInputDate.vue';
+import split from './components/split';
+const emit = defineEmits(['ticketTransfered']);
+
+const $props = defineProps({
+    ticket: {
+        type: [Array, Object],
+        default: () => {},
+    },
+});
+
+const splitDate = ref(Date.vnNew());
+
+const splitSelectedRows = async () => {
+    const tickets = Array.isArray($props.ticket) ? $props.ticket : [$props.ticket];
+    await split(tickets, splitDate.value);
+    emit('ticketTransfered', tickets);
+};
+</script>
+
+<template>
+    <VnInputDate class="q-mr-sm" :label="$t('New date')" v-model="splitDate" clearable />
+    <QBtn class="q-mr-sm" color="primary" label="Split" @click="splitSelectedRows"></QBtn>
+</template>
+<style lang="scss">
+.q-table__bottom.row.items-center.q-table__bottom--nodata {
+    border-top: none;
+}
+</style>
+<i18n>
+es:
+    Sales to transfer: Líneas a transferir
+    Destination ticket: Ticket destinatario
+</i18n>
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 8cb518823..5838efa88 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -20,6 +20,7 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -40,7 +41,7 @@ const editableStates = ref([]);
 const ticketUrl = ref();
 const grafanaUrl = 'https://grafana.verdnatura.es';
 const stateBtnDropdownRef = ref();
-const descriptorData = useArrayData('ticketData');
+const descriptorData = useArrayData('Ticket');
 
 onMounted(async () => {
     ticketUrl.value = (await getUrl('ticket/')) + entityId.value + '/';
@@ -320,83 +321,7 @@ onMounted(async () => {
                     <template #body="props">
                         <QTr :props="props">
                             <QTd class="q-gutter-x-xs">
-                                <QBtn
-                                    flat
-                                    round
-                                    icon="vn:claims"
-                                    v-if="props.row.claim"
-                                    color="primary"
-                                    :to="{
-                                        name: 'ClaimCard',
-                                        params: {
-                                            id: props.row.claim.claimFk,
-                                        },
-                                    }"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.claim') }}:
-                                        {{ props.row.claim.claimFk }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QBtn
-                                    flat
-                                    round
-                                    icon="vn:claims"
-                                    v-if="props.row.claimBeginning"
-                                    color="primary"
-                                    :to="{
-                                        name: 'ClaimCard',
-                                        params: {
-                                            id: props.row.claimBeginning.claimFk,
-                                        },
-                                    }"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.claim') }}:
-                                        {{ props.row.claimBeginning.claimFk }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QIcon
-                                    name="warning"
-                                    v-show="props.row.visible < 0"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('globals.visible') }}:
-                                        {{ props.row.visible }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:reserved"
-                                    v-show="props.row.reserved"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.reserved') }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:unavailable"
-                                    v-show="props.row.itemShortage"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.itemShortage') }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:components"
-                                    v-show="props.row.hasComponentLack"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.hasComponentLack') }}
-                                    </QTooltip>
-                                </QIcon>
+                                <TicketProblems :row="props.row" />
                             </QTd>
                             <QTd>
                                 <QBtn class="link" flat>
diff --git a/src/pages/Ticket/Card/TicketTracking.vue b/src/pages/Ticket/Card/TicketTracking.vue
index f4b8544d3..acf464fb1 100644
--- a/src/pages/Ticket/Card/TicketTracking.vue
+++ b/src/pages/Ticket/Card/TicketTracking.vue
@@ -19,7 +19,7 @@ watch(
     async (val) => {
         paginateFilter.where.ticketFk = val;
         paginateRef.value.fetch();
-    }
+    },
 );
 
 const paginateFilter = reactive({
@@ -119,7 +119,7 @@ const openCreateModal = () => createTrackingDialogRef.value.show();
                 color="primary"
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('tracking.addState') }}
diff --git a/src/pages/Ticket/Card/TicketTransfer.vue b/src/pages/Ticket/Card/TicketTransfer.vue
index 005d74a0e..ffa964c92 100644
--- a/src/pages/Ticket/Card/TicketTransfer.vue
+++ b/src/pages/Ticket/Card/TicketTransfer.vue
@@ -1,11 +1,11 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
-
 import VnInput from 'src/components/common/VnInput.vue';
 import TicketTransferForm from './TicketTransferForm.vue';
 
 import { toDateFormat } from 'src/filters/date.js';
+const emit = defineEmits(['ticketTransfered']);
 
 const $props = defineProps({
     mana: {
@@ -21,16 +21,15 @@ const $props = defineProps({
         default: () => {},
     },
     ticket: {
-        type: Object,
+        type: [Array, Object],
         default: () => {},
     },
 });
 
+onMounted(() => (_transfer.value = $props.transfer));
 const { t } = useI18n();
-const QPopupProxyRef = ref(null);
 const transferFormRef = ref(null);
 const _transfer = ref();
-
 const transferLinesColumns = computed(() => [
     {
         label: t('ticketList.id'),
@@ -86,76 +85,74 @@ const handleRowClick = (row) => {
         transferFormRef.value.transferSales(ticketId);
     }
 };
-
-onMounted(() => (_transfer.value = $props.transfer));
 </script>
 
 <template>
-    <QPopupProxy ref="QPopupProxyRef" data-cy="ticketTransferPopup">
-        <QCard class="q-px-md" style="display: flex; width: 80vw">
-            <QTable
-                :rows="transfer.sales"
-                :columns="transferLinesColumns"
-                :title="t('Sales to transfer')"
-                row-key="id"
-                :pagination="{ rowsPerPage: 0 }"
-                class="full-width q-mt-md"
-                :no-data-label="t('globals.noResults')"
-            >
-                <template #body-cell-quantity="{ row }">
-                    <QTd @click.stop>
-                        <VnInput
-                            v-model.number="row.quantity"
-                            :clearable="false"
-                            style="max-width: 60px"
-                        />
-                    </QTd>
-                </template>
-            </QTable>
-            <QSeparator vertical spaced />
-            <QTable
-                v-if="transfer.lastActiveTickets"
-                :rows="transfer.lastActiveTickets"
-                :columns="destinationTicketColumns"
-                :title="t('Destination ticket')"
-                row-key="id"
-                class="full-width q-mt-md"
-                @row-click="(_, row) => handleRowClick(row)"
-            >
-                <template #body-cell-address="{ row }">
-                    <QTd @click.stop>
-                        <span>
-                            {{ row.nickname }}
-                            {{ row.name }}
-                            {{ row.street }}
-                            {{ row.postalCode }}
-                            {{ row.city }}
-                        </span>
-                        <QTooltip>
-                            {{ row.nickname }}
-                            {{ row.name }}
-                            {{ row.street }}
-                            {{ row.postalCode }}
-                            {{ row.city }}
-                        </QTooltip>
-                    </QTd>
-                </template>
+    <QTable
+        :rows="transfer.sales"
+        :columns="transferLinesColumns"
+        :title="t('Sales to transfer')"
+        row-key="id"
+        :pagination="{ rowsPerPage: 0 }"
+        class="full-width q-mt-md"
+        :no-data-label="t('globals.noResults')"
+    >
+        <template #body-cell-quantity="{ row }">
+            <QTd @click.stop>
+                <VnInput
+                    v-model.number="row.quantity"
+                    :clearable="false"
+                    style="max-width: 60px"
+                />
+            </QTd>
+        </template>
+    </QTable>
+    <QSeparator vertical spaced />
+    <QTable
+        v-if="transfer.lastActiveTickets"
+        :rows="transfer.lastActiveTickets"
+        :columns="destinationTicketColumns"
+        :title="t('Destination ticket')"
+        row-key="id"
+        class="full-width q-mt-md"
+        @row-click="(_, row) => handleRowClick(row)"
+        :no-data-label="t('globals.noResults')"
+        :pagination="{ rowsPerPage: 0 }"
+    >
+        <template #body-cell-address="{ row }">
+            <QTd @click.stop>
+                <span>
+                    {{ row.nickname }}
+                    {{ row.name }}
+                    {{ row.street }}
+                    {{ row.postalCode }}
+                    {{ row.city }}
+                </span>
+                <QTooltip>
+                    {{ row.nickname }}
+                    {{ row.name }}
+                    {{ row.street }}
+                    {{ row.postalCode }}
+                    {{ row.city }}
+                </QTooltip>
+            </QTd>
+        </template>
 
-                <template #no-data>
-                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-                </template>
-                <template #bottom>
-                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-                </template>
-            </QTable>
-        </QCard>
-    </QPopupProxy>
+        <template #no-data>
+            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+        </template>
+        <template #bottom>
+            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+        </template>
+    </QTable>
 </template>
-
+<style lang="scss">
+.q-table__bottom.row.items-center.q-table__bottom--nodata {
+    border-top: none;
+}
+</style>
 <i18n>
 es:
     Sales to transfer: Líneas a transferir
     Destination ticket: Ticket destinatario
-    Transfer to ticket: Transferir a ticket
-    New ticket: Nuevo ticket
 </i18n>
diff --git a/src/pages/Ticket/Card/TicketTransferProxy.vue b/src/pages/Ticket/Card/TicketTransferProxy.vue
new file mode 100644
index 000000000..3f3f018df
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketTransferProxy.vue
@@ -0,0 +1,54 @@
+<script setup>
+import { ref } from 'vue';
+import TicketTransfer from './TicketTransfer.vue';
+import Split from './TicketSplit.vue';
+const emit = defineEmits(['ticketTransfered']);
+
+const $props = defineProps({
+    mana: {
+        type: Number,
+        default: null,
+    },
+    newPrice: {
+        type: Number,
+        default: 0,
+    },
+    transfer: {
+        type: Object,
+        default: () => {},
+    },
+    ticket: {
+        type: [Array, Object],
+        default: () => {},
+    },
+    split: {
+        type: Boolean,
+        default: false,
+    },
+});
+
+const popupProxyRef = ref(null);
+const splitRef = ref(null);
+const transferRef = ref(null);
+</script>
+
+<template>
+    <QPopupProxy ref="popupProxyRef" data-cy="ticketTransferPopup">
+        <div class="flex row items-center q-ma-lg" v-if="$props.split">
+            <Split
+                ref="splitRef"
+                @splitSelectedRows="splitSelectedRows"
+                :ticket="$props.ticket"
+            />
+        </div>
+
+        <div v-else>
+            <TicketTransfer
+                ref="transferRef"
+                :ticket="$props.ticket"
+                :sales="$props.sales"
+                :transfer="$props.transfer"
+            />
+        </div>
+    </QPopupProxy>
+</template>
diff --git a/src/pages/Ticket/Card/components/split.js b/src/pages/Ticket/Card/components/split.js
new file mode 100644
index 000000000..afa1d5cd6
--- /dev/null
+++ b/src/pages/Ticket/Card/components/split.js
@@ -0,0 +1,22 @@
+import axios from 'axios';
+import notifyResults from 'src/utils/notifyResults';
+
+export default async function (data, date) {
+    const reducedData = data.reduce((acc, item) => {
+        const existing = acc.find(({ ticketFk }) => ticketFk === item.id);
+        if (existing) {
+            existing.sales.push(item.saleFk);
+        } else {
+            acc.push({ ticketFk: item.id, sales: [item.saleFk], date });
+        }
+        return acc;
+    }, []);
+
+    const promises = reducedData.map((params) => axios.post(`Tickets/split`, params));
+
+    const results = await Promise.allSettled(promises);
+
+    notifyResults(results, 'ticketFk');
+
+    return results;
+}
diff --git a/src/pages/Ticket/Negative/TicketLackDetail.vue b/src/pages/Ticket/Negative/TicketLackDetail.vue
new file mode 100644
index 000000000..dcf835d03
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackDetail.vue
@@ -0,0 +1,198 @@
+<script setup>
+import { computed, onMounted, onUnmounted, ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+import ChangeQuantityDialog from './components/ChangeQuantityDialog.vue';
+import ChangeStateDialog from './components/ChangeStateDialog.vue';
+import ChangeItemDialog from './components/ChangeItemDialog.vue';
+import TicketTransferProxy from '../Card/TicketTransferProxy.vue';
+import FetchData from 'src/components/FetchData.vue';
+import { useStateStore } from 'stores/useStateStore';
+import { useState } from 'src/composables/useState';
+
+import { useRoute } from 'vue-router';
+import TicketLackTable from './TicketLackTable.vue';
+import VnPopupProxy from 'src/components/common/VnPopupProxy.vue';
+import ItemProposalProxy from 'src/pages/Item/components/ItemProposalProxy.vue';
+
+import { useQuasar } from 'quasar';
+const quasar = useQuasar();
+const { t } = useI18n();
+const editableStates = ref([]);
+const stateStore = useStateStore();
+const tableRef = ref();
+const changeItemDialogRef = ref(null);
+const changeStateDialogRef = ref(null);
+const changeQuantityDialogRef = ref(null);
+const showProposalDialog = ref(false);
+const showChangeQuantityDialog = ref(false);
+const selectedRows = ref([]);
+const route = useRoute();
+onMounted(() => {
+    stateStore.rightDrawer = false;
+});
+onUnmounted(() => {
+    stateStore.rightDrawer = true;
+});
+
+const entityId = computed(() => route.params.id);
+const item = ref({});
+
+const itemProposalSelected = ref(null);
+const reload = async () => {
+    tableRef.value.tableRef.reload();
+};
+defineExpose({ reload });
+const filter = computed(() => ({
+    scopeDays: route.query.days,
+    showType: true,
+    alertLevelCode: 'FREE',
+    date: Date.vnNew(),
+    warehouseFk: useState().getUser().value.warehouseFk,
+}));
+const itemProposalEvt = (data) => {
+    const { itemProposal } = data;
+    itemProposalSelected.value = itemProposal;
+    reload();
+};
+
+function onBuysFetched(data) {
+    Object.assign(item.value, data[0]);
+}
+const showItemProposal = () => {
+    quasar
+        .dialog({
+            component: ItemProposalProxy,
+            componentProps: {
+                itemLack: tableRef.value.itemLack,
+                replaceAction: true,
+                sales: selectedRows.value,
+            },
+        })
+        .onOk(itemProposalEvt);
+};
+</script>
+
+<template>
+    <FetchData
+        url="States/editableStates"
+        @on-fetch="(data) => (editableStates = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Items/${entityId}/getCard`"
+        :fields="['longName']"
+        @on-fetch="(data) => (item = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Buys/latestBuysFilter`"
+        :fields="['longName']"
+        :filter="{ where: { 'i.id': entityId } }"
+        @on-fetch="onBuysFetched"
+        auto-load
+    />
+
+    <TicketLackTable
+        ref="tableRef"
+        :filter="filter"
+        @update:selection="({ value }, _) => (selectedRows = value)"
+    >
+        <template #top-right>
+            <QBtnGroup push class="q-mr-lg" style="column-gap: 1px">
+                <QBtn
+                    data-cy="transferLines"
+                    color="primary"
+                    :disable="!(selectedRows.length === 1)"
+                >
+                    <template #default>
+                        <QIcon name="vn:splitline" />
+                        <QIcon name="vn:ticket" />
+
+                        <QTooltip>{{ t('ticketSale.transferLines') }} </QTooltip>
+                        <TicketTransferProxy
+                            ref="transferFormRef"
+                            split="true"
+                            :ticket="selectedRows"
+                            :transfer="{
+                                sales: selectedRows,
+                                lastActiveTickets: selectedRows.map((row) => row.id),
+                            }"
+                            @ticket-transfered="reload"
+                        ></TicketTransferProxy>
+                    </template>
+                </QBtn>
+                <QBtn
+                    color="primary"
+                    @click="showProposalDialog = true"
+                    :disable="selectedRows.length < 1"
+                    data-cy="itemProposal"
+                >
+                    <QIcon
+                        name="import_export"
+                        class="rotate-90"
+                        @click="showItemProposal"
+                    ></QIcon>
+                    <QTooltip bottom anchor="bottom right">
+                        {{ t('itemProposal') }}
+                    </QTooltip>
+                </QBtn>
+                <VnPopupProxy
+                    data-cy="changeItem"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeItem.title')"
+                >
+                    <template #extraIcon> <QIcon name="vn:item" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeItemDialog
+                            ref="changeItemDialogRef"
+                            @update-item="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy>
+                <VnPopupProxy
+                    data-cy="changeState"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeState.title')"
+                >
+                    <template #extraIcon> <QIcon name="vn:eye" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeStateDialog
+                            ref="changeStateDialogRef"
+                            @update-state="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy>
+                <VnPopupProxy
+                    data-cy="changeQuantity"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeQuantity.title')"
+                    @click="showChangeQuantityDialog = true"
+                >
+                    <template #extraIcon> <QIcon name="exposure" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeQuantityDialog
+                            ref="changeQuantityDialogRef"
+                            @update-quantity="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy> </QBtnGroup
+        ></template>
+    </TicketLackTable>
+</template>
+<style lang="scss" scoped>
+.list-enter-active,
+.list-leave-active {
+    transition: all 1s ease;
+}
+.list-enter-from,
+.list-leave-to {
+    opacity: 0;
+    background-color: $primary;
+}
+.q-table.q-table__container > div:first-child {
+    border-radius: unset;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/TicketLackFilter.vue b/src/pages/Ticket/Negative/TicketLackFilter.vue
new file mode 100644
index 000000000..3762f453d
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackFilter.vue
@@ -0,0 +1,175 @@
+<script setup>
+import { ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+import FetchData from 'components/FetchData.vue';
+import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+const { t } = useI18n();
+const props = defineProps({
+    dataKey: {
+        type: String,
+        required: true,
+    },
+});
+
+const to = Date.vnNew();
+to.setDate(to.getDate() + 1);
+
+const warehouses = ref();
+const categoriesOptions = ref([]);
+const itemTypesRef = ref(null);
+const itemTypesOptions = ref([]);
+
+const itemTypesFilter = {
+    fields: ['id', 'name', 'categoryFk'],
+    include: 'category',
+    order: 'name ASC',
+    where: {},
+};
+const onCategoryChange = async (categoryFk, search) => {
+    if (!categoryFk) {
+        itemTypesFilter.where.categoryFk = null;
+        delete itemTypesFilter.where.categoryFk;
+    } else {
+        itemTypesFilter.where.categoryFk = categoryFk;
+    }
+    search();
+    await itemTypesRef.value.fetch();
+};
+const emit = defineEmits(['set-user-params']);
+
+const setUserParams = (params) => {
+    emit('set-user-params', params);
+};
+</script>
+
+<template>
+    <FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
+    <FetchData
+        url="ItemCategories"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
+        @on-fetch="(data) => (categoriesOptions = data)"
+        auto-load
+    />
+
+    <FetchData
+        ref="itemTypesRef"
+        url="ItemTypes"
+        :filter="itemTypesFilter"
+        @on-fetch="(data) => (itemTypesOptions = data)"
+        auto-load
+    />
+
+    <VnFilterPanel
+        :data-key="props.dataKey"
+        :search-button="true"
+        @set-user-params="setUserParams"
+    >
+        <template #tags="{ tag, formatFn }">
+            <div class="q-gutter-x-xs">
+                <strong>{{ t(`negative.${tag.label}`) }}</strong>
+                <span>{{ formatFn(tag.value) }}</span>
+            </div>
+        </template>
+        <template #body="{ params, searchFn }">
+            <QList dense class="q-gutter-y-sm q-mt-sm">
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.days"
+                            :label="t('negative.days')"
+                            dense
+                            is-outlined
+                            type="number"
+                            @update:model-value="
+                                (value) => {
+                                    setUserParams(params);
+                                }
+                            "
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.id"
+                            :label="t('negative.id')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.producer"
+                            :label="t('negative.producer')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.origen"
+                            :label="t('negative.origen')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection> </QItem
+                ><QItem>
+                    <QItemSection v-if="categoriesOptions">
+                        <VnSelect
+                            :label="t('negative.categoryFk')"
+                            v-model="params.categoryFk"
+                            @update:model-value="
+                                ($event) => onCategoryChange($event, searchFn)
+                            "
+                            :options="categoriesOptions"
+                            option-value="id"
+                            option-label="name"
+                            hide-selected
+                            dense
+                            outlined
+                            rounded
+                        /> </QItemSection
+                    ><QItemSection v-else>
+                        <QSkeleton class="full-width" type="QSelect" />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection v-if="itemTypesOptions">
+                        <VnSelect
+                            :label="t('negative.type')"
+                            v-model="params.typeFk"
+                            @update:model-value="searchFn()"
+                            :options="itemTypesOptions"
+                            option-value="id"
+                            option-label="name"
+                            hide-selected
+                            dense
+                            outlined
+                            rounded
+                        >
+                            <template #option="scope">
+                                <QItem v-bind="scope.itemProps">
+                                    <QItemSection>
+                                        <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                        <QItemLabel caption>{{
+                                            scope.opt?.category?.name
+                                        }}</QItemLabel>
+                                    </QItemSection>
+                                </QItem>
+                            </template>
+                        </VnSelect> </QItemSection
+                    ><QItemSection v-else>
+                        <QSkeleton class="full-width" type="QSelect" />
+                    </QItemSection>
+                </QItem>
+            </QList>
+        </template>
+    </VnFilterPanel>
+</template>
diff --git a/src/pages/Ticket/Negative/TicketLackList.vue b/src/pages/Ticket/Negative/TicketLackList.vue
new file mode 100644
index 000000000..d1e8b823a
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackList.vue
@@ -0,0 +1,227 @@
+<script setup>
+import { computed, ref, reactive } from 'vue';
+import { useI18n } from 'vue-i18n';
+import { useStateStore } from 'stores/useStateStore';
+import VnTable from 'components/VnTable/VnTable.vue';
+import { onBeforeMount } from 'vue';
+import { dashIfEmpty, toDate, toHour } from 'src/filters';
+import { useRouter } from 'vue-router';
+import { useState } from 'src/composables/useState';
+import { useRole } from 'src/composables/useRole';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import RightMenu from 'src/components/common/RightMenu.vue';
+import TicketLackFilter from './TicketLackFilter.vue';
+onBeforeMount(() => {
+    stateStore.$state.rightDrawer = true;
+});
+const router = useRouter();
+const stateStore = useStateStore();
+const { t } = useI18n();
+const selectedRows = ref([]);
+const tableRef = ref();
+const filterParams = ref({});
+const negativeParams = reactive({
+    days: useRole().likeAny('buyer') ? 2 : 0,
+    warehouseFk: useState().getUser().value.warehouseFk,
+});
+const redirectToCreateView = ({ itemFk }) => {
+    router.push({
+        name: 'NegativeDetail',
+        params: { id: itemFk },
+        query: { days: filterParams.value.days ?? negativeParams.days },
+    });
+};
+const columns = computed(() => [
+    {
+        name: 'date',
+        align: 'center',
+        label: t('negative.date'),
+        format: ({ timed }) => toDate(timed),
+        sortable: true,
+        cardVisible: true,
+        isId: true,
+        columnFilter: {
+            component: 'date',
+        },
+    },
+    {
+        columnClass: 'shrink',
+        name: 'timed',
+        align: 'center',
+        label: t('negative.timed'),
+        format: ({ timed }) => toHour(timed),
+        sortable: true,
+        cardVisible: true,
+        columnFilter: {
+            component: 'time',
+        },
+    },
+    {
+        name: 'itemFk',
+        align: 'center',
+        label: t('negative.id'),
+        format: ({ itemFk }) => itemFk,
+        sortable: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'longName',
+        align: 'center',
+        label: t('negative.longName'),
+        field: ({ longName }) => longName,
+
+        sortable: true,
+        headerStyle: 'width: 350px',
+        cardVisible: true,
+        columnClass: 'expand',
+    },
+    {
+        name: 'producer',
+        align: 'center',
+        label: t('negative.supplier'),
+        field: ({ producer }) => dashIfEmpty(producer),
+        sortable: true,
+        columnClass: 'shrink',
+    },
+    {
+        name: 'inkFk',
+        align: 'center',
+        label: t('negative.colour'),
+        field: ({ inkFk }) => inkFk,
+        sortable: true,
+        cardVisible: true,
+    },
+    {
+        name: 'size',
+        align: 'center',
+        label: t('negative.size'),
+        field: ({ size }) => size,
+        sortable: true,
+        cardVisible: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'category',
+        align: 'center',
+        label: t('negative.origen'),
+        field: ({ category }) => dashIfEmpty(category),
+        sortable: true,
+        cardVisible: true,
+    },
+    {
+        name: 'lack',
+        align: 'center',
+        label: t('negative.lack'),
+        field: ({ lack }) => lack,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+        sortable: true,
+        headerStyle: 'padding-center: 33px',
+        cardVisible: true,
+    },
+    {
+        name: 'tableActions',
+        align: 'center',
+        actions: [
+            {
+                title: t('Open details'),
+                icon: 'edit',
+                action: redirectToCreateView,
+                isPrimary: true,
+            },
+        ],
+    },
+]);
+
+const setUserParams = (params) => {
+    filterParams.value = params;
+};
+</script>
+
+<template>
+    <RightMenu>
+        <template #right-panel>
+            <TicketLackFilter data-key="NegativeList" @set-user-params="setUserParams" />
+        </template>
+    </RightMenu>
+    {{ filterRef }}
+    <VnTable
+        ref="tableRef"
+        data-key="NegativeList"
+        :url="`Tickets/itemLack`"
+        :order="['itemFk DESC, date DESC, timed DESC']"
+        :user-params="negativeParams"
+        auto-load
+        :columns="columns"
+        default-mode="table"
+        :right-search="false"
+        :is-editable="false"
+        :use-model="true"
+        :map-key="false"
+        :row-click="redirectToCreateView"
+        v-model:selected="selectedRows"
+        :create="false"
+        :crud-model="{
+            disableInfiniteScroll: true,
+        }"
+        :table="{
+            'row-key': 'itemFk',
+            selection: 'multiple',
+        }"
+    >
+        <template #column-itemFk="{ row }">
+            <div
+                style="display: flex; justify-content: space-around; align-items: center"
+            >
+                <span @click.stop>{{ row.itemFk }}</span>
+            </div>
+        </template>
+        <template #column-longName="{ row }">
+            <span class="link" @click.stop>
+                {{ row.longName }}
+                <ItemDescriptorProxy :id="row.itemFk" />
+            </span>
+        </template>
+    </VnTable>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+.q-btn-group > .q-btn-item:not(:first-child) {
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/TicketLackTable.vue b/src/pages/Ticket/Negative/TicketLackTable.vue
new file mode 100644
index 000000000..176e8f7ad
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackTable.vue
@@ -0,0 +1,356 @@
+<script setup>
+import FetchedTags from 'components/ui/FetchedTags.vue';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import { computed, ref, watch } from 'vue';
+import { useI18n } from 'vue-i18n';
+import axios from 'axios';
+import FetchData from 'src/components/FetchData.vue';
+import { toDate, toHour } from 'src/filters';
+import useNotify from 'src/composables/useNotify.js';
+import ZoneDescriptorProxy from 'pages/Zone/Card/ZoneDescriptorProxy.vue';
+import { useRoute } from 'vue-router';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+import TicketDescriptorProxy from '../Card/TicketDescriptorProxy.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
+
+const $props = defineProps({
+    filter: {
+        type: Object,
+        default: () => ({}),
+    },
+});
+
+watch(
+    () => $props.filter,
+    (v) => {
+        filterLack.value.where = v;
+        tableRef.value.reload(filterLack);
+    },
+);
+
+const filterLack = ref({
+    include: [
+        {
+            relation: 'workers',
+            scope: {
+                fields: ['id', 'firstName'],
+            },
+        },
+    ],
+    where: { ...$props.filter },
+    order: 'ts.alertLevelCode ASC',
+});
+
+const selectedRows = ref([]);
+const { t } = useI18n();
+const { notify } = useNotify();
+const entityId = computed(() => route.params.id);
+const item = ref({});
+const route = useRoute();
+const columns = computed(() => [
+    {
+        name: 'status',
+        align: 'center',
+        sortable: false,
+        columnClass: 'shrink',
+        columnFilter: false,
+    },
+    {
+        name: 'ticketFk',
+        label: t('negative.detail.ticketFk'),
+        align: 'center',
+        sortable: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+        },
+    },
+    {
+        name: 'shipped',
+        label: t('negative.detail.shipped'),
+        field: 'shipped',
+        align: 'center',
+        format: ({ shipped }) => toDate(shipped),
+        sortable: true,
+        columnFilter: {
+            component: 'date',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'minTimed',
+        label: t('negative.detail.theoreticalhour'),
+        field: 'minTimed',
+        align: 'center',
+        sortable: true,
+        component: 'time',
+        columnFilter: {},
+    },
+    {
+        name: 'alertLevelCode',
+        label: t('negative.detail.state'),
+        columnFilter: {
+            name: 'alertLevelCode',
+            component: 'select',
+            attrs: {
+                url: 'AlertLevels',
+                fields: ['name', 'code'],
+                optionLabel: 'code',
+                optionValue: 'code',
+            },
+        },
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'zoneName',
+        label: t('negative.detail.zoneName'),
+        field: 'zoneName',
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'nickname',
+        label: t('negative.detail.nickname'),
+        field: 'nickname',
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'quantity',
+        label: t('negative.detail.quantity'),
+        field: 'quantity',
+        sortable: true,
+        component: 'input',
+        type: 'number',
+    },
+]);
+
+const emit = defineEmits(['update:selection']);
+const itemLack = ref(null);
+const fetchItemLack = ref(null);
+const tableRef = ref(null);
+defineExpose({ tableRef, itemLack });
+watch(selectedRows, () => emit('update:selection', selectedRows));
+const getInputEvents = ({ col, ...rows }) => ({
+    'update:modelValue': () => saveChange(col.name, rows),
+    'keyup.enter': () => saveChange(col.name, rows),
+});
+const saveChange = async (field, { row }) => {
+    try {
+        switch (field) {
+            case 'alertLevelCode':
+                await axios.post(`Tickets/state`, {
+                    ticketFk: row.ticketFk,
+                    code: row[field],
+                });
+                break;
+
+            case 'quantity':
+                await axios.post(`Sales/${row.saleFk}/updateQuantity`, {
+                    quantity: +row.quantity,
+                });
+                break;
+        }
+        notify('globals.dataSaved', 'positive');
+        fetchItemLack.value.fetch();
+    } catch (err) {
+        console.error('Error saving changes', err);
+        f;
+    }
+};
+
+function onBuysFetched(data) {
+    Object.assign(item.value, data[0]);
+}
+</script>
+
+<template>
+    <FetchData
+        ref="fetchItemLack"
+        :url="`Tickets/itemLack`"
+        :params="{ id: entityId }"
+        @on-fetch="(data) => (itemLack = data[0])"
+        auto-load
+    />
+    <FetchData
+        :url="`Items/${entityId}/getCard`"
+        :fields="['longName']"
+        @on-fetch="(data) => (item = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Buys/latestBuysFilter`"
+        :fields="['longName']"
+        :filter="{ where: { 'i.id': entityId } }"
+        @on-fetch="onBuysFetched"
+        auto-load
+    />
+    <VnTable
+        ref="tableRef"
+        data-key="NegativeItem"
+        :map-key="false"
+        :url="`Tickets/itemLack/${entityId}`"
+        :columns="columns"
+        auto-load
+        :create="false"
+        :create-as-dialog="false"
+        :use-model="true"
+        :filter="filterLack"
+        :order="['ts.alertLevelCode ASC']"
+        :table="{
+            'row-key': 'id',
+            selection: 'multiple',
+        }"
+        dense
+        :is-editable="true"
+        :row-click="false"
+        :right-search="false"
+        :right-search-icon="false"
+        v-model:selected="selectedRows"
+        :disable-option="{ card: true }"
+    >
+        <template #top-left>
+            <div style="display: flex; align-items: center" v-if="itemLack">
+                <!-- <VnImg :id="itemLack.itemFk" class="rounded image-wrapper"></VnImg> -->
+                <div class="flex column" style="align-items: center">
+                    <QBadge
+                        ref="badgeLackRef"
+                        class="q-ml-xs"
+                        text-color="white"
+                        :color="itemLack.lack === 0 ? 'positive' : 'negative'"
+                        :label="itemLack.lack"
+                    />
+                </div>
+                <div class="flex column left" style="align-items: flex-start">
+                    <QBtn flat class="link text-blue">
+                        {{ item?.longName ?? item.name }}
+                        <ItemDescriptorProxy :id="entityId" />
+                        <FetchedTags class="q-ml-md" :item="item" :columns="7" />
+                    </QBtn>
+                </div>
+            </div>
+        </template>
+        <template #top-right>
+            <slot name="top-right" />
+        </template>
+
+        <template #column-status="{ row }">
+            <QTd style="min-width: 150px">
+                <div class="icon-container">
+                    <QIcon
+                        v-if="row.isBasket"
+                        name="vn:basket"
+                        color="primary"
+                        class="cursor-pointer"
+                        size="xs"
+                    >
+                        <QTooltip>{{ t('negative.detail.isBasket') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasToIgnore"
+                        name="star"
+                        color="primary"
+                        class="cursor-pointer fill-icon"
+                        size="xs"
+                    >
+                        <QTooltip>{{ t('negative.detail.hasToIgnore') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasObservation"
+                        name="change_circle"
+                        color="primary"
+                        class="cursor-pointer"
+                        size="xs"
+                    >
+                        <QTooltip>{{
+                            t('negative.detail.hasObservation')
+                        }}</QTooltip> </QIcon
+                    ><QIcon
+                        v-if="row.isRookie"
+                        name="vn:Person"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.isRookie') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.peticionCompra"
+                        name="vn:buyrequest"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.peticionCompra') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.turno"
+                        name="vn:calendar"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.turno') }}</QTooltip>
+                    </QIcon>
+                </div></QTd
+            >
+        </template>
+        <template #column-nickname="{ row }">
+            <span class="link" @click.stop>
+                {{ row.nickname }}
+                <CustomerDescriptorProxy :id="row.customerId" />
+            </span>
+        </template>
+        <template #column-ticketFk="{ row }">
+            <span class="q-pa-sm link">
+                {{ row.id }}
+                <TicketDescriptorProxy :id="row.id" />
+            </span>
+        </template>
+        <template #column-alertLevelCode="props">
+            <VnSelect
+                url="States/editableStates"
+                auto-load
+                hide-selected
+                option-value="id"
+                option-label="name"
+                v-model="props.row.alertLevelCode"
+                v-on="getInputEvents(props)"
+            />
+        </template>
+
+        <template #column-zoneName="{ row }">
+            <span class="link">{{ row.zoneName }}</span>
+            <ZoneDescriptorProxy :id="row.zoneFk" />
+        </template>
+        <template #column-quantity="props">
+            <VnInputNumber
+                v-model.number="props.row.quantity"
+                v-on="getInputEvents(props)"
+            ></VnInputNumber>
+        </template>
+    </VnTable>
+</template>
+<style lang="scss" scoped>
+.icon-container {
+    display: grid;
+    grid-template-columns: repeat(3, 0.2fr);
+    row-gap: 5px; /* Ajusta el espacio entre los iconos según sea necesario */
+}
+.icon-container > * {
+    width: 100%;
+    height: auto;
+}
+.list-enter-active,
+.list-leave-active {
+    transition: all 1s ease;
+}
+.list-enter-from,
+.list-leave-to {
+    opacity: 0;
+    background-color: $primary;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeItemDialog.vue b/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
new file mode 100644
index 000000000..e419b85c0
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
@@ -0,0 +1,90 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import notifyResults from 'src/utils/notifyResults';
+const emit = defineEmits(['update-item']);
+
+const showChangeItemDialog = ref(false);
+const newItem = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+
+const updateItem = async () => {
+    try {
+        showChangeItemDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
+            axios.post(`Sales/replaceItem`, {
+                saleFk,
+                substitutionFk: newItem.value,
+                quantity,
+            }),
+        );
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'saleFk');
+        emit('update-item', newItem.value);
+    } catch (err) {
+        console.error('Error updating item:', err);
+        return err;
+    }
+};
+</script>
+
+<template>
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            {{ showChangeItemDialog }}
+            <span>{{ $t('negative.detail.modal.changeItem.title') }}</span>
+            <VnSelect
+                url="Items/WithName"
+                :fields="['id', 'name']"
+                :sort-by="['id DESC']"
+                :options="items"
+                option-label="name"
+                option-value="id"
+                v-model="newItem"
+            >
+            </VnSelect>
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newItem"
+                @click="updateItem"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue b/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
new file mode 100644
index 000000000..2e9aac4f0
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
@@ -0,0 +1,84 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnInput from 'src/components/common/VnInput.vue';
+import notifyResults from 'src/utils/notifyResults';
+
+const showChangeQuantityDialog = ref(false);
+const newQuantity = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+const emit = defineEmits(['update-quantity']);
+const updateQuantity = async () => {
+    try {
+        showChangeQuantityDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ saleFk }) =>
+            axios.post(`Sales/${saleFk}/updateQuantity`, {
+                saleFk,
+                quantity: +newQuantity.value,
+            }),
+        );
+
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'saleFk');
+
+        emit('update-quantity', newQuantity.value);
+    } catch (err) {
+        return err;
+    }
+};
+</script>
+
+<template>
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            <span>{{ $t('negative.detail.modal.changeQuantity.title') }}</span>
+            <VnInput
+                type="number"
+                :min="0"
+                :label="$t('negative.detail.modal.changeQuantity.placeholder')"
+                v-model="newQuantity"
+            />
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newQuantity || newQuantity < 0"
+                @click="updateQuantity"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeStateDialog.vue b/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
new file mode 100644
index 000000000..1acc7e0ef
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
@@ -0,0 +1,91 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import FetchData from 'components/FetchData.vue';
+import notifyResults from 'src/utils/notifyResults';
+
+const emit = defineEmits(['update-state']);
+const editableStates = ref([]);
+const showChangeStateDialog = ref(false);
+const newState = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+const updateState = async () => {
+    try {
+        showChangeStateDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ id }) =>
+            axios.post(`Tickets/state`, {
+                ticketFk: id,
+                code: newState.value,
+            }),
+        );
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'ticketFk');
+
+        emit('update-state', newState.value);
+    } catch (err) {
+        return err;
+    }
+};
+</script>
+
+<template>
+    <FetchData
+        url="States/editableStates"
+        @on-fetch="(data) => (editableStates = data)"
+        auto-load
+    />
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            <span>{{ $t('negative.detail.modal.changeState.title') }}</span>
+            <VnSelect
+                :label="$t('negative.detail.modal.changeState.placeholder')"
+                v-model="newState"
+                :options="editableStates"
+                option-label="name"
+                option-value="code"
+            />
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newState"
+                @click="updateState"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/TicketFuture.vue b/src/pages/Ticket/TicketFuture.vue
index 0d216bed4..92911cd25 100644
--- a/src/pages/Ticket/TicketFuture.vue
+++ b/src/pages/Ticket/TicketFuture.vue
@@ -1,24 +1,22 @@
 <script setup>
-import { onMounted, ref, computed, reactive } from 'vue';
+import { ref, computed, reactive, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 
-import FetchData from 'components/FetchData.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
 import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
 import TicketFutureFilter from './TicketFutureFilter.vue';
 
 import { dashIfEmpty, toCurrency } from 'src/filters';
 import { useVnConfirm } from 'composables/useVnConfirm';
-import { useArrayData } from 'composables/useArrayData';
 import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import useNotify from 'src/composables/useNotify.js';
 import { useState } from 'src/composables/useState';
 import { toDateTimeFormat } from 'src/filters/date.js';
 import axios from 'axios';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const state = useState();
 const { t } = useI18n();
@@ -26,214 +24,126 @@ const { openConfirmationModal } = useVnConfirm();
 const { notify } = useNotify();
 const user = state.getUser();
 
-const itemPackingTypesOptions = ref([]);
 const selectedTickets = ref([]);
-
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'id':
-            return { id: value };
-        case 'futureId':
-            return { futureId: value };
-        case 'liters':
-            return { liters: value };
-        case 'lines':
-            return { lines: value };
-        case 'iptColFilter':
-            return { ipt: { like: `%${value}%` } };
-        case 'futureIptColFilter':
-            return { futureIpt: { like: `%${value}%` } };
-        case 'totalWithVat':
-            return { totalWithVat: value };
-    }
-};
-
+const vnTableRef = ref({});
+const originElRef = ref(null);
+const destinationElRef = ref(null);
 const userParams = reactive({
     futureScopeDays: Date.vnNew().toISOString(),
     originScopeDays: Date.vnNew().toISOString(),
     warehouseFk: user.value.warehouseFk,
 });
 
-const arrayData = useArrayData('FutureTickets', {
-    url: 'Tickets/getTicketsFuture',
-    userParams: userParams,
-    exprBuilder: exprBuilder,
-});
-const { store } = arrayData;
-
-const params = reactive({
-    futureScopeDays: Date.vnNew(),
-    originScopeDays: Date.vnNew(),
-    warehouseFk: user.value.warehouseFk,
-});
-
-const applyColumnFilter = async (col) => {
-    const paramKey = col.columnFilter?.filterParamKey || col.field;
-    params[paramKey] = col.columnFilter.filterValue;
-    await arrayData.addFilter({ params });
-};
-
-const getInputEvents = (col) => {
-    return col.columnFilter.type === 'select'
-        ? { 'update:modelValue': () => applyColumnFilter(col) }
-        : {
-              'keyup.enter': () => applyColumnFilter(col),
-          };
-};
-
-const tickets = computed(() => store.data);
-
 const ticketColumns = computed(() => [
     {
-        label: t('futureTickets.problems'),
+        label: '',
         name: 'problems',
+        headerClass: 'horizontal-separator',
         align: 'left',
-        columnFilter: null,
+        columnFilter: false,
     },
     {
         label: t('advanceTickets.ticketId'),
-        name: 'ticketId',
+        name: 'id',
         align: 'center',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            filterParamKey: 'id',
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('futureTickets.shipped'),
         name: 'shipped',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
+        columnFilter: false,
+        headerClass: 'horizontal-separator',
     },
     {
+        align: 'center',
+        class: 'shrink',
         label: t('advanceTickets.ipt'),
         name: 'ipt',
-        field: 'ipt',
-        align: 'left',
-        sortable: true,
         columnFilter: {
-            component: VnSelect,
-            filterParamKey: 'iptColFilter',
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
+            component: 'select',
             attrs: {
-                options: itemPackingTypesOptions.value,
-                'option-value': 'code',
-                'option-label': 'description',
-                dense: true,
+                url: 'itemPackingTypes',
+                fields: ['code', 'description'],
+                where: { isActive: true },
+                optionValue: 'code',
+                optionLabel: 'description',
+                inWhere: false,
             },
         },
-        format: (val) => dashIfEmpty(val),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.ipt),
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('ticketList.state'),
         name: 'state',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
+        columnFilter: false,
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('advanceTickets.liters'),
         name: 'liters',
-        field: 'liters',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('advanceTickets.import'),
-        field: 'import',
         name: 'import',
         align: 'left',
-        sortable: true,
+        headerClass: 'horizontal-separator',
+        columnFilter: false,
+        format: (row) => toCurrency(row.totalWithVat),
     },
     {
         label: t('futureTickets.availableLines'),
         name: 'lines',
         field: 'lines',
         align: 'center',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.lines),
     },
     {
         label: t('advanceTickets.futureId'),
         name: 'futureId',
-        align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            filterParamKey: 'futureId',
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        align: 'center',
+        headerClass: 'horizontal-separator vertical-separator ',
+        columnClass: 'vertical-separator',
     },
     {
         label: t('futureTickets.futureShipped'),
         name: 'futureShipped',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        columnFilter: false,
+        format: (row) => toDateTimeFormat(row.futureShipped),
     },
-
     {
+        align: 'center',
         label: t('advanceTickets.futureIpt'),
+        class: 'shrink',
         name: 'futureIpt',
-        field: 'futureIpt',
-        align: 'left',
-        sortable: true,
         columnFilter: {
-            component: VnSelect,
-            filterParamKey: 'futureIptColFilter',
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
+            component: 'select',
             attrs: {
-                options: itemPackingTypesOptions.value,
-                'option-value': 'code',
-                'option-label': 'description',
-                dense: true,
+                url: 'itemPackingTypes',
+                fields: ['code', 'description'],
+                where: { isActive: true },
+                optionValue: 'code',
+                optionLabel: 'description',
             },
         },
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.futureIpt),
     },
     {
         label: t('advanceTickets.futureState'),
         name: 'futureState',
         align: 'right',
-        sortable: true,
-        columnFilter: null,
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        class: 'expand',
+        columnFilter: false,
+        format: (row, dashIfEmpty) => dashIfEmpty(row.futureState),
     },
 ]);
 
@@ -258,26 +168,51 @@ const moveTicketsFuture = async () => {
     await axios.post('Tickets/merge', params);
     notify(t('advanceTickets.moveTicketSuccess'), 'positive');
     selectedTickets.value = [];
-    arrayData.fetch({ append: false });
+    vnTableRef.value.reload();
 };
-onMounted(async () => {
-    await arrayData.fetch({ append: false });
-});
+
+watch(
+    () => vnTableRef.value.tableRef?.$el,
+    ($el) => {
+        if (!$el) return;
+        const head = $el.querySelector('thead');
+        const firstRow = $el.querySelector('thead > tr');
+
+        const newRow = document.createElement('tr');
+        destinationElRef.value = document.createElement('th');
+        originElRef.value = document.createElement('th');
+
+        newRow.classList.add('bg-header');
+        destinationElRef.value.classList.add('text-uppercase', 'color-vn-label');
+        originElRef.value.classList.add('text-uppercase', 'color-vn-label');
+
+        destinationElRef.value.setAttribute('colspan', '7');
+        originElRef.value.setAttribute('colspan', '9');
+
+        originElRef.value.textContent = `${t('advanceTickets.origin')}`;
+        destinationElRef.value.textContent = `${t('advanceTickets.destination')}`;
+
+        newRow.append(destinationElRef.value, originElRef.value);
+        head.insertBefore(newRow, firstRow);
+    },
+    { once: true, inmmediate: true },
+);
+
+watch(
+    () => vnTableRef.value.params,
+    () => {
+        if (originElRef.value && destinationElRef.value) {
+            destinationElRef.value.textContent = `${t('advanceTickets.origin')}`;
+            originElRef.value.textContent = `${t('advanceTickets.destination')}`;
+        }
+    },
+    { deep: true },
+);
 </script>
 
 <template>
-    <FetchData
-        url="itemPackingTypes"
-        :filter="{
-            fields: ['code', 'description'],
-            order: 'description ASC',
-            where: { isActive: true },
-        }"
-        auto-load
-        @on-fetch="(data) => (itemPackingTypesOptions = data)"
-    />
     <VnSearchbar
-        data-key="FutureTickets"
+        data-key="futureTicket"
         :label="t('Search ticket')"
         :info="t('futureTickets.searchInfo')"
     />
@@ -293,7 +228,7 @@ onMounted(async () => {
                         t(`futureTickets.moveTicketDialogSubtitle`, {
                             selectedTickets: selectedTickets.length,
                         }),
-                        moveTicketsFuture
+                        moveTicketsFuture,
                     )
                 "
             >
@@ -305,235 +240,135 @@ onMounted(async () => {
     </VnSubToolbar>
     <RightMenu>
         <template #right-panel>
-            <TicketFutureFilter data-key="FutureTickets" />
+            <TicketFutureFilter data-key="futureTickets" />
         </template>
     </RightMenu>
     <QPage class="column items-center q-pa-md">
-        <QTable
-            :rows="tickets"
+        <VnTable
+            data-key="futureTickets"
+            ref="vnTableRef"
+            url="Tickets/getTicketsFuture"
+            search-url="futureTickets"
+            :user-params="userParams"
+            :limit="0"
             :columns="ticketColumns"
-            row-key="id"
-            selection="multiple"
+            :table="{
+                'row-key': '$index',
+                selection: 'multiple',
+            }"
             v-model:selected="selectedTickets"
-            :pagination="{ rowsPerPage: 0 }"
-            :no-data-label="t('globals.noResults')"
-            style="max-width: 99%"
+            :right-search="false"
+            auto-load
+            :disable-option="{ card: true }"
         >
-            <template #header="props">
-                <QTr>
-                    <QTh class="horizontal-separator" />
-                    <QTh
-                        class="horizontal-separator text-uppercase color-vn-label"
-                        colspan="8"
-                        translate
-                    >
-                        {{ t('advanceTickets.origin') }}
-                    </QTh>
-                    <QTh
-                        class="horizontal-separator text-uppercase color-vn-label"
-                        colspan="4"
-                        translate
-                    >
-                        {{ t('advanceTickets.destination') }}
-                    </QTh>
-                </QTr>
-                <QTr>
-                    <QTh>
-                        <QCheckbox v-model="props.selected" />
-                    </QTh>
-                    <QTh
-                        v-for="(col, index) in ticketColumns"
-                        :key="index"
-                        :class="{ 'vertical-separator': col.name === 'futureId' }"
-                    >
-                        {{ col.label }}
-                    </QTh>
-                </QTr>
-            </template>
-            <template #top-row="{ cols }">
-                <QTr>
-                    <QTd />
-                    <QTd
-                        v-for="(col, index) in cols"
-                        :key="index"
-                        style="max-width: 100px"
-                    >
-                        <component
-                            :is="col.columnFilter.component"
-                            v-if="col.columnFilter"
-                            v-model="col.columnFilter.filterValue"
-                            v-bind="col.columnFilter.attrs"
-                            v-on="col.columnFilter.event(col)"
-                            dense
-                        />
-                    </QTd>
-                </QTr>
-            </template>
-            <template #header-cell-availableLines="{ col }">
-                <QTh class="vertical-separator">
-                    {{ col.label }}
-                </QTh>
-            </template>
-            <template #body-cell-problems="{ row }">
-                <QTd class="q-gutter-x-xs">
+            <template #column-problems="{ row }">
+                <span class="q-gutter-x-xs">
                     <QIcon
-                        v-if="row.isTaxDataChecked === 0"
+                        v-if="row.futureAgencyFk !== row.agencyFk && row.agencyFk"
                         color="primary"
-                        name="vn:no036"
+                        name="vn:agency-term"
                         size="xs"
+                        class="q-mr-xs"
                     >
-                        <QTooltip>
-                            {{ t('futureTickets.noVerified') }}
+                        <QTooltip class="column">
+                            <span>
+                                {{
+                                    t('advanceTickets.originAgency', {
+                                        agency: row.futureAgency,
+                                    })
+                                }}
+                            </span>
+                            <span>
+                                {{
+                                    t('advanceTickets.destinationAgency', {
+                                        agency: row.agency,
+                                    })
+                                }}
+                            </span>
                         </QTooltip>
                     </QIcon>
-                    <QIcon
-                        v-if="row.hasTicketRequest"
-                        color="primary"
-                        name="vn:buyrequest"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.purchaseRequest') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.itemShortage"
-                        color="primary"
-                        name="vn:unavailable"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('ticketSale.noVisible') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.isFreezed"
-                        color="primary"
-                        name="vn:frozen"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.clientFrozen') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon v-if="row.risk" color="primary" name="vn:risk" size="xs">
-                        <QTooltip>
-                            {{ t('futureTickets.risk') }}: {{ row.risk }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasComponentLack"
-                        color="primary"
-                        name="vn:components"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.componentLack') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasRounding"
-                        color="primary"
-                        name="sync_problem"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.rounding') }}
-                        </QTooltip>
-                    </QIcon>
-                </QTd>
+                    <TicketProblems :row />
+                </span>
             </template>
-            <template #body-cell-ticketId="{ row }">
-                <QTd>
-                    <QBtn flat class="link">
-                        {{ row.id }}
-                        <TicketDescriptorProxy :id="row.id" />
-                    </QBtn>
-                </QTd>
+            <template #column-id="{ row }">
+                <QBtn flat class="link" @click.stop dense>
+                    {{ row.id }}
+                    <TicketDescriptorProxy :id="row.id" />
+                </QBtn>
             </template>
-            <template #body-cell-shipped="{ row }">
-                <QTd class="shipped">
-                    <QBadge
-                        text-color="black"
-                        :color="getDateQBadgeColor(row.shipped)"
-                        class="q-ma-none"
-                    >
-                        {{ toDateTimeFormat(row.shipped) }}
-                    </QBadge>
-                </QTd>
+            <template #column-shipped="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="getDateQBadgeColor(row.shipped)"
+                    class="q-ma-none"
+                >
+                    {{ toDateTimeFormat(row.shipped) }}
+                </QBadge>
             </template>
-            <template #body-cell-state="{ row }">
-                <QTd>
-                    <QBadge
-                        text-color="black"
-                        :color="row.classColor"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ row.state }}
-                    </QBadge>
-                </QTd>
+            <template #column-state="{ row }">
+                <QBadge
+                    v-if="row.state"
+                    text-color="black"
+                    :color="row.classColor"
+                    class="q-ma-none"
+                    dense
+                >
+                    {{ row.state }}
+                </QBadge>
+                <span v-else> {{ dashIfEmpty(row.state) }}</span>
             </template>
-            <template #body-cell-import="{ row }">
-                <QTd>
-                    <QBadge
-                        :text-color="
-                            totalPriceColor(row.totalWithVat) === 'warning'
-                                ? 'black'
-                                : 'white'
-                        "
-                        :color="totalPriceColor(row.totalWithVat)"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ toCurrency(row.totalWithVat || 0) }}
-                    </QBadge>
-                </QTd>
+            <template #column-import="{ row }">
+                <QBadge
+                    :text-color="
+                        totalPriceColor(row.totalWithVat) === 'warning'
+                            ? 'black'
+                            : 'white'
+                    "
+                    :color="totalPriceColor(row.totalWithVat)"
+                    class="q-ma-none"
+                    dense
+                >
+                    {{ toCurrency(row.totalWithVat || 0) }}
+                </QBadge>
             </template>
-            <template #body-cell-futureId="{ row }">
-                <QTd class="vertical-separator">
-                    <QBtn flat class="link" dense>
-                        {{ row.futureId }}
-                        <TicketDescriptorProxy :id="row.futureId" />
-                    </QBtn>
-                </QTd>
+            <template #column-futureId="{ row }">
+                <QBtn flat class="link" @click.stop dense>
+                    {{ row.futureId }}
+                    <TicketDescriptorProxy :id="row.futureId" />
+                </QBtn>
             </template>
-            <template #body-cell-futureShipped="{ row }">
-                <QTd class="shipped">
-                    <QBadge
-                        text-color="black"
-                        :color="getDateQBadgeColor(row.futureShipped)"
-                        class="q-ma-none"
-                    >
-                        {{ toDateTimeFormat(row.futureShipped) }}
-                    </QBadge>
-                </QTd>
+            <template #column-futureShipped="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="getDateQBadgeColor(row.futureShipped)"
+                    class="q-ma-none"
+                >
+                    {{ toDateTimeFormat(row.futureShipped) }}
+                </QBadge>
             </template>
-            <template #body-cell-futureState="{ row }">
-                <QTd>
-                    <QBadge
-                        text-color="black"
-                        :color="row.futureClassColor"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ row.futureState }}
-                    </QBadge>
-                </QTd>
+            <template #column-futureState="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="row.futureClassColor"
+                    class="q-mr-xs"
+                    dense
+                >
+                    {{ row.futureState }}
+                </QBadge>
             </template>
-        </QTable>
+        </VnTable>
     </QPage>
 </template>
 
 <style scoped lang="scss">
-.shipped {
-    min-width: 132px;
-}
-.vertical-separator {
+:deep(.vertical-separator) {
     border-left: 4px solid white !important;
 }
 
-.horizontal-separator {
+:deep(.horizontal-separator) {
+    border-top: 4px solid white !important;
+}
+:deep(.horizontal-bottom-separator) {
     border-bottom: 4px solid white !important;
 }
 </style>
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index d28b0af71..64e060a39 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -12,7 +12,7 @@ import axios from 'axios';
 import { onMounted } from 'vue';
 
 const { t } = useI18n();
-const props = defineProps({
+defineProps({
     dataKey: {
         type: String,
         required: true,
@@ -58,7 +58,7 @@ onMounted(async () => {
         auto-load
     />
     <VnFilterPanel
-        :data-key="props.dataKey"
+        :data-key
         :un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
     >
         <template #tags="{ tag, formatFn }">
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index f11b32c3a..cdbb22d9b 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -23,6 +23,8 @@ ticketSale:
     hasComponentLack: Component lack
     ok: Ok
     more: More
+    transferLines: Transfer lines(no basket)/ Split
+    transferBasket: Some row selected is basket
 advanceTickets:
     preparation: Preparation
     origin: Origin
@@ -188,7 +190,6 @@ ticketList:
     accountPayment: Account payment
     sendDocuware: Set delivered and send delivery note(s) to the tablet
     addPayment: Add payment
-    date: Date
     company: Company
     amount: Amount
     reference: Reference
@@ -202,9 +203,89 @@ ticketList:
     creditCard: Credit card
     transfers: Transfers
     province: Province
-    warehouse: Warehouse
-    hour: Hour
     closure: Closure
     toLines: Go to lines
     addressNickname: Address nickname
     ref: Reference
+    rounding: Rounding
+    noVerifiedData: No verified data
+    purchaseRequest: Purchase request
+    notVisible: Not visible
+    clientFrozen: Client frozen
+    componentLack: Component lack
+negative:
+    hour: Hour
+    id: Id Article
+    longName: Article
+    supplier: Supplier
+    colour: Colour
+    size: Size
+    origen: Origin
+    value: Negative
+    itemFk: Article
+    producer: Producer
+    warehouse: Warehouse
+    warehouseFk: Warehouse
+    category: Category
+    categoryFk: Family
+    type: Type
+    typeFk: Type
+    lack: Negative
+    inkFk: inkFk
+    timed: timed
+    date: Date
+    minTimed: minTimed
+    negativeAction: Negative
+    totalNegative: Total negatives
+    days: Days
+    buttonsUpdate:
+        item: Item
+        state: State
+        quantity: Quantity
+    modalOrigin:
+        title: Update negatives
+        question: Select a state to update
+    modalSplit:
+        title: Confirm split selected
+        question: Select a state to update
+    detail:
+        saleFk: Sale
+        itemFk: Article
+        ticketFk: Ticket
+        code: Code
+        nickname: Alias
+        name: Name
+        zoneName: Agency name
+        shipped: Date
+        theoreticalhour: Theoretical hour
+        agName: Agency
+        quantity: Quantity
+        alertLevelCode: Group state
+        state: State
+        peticionCompra: Ticket request
+        isRookie: Is rookie
+        turno: Turn line
+        isBasket: Basket
+        hasObservation: Has substitution
+        hasToIgnore: VIP
+        modal:
+            changeItem:
+                title: Update item reference
+                placeholder: New item
+            changeState:
+                title: Update tickets state
+                placeholder: New state
+            changeQuantity:
+                title: Update tickets quantity
+                placeholder: New quantity
+            split:
+                title: Are you sure you want to split selected tickets?
+                subTitle: Confirm split action
+            handleSplited:
+                title: Handle splited  tickets
+                subTitle: Confirm date and agency
+    split:
+        ticket: Old ticket
+        newTicket: New ticket
+        status: Result
+        message: Message
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index 945da8367..75d3c6a2b 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -127,6 +127,8 @@ ticketSale:
     ok: Ok
     more: Más
     address: Consignatario
+    transferLines: Transferir líneas(no cesta)/ Separar
+    transferBasket: No disponible para una cesta
     size: Medida
 ticketComponents:
     serie: Serie
@@ -213,3 +215,84 @@ ticketList:
     toLines: Ir a lineas
     addressNickname: Alias consignatario
     ref: Referencia
+negative:
+    hour: Hora
+    id: Id Articulo
+    longName: Articulo
+    supplier: Productor
+    colour: Color
+    size: Medida
+    origen: Origen
+    value: Negativo
+    warehouseFk: Almacen
+    producer: Producer
+    category: Categoría
+    categoryFk: Familia
+    typeFk: Familia
+    warehouse: Almacen
+    lack: Negativo
+    inkFk: Color
+    timed: Hora
+    date: Fecha
+    minTimed: Hora
+    type: Tipo
+    negativeAction: Negativo
+    totalNegative: Total negativos
+    days: Rango de dias
+    buttonsUpdate:
+        item: artículo
+        state: Estado
+        quantity: Cantidad
+    modalOrigin:
+        title: Actualizar negativos
+        question: Seleccione un estado para guardar
+    modalSplit:
+        title: Confirmar acción de split
+        question: Selecciona un estado
+    detail:
+        saleFk: Línea
+        itemFk: Artículo
+        ticketFk: Ticket
+        code: code
+        nickname: Alias
+        name: Nombre
+        zoneName: Agencia
+        shipped: F. envío
+        theoreticalhour: Hora teórica
+        agName: Agencia
+        quantity: Cantidad
+        alertLevelCode: Estado agrupado
+        state: Estado
+        peticionCompra: Petición compra
+        isRookie: Cliente nuevo
+        turno: Linea turno
+        isBasket: Cesta
+        hasObservation: Tiene sustitución
+        hasToIgnore: VIP
+        modal:
+            changeItem:
+                title: Actualizar referencia artículo
+                placeholder: Nuevo articulo
+            changeState:
+                title: Actualizar estado
+                placeholder: Nuevo estado
+            changeQuantity:
+                title: Actualizar cantidad
+                placeholder: Nueva cantidad
+            split:
+                title: ¿Seguro de separar los tickets seleccionados?
+                subTitle: Confirma separar tickets seleccionados
+            handleSplited:
+                title: Gestionar tickets spliteados
+                subTitle: Confir fecha y agencia
+    split:
+        ticket: Ticket viejo
+        newTicket: Ticket nuevo
+        status: Estado
+        message: Mensaje
+    rounding: Redondeo
+    noVerifiedData: Sin datos comprobados
+    purchaseRequest: Petición de compra
+    notVisible: No visible
+    clientFrozen: Cliente congelado
+    componentLack: Faltan componentes
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index 4b9aa28ed..b1adc8126 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
+import VnInputTime from 'components/common/VnInputTime.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -53,7 +54,16 @@ const warehousesOptionsIn = ref([]);
                 <VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
                 <VnInputDate v-model="data.landed" :label="t('globals.landed')" />
             </VnRow>
-
+            <VnRow>
+                <VnInputDate
+                    v-model="data.availabled"
+                    :label="t('travel.summary.availabled')" 
+                    />
+                <VnInputTime
+                    v-model="data.availabled"
+                    :label="t('travel.summary.availabledHour')"
+                />
+            </VnRow>
             <VnRow>
                 <VnSelect
                     :label="t('globals.warehouseOut')"
@@ -101,10 +111,3 @@ const warehousesOptionsIn = ref([]);
         </template>
     </FormModel>
 </template>
-
-<i18n>
-es:
-    raidDays: El travel se desplaza automáticamente cada día para estar desde hoy al número de días indicado. Si se deja vacio no se moverá
-en:
-    raidDays: The travel adjusts itself daily to match the number of days set, starting from today. If left blank, it won’t move
-</i18n>
diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue
index 445675b90..cb09eafd6 100644
--- a/src/pages/Travel/Card/TravelCard.vue
+++ b/src/pages/Travel/Card/TravelCard.vue
@@ -1,43 +1,13 @@
 <script setup>
 import TravelDescriptor from './TravelDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
-
-const userFilter = {
-    fields: [
-        'id',
-        'ref',
-        'shipped',
-        'landed',
-        'totalEntries',
-        'warehouseInFk',
-        'warehouseOutFk',
-        'cargoSupplierFk',
-        'agencyModeFk',
-        'isRaid',
-        'isDelivered',
-        'isReceived',
-    ],
-    include: [
-        {
-            relation: 'warehouseIn',
-            scope: {
-                fields: ['name'],
-            },
-        },
-        {
-            relation: 'warehouseOut',
-            scope: {
-                fields: ['name'],
-            },
-        },
-    ],
-};
+import filter from './TravelFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Travel"
-        base-url="Travels"
+        url="Travels"
         :descriptor="TravelDescriptor"
-        :user-filter="userFilter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index 72acf91b8..922f89f33 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -32,7 +32,6 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
 
 <template>
     <CardDescriptor
-        module="Travel"
         :url="`Travels/${entityId}`"
         :title="data.title"
         :subtitle="data.subtitle"
diff --git a/src/pages/Travel/Card/TravelFilter.js b/src/pages/Travel/Card/TravelFilter.js
index f5f4520fd..05436834f 100644
--- a/src/pages/Travel/Card/TravelFilter.js
+++ b/src/pages/Travel/Card/TravelFilter.js
@@ -11,6 +11,7 @@ export default {
         'agencyModeFk',
         'isRaid',
         'daysInForward',
+        'availabled',
     ],
     include: [
         {
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 16d42f104..9f9552611 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -10,6 +10,8 @@ import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'
 import FetchData from 'src/components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import { toDate, toCurrency, toCelsius } from 'src/filters';
+import { toDateTimeFormat } from 'src/filters/date.js';
+import { dashIfEmpty } from 'src/filters';
 import axios from 'axios';
 import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
 
@@ -333,6 +335,12 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 <VnLv :label="t('globals.reference')" :value="travel.ref" />
                 <VnLv label="m³" :value="travel.m3" />
                 <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
+                <VnLv
+                    :label="t('travel.summary.availabled')"
+                    :value="
+                        dashIfEmpty(toDateTimeFormat(travel.availabled))
+                    "
+                />
             </QCard>
             <QCard class="full-width">
                 <VnTitle :text="t('travel.summary.entries')" />
diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index 2946c8814..2376bd6d2 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -217,7 +217,7 @@ const removeThermograph = async (id) => {
             icon="add"
             color="primary"
             @click="redirectToThermographForm('create')"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip class="text-no-wrap">
             {{ t('Add thermograph') }}
diff --git a/src/pages/Travel/ExtraCommunityFilter.vue b/src/pages/Travel/ExtraCommunityFilter.vue
index b903aeabf..b22574632 100644
--- a/src/pages/Travel/ExtraCommunityFilter.vue
+++ b/src/pages/Travel/ExtraCommunityFilter.vue
@@ -113,7 +113,7 @@ warehouses();
                         <template #append>
                             <QBtn
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 flat
                                 dense
                                 size="12px"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index e90c01be2..b227afcb2 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -10,6 +10,9 @@ import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import TravelFilter from './TravelFilter.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
 import VnSection from 'src/components/common/VnSection.vue';
+import VnInputTime from 'src/components/common/VnInputTime.vue';
+import VnInputDate from 'src/components/common/VnInputDate.vue';
+import { toDateTimeFormat } from 'src/filters/date';
 
 const { viewSummary } = useSummaryDialog();
 const router = useRouter();
@@ -167,6 +170,17 @@ const columns = computed(() => [
         cardVisible: true,
         create: true,
     },
+    {
+        align: 'left',
+        name: 'availabled',
+        label: t('travel.summary.availabled'),
+        component: 'input',
+        columnClass: 'expand',
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(toDateTimeFormat(row.availabled)),
+    },
     {
         align: 'right',
         label: '',
@@ -269,6 +283,16 @@ const columns = computed(() => [
                         :class="{ 'is-active': row.isReceived }"
                     />
                 </template>
+                <template #more-create-dialog="{ data }">
+                    <VnInputDate
+                        v-model="data.availabled"
+                        :label="t('travel.summary.availabled')"
+                    />
+                    <VnInputTime
+                        v-model="data.availabled"
+                        :label="t('travel.summary.availabledHour')"
+                    />
+                </template>
                 <template #moreFilterPanel="{ params }">
                     <VnInputNumber
                         :label="t('params.scopeDays')"
diff --git a/src/pages/Wagon/Card/WagonCard.vue b/src/pages/Wagon/Card/WagonCard.vue
index ed6c83778..644a30ffa 100644
--- a/src/pages/Wagon/Card/WagonCard.vue
+++ b/src/pages/Wagon/Card/WagonCard.vue
@@ -2,5 +2,5 @@
 import VnCard from 'components/common/VnCard.vue';
 </script>
 <template>
-    <VnCard data-key="Wagon" base-url="Wagons" />
+    <VnCard data-key="Wagon" url="Wagons" />
 </template>
diff --git a/src/pages/Wagon/Type/WagonTypeList.vue b/src/pages/Wagon/Type/WagonTypeList.vue
index c0943c58e..4c0b078a7 100644
--- a/src/pages/Wagon/Type/WagonTypeList.vue
+++ b/src/pages/Wagon/Type/WagonTypeList.vue
@@ -96,7 +96,13 @@ async function remove(row) {
         >
         </VnTable>
         <QPageSticky :offset="[18, 18]">
-            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
+            <QBtn
+                @click.stop="dialog.show()"
+                color="primary"
+                fab
+                icon="add"
+                v-shortcut="'+'"
+            >
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Create new Wagon type')"
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
index 6a13e3f39..fcf0f0369 100644
--- a/src/pages/Worker/Card/WorkerBasicData.vue
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -1,6 +1,5 @@
 <script setup>
-import { ref, onBeforeMount } from 'vue';
-import { useRoute } from 'vue-router';
+import { ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import FetchData from 'components/FetchData.vue';
@@ -11,18 +10,13 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 
 const { t } = useI18n();
+const form = ref();
 const educationLevels = ref([]);
 const countries = ref([]);
 const maritalStatus = [
     { code: 'M', name: t('Married') },
     { code: 'S', name: t('Single') },
 ];
-const advancedSummary = ref({});
-
-onBeforeMount(async () => {
-    advancedSummary.value =
-        (await useAdvancedSummary('Workers', +useRoute().params.id)) ?? {};
-});
 </script>
 <template>
     <FetchData
@@ -38,14 +32,15 @@ onBeforeMount(async () => {
         auto-load
     />
     <FormModel
-        :filter="{ where: { id: +$route.params.id } }"
-        url="Workers/summary"
+        ref="form"
         :url-update="`Workers/${$route.params.id}`"
         auto-load
         model="Worker"
         @on-fetch="
             async (data) => {
-                Object.assign(data, advancedSummary);
+                Object.assign(data, (await useAdvancedSummary('Workers', data.id)) ?? {});
+                await $nextTick();
+                if (form) form.hasChanges = false;
             }
         "
     >
diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue
index 5ca95a1a4..df4616011 100644
--- a/src/pages/Worker/Card/WorkerCalendar.vue
+++ b/src/pages/Worker/Card/WorkerCalendar.vue
@@ -1,7 +1,8 @@
 <script setup>
-import { nextTick, ref, watch } from 'vue';
+import { nextTick, ref, watch, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
+import { useAcl } from 'src/composables/useAcl';
 
 import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
 import FetchData from 'components/FetchData.vue';
@@ -9,10 +10,17 @@ import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 import axios from 'axios';
+import VnNotes from 'src/components/ui/VnNotes.vue';
+import { useStateStore } from 'src/stores/useStateStore';
+const stateStore = useStateStore();
 
 const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
+const acl = useAcl();
+const canSeeNotes = computed(() =>
+    acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
+);
 const workerIsFreelance = ref();
 const WorkerFreelanceRef = ref();
 const workerCalendarFilterRef = ref(null);
@@ -26,6 +34,10 @@ const contractHolidays = ref(null);
 const yearHolidays = ref(null);
 const eventsMap = ref({});
 const festiveEventsMap = ref({});
+const saveUrl = ref();
+const body = {
+    workerFk: route.params.id,
+};
 
 const onFetchActiveContract = (data) => {
     if (!data) return;
@@ -67,7 +79,7 @@ const onFetchAbsences = (data) => {
                     name: holidayName,
                     isFestive: true,
                 },
-                true
+                true,
             );
         });
     }
@@ -146,7 +158,7 @@ watch(
     async () => {
         await nextTick();
         await activeContractRef.value.fetch();
-    }
+    },
 );
 watch([year, businessFk], () => refreshData());
 </script>
@@ -181,6 +193,20 @@ watch([year, businessFk], () => refreshData());
             />
         </template>
     </RightMenu>
+    <Teleport to="#st-data" v-if="stateStore.isSubToolbarShown() && canSeeNotes">
+        <VnNotes
+            :just-input="true"
+            :url="`Workers/${route.params.id}/business`"
+            :filter="{ fields: ['id', 'notes', 'workerFk'] }"
+            :save-url="saveUrl"
+            @on-fetch="
+                (data) => {
+                    saveUrl = `Businesses/${data.id}`;
+                }
+            "
+            :body="body"
+        />
+    </Teleport>
     <QPage class="column items-center">
         <QCard v-if="workerIsFreelance">
             <QCardSection class="text-center">
diff --git a/src/pages/Worker/Card/WorkerCalendarFilter.vue b/src/pages/Worker/Card/WorkerCalendarFilter.vue
index 67b7df907..48fc4094b 100644
--- a/src/pages/Worker/Card/WorkerCalendarFilter.vue
+++ b/src/pages/Worker/Card/WorkerCalendarFilter.vue
@@ -180,8 +180,6 @@ const yearList = ref(generateYears());
                     :is-clearable="false"
                 />
             </QItemSection>
-        </QItem>
-        <QItem>
             <QItemSection>
                 <VnSelect
                     :label="t('Contract')"
diff --git a/src/pages/Worker/Card/WorkerCard.vue b/src/pages/Worker/Card/WorkerCard.vue
index 1ada15a33..3b7a62025 100644
--- a/src/pages/Worker/Card/WorkerCard.vue
+++ b/src/pages/Worker/Card/WorkerCard.vue
@@ -3,5 +3,10 @@ import WorkerDescriptor from './WorkerDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Worker" custom-url="Workers/summary" :descriptor="WorkerDescriptor" />
+    <VnCardBeta
+        data-key="Worker"
+        url="Workers/summary"
+        :id-in-where="true"
+        :descriptor="WorkerDescriptor"
+    />
 </template>
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 2b0af4926..0e946f1dd 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -10,7 +10,7 @@ import axios from 'axios';
 import VnImg from 'src/components/ui/VnImg.vue';
 import EditPictureForm from 'components/EditPictureForm.vue';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 
 const $props = defineProps({
     id: {
@@ -21,7 +21,7 @@ const $props = defineProps({
     dataKey: {
         type: String,
         required: false,
-        default: 'workerData',
+        default: 'Worker',
     },
 });
 const image = ref(null);
@@ -50,9 +50,8 @@ const handlePhotoUpdated = (evt = false) => {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
-        module="Worker"
         :data-key="dataKey"
-        url="Workers/descriptor"
+        url="Workers/summary"
         :filter="{ where: { id: entityId } }"
         title="user.nickname"
         @on-fetch="getIsExcluded"
@@ -153,7 +152,7 @@ const handlePhotoUpdated = (evt = false) => {
                 <QBtn
                     :to="{
                         name: 'AccountCard',
-                        params: { id: entity.user.id },
+                        params: { id: entity.user?.id },
                     }"
                     size="md"
                     icon="face"
diff --git a/src/pages/Worker/Card/WorkerDescriptorProxy.vue b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
index 43deb7821..a142570f9 100644
--- a/src/pages/Worker/Card/WorkerDescriptorProxy.vue
+++ b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
@@ -12,11 +12,6 @@ const $props = defineProps({
 
 <template>
     <QPopupProxy>
-        <WorkerDescriptor
-            v-if="$props.id"
-            :id="$props.id"
-            :summary="WorkerSummary"
-            data-key="workerDescriptorProxy"
-        />
+        <WorkerDescriptor v-if="$props.id" :id="$props.id" :summary="WorkerSummary" />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Worker/Card/WorkerFormation.vue b/src/pages/Worker/Card/WorkerFormation.vue
index 6fd5a4eae..e8680f7dd 100644
--- a/src/pages/Worker/Card/WorkerFormation.vue
+++ b/src/pages/Worker/Card/WorkerFormation.vue
@@ -94,6 +94,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'hasDiploma',
         label: t('worker.formation.tableVisibleColumns.hasDiploma'),
+        component: 'checkbox',
         create: true,
     },
     {
@@ -118,7 +119,7 @@ const columns = computed(() => [
         :url="`Workers/${entityId}/trainingCourse`"
         :url-create="`Workers/${entityId}/trainingCourse`"
         save-url="TrainingCourses/crud"
-        :filter="courseFilter"
+        :user-filter="courseFilter"
         :create="{
             urlCreate: 'trainingCourses',
             title: t('Create training course'),
diff --git a/src/pages/Worker/Card/WorkerMedical.vue b/src/pages/Worker/Card/WorkerMedical.vue
index c220df76a..c04f6496b 100644
--- a/src/pages/Worker/Card/WorkerMedical.vue
+++ b/src/pages/Worker/Card/WorkerMedical.vue
@@ -3,11 +3,23 @@ import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import VnTable from 'components/VnTable/VnTable.vue';
+import { dashIfEmpty } from 'src/filters';
 const tableRef = ref();
 const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => route.params.id);
 
+const centerFilter = {
+    include: [
+        {
+            relation: 'center',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+    ],
+};
+
 const columns = [
     {
         align: 'left',
@@ -36,6 +48,9 @@ const columns = [
             url: 'medicalCenters',
             fields: ['id', 'name'],
         },
+        format: (row, dashIfEmpty) => {
+            return dashIfEmpty(row.center?.name);
+        },
     },
     {
         align: 'left',
@@ -84,6 +99,7 @@ const columns = [
         ref="tableRef"
         data-key="WorkerMedical"
         :url="`Workers/${entityId}/medicalReview`"
+        :user-filter="centerFilter"
         save-url="MedicalReviews/crud"
         :create="{
             urlCreate: 'medicalReviews',
diff --git a/src/pages/Worker/Card/WorkerOperator.vue b/src/pages/Worker/Card/WorkerOperator.vue
index cdacc72c0..6faeefe67 100644
--- a/src/pages/Worker/Card/WorkerOperator.vue
+++ b/src/pages/Worker/Card/WorkerOperator.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
 import FetchData from 'components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
@@ -19,6 +19,7 @@ const trainsData = ref([]);
 const machinesData = ref([]);
 const route = useRoute();
 const routeId = computed(() => route.params.id);
+const selected = ref([]);
 
 const initialData = computed(() => {
     return {
@@ -41,6 +42,21 @@ async function insert() {
     await axios.post('Operators', initialData.value);
     crudModelRef.value.reload();
 }
+
+watch(
+    () => crudModelRef.value?.formData,
+    (formData) => {
+        if (formData && formData.length) {
+            if (JSON.stringify(selected.value) !== JSON.stringify(formData)) {
+                selected.value = formData;
+            }
+        } else if (selected.value.length > 0) {
+            selected.value = [];
+        }
+    },
+    { immediate: true, deep: true }
+);
+
 </script>
 
 <template>
@@ -67,6 +83,7 @@ async function insert() {
             :data-required="{ workerFk: route.params.id }"
             ref="crudModelRef"
             search-url="operator"
+            :selected="selected"
             auto-load
         >
             <template #body="{ rows }">
diff --git a/src/pages/Worker/Card/WorkerPda.vue b/src/pages/Worker/Card/WorkerPda.vue
index f6cb92aac..47e13cf6d 100644
--- a/src/pages/Worker/Card/WorkerPda.vue
+++ b/src/pages/Worker/Card/WorkerPda.vue
@@ -101,7 +101,7 @@ function reloadData() {
                                 openConfirmationModal(
                                     t(`Remove PDA`),
                                     t('Do you want to remove this PDA?'),
-                                    () => deallocatePDA(row.deviceProductionFk)
+                                    () => deallocatePDA(row.deviceProductionFk),
                                 )
                             "
                         >
@@ -114,7 +114,13 @@ function reloadData() {
             </template>
         </VnPaginate>
         <QPageSticky :offset="[18, 18]">
-            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
+            <QBtn
+                @click.stop="dialog.show()"
+                color="primary"
+                fab
+                icon="add"
+                v-shortcut="'+'"
+            >
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Add new device')"
diff --git a/src/pages/Worker/Card/WorkerPit.vue b/src/pages/Worker/Card/WorkerPit.vue
index 79cf1a04f..40e814452 100644
--- a/src/pages/Worker/Card/WorkerPit.vue
+++ b/src/pages/Worker/Card/WorkerPit.vue
@@ -221,7 +221,7 @@ const deleteRelative = async (id) => {
                                 color="primary"
                                 flat
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 style="flex: 0"
                                 data-cy="addRelative"
                             />
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 992f6ec71..78c5dfd82 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -9,7 +9,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
 
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index c580e5202..7def6e94c 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -64,17 +64,17 @@ const selectedCalendarDates = ref([]);
 // Date formateada para bindear al componente QDate
 const selectedDateFormatted = ref(toDateString(defaultDate.value));
 
-const arrayData = useArrayData('workerData');
+const arrayData = useArrayData('Worker');
 const acl = useAcl();
 const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear());
 const worker = computed(() => arrayData.store?.data);
 const canSend = computed(() =>
-    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }])
+    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]),
 );
 const canUpdate = computed(() =>
     acl.hasAny([
         { model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' },
-    ])
+    ]),
 );
 const isHimself = computed(() => user.value.id === Number(route.params.id));
 
@@ -100,7 +100,7 @@ const getHeaderFormattedDate = (date) => {
 };
 
 const formattedWeekTotalHours = computed(() =>
-    secondsToHoursMinutes(weekTotalHours.value)
+    secondsToHoursMinutes(weekTotalHours.value),
 );
 
 const onInputChange = async (date) => {
@@ -320,7 +320,7 @@ const getFinishTime = () => {
     today.setHours(0, 0, 0, 0);
 
     let todayInWeek = weekDays.value.find(
-        (day) => day.dated.getTime() === today.getTime()
+        (day) => day.dated.getTime() === today.getTime(),
     );
 
     if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
@@ -472,7 +472,7 @@ onMounted(async () => {
                         openConfirmationModal(
                             t('Send time control email'),
                             t('Are you sure you want to send it?'),
-                            resendEmail
+                            resendEmail,
                         )
                     "
                 >
@@ -561,7 +561,7 @@ onMounted(async () => {
                                 @show-worker-time-form="
                                     showWorkerTimeForm(
                                         { id: hour.id, entryCode: hour.direction },
-                                        'edit'
+                                        'edit',
                                     )
                                 "
                                 class="hour-chip"
@@ -577,7 +577,7 @@ onMounted(async () => {
                             </span>
                             <QBtn
                                 icon="add_circle"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 flat
                                 color="primary"
                                 class="fill-icon cursor-pointer"
diff --git a/src/pages/Department/Card/DepartmentBasicData.vue b/src/pages/Worker/Department/Card/DepartmentBasicData.vue
similarity index 73%
rename from src/pages/Department/Card/DepartmentBasicData.vue
rename to src/pages/Worker/Department/Card/DepartmentBasicData.vue
index b13aed2d3..66210be7b 100644
--- a/src/pages/Department/Card/DepartmentBasicData.vue
+++ b/src/pages/Worker/Department/Card/DepartmentBasicData.vue
@@ -1,27 +1,16 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
-
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
-
-const route = useRoute();
-const { t } = useI18n();
 </script>
 <template>
-    <FormModel
-        :url="`Departments/${route.params.id}`"
-        model="department"
-        auto-load
-        class="full-width"
-    >
+    <FormModel model="Department" auto-load class="full-width">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
-                    :label="t('globals.name')"
+                    :label="$t('globals.name')"
                     v-model="data.name"
                     :rules="validate('globals.name')"
                     clearable
@@ -29,33 +18,33 @@ const { t } = useI18n();
                 />
                 <VnInput
                     v-model="data.code"
-                    :label="t('globals.code')"
+                    :label="$t('globals.code')"
                     :rules="validate('globals.code')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="t('department.chat')"
+                    :label="$t('department.chat')"
                     v-model="data.chatName"
                     :rules="validate('department.chat')"
                     clearable
                 />
                 <VnInput
                     v-model="data.notificationEmail"
-                    :label="t('globals.params.email')"
+                    :label="$t('globals.params.email')"
                     :rules="validate('globals.params.email')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnSelectWorker
-                    :label="t('department.bossDepartment')"
+                    :label="$t('department.bossDepartment')"
                     v-model="data.workerFk"
                     :rules="validate('department.bossDepartment')"
                 />
                 <VnSelect
-                    :label="t('department.selfConsumptionCustomer')"
+                    :label="$t('department.selfConsumptionCustomer')"
                     v-model="data.clientFk"
                     url="Clients"
                     option-value="id"
@@ -67,11 +56,11 @@ const { t } = useI18n();
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.telework')"
+                    :label="$t('department.telework')"
                     v-model="data.isTeleworking"
                 />
                 <QCheckbox
-                    :label="t('department.notifyOnErrors')"
+                    :label="$t('department.notifyOnErrors')"
                     v-model="data.hasToMistake"
                     :false-value="0"
                     :true-value="1"
@@ -79,17 +68,17 @@ const { t } = useI18n();
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.worksInProduction')"
+                    :label="$t('department.worksInProduction')"
                     v-model="data.isProduction"
                 />
                 <QCheckbox
-                    :label="t('department.hasToRefill')"
+                    :label="$t('department.hasToRefill')"
                     v-model="data.hasToRefill"
                 />
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.hasToSendMail')"
+                    :label="$t('department.hasToSendMail')"
                     v-model="data.hasToSendMail"
                 />
             </VnRow>
diff --git a/src/pages/Department/Card/DepartmentCard.vue b/src/pages/Worker/Department/Card/DepartmentCard.vue
similarity index 70%
rename from src/pages/Department/Card/DepartmentCard.vue
rename to src/pages/Worker/Department/Card/DepartmentCard.vue
index 4b9fe419c..2e3f11521 100644
--- a/src/pages/Department/Card/DepartmentCard.vue
+++ b/src/pages/Worker/Department/Card/DepartmentCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
+import DepartmentDescriptor from 'pages/Worker/Department/Card/DepartmentDescriptor.vue';
 </script>
 <template>
     <VnCardBeta
         class="q-pa-md column items-center"
         v-bind="{ ...$attrs }"
         data-key="Department"
-        base-url="Departments"
+        url="Departments"
         :descriptor="DepartmentDescriptor"
     />
 </template>
diff --git a/src/pages/Department/Card/DepartmentDescriptor.vue b/src/pages/Worker/Department/Card/DepartmentDescriptor.vue
similarity index 84%
rename from src/pages/Department/Card/DepartmentDescriptor.vue
rename to src/pages/Worker/Department/Card/DepartmentDescriptor.vue
index b219ccfe1..4b7dfd9b8 100644
--- a/src/pages/Department/Card/DepartmentDescriptor.vue
+++ b/src/pages/Worker/Department/Card/DepartmentDescriptor.vue
@@ -5,7 +5,6 @@ import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
@@ -32,15 +31,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const department = ref();
-
-const data = ref(useCardDescription());
-
-const setData = (entity) => {
-    if (!entity) return;
-    data.value = useCardDescription(entity.name, entity.id);
-};
-
 const removeDepartment = async () => {
     await axios.post(`/Departments/${entityId.value}/removeChild`, entityId.value);
     router.push({ name: 'WorkerDepartment' });
@@ -52,19 +42,10 @@ const { openConfirmationModal } = useVnConfirm();
 <template>
     <CardDescriptor
         ref="DepartmentDescriptorRef"
-        module="Department"
         :url="`Departments/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :summary="$props.summary"
         :to-module="{ name: 'WorkerDepartment' }"
-        @on-fetch="
-            (data) => {
-                department = data;
-                setData(data);
-            }
-        "
-        data-key="department"
+        data-key="Department"
     >
         <template #menu="{}">
             <QItem
@@ -74,7 +55,7 @@ const { openConfirmationModal } = useVnConfirm();
                     openConfirmationModal(
                         t('Are you sure you want to delete it?'),
                         t('Delete department'),
-                        removeDepartment
+                        removeDepartment,
                     )
                 "
             >
diff --git a/src/pages/Department/Card/DepartmentDescriptorProxy.vue b/src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue
similarity index 100%
rename from src/pages/Department/Card/DepartmentDescriptorProxy.vue
rename to src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue
diff --git a/src/pages/Department/Card/DepartmentSummary.vue b/src/pages/Worker/Department/Card/DepartmentSummary.vue
similarity index 99%
rename from src/pages/Department/Card/DepartmentSummary.vue
rename to src/pages/Worker/Department/Card/DepartmentSummary.vue
index 3d481601f..3719137e4 100644
--- a/src/pages/Department/Card/DepartmentSummary.vue
+++ b/src/pages/Worker/Department/Card/DepartmentSummary.vue
@@ -27,7 +27,7 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="DepartmentSummary"
+        data-key="Department"
         ref="summary"
         :url="`Departments/${entityId}`"
         class="full-width"
diff --git a/src/pages/Department/Card/DepartmentSummaryDialog.vue b/src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue
similarity index 100%
rename from src/pages/Department/Card/DepartmentSummaryDialog.vue
rename to src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue
diff --git a/src/pages/Worker/WorkerDepartmentTree.vue b/src/pages/Worker/WorkerDepartmentTree.vue
index 9abf4e312..9baf5ee57 100644
--- a/src/pages/Worker/WorkerDepartmentTree.vue
+++ b/src/pages/Worker/WorkerDepartmentTree.vue
@@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useState } from 'src/composables/useState';
 import { useQuasar } from 'quasar';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import CreateDepartmentChild from './CreateDepartmentChild.vue';
 import axios from 'axios';
 import { useRouter } from 'vue-router';
@@ -173,7 +173,7 @@ function handleEvent(type, event, node) {
                             color="primary"
                             flat
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             class="cursor-pointer"
                             @click.stop="showCreateNodeForm(node.id)"
                         >
diff --git a/src/pages/Zone/Card/ZoneBasicData.vue b/src/pages/Zone/Card/ZoneBasicData.vue
index cbeeff2e9..03013f011 100644
--- a/src/pages/Zone/Card/ZoneBasicData.vue
+++ b/src/pages/Zone/Card/ZoneBasicData.vue
@@ -1,5 +1,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
+import { ref } from 'vue';
+import FetchData from 'components/FetchData.vue';
 import FormModel from 'src/components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
@@ -7,10 +9,23 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
 const { t } = useI18n();
+const validAddresses = ref([]);
+const addresses = ref([]);
+
+const setFilteredAddresses = (data) => {
+    const validIds = new Set(validAddresses.value.map((item) => item.addressFk));
+    addresses.value = data.filter((address) => validIds.has(address.id));
+};
 </script>
 
 <template>
-    <FormModel :url="`Zones/${$route.params.id}`" auto-load model="zone">
+    <FetchData
+        url="RoadmapAddresses"
+        auto-load
+        @on-fetch="(data) => (validAddresses = data)"
+    />
+    <FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
+    <FormModel auto-load model="Zone">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
@@ -18,15 +33,15 @@ const { t } = useI18n();
                     :label="t('Name')"
                     clearable
                     v-model="data.name"
+                    :required="true"
                 />
             </VnRow>
-
             <VnRow>
                 <VnSelect
                     v-model="data.agencyModeFk"
                     :rules="validate('zone.agencyModeFk')"
-                     url="AgencyModes/isActive"
-                     :fields="['id', 'name']"
+                    url="AgencyModes/isActive"
+                    :fields="['id', 'name']"
                     :label="t('Agency')"
                     emit-value
                     map-options
@@ -69,7 +84,7 @@ const { t } = useI18n();
                     type="number"
                     min="0"
                 />
-                <VnInputTime v-model="data.hour" :label="t('Closing')" />
+                <VnInputTime v-model="data.hour" :label="t('Closing')" :required="true" />
             </VnRow>
 
             <VnRow>
@@ -78,7 +93,7 @@ const { t } = useI18n();
                     :label="t('Price')"
                     type="number"
                     min="0"
-                    required="true"
+                    :required="true"
                     clearable
                 />
                 <VnInput
@@ -86,7 +101,7 @@ const { t } = useI18n();
                     :label="t('Price optimum')"
                     type="number"
                     min="0"
-                    required="true"
+                    :required="true"
                     clearable
                 />
             </VnRow>
@@ -103,12 +118,14 @@ const { t } = useI18n();
                     v-model="data.addressFk"
                     option-value="id"
                     option-label="nickname"
-                    url="Addresses"
+                    :options="addresses"
                     :fields="['id', 'nickname']"
                     sort-by="id"
                     hide-selected
                     map-options
                     :rules="validate('data.addressFk')"
+                    :filter-options="['id']"
+                    :where="filterWhere"
                 />
             </VnRow>
             <VnRow>
diff --git a/src/pages/Zone/Card/ZoneCard.vue b/src/pages/Zone/Card/ZoneCard.vue
index a470cd5bd..41daff5c0 100644
--- a/src/pages/Zone/Card/ZoneCard.vue
+++ b/src/pages/Zone/Card/ZoneCard.vue
@@ -1,13 +1,12 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import { computed } from 'vue';
 
 import VnCard from 'components/common/VnCard.vue';
 import ZoneDescriptor from './ZoneDescriptor.vue';
 import ZoneFilterPanel from '../ZoneFilterPanel.vue';
+import filter from './ZoneFilter.js';
 
-const { t } = useI18n();
 const route = useRoute();
 const routeName = computed(() => route.name);
 
@@ -19,15 +18,16 @@ function notIsLocations(ifIsFalse, ifIsTrue) {
 
 <template>
     <VnCard
-        data-key="zone"
-        :base-url="notIsLocations('Zones', undefined)"
+        data-key="Zone"
+        :url="notIsLocations('Zones', undefined)"
         :descriptor="ZoneDescriptor"
+        :filter="filter"
         :filter-panel="notIsLocations(ZoneFilterPanel, undefined)"
         :search-data-key="notIsLocations('ZoneList', undefined)"
         :searchbar-props="{
             url: notIsLocations('Zones', 'ZoneLocations'),
-            label: notIsLocations(t('list.searchZone'), t('list.searchLocation')),
-            info: t('list.searchInfo'),
+            label: notIsLocations($t('list.searchZone'), $t('list.searchLocation')),
+            info: $t('list.searchInfo'),
             whereFilter: notIsLocations((value) => {
                 return /^\d+$/.test(value)
                     ? { id: value }
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index 8355c219e..27676212e 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -1,15 +1,14 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 { toTimeFormat } from 'src/filters/date';
 import { toCurrency } from 'filters/index';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
+import filter from './ZoneFilter.js';
 
 const $props = defineProps({
     id: {
@@ -20,49 +19,22 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
-
-const filter = {
-    include: [
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['name', 'id'],
-            },
-        },
-    ],
-};
-
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
 </script>
 
 <template>
-    <CardDescriptor
-        module="Zone"
-        :url="`Zones/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        :filter="filter"
-        @on-fetch="setData"
-        data-key="zoneData"
-    >
+    <CardDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
         <template #menu="{ entity }">
             <ZoneDescriptorMenuItems :zone="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('list.agency')" :value="entity.agencyMode.name" />
-            <VnLv :label="t('zone.closing')" :value="toTimeFormat(entity.hour)" />
-            <VnLv :label="t('zone.travelingDays')" :value="entity.travelingDays" />
-            <VnLv :label="t('list.price')" :value="toCurrency(entity.price)" />
-            <VnLv :label="t('zone.bonus')" :value="toCurrency(entity.bonus)" />
+            <VnLv :label="$t('list.agency')" :value="entity.agencyMode?.name" />
+            <VnLv :label="$t('zone.closing')" :value="toTimeFormat(entity.hour)" />
+            <VnLv :label="$t('zone.travelingDays')" :value="entity.travelingDays" />
+            <VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
+            <VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
         </template>
     </CardDescriptor>
 </template>
-
diff --git a/src/pages/Zone/Card/ZoneEvents.vue b/src/pages/Zone/Card/ZoneEvents.vue
index a5806bab9..1e6debd25 100644
--- a/src/pages/Zone/Card/ZoneEvents.vue
+++ b/src/pages/Zone/Card/ZoneEvents.vue
@@ -78,13 +78,13 @@ const onZoneEventFormClose = () => {
                         {
                             isNewMode: true,
                         },
-                        true
+                        true,
                     )
                 "
                 color="primary"
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('eventsInclusionForm.addEvent') }}
diff --git a/src/pages/Zone/Card/ZoneFilter.js b/src/pages/Zone/Card/ZoneFilter.js
new file mode 100644
index 000000000..3298c7c8a
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneFilter.js
@@ -0,0 +1,10 @@
+export default {
+    include: [
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['name', 'id'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Zone/Card/ZoneSearchbar.vue b/src/pages/Zone/Card/ZoneSearchbar.vue
index f7a59e97f..d1188a1e8 100644
--- a/src/pages/Zone/Card/ZoneSearchbar.vue
+++ b/src/pages/Zone/Card/ZoneSearchbar.vue
@@ -22,15 +22,50 @@ const exprBuilder = (param, value) => {
             return /^\d+$/.test(value) ? { id: value } : { name: { like: `%${value}%` } };
     }
 };
+
+const tableFilter = {
+    include: [
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'address',
+            scope: {
+                fields: ['id', 'nickname', 'provinceFk', 'postalCode'],
+                include: [
+                    {
+                        relation: 'province',
+                        scope: {
+                            fields: ['id', 'name'],
+                        },
+                    },
+                    {
+                        relation: 'postcode',
+                        scope: {
+                            fields: ['code', 'townFk'],
+                            include: {
+                                relation: 'town',
+                                scope: {
+                                    fields: ['id', 'name'],
+                                },
+                            },
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+};
 </script>
 
 <template>
     <VnSearchbar
         data-key="ZonesList"
         url="Zones"
-        :filter="{
-            include: { relation: 'agencyMode', scope: { fields: ['name'] } },
-        }"
+        :filter="tableFilter"
         :expr-builder="exprBuilder"
         :label="t('list.searchZone')"
         :info="t('list.searchInfo')"
diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
index 124802633..5b29b495b 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 filter from './ZoneFilter.js';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
 
 const route = useRoute();
@@ -26,19 +27,6 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const zoneUrl = ref();
 
-const filter = computed(() => {
-    const filter = {
-        include: {
-            relation: 'agencyMode',
-            fields: ['name'],
-        },
-        where: {
-            id: entityId,
-        },
-    };
-    return filter;
-});
-
 const columns = computed(() => [
     {
         label: t('list.name'),
@@ -72,9 +60,9 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="ZoneSummary"
+        data-key="Zone"
         ref="summary"
-        url="Zones/findOne"
+        :url="`Zones/${entityId}`"
         :filter="filter"
     >
         <template #header="{ entity }">
diff --git a/src/pages/Zone/Card/ZoneWarehouses.vue b/src/pages/Zone/Card/ZoneWarehouses.vue
index c96735697..165e9c840 100644
--- a/src/pages/Zone/Card/ZoneWarehouses.vue
+++ b/src/pages/Zone/Card/ZoneWarehouses.vue
@@ -109,7 +109,7 @@ const openCreateWarehouseForm = () => createWarehouseDialogRef.value.show();
                 icon="add"
                 color="primary"
                 @click="openCreateWarehouseForm()"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Zone/Delivery/ZoneDeliveryList.vue b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
index 975cbdb67..e3ec8cb2d 100644
--- a/src/pages/Zone/Delivery/ZoneDeliveryList.vue
+++ b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
+            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
index 5a7f0bb4c..7b5c2ddbc 100644
--- a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
+++ b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
+            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/pages/Zone/ZoneList.vue b/src/pages/Zone/ZoneList.vue
index e4a1774fe..4df84e4bd 100644
--- a/src/pages/Zone/ZoneList.vue
+++ b/src/pages/Zone/ZoneList.vue
@@ -4,7 +4,7 @@ import { useRouter } from 'vue-router';
 import { computed, ref } from 'vue';
 import axios from 'axios';
 
-import { toCurrency } from 'src/filters';
+import { dashIfEmpty, toCurrency } from 'src/filters';
 import { toTimeFormat } from 'src/filters/date';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import useNotify from 'src/composables/useNotify.js';
@@ -17,7 +17,6 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 import ZoneFilterPanel from './ZoneFilterPanel.vue';
 import ZoneSearchbar from './Card/ZoneSearchbar.vue';
-import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const router = useRouter();
@@ -26,7 +25,6 @@ const { viewSummary } = useSummaryDialog();
 const { openConfirmationModal } = useVnConfirm();
 const tableRef = ref();
 const warehouseOptions = ref([]);
-const validAddresses = ref([]);
 
 const tableFilter = {
     include: [
@@ -131,6 +129,7 @@ const columns = computed(() => [
         label: t('list.addressFk'),
         cardVisible: true,
         columnFilter: false,
+        columnClass: 'expand',
     },
     {
         align: 'right',
@@ -161,30 +160,18 @@ const handleClone = (id) => {
     openConfirmationModal(
         t('list.confirmCloneTitle'),
         t('list.confirmCloneSubtitle'),
-        () => clone(id)
+        () => clone(id),
     );
 };
 
-function showValidAddresses(row) {
-    if (row.addressFk) {
-        const isValid = validAddresses.value.some(
-            (address) => address.addressFk === row.addressFk
-        );
-        if (isValid)
-            return `${row.address?.nickname},
-            ${row.address?.postcode?.town?.name} (${row.address?.province?.name})`;
-        else return '-';
-    }
-    return '-';
+function formatRow(row) {
+    if (!row?.address) return '-';
+    return dashIfEmpty(`${row?.address?.nickname},
+            ${row?.address?.postcode?.town?.name} (${row?.address?.province?.name})`);
 }
 </script>
 
 <template>
-    <FetchData
-        url="RoadmapAddresses"
-        auto-load
-        @on-fetch="(data) => (validAddresses = data)"
-    />
     <ZoneSearchbar />
     <RightMenu>
         <template #right-panel>
@@ -207,7 +194,7 @@ function showValidAddresses(row) {
         :right-search="false"
     >
         <template #column-addressFk="{ row }">
-            {{ showValidAddresses(row) }}
+            {{ dashIfEmpty(formatRow(row)) }}
         </template>
         <template #more-create-dialog="{ data }">
             <VnSelect
diff --git a/src/router/modules/account/aliasCard.js b/src/router/modules/account/aliasCard.js
index cbbd31e51..a5b00f44b 100644
--- a/src/router/modules/account/aliasCard.js
+++ b/src/router/modules/account/aliasCard.js
@@ -3,7 +3,7 @@ export default {
     path: ':id',
     component: () => import('src/pages/Account/Alias/Card/AliasCard.vue'),
     redirect: { name: 'AliasSummary' },
-    meta: { menu: ['AliasBasicData', 'AliasUsers'] },
+    meta: { moduleName: 'Alias', menu: ['AliasBasicData', 'AliasUsers'] },
     children: [
         {
             name: 'AliasSummary',
diff --git a/src/router/modules/account/roleCard.js b/src/router/modules/account/roleCard.js
index c36ce71b9..f8100071f 100644
--- a/src/router/modules/account/roleCard.js
+++ b/src/router/modules/account/roleCard.js
@@ -4,6 +4,7 @@ export default {
     component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
     redirect: { name: 'RoleSummary' },
     meta: {
+        moduleName: 'Role',
         menu: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
     },
     children: [
diff --git a/src/router/modules/entry.js b/src/router/modules/entry.js
index f362c7653..b5656dc5f 100644
--- a/src/router/modules/entry.js
+++ b/src/router/modules/entry.js
@@ -6,13 +6,7 @@ const entryCard = {
     component: () => import('src/pages/Entry/Card/EntryCard.vue'),
     redirect: { name: 'EntrySummary' },
     meta: {
-        menu: [
-            'EntryBasicData',
-            'EntryBuys',
-            'EntryNotes',
-            'EntryDms',
-            'EntryLog',
-        ],
+        menu: ['EntryBasicData', 'EntryBuys', 'EntryNotes', 'EntryDms', 'EntryLog'],
     },
     children: [
         {
@@ -91,7 +85,7 @@ export default {
             'EntryLatestBuys',
             'EntryStockBought',
             'EntryWasteRecalc',
-        ]
+        ],
     },
     component: RouterView,
     redirect: { name: 'EntryMain' },
@@ -103,7 +97,7 @@ export default {
             redirect: { name: 'EntryIndexMain' },
             children: [
                 {
-                    path:'',
+                    path: '',
                     name: 'EntryIndexMain',
                     redirect: { name: 'EntryList' },
                     component: () => import('src/pages/Entry/EntryList.vue'),
@@ -115,6 +109,7 @@ export default {
                                 title: 'list',
                                 icon: 'view_list',
                             },
+                            component: () => import('src/pages/Entry/EntryList.vue'),
                         },
                         entryCard,
                     ],
@@ -127,7 +122,7 @@ export default {
                         icon: 'add',
                     },
                     component: () => import('src/pages/Entry/EntryCreate.vue'),
-                },                
+                },
                 {
                     path: 'my',
                     name: 'MyEntries',
@@ -167,4 +162,4 @@ export default {
             ],
         },
     ],
-};
\ No newline at end of file
+};
diff --git a/src/router/modules/route.js b/src/router/modules/route.js
index 946ad3e15..835324d20 100644
--- a/src/router/modules/route.js
+++ b/src/router/modules/route.js
@@ -160,6 +160,36 @@ const roadmapCard = {
     ],
 };
 
+const vehicleCard = {
+    path: ':id',
+    name: 'VehicleCard',
+    component: () => import('src/pages/Route/Vehicle/Card/VehicleCard.vue'),
+    redirect: { name: 'VehicleSummary' },
+    meta: {
+        menu: ['VehicleBasicData'],
+    },
+    children: [
+        {
+            name: 'VehicleSummary',
+            path: 'summary',
+            meta: {
+                title: 'summary',
+                icon: 'view_list',
+            },
+            component: () => import('src/pages/Route/Vehicle/Card/VehicleSummary.vue'),
+        },
+        {
+            name: 'VehicleBasicData',
+            path: 'basic-data',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+            },
+            component: () => import('src/pages/Route/Vehicle/Card/VehicleBasicData.vue'),
+        },
+    ],
+};
+
 export default {
     name: 'Route',
     path: '/route',
@@ -174,6 +204,7 @@ export default {
             'RouteRoadmap',
             'CmrList',
             'AgencyList',
+            'VehicleList',
         ],
     },
     component: RouterView,
@@ -280,6 +311,27 @@ export default {
                         agencyCard,
                     ],
                 },
+                {
+                    path: 'vehicle',
+                    name: 'RouteVehicle',
+                    redirect: { name: 'VehicleList' },
+                    meta: {
+                        title: 'vehicle',
+                        icon: 'directions_car',
+                    },
+                    component: () => import('src/pages/Route/Vehicle/VehicleList.vue'),
+                    children: [
+                        {
+                            path: 'list',
+                            name: 'VehicleList',
+                            meta: {
+                                title: 'vehicleList',
+                                icon: 'directions_car',
+                            },
+                        },
+                        vehicleCard,
+                    ],
+                },
             ],
         },
     ],
diff --git a/src/router/modules/shelving.js b/src/router/modules/shelving.js
index 55fb04278..c085dd8dc 100644
--- a/src/router/modules/shelving.js
+++ b/src/router/modules/shelving.js
@@ -3,7 +3,7 @@ import { RouterView } from 'vue-router';
 const parkingCard = {
     name: 'ParkingCard',
     path: ':id',
-    component: () => import('src/pages/Parking/Card/ParkingCard.vue'),
+    component: () => import('src/pages/Shelving/Parking/Card/ParkingCard.vue'),
     redirect: { name: 'ParkingSummary' },
     meta: {
         menu: ['ParkingBasicData', 'ParkingLog'],
@@ -16,7 +16,7 @@ const parkingCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () => import('src/pages/Parking/Card/ParkingSummary.vue'),
+            component: () => import('src/pages/Shelving/Parking/Card/ParkingSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -25,7 +25,8 @@ const parkingCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () => import('src/pages/Parking/Card/ParkingBasicData.vue'),
+            component: () =>
+                import('src/pages/Shelving/Parking/Card/ParkingBasicData.vue'),
         },
         {
             path: 'log',
@@ -34,7 +35,7 @@ const parkingCard = {
                 title: 'log',
                 icon: 'history',
             },
-            component: () => import('src/pages/Parking/Card/ParkingLog.vue'),
+            component: () => import('src/pages/Shelving/Parking/Card/ParkingLog.vue'),
         },
     ],
 };
@@ -127,7 +128,7 @@ export default {
                         title: 'parkingList',
                         icon: 'view_list',
                     },
-                    component: () => import('src/pages/Parking/ParkingList.vue'),
+                    component: () => import('src/pages/Shelving/Parking/ParkingList.vue'),
                     children: [
                         {
                             path: 'list',
diff --git a/src/router/modules/supplier.js b/src/router/modules/supplier.js
index 4ece4c784..19763cdf3 100644
--- a/src/router/modules/supplier.js
+++ b/src/router/modules/supplier.js
@@ -1,19 +1,12 @@
 import { RouterView } from 'vue-router';
 
-export default {
-    path: '/supplier',
-    name: 'Supplier',
+const supplierCard = {
+    name: 'SupplierCard',
+    path: ':id',
+    component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
+    redirect: { name: 'SupplierSummary' },
     meta: {
-        title: 'suppliers',
-        icon: 'vn:supplier',
-        moduleName: 'Supplier',
-        keyBinding: 'p',
-    },
-    component: RouterView,
-    redirect: { name: 'SupplierMain' },
-    menus: {
-        main: ['SupplierList'],
-        card: [
+        menu: [
             'SupplierBasicData',
             'SupplierFiscalData',
             'SupplierBillingData',
@@ -27,21 +20,165 @@ export default {
             'SupplierDms',
         ],
     },
+    children: [
+        {
+            name: 'SupplierSummary',
+            path: 'summary',
+            meta: {
+                title: 'summary',
+                icon: 'launch',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierSummary.vue'),
+        },
+        {
+            path: 'basic-data',
+            name: 'SupplierBasicData',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBasicData.vue'),
+        },
+        {
+            path: 'fiscal-data',
+            name: 'SupplierFiscalData',
+            meta: {
+                title: 'fiscalData',
+                icon: 'vn:dfiscales',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
+        },
+        {
+            path: 'billing-data',
+            name: 'SupplierBillingData',
+            meta: {
+                title: 'billingData',
+                icon: 'vn:payment',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBillingData.vue'),
+        },
+        {
+            path: 'log',
+            name: 'SupplierLog',
+            meta: {
+                title: 'log',
+                icon: 'vn:History',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
+        },
+        {
+            path: 'account',
+            name: 'SupplierAccounts',
+            meta: {
+                title: 'accounts',
+                icon: 'vn:credit',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAccounts.vue'),
+        },
+        {
+            path: 'contact',
+            name: 'SupplierContacts',
+            meta: {
+                title: 'contacts',
+                icon: 'contact_phone',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierContacts.vue'),
+        },
+        {
+            path: 'address',
+            name: 'SupplierAddresses',
+            meta: {
+                title: 'addresses',
+                icon: 'vn:delivery',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAddresses.vue'),
+        },
+        {
+            path: 'address/create',
+            name: 'SupplierAddressesCreate',
+            component: () =>
+                import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
+        },
+        {
+            path: 'balance',
+            name: 'SupplierBalance',
+            meta: {
+                title: 'balance',
+                icon: 'balance',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBalance.vue'),
+        },
+        {
+            path: 'consumption',
+            name: 'SupplierConsumption',
+            meta: {
+                title: 'consumption',
+                icon: 'show_chart',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierConsumption.vue'),
+        },
+        {
+            path: 'agency-term',
+            name: 'SupplierAgencyTerm',
+            meta: {
+                title: 'agencyTerm',
+                icon: 'vn:agency-term',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
+        },
+        {
+            path: 'dms',
+            name: 'SupplierDms',
+            meta: {
+                title: 'dms',
+                icon: 'smb_share',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
+        },
+        {
+            path: 'agency-term/create',
+            name: 'SupplierAgencyTermCreate',
+            component: () =>
+                import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
+        },
+    ],
+};
+
+export default {
+    name: 'Supplier',
+    path: '/supplier',
+    meta: {
+        title: 'suppliers',
+        icon: 'vn:supplier',
+        moduleName: 'Supplier',
+        keyBinding: 'p',
+        menu: ['SupplierList'],
+    },
+    component: RouterView,
+    redirect: { name: 'SupplierMain' },
     children: [
         {
             path: '',
             name: 'SupplierMain',
             component: () => import('src/components/common/VnModule.vue'),
-            redirect: { name: 'SupplierList' },
+            redirect: { name: 'SupplierIndexMain' },
             children: [
                 {
-                    path: 'list',
-                    name: 'SupplierList',
-                    meta: {
-                        title: 'list',
-                        icon: 'view_list',
-                    },
+                    path: '',
+                    name: 'SupplierIndexMain',
+                    redirect: { name: 'SupplierList' },
                     component: () => import('src/pages/Supplier/SupplierList.vue'),
+                    children: [
+                        {
+                            path: 'list',
+                            name: 'SupplierList',
+                            meta: {
+                                title: 'list',
+                                icon: 'view_list',
+                            },
+                        },
+                        supplierCard,
+                    ],
                 },
                 {
                     path: 'create',
@@ -54,143 +191,5 @@ export default {
                 },
             ],
         },
-        {
-            name: 'SupplierCard',
-            path: ':id',
-            component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
-            redirect: { name: 'SupplierSummary' },
-            children: [
-                {
-                    name: 'SupplierSummary',
-                    path: 'summary',
-                    meta: {
-                        title: 'summary',
-                        icon: 'launch',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierSummary.vue'),
-                },
-                {
-                    path: 'basic-data',
-                    name: 'SupplierBasicData',
-                    meta: {
-                        title: 'basicData',
-                        icon: 'vn:settings',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBasicData.vue'),
-                },
-                {
-                    path: 'fiscal-data',
-                    name: 'SupplierFiscalData',
-                    meta: {
-                        title: 'fiscalData',
-                        icon: 'vn:dfiscales',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
-                },
-                {
-                    path: 'billing-data',
-                    name: 'SupplierBillingData',
-                    meta: {
-                        title: 'billingData',
-                        icon: 'vn:payment',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBillingData.vue'),
-                },
-                {
-                    path: 'log',
-                    name: 'SupplierLog',
-                    meta: {
-                        title: 'log',
-                        icon: 'vn:History',
-                    },
-                    component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
-                },
-                {
-                    path: 'account',
-                    name: 'SupplierAccounts',
-                    meta: {
-                        title: 'accounts',
-                        icon: 'vn:credit',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAccounts.vue'),
-                },
-                {
-                    path: 'contact',
-                    name: 'SupplierContacts',
-                    meta: {
-                        title: 'contacts',
-                        icon: 'contact_phone',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierContacts.vue'),
-                },
-                {
-                    path: 'address',
-                    name: 'SupplierAddresses',
-                    meta: {
-                        title: 'addresses',
-                        icon: 'vn:delivery',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAddresses.vue'),
-                },
-                {
-                    path: 'address/create',
-                    name: 'SupplierAddressesCreate',
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
-                },
-                {
-                    path: 'balance',
-                    name: 'SupplierBalance',
-                    meta: {
-                        title: 'balance',
-                        icon: 'balance',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBalance.vue'),
-                },
-                {
-                    path: 'consumption',
-                    name: 'SupplierConsumption',
-                    meta: {
-                        title: 'consumption',
-                        icon: 'show_chart',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierConsumption.vue'),
-                },
-                {
-                    path: 'agency-term',
-                    name: 'SupplierAgencyTerm',
-                    meta: {
-                        title: 'agencyTerm',
-                        icon: 'vn:agency-term',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
-                },
-                {
-                    path: 'dms',
-                    name: 'SupplierDms',
-                    meta: {
-                        title: 'dms',
-                        icon: 'smb_share',
-                    },
-                    component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
-                },
-                {
-                    path: 'agency-term/create',
-                    name: 'SupplierAgencyTermCreate',
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
-                },
-            ],
-        },
     ],
 };
diff --git a/src/router/modules/ticket.js b/src/router/modules/ticket.js
index e5b423f64..bfcb78787 100644
--- a/src/router/modules/ticket.js
+++ b/src/router/modules/ticket.js
@@ -192,7 +192,13 @@ export default {
         icon: 'vn:ticket',
         moduleName: 'Ticket',
         keyBinding: 't',
-        menu: ['TicketList', 'TicketAdvance', 'TicketWeekly', 'TicketFuture'],
+        menu: [
+            'TicketList',
+            'TicketAdvance',
+            'TicketWeekly',
+            'TicketFuture',
+            'TicketNegative',
+        ],
     },
     component: RouterView,
     redirect: { name: 'TicketMain' },
@@ -229,6 +235,32 @@ export default {
                     },
                     component: () => import('src/pages/Ticket/TicketCreate.vue'),
                 },
+                {
+                    path: 'negative',
+                    redirect: { name: 'TicketNegative' },
+                    children: [
+                        {
+                            name: 'TicketNegative',
+                            meta: {
+                                title: 'negative',
+                                icon: 'exposure',
+                            },
+                            component: () =>
+                                import('src/pages/Ticket/Negative/TicketLackList.vue'),
+                            path: '',
+                        },
+                        {
+                            name: 'NegativeDetail',
+                            path: ':id',
+                            meta: {
+                                title: 'summary',
+                                icon: 'launch',
+                            },
+                            component: () =>
+                                import('src/pages/Ticket/Negative/TicketLackDetail.vue'),
+                        },
+                    ],
+                },
                 {
                     path: 'weekly',
                     name: 'TicketWeekly',
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index 1d013c596..3eb95a96e 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -201,9 +201,10 @@ const workerCard = {
 const departmentCard = {
     name: 'DepartmentCard',
     path: ':id',
-    component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
+    component: () => import('src/pages/Worker/Department/Card/DepartmentCard.vue'),
     redirect: { name: 'DepartmentSummary' },
     meta: {
+        moduleName: 'Department',
         menu: ['DepartmentBasicData'],
     },
     children: [
@@ -214,7 +215,8 @@ const departmentCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () => import('src/pages/Department/Card/DepartmentSummary.vue'),
+            component: () =>
+                import('src/pages/Worker/Department/Card/DepartmentSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -223,7 +225,8 @@ const departmentCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () => import('src/pages/Department/Card/DepartmentBasicData.vue'),
+            component: () =>
+                import('src/pages/Worker/Department/Card/DepartmentBasicData.vue'),
         },
     ],
 };
diff --git a/src/stores/__tests__/useNavigationStore.spec.js b/src/stores/__tests__/useNavigationStore.spec.js
new file mode 100644
index 000000000..c5df6157e
--- /dev/null
+++ b/src/stores/__tests__/useNavigationStore.spec.js
@@ -0,0 +1,153 @@
+import { setActivePinia, createPinia } from 'pinia';
+import { describe, beforeEach, afterEach, it, expect, vi, beforeAll } from 'vitest';
+import { useNavigationStore } from '../useNavigationStore';
+import axios from 'axios';
+
+let store;
+
+vi.mock('src/router/modules', () => [
+    { name: 'Item', meta: {} },
+    { name: 'Shelving', meta: {} },
+    { name: 'Order', meta: {} },
+]);
+
+vi.mock('src/filters', () => ({
+    toLowerCamel: vi.fn((name) => name.toLowerCase()),
+}));
+
+const modulesMock = [
+    {
+        name: 'Item',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'item',
+        isPinned: true,
+    },
+    {
+        name: 'Shelving',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'shelving',
+        isPinned: false,
+    },
+    {
+        name: 'Order',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'order',
+        isPinned: false,
+    },
+];
+
+const pinnedModulesMock = [
+    {
+        name: 'Item',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'item',
+        isPinned: true,
+    },
+];
+
+describe('useNavigationStore', () => {
+    beforeEach(() => {
+        setActivePinia(createPinia());
+        vi.spyOn(axios, 'get').mockResolvedValue({ data: true });
+        store = useNavigationStore();
+        store.getModules = vi.fn().mockReturnValue({
+            value: modulesMock,
+        });
+        store.getPinnedModules = vi.fn().mockReturnValue({
+            value: pinnedModulesMock,
+        });
+    });
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
+
+    it('should return modules with correct structure', () => {
+        const store = useNavigationStore();
+        const modules = store.getModules();
+
+        expect(modules.value).toEqual(modulesMock);
+    });
+
+    it('should return pinned modules', () => {
+        const store = useNavigationStore();
+        const pinnedModules = store.getPinnedModules();
+
+        expect(pinnedModules.value).toEqual(pinnedModulesMock);
+    });
+
+    it('should toggle pinned modules', () => {
+        const store = useNavigationStore();
+
+        store.togglePinned('item');
+        store.togglePinned('shelving');
+        expect(store.pinnedModules).toEqual(['item', 'shelving']);
+
+        store.togglePinned('item');
+        expect(store.pinnedModules).toEqual(['shelving']);
+    });
+
+    it('should fetch pinned modules', async () => {
+        vi.spyOn(axios, 'get').mockResolvedValue({
+            data: [{ id: 1, workerFk: 9, moduleFk: 'order', position: 1 }],
+        });
+        const store = useNavigationStore();
+        await store.fetchPinned();
+
+        expect(store.pinnedModules).toEqual(['order']);
+    });
+
+    it('should add menu item correctly', () => {
+        const store = useNavigationStore();
+        const module = 'customer';
+        const parent = [];
+        const route = {
+            name: 'customer',
+            title: 'Customer',
+            icon: 'customer',
+            meta: {
+                keyBinding: 'ctrl+shift+c',
+                name: 'customer',
+                title: 'Customer',
+                icon: 'customer',
+                menu: 'customer',
+                menuChildren: [{ name: 'customer', title: 'Customer', icon: 'customer' }],
+            },
+        };
+
+        const result = store.addMenuItem(module, route, parent);
+        const expectedItem = {
+            children: [
+                {
+                    icon: 'customer',
+                    name: 'customer',
+                    title: 'globals.pageTitles.Customer',
+                },
+            ],
+            icon: 'customer',
+            keyBinding: 'ctrl+shift+c',
+            name: 'customer',
+            title: 'globals.pageTitles.Customer',
+        };
+        expect(result).toEqual(expectedItem);
+        expect(parent.length).toBe(1);
+        expect(parent).toEqual([expectedItem]);
+    });
+
+    it('should not add menu item if condition is not met', () => {
+        const store = useNavigationStore();
+        const module = 'testModule';
+        const route = { meta: { hidden: true, menuchildren: {} } };
+        const parent = [];
+        const result = store.addMenuItem(module, route, parent);
+        expect(result).toBeUndefined();
+        expect(parent.length).toBe(0);
+    });
+});
diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js
index 8d62fdb4a..b3996d1e3 100644
--- a/src/stores/useArrayDataStore.js
+++ b/src/stores/useArrayDataStore.js
@@ -19,6 +19,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
         page: 1,
         mapKey: 'id',
         keepData: false,
+        oneRecord: false,
     };
 
     function get(key) {
diff --git a/src/utils/notifyResults.js b/src/utils/notifyResults.js
new file mode 100644
index 000000000..e87ad6c6f
--- /dev/null
+++ b/src/utils/notifyResults.js
@@ -0,0 +1,19 @@
+import { Notify } from 'quasar';
+
+export default function (results, key) {
+    results.forEach((result, index) => {
+        if (result.status === 'fulfilled') {
+            const data = JSON.parse(result.value.config.data);
+            Notify.create({
+                type: 'positive',
+                message: `Operación (${index + 1}) ${data[key]} completada con éxito.`,
+            });
+        } else {
+            const data = JSON.parse(result.reason.config.data);
+            Notify.create({
+                type: 'negative',
+                message: `Operación (${index + 1}) ${data[key]} fallida: ${result.reason.message}`,
+            });
+        }
+    });
+}
diff --git a/test/cypress/integration/Order/orderCatalog.spec.js b/test/cypress/integration/Order/orderCatalog.spec.js
index cffc47f91..1770a6b56 100644
--- a/test/cypress/integration/Order/orderCatalog.spec.js
+++ b/test/cypress/integration/Order/orderCatalog.spec.js
@@ -45,7 +45,6 @@ describe('OrderCatalog', () => {
         ).type('{enter}');
         cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
         cy.dataCy('catalogFilterValueDialogBtn').last().click();
-        cy.get('[data-cy="catalogFilterValueDialogTagSelect"]').click();
         cy.selectOption("[data-cy='catalogFilterValueDialogTagSelect']", 'Tallos');
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').focus();
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').type('2');
diff --git a/test/cypress/integration/entry/entryList.spec.js b/test/cypress/integration/entry/entryList.spec.js
new file mode 100644
index 000000000..4f99f0cb6
--- /dev/null
+++ b/test/cypress/integration/entry/entryList.spec.js
@@ -0,0 +1,224 @@
+describe('Entry', () => {
+    beforeEach(() => {
+        cy.viewport(1920, 1080);
+        cy.login('buyer');
+        cy.visit(`/#/entry/list`);
+    });
+
+    it('Filter deleted entries and other fields', () => {
+        createEntry();
+        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
+        cy.waitForElement('[data-cy="entry-buys"]');
+        deleteEntry();
+        cy.typeSearchbar('{enter}');
+        cy.get('span[title="Date"]').click().click();
+        cy.typeSearchbar('{enter}');
+        cy.url().should('include', 'order');
+        cy.get('td[data-row-index="0"][data-col-field="landed"]').should(
+            'have.text',
+            '-',
+        );
+    });
+
+    it('Create entry, modify travel and add buys', () => {
+        createEntryAndBuy();
+        cy.get('a[data-cy="EntryBasicData-menu-item"]').click();
+        selectTravel('two');
+        cy.saveCard();
+        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
+        deleteEntry();
+    });
+
+    it('Clone entry and recalculate rates', () => {
+        createEntry();
+
+        cy.waitForElement('[data-cy="entry-buys"]');
+
+        cy.url().then((previousUrl) => {
+            cy.get('[data-cy="descriptor-more-opts"]').click();
+            cy.get('div[data-cy="clone-entry"]').should('be.visible').click();
+
+            cy.get('.q-notification__message').eq(1).should('have.text', 'Entry cloned');
+
+            cy.url()
+                .should('not.eq', previousUrl)
+                .then(() => {
+                    cy.waitForElement('[data-cy="entry-buys"]');
+
+                    cy.get('[data-cy="descriptor-more-opts"]').click();
+                    cy.get('div[data-cy="recalculate-rates"]').click();
+
+                    cy.get('.q-notification__message')
+                        .eq(2)
+                        .should('have.text', 'Entry prices recalculated');
+
+                    cy.get('[data-cy="descriptor-more-opts"]').click();
+                    deleteEntry();
+
+                    cy.log(previousUrl);
+
+                    cy.visit(previousUrl);
+
+                    cy.waitForElement('[data-cy="entry-buys"]');
+                    deleteEntry();
+                });
+        });
+    });
+
+    it('Should notify when entry is lock by another user', () => {
+        const checkLockMessage = () => {
+            cy.get('[data-cy="entry-lock-confirm"]').should('be.visible');
+            cy.get('[data-cy="VnConfirm_message"] > span').should(
+                'contain.text',
+                'This entry has been locked by buyerNick',
+            );
+        };
+
+        createEntry();
+        goToEntryBuys();
+        cy.get('.q-notification__message')
+            .eq(1)
+            .should('have.text', 'The entry has been locked successfully');
+
+        cy.login('logistic');
+        cy.reload();
+        checkLockMessage();
+        cy.get('[data-cy="VnConfirm_cancel"]').click();
+        cy.url().should('include', 'summary');
+
+        goToEntryBuys();
+        checkLockMessage();
+        cy.get('[data-cy="VnConfirm_confirm"]').click();
+        cy.url().should('include', 'buys');
+
+        deleteEntry();
+    });
+
+    it('Edit buys and use toolbar actions', () => {
+        const COLORS = {
+            negative: 'rgb(251, 82, 82)',
+            positive: 'rgb(200, 228, 132)',
+            enabled: 'rgb(255, 255, 255)',
+            disable: 'rgb(168, 168, 168)',
+        };
+
+        const selectCell = (field, row = 0) =>
+            cy.get(`td[data-col-field="${field}"][data-row-index="${row}"]`);
+        const selectSpan = (field, row = 0) => selectCell(field, row).find('div > span');
+        const selectButton = (cySelector) => cy.get(`button[data-cy="${cySelector}"]`);
+        const clickAndType = (field, value, row = 0) => {
+            selectCell(field, row).click().type(`${value}{esc}`);
+        };
+        const checkText = (field, expectedText, row = 0) =>
+            selectCell(field, row).should('have.text', expectedText);
+        const checkColor = (field, expectedColor, row = 0) =>
+            selectSpan(field, row).should('have.css', 'color', expectedColor);
+
+        createEntryAndBuy();
+
+        selectCell('isIgnored').click().click().type('{esc}');
+        checkText('isIgnored', 'close');
+
+        clickAndType('stickers', '1');
+        checkText('stickers', '0/01');
+        checkText('quantity', '1');
+        checkText('amount', '50.00');
+        clickAndType('packing', '2');
+        checkText('packing', '12');
+        checkText('weight', '12.0');
+        checkText('quantity', '12');
+        checkText('amount', '600.00');
+        checkColor('packing', COLORS.enabled);
+
+        selectCell('groupingMode').click().click().click();
+        checkColor('packing', COLORS.disable);
+        checkColor('grouping', COLORS.enabled);
+
+        selectCell('buyingValue').click().clear().type('{backspace}{backspace}1');
+        checkText('amount', '12.00');
+        checkColor('minPrice', COLORS.disable);
+
+        selectCell('hasMinPrice').click().click();
+        checkColor('minPrice', COLORS.enabled);
+        selectCell('hasMinPrice').click();
+
+        cy.saveCard();
+        cy.get('span[data-cy="footer-stickers"]').should('have.text', '1');
+        cy.get('.q-notification__message').contains('Data saved');
+
+        selectButton('change-quantity-sign').should('be.disabled');
+        selectButton('check-buy-amount').should('be.disabled');
+        cy.get('tr.cursor-pointer > .q-table--col-auto-width > .q-checkbox').click();
+        selectButton('change-quantity-sign').should('be.enabled');
+        selectButton('check-buy-amount').should('be.enabled');
+
+        selectButton('change-quantity-sign').click();
+        selectButton('set-negative-quantity').click();
+        checkText('quantity', '-12');
+        selectButton('set-positive-quantity').click();
+        checkText('quantity', '12');
+        checkColor('amount', COLORS.disable);
+
+        selectButton('check-buy-amount').click();
+        selectButton('uncheck-amount').click();
+        checkColor('amount', COLORS.disable);
+
+        selectButton('check-amount').click();
+        checkColor('amount', COLORS.positive);
+        cy.saveCard();
+
+        cy.get('span[data-cy="footer-amount"]').should(
+            'have.css',
+            'color',
+            COLORS.positive,
+        );
+
+        deleteEntry();
+    });
+
+    function goToEntryBuys() {
+        const entryBuySelector = 'a[data-cy="EntryBuys-menu-item"]';
+        cy.get(entryBuySelector).should('be.visible');
+        cy.waitForElement('[data-cy="entry-buys"]');
+        cy.get(entryBuySelector).click();
+    }
+
+    function deleteEntry() {
+        cy.get('[data-cy="descriptor-more-opts"]').click();
+        cy.waitForElement('div[data-cy="delete-entry"]');
+        cy.get('div[data-cy="delete-entry"]').should('be.visible').click();
+        cy.url().should('include', 'list');
+    }
+
+    function createEntryAndBuy() {
+        createEntry();
+        createBuy();
+    }
+
+    function createEntry() {
+        cy.get('button[data-cy="vnTableCreateBtn"]').click();
+        selectTravel('one');
+        cy.get('button[data-cy="FormModelPopup_save"]').click();
+        cy.url().should('include', 'summary');
+        cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
+    }
+
+    function selectTravel(warehouse) {
+        cy.get('i[data-cy="Travel_icon"]').click();
+        cy.get('input[data-cy="Warehouse Out_select"]').type(warehouse);
+        cy.get('div[role="listbox"] > div > div[role="option"]').eq(0).click();
+        cy.get('button[data-cy="save-filter-travel-form"]').click();
+        cy.get('tr').eq(1).click();
+    }
+
+    function createBuy() {
+        cy.get('a[data-cy="EntryBuys-menu-item"]').click();
+        cy.get('a[data-cy="EntryBuys-menu-item"]').click();
+        cy.get('button[data-cy="vnTableCreateBtn"]').click();
+
+        cy.get('input[data-cy="itemFk-create-popup"]').type('1');
+        cy.get('div[role="listbox"] > div > div[role="option"]').eq(0).click();
+        cy.get('input[data-cy="Grouping mode_select"]').should('have.value', 'packing');
+        cy.get('button[data-cy="FormModelPopup_save"]').click();
+    }
+});
diff --git a/test/cypress/integration/entry/stockBought.spec.js b/test/cypress/integration/entry/stockBought.spec.js
index 078ad19cc..bc36156b4 100644
--- a/test/cypress/integration/entry/stockBought.spec.js
+++ b/test/cypress/integration/entry/stockBought.spec.js
@@ -6,6 +6,7 @@ describe('EntryStockBought', () => {
     });
     it('Should edit the reserved space', () => {
         cy.get('.q-field__native.q-placeholder').should('have.value', '01/01/2001');
+        cy.get('[data-col-field="reserve"][data-row-index="0"]').click();
         cy.get('input[name="reserve"]').type('10{enter}');
         cy.get('button[title="Save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data saved');
@@ -15,25 +16,35 @@ describe('EntryStockBought', () => {
         cy.get('input[aria-label="Reserve"]').type('1');
         cy.get('input[aria-label="Date"]').eq(1).clear();
         cy.get('input[aria-label="Date"]').eq(1).type('01-01');
-        cy.get('input[aria-label="Buyer"]').type('buyerboss{downarrow}{enter}');
+        cy.get('input[aria-label="Buyer"]').type('buyerBossNick');
+        cy.get('div[role="listbox"] > div > div[role="option"]')
+            .eq(0)
+            .should('be.visible')
+            .click();
+
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data created');
+
+        cy.get('[data-col-field="reserve"][data-row-index="1"]').click().clear();
+        cy.get('[data-cy="searchBtn"]').eq(1).click();
+        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata')
+            .should('have.text', 'warningNo data available')
+            .type('{esc}');
+        cy.get('[data-col-field="reserve"][data-row-index="1"]')
+            .click()
+            .type('{backspace}{enter}');
+        cy.get('[data-cy="crudModelDefaultSaveBtn"]').should('be.enabled').click();
+        cy.get('.q-notification__message').eq(1).should('have.text', 'Data saved');
     });
     it('Should check detail for the buyer', () => {
-        cy.get(':nth-child(1) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
+        cy.get('[data-cy="searchBtn"]').eq(0).click();
         cy.get('tBody > tr').eq(1).its('length').should('eq', 1);
     });
-    it('Should check detail for the buyerBoss and had no content', () => {
-        cy.get(':nth-child(2) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
-        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata').should(
-            'have.text',
-            'warningNo data available'
-        );
-    });
+
     it('Should edit travel m3 and refresh', () => {
-        cy.get('.vn-row > div > .q-btn > .q-btn__content > .q-icon').click();
-        cy.get('input[aria-label="m3"]').clear();
-        cy.get('input[aria-label="m3"]').type('60');
-        cy.get('.q-mt-lg > .q-btn--standard > .q-btn__content > .block').click();
+        cy.get('[data-cy="edit-travel"]').should('be.visible').click();
+        cy.get('input[aria-label="m3"]').clear().type('60');
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.vn-row > div > :nth-child(2)').should('have.text', '60');
     });
 });
diff --git a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
index 2016fca6d..11ca1bb59 100644
--- a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
@@ -1,9 +1,9 @@
 /// <reference types="cypress" />
 describe('InvoiceInBasicData', () => {
-    const formInputs = '.q-form > .q-card input';
     const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
-    const documentBtns = '[data-cy="dms-buttons"] button';
     const dialogInputs = '.q-dialog input';
+    const resetBtn = '.q-btn-group--push > .q-btn--flat';
+    const getDocumentBtns = (opt) => `[data-cy="dms-buttons"]  > :nth-child(${opt})`;
 
     beforeEach(() => {
         cy.login('developer');
@@ -11,13 +11,16 @@ describe('InvoiceInBasicData', () => {
     });
 
     it('should edit the provideer and supplier ref', () => {
-        cy.selectOption(firstFormSelect, 'Bros');
-        cy.get('[title="Reset"]').click();
-        cy.get(formInputs).eq(1).type('{selectall}4739');
-        cy.saveCard();
+        cy.dataCy('UnDeductibleVatSelect').type('4751000000');
+        cy.get('.q-menu .q-item').contains('4751000000').click();
+        cy.get(resetBtn).click();
 
-        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Plants nick');
-        cy.get(formInputs).eq(1).invoke('val').should('eq', '4739');
+        cy.waitForElement('#formModel').within(() => {
+            cy.dataCy('vnSupplierSelect').type('Bros nick');
+        })
+        cy.get('.q-menu .q-item').contains('Bros nick').click();
+        cy.saveCard();
+        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Bros nick');
     });
 
     it('should edit, remove and create the dms data', () => {
@@ -25,18 +28,18 @@ describe('InvoiceInBasicData', () => {
         const secondInput = "I don't know what posting here!";
 
         //edit
-        cy.get(documentBtns).eq(1).click();
+        cy.get(getDocumentBtns(2)).click();
         cy.get(dialogInputs).eq(0).type(`{selectall}${firtsInput}`);
         cy.get('textarea').type(`{selectall}${secondInput}`);
         cy.get('[data-cy="FormModelPopup_save"]').click();
-        cy.get(documentBtns).eq(1).click();
+        cy.get(getDocumentBtns(2)).click();
         cy.get(dialogInputs).eq(0).invoke('val').should('eq', firtsInput);
         cy.get('textarea').invoke('val').should('eq', secondInput);
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
 
         //remove
-        cy.get(documentBtns).eq(2).click();
+        cy.get(getDocumentBtns(3)).click();
         cy.get('[data-cy="VnConfirm_confirm"]').click();
         cy.checkNotification('Data saved');
 
@@ -46,7 +49,7 @@ describe('InvoiceInBasicData', () => {
             'test/cypress/fixtures/image.jpg',
             {
                 force: true,
-            }
+            },
         );
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
diff --git a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
index f8b403a45..1e7ce1003 100644
--- a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
@@ -36,7 +36,7 @@ describe('InvoiceInVat', () => {
         cy.get(dialogInputs).eq(0).type(randomInt);
         cy.get(dialogInputs).eq(1).type('This is a dummy expense');
 
-        cy.get('button[type="submit"]').click();
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data created');
     });
 });
diff --git a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
index 5f629df0b..02b7fbb43 100644
--- a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
+++ b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
@@ -7,9 +7,7 @@ describe('InvoiceOut negative bases', () => {
     });
 
     it('should filter and download as CSV', () => {
-        cy.get(
-            ':nth-child(7) > .full-width > :nth-child(1) > .column > div.q-px-xs > .q-field > .q-field__inner > .q-field__control'
-        ).type('23{enter}');
+        cy.get('input[name="ticketFk"]').type('23{enter}');
         cy.get('#subToolbar > .q-btn').click();
         cy.checkNotification('CSV downloaded successfully');
     });
diff --git a/test/cypress/integration/item/ItemProposal.spec.js b/test/cypress/integration/item/ItemProposal.spec.js
new file mode 100644
index 000000000..b3ba9f676
--- /dev/null
+++ b/test/cypress/integration/item/ItemProposal.spec.js
@@ -0,0 +1,11 @@
+/// <reference types="cypress" />
+describe('ItemProposal', () => {
+    beforeEach(() => {
+        const ticketId = 1;
+
+        cy.login('developer');
+        cy.visit(`/#/ticket/${ticketId}/summary`);
+    });
+
+    describe('Handle item proposal selected', () => {});
+});
diff --git a/test/cypress/integration/item/itemTag.spec.js b/test/cypress/integration/item/itemTag.spec.js
index 17423bc51..425eaffe6 100644
--- a/test/cypress/integration/item/itemTag.spec.js
+++ b/test/cypress/integration/item/itemTag.spec.js
@@ -16,10 +16,7 @@ describe('Item tag', () => {
         cy.dataCy(newTag).should('be.visible').click().type('Genero{enter}');
         cy.dataCy('tagGeneroValue').eq(1).should('be.visible');
         cy.dataCy(saveBtn).click();
-        cy.get('.q-notification__message').should(
-            'have.text',
-            "The tag or priority can't be repeated for an item",
-        );
+        cy.checkNotification("The tag or priority can't be repeated for an item");
     });
 
     it('should add a new tag', () => {
diff --git a/test/cypress/integration/parking/parkingBasicData.spec.js b/test/cypress/integration/parking/parkingBasicData.spec.js
index 0d130d335..f64f23ec8 100644
--- a/test/cypress/integration/parking/parkingBasicData.spec.js
+++ b/test/cypress/integration/parking/parkingBasicData.spec.js
@@ -13,11 +13,11 @@ describe('ParkingBasicData', () => {
         cy.get(sectorOpt).click();
 
         cy.get(codeInput).eq(0).clear();
-        cy.get(codeInput).eq(0).type(123);
+        cy.get(codeInput).eq(0).type('900-001');
 
         cy.saveCard();
 
         cy.get(sectorSelect).should('have.value', 'Second sector');
-        cy.get(codeInput).should('have.value', 123);
+        cy.get(codeInput).should('have.value', '900-001');
     });
 });
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index e28caea7c..82ec6626d 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -15,6 +15,7 @@ describe('AgencyWorkCenter', () => {
 
         // expect error when duplicate
         cy.get(createButton).click();
+        cy.selectOption(workCenterCombobox, 'workCenterOne');
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('This workCenter is already assigned to this agency');
         cy.get('[data-cy="FormModelPopup_cancel"]').click();
diff --git a/test/cypress/integration/route/routeList.spec.js b/test/cypress/integration/route/routeList.spec.js
index 4da43ce8e..976ce7352 100644
--- a/test/cypress/integration/route/routeList.spec.js
+++ b/test/cypress/integration/route/routeList.spec.js
@@ -4,9 +4,6 @@ describe('Route', () => {
         cy.login('developer');
         cy.visit(`/#/route/extended-list`);
     });
-    const getVnSelect =
-        '> :nth-child(1) > .column > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
-    const getRowColumn = (row, column) => `:nth-child(${row}) > :nth-child(${column})`;
 
     it('Route list create route', () => {
         cy.addBtnClick();
@@ -17,15 +14,23 @@ describe('Route', () => {
 
     it('Route list search and edit', () => {
         cy.get('#searchbar input').type('{enter}');
-        cy.get('input[name="description"]').type('routeTestOne{enter}');
+        cy.get('[data-col-field="description"][data-row-index="0"]')
+            .click()
+            .type('routeTestOne{enter}');
         cy.get('.q-table tr')
             .its('length')
             .then((rowCount) => {
                 expect(rowCount).to.be.greaterThan(0);
             });
-        cy.get(getRowColumn(1, 3) + getVnSelect).type('{downArrow}{enter}');
-        cy.get(getRowColumn(1, 4) + getVnSelect).type('{downArrow}{enter}');
-        cy.get(getRowColumn(1, 5) + getVnSelect).type('{downArrow}{enter}');
+        cy.get('[data-col-field="workerFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
+        cy.get('[data-col-field="agencyModeFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
+        cy.get('[data-col-field="vehicleFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
         cy.get('button[title="Save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data saved');
     });
diff --git a/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
new file mode 100644
index 000000000..64b9ca0a0
--- /dev/null
+++ b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
@@ -0,0 +1,13 @@
+describe('Vehicle', () => {
+    beforeEach(() => {
+        cy.viewport(1920, 1080);
+        cy.login('deliveryAssistant');
+        cy.visit(`/#/route/vehicle/7`);
+    });
+
+    it('should delete a vehicle', () => {
+        cy.openActionsDescriptor();
+        cy.get('[data-cy="delete"]').click();
+        cy.checkNotification('Vehicle removed');
+    });
+});
diff --git a/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js b/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
new file mode 100644
index 000000000..9ea1cff63
--- /dev/null
+++ b/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
@@ -0,0 +1,147 @@
+/// <reference types="cypress" />
+describe('Ticket Lack detail', () => {
+    beforeEach(() => {
+        cy.login('developer');
+        cy.intercept('GET', /\/api\/Tickets\/itemLack\/5.*$/, {
+            statusCode: 200,
+            body: [
+                {
+                    saleFk: 33,
+                    code: 'OK',
+                    ticketFk: 142,
+                    nickname: 'Malibu Point',
+                    shipped: '2000-12-31T23:00:00.000Z',
+                    hour: 0,
+                    quantity: 50,
+                    agName: 'Super-Man delivery',
+                    alertLevel: 0,
+                    stateName: 'OK',
+                    stateId: 3,
+                    itemFk: 5,
+                    price: 1.79,
+                    alertLevelCode: 'FREE',
+                    zoneFk: 9,
+                    zoneName: 'Zone superMan',
+                    theoreticalhour: '2011-11-01T22:59:00.000Z',
+                    isRookie: 1,
+                    turno: 1,
+                    peticionCompra: 1,
+                    hasObservation: 1,
+                    hasToIgnore: 1,
+                    isBasket: 1,
+                    minTimed: 0,
+                    customerId: 1104,
+                    customerName: 'Tony Stark',
+                    observationTypeCode: 'administrative',
+                },
+            ],
+        }).as('getItemLack');
+
+        cy.visit('/#/ticket/negative/5');
+        cy.wait('@getItemLack');
+    });
+    describe('Table actions', () => {
+        it.skip('should display only one row in the lack list', () => {
+            cy.location('href').should('contain', '#/ticket/negative/5');
+
+            cy.get('[data-cy="changeItem"]').should('be.disabled');
+            cy.get('[data-cy="changeState"]').should('be.disabled');
+            cy.get('[data-cy="changeQuantity"]').should('be.disabled');
+            cy.get('[data-cy="itemProposal"]').should('be.disabled');
+            cy.get('[data-cy="transferLines"]').should('be.disabled');
+            cy.get('tr.cursor-pointer > :nth-child(1)').click();
+            cy.get('[data-cy="changeItem"]').should('be.enabled');
+            cy.get('[data-cy="changeState"]').should('be.enabled');
+            cy.get('[data-cy="changeQuantity"]').should('be.enabled');
+            cy.get('[data-cy="itemProposal"]').should('be.enabled');
+            cy.get('[data-cy="transferLines"]').should('be.enabled');
+        });
+    });
+    describe('Item proposal', () => {
+        beforeEach(() => {
+            cy.get('tr.cursor-pointer > :nth-child(1)').click();
+
+            cy.intercept('GET', /\/api\/Items\/getSimilar\?.*$/, {
+                statusCode: 200,
+                body: [
+                    {
+                        id: 1,
+                        longName: 'Ranged weapon longbow 50cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 0,
+                        match6: 0,
+                        match7: 0,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 20,
+                        calc_id: 6,
+                        counter: 0,
+                        minQuantity: 1,
+                        visible: null,
+                        price2: 1,
+                    },
+                    {
+                        id: 2,
+                        longName: 'Ranged weapon longbow 100cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 0,
+                        match6: 1,
+                        match7: 0,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 50,
+                        calc_id: 6,
+                        counter: 1,
+                        minQuantity: 5,
+                        visible: null,
+                        price2: 10,
+                    },
+                    {
+                        id: 3,
+                        longName: 'Ranged weapon longbow 200cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 1,
+                        match6: 1,
+                        match7: 1,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 185,
+                        calc_id: 6,
+                        counter: 10,
+                        minQuantity: 10,
+                        visible: null,
+                        price2: 100,
+                    },
+                ],
+            }).as('getItemGetSimilar');
+            cy.get('[data-cy="itemProposal"]').click();
+            cy.wait('@getItemGetSimilar');
+        });
+        describe('Replace item if', () => {
+            it.only('Quantity is less than available', () => {
+                cy.get(':nth-child(1) > .text-right  > .q-btn').click();
+            });
+        });
+    });
+});
diff --git a/test/cypress/integration/ticket/negative/TicketLackList.spec.js b/test/cypress/integration/ticket/negative/TicketLackList.spec.js
new file mode 100644
index 000000000..01ab4f621
--- /dev/null
+++ b/test/cypress/integration/ticket/negative/TicketLackList.spec.js
@@ -0,0 +1,36 @@
+/// <reference types="cypress" />
+describe('Ticket Lack list', () => {
+    beforeEach(() => {
+        cy.login('developer');
+        cy.intercept('GET', /Tickets\/itemLack\?.*$/, {
+            statusCode: 200,
+            body: [
+                {
+                    itemFk: 5,
+                    longName: 'Ranged weapon pistol 9mm',
+                    warehouseFk: 1,
+                    producer: null,
+                    size: 15,
+                    category: null,
+                    warehouse: 'Warehouse One',
+                    lack: -50,
+                    inkFk: 'SLV',
+                    timed: '2025-01-25T22:59:00.000Z',
+                    minTimed: '23:59',
+                    originFk: 'Holand',
+                },
+            ],
+        }).as('getLack');
+
+        cy.visit('/#/ticket/negative');
+    });
+
+    describe('Table actions', () => {
+        it('should display only one row in the lack list', () => {
+            cy.wait('@getLack', { timeout: 10000 });
+
+            cy.get('.q-virtual-scroll__content > :nth-child(1) > .sticky').click();
+            cy.location('href').should('contain', '#/ticket/negative/5');
+        });
+    });
+});
diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js
index 2984a4ee4..593021e6e 100644
--- a/test/cypress/integration/ticket/ticketList.spec.js
+++ b/test/cypress/integration/ticket/ticketList.spec.js
@@ -53,4 +53,29 @@ describe('TicketList', () => {
         cy.checkNotification('Data created');
         cy.url().should('match', /\/ticket\/\d+\/summary/);
     });
+
+    it('should show the corerct problems', () => {
+        cy.intercept('GET', '**/api/Tickets/filter*', (req) => {
+            req.headers['cache-control'] = 'no-cache';
+            req.headers['pragma'] = 'no-cache';
+            req.headers['expires'] = '0';
+
+            req.on('response', (res) => {
+                delete res.headers['if-none-match'];
+                delete res.headers['if-modified-since'];
+            });
+        }).as('ticket');
+
+        cy.get('[data-cy="Warehouse_select"]').type('Warehouse Five');
+        cy.get('.q-menu .q-item').contains('Warehouse Five').click();
+        cy.wait('@ticket').then((interception) => {
+            const data = interception.response.body[1];
+            expect(data.hasComponentLack).to.equal(1);
+            expect(data.isTooLittle).to.equal(1);
+            expect(data.hasItemShortage).to.equal(1);
+        });
+        cy.get('.icon-components').should('exist');
+        cy.get('.icon-unavailable').should('exist');
+        cy.get('.icon-isTooLittle').should('exist');
+    });
 });
diff --git a/test/cypress/integration/vnComponent/VnShortcut.spec.js b/test/cypress/integration/vnComponent/VnShortcut.spec.js
index b49b4e964..e08c44635 100644
--- a/test/cypress/integration/vnComponent/VnShortcut.spec.js
+++ b/test/cypress/integration/vnComponent/VnShortcut.spec.js
@@ -28,6 +28,17 @@ describe('VnShortcuts', () => {
             });
 
             cy.url().should('include', module);
+            if (['monitor', 'claim'].includes(module)) {
+                return;
+            }
+            cy.waitForElement('.q-page').should('exist');
+            cy.dataCy('vnTableCreateBtn').should('exist');
+            cy.get('.q-page').trigger('keydown', {
+                ctrlKey: true,
+                altKey: true,
+                key: '+',
+            });
+            cy.get('#formModel').should('exist');
         });
     }
 });
diff --git a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
index 343c1c127..2cd43984a 100644
--- a/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
+++ b/test/cypress/integration/wagon/wagonType/wagonTypeCreate.spec.js
@@ -9,7 +9,7 @@ describe('WagonTypeCreate', () => {
     it('should create a new wagon type and then delete it', () => {
         cy.get('.q-page-sticky > div > .q-btn').click();
         cy.get('input').first().type('Example for testing');
-        cy.get('button[type="submit"]').click();
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('[title="Remove"] > .q-btn__content > .q-icon').first().click();
     });
 });
diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js
index 95a075fb3..70ded3f79 100644
--- a/test/cypress/integration/zone/zoneBasicData.spec.js
+++ b/test/cypress/integration/zone/zoneBasicData.spec.js
@@ -1,5 +1,6 @@
 describe('ZoneBasicData', () => {
     const priceBasicData = '[data-cy="Price_input"]';
+    const saveBtn = '.q-btn-group > .q-btn--standard';
 
     beforeEach(() => {
         cy.viewport(1280, 720);
@@ -8,20 +9,27 @@ describe('ZoneBasicData', () => {
     });
 
     it('should throw an error if the name is empty', () => {
-        cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.intercept('GET', /\/api\/Zones\/4./).as('zone');
+
+        cy.wait('@zone').then(() => {
+            cy.get('[data-cy="zone-basic-data-name"] input').type(
+                '{selectall}{backspace}',
+            );
+        });
+
+        cy.get(saveBtn).click();
         cy.checkNotification("can't be blank");
     });
 
     it('should throw an error if the price is empty', () => {
         cy.get(priceBasicData).clear();
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.get(saveBtn).click();
         cy.checkNotification('cannot be blank');
     });
 
     it("should edit the basicData's zone", () => {
         cy.get('.q-card > :nth-child(1)').type(' modified');
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.get(saveBtn).click();
         cy.checkNotification('Data saved');
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 2c93fbf84..aa4a1219e 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -87,36 +87,55 @@ Cypress.Commands.add('getValue', (selector) => {
 });
 
 // Fill Inputs
-Cypress.Commands.add('selectOption', (selector, option, timeout = 5000) => {
+Cypress.Commands.add('selectOption', (selector, option, timeout = 2500) => {
     cy.waitForElement(selector, timeout);
-    cy.get(selector).click();
-    cy.get(selector).invoke('data', 'url').as('dataUrl');
-    cy.get(selector)
-        .clear()
-        .type(option)
-        .then(() => {
-            cy.get('.q-menu', { timeout })
-                .should('be.visible') // Asegurarse de que el menú está visible
-                .and('exist') // Verificar que el menú existe
-                .then(() => {
-                    cy.get('@dataUrl').then((url) => {
-                        if (url) {
-                            // Esperar a que el menú no esté visible (desaparezca)
-                            cy.get('.q-menu').should('not.be.visible');
-                            // Ahora esperar a que el menú vuelva a aparecer
-                            cy.get('.q-menu').should('be.visible').and('exist');
-                        }
-                    });
-                });
-        });
 
-    // Finalmente, seleccionar la opción deseada
-    cy.get('.q-menu:visible') // Asegurarse de que estamos dentro del menú visible
-        .find('.q-item') // Encontrar los elementos de las opciones
-        .contains(option) // Verificar que existe una opción que contenga el texto deseado
-        .click(); // Hacer clic en la opción
+    cy.get(selector, { timeout })
+        .should('exist')
+        .should('be.visible')
+        .click()
+        .then(($el) => {
+            cy.wrap($el.is('input') ? $el : $el.find('input'))
+                .invoke('attr', 'aria-controls')
+                .then((ariaControl) => selectItem(selector, option, ariaControl));
+        });
 });
 
+function selectItem(selector, option, ariaControl, hasWrite = true) {
+    if (!hasWrite) cy.wait(100);
+
+    getItems(ariaControl).then((items) => {
+        const matchingItem = items
+            .toArray()
+            .find((item) => item.innerText.includes(option));
+        if (matchingItem) return cy.wrap(matchingItem).click();
+
+        if (hasWrite) cy.get(selector).clear().type(option, { delay: 0 });
+        return selectItem(selector, option, ariaControl, false);
+    });
+}
+
+function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) {
+    // Se intenta obtener la lista de opciones del desplegable de manera recursiva
+    return cy
+        .get('#' + ariaControl, { timeout })
+        .should('exist')
+        .find('.q-item')
+        .should('exist')
+        .then(($items) => {
+            if (!$items?.length || $items.first().text().trim() === '') {
+                if (Cypress._.now() - startTime > timeout) {
+                    throw new Error(
+                        `getItems: Tiempo de espera (${timeout}ms) excedido.`,
+                    );
+                }
+                return getItems(ariaControl, startTime, timeout);
+            }
+
+            return cy.wrap($items);
+        });
+}
+
 Cypress.Commands.add('countSelectOptions', (selector, option) => {
     cy.waitForElement(selector);
     cy.get(selector).click({ force: true });
diff --git a/test/cypress/support/waitUntil.js b/test/cypress/support/waitUntil.js
index 5fb47a2d8..359f8643f 100644
--- a/test/cypress/support/waitUntil.js
+++ b/test/cypress/support/waitUntil.js
@@ -1,7 +1,7 @@
 const waitUntil = (subject, checkFunction, originalOptions = {}) => {
     if (!(checkFunction instanceof Function)) {
         throw new Error(
-            '`checkFunction` parameter should be a function. Found: ' + checkFunction
+            '`checkFunction` parameter should be a function. Found: ' + checkFunction,
         );
     }
 

From c67ae3e17e3261692185d92861e62084cbc68b99 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 25 Feb 2025 09:53:02 +0100
Subject: [PATCH 27/28] Revert "revert
 1015acefb7e400be2d8b5958dba69b4d98276b34"

This reverts commit 223a1ea4490ea6ad2a00c60297fd3c74cd713338.
---
 cypress.config.js                             |   15 +-
 quasar.config.js                              |    1 -
 src/boot/defaults/constants.js                |    2 +
 src/boot/keyShortcut.js                       |   17 +-
 src/boot/qformMixin.js                        |   23 +-
 src/boot/quasar.js                            |    1 +
 src/components/CreateBankEntityForm.vue       |    2 +-
 src/components/CrudModel.vue                  |   16 +-
 src/components/FilterTravelForm.vue           |    4 +-
 src/components/FormModel.vue                  |   45 +-
 src/components/FormModelPopup.vue             |   50 +-
 src/components/ItemsFilterPanel.vue           |    4 +-
 src/components/LeftMenu.vue                   |   67 +-
 src/components/LeftMenuItem.vue               |    1 +
 src/components/RefundInvoiceForm.vue          |   15 +-
 src/components/TicketProblems.vue             |   82 +-
 src/components/TransferInvoiceForm.vue        |   15 +-
 src/components/VnTable/VnColumn.vue           |   51 +-
 src/components/VnTable/VnFilter.vue           |   58 +-
 src/components/VnTable/VnOrder.vue            |  101 +-
 src/components/VnTable/VnTable.vue            |  572 ++++++--
 src/components/VnTable/VnTableFilter.vue      |   57 +-
 src/components/VnTable/VnVisibleColumn.vue    |   19 +-
 src/components/__tests__/FormModel.spec.js    |   12 +-
 src/components/__tests__/Leftmenu.spec.js     |  376 ++++-
 src/components/__tests__/UserPanel.spec.js    |  100 +-
 src/components/common/VnCard.vue              |   39 +-
 src/components/common/VnCardBeta.vue          |   61 +-
 src/components/common/VnCheckbox.vue          |   43 +
 src/components/common/VnColor.vue             |   32 +
 src/components/common/VnComponent.vue         |    6 +-
 src/components/common/VnDmsList.vue           |   12 +-
 src/components/common/VnInput.vue             |   22 +-
 src/components/common/VnInputDate.vue         |    8 +-
 src/components/common/VnInputNumber.vue       |    2 +
 src/components/common/VnPopupProxy.vue        |   38 +
 src/components/common/VnSection.vue           |    9 +-
 src/components/common/VnSelect.vue            |   22 +-
 src/components/common/VnSelectCache.vue       |    4 +-
 src/components/common/VnSelectDialog.vue      |    2 -
 src/components/common/VnSelectSupplier.vue    |    6 +-
 .../common/VnSelectTravelExtended.vue         |   50 +
 .../common/__tests__/VnNotes.spec.js          |  151 +-
 src/components/ui/CardDescriptor.vue          |   46 +-
 src/components/ui/CardSummary.vue             |   14 +-
 src/components/ui/SkeletonDescriptor.vue      |   65 +-
 src/components/ui/VnConfirm.vue               |    3 +-
 src/components/ui/VnFilterPanel.vue           |   16 +-
 src/components/ui/VnMoreOptions.vue           |    2 +-
 src/components/ui/VnNotes.vue                 |   94 +-
 src/components/ui/VnStockValueDisplay.vue     |   41 +
 src/components/ui/VnSubToolbar.vue            |   11 +-
 .../ui/__tests__/CardSummary.spec.js          |   14 +-
 .../__tests__/useArrayData.spec.js            |   29 +-
 src/composables/checkEntryLock.js             |   65 +
 src/composables/getColAlign.js                |   22 +
 src/composables/useArrayData.js               |   13 +-
 src/composables/useRole.js                    |   10 +
 src/css/app.scss                              |   28 +-
 src/css/quasar.variables.scss                 |    6 +-
 src/filters/toDate.js                         |   11 +-
 src/i18n/locale/en.yml                        |  117 ++
 src/i18n/locale/es.yml                        |  225 ++-
 src/layouts/MainLayout.vue                    |    2 +-
 src/layouts/OutLayout.vue                     |    5 +-
 src/pages/Account/AccountAliasList.vue        |   10 +-
 src/pages/Account/AccountExprBuilder.js       |   18 +
 src/pages/Account/AccountList.vue             |   26 +-
 src/pages/Account/Alias/AliasExprBuilder.js   |    8 +
 src/pages/Account/Alias/Card/AliasCard.vue    |   10 +-
 .../Account/Alias/Card/AliasDescriptor.vue    |   11 +-
 src/pages/Account/Alias/Card/AliasSummary.vue |   19 +-
 src/pages/Account/Card/AccountBasicData.vue   |   38 +-
 src/pages/Account/Card/AccountCard.vue        |   10 +-
 src/pages/Account/Card/AccountDescriptor.vue  |   43 +-
 .../Account/Card/AccountDescriptorMenu.vue    |   27 +-
 src/pages/Account/Card/AccountFilter.js       |    3 +
 src/pages/Account/Card/AccountMailAlias.vue   |    7 +-
 src/pages/Account/Card/AccountSummary.vue     |   41 +-
 src/pages/Account/Role/AccountRoles.vue       |   18 +-
 src/pages/Account/Role/Card/RoleBasicData.vue |   14 +-
 src/pages/Account/Role/Card/RoleCard.vue      |    7 +-
 .../Account/Role/Card/RoleDescriptor.vue      |   16 +-
 src/pages/Account/Role/Card/RoleSummary.vue   |   23 +-
 src/pages/Account/Role/Card/SubRoles.vue      |    6 +-
 src/pages/Account/Role/RoleExprBuilder.js     |   16 +
 src/pages/Claim/Card/ClaimBasicData.vue       |    1 -
 src/pages/Claim/Card/ClaimCard.vue            |    9 +-
 src/pages/Claim/Card/ClaimDescriptor.vue      |   17 +-
 src/pages/Claim/Card/ClaimLines.vue           |    8 +-
 src/pages/Claim/Card/ClaimNotes.vue           |    3 +-
 src/pages/Claim/Card/ClaimPhoto.vue           |    4 +-
 src/pages/Claim/ClaimList.vue                 |    2 +-
 src/pages/Customer/Card/CustomerAddress.vue   |    8 +-
 src/pages/Customer/Card/CustomerBalance.vue   |    4 +-
 src/pages/Customer/Card/CustomerBasicData.vue |    4 +-
 .../Customer/Card/CustomerBillingData.vue     |    2 +-
 src/pages/Customer/Card/CustomerCard.vue      |    4 +-
 .../Customer/Card/CustomerConsumption.vue     |   95 +-
 src/pages/Customer/Card/CustomerContacts.vue  |    2 +-
 .../Customer/Card/CustomerCreditContracts.vue |    2 +-
 .../Customer/Card/CustomerDescriptor.vue      |   42 +-
 .../Customer/Card/CustomerDescriptorMenu.vue  |   17 +
 .../Customer/Card/CustomerFileManagement.vue  |    2 +-
 .../Customer/Card/CustomerFiscalData.vue      |   32 +-
 src/pages/Customer/Card/CustomerNotes.vue     |    1 +
 src/pages/Customer/Card/CustomerSamples.vue   |    2 +-
 src/pages/Customer/Card/CustomerWebAccess.vue |    2 +-
 src/pages/Customer/CustomerFilter.vue         |    6 +-
 src/pages/Customer/CustomerList.vue           |    4 +-
 .../Customer/Defaulter/CustomerDefaulter.vue  |    2 +-
 .../components/CustomerAddressEdit.vue        |    4 +-
 .../components/CustomerNewPayment.vue         |    6 +-
 .../components/CustomerSamplesCreate.vue      |    9 +-
 src/pages/Customer/locale/en.yml              |    3 +
 src/pages/Customer/locale/es.yml              |    3 +
 src/pages/Entry/Card/EntryBasicData.vue       |   63 +-
 src/pages/Entry/Card/EntryBuys.vue            | 1232 +++++++++++------
 src/pages/Entry/Card/EntryCard.vue            |    6 +-
 src/pages/Entry/Card/EntryDescriptor.vue      |  158 ++-
 src/pages/Entry/Card/EntryFilter.js           |   17 +-
 src/pages/Entry/Card/EntryNotes.vue           |    4 +-
 src/pages/Entry/Card/EntrySummary.vue         |  388 ++----
 src/pages/Entry/EntryFilter.vue               |  257 ++--
 src/pages/Entry/EntryList.vue                 |  368 +++--
 src/pages/Entry/EntryStockBought.vue          |   18 +-
 src/pages/Entry/EntryStockBoughtDetail.vue    |   22 +-
 src/pages/Entry/locale/en.yml                 |   84 +-
 src/pages/Entry/locale/es.yml                 |  107 +-
 .../InvoiceIn/Card/InvoiceInBasicData.vue     |    6 +-
 src/pages/InvoiceIn/Card/InvoiceInCard.vue    |   41 +-
 .../InvoiceIn/Card/InvoiceInDescriptor.vue    |   33 +-
 .../Card/InvoiceInDescriptorMenu.vue          |    4 +-
 src/pages/InvoiceIn/Card/InvoiceInDueDay.vue  |   26 +-
 src/pages/InvoiceIn/Card/InvoiceInFilter.js   |   33 +
 .../InvoiceIn/Card/InvoiceInIntrastat.vue     |    2 +-
 src/pages/InvoiceIn/Card/InvoiceInSummary.vue |   13 +-
 src/pages/InvoiceIn/Card/InvoiceInVat.vue     |   78 +-
 src/pages/InvoiceIn/InvoiceInList.vue         |    5 +-
 src/pages/InvoiceIn/InvoiceInToBook.vue       |   56 +-
 src/pages/InvoiceIn/locale/en.yml             |    5 +-
 src/pages/InvoiceIn/locale/es.yml             |    9 +-
 src/pages/InvoiceOut/Card/InvoiceOutCard.vue  |    4 +-
 .../InvoiceOut/Card/InvoiceOutDescriptor.vue  |   28 +-
 src/pages/InvoiceOut/Card/InvoiceOutFilter.js |   16 +
 src/pages/Item/Card/ItemBarcode.vue           |    2 +-
 src/pages/Item/Card/ItemBasicData.vue         |   42 +-
 src/pages/Item/Card/ItemBotanical.vue         |    4 +-
 src/pages/Item/Card/ItemCard.vue              |    2 +-
 src/pages/Item/Card/ItemDescriptor.vue        |   26 +-
 src/pages/Item/Card/ItemDescriptorProxy.vue   |    6 +-
 src/pages/Item/Card/ItemShelving.vue          |   10 +-
 src/pages/Item/Card/ItemTags.vue              |    2 +-
 src/pages/Item/ItemFixedPrice.vue             |   16 +-
 .../Item/ItemType/Card/ItemTypeBasicData.vue  |    7 +-
 src/pages/Item/ItemType/Card/ItemTypeCard.vue |    6 +-
 .../Item/ItemType/Card/ItemTypeDescriptor.vue |   40 +-
 .../Item/ItemType/Card/ItemTypeFilter.js      |    8 +
 .../Item/ItemType/Card/ItemTypeSummary.vue    |   15 +-
 .../{Card => components}/CreateGenusForm.vue  |    0
 .../{Card => components}/CreateSpecieForm.vue |    0
 src/pages/Item/components/ItemProposal.vue    |  332 +++++
 .../Item/components/ItemProposalProxy.vue     |   56 +
 src/pages/Item/locale/en.yml                  |   24 +-
 src/pages/Item/locale/es.yml                  |   31 +-
 src/pages/Monitor/MonitorOrders.vue           |    2 +-
 src/pages/Monitor/locale/en.yml               |    1 +
 src/pages/Monitor/locale/es.yml               |    1 +
 .../Order/Card/CatalogFilterValueDialog.vue   |    2 +-
 src/pages/Order/Card/OrderBasicData.vue       |    6 +-
 src/pages/Order/Card/OrderCard.vue            |    4 +-
 src/pages/Order/Card/OrderCatalogFilter.vue   |    4 +-
 .../Order/Card/OrderCatalogItemDialog.vue     |    8 +-
 src/pages/Order/Card/OrderDescriptor.vue      |   38 +-
 src/pages/Order/Card/OrderFilter.js           |   26 +
 src/pages/Order/Card/OrderLines.vue           |    4 +-
 src/pages/Order/Card/OrderSummary.vue         |    2 +-
 src/pages/Order/OrderList.vue                 |    7 +-
 src/pages/Route/Agency/AgencyList.vue         |    4 +-
 .../Route/Agency/Card/AgencyBasicData.vue     |    2 +-
 src/pages/Route/Agency/Card/AgencyCard.vue    |    2 +-
 .../Route/Agency/Card/AgencyDescriptor.vue    |    1 -
 .../Route/Agency/Card/AgencyWorkcenter.vue    |    2 +-
 src/pages/Route/Card/RouteCard.vue            |    5 +-
 src/pages/Route/Card/RouteDescriptor.vue      |   70 +-
 src/pages/Route/Card/RouteFilter.js           |   39 +
 src/pages/Route/Card/RouteFilter.vue          |    2 +-
 src/pages/Route/Card/RouteForm.vue            |   54 +-
 src/pages/Route/Roadmap/RoadmapBasicData.vue  |    5 +-
 src/pages/Route/Roadmap/RoadmapCard.vue       |    2 +-
 src/pages/Route/Roadmap/RoadmapDescriptor.vue |   18 +-
 src/pages/Route/Roadmap/RoadmapFilter.js      |    3 +
 src/pages/Route/Roadmap/RoadmapStops.vue      |    2 +-
 src/pages/Route/Roadmap/RoadmapSummary.vue    |    3 +-
 src/pages/Route/RouteExtendedList.vue         |  152 +-
 src/pages/Route/RouteList.vue                 |   31 +
 src/pages/Route/RouteTickets.vue              |   18 +-
 .../Route/Vehicle/Card/VehicleBasicData.vue   |  162 +++
 src/pages/Route/Vehicle/Card/VehicleCard.vue  |   13 +
 .../Route/Vehicle/Card/VehicleDescriptor.vue  |   49 +
 .../Route/Vehicle/Card/VehicleSummary.vue     |  127 ++
 src/pages/Route/Vehicle/VehicleFilter.js      |   76 +
 src/pages/Route/Vehicle/VehicleList.vue       |  224 +++
 src/pages/Route/Vehicle/locale/en.yml         |   20 +
 src/pages/Route/Vehicle/locale/es.yml         |   20 +
 src/pages/Shelving/Card/ShelvingCard.vue      |    4 +-
 .../Shelving/Card/ShelvingDescriptor.vue      |   30 +-
 src/pages/Shelving/Card/ShelvingFilter.js     |   15 +
 src/pages/Shelving/Card/ShelvingForm.vue      |   32 +-
 src/pages/Shelving/Card/ShelvingSearchbar.vue |    8 +-
 src/pages/Shelving/Card/ShelvingSummary.vue   |   37 +-
 .../Parking/Card/ParkingBasicData.vue         |   18 +-
 .../Parking/Card/ParkingCard.vue              |    6 +-
 .../Parking/Card/ParkingDescriptor.vue        |   16 +-
 .../Shelving/Parking/Card/ParkingFilter.js    |    4 +
 .../Parking/Card/ParkingLog.vue               |    0
 .../Parking/Card/ParkingSummary.vue           |    0
 .../Shelving/Parking/ParkingExprBuilder.js    |   10 +
 .../{ => Shelving}/Parking/ParkingFilter.vue  |    0
 .../{ => Shelving}/Parking/ParkingList.vue    |   13 +-
 .../{ => Shelving}/Parking/locale/en.yml      |    0
 .../{ => Shelving}/Parking/locale/es.yml      |    0
 src/pages/Shelving/ShelvingExprBuilder.js     |   10 +
 src/pages/Shelving/ShelvingList.vue           |   26 +-
 src/pages/Supplier/Card/SupplierAccounts.vue  |    6 +-
 src/pages/Supplier/Card/SupplierAddresses.vue |    2 +-
 .../Supplier/Card/SupplierAgencyTerm.vue      |    2 +-
 src/pages/Supplier/Card/SupplierBasicData.vue |    3 +-
 src/pages/Supplier/Card/SupplierCard.vue      |   16 +-
 .../Supplier/Card/SupplierConsumption.vue     |  103 +-
 src/pages/Supplier/Card/SupplierContacts.vue  |    2 +-
 .../Supplier/Card/SupplierDescriptor.vue      |   49 +-
 src/pages/Supplier/Card/SupplierFilter.js     |   35 +
 .../Supplier/Card/SupplierFiscalData.vue      |   22 +-
 src/pages/Supplier/SupplierList.vue           |   91 +-
 src/pages/Supplier/SupplierListFilter.vue     |  122 --
 .../Ticket/Card/BasicData/TicketBasicData.vue |   16 +-
 .../Card/BasicData/TicketBasicDataForm.vue    |    4 +-
 .../Card/BasicData/TicketBasicDataView.vue    |  116 +-
 src/pages/Ticket/Card/TicketCard.vue          |    8 +-
 src/pages/Ticket/Card/TicketComponents.vue    |    2 +-
 src/pages/Ticket/Card/TicketDescriptor.vue    |  139 +-
 src/pages/Ticket/Card/TicketExpedition.vue    |    2 +-
 src/pages/Ticket/Card/TicketFilter.js         |   72 +
 src/pages/Ticket/Card/TicketNotes.vue         |    4 +-
 src/pages/Ticket/Card/TicketPackage.vue       |    4 +-
 src/pages/Ticket/Card/TicketSale.vue          |   60 +-
 src/pages/Ticket/Card/TicketService.vue       |    6 +-
 src/pages/Ticket/Card/TicketSplit.vue         |   37 +
 src/pages/Ticket/Card/TicketSummary.vue       |   81 +-
 src/pages/Ticket/Card/TicketTracking.vue      |    4 +-
 src/pages/Ticket/Card/TicketTransfer.vue      |  131 +-
 src/pages/Ticket/Card/TicketTransferProxy.vue |   54 +
 src/pages/Ticket/Card/components/split.js     |   22 +
 .../Ticket/Negative/TicketLackDetail.vue      |  198 +++
 .../Ticket/Negative/TicketLackFilter.vue      |  175 +++
 src/pages/Ticket/Negative/TicketLackList.vue  |  227 +++
 src/pages/Ticket/Negative/TicketLackTable.vue |  356 +++++
 .../Negative/components/ChangeItemDialog.vue  |   90 ++
 .../components/ChangeQuantityDialog.vue       |   84 ++
 .../Negative/components/ChangeStateDialog.vue |   91 ++
 src/pages/Ticket/TicketFuture.vue             |  555 +++-----
 src/pages/Ticket/TicketFutureFilter.vue       |    4 +-
 src/pages/Ticket/locale/en.yml                |   87 +-
 src/pages/Ticket/locale/es.yml                |   83 ++
 src/pages/Travel/Card/TravelBasicData.vue     |   19 +-
 src/pages/Travel/Card/TravelCard.vue          |   36 +-
 src/pages/Travel/Card/TravelDescriptor.vue    |    1 -
 src/pages/Travel/Card/TravelFilter.js         |    1 +
 src/pages/Travel/Card/TravelSummary.vue       |    8 +
 src/pages/Travel/Card/TravelThermographs.vue  |    2 +-
 src/pages/Travel/ExtraCommunityFilter.vue     |    2 +-
 src/pages/Travel/TravelList.vue               |   24 +
 src/pages/Wagon/Card/WagonCard.vue            |    2 +-
 src/pages/Wagon/Type/WagonTypeList.vue        |    8 +-
 src/pages/Worker/Card/WorkerBasicData.vue     |   17 +-
 src/pages/Worker/Card/WorkerCalendar.vue      |   32 +-
 .../Worker/Card/WorkerCalendarFilter.vue      |    2 -
 src/pages/Worker/Card/WorkerCard.vue          |    7 +-
 src/pages/Worker/Card/WorkerDescriptor.vue    |    9 +-
 .../Worker/Card/WorkerDescriptorProxy.vue     |    7 +-
 src/pages/Worker/Card/WorkerFormation.vue     |    3 +-
 src/pages/Worker/Card/WorkerMedical.vue       |   16 +
 src/pages/Worker/Card/WorkerOperator.vue      |   19 +-
 src/pages/Worker/Card/WorkerPda.vue           |   10 +-
 src/pages/Worker/Card/WorkerPit.vue           |    2 +-
 src/pages/Worker/Card/WorkerSummary.vue       |    2 +-
 src/pages/Worker/Card/WorkerTimeControl.vue   |   16 +-
 .../Department/Card/DepartmentBasicData.vue   |   35 +-
 .../Department/Card/DepartmentCard.vue        |    4 +-
 .../Department/Card/DepartmentDescriptor.vue  |   23 +-
 .../Card/DepartmentDescriptorProxy.vue        |    0
 .../Department/Card/DepartmentSummary.vue     |    2 +-
 .../Card/DepartmentSummaryDialog.vue          |    0
 src/pages/Worker/WorkerDepartmentTree.vue     |    4 +-
 src/pages/Zone/Card/ZoneBasicData.vue         |   33 +-
 src/pages/Zone/Card/ZoneCard.vue              |   12 +-
 src/pages/Zone/Card/ZoneDescriptor.vue        |   44 +-
 src/pages/Zone/Card/ZoneEvents.vue            |    4 +-
 src/pages/Zone/Card/ZoneFilter.js             |   10 +
 src/pages/Zone/Card/ZoneSearchbar.vue         |   41 +-
 src/pages/Zone/Card/ZoneSummary.vue           |   18 +-
 src/pages/Zone/Card/ZoneWarehouses.vue        |    2 +-
 src/pages/Zone/Delivery/ZoneDeliveryList.vue  |    2 +-
 src/pages/Zone/Upcoming/ZoneUpcomingList.vue  |    2 +-
 src/router/modules/account/aliasCard.js       |    2 +-
 src/router/modules/account/roleCard.js        |    1 +
 src/router/modules/entry.js                   |   17 +-
 src/router/modules/route.js                   |   52 +
 src/router/modules/shelving.js                |   11 +-
 src/router/modules/supplier.js                |  315 +++--
 src/router/modules/ticket.js                  |   34 +-
 src/router/modules/worker.js                  |    9 +-
 .../__tests__/useNavigationStore.spec.js      |  153 ++
 src/stores/useArrayDataStore.js               |    1 +
 src/utils/notifyResults.js                    |   19 +
 .../integration/Order/orderCatalog.spec.js    |    1 -
 .../integration/entry/stockBought.spec.js     |   37 +-
 .../invoiceIn/invoiceInBasicData.spec.js      |   27 +-
 .../invoiceIn/invoiceInVat.spec.js            |    2 +-
 .../invoiceOutNegativeBases.spec.js           |    4 +-
 .../integration/item/ItemProposal.spec.js     |   11 +
 test/cypress/integration/item/itemTag.spec.js |    5 +-
 .../parking/parkingBasicData.spec.js          |    4 +-
 .../route/agency/agencyWorkCenter.spec.js     |    1 +
 .../integration/route/routeList.spec.js       |   19 +-
 .../route/vehicle/vehicleDescriptor.spec.js   |   13 +
 .../ticket/negative/TicketLackDetail.spec.js  |  147 ++
 .../ticket/negative/TicketLackList.spec.js    |   36 +
 .../integration/ticket/ticketList.spec.js     |   25 +
 .../vnComponent/VnShortcut.spec.js            |   11 +
 .../integration/zone/zoneBasicData.spec.js    |   16 +-
 test/cypress/support/commands.js              |   71 +-
 test/cypress/support/waitUntil.js             |    2 +-
 334 files changed, 9284 insertions(+), 4283 deletions(-)
 create mode 100644 src/boot/defaults/constants.js
 create mode 100644 src/components/common/VnCheckbox.vue
 create mode 100644 src/components/common/VnColor.vue
 create mode 100644 src/components/common/VnPopupProxy.vue
 create mode 100644 src/components/common/VnSelectTravelExtended.vue
 create mode 100644 src/components/ui/VnStockValueDisplay.vue
 create mode 100644 src/composables/checkEntryLock.js
 create mode 100644 src/composables/getColAlign.js
 create mode 100644 src/pages/Account/AccountExprBuilder.js
 create mode 100644 src/pages/Account/Alias/AliasExprBuilder.js
 create mode 100644 src/pages/Account/Card/AccountFilter.js
 create mode 100644 src/pages/Account/Role/RoleExprBuilder.js
 create mode 100644 src/pages/InvoiceIn/Card/InvoiceInFilter.js
 create mode 100644 src/pages/InvoiceOut/Card/InvoiceOutFilter.js
 create mode 100644 src/pages/Item/ItemType/Card/ItemTypeFilter.js
 rename src/pages/Item/{Card => components}/CreateGenusForm.vue (100%)
 rename src/pages/Item/{Card => components}/CreateSpecieForm.vue (100%)
 create mode 100644 src/pages/Item/components/ItemProposal.vue
 create mode 100644 src/pages/Item/components/ItemProposalProxy.vue
 create mode 100644 src/pages/Order/Card/OrderFilter.js
 create mode 100644 src/pages/Route/Card/RouteFilter.js
 create mode 100644 src/pages/Route/Roadmap/RoadmapFilter.js
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleBasicData.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleCard.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
 create mode 100644 src/pages/Route/Vehicle/Card/VehicleSummary.vue
 create mode 100644 src/pages/Route/Vehicle/VehicleFilter.js
 create mode 100644 src/pages/Route/Vehicle/VehicleList.vue
 create mode 100644 src/pages/Route/Vehicle/locale/en.yml
 create mode 100644 src/pages/Route/Vehicle/locale/es.yml
 create mode 100644 src/pages/Shelving/Card/ShelvingFilter.js
 rename src/pages/{ => Shelving}/Parking/Card/ParkingBasicData.vue (68%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingCard.vue (53%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingDescriptor.vue (58%)
 create mode 100644 src/pages/Shelving/Parking/Card/ParkingFilter.js
 rename src/pages/{ => Shelving}/Parking/Card/ParkingLog.vue (100%)
 rename src/pages/{ => Shelving}/Parking/Card/ParkingSummary.vue (100%)
 create mode 100644 src/pages/Shelving/Parking/ParkingExprBuilder.js
 rename src/pages/{ => Shelving}/Parking/ParkingFilter.vue (100%)
 rename src/pages/{ => Shelving}/Parking/ParkingList.vue (90%)
 rename src/pages/{ => Shelving}/Parking/locale/en.yml (100%)
 rename src/pages/{ => Shelving}/Parking/locale/es.yml (100%)
 create mode 100644 src/pages/Shelving/ShelvingExprBuilder.js
 create mode 100644 src/pages/Supplier/Card/SupplierFilter.js
 delete mode 100644 src/pages/Supplier/SupplierListFilter.vue
 create mode 100644 src/pages/Ticket/Card/TicketFilter.js
 create mode 100644 src/pages/Ticket/Card/TicketSplit.vue
 create mode 100644 src/pages/Ticket/Card/TicketTransferProxy.vue
 create mode 100644 src/pages/Ticket/Card/components/split.js
 create mode 100644 src/pages/Ticket/Negative/TicketLackDetail.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackFilter.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackList.vue
 create mode 100644 src/pages/Ticket/Negative/TicketLackTable.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeItemDialog.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
 create mode 100644 src/pages/Ticket/Negative/components/ChangeStateDialog.vue
 rename src/pages/{ => Worker}/Department/Card/DepartmentBasicData.vue (73%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentCard.vue (70%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentDescriptor.vue (84%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentDescriptorProxy.vue (100%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentSummary.vue (99%)
 rename src/pages/{ => Worker}/Department/Card/DepartmentSummaryDialog.vue (100%)
 create mode 100644 src/pages/Zone/Card/ZoneFilter.js
 create mode 100644 src/stores/__tests__/useNavigationStore.spec.js
 create mode 100644 src/utils/notifyResults.js
 create mode 100644 test/cypress/integration/item/ItemProposal.spec.js
 create mode 100644 test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
 create mode 100644 test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
 create mode 100644 test/cypress/integration/ticket/negative/TicketLackList.spec.js

diff --git a/cypress.config.js b/cypress.config.js
index dfe963a12..dd7de895c 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -39,10 +39,17 @@ export default defineConfig({
         downloadsFolder: 'test/cypress/downloads',
         video: false,
         specPattern: 'test/cypress/integration/**/*.spec.js',
-        experimentalRunAllSpecs: true,
-        watchForFileChanges: true,
-        reporter,
-        reporterOptions,
+        experimentalRunAllSpecs: false,
+        watchForFileChanges: false,
+        reporter: 'cypress-mochawesome-reporter',
+        reporterOptions: {
+            charts: true,
+            reportPageTitle: 'Cypress Inline Reporter',
+            reportFilename: '[status]_[datetime]-report',
+            embeddedScreenshots: true,
+            reportDir: 'test/cypress/reports',
+            inlineAssets: true,
+        },
         component: {
             componentFolder: 'src',
             testFiles: '**/*.spec.js',
diff --git a/quasar.config.js b/quasar.config.js
index df2cf246d..8b6125a90 100644
--- a/quasar.config.js
+++ b/quasar.config.js
@@ -31,7 +31,6 @@ export default configure(function (/* ctx */) {
         // --> boot files are part of "main.js"
         // https://v2.quasar.dev/quasar-cli/boot-files
         boot: ['i18n', 'axios', 'vnDate', 'validations', 'quasar', 'quasar.defaults'],
-
         // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
         css: ['app.scss'],
 
diff --git a/src/boot/defaults/constants.js b/src/boot/defaults/constants.js
new file mode 100644
index 000000000..c96ceb2d1
--- /dev/null
+++ b/src/boot/defaults/constants.js
@@ -0,0 +1,2 @@
+export const langs = ['en', 'es'];
+export const decimalPlaces = 2;
diff --git a/src/boot/keyShortcut.js b/src/boot/keyShortcut.js
index 5afb5b74a..6da06c8bf 100644
--- a/src/boot/keyShortcut.js
+++ b/src/boot/keyShortcut.js
@@ -1,6 +1,6 @@
 export default {
-    mounted: function (el, binding) {
-        const shortcut = binding.value ?? '+';
+    mounted(el, binding) {
+        const shortcut = binding.value || '+';
 
         const { key, ctrl, alt, callback } =
             typeof shortcut === 'string'
@@ -8,25 +8,24 @@ export default {
                       key: shortcut,
                       ctrl: true,
                       alt: true,
-                      callback: () =>
-                          document
-                              .querySelector(`button[shortcut="${shortcut}"]`)
-                              ?.click(),
+                      callback: () => el?.click(),
                   }
                 : binding.value;
 
+        if (!el.hasAttribute('shortcut')) {
+            el.setAttribute('shortcut', key);
+        }
+
         const handleKeydown = (event) => {
             if (event.key === key && (!ctrl || event.ctrlKey) && (!alt || event.altKey)) {
                 callback();
             }
         };
 
-        // Attach the event listener to the window
         window.addEventListener('keydown', handleKeydown);
-
         el._handleKeydown = handleKeydown;
     },
-    unmounted: function (el) {
+    unmounted(el) {
         if (el._handleKeydown) {
             window.removeEventListener('keydown', el._handleKeydown);
         }
diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js
index 97d80c670..182c51e47 100644
--- a/src/boot/qformMixin.js
+++ b/src/boot/qformMixin.js
@@ -9,19 +9,19 @@ export default {
         if (!form) return;
         try {
             const inputsFormCard = form.querySelectorAll(
-                `input:not([disabled]):not([type="checkbox"])`
+                `input:not([disabled]):not([type="checkbox"])`,
             );
             if (inputsFormCard.length) {
                 focusFirstInput(inputsFormCard[0]);
             }
             const textareas = document.querySelectorAll(
-                'textarea:not([disabled]), [contenteditable]:not([disabled])'
+                'textarea:not([disabled]), [contenteditable]:not([disabled])',
             );
             if (textareas.length) {
                 focusFirstInput(textareas[textareas.length - 1]);
             }
             const inputs = document.querySelectorAll(
-                'form#formModel input:not([disabled]):not([type="checkbox"])'
+                'form#formModel input:not([disabled]):not([type="checkbox"])',
             );
             const input = inputs[0];
             if (!input) return;
@@ -30,22 +30,5 @@ export default {
         } catch (error) {
             console.error(error);
         }
-        form.addEventListener('keyup', function (evt) {
-            if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
-                const input = evt.target;
-                if (input.type == 'textarea' && evt.shiftKey) {
-                    evt.preventDefault();
-                    let { selectionStart, selectionEnd } = input;
-                    input.value =
-                        input.value.substring(0, selectionStart) +
-                        '\n' +
-                        input.value.substring(selectionEnd);
-                    selectionStart = selectionEnd = selectionStart + 1;
-                    return;
-                }
-                evt.preventDefault();
-                that.onSubmit();
-            }
-        });
     },
 };
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 547517682..a8c397b83 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -51,4 +51,5 @@ export default boot(({ app }) => {
 
         await useCau(response, message);
     };
+    app.provide('app', app);
 });
diff --git a/src/components/CreateBankEntityForm.vue b/src/components/CreateBankEntityForm.vue
index 2da3aa994..7c4b94a6a 100644
--- a/src/components/CreateBankEntityForm.vue
+++ b/src/components/CreateBankEntityForm.vue
@@ -14,7 +14,7 @@ const { t } = useI18n();
 const bicInputRef = ref(null);
 const state = useState();
 
-const customer = computed(() => state.get('customer'));
+const customer = computed(() => state.get('Customer'));
 
 const countriesFilter = {
     fields: ['id', 'name', 'code'],
diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue
index d569dfda1..93a2ac96a 100644
--- a/src/components/CrudModel.vue
+++ b/src/components/CrudModel.vue
@@ -64,6 +64,10 @@ const $props = defineProps({
         type: Function,
         default: null,
     },
+    beforeSaveFn: {
+        type: Function,
+        default: null,
+    },
     goTo: {
         type: String,
         default: '',
@@ -176,7 +180,11 @@ async function saveChanges(data) {
         hasChanges.value = false;
         return;
     }
-    const changes = data || getChanges();
+    let changes = data || getChanges();
+    if ($props.beforeSaveFn) {
+        changes = await $props.beforeSaveFn(changes, getChanges);
+    }
+
     try {
         await axios.post($props.saveUrl || $props.url + '/crud', changes);
     } finally {
@@ -229,12 +237,12 @@ async function remove(data) {
                 componentProps: {
                     title: t('globals.confirmDeletion'),
                     message: t('globals.confirmDeletionMessage'),
-                    newData,
+                    data: { deletes: ids },
                     ids,
+                    promise: saveChanges,
                 },
             })
             .onOk(async () => {
-                await saveChanges({ deletes: ids });
                 newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
                 fetch(newData);
             });
@@ -374,6 +382,8 @@ watch(formUrl, async () => {
                 @click="onSubmit"
                 :disable="!hasChanges"
                 :title="t('globals.save')"
+                v-shortcut="'s'"
+                shortcut="s"
                 data-cy="crudModelDefaultSaveBtn"
             />
             <slot name="moreAfterActions" />
diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue
index 4d43c3810..765d97763 100644
--- a/src/components/FilterTravelForm.vue
+++ b/src/components/FilterTravelForm.vue
@@ -181,6 +181,7 @@ const selectTravel = ({ id }) => {
                     color="primary"
                     :disabled="isLoading"
                     :loading="isLoading"
+                    data-cy="save-filter-travel-form"
                 />
             </div>
             <QTable
@@ -191,9 +192,10 @@ const selectTravel = ({ id }) => {
                 :no-data-label="t('Enter a new search')"
                 class="q-mt-lg"
                 @row-click="(_, row) => selectTravel(row)"
+                data-cy="table-filter-travel-form"
             >
                 <template #body-cell-id="{ row }">
-                    <QTd auto-width @click.stop>
+                    <QTd auto-width @click.stop data-cy="travelFk-travel-form">
                         <QBtn flat color="blue">{{ row.id }}</QBtn>
                         <TravelDescriptorProxy :id="row.id" />
                     </QTd>
diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 19d917149..5e67a1310 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue';
+import { onMounted, onUnmounted, computed, ref, watch, nextTick, useAttrs } from 'vue';
 import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -23,6 +23,7 @@ const { validate } = useValidator();
 const { notify } = useNotify();
 const route = useRoute();
 const myForm = ref(null);
+const attrs = useAttrs();
 const $props = defineProps({
     url: {
         type: String,
@@ -85,7 +86,7 @@ const $props = defineProps({
     },
     reload: {
         type: Boolean,
-        default: false,
+        default: true,
     },
     defaultTrim: {
         type: Boolean,
@@ -106,15 +107,15 @@ const isLoading = ref(false);
 // Si elegimos observar los cambios del form significa que inicialmente las actions estaran deshabilitadas
 const isResetting = ref(false);
 const hasChanges = ref(!$props.observeFormChanges);
-const originalData = ref({});
-const formData = computed(() => state.get(modelValue));
+const originalData = computed(() => state.get(modelValue));
+const formData = ref();
 const defaultButtons = computed(() => ({
     save: {
         dataCy: 'saveDefaultBtn',
         color: 'primary',
         icon: 'save',
         label: 'globals.save',
-        click: () => myForm.value.submit(),
+        click: async () => await save(),
         type: 'submit',
     },
     reset: {
@@ -128,8 +129,6 @@ const defaultButtons = computed(() => ({
 }));
 
 onMounted(async () => {
-    originalData.value = JSON.parse(JSON.stringify($props.formInitialData ?? {}));
-
     nextTick(() => (componentIsRendered.value = true));
 
     // Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla
@@ -161,10 +160,18 @@ if (!$props.url)
         (val) => updateAndEmit('onFetch', { val }),
     );
 
+watch(
+    originalData,
+    (val) => {
+        if (val) formData.value = JSON.parse(JSON.stringify(val));
+    },
+    { immediate: true },
+);
+
 watch(
     () => [$props.url, $props.filter],
     async () => {
-        originalData.value = null;
+        state.set(modelValue, null);
         reset();
         await fetch();
     },
@@ -199,7 +206,6 @@ async function fetch() {
         updateAndEmit('onFetch', { val: data });
     } catch (e) {
         state.set(modelValue, {});
-        originalData.value = {};
         throw e;
     }
 }
@@ -242,6 +248,7 @@ async function saveAndGo() {
 }
 
 function reset() {
+    formData.value = JSON.parse(JSON.stringify(originalData.value));
     updateAndEmit('onFetch', { val: originalData.value });
     if ($props.observeFormChanges) {
         hasChanges.value = false;
@@ -266,7 +273,6 @@ function filter(value, update, filterOptions) {
 
 function updateAndEmit(evt, { val, res, old } = { val: null, res: null, old: null }) {
     state.set(modelValue, val);
-    originalData.value = val && JSON.parse(JSON.stringify(val));
     if (!$props.url) arrayData.store.data = val;
 
     emit(evt, state.get(modelValue), res, old);
@@ -301,6 +307,22 @@ async function onKeyup(evt) {
     }
 }
 
+async function onKeyup(evt) {
+    if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
+        const input = evt.target;
+        if (input.type == 'textarea' && evt.shiftKey) {
+            let { selectionStart, selectionEnd } = input;
+            input.value =
+                input.value.substring(0, selectionStart) +
+                '\n' +
+                input.value.substring(selectionEnd);
+            selectionStart = selectionEnd = selectionStart + 1;
+            return;
+        }
+        await save();
+    }
+}
+
 defineExpose({
     save,
     isLoading,
@@ -315,7 +337,8 @@ defineExpose({
         <QForm
             ref="myForm"
             v-if="formData"
-            @submit="save"
+            @submit.prevent
+            @keyup.prevent="onKeyup"
             @reset="reset"
             class="q-pa-md"
             :style="maxWidth ? 'max-width: ' + maxWidth : ''"
diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue
index afdc6efca..85943e91e 100644
--- a/src/components/FormModelPopup.vue
+++ b/src/components/FormModelPopup.vue
@@ -1,12 +1,13 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, useAttrs, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
 
 import FormModel from 'components/FormModel.vue';
 
 const emit = defineEmits(['onDataSaved', 'onDataCanceled']);
 
-defineProps({
+const props = defineProps({
     title: {
         type: String,
         default: '',
@@ -15,23 +16,41 @@ defineProps({
         type: String,
         default: '',
     },
+    showSaveAndContinueBtn: {
+        type: Boolean,
+        default: false,
+    },
 });
 
 const { t } = useI18n();
-
+const attrs = useAttrs();
+const state = useState();
 const formModelRef = ref(null);
 const closeButton = ref(null);
+const isSaveAndContinue = ref(props.showSaveAndContinueBtn);
+const isLoading = computed(() => formModelRef.value?.isLoading);
+const reset = computed(() => formModelRef.value?.reset);
 
-const onDataSaved = (formData, requestResponse) => {
-    if (closeButton.value) closeButton.value.click();
+const onDataSaved = async (formData, requestResponse) => {
+    if (!isSaveAndContinue.value) closeButton.value?.click();
+    if (isSaveAndContinue.value) {
+        await nextTick();
+        state.set(attrs.model, attrs.formInitialData);
+    }
+    isSaveAndContinue.value = props.showSaveAndContinueBtn;
     emit('onDataSaved', formData, requestResponse);
 };
 
-const isLoading = computed(() => formModelRef.value?.isLoading);
+const onClick = async (saveAndContinue) => {
+    isSaveAndContinue.value = saveAndContinue;
+    await formModelRef.value.save();
+};
 
 defineExpose({
     isLoading,
     onDataSaved,
+    isSaveAndContinue,
+    reset,
 });
 </script>
 
@@ -59,15 +78,16 @@ defineExpose({
                     flat
                     :disabled="isLoading"
                     :loading="isLoading"
-                    @click="emit('onDataCanceled')"
-                    v-close-popup
                     data-cy="FormModelPopup_cancel"
+                    v-close-popup
                     z-max
+                    @click="emit('onDataCanceled')"
                 />
                 <QBtn
+                    :flat="showSaveAndContinueBtn"
                     :label="t('globals.save')"
                     :title="t('globals.save')"
-                    type="submit"
+                    @click="onClick(false)"
                     color="primary"
                     class="q-ml-sm"
                     :disabled="isLoading"
@@ -75,6 +95,18 @@ defineExpose({
                     data-cy="FormModelPopup_save"
                     z-max
                 />
+                <QBtn
+                    v-if="showSaveAndContinueBtn"
+                    :label="t('globals.isSaveAndContinue')"
+                    :title="t('globals.isSaveAndContinue')"
+                    color="primary"
+                    class="q-ml-sm"
+                    :disabled="isLoading"
+                    :loading="isLoading"
+                    data-cy="FormModelPopup_isSaveAndContinue"
+                    z-max
+                    @click="onClick(true)"
+                />
             </div>
         </template>
     </FormModel>
diff --git a/src/components/ItemsFilterPanel.vue b/src/components/ItemsFilterPanel.vue
index 36123b834..f73753a6b 100644
--- a/src/components/ItemsFilterPanel.vue
+++ b/src/components/ItemsFilterPanel.vue
@@ -281,7 +281,7 @@ const setCategoryList = (data) => {
             <QItem class="q-mt-lg">
                 <QBtn
                     icon="add_circle"
-                    shortcut="+"
+                    v-shortcut="'+'"
                     flat
                     class="fill-icon-on-hover q-px-xs"
                     color="primary"
@@ -327,7 +327,6 @@ en:
         active: Is active
         visible: Is visible
         floramondo: Is floramondo
-        salesPersonFk: Buyer
         categoryFk: Category
 
 es:
@@ -338,7 +337,6 @@ es:
         active: Activo
         visible: Visible
         floramondo: Floramondo
-        salesPersonFk: Comprador
         categoryFk: Categoría
     Plant: Planta natural
     Flower: Flor fresca
diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index 644f831d4..9a9949499 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -41,7 +41,6 @@ const filteredItems = computed(() => {
         return locale.includes(normalizedSearch);
     });
 });
-
 const filteredPinnedModules = computed(() => {
     if (!search.value) return pinnedModules.value;
     const normalizedSearch = search.value
@@ -72,7 +71,7 @@ watch(
         items.value = [];
         getRoutes();
     },
-    { deep: true }
+    { deep: true },
 );
 
 function findMatches(search, item) {
@@ -104,33 +103,40 @@ function addChildren(module, route, parent) {
 }
 
 function getRoutes() {
-    if (props.source === 'main') {
-        const modules = Object.assign([], navigation.getModules().value);
-
-        for (const item of modules) {
-            const moduleDef = routes.find(
-                (route) => toLowerCamel(route.name) === item.module
-            );
-            if (!moduleDef) continue;
-            item.children = [];
-
-            addChildren(item.module, moduleDef, item.children);
-        }
-
-        items.value = modules;
+    const handleRoutes = {
+        main: getMainRoutes,
+        card: getCardRoutes,
+    };
+    try {
+        handleRoutes[props.source]();
+    } catch (error) {
+        throw new Error(`Method is not defined`);
     }
+}
+function getMainRoutes() {
+    const modules = Object.assign([], navigation.getModules().value);
 
-    if (props.source === 'card') {
-        const currentRoute = route.matched[1];
-        const currentModule = toLowerCamel(currentRoute.name);
-        let moduleDef = routes.find(
-            (route) => toLowerCamel(route.name) === currentModule
+    for (const item of modules) {
+        const moduleDef = routes.find(
+            (route) => toLowerCamel(route.name) === item.module,
         );
+        if (!moduleDef) continue;
+        item.children = [];
 
-        if (!moduleDef) return;
-        if (!moduleDef?.menus) moduleDef = betaGetRoutes();
-        addChildren(currentModule, moduleDef, items.value);
+        addChildren(item.module, moduleDef, item.children);
     }
+
+    items.value = modules;
+}
+
+function getCardRoutes() {
+    const currentRoute = route.matched[1];
+    const currentModule = toLowerCamel(currentRoute.name);
+    let moduleDef = routes.find((route) => toLowerCamel(route.name) === currentModule);
+
+    if (!moduleDef) return;
+    if (!moduleDef?.menus) moduleDef = betaGetRoutes();
+    addChildren(currentModule, moduleDef, items.value);
 }
 
 function betaGetRoutes() {
@@ -223,9 +229,16 @@ const searchModule = () => {
                 </template>
                 <template v-for="(item, index) in filteredItems" :key="item.name">
                     <template
-                        v-if="search ||item.children && !filteredPinnedModules.has(item.name)"
+                        v-if="
+                            search ||
+                            (item.children && !filteredPinnedModules.has(item.name))
+                        "
                     >
-                        <LeftMenuItem :item="item" group="modules" :class="search && index === 0 ? 'searched' : ''">
+                        <LeftMenuItem
+                            :item="item"
+                            group="modules"
+                            :class="search && index === 0 ? 'searched' : ''"
+                        >
                             <template #side>
                                 <QBtn
                                     v-if="item.isPinned === true"
@@ -342,7 +355,7 @@ const searchModule = () => {
 .header {
     color: var(--vn-label-color);
 }
-.searched{
+.searched {
     background-color: var(--vn-section-hover-color);
 }
 </style>
diff --git a/src/components/LeftMenuItem.vue b/src/components/LeftMenuItem.vue
index a3112b17f..c0cee44fe 100644
--- a/src/components/LeftMenuItem.vue
+++ b/src/components/LeftMenuItem.vue
@@ -26,6 +26,7 @@ const itemComputed = computed(() => {
         :to="{ name: itemComputed.name }"
         clickable
         v-ripple
+        :data-cy="`${itemComputed.name}-menu-item`"
     >
         <QItemSection avatar v-if="itemComputed.icon">
             <QIcon :name="itemComputed.icon" />
diff --git a/src/components/RefundInvoiceForm.vue b/src/components/RefundInvoiceForm.vue
index 590acede0..6dcb8b390 100644
--- a/src/components/RefundInvoiceForm.vue
+++ b/src/components/RefundInvoiceForm.vue
@@ -9,6 +9,7 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -131,15 +132,11 @@ const refund = async () => {
                         :required="true"
                     /> </VnRow
                 ><VnRow>
-                    <div>
-                        <QCheckbox
-                            :label="t('Inherit warehouse')"
-                            v-model="invoiceParams.inheritWarehouse"
-                        />
-                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                            <QTooltip>{{ t('Inherit warehouse tooltip') }}</QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="invoiceParams.inheritWarehouse"
+                        :label="t('Inherit warehouse')"
+                        :info="t('Inherit warehouse tooltip')"
+                    />
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue
index 934b13a1c..783f2556f 100644
--- a/src/components/TicketProblems.vue
+++ b/src/components/TicketProblems.vue
@@ -4,26 +4,21 @@ import { toCurrency } from 'src/filters';
 defineProps({ row: { type: Object, required: true } });
 </script>
 <template>
-    <span>
-        <QIcon
-            v-if="row.isTaxDataChecked === 0"
-            name="vn:no036"
-            color="primary"
-            size="xs"
+    <span class="q-gutter-x-xs">
+        <router-link
+            v-if="row.claim?.claimFk"
+            :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
+            class="link"
         >
-            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.hasTicketRequest" name="vn:buyrequest" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.itemShortage" name="vn:unavailable" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
-        </QIcon>
-        <QIcon v-if="row.isFreezed" name="vn:frozen" color="primary" size="xs">
-            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
-        </QIcon>
+            <QIcon name="vn:claims" size="xs">
+                <QTooltip>
+                    {{ t('ticketSale.claim') }}:
+                    {{ row.claim?.claimFk }}
+                </QTooltip>
+            </QIcon>
+        </router-link>
         <QIcon
-            v-if="row.risk"
+            v-if="row?.risk"
             name="vn:risk"
             :color="row.hasHighRisk ? 'negative' : 'primary'"
             size="xs"
@@ -33,10 +28,57 @@ defineProps({ row: { type: Object, required: true } });
                 {{ toCurrency(row.risk - row.credit) }}
             </QTooltip>
         </QIcon>
-        <QIcon v-if="row.hasComponentLack" name="vn:components" color="primary" size="xs">
+        <QIcon
+            v-if="row?.hasComponentLack"
+            name="vn:components"
+            color="primary"
+            size="xs"
+        >
             <QTooltip>{{ $t('salesTicketsTable.componentLack') }}</QTooltip>
         </QIcon>
-        <QIcon v-if="row.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
+        <QIcon v-if="row?.hasItemDelay" color="primary" size="xs" name="vn:hasItemDelay">
+            <QTooltip>
+                {{ $t('ticket.summary.hasItemDelay') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.hasItemLost" color="primary" size="xs" name="vn:hasItemLost">
+            <QTooltip>
+                {{ $t('salesTicketsTable.hasItemLost') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.hasItemShortage"
+            name="vn:unavailable"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.notVisible') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.hasRounding" color="primary" name="sync_problem" size="xs">
+            <QTooltip>
+                {{ $t('ticketList.rounding') }}
+            </QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.hasTicketRequest"
+            name="vn:buyrequest"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.purchaseRequest') }}</QTooltip>
+        </QIcon>
+        <QIcon
+            v-if="row?.isTaxDataChecked !== 0"
+            name="vn:no036"
+            color="primary"
+            size="xs"
+        >
+            <QTooltip>{{ $t('salesTicketsTable.noVerifiedData') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.isFreezed" name="vn:frozen" color="primary" size="xs">
+            <QTooltip>{{ $t('salesTicketsTable.clientFrozen') }}</QTooltip>
+        </QIcon>
+        <QIcon v-if="row?.isTooLittle" name="vn:isTooLittle" color="primary" size="xs">
             <QTooltip>{{ $t('salesTicketsTable.tooLittle') }}</QTooltip>
         </QIcon>
     </span>
diff --git a/src/components/TransferInvoiceForm.vue b/src/components/TransferInvoiceForm.vue
index aa71070d6..c4ef1454a 100644
--- a/src/components/TransferInvoiceForm.vue
+++ b/src/components/TransferInvoiceForm.vue
@@ -10,6 +10,7 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FormPopup from './FormPopup.vue';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import VnCheckbox from './common/VnCheckbox.vue';
 
 const $props = defineProps({
     invoiceOutData: {
@@ -186,15 +187,11 @@ const makeInvoice = async () => {
                     />
                 </VnRow>
                 <VnRow>
-                    <div>
-                        <QCheckbox
-                            :label="t('Bill destination client')"
-                            v-model="checked"
-                        />
-                        <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                            <QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="checked"
+                        :label="t('Bill destination client')"
+                        :info="t('transferInvoiceInfo')"
+                    />
                 </VnRow>
             </template>
         </FormPopup>
diff --git a/src/components/VnTable/VnColumn.vue b/src/components/VnTable/VnColumn.vue
index 9e9bfad69..d0e245388 100644
--- a/src/components/VnTable/VnColumn.vue
+++ b/src/components/VnTable/VnColumn.vue
@@ -1,9 +1,8 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QIcon, QCheckbox } from 'quasar';
+import { QIcon, QToggle } from 'quasar';
 import { dashIfEmpty } from 'src/filters';
 
-/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnSelectCache from 'components/common/VnSelectCache.vue';
 import VnInput from 'components/common/VnInput.vue';
@@ -12,8 +11,11 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
 import VnComponent from 'components/common/VnComponent.vue';
 import VnUserLink from 'components/ui/VnUserLink.vue';
+import VnSelectEnum from '../common/VnSelectEnum.vue';
+import VnCheckbox from '../common/VnCheckbox.vue';
 
 const model = defineModel(undefined, { required: true });
+const emit = defineEmits(['blur']);
 const $props = defineProps({
     column: {
         type: Object,
@@ -39,10 +41,18 @@ const $props = defineProps({
         type: Object,
         default: null,
     },
+    autofocus: {
+        type: Boolean,
+        default: false,
+    },
     showLabel: {
         type: Boolean,
         default: null,
     },
+    eventHandlers: {
+        type: Object,
+        default: null,
+    },
 });
 
 const defaultSelect = {
@@ -99,7 +109,8 @@ const defaultComponents = {
         },
     },
     checkbox: {
-        component: markRaw(QCheckbox),
+        ref: 'checkbox',
+        component: markRaw(VnCheckbox),
         attrs: ({ model }) => {
             const defaultAttrs = {
                 disable: !$props.isEditable,
@@ -115,6 +126,10 @@ const defaultComponents = {
         },
         forceAttrs: {
             label: $props.showLabel && $props.column.label,
+            autofocus: true,
+        },
+        events: {
+            blur: () => emit('blur'),
         },
     },
     select: {
@@ -125,12 +140,19 @@ const defaultComponents = {
         component: markRaw(VnSelect),
         ...defaultSelect,
     },
+    selectEnum: {
+        component: markRaw(VnSelectEnum),
+        ...defaultSelect,
+    },
     icon: {
         component: markRaw(QIcon),
     },
     userLink: {
         component: markRaw(VnUserLink),
     },
+    toggle: {
+        component: markRaw(QToggle),
+    },
 };
 
 const value = computed(() => {
@@ -160,7 +182,28 @@ const col = computed(() => {
     return newColumn;
 });
 
-const components = computed(() => $props.components ?? defaultComponents);
+const components = computed(() => {
+    const sourceComponents = $props.components ?? defaultComponents;
+
+    return Object.keys(sourceComponents).reduce((acc, key) => {
+        const component = sourceComponents[key];
+
+        if (!component || typeof component !== 'object') {
+            acc[key] = component;
+            return acc;
+        }
+
+        acc[key] = {
+            ...component,
+            attrs: {
+                ...(component.attrs || {}),
+                autofocus: $props.autofocus,
+            },
+            event: { ...component?.event, ...$props?.eventHandlers },
+        };
+        return acc;
+    }, {});
+});
 </script>
 <template>
     <div class="row no-wrap">
diff --git a/src/components/VnTable/VnFilter.vue b/src/components/VnTable/VnFilter.vue
index 426f5c716..0de3834ea 100644
--- a/src/components/VnTable/VnFilter.vue
+++ b/src/components/VnTable/VnFilter.vue
@@ -1,14 +1,12 @@
 <script setup>
 import { markRaw, computed } from 'vue';
-import { QCheckbox } from 'quasar';
+import { QCheckbox, QToggle } from 'quasar';
 import { useArrayData } from 'composables/useArrayData';
-
-/* basic input */
 import VnSelect from 'components/common/VnSelect.vue';
 import VnInput from 'components/common/VnInput.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInputTime from 'components/common/VnInputTime.vue';
-import VnTableColumn from 'components/VnTable/VnColumn.vue';
+import VnColumn from 'components/VnTable/VnColumn.vue';
 
 const $props = defineProps({
     column: {
@@ -27,6 +25,10 @@ const $props = defineProps({
         type: String,
         default: 'table',
     },
+    customClass: {
+        type: String,
+        default: '',
+    },
 });
 
 defineExpose({ addFilter, props: $props });
@@ -34,7 +36,7 @@ defineExpose({ addFilter, props: $props });
 const model = defineModel(undefined, { required: true });
 const arrayData = useArrayData(
     $props.dataKey,
-    $props.searchUrl ? { searchUrl: $props.searchUrl } : null
+    $props.searchUrl ? { searchUrl: $props.searchUrl } : null,
 );
 const columnFilter = computed(() => $props.column?.columnFilter);
 
@@ -46,19 +48,18 @@ const enterEvent = {
 
 const defaultAttrs = {
     filled: !$props.showTitle,
-    class: 'q-px-xs q-pb-xs q-pt-none fit',
     dense: true,
 };
 
 const forceAttrs = {
-    label: $props.showTitle ? '' : columnFilter.value?.label ?? $props.column.label,
+    label: $props.showTitle ? '' : (columnFilter.value?.label ?? $props.column.label),
 };
 
 const selectComponent = {
     component: markRaw(VnSelect),
     event: updateEvent,
     attrs: {
-        class: 'q-px-sm q-pb-xs q-pt-none fit',
+        class: `q-pt-none fit ${$props.customClass}`,
         dense: true,
         filled: !$props.showTitle,
     },
@@ -109,14 +110,24 @@ const components = {
         component: markRaw(QCheckbox),
         event: updateEvent,
         attrs: {
-            dense: true,
-            class: $props.showTitle ? 'q-py-sm q-mt-md' : 'q-px-md q-py-xs fit',
+            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
             'toggle-indeterminate': true,
+            size: 'sm',
         },
         forceAttrs,
     },
     select: selectComponent,
     rawSelect: selectComponent,
+    toggle: {
+        component: markRaw(QToggle),
+        event: updateEvent,
+        attrs: {
+            class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
+            'toggle-indeterminate': true,
+            size: 'sm',
+        },
+        forceAttrs,
+    },
 };
 
 async function addFilter(value, name) {
@@ -132,19 +143,8 @@ async function addFilter(value, name) {
     await arrayData.addFilter({ params: { [field]: value } });
 }
 
-function alignRow() {
-    switch ($props.column.align) {
-        case 'left':
-            return 'justify-start items-start';
-        case 'right':
-            return 'justify-end items-end';
-        default:
-            return 'flex-center';
-    }
-}
-
 const showFilter = computed(
-    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions'
+    () => $props.column?.columnFilter !== false && $props.column.name != 'tableActions',
 );
 
 const onTabPressed = async () => {
@@ -152,13 +152,8 @@ const onTabPressed = async () => {
 };
 </script>
 <template>
-    <div
-        v-if="showFilter"
-        class="full-width"
-        :class="alignRow()"
-        style="max-height: 45px; overflow: hidden"
-    >
-        <VnTableColumn
+    <div v-if="showFilter" class="full-width" style="overflow: hidden">
+        <VnColumn
             :column="$props.column"
             default="input"
             v-model="model"
@@ -168,3 +163,8 @@ const onTabPressed = async () => {
         />
     </div>
 </template>
+<style lang="scss" scoped>
+label.vn-label-padding > .q-field__inner > .q-field__control {
+    padding: inherit !important;
+}
+</style>
diff --git a/src/components/VnTable/VnOrder.vue b/src/components/VnTable/VnOrder.vue
index 8ffdfe2bc..47ed9acf4 100644
--- a/src/components/VnTable/VnOrder.vue
+++ b/src/components/VnTable/VnOrder.vue
@@ -23,6 +23,10 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    align: {
+        type: String,
+        default: 'end',
+    },
 });
 const hover = ref();
 const arrayData = useArrayData($props.dataKey, { searchUrl: $props.searchUrl });
@@ -41,55 +45,78 @@ async function orderBy(name, direction) {
             break;
     }
     if (!direction) return await arrayData.deleteOrder(name);
+
     await arrayData.addOrder(name, direction);
 }
 
 defineExpose({ orderBy });
+
+function textAlignToFlex(textAlign) {
+    return `justify-content: ${
+        {
+            'text-center': 'center',
+            'text-left': 'start',
+            'text-right': 'end',
+        }[textAlign] || 'start'
+    };`;
+}
 </script>
 <template>
     <div
         @mouseenter="hover = true"
         @mouseleave="hover = false"
         @click="orderBy(name, model?.direction)"
-        class="row items-center no-wrap cursor-pointer"
+        class="items-center no-wrap cursor-pointer title"
+        :style="textAlignToFlex(align)"
     >
         <span :title="label">{{ label }}</span>
-        <QChip
-            v-if="name"
-            :label="!vertical ? model?.index : ''"
-            :icon="
-                (model?.index || hover) && !vertical
-                    ? model?.direction == 'DESC'
-                        ? 'arrow_downward'
-                        : 'arrow_upward'
-                    : undefined
-            "
-            :size="vertical ? '' : 'sm'"
-            :class="[
-                model?.index ? 'color-vn-text' : 'bg-transparent',
-                vertical ? 'q-px-none' : '',
-            ]"
-            class="no-box-shadow"
-            :clickable="true"
-            style="min-width: 40px"
-        >
-            <div
-                class="column flex-center"
-                v-if="vertical"
-                :style="!model?.index && 'color: #5d5d5d'"
+        <div v-if="name && model?.index">
+            <QChip
+                :label="!vertical ? model?.index : ''"
+                :icon="
+                    (model?.index || hover) && !vertical
+                        ? model?.direction == 'DESC'
+                            ? 'arrow_downward'
+                            : 'arrow_upward'
+                        : undefined
+                "
+                :size="vertical ? '' : 'sm'"
+                :class="[
+                    model?.index ? 'color-vn-text' : 'bg-transparent',
+                    vertical ? 'q-px-none' : '',
+                ]"
+                class="no-box-shadow"
+                :clickable="true"
+                style="min-width: 40px; max-height: 30px"
             >
-                {{ model?.index }}
-                <QIcon
-                    :name="
-                        model?.index
-                            ? model?.direction == 'DESC'
-                                ? 'arrow_downward'
-                                : 'arrow_upward'
-                            : 'swap_vert'
-                    "
-                    size="xs"
-                />
-            </div>
-        </QChip>
+                <div
+                    class="column flex-center"
+                    v-if="vertical"
+                    :style="!model?.index && 'color: #5d5d5d'"
+                >
+                    {{ model?.index }}
+                    <QIcon
+                        :name="
+                            model?.index
+                                ? model?.direction == 'DESC'
+                                    ? 'arrow_downward'
+                                    : 'arrow_upward'
+                                : 'swap_vert'
+                        "
+                        size="xs"
+                    />
+                </div>
+            </QChip>
+        </div>
     </div>
 </template>
+<style lang="scss" scoped>
+.title {
+    display: flex;
+    align-items: center;
+    height: 30px;
+    width: 100%;
+    color: var(--vn-label-color);
+    white-space: nowrap;
+}
+</style>
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 532c89456..d67d157c2 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -1,22 +1,38 @@
 <script setup>
-import { ref, onBeforeMount, onMounted, computed, watch, useAttrs } from 'vue';
+import {
+    ref,
+    onBeforeMount,
+    onMounted,
+    onUnmounted,
+    computed,
+    watch,
+    h,
+    render,
+    inject,
+    useAttrs,
+    nextTick,
+} from 'vue';
+import { useArrayData } from 'src/composables/useArrayData';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
-import { useQuasar } from 'quasar';
+import { useQuasar, date } from 'quasar';
 import { useStateStore } from 'stores/useStateStore';
 import { useFilterParams } from 'src/composables/useFilterParams';
+import { dashIfEmpty, toDate } from 'src/filters';
 
 import CrudModel from 'src/components/CrudModel.vue';
 import FormModelPopup from 'components/FormModelPopup.vue';
 
-import VnTableColumn from 'components/VnTable/VnColumn.vue';
+import VnColumn from 'components/VnTable/VnColumn.vue';
 import VnFilter from 'components/VnTable/VnFilter.vue';
 import VnTableChip from 'components/VnTable/VnChip.vue';
 import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
 import VnTableFilter from './VnTableFilter.vue';
+import { getColAlign } from 'src/composables/getColAlign';
 
+const arrayData = useArrayData(useAttrs()['data-key']);
 const $props = defineProps({
     columns: {
         type: Array,
@@ -42,10 +58,6 @@ const $props = defineProps({
         type: [Function, Boolean],
         default: null,
     },
-    rowCtrlClick: {
-        type: [Function, Boolean],
-        default: null,
-    },
     redirect: {
         type: String,
         default: null,
@@ -114,7 +126,19 @@ const $props = defineProps({
         type: Boolean,
         default: false,
     },
+    withFilters: {
+        type: Boolean,
+        default: true,
+    },
+    overlay: {
+        type: Boolean,
+        default: false,
+    },
+    createComplement: {
+        type: Object,
+    },
 });
+
 const { t } = useI18n();
 const stateStore = useStateStore();
 const route = useRoute();
@@ -132,10 +156,18 @@ const showForm = ref(false);
 const splittedColumns = ref({ columns: [] });
 const columnsVisibilitySkipped = ref();
 const createForm = ref();
+const createRef = ref(null);
 const tableRef = ref();
 const params = ref(useFilterParams($attrs['data-key']).params);
 const orders = ref(useFilterParams($attrs['data-key']).orders);
+const app = inject('app');
 
+const editingRow = ref(null);
+const editingField = ref(null);
+const isTableMode = computed(() => mode.value == TABLE_MODE);
+const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
+const selectRegex = /select/;
+const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
 const tableModes = [
     {
         icon: 'view_column',
@@ -156,7 +188,8 @@ onBeforeMount(() => {
     hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
 });
 
-onMounted(() => {
+onMounted(async () => {
+    if ($props.isEditable) document.addEventListener('click', clickHandler);
     mode.value =
         quasar.platform.is.mobile && !$props.disableOption?.card
             ? CARD_MODE
@@ -178,14 +211,25 @@ onMounted(() => {
     }
 });
 
+onUnmounted(async () => {
+    if ($props.isEditable) document.removeEventListener('click', clickHandler);
+});
+
 watch(
     () => $props.columns,
     (value) => splitColumns(value),
     { immediate: true },
 );
 
-const isTableMode = computed(() => mode.value == TABLE_MODE);
-const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
+defineExpose({
+    create: createForm,
+    reload,
+    redirect: redirectFn,
+    selected,
+    CrudModelRef,
+    params,
+    tableRef,
+});
 
 function splitColumns(columns) {
     splittedColumns.value = {
@@ -231,16 +275,6 @@ const rowClickFunction = computed(() => {
     return () => {};
 });
 
-const rowCtrlClickFunction = computed(() => {
-    if ($props.rowCtrlClick != undefined) return $props.rowCtrlClick;
-    if ($props.redirect)
-        return (evt, { id }) => {
-            stopEventPropagation(evt);
-            window.open(`/#/${$props.redirect}/${id}`, '_blank');
-        };
-    return () => {};
-});
-
 function redirectFn(id) {
     router.push({ path: `/${$props.redirect}/${id}` });
 }
@@ -262,21 +296,6 @@ function columnName(col) {
     return name;
 }
 
-function getColAlign(col) {
-    return 'text-' + (col.align ?? 'left');
-}
-
-const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
-defineExpose({
-    create: createForm,
-    reload,
-    redirect: redirectFn,
-    selected,
-    CrudModelRef,
-    params,
-    tableRef,
-});
-
 function handleOnDataSaved(_) {
     if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
     else $props.create.onDataSaved(_);
@@ -305,6 +324,237 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
     }
 }
 
+function isEditableColumn(column) {
+    const isEditableCol = column?.isEditable ?? true;
+    const isVisible = column?.visible ?? true;
+    const hasComponent = column?.component;
+
+    return $props.isEditable && isVisible && hasComponent && isEditableCol;
+}
+
+function hasEditableFormat(column) {
+    if (isEditableColumn(column)) return 'editable-text';
+}
+
+const clickHandler = async (event) => {
+    const clickedElement = event.target.closest('td');
+
+    const isDateElement = event.target.closest('.q-date');
+    const isTimeElement = event.target.closest('.q-time');
+    const isQselectDropDown = event.target.closest('.q-select__dropdown-icon');
+
+    if (isDateElement || isTimeElement || isQselectDropDown) return;
+
+    if (clickedElement === null) {
+        await destroyInput(editingRow.value, editingField.value);
+        return;
+    }
+    const rowIndex = clickedElement.getAttribute('data-row-index');
+    const colField = clickedElement.getAttribute('data-col-field');
+    const column = $props.columns.find((col) => col.name === colField);
+
+    if (editingRow.value !== null && editingField.value !== null) {
+        if (editingRow.value == rowIndex && editingField.value == colField) return;
+
+        await destroyInput(editingRow.value, editingField.value);
+    }
+
+    if (isEditableColumn(column)) {
+        await renderInput(Number(rowIndex), colField, clickedElement);
+    }
+};
+
+async function handleTabKey(event, rowIndex, colField) {
+    if (editingRow.value == rowIndex && editingField.value == colField)
+        await destroyInput(editingRow.value, editingField.value);
+
+    const direction = event.shiftKey ? -1 : 1;
+    const { nextRowIndex, nextColumnName } = await handleTabNavigation(
+        rowIndex,
+        colField,
+        direction,
+    );
+
+    if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return;
+
+    event.preventDefault();
+    await renderInput(nextRowIndex, nextColumnName, null);
+}
+
+async function renderInput(rowId, field, clickedElement) {
+    editingField.value = field;
+    editingRow.value = rowId;
+
+    const originalColumn = $props.columns.find((col) => col.name === field);
+    const column = { ...originalColumn, ...{ label: '' } };
+    const row = CrudModelRef.value.formData[rowId];
+    const oldValue = CrudModelRef.value.formData[rowId][column?.name];
+
+    if (!clickedElement)
+        clickedElement = document.querySelector(
+            `[data-row-index="${rowId}"][data-col-field="${field}"]`,
+        );
+
+    Array.from(clickedElement.childNodes).forEach((child) => {
+        child.style.visibility = 'hidden';
+        child.style.position = 'relative';
+    });
+
+    const isSelect = selectRegex.test(column?.component);
+    if (isSelect) column.attrs = { ...column.attrs, 'emit-value': false };
+
+    const node = h(VnColumn, {
+        row: row,
+        class: 'temp-input',
+        column: column,
+        modelValue: row[column.name],
+        componentProp: 'columnField',
+        autofocus: true,
+        focusOnMount: true,
+        eventHandlers: {
+            'update:modelValue': async (value) => {
+                if (isSelect && value) {
+                    row[column.name] = value[column.attrs?.optionValue ?? 'id'];
+                    row[column?.name + 'TextValue'] =
+                        value[column.attrs?.optionLabel ?? 'name'];
+                    await column?.cellEvent?.['update:modelValue']?.(
+                        value,
+                        oldValue,
+                        row,
+                    );
+                } else row[column.name] = value;
+                await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
+            },
+            keyup: async (event) => {
+                if (event.key === 'Enter')
+                    await destroyInput(rowIndex, field, clickedElement);
+            },
+            keydown: async (event) => {
+                switch (event.key) {
+                    case 'Tab':
+                        await handleTabKey(event, rowId, field);
+                        event.stopPropagation();
+                        break;
+                    case 'Escape':
+                        await destroyInput(rowId, field, clickedElement);
+                        break;
+                    default:
+                        break;
+                }
+            },
+            click: (event) => {
+                column?.cellEvent?.['click']?.(event, row);
+            },
+        },
+    });
+
+    node.appContext = app._context;
+    render(node, clickedElement);
+
+    if (['toggle'].includes(column?.component))
+        node.el?.querySelector('span > div').focus();
+
+    if (['checkbox', undefined].includes(column?.component))
+        node.el?.querySelector('span > div > div').focus();
+}
+
+async function destroyInput(rowIndex, field, clickedElement) {
+    if (!clickedElement)
+        clickedElement = document.querySelector(
+            `[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
+        );
+    if (clickedElement) {
+        await nextTick();
+        render(null, clickedElement);
+        Array.from(clickedElement.childNodes).forEach((child) => {
+            child.style.visibility = 'visible';
+            child.style.position = '';
+        });
+    }
+    if (editingRow.value !== rowIndex || editingField.value !== field) return;
+    editingRow.value = null;
+    editingField.value = null;
+}
+
+async function handleTabNavigation(rowIndex, colName, direction) {
+    const columns = $props.columns;
+    const totalColumns = columns.length;
+    let currentColumnIndex = columns.findIndex((col) => col.name === colName);
+
+    let iterations = 0;
+    let newColumnIndex = currentColumnIndex;
+
+    do {
+        iterations++;
+        newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns;
+
+        if (isEditableColumn(columns[newColumnIndex])) break;
+    } while (iterations < totalColumns);
+
+    if (iterations >= totalColumns + 1) return;
+
+    if (direction === 1 && newColumnIndex <= currentColumnIndex) {
+        rowIndex++;
+    } else if (direction === -1 && newColumnIndex >= currentColumnIndex) {
+        rowIndex--;
+    }
+    return { nextRowIndex: rowIndex, nextColumnName: columns[newColumnIndex].name };
+}
+
+function getCheckboxIcon(value) {
+    switch (typeof value) {
+        case 'boolean':
+            return value ? 'check' : 'close';
+        case 'number':
+            return value === 0 ? 'close' : 'check';
+        case 'undefined':
+            return 'indeterminate_check_box';
+        default:
+            return 'indeterminate_check_box';
+    }
+}
+
+function getToggleIcon(value) {
+    if (value === null) return 'help_outline';
+    return value ? 'toggle_on' : 'toggle_off';
+}
+
+function formatColumnValue(col, row, dashIfEmpty) {
+    if (col?.format || row[col?.name + 'TextValue']) {
+        if (selectRegex.test(col?.component) && row[col?.name + 'TextValue']) {
+            return dashIfEmpty(row[col?.name + 'TextValue']);
+        } else {
+            return col.format(row, dashIfEmpty);
+        }
+    }
+
+    if (col?.component === 'date') return dashIfEmpty(toDate(row[col?.name]));
+
+    if (col?.component === 'time')
+        return row[col?.name] >= 5
+            ? dashIfEmpty(date.formatDate(new Date(row[col?.name]), 'HH:mm'))
+            : row[col?.name];
+
+    if (selectRegex.test(col?.component) && $props.isEditable) {
+        const { find, url } = col.attrs;
+        const urlRelation = url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
+
+        if (col?.attrs.options) {
+            const find = col?.attrs.options.find((option) => option.id === row[col.name]);
+            if (!col.attrs?.optionLabel || !find) return dashIfEmpty(row[col?.name]);
+            return dashIfEmpty(find[col.attrs?.optionLabel ?? 'name']);
+        }
+
+        if (typeof row[urlRelation] == 'object') {
+            if (typeof find == 'object')
+                return dashIfEmpty(row[urlRelation][find?.label ?? 'name']);
+
+            return dashIfEmpty(row[urlRelation][col?.attrs.optionLabel ?? 'name']);
+        }
+        if (typeof row[urlRelation] == 'string') return dashIfEmpty(row[urlRelation]);
+    }
+    return dashIfEmpty(row[col?.name]);
+}
 function cardClick(_, row) {
     if ($props.redirect) router.push({ path: `/${$props.redirect}/${row.id}` });
 }
@@ -315,7 +565,7 @@ function cardClick(_, row) {
         v-model="stateStore.rightDrawer"
         side="right"
         :width="256"
-        show-if-above
+        :overlay="$props.overlay"
     >
         <QScrollArea class="fit">
             <VnTableFilter
@@ -336,7 +586,7 @@ function cardClick(_, row) {
     <CrudModel
         v-bind="$attrs"
         :class="$attrs['class'] ?? 'q-px-md'"
-        :limit="$attrs['limit'] ?? 20"
+        :limit="$attrs['limit'] ?? 100"
         ref="CrudModelRef"
         @on-fetch="(...args) => emit('onFetch', ...args)"
         :search-url="searchUrl"
@@ -352,8 +602,12 @@ function cardClick(_, row) {
             <QTable
                 ref="tableRef"
                 v-bind="table"
-                class="vnTable"
-                :class="{ 'last-row-sticky': $props.footer }"
+                :class="[
+                    'vnTable',
+                    table ? 'selection-cell' : '',
+                    $props.footer ? 'last-row-sticky' : '',
+                ]"
+                wrap-cells
                 :columns="splittedColumns.columns"
                 :rows="rows"
                 v-model:selected="selected"
@@ -367,11 +621,13 @@ function cardClick(_, row) {
                 @row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
                 @update:selected="emit('update:selected', $event)"
                 @selection="(details) => handleSelection(details, rows)"
+                :hide-selected-banner="true"
             >
                 <template #top-left v-if="!$props.withoutHeader">
-                    <slot name="top-left"></slot>
+                    <slot name="top-left"> </slot>
                 </template>
                 <template #top-right v-if="!$props.withoutHeader">
+                    <slot name="top-right"></slot>
                     <VnVisibleColumn
                         v-if="isTableMode"
                         v-model="splittedColumns.columns"
@@ -389,32 +645,39 @@ function cardClick(_, row) {
                 <template #header-cell="{ col }">
                     <QTh
                         v-if="col.visible ?? true"
-                        :style="col.headerStyle"
-                        :class="col.headerClass"
+                        v-bind:class="col.headerClass"
+                        class="body-cell"
+                        :style="col?.width ? `max-width: ${col?.width}` : ''"
                     >
                         <div
-                            class="column ellipsis"
-                            :class="`text-${col?.align ?? 'left'}`"
-                            :style="$props.columnSearch ? 'height: 75px' : ''"
+                            class="no-padding"
+                            :style="[
+                                withFilters && $props.columnSearch ? 'height: 75px' : '',
+                            ]"
                         >
-                            <div class="row items-center no-wrap" style="height: 30px">
+                            <div style="height: 30px">
                                 <QTooltip v-if="col.toolTip">{{ col.toolTip }}</QTooltip>
                                 <VnTableOrder
                                     v-model="orders[col.orderBy ?? col.name]"
                                     :name="col.orderBy ?? col.name"
-                                    :label="col?.label"
+                                    :label="col?.labelAbbreviation ?? col?.label"
                                     :data-key="$attrs['data-key']"
                                     :search-url="searchUrl"
+                                    :align="getColAlign(col)"
                                 />
                             </div>
                             <VnFilter
-                                v-if="$props.columnSearch"
+                                v-if="
+                                    $props.columnSearch &&
+                                    col.columnSearch !== false &&
+                                    withFilters
+                                "
                                 :column="col"
                                 :show-title="true"
                                 :data-key="$attrs['data-key']"
                                 v-model="params[columnName(col)]"
                                 :search-url="searchUrl"
-                                class="full-width"
+                                customClass="header-filter"
                             />
                         </div>
                     </QTh>
@@ -432,32 +695,67 @@ function cardClick(_, row) {
                     </QTd>
                 </template>
                 <template #body-cell="{ col, row, rowIndex }">
-                    <!-- Columns -->
                     <QTd
-                        auto-width
-                        class="no-margin"
-                        :class="[getColAlign(col), col.columnClass]"
-                        :style="col.style"
+                        class="no-margin q-px-xs"
                         v-if="col.visible ?? true"
-                        @click.ctrl="
-                            ($event) =>
-                                rowCtrlClickFunction && rowCtrlClickFunction($event, row)
-                        "
+                        :style="{
+                            'max-width': col?.width ?? false,
+                            position: 'relative',
+                        }"
+                        :class="[
+                            col.columnClass,
+                            'body-cell no-margin no-padding',
+                            getColAlign(col),
+                        ]"
+                        :data-row-index="rowIndex"
+                        :data-col-field="col?.name"
                     >
-                        <slot
-                            :name="`column-${col.name}`"
-                            :col="col"
-                            :row="row"
-                            :row-index="rowIndex"
+                        <div
+                            class="no-padding no-margin peter"
+                            style="
+                                overflow: hidden;
+                                text-overflow: ellipsis;
+                                white-space: nowrap;
+                            "
                         >
-                            <VnTableColumn
-                                :column="col"
+                            <slot
+                                :name="`column-${col.name}`"
+                                :col="col"
                                 :row="row"
-                                :is-editable="col.isEditable ?? isEditable"
-                                v-model="row[col.name]"
-                                component-prop="columnField"
-                            />
-                        </slot>
+                                :row-index="rowIndex"
+                            >
+                                <QIcon
+                                    v-if="col?.component === 'toggle'"
+                                    :name="
+                                        col?.getIcon
+                                            ? col.getIcon(row[col?.name])
+                                            : getToggleIcon(row[col?.name])
+                                    "
+                                    style="color: var(--vn-text-color)"
+                                    :class="hasEditableFormat(col)"
+                                    size="14px"
+                                />
+                                <QIcon
+                                    v-else-if="col?.component === 'checkbox'"
+                                    :name="getCheckboxIcon(row[col?.name])"
+                                    style="color: var(--vn-text-color)"
+                                    :class="hasEditableFormat(col)"
+                                    size="14px"
+                                />
+                                <span
+                                    v-else
+                                    :class="hasEditableFormat(col)"
+                                    :style="
+                                        typeof col?.style == 'function'
+                                            ? col.style(row)
+                                            : col?.style
+                                    "
+                                    style="bottom: 0"
+                                >
+                                    {{ formatColumnValue(col, row, dashIfEmpty) }}
+                                </span>
+                            </slot>
+                        </div>
                     </QTd>
                 </template>
                 <template #body-cell-tableActions="{ col, row }">
@@ -478,7 +776,7 @@ function cardClick(_, row) {
                             flat
                             dense
                             :class="
-                                btn.isPrimary ? 'text-primary-light' : 'color-vn-text '
+                                btn.isPrimary ? 'text-primary-light' : 'color-vn-label'
                             "
                             :style="`visibility: ${
                                 ((btn.show && btn.show(row)) ?? true)
@@ -486,6 +784,7 @@ function cardClick(_, row) {
                                     : 'hidden'
                             }`"
                             @click="btn.action(row)"
+                            :data-cy="btn?.name ?? `tableAction-${index}`"
                         />
                     </QTd>
                 </template>
@@ -534,7 +833,7 @@ function cardClick(_, row) {
                                 </QCardSection>
                                 <!-- Fields -->
                                 <QCardSection
-                                    class="q-pl-sm q-pr-lg q-py-xs"
+                                    class="q-pl-sm q-py-xs"
                                     :class="$props.cardClass"
                                 >
                                     <div
@@ -555,7 +854,7 @@ function cardClick(_, row) {
                                                         :row="row"
                                                         :row-index="index"
                                                     >
-                                                        <VnTableColumn
+                                                        <VnColumn
                                                             :column="col"
                                                             :row="row"
                                                             :is-editable="false"
@@ -583,12 +882,12 @@ function cardClick(_, row) {
                                     :icon="btn.icon"
                                     data-cy="cardBtn"
                                     class="q-pa-xs"
-                                    flat
                                     :class="
                                         btn.isPrimary
                                             ? 'text-primary-light'
-                                            : 'color-vn-text '
+                                            : 'color-vn-label'
                                     "
+                                    flat
                                     @click="btn.action(row)"
                                 />
                             </QCardSection>
@@ -596,14 +895,17 @@ function cardClick(_, row) {
                     </component>
                 </template>
                 <template #bottom-row="{ cols }" v-if="$props.footer">
-                    <QTr v-if="rows.length" style="height: 30px">
+                    <QTr v-if="rows.length" style="height: 45px">
+                        <QTh v-if="table.selection" />
                         <QTh
                             v-for="col of cols.filter((cols) => cols.visible ?? true)"
                             :key="col?.id"
-                            class="text-center"
                             :class="getColAlign(col)"
                         >
-                            <slot :name="`column-footer-${col.name}`" />
+                            <slot
+                                :name="`column-footer-${col.name}`"
+                                :isEditableColumn="isEditableColumn(col)"
+                            />
                         </QTh>
                     </QTr>
                 </template>
@@ -622,7 +924,7 @@ function cardClick(_, row) {
                     size="md"
                     round
                     flat
-                    shortcut="+"
+                    v-shortcut="'+'"
                     :disabled="!disabledAttr"
                 />
                 <QTooltip>
@@ -640,39 +942,52 @@ function cardClick(_, row) {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             data-cy="vnTableCreateBtn"
         />
         <QTooltip self="top right">
             {{ createForm?.title }}
         </QTooltip>
     </QPageSticky>
-    <QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
+    <QDialog
+        v-model="showForm"
+        transition-show="scale"
+        transition-hide="scale"
+        :full-width="createComplement?.isFullWidth ?? false"
+        data-cy="vn-table-create-dialog"
+    >
         <FormModelPopup
+            ref="createRef"
             v-bind="createForm"
             :model="$attrs['data-key'] + 'Create'"
             @on-data-saved="(_, res) => createForm.onDataSaved(res)"
         >
             <template #form-inputs="{ data }">
-                <div class="grid-create">
-                    <slot
-                        v-for="column of splittedColumns.create"
-                        :key="column.name"
-                        :name="`column-create-${column.name}`"
-                        :data="data"
-                        :column-name="column.name"
-                        :label="column.label"
-                    >
-                        <VnTableColumn
-                            :column="column"
-                            :row="{}"
-                            default="input"
-                            v-model="data[column.name]"
-                            :show-label="true"
-                            component-prop="columnCreate"
-                        />
-                    </slot>
-                    <slot name="more-create-dialog" :data="data" />
+                <div :style="createComplement?.containerStyle">
+                    <div>
+                        <slot name="previous-create-dialog" :data="data" />
+                    </div>
+                    <div class="grid-create" :style="createComplement?.columnGridStyle">
+                        <slot
+                            v-for="column of splittedColumns.create"
+                            :key="column.name"
+                            :name="`column-create-${column.name}`"
+                            :data="data"
+                            :column-name="column.name"
+                            :label="column.label"
+                        >
+                            <VnColumn
+                                :column="column"
+                                :row="{}"
+                                default="input"
+                                v-model="data[column.name]"
+                                :show-label="true"
+                                component-prop="columnCreate"
+                                :data-cy="`${column.name}-create-popup`"
+                            />
+                        </slot>
+                        <slot name="more-create-dialog" :data="data" />
+                    </div>
                 </div>
             </template>
         </FormModelPopup>
@@ -690,6 +1005,42 @@ es:
 </i18n>
 
 <style lang="scss">
+.selection-cell {
+    table td:first-child {
+        padding: 0px;
+    }
+}
+.side-padding {
+    padding-left: 1px;
+    padding-right: 1px;
+}
+.editable-text:hover {
+    border-bottom: 1px dashed var(--q-primary);
+    @extend .side-padding;
+}
+.editable-text {
+    border-bottom: 1px dashed var(--vn-label-color);
+    @extend .side-padding;
+}
+.cell-input {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding-top: 0px !important;
+}
+.q-field--labeled .q-field__native,
+.q-field--labeled .q-field__prefix,
+.q-field--labeled .q-field__suffix {
+    padding-top: 20px;
+}
+
+.body-cell {
+    padding-left: 4px !important;
+    padding-right: 4px !important;
+    position: relative;
+}
 .bg-chip-secondary {
     background-color: var(--vn-page-color);
     color: var(--vn-text-color);
@@ -706,8 +1057,8 @@ es:
 
 .grid-three {
     display: grid;
-    grid-template-columns: repeat(auto-fit, minmax(350px, max-content));
-    max-width: 100%;
+    grid-template-columns: repeat(auto-fit, minmax(300px, max-content));
+    width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -715,7 +1066,6 @@ es:
 .grid-create {
     display: grid;
     grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
-    max-width: 100%;
     grid-gap: 20px;
     margin: 0 auto;
 }
@@ -731,7 +1081,9 @@ es:
         }
     }
 }
-
+.q-table tbody tr td {
+    position: relative;
+}
 .q-table {
     th {
         padding: 0;
@@ -780,6 +1132,7 @@ es:
 .vn-label-value {
     display: flex;
     flex-direction: row;
+    align-items: center;
     color: var(--vn-text-color);
     .value {
         overflow: hidden;
@@ -831,4 +1184,15 @@ es:
 .q-table__middle.q-virtual-scroll.q-virtual-scroll--vertical.scroll {
     background-color: var(--vn-section-color);
 }
+.temp-input {
+    top: 0;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    display: flex;
+}
+
+label.header-filter > .q-field__inner > .q-field__control {
+    padding: inherit;
+}
 </style>
diff --git a/src/components/VnTable/VnTableFilter.vue b/src/components/VnTable/VnTableFilter.vue
index 732605ce5..79b903e54 100644
--- a/src/components/VnTable/VnTableFilter.vue
+++ b/src/components/VnTable/VnTableFilter.vue
@@ -27,31 +27,36 @@ function columnName(col) {
 </script>
 <template>
     <VnFilterPanel v-bind="$attrs" :search-button="true" :disable-submit-event="true">
-        <template #body="{ params, orders }">
+        <template #body="{ params, orders, searchFn }">
             <div
-                class="row no-wrap flex-center"
+                class="container"
                 v-for="col of columns.filter((c) => c.columnFilter ?? true)"
                 :key="col.id"
             >
-                <VnFilter
-                    ref="tableFilterRef"
-                    :column="col"
-                    :data-key="$attrs['data-key']"
-                    v-model="params[columnName(col)]"
-                    :search-url="searchUrl"
-                />
-                <VnTableOrder
-                    v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
-                    v-model="orders[col.orderBy ?? col.name]"
-                    :name="col.orderBy ?? col.name"
-                    :data-key="$attrs['data-key']"
-                    :search-url="searchUrl"
-                    :vertical="true"
-                />
+                <div class="filter">
+                    <VnFilter
+                        ref="tableFilterRef"
+                        :column="col"
+                        :data-key="$attrs['data-key']"
+                        v-model="params[columnName(col)]"
+                        :search-url="searchUrl"
+                    />
+                </div>
+                <div class="order">
+                    <VnTableOrder
+                        v-if="col?.columnFilter !== false && col?.name !== 'tableActions'"
+                        v-model="orders[col.orderBy ?? col.name]"
+                        :name="col.orderBy ?? col.name"
+                        :data-key="$attrs['data-key']"
+                        :search-url="searchUrl"
+                        :vertical="true"
+                    />
+                </div>
             </div>
             <slot
                 name="moreFilterPanel"
                 :params="params"
+                :search-fn="searchFn"
                 :orders="orders"
                 :columns="columns"
             />
@@ -67,3 +72,21 @@ function columnName(col) {
         </template>
     </VnFilterPanel>
 </template>
+<style lang="scss" scoped>
+.container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 45px;
+    gap: 10px;
+}
+
+.filter {
+    width: 70%;
+    height: 40px;
+    text-align: center;
+}
+.order {
+    width: 10%;
+}
+</style>
diff --git a/src/components/VnTable/VnVisibleColumn.vue b/src/components/VnTable/VnVisibleColumn.vue
index dad950d73..6d15c585e 100644
--- a/src/components/VnTable/VnVisibleColumn.vue
+++ b/src/components/VnTable/VnVisibleColumn.vue
@@ -32,16 +32,21 @@ const areAllChecksMarked = computed(() => {
 
 function setUserConfigViewData(data, isLocal) {
     if (!data) return;
-    // Importante: El name de las columnas de la tabla debe conincidir con el name de las variables que devuelve la view config
     if (!isLocal) localColumns.value = [];
-    // Array to Object
+
     const skippeds = $props.skip.reduce((a, v) => ({ ...a, [v]: v }), {});
 
     for (let column of columns.value) {
-        const { label, name } = column;
+        const { label, name, labelAbbreviation } = column;
         if (skippeds[name]) continue;
         column.visible = data[name] ?? true;
-        if (!isLocal) localColumns.value.push({ name, label, visible: column.visible });
+        if (!isLocal)
+            localColumns.value.push({
+                name,
+                label,
+                labelAbbreviation,
+                visible: column.visible,
+            });
     }
 }
 
@@ -152,7 +157,11 @@ onMounted(async () => {
                     <QCheckbox
                         v-for="col in localColumns"
                         :key="col.name"
-                        :label="col.label ?? col.name"
+                        :label="
+                            col?.labelAbbreviation
+                                ? col.labelAbbreviation + ` (${col.label ?? col.name})`
+                                : (col.label ?? col.name)
+                        "
                         v-model="col.visible"
                     />
                 </div>
diff --git a/src/components/__tests__/FormModel.spec.js b/src/components/__tests__/FormModel.spec.js
index e35684bc3..3dce04374 100644
--- a/src/components/__tests__/FormModel.spec.js
+++ b/src/components/__tests__/FormModel.spec.js
@@ -57,6 +57,7 @@ describe('FormModel', () => {
             vm.state.set(model, formInitialData);
             expect(vm.hasChanges).toBe(false);
 
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             expect(vm.hasChanges).toBe(true);
@@ -93,9 +94,13 @@ describe('FormModel', () => {
 
         it('should call axios.patch with the right data', async () => {
             const spy = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
-            const { vm } = mount({ propsData: { url, model, formInitialData } });
-            vm.formData.mockKey = 'newVal';
+            const { vm } = mount({ propsData: { url, model } });
+
+            vm.formData = {};
             await vm.$nextTick();
+            vm.formData = { mockKey: 'newVal' };
+            await vm.$nextTick();
+
             await vm.save();
             expect(spy).toHaveBeenCalled();
             vm.formData.mockKey = 'mockVal';
@@ -106,6 +111,7 @@ describe('FormModel', () => {
             const { vm } = mount({
                 propsData: { url, model, formInitialData, urlCreate: 'mockUrlCreate' },
             });
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
@@ -119,7 +125,7 @@ describe('FormModel', () => {
             });
             const spyPatch = vi.spyOn(axios, 'patch').mockResolvedValue({ data: {} });
             const spySaveFn = vi.spyOn(vm.$props, 'saveFn');
-
+            await vm.$nextTick();
             vm.formData.mockKey = 'newVal';
             await vm.$nextTick();
             await vm.save();
diff --git a/src/components/__tests__/Leftmenu.spec.js b/src/components/__tests__/Leftmenu.spec.js
index 10d9d66fb..4ab8b527f 100644
--- a/src/components/__tests__/Leftmenu.spec.js
+++ b/src/components/__tests__/Leftmenu.spec.js
@@ -1,9 +1,12 @@
-import { vi, describe, expect, it, beforeAll } from 'vitest';
+import { vi, describe, expect, it, beforeAll, beforeEach, afterEach } from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import Leftmenu from 'components/LeftMenu.vue';
-
+import * as vueRouter from 'vue-router';
 import { useNavigationStore } from 'src/stores/useNavigationStore';
 
+let vm;
+let navigation;
+
 vi.mock('src/router/modules', () => ({
     default: [
         {
@@ -21,6 +24,16 @@ vi.mock('src/router/modules', () => ({
                 {
                     path: '',
                     name: 'CustomerMain',
+                    meta: {
+                        menu: 'Customer',
+                        menuChildren: [
+                            {
+                                name: 'CustomerCreditContracts',
+                                title: 'creditContracts',
+                                icon: 'vn:solunion',
+                            },
+                        ],
+                    },
                     children: [
                         {
                             path: 'list',
@@ -28,6 +41,13 @@ vi.mock('src/router/modules', () => ({
                             meta: {
                                 title: 'list',
                                 icon: 'view_list',
+                                menuChildren: [
+                                    {
+                                        name: 'CustomerCreditContracts',
+                                        title: 'creditContracts',
+                                        icon: 'vn:solunion',
+                                    },
+                                ],
                             },
                         },
                         {
@@ -44,51 +64,325 @@ vi.mock('src/router/modules', () => ({
         },
     ],
 }));
-
-describe('Leftmenu', () => {
-    let vm;
-    let navigation;
-    beforeAll(() => {
-        vi.spyOn(axios, 'get').mockResolvedValue({
-            data: [],
-        });
-
-        vm = createWrapper(Leftmenu, {
-            propsData: {
-                source: 'main',
+vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
+    matched: [
+        {
+            path: '/',
+            redirect: {
+                name: 'Dashboard',
             },
-        }).vm;
-
-        navigation = useNavigationStore();
-        navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
-        navigation.getModules = vi.fn().mockReturnValue({
-            value: [
+            name: 'Main',
+            meta: {},
+            props: {
+                default: false,
+            },
+            children: [
                 {
-                    name: 'customer',
-                    title: 'customer.pageTitles.customers',
-                    icon: 'vn:customer',
-                    module: 'customer',
+                    path: '/dashboard',
+                    name: 'Dashboard',
+                    meta: {
+                        title: 'dashboard',
+                        icon: 'dashboard',
+                    },
                 },
             ],
+        },
+        {
+            path: '/customer',
+            redirect: {
+                name: 'CustomerMain',
+            },
+            name: 'Customer',
+            meta: {
+                title: 'customers',
+                icon: 'vn:client',
+                moduleName: 'Customer',
+                keyBinding: 'c',
+                menu: 'customer',
+            },
+        },
+    ],
+    query: {},
+    params: {},
+    meta: { moduleName: 'mockName' },
+    path: 'mockName/1',
+    name: 'Customer',
+});
+function mount(source = 'main') {
+    vi.spyOn(axios, 'get').mockResolvedValue({
+        data: [],
+    });
+    const wrapper = createWrapper(Leftmenu, {
+        propsData: {
+            source,
+        },
+    });
+
+    navigation = useNavigationStore();
+    navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
+    navigation.getModules = vi.fn().mockReturnValue({
+        value: [
+            {
+                name: 'customer',
+                title: 'customer.pageTitles.customers',
+                icon: 'vn:customer',
+                module: 'customer',
+            },
+        ],
+    });
+    return wrapper;
+}
+
+describe('getRoutes', () => {
+    afterEach(() => vi.clearAllMocks());
+    const getRoutes = vi.fn().mockImplementation((props, getMethodA, getMethodB) => {
+        const handleRoutes = {
+            methodA: getMethodA,
+            methodB: getMethodB,
+        };
+        try {
+            handleRoutes[props.source]();
+        } catch (error) {
+            throw Error('Method not defined');
+        }
+    });
+
+    const getMethodA = vi.fn();
+    const getMethodB = vi.fn();
+    const fn = (props) => getRoutes(props, getMethodA, getMethodB);
+
+    it('should call getMethodB when source is card', () => {
+        let props = { source: 'methodB' };
+        fn(props);
+
+        expect(getMethodB).toHaveBeenCalled();
+        expect(getMethodA).not.toHaveBeenCalled();
+    });
+    it('should call getMethodA when source is main', () => {
+        let props = { source: 'methodA' };
+        fn(props);
+
+        expect(getMethodA).toHaveBeenCalled();
+        expect(getMethodB).not.toHaveBeenCalled();
+    });
+
+    it('should call getMethodA when source is not exists or undefined', () => {
+        let props = { source: 'methodC' };
+        expect(() => fn(props)).toThrowError('Method not defined');
+
+        expect(getMethodA).not.toHaveBeenCalled();
+        expect(getMethodB).not.toHaveBeenCalled();
+    });
+});
+
+describe('Leftmenu as card', () => {
+    beforeAll(() => {
+        vm = mount('card').vm;
+    });
+
+    it('should get routes for card source', async () => {
+        vm.getRoutes();
+    });
+});
+describe('Leftmenu as main', () => {
+    beforeEach(() => {
+        vm = mount().vm;
+    });
+
+    it('should initialize with default props', () => {
+        expect(vm.source).toBe('main');
+    });
+
+    it('should filter items based on search input', async () => {
+        vm.search = 'cust';
+        await vm.$nextTick();
+        expect(vm.filteredItems[0].name).toEqual('customer');
+        expect(vm.filteredItems[0].module).toEqual('customer');
+    });
+    it('should filter items based on search input', async () => {
+        vm.search = 'Rou';
+        await vm.$nextTick();
+        expect(vm.filteredItems).toEqual([]);
+    });
+
+    it('should return pinned items', () => {
+        vm.items = [
+            { name: 'Item 1', isPinned: false },
+            { name: 'Item 2', isPinned: true },
+        ];
+        expect(vm.pinnedModules).toEqual(
+            new Map([['Item 2', { name: 'Item 2', isPinned: true }]]),
+        );
+    });
+
+    it('should find matches in routes', () => {
+        const search = 'child1';
+        const item = {
+            children: [
+                { name: 'child1', children: [] },
+                { name: 'child2', children: [] },
+            ],
+        };
+        const matches = vm.findMatches(search, item);
+        expect(matches).toEqual([{ name: 'child1', children: [] }]);
+    });
+    it('should not proceed if event is already prevented', async () => {
+        const item = { module: 'testModule', isPinned: false };
+        const event = {
+            preventDefault: vi.fn(),
+            stopPropagation: vi.fn(),
+            defaultPrevented: true,
+        };
+
+        await vm.togglePinned(item, event);
+
+        expect(event.preventDefault).not.toHaveBeenCalled();
+        expect(event.stopPropagation).not.toHaveBeenCalled();
+    });
+
+    it('should call quasar.notify with success message', async () => {
+        const item = { module: 'testModule', isPinned: false };
+        const event = {
+            preventDefault: vi.fn(),
+            stopPropagation: vi.fn(),
+            defaultPrevented: false,
+        };
+        const response = { data: { id: 1 } };
+
+        vi.spyOn(axios, 'post').mockResolvedValue(response);
+        vi.spyOn(vm.quasar, 'notify');
+
+        await vm.togglePinned(item, event);
+
+        expect(vm.quasar.notify).toHaveBeenCalledWith({
+            message: 'Data saved',
+            type: 'positive',
         });
     });
 
-    it('should return a proper formated object with two child items', async () => {
-        const expectedMenuItem = [
-            {
-                children: null,
-                name: 'CustomerList',
-                title: 'globals.pageTitles.list',
-                icon: 'view_list',
-            },
-            {
-                children: null,
-                name: 'CustomerCreate',
-                title: 'globals.pageTitles.createCustomer',
-                icon: 'vn:addperson',
-            },
-        ];
-        const firstMenuItem = vm.items[0];
-        expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
+    it('should handle a single matched route with a menu', () => {
+        const route = {
+            matched: [{ meta: { menu: 'customer' } }],
+        };
+
+        const result = vm.betaGetRoutes();
+
+        expect(result.meta.menu).toEqual(route.matched[0].meta.menu);
+    });
+    it('should get routes for main source', () => {
+        vm.props.source = 'main';
+        vm.getRoutes();
+        expect(navigation.getModules).toHaveBeenCalled();
+    });
+
+    it('should find direct child matches', () => {
+        const search = 'child1';
+        const item = {
+            children: [{ name: 'child1' }, { name: 'child2' }],
+        };
+        const result = vm.findMatches(search, item);
+        expect(result).toEqual([{ name: 'child1' }]);
+    });
+
+    it('should find nested child matches', () => {
+        const search = 'child3';
+        const item = {
+            children: [
+                { name: 'child1' },
+                {
+                    name: 'child2',
+                    children: [{ name: 'child3' }],
+                },
+            ],
+        };
+        const result = vm.findMatches(search, item);
+        expect(result).toEqual([{ name: 'child3' }]);
+    });
+});
+
+describe('normalize', () => {
+    beforeAll(() => {
+        vm = mount('card').vm;
+    });
+    it('should normalize and lowercase text', () => {
+        const input = 'ÁÉÍÓÚáéíóú';
+        const expected = 'aeiouaeiou';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle empty string', () => {
+        const input = '';
+        const expected = '';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle text without diacritics', () => {
+        const input = 'hello';
+        const expected = 'hello';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+
+    it('should handle mixed text', () => {
+        const input = 'Héllo Wórld!';
+        const expected = 'hello world!';
+        expect(vm.normalize(input)).toBe(expected);
+    });
+});
+
+describe('addChildren', () => {
+    const module = 'testModule';
+    beforeEach(() => {
+        vm = mount().vm;
+        vi.clearAllMocks();
+    });
+
+    it('should add menu items to parent if matches are found', () => {
+        const parent = 'testParent';
+        const route = {
+            meta: {
+                menu: 'testMenu',
+            },
+            children: [{ name: 'child1' }, { name: 'child2' }],
+        };
+        vm.addChildren(module, route, parent);
+
+        expect(navigation.addMenuItem).toHaveBeenCalled();
+    });
+
+    it('should handle routes with no meta menu', () => {
+        const route = {
+            meta: {},
+            menus: {},
+        };
+
+        const parent = [];
+
+        vm.addChildren(module, route, parent);
+        expect(navigation.addMenuItem).toHaveBeenCalled();
+    });
+
+    it('should handle empty parent array', () => {
+        const parent = [];
+        const route = {
+            meta: {
+                menu: 'child11',
+            },
+            children: [
+                {
+                    name: 'child1',
+                    meta: {
+                        menuChildren: [
+                            {
+                                name: 'CustomerCreditContracts',
+                                title: 'creditContracts',
+                                icon: 'vn:solunion',
+                            },
+                        ],
+                    },
+                },
+            ],
+        };
+        vm.addChildren(module, route, parent);
+        expect(navigation.addMenuItem).toHaveBeenCalled();
     });
 });
diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js
index ac20f911e..9e449745a 100644
--- a/src/components/__tests__/UserPanel.spec.js
+++ b/src/components/__tests__/UserPanel.spec.js
@@ -1,61 +1,65 @@
-import { vi, describe, expect, it, beforeEach, beforeAll, afterEach } from 'vitest';
+import { vi, describe, expect, it, beforeEach, afterEach } from 'vitest';
 import { createWrapper } from 'app/test/vitest/helper';
 import UserPanel from 'src/components/UserPanel.vue';
 import axios from 'axios';
 import { useState } from 'src/composables/useState';
 
+vi.mock('src/utils/quasarLang', () => ({
+  default: vi.fn(),
+}));
+
 describe('UserPanel', () => {
-    let wrapper;
-    let vm;
-    let state;
+  let wrapper;
+  let vm;
+  let state;
 
-    beforeEach(() => {
-        wrapper = createWrapper(UserPanel, {});
-        state = useState();
-        state.setUser({
-            id: 115,
-            name: 'itmanagement',
-            nickname: 'itManagementNick',
-            lang: 'en',
-            darkMode: false,
-            companyFk: 442,
-            warehouseFk: 1,
-        });
-        wrapper = wrapper.wrapper;
-        vm = wrapper.vm;
+  beforeEach(() => {
+    wrapper = createWrapper(UserPanel, {});
+    state = useState();
+    state.setUser({
+      id: 115,
+      name: 'itmanagement',
+      nickname: 'itManagementNick',
+      lang: 'en',
+      darkMode: false,
+      companyFk: 442,
+      warehouseFk: 1,
     });
+    wrapper = wrapper.wrapper;
+    vm = wrapper.vm;
+  });
 
-    afterEach(() => {
-        vi.clearAllMocks();
-    });
+  afterEach(() => {
+    vi.clearAllMocks();
+  });
 
-    it('should fetch warehouses data on mounted', async () => {
-        const fetchData = wrapper.findComponent({ name: 'FetchData' });
-        expect(fetchData.props('url')).toBe('Warehouses');
-        expect(fetchData.props('autoLoad')).toBe(true);
-    });
+  it('should fetch warehouses data on mounted', async () => {
+    const fetchData = wrapper.findComponent({ name: 'FetchData' });
+    expect(fetchData.props('url')).toBe('Warehouses');
+    expect(fetchData.props('autoLoad')).toBe(true);
+  });
 
-    it('should toggle dark mode correctly and update preferences', async () => {
-        await vm.saveDarkMode(true);
-        expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
-        expect(vm.user.darkMode).toBe(true);
-        vm.updatePreferences();
-        expect(vm.darkMode).toBe(true);
-    });
+  it('should toggle dark mode correctly and update preferences', async () => {
+    await vm.saveDarkMode(true);
+    expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true });
+    expect(vm.user.darkMode).toBe(true);
+    await vm.updatePreferences();
+    expect(vm.darkMode).toBe(true);
+  });
 
-    it('should change user language and update preferences', async () => {
-        const userLanguage = 'es';
-        await vm.saveLanguage(userLanguage);
-        expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
-        expect(vm.user.lang).toBe(userLanguage);
-        vm.updatePreferences();
-        expect(vm.locale).toBe(userLanguage);
-    });
+  it('should change user language and update preferences', async () => {
+    const userLanguage = 'es';
+    await vm.saveLanguage(userLanguage);
+    expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage });
+    expect(vm.user.lang).toBe(userLanguage);
+    await vm.updatePreferences();
+    expect(vm.locale).toBe(userLanguage);
+  });
 
-    it('should update user data', async () => {
-        const key = 'name';
-        const value = 'itboss';
-        await vm.saveUserData(key, value);
-        expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
-    });
-});
+  it('should update user data', async () => {
+    const key = 'name';
+    const value = 'itboss';
+    await vm.saveUserData(key, value);
+    expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value });
+  });
+});
\ No newline at end of file
diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue
index 0d80f43ce..44002c22a 100644
--- a/src/components/common/VnCard.vue
+++ b/src/components/common/VnCard.vue
@@ -10,11 +10,11 @@ import LeftMenu from 'components/LeftMenu.vue';
 import RightMenu from 'components/common/RightMenu.vue';
 const props = defineProps({
     dataKey: { type: String, required: true },
-    baseUrl: { type: String, default: undefined },
-    customUrl: { type: String, default: undefined },
+    url: { type: String, default: undefined },
     filter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
+    idInWhere: { type: Boolean, default: false },
     searchDataKey: { type: String, default: undefined },
     searchbarProps: { type: Object, default: undefined },
     redirectOnError: { type: Boolean, default: false },
@@ -23,25 +23,20 @@ const props = defineProps({
 const stateStore = useStateStore();
 const route = useRoute();
 const router = useRouter();
-const url = computed(() => {
-    if (props.baseUrl) {
-        return `${props.baseUrl}/${route.params.id}`;
-    }
-    return props.customUrl;
-});
 const searchRightDataKey = computed(() => {
     if (!props.searchDataKey) return route.name;
     return props.searchDataKey;
 });
+
 const arrayData = useArrayData(props.dataKey, {
-    url: url.value,
-    filter: props.filter,
+    url: props.url,
+    userFilter: props.filter,
+    oneRecord: true,
 });
 
 onBeforeMount(async () => {
     try {
-        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
-        await arrayData.fetch({ append: false, updateRouter: false });
+        await fetch(route.params.id);
     } catch {
         const { matched: matches } = router.currentRoute.value;
         const { path } = matches.at(-1);
@@ -49,13 +44,17 @@ onBeforeMount(async () => {
     }
 });
 
-if (props.baseUrl) {
-    onBeforeRouteUpdate(async (to, from) => {
-        if (to.params.id !== from.params.id) {
-            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
-            await arrayData.fetch({ append: false, updateRouter: false });
-        }
-    });
+onBeforeRouteUpdate(async (to, from) => {
+    const id = to.params.id;
+    if (id !== from.params.id) await fetch(id, true);
+});
+
+async function fetch(id, append = false) {
+    const regex = /\/(\d+)/;
+    if (props.idInWhere) arrayData.store.filter.where = { id };
+    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
+    else arrayData.store.url = props.url.replace(regex, `/${id}`);
+    await arrayData.fetch({ append, updateRouter: false });
 }
 </script>
 <template>
@@ -83,7 +82,7 @@ if (props.baseUrl) {
         <QPage>
             <VnSubToolbar />
             <div :class="[useCardSize(), $attrs.class]">
-                <RouterView :key="route.path" />
+                <RouterView :key="$route.path" />
             </div>
         </QPage>
     </QPageContainer>
diff --git a/src/components/common/VnCardBeta.vue b/src/components/common/VnCardBeta.vue
index f237a300c..7c82316dc 100644
--- a/src/components/common/VnCardBeta.vue
+++ b/src/components/common/VnCardBeta.vue
@@ -1,6 +1,6 @@
 <script setup>
-import { onBeforeMount, computed } from 'vue';
-import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
+import { onBeforeMount } from 'vue';
+import { useRouter, onBeforeRouteUpdate } from 'vue-router';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useStateStore } from 'stores/useStateStore';
 import useCardSize from 'src/composables/useCardSize';
@@ -9,10 +9,9 @@ import VnSubToolbar from '../ui/VnSubToolbar.vue';
 
 const props = defineProps({
     dataKey: { type: String, required: true },
-    baseUrl: { type: String, default: undefined },
-    customUrl: { type: String, default: undefined },
+    url: { type: String, default: undefined },
+    idInWhere: { type: Boolean, default: false },
     filter: { type: Object, default: () => {} },
-    userFilter: { type: Object, default: () => {} },
     descriptor: { type: Object, required: true },
     filterPanel: { type: Object, default: undefined },
     searchDataKey: { type: String, default: undefined },
@@ -21,46 +20,42 @@ const props = defineProps({
 });
 
 const stateStore = useStateStore();
-const route = useRoute();
 const router = useRouter();
-const url = computed(() => {
-    if (props.baseUrl) {
-        return `${props.baseUrl}/${route.params.id}`;
-    }
-    return props.customUrl;
-});
-
 const arrayData = useArrayData(props.dataKey, {
-    url: url.value,
-    filter: props.filter,
-    userFilter: props.userFilter,
+    url: props.url,
+    userFilter: props.filter,
+    oneRecord: true,
 });
 
 onBeforeMount(async () => {
+    const route = router.currentRoute.value;
     try {
-        if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
-        await arrayData.fetch({ append: false, updateRouter: false });
+        await fetch(route.params.id);
     } catch {
-        const { matched: matches } = router.currentRoute.value;
+        const { matched: matches } = route;
         const { path } = matches.at(-1);
         router.push({ path: path.replace(/:id.*/, '') });
     }
 });
 
-if (props.baseUrl) {
-    onBeforeRouteUpdate(async (to, from) => {
-        if (hasRouteParam(to.params)) {
-            const { matched } = router.currentRoute.value;
-            const { name } = matched.at(-3);
-            if (name) {
-                router.push({ name, params: to.params });
-            }
+onBeforeRouteUpdate(async (to, from) => {
+    if (hasRouteParam(to.params)) {
+        const { matched } = router.currentRoute.value;
+        const { name } = matched.at(-3);
+        if (name) {
+            router.push({ name, params: to.params });
         }
-        if (to.params.id !== from.params.id) {
-            arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
-            await arrayData.fetch({ append: false, updateRouter: false });
-        }
-    });
+    }
+    const id = to.params.id;
+    if (id !== from.params.id) await fetch(id, true);
+});
+
+async function fetch(id, append = false) {
+    const regex = /\/(\d+)/;
+    if (props.idInWhere) arrayData.store.filter.where = { id };
+    else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
+    else arrayData.store.url = props.url.replace(regex, `/${id}`);
+    await arrayData.fetch({ append, updateRouter: false });
 }
 function hasRouteParam(params, valueToCheck = ':addressId') {
     return Object.values(params).includes(valueToCheck);
@@ -74,6 +69,6 @@ function hasRouteParam(params, valueToCheck = ':addressId') {
     </Teleport>
     <VnSubToolbar />
     <div :class="[useCardSize(), $attrs.class]">
-        <RouterView :key="route.path" />
+        <RouterView :key="$route.path" />
     </div>
 </template>
diff --git a/src/components/common/VnCheckbox.vue b/src/components/common/VnCheckbox.vue
new file mode 100644
index 000000000..27131d45e
--- /dev/null
+++ b/src/components/common/VnCheckbox.vue
@@ -0,0 +1,43 @@
+<script setup>
+import { computed } from 'vue';
+
+const model = defineModel({ type: [Number, Boolean] });
+const $props = defineProps({
+    info: {
+        type: String,
+        default: null,
+    },
+});
+
+const checkboxModel = computed({
+    get() {
+        if (typeof model.value === 'number') {
+            return model.value !== 0;
+        }
+        return model.value;
+    },
+    set(value) {
+        if (typeof model.value === 'number') {
+            model.value = value ? 1 : 0;
+        } else {
+            model.value = value;
+        }
+    },
+});
+</script>
+<template>
+    <div>
+        <QCheckbox v-bind="$attrs" v-on="$attrs" v-model="checkboxModel" />
+        <QIcon
+            v-if="info"
+            v-bind="$attrs"
+            class="cursor-info q-ml-sm"
+            name="info"
+            size="sm"
+        >
+            <QTooltip>
+                {{ info }}
+            </QTooltip>
+        </QIcon>
+    </div>
+</template>
diff --git a/src/components/common/VnColor.vue b/src/components/common/VnColor.vue
new file mode 100644
index 000000000..8a5a787b0
--- /dev/null
+++ b/src/components/common/VnColor.vue
@@ -0,0 +1,32 @@
+<script setup>
+const $props = defineProps({
+    colors: {
+        type: String,
+        default: '{"value": []}',
+    },
+});
+
+const colorArray = JSON.parse($props.colors)?.value;
+const maxHeight = 30;
+const colorHeight = maxHeight / colorArray?.length;
+</script>
+<template>
+    <div v-if="colors" class="color-div" :style="{ height: `${maxHeight}px` }">
+        <div
+            v-for="(color, index) in colorArray"
+            :key="index"
+            :style="{
+                backgroundColor: `#${color}`,
+                height: `${colorHeight}px`,
+            }"
+        >
+            &nbsp;
+        </div>
+    </div>
+</template>
+<style scoped>
+.color-div {
+    display: flex;
+    flex-direction: column;
+}
+</style>
diff --git a/src/components/common/VnComponent.vue b/src/components/common/VnComponent.vue
index 580bcf348..a9e1c8cff 100644
--- a/src/components/common/VnComponent.vue
+++ b/src/components/common/VnComponent.vue
@@ -17,6 +17,8 @@ const $props = defineProps({
     },
 });
 
+const emit = defineEmits(['blur']);
+
 const componentArray = computed(() => {
     if (typeof $props.prop === 'object') return [$props.prop];
     return $props.prop;
@@ -46,7 +48,8 @@ function toValueAttrs(attrs) {
     <span
         v-for="toComponent of componentArray"
         :key="toComponent.name"
-        class="column flex-center fit"
+        class="column fit"
+        :class="toComponent?.component == 'checkbox' ? 'flex-center' : ''"
     >
         <component
             v-if="toComponent?.component"
@@ -54,6 +57,7 @@ function toValueAttrs(attrs) {
             v-bind="mix(toComponent).attrs"
             v-on="mix(toComponent).event ?? {}"
             v-model="model"
+            @blur="emit('blur')"
         />
     </span>
 </template>
diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue
index 36c87bab0..424781a26 100644
--- a/src/components/common/VnDmsList.vue
+++ b/src/components/common/VnDmsList.vue
@@ -17,7 +17,7 @@ import { useSession } from 'src/composables/useSession';
 const route = useRoute();
 const quasar = useQuasar();
 const { t } = useI18n();
-const rows = ref();
+const rows = ref([]);
 const dmsRef = ref();
 const formDialog = ref({});
 const token = useSession().getTokenMultimedia();
@@ -389,6 +389,14 @@ defineExpose({
                     </div>
                 </template>
             </QTable>
+            <div 
+                v-else 
+                class="info-row q-pa-md text-center"
+            >
+                <h5>
+                    {{ t('No data to display') }}
+                </h5>
+            </div>
         </template>
     </VnPaginate>
     <QDialog v-model="formDialog.show">
@@ -405,7 +413,7 @@ defineExpose({
             fab
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut
             @click="showFormDialog()"
             class="fill-icon"
         >
diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 78f08a479..aeb4a31fd 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -11,6 +11,7 @@ const emit = defineEmits([
     'update:options',
     'keyup.enter',
     'remove',
+    'blur',
 ]);
 
 const $props = defineProps({
@@ -136,6 +137,7 @@ const handleUppercase = () => {
             :type="$attrs.type"
             :class="{ required: isRequired }"
             @keyup.enter="emit('keyup.enter')"
+            @blur="emit('blur')"
             @keydown="handleKeydown"
             :clearable="false"
             :rules="mixinRules"
@@ -143,7 +145,7 @@ const handleUppercase = () => {
             hide-bottom-space
             :data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
         >
-            <template #prepend>
+            <template #prepend v-if="$slots.prepend">
                 <slot name="prepend" />
             </template>
             <template #append>
@@ -168,11 +170,11 @@ const handleUppercase = () => {
                         }
                     "
                 ></QIcon>
-                
+
                 <QIcon
                     name="match_case"
                     size="xs"
-                    v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
+                    v-if="!$attrs.disabled && !$attrs.readonly && $props.uppercase"
                     @click="handleUppercase"
                     class="uppercase-icon"
                 >
@@ -180,7 +182,7 @@ const handleUppercase = () => {
                         {{ t('Convert to uppercase') }}
                     </QTooltip>
                 </QIcon>
-                
+
                 <slot name="append" v-if="$slots.append && !$attrs.disabled" />
                 <QIcon v-if="info" name="info">
                     <QTooltip max-width="350px">
@@ -194,13 +196,15 @@ const handleUppercase = () => {
 
 <style>
 .uppercase-icon {
-  transition: color 0.3s, transform 0.2s;
-  cursor: pointer;
+    transition:
+        color 0.3s,
+        transform 0.2s;
+    cursor: pointer;
 }
 
 .uppercase-icon:hover {
-  color: #ed9937;
-  transform: scale(1.2);
+    color: #ed9937;
+    transform: scale(1.2);
 }
 </style>
 <i18n>
@@ -214,4 +218,4 @@ const handleUppercase = () => {
         maxLength: El valor excede los {value} carácteres
         inputMax: Debe ser menor a {value}
         Convert to uppercase: Convertir a mayúsculas
-</i18n>
\ No newline at end of file
+</i18n>
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index 13c141343..1f4705faa 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -42,7 +42,7 @@ const formattedDate = computed({
                 if (value.at(2) == '/') value = value.split('/').reverse().join('/');
                 value = date.formatDate(
                     new Date(value).toISOString(),
-                    'YYYY-MM-DDTHH:mm:ss.SSSZ'
+                    'YYYY-MM-DDTHH:mm:ss.SSSZ',
                 );
             }
             const [year, month, day] = value.split('-').map((e) => parseInt(e));
@@ -55,7 +55,7 @@ const formattedDate = computed({
                     orgDate.getHours(),
                     orgDate.getMinutes(),
                     orgDate.getSeconds(),
-                    orgDate.getMilliseconds()
+                    orgDate.getMilliseconds(),
                 );
             }
         }
@@ -64,7 +64,7 @@ const formattedDate = computed({
 });
 
 const popupDate = computed(() =>
-    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
+    model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value,
 );
 onMounted(() => {
     // fix quasar bug
@@ -73,7 +73,7 @@ onMounted(() => {
 watch(
     () => model.value,
     (val) => (formattedDate.value = val),
-    { immediate: true }
+    { immediate: true },
 );
 
 const styleAttrs = computed(() => {
diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue
index 165cfae3d..274f78b21 100644
--- a/src/components/common/VnInputNumber.vue
+++ b/src/components/common/VnInputNumber.vue
@@ -8,6 +8,7 @@ defineProps({
 });
 
 const model = defineModel({ type: [Number, String] });
+const emit = defineEmits(['blur']);
 </script>
 <template>
     <VnInput
@@ -24,5 +25,6 @@ const model = defineModel({ type: [Number, String] });
                     model = parseFloat(val).toFixed(decimalPlaces);
             }
         "
+        @blur="emit('blur')"
     />
 </template>
diff --git a/src/components/common/VnPopupProxy.vue b/src/components/common/VnPopupProxy.vue
new file mode 100644
index 000000000..f386bfff8
--- /dev/null
+++ b/src/components/common/VnPopupProxy.vue
@@ -0,0 +1,38 @@
+<script setup>
+import { ref } from 'vue';
+
+defineProps({
+    label: {
+        type: String,
+        default: '',
+    },
+    icon: {
+        type: String,
+        required: true,
+        default: null,
+    },
+    color: {
+        type: String,
+        default: 'primary',
+    },
+    tooltip: {
+        type: String,
+        default: null,
+    },
+});
+const popupProxyRef = ref(null);
+</script>
+
+<template>
+    <QBtn :color="$props.color" :icon="$props.icon" :label="$t($props.label)">
+        <template #default>
+            <slot name="extraIcon"></slot>
+            <QPopupProxy ref="popupProxyRef" style="max-width: none">
+                <QCard>
+                    <slot :popup="popupProxyRef"></slot>
+                </QCard>
+            </QPopupProxy>
+            <QTooltip>{{ $t($props.tooltip) }}</QTooltip>
+        </template>
+    </QBtn>
+</template>
diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
index ef65b841f..4bd17124f 100644
--- a/src/components/common/VnSection.vue
+++ b/src/components/common/VnSection.vue
@@ -106,7 +106,14 @@ function checkIsMain() {
                     :data-key="dataKey"
                     :array-data="arrayData"
                     :columns="columns"
-                />
+                >
+                    <template #moreFilterPanel="{ params, orders, searchFn }">
+                        <slot
+                            name="moreFilterPanel"
+                            v-bind="{ params, orders, searchFn }"
+                        />
+                    </template>
+                </VnTableFilter>
             </slot>
         </template>
     </RightAdvancedMenu>
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 95fe80a69..339f90e0e 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -10,7 +10,12 @@ const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 const $attrs = useAttrs();
 const { t } = useI18n();
 
-const { isRequired, requiredFieldRule } = useRequired($attrs);
+const isRequired = computed(() => {
+    return useRequired($attrs).isRequired;
+});
+const requiredFieldRule = computed(() => {
+    return useRequired($attrs).requiredFieldRule;
+});
 
 const $props = defineProps({
     modelValue: {
@@ -166,7 +171,8 @@ onMounted(() => {
 });
 
 const arrayDataKey =
-    $props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label);
+    $props.dataKey ??
+    ($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
 
 const arrayData = useArrayData(arrayDataKey, {
     url: $props.url,
@@ -215,7 +221,7 @@ async function fetchFilter(val) {
         optionFilterValue.value ??
         (new RegExp(/\d/g).test(val)
             ? optionValue.value
-            : optionFilter.value ?? optionLabel.value);
+            : (optionFilter.value ?? optionLabel.value));
 
     let defaultWhere = {};
     if ($props.filterOptions.length) {
@@ -234,7 +240,7 @@ async function fetchFilter(val) {
 
     const { data } = await arrayData.applyFilter(
         { filter: filterOptions },
-        { updateRouter: false }
+        { updateRouter: false },
     );
     setOptions(data);
     return data;
@@ -267,7 +273,7 @@ async function filterHandler(val, update) {
                 ref.setOptionIndex(-1);
                 ref.moveOptionSelection(1, true);
             }
-        }
+        },
     );
 }
 
@@ -303,7 +309,7 @@ function handleKeyDown(event) {
         if (inputValue) {
             const matchingOption = myOptions.value.find(
                 (option) =>
-                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase()
+                    option[optionLabel.value].toLowerCase() === inputValue.toLowerCase(),
             );
 
             if (matchingOption) {
@@ -315,11 +321,11 @@ function handleKeyDown(event) {
         }
 
         const focusableElements = document.querySelectorAll(
-            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])'
+            'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])',
         );
         const currentIndex = Array.prototype.indexOf.call(
             focusableElements,
-            event.target
+            event.target,
         );
         if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) {
             focusableElements[currentIndex + 1].focus();
diff --git a/src/components/common/VnSelectCache.vue b/src/components/common/VnSelectCache.vue
index 29cf22dc5..f0f3357f6 100644
--- a/src/components/common/VnSelectCache.vue
+++ b/src/components/common/VnSelectCache.vue
@@ -14,7 +14,7 @@ const $props = defineProps({
     },
 });
 const options = ref([]);
-
+const emit = defineEmits(['blur']);
 onBeforeMount(async () => {
     const { url, optionValue, optionLabel } = useAttrs();
     const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
@@ -35,5 +35,5 @@ onBeforeMount(async () => {
 });
 </script>
 <template>
-    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" />
+    <VnSelect v-bind="$attrs" :options="$attrs.options ?? options" @blur="emit('blur')" />
 </template>
diff --git a/src/components/common/VnSelectDialog.vue b/src/components/common/VnSelectDialog.vue
index a4cd0011d..41730b217 100644
--- a/src/components/common/VnSelectDialog.vue
+++ b/src/components/common/VnSelectDialog.vue
@@ -37,7 +37,6 @@ const isAllowedToCreate = computed(() => {
 
 defineExpose({ vnSelectDialogRef: select });
 </script>
-
 <template>
     <VnSelect
         ref="select"
@@ -67,7 +66,6 @@ defineExpose({ vnSelectDialogRef: select });
         </template>
     </VnSelect>
 </template>
-
 <style lang="scss" scoped>
 .default-icon {
     cursor: pointer;
diff --git a/src/components/common/VnSelectSupplier.vue b/src/components/common/VnSelectSupplier.vue
index f86db4f2d..5b52ae75b 100644
--- a/src/components/common/VnSelectSupplier.vue
+++ b/src/components/common/VnSelectSupplier.vue
@@ -1,9 +1,7 @@
 <script setup>
-import { computed } from 'vue';
 import VnSelect from 'components/common/VnSelect.vue';
 
 const model = defineModel({ type: [String, Number, Object] });
-const url = 'Suppliers';
 </script>
 
 <template>
@@ -11,11 +9,13 @@ const url = 'Suppliers';
         :label="$t('globals.supplier')"
         v-bind="$attrs"
         v-model="model"
-        :url="url"
+        url="Suppliers"
         option-value="id"
         option-label="nickname"
         :fields="['id', 'name', 'nickname', 'nif']"
+        :filter-options="['id', 'name', 'nickname', 'nif']"
         sort-by="name ASC"
+        data-cy="vnSupplierSelect"
     >
         <template #option="scope">
             <QItem v-bind="scope.itemProps">
diff --git a/src/components/common/VnSelectTravelExtended.vue b/src/components/common/VnSelectTravelExtended.vue
new file mode 100644
index 000000000..46538f5f9
--- /dev/null
+++ b/src/components/common/VnSelectTravelExtended.vue
@@ -0,0 +1,50 @@
+<script setup>
+import VnSelectDialog from './VnSelectDialog.vue';
+import FilterTravelForm from 'src/components/FilterTravelForm.vue';
+import { useI18n } from 'vue-i18n';
+import { toDate } from 'src/filters';
+const { t } = useI18n();
+
+const $props = defineProps({
+    data: {
+        type: Object,
+        required: true,
+    },
+    onFilterTravelSelected: {
+        type: Function,
+        required: true,
+    },
+});
+</script>
+<template>
+    <VnSelectDialog
+        :label="t('entry.basicData.travel')"
+        v-bind="$attrs"
+        url="Travels/filter"
+        :fields="['id', 'warehouseInName']"
+        option-value="id"
+        option-label="warehouseInName"
+        map-options
+        hide-selected
+        :required="true"
+        action-icon="filter_alt"
+        :roles-allowed-to-create="['buyer']"
+    >
+        <template #form>
+            <FilterTravelForm @travel-selected="onFilterTravelSelected(data, $event)" />
+        </template>
+        <template #option="scope">
+            <QItem v-bind="scope.itemProps">
+                <QItemSection>
+                    <QItemLabel>
+                        {{ scope.opt?.agencyModeName }} -
+                        {{ scope.opt?.warehouseInName }}
+                        ({{ toDate(scope.opt?.shipped) }}) →
+                        {{ scope.opt?.warehouseOutName }}
+                        ({{ toDate(scope.opt?.landed) }})
+                    </QItemLabel>
+                </QItemSection>
+            </QItem>
+        </template>
+    </VnSelectDialog>
+</template>
diff --git a/src/components/common/__tests__/VnNotes.spec.js b/src/components/common/__tests__/VnNotes.spec.js
index 8f24a7f14..2603bf03c 100644
--- a/src/components/common/__tests__/VnNotes.spec.js
+++ b/src/components/common/__tests__/VnNotes.spec.js
@@ -1,51 +1,78 @@
-import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
+import {
+    describe,
+    it,
+    expect,
+    vi,
+    beforeAll,
+    afterEach,
+    beforeEach,
+    afterAll,
+} from 'vitest';
 import { createWrapper, axios } from 'app/test/vitest/helper';
 import VnNotes from 'src/components/ui/VnNotes.vue';
+import vnDate from 'src/boot/vnDate';
 
 describe('VnNotes', () => {
     let vm;
     let wrapper;
     let spyFetch;
     let postMock;
-    let expectedBody;
-    const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
-
-    function generateExpectedBody() {
-        expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
-    }
-
-    async function setTestParams(text, observationType, type){
-        vm.newNote.text = text;
-        vm.newNote.observationTypeFk = observationType;
-        wrapper.setProps({ selectType: type });
-    }
-
-    beforeAll(async () => {        
-        vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
-
+    let patchMock;
+    let expectedInsertBody;
+    let expectedUpdateBody;
+    const defaultOptions = {
+        url: '/test',
+        body: { name: 'Tony', lastName: 'Stark' },
+        selectType: false,
+        saveUrl: null,
+        justInput: false,
+    };
+    function generateWrapper(
+        options = defaultOptions,
+        text = null,
+        observationType = null,
+    ) {
+        vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
         wrapper = createWrapper(VnNotes, {
-            propsData: {
-                url: '/test',
-                body: { name: 'Tony', lastName: 'Stark' },
-            }
+            propsData: options,
         });
         wrapper = wrapper.wrapper;
         vm = wrapper.vm;
-    });
+        vm.newNote.text = text;
+        vm.newNote.observationTypeFk = observationType;
+    }
+
+    function createSpyFetch() {
+        spyFetch = vi.spyOn(vm.$refs.vnPaginateRef, 'fetch');
+    }
+
+    function generateExpectedBody() {
+        expectedInsertBody = {
+            ...vm.$props.body,
+            ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk },
+        };
+        expectedUpdateBody = { ...vm.$props.body, ...{ notes: vm.newNote.text } };
+    }
 
     beforeEach(() => {
-        postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
-        spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
+        postMock = vi.spyOn(axios, 'post');
+        patchMock = vi.spyOn(axios, 'patch');
     });
 
     afterEach(() => {
         vi.clearAllMocks();
-        expectedBody = {};
+        expectedInsertBody = {};
+        expectedUpdateBody = {};
+    });
+
+    afterAll(() => {
+        vi.restoreAllMocks();
     });
 
     describe('insert', () => {
-        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
-            await setTestParams( null, null, true );
+        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is null', async () => {
+            generateWrapper({ selectType: true });
+            createSpyFetch();
 
             await vm.insert();
 
@@ -53,8 +80,9 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
-            await setTestParams( "", null, false );
+        it('should not call axios.post and vnPaginateRef.fetch when newNote.text is empty', async () => {
+            generateWrapper(null, '');
+            createSpyFetch();
 
             await vm.insert();
 
@@ -62,8 +90,9 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
-            await setTestParams( "Test Note", null, true );
+        it('should not call axios.post and vnPaginateRef.fetch when observationTypeFk is null and selectType is true', async () => {
+            generateWrapper({ selectType: true }, 'Test Note');
+            createSpyFetch();
 
             await vm.insert();
 
@@ -71,37 +100,57 @@ describe('VnNotes', () => {
             expect(spyFetch).not.toHaveBeenCalled();
         });
 
-        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
-            await setTestParams( "Test Note", null, false );
-
+        it('should call axios.post and vnPaginateRef.fetch when observationTypeFk is missing and selectType is false', async () => {
+            generateWrapper(null, 'Test Note');
+            createSpyFetch();
             generateExpectedBody();
 
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
-            expect(spyFetch).toHaveBeenCalled();
-        });
-
-        it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {            
-            await setTestParams( "Test Note", 1, false );
-
-            generateExpectedBody();
-
-            await vm.insert();
-
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
             expect(spyFetch).toHaveBeenCalled();
         });
 
         it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
-            await setTestParams( "Test Note", 1, true );
-
+            generateWrapper({ selectType: true }, 'Test Note', 1);
+            createSpyFetch();
             generateExpectedBody();
-            
+
             await vm.insert();
 
-            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
+            expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedInsertBody);
             expect(spyFetch).toHaveBeenCalled();
         });
     });
-});
\ No newline at end of file
+
+    describe('update', () => {
+        it('should call axios.patch with saveUrl when saveUrl is set and justInput is true', async () => {
+            generateWrapper({
+                url: '/business',
+                justInput: true,
+                saveUrl: '/saveUrlTest',
+            });
+            generateExpectedBody();
+
+            await vm.update();
+
+            expect(patchMock).toHaveBeenCalledWith(vm.$props.saveUrl, expectedUpdateBody);
+        });
+
+        it('should call axios.patch with url when saveUrl is not set and justInput is true', async () => {
+            generateWrapper({
+                url: '/business',
+                body: { workerFk: 1110 },
+                justInput: true,
+            });
+            generateExpectedBody();
+
+            await vm.update();
+
+            expect(patchMock).toHaveBeenCalledWith(
+                `${vm.$props.url}/${vm.$props.body.workerFk}`,
+                expectedUpdateBody,
+            );
+        });
+    });
+});
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index 01027e230..b8db68bee 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 { useClipboard } from 'src/composables/useClipboard';
 import VnMoreOptions from './VnMoreOptions.vue';
 
 const $props = defineProps({
@@ -29,10 +30,6 @@ const $props = defineProps({
         type: String,
         default: null,
     },
-    module: {
-        type: String,
-        default: null,
-    },
     summary: {
         type: Object,
         default: null,
@@ -46,6 +43,7 @@ const $props = defineProps({
 const state = useState();
 const route = useRoute();
 const { t } = useI18n();
+const { copyText } = useClipboard();
 const { viewSummary } = useSummaryDialog();
 let arrayData;
 let store;
@@ -57,12 +55,13 @@ defineExpose({ getData });
 onBeforeMount(async () => {
     arrayData = useArrayData($props.dataKey, {
         url: $props.url,
-        filter: $props.filter,
+        userFilter: $props.filter,
         skip: 0,
+        oneRecord: true,
     });
     store = arrayData.store;
     entity = computed(() => {
-        const data = (Array.isArray(store.data) ? store.data[0] : store.data) ?? {};
+        const data = store.data ?? {};
         if (data) emit('onFetch', data);
         return data;
     });
@@ -84,7 +83,7 @@ async function getData() {
     try {
         const { data } = await arrayData.fetch({ append: false, updateRouter: false });
         state.set($props.dataKey, data);
-        emit('onFetch', Array.isArray(data) ? data[0] : data);
+        emit('onFetch', data);
     } finally {
         isLoading.value = false;
     }
@@ -102,6 +101,14 @@ function getValueFromPath(path) {
     return current;
 }
 
+function copyIdText(id) {
+    copyText(id, {
+        component: {
+            copyValue: id,
+        },
+    });
+}
+
 const emit = defineEmits(['onFetch']);
 
 const iconModule = computed(() => route.matched[1].meta.icon);
@@ -147,7 +154,9 @@ const toModule = computed(() =>
                         {{ t('components.smartCard.openSummary') }}
                     </QTooltip>
                 </QBtn>
-                <RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }">
+                <RouterLink
+                    :to="{ name: `${dataKey}Summary`, params: { id: entity.id } }"
+                >
                     <QBtn
                         class="link"
                         color="white"
@@ -186,6 +195,19 @@ const toModule = computed(() =>
                     <QItem>
                         <QItemLabel class="subtitle">
                             #{{ getValueFromPath(subtitle) ?? entity.id }}
+                            <QBtn
+                                round
+                                flat
+                                dense
+                                size="sm"
+                                icon="content_copy"
+                                color="primary"
+                                @click.stop="copyIdText(entity.id)"
+                            >
+                                <QTooltip>
+                                    {{ t('globals.copyId') }}
+                                </QTooltip>
+                            </QBtn>
                         </QItemLabel>
 
                         <QBtn
@@ -308,3 +330,11 @@ const toModule = computed(() =>
     }
 }
 </style>
+<i18n>
+    en:
+        globals:
+            copyId: Copy ID
+    es:
+        globals:
+            copyId: Copiar ID
+</i18n>
diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index c815b8e16..6a61994c1 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -40,9 +40,10 @@ const arrayData = useArrayData(props.dataKey, {
     filter: props.filter,
     userFilter: props.userFilter,
     skip: 0,
+    oneRecord: true,
 });
 const { store } = arrayData;
-const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
+const entity = computed(() => store.data);
 const isLoading = ref(false);
 
 defineExpose({
@@ -61,7 +62,7 @@ async function fetch() {
     store.filter = props.filter ?? {};
     isLoading.value = true;
     const { data } = await arrayData.fetch({ append: false, updateRouter: false });
-    emit('onFetch', Array.isArray(data) ? data[0] : data);
+    emit('onFetch', data);
     isLoading.value = false;
 }
 </script>
@@ -208,4 +209,13 @@ async function fetch() {
 .summaryHeader {
     color: $white;
 }
+
+.cardSummary :deep(.q-card__section[content]) {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 0;
+    > * {
+        flex: 1;
+    }
+}
 </style>
diff --git a/src/components/ui/SkeletonDescriptor.vue b/src/components/ui/SkeletonDescriptor.vue
index 9679751f5..f9188221a 100644
--- a/src/components/ui/SkeletonDescriptor.vue
+++ b/src/components/ui/SkeletonDescriptor.vue
@@ -1,53 +1,32 @@
+<script setup>
+defineProps({
+    hasImage: {
+        type: Boolean,
+        default: false,
+    },
+});
+</script>
 <template>
-    <div id="descriptor-skeleton">
+    <div id="descriptor-skeleton" class="bg-vn-page">
         <div class="row justify-between q-pa-sm">
-            <QSkeleton square size="40px" />
-            <QSkeleton square size="40px" />
-            <QSkeleton square height="40px" width="20px" />
+            <QSkeleton square size="30px" v-for="i in 3" :key="i" />
         </div>
-        <div class="col justify-between q-pa-sm q-gutter-y-xs">
-            <QSkeleton square height="40px" width="150px" />
-            <QSkeleton square height="30px" width="70px" />
+        <div class="q-pa-xs" v-if="hasImage">
+            <QSkeleton square height="200px" width="100%" />
         </div>
-        <div class="col q-pl-sm q-pa-sm q-mb-md">
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
-            </div>
-            <div class="row justify-between">
-                <QSkeleton type="text" square height="30px" width="20%" />
-                <QSkeleton type="text" square height="30px" width="60%" />
+        <div class="col justify-between q-pa-md q-gutter-y-xs">
+            <QSkeleton square height="25px" width="150px" />
+            <QSkeleton square height="15px" width="70px" />
+        </div>
+        <div class="q-pl-sm q-pa-sm q-mb-md">
+            <div class="row q-gutter-x-sm q-pa-none q-ma-none" v-for="i in 5" :key="i">
+                <QSkeleton type="text" square height="20px" width="30%" />
+                <QSkeleton type="text" square height="20px" width="60%" />
             </div>
         </div>
 
-        <QCardActions>
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
-            <QSkeleton size="40px" />
+        <QCardActions class="q-gutter-x-sm justify-between">
+            <QSkeleton size="40px" v-for="i in 5" :key="i" />
         </QCardActions>
     </div>
 </template>
-
-<style lang="scss" scoped>
-#descriptor-skeleton .q-card__actions {
-    justify-content: space-between;
-}
-</style>
diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue
index a02b56bdb..c6f539879 100644
--- a/src/components/ui/VnConfirm.vue
+++ b/src/components/ui/VnConfirm.vue
@@ -82,7 +82,7 @@ function cancel() {
                     @click="cancel()"
                 />
             </QCardSection>
-            <QCardSection class="q-pb-none">
+            <QCardSection class="q-pb-none" data-cy="VnConfirm_message">
                 <span v-if="message !== false" v-html="message" />
             </QCardSection>
             <QCardSection class="row items-center q-pt-none">
@@ -95,6 +95,7 @@ function cancel() {
                     :disable="isLoading"
                     flat
                     @click="cancel()"
+                    data-cy="VnConfirm_cancel"
                 />
                 <QBtn
                     :label="t('globals.confirm')"
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 93f069cc6..d6b525dc8 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -114,7 +114,7 @@ async function clearFilters() {
         arrayData.resetPagination();
         // Filtrar los params no removibles
         const removableFilters = Object.keys(userParams.value).filter((param) =>
-            $props.unremovableParams.includes(param)
+            $props.unremovableParams.includes(param),
         );
         const newParams = {};
         // Conservar solo los params que no son removibles
@@ -162,13 +162,13 @@ const formatTags = (tags) => {
 
 const tags = computed(() => {
     const filteredTags = tagsList.value.filter(
-        (tag) => !($props.customTags || []).includes(tag.label)
+        (tag) => !($props.customTags || []).includes(tag.label),
     );
     return formatTags(filteredTags);
 });
 
 const customTags = computed(() =>
-    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
+    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label)),
 );
 
 async function remove(key) {
@@ -188,10 +188,13 @@ function formatValue(value) {
 const getLocale = (label) => {
     const param = label.split('.').at(-1);
     const globalLocale = `globals.params.${param}`;
+    const moduleName = route.meta.moduleName;
+    const moduleLocale = `${moduleName.toLowerCase()}.${param}`;
     if (te(globalLocale)) return t(globalLocale);
-    else if (te(t(`params.${param}`)));
+    else if (te(moduleLocale)) return t(moduleLocale);
     else {
-        const camelCaseModuleName = route.meta.moduleName.charAt(0).toLowerCase() + route.meta.moduleName.slice(1);    
+        const camelCaseModuleName =
+            moduleName.charAt(0).toLowerCase() + moduleName.slice(1);
         return t(`${camelCaseModuleName}.params.${param}`);
     }
 };
@@ -290,6 +293,9 @@ const getLocale = (label) => {
     />
 </template>
 <style scoped lang="scss">
+.q-field__label.no-pointer-events.absolute.ellipsis {
+    margin-left: 6px !important;
+}
 .list {
     width: 256px;
 }
diff --git a/src/components/ui/VnMoreOptions.vue b/src/components/ui/VnMoreOptions.vue
index 39e84be2b..8a1c7a0f2 100644
--- a/src/components/ui/VnMoreOptions.vue
+++ b/src/components/ui/VnMoreOptions.vue
@@ -11,7 +11,7 @@
         <QTooltip>
             {{ $t('components.cardDescriptor.moreOptions') }}
         </QTooltip>
-        <QMenu ref="menuRef">
+        <QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
             <QList>
                 <slot name="menu" :menu-ref="$refs.menuRef" />
             </QList>
diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue
index 1690a94ba..ec6289a67 100644
--- a/src/components/ui/VnNotes.vue
+++ b/src/components/ui/VnNotes.vue
@@ -1,6 +1,6 @@
 <script setup>
 import axios from 'axios';
-import { ref, reactive } from 'vue';
+import { ref, reactive, useAttrs, computed } from 'vue';
 import { onBeforeRouteLeave } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useQuasar } from 'quasar';
@@ -16,12 +16,27 @@ import VnSelect from 'components/common/VnSelect.vue';
 import FetchData from 'components/FetchData.vue';
 import VnInput from 'components/common/VnInput.vue';
 
+const emit = defineEmits(['onFetch']);
+
+const originalAttrs = useAttrs();
+
+const $attrs = computed(() => {
+    const { style, ...rest } = originalAttrs;
+    return rest;
+});
+
+const isRequired = computed(() => {
+    return Object.keys($attrs).includes('required')
+});
+
 const $props = defineProps({
     url: { type: String, default: null },
+    saveUrl: {type: String, default: null},
     filter: { type: Object, default: () => {} },
     body: { type: Object, default: () => {} },
     addNote: { type: Boolean, default: false },
     selectType: { type: Boolean, default: false },
+    justInput: { type: Boolean, default: false },
 });
 
 const { t } = useI18n();
@@ -29,6 +44,13 @@ const quasar = useQuasar();
 const newNote = reactive({ text: null, observationTypeFk: null });
 const observationTypes = ref([]);
 const vnPaginateRef = ref();
+let originalText;
+
+function handleClick(e) {
+    if (e.shiftKey && e.key === 'Enter') return;
+    if ($props.justInput) confirmAndUpdate();
+    else insert();
+}
 
 async function insert() {
     if (!newNote.text || ($props.selectType && !newNote.observationTypeFk)) return;
@@ -41,8 +63,36 @@ async function insert() {
     await axios.post($props.url, newBody);
     await vnPaginateRef.value.fetch();
 }
+
+function confirmAndUpdate() {
+    if(!newNote.text && originalText)
+        quasar
+            .dialog({
+                component: VnConfirm,
+                componentProps: {
+                    title: t('New note is empty'),
+                    message: t('Are you sure remove this note?'),
+                },
+            })
+            .onOk(update)
+            .onCancel(() => {
+                newNote.text = originalText;
+            });
+    else update();
+}
+
+async function update() {
+    originalText = newNote.text;
+    const body = $props.body;
+    const newBody = {
+        ...body,
+        ...{ notes: newNote.text },
+    };
+    await axios.patch(`${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, newBody);
+}
+
 onBeforeRouteLeave((to, from, next) => {
-    if (newNote.text)
+    if ((newNote.text && !$props.justInput) || (newNote.text !== originalText) && $props.justInput)
         quasar.dialog({
             component: VnConfirm,
             componentProps: {
@@ -53,6 +103,13 @@ onBeforeRouteLeave((to, from, next) => {
         });
     else next();
 });
+
+function fetchData([ data ]) {
+    newNote.text = data?.notes;
+    originalText = data?.notes;
+    emit('onFetch', data);
+}
+
 </script>
 <template>
     <FetchData
@@ -62,8 +119,19 @@ onBeforeRouteLeave((to, from, next) => {
         auto-load
         @on-fetch="(data) => (observationTypes = data)"
     />
-    <QCard class="q-pa-xs q-mb-lg full-width" v-if="$props.addNote">
-        <QCardSection horizontal>
+    <FetchData
+        v-if="justInput"
+        :url="url"
+        :filter="filter"
+        @on-fetch="fetchData"
+        auto-load
+    />
+    <QCard 
+        class="q-pa-xs q-mb-lg full-width" 
+        :class="{ 'just-input': $props.justInput }"
+        v-if="$props.addNote || $props.justInput"
+    >
+        <QCardSection horizontal v-if="!$props.justInput">
             {{ t('New note') }}
         </QCardSection>
         <QCardSection class="q-px-xs q-my-none q-py-none">
@@ -75,19 +143,19 @@ onBeforeRouteLeave((to, from, next) => {
                     v-model="newNote.observationTypeFk"
                     option-label="description"
                     style="flex: 0.15"
-                    :required="true"
+                    :required="isRequired"
                     @keyup.enter.stop="insert"
                 />
                 <VnInput
                     v-model.trim="newNote.text"
                     type="textarea"
-                    :label="t('Add note here...')"
+                    :label="$props.justInput && newNote.text ? '' : t('Add note here...')"
                     filled
                     size="lg"
                     autogrow
-                    @keyup.enter.stop="insert"
+                    @keyup.enter.stop="handleClick"
+                    :required="isRequired"
                     clearable
-                    :required="true"
                 >
                     <template #append>
                         <QBtn
@@ -95,7 +163,7 @@ onBeforeRouteLeave((to, from, next) => {
                             icon="save"
                             color="primary"
                             flat
-                            @click="insert"
+                            @click="handleClick"
                             class="q-mb-xs"
                             dense
                             data-cy="saveNote"
@@ -106,6 +174,7 @@ onBeforeRouteLeave((to, from, next) => {
         </QCardSection>
     </QCard>
     <VnPaginate
+        v-if="!$props.justInput"
         :data-key="$props.url"
         :url="$props.url"
         order="created DESC"
@@ -198,6 +267,11 @@ onBeforeRouteLeave((to, from, next) => {
         }
     }
 }
+.just-input {
+    padding-right: 18px;
+    margin-bottom: 2px;
+    box-shadow: none;
+}
 </style>
 <i18n>
     es:
@@ -205,4 +279,6 @@ onBeforeRouteLeave((to, from, next) => {
         New note: Nueva nota
         Save (Enter): Guardar (Intro)
         Observation type: Tipo de observación
+        New note is empty: La nueva nota esta vacia
+        Are you sure remove this note?: Estas seguro de quitar esta nota?
 </i18n>
diff --git a/src/components/ui/VnStockValueDisplay.vue b/src/components/ui/VnStockValueDisplay.vue
new file mode 100644
index 000000000..d8f43323b
--- /dev/null
+++ b/src/components/ui/VnStockValueDisplay.vue
@@ -0,0 +1,41 @@
+<script setup>
+import { toPercentage } from 'filters/index';
+
+import { computed } from 'vue';
+
+const props = defineProps({
+    value: {
+        type: Number,
+        required: true,
+    },
+});
+
+const valueClass = computed(() =>
+    props.value === 0 ? 'neutral' : props.value > 0 ? 'positive' : 'negative',
+);
+const iconName = computed(() =>
+    props.value === 0 ? 'equal' : props.value > 0 ? 'arrow_upward' : 'arrow_downward',
+);
+const formattedValue = computed(() => props.value);
+</script>
+<template>
+    <span :class="valueClass">
+        <QIcon :name="iconName" size="sm" class="value-icon" />
+        {{ toPercentage(formattedValue) }}
+    </span>
+</template>
+
+<style lang="scss" scoped>
+.positive {
+    color: $secondary;
+}
+.negative {
+    color: $negative;
+}
+.neutral {
+    color: $primary;
+}
+.value-icon {
+    margin-right: 4px;
+}
+</style>
diff --git a/src/components/ui/VnSubToolbar.vue b/src/components/ui/VnSubToolbar.vue
index 5ded4be00..8d4126d1d 100644
--- a/src/components/ui/VnSubToolbar.vue
+++ b/src/components/ui/VnSubToolbar.vue
@@ -19,23 +19,26 @@ onMounted(() => {
     const observer = new MutationObserver(
         () =>
             (hasContent.value =
-                actions.value?.childNodes?.length + data.value?.childNodes?.length)
+                actions.value?.childNodes?.length + data.value?.childNodes?.length),
     );
     if (actions.value) observer.observe(actions.value, opts);
     if (data.value) observer.observe(data.value, opts);
 });
 
-onBeforeUnmount(() => stateStore.toggleSubToolbar());
+const actionsChildCount = () => !!actions.value?.childNodes?.length;
+
+onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
 </script>
 
 <template>
     <QToolbar
         id="subToolbar"
-        class="justify-end sticky"
         v-show="hasContent || $slots['st-actions'] || $slots['st-data']"
+        class="justify-end sticky"
     >
         <slot name="st-data">
-            <div id="st-data"></div>
+            <div id="st-data" :class="{ 'full-width': !actionsChildCount() }">
+            </div>
         </slot>
         <QSpace />
         <slot name="st-actions">
diff --git a/src/components/ui/__tests__/CardSummary.spec.js b/src/components/ui/__tests__/CardSummary.spec.js
index 411ebf9bb..2f7f90882 100644
--- a/src/components/ui/__tests__/CardSummary.spec.js
+++ b/src/components/ui/__tests__/CardSummary.spec.js
@@ -51,16 +51,6 @@ describe('CardSummary', () => {
         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 newUrl = 'CardSummary/35';
         const newKey = 'cardSummaryKey/35';
@@ -72,7 +62,7 @@ describe('CardSummary', () => {
         expect(vm.store.filter).toEqual({ key: newKey });
     });
 
-    it('should return true if route path ends with /summary' , () => {
+    it('should return true if route path ends with /summary', () => {
         expect(vm.isSummary).toBe(true);
     });
-});
\ No newline at end of file
+});
diff --git a/src/composables/__tests__/useArrayData.spec.js b/src/composables/__tests__/useArrayData.spec.js
index d4c5d0949..a610ba9eb 100644
--- a/src/composables/__tests__/useArrayData.spec.js
+++ b/src/composables/__tests__/useArrayData.spec.js
@@ -16,7 +16,7 @@ describe('useArrayData', () => {
         vi.clearAllMocks();
     });
 
-    it('should fetch and repalce url with new params', async () => {
+    it('should fetch and replace url with new params', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
@@ -33,11 +33,11 @@ describe('useArrayData', () => {
         });
         expect(routerReplace.path).toEqual('mockSection/list');
         expect(JSON.parse(routerReplace.query.params)).toEqual(
-            expect.objectContaining(params)
+            expect.objectContaining(params),
         );
     });
 
-    it('Should get data and send new URL without keeping parameters, if there is only one record', async () => {
+    it('should get data and send new URL without keeping parameters, if there is only one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }] });
 
         const arrayData = useArrayData('ArrayData', { url: 'mockUrl', navigate: {} });
@@ -56,7 +56,7 @@ describe('useArrayData', () => {
         expect(routerPush.query).toBeUndefined();
     });
 
-    it('Should get data and send new URL keeping parameters, if you have more than one record', async () => {
+    it('should get data and send new URL keeping parameters, if you have more than one record', async () => {
         vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [{ id: 1 }, { id: 2 }] });
 
         vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
@@ -95,4 +95,25 @@ describe('useArrayData', () => {
         expect(routerPush.path).toEqual('mockName/');
         expect(routerPush.query.params).toBeDefined();
     });
+
+    it('should return one record', async () => {
+        vi.spyOn(axios, 'get').mockReturnValueOnce({
+            data: [
+                { id: 1, name: 'Entity 1' },
+                { id: 2, name: 'Entity 2' },
+            ],
+        });
+        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
+        await arrayData.fetch({});
+
+        expect(arrayData.store.data).toEqual({ id: 1, name: 'Entity 1' });
+    });
+
+    it('should handle empty data gracefully if has to return one record', async () => {
+        vi.spyOn(axios, 'get').mockReturnValueOnce({ data: [] });
+        const arrayData = useArrayData('ArrayData', { url: 'mockUrl', oneRecord: true });
+        await arrayData.fetch({});
+
+        expect(arrayData.store.data).toBeUndefined();
+    });
 });
diff --git a/src/composables/checkEntryLock.js b/src/composables/checkEntryLock.js
new file mode 100644
index 000000000..f964dea27
--- /dev/null
+++ b/src/composables/checkEntryLock.js
@@ -0,0 +1,65 @@
+import { useQuasar } from 'quasar';
+import { useI18n } from 'vue-i18n';
+import { useRouter } from 'vue-router';
+import axios from 'axios';
+import VnConfirm from 'components/ui/VnConfirm.vue';
+
+export async function checkEntryLock(entryFk, userFk) {
+    const { t } = useI18n();
+    const quasar = useQuasar();
+    const { push } = useRouter();
+    const { data } = await axios.get(`Entries/${entryFk}`, {
+        params: {
+            filter: JSON.stringify({
+                fields: ['id', 'locked', 'lockerUserFk'],
+                include: { relation: 'user', scope: { fields: ['id', 'nickname'] } },
+            }),
+        },
+    });
+    const entryConfig = await axios.get('EntryConfigs/findOne');
+
+    if (data?.lockerUserFk && data?.locked) {
+        const now = new Date(Date.vnNow()).getTime();
+        const lockedTime = new Date(data.locked).getTime();
+        const timeDiff = (now - lockedTime) / 1000;
+        const isMaxTimeLockExceeded = entryConfig.data.maxLockTime > timeDiff;
+
+        if (data?.lockerUserFk !== userFk && isMaxTimeLockExceeded) {
+            quasar
+                .dialog({
+                    component: VnConfirm,
+                    componentProps: {
+                        'data-cy': 'entry-lock-confirm',
+                        title: t('entry.lock.title'),
+                        message: t('entry.lock.message', {
+                            userName: data?.user?.nickname,
+                            time: timeDiff / 60,
+                        }),
+                    },
+                })
+                .onOk(
+                    async () =>
+                        await axios.patch(`Entries/${entryFk}`, {
+                            locked: Date.vnNow(),
+                            lockerUserFk: userFk,
+                        }),
+                )
+                .onCancel(() => {
+                    push({ path: `summary` });
+                });
+        }
+    } else {
+        await axios
+            .patch(`Entries/${entryFk}`, {
+                locked: Date.vnNow(),
+                lockerUserFk: userFk,
+            })
+            .then(
+                quasar.notify({
+                    message: t('entry.lock.success'),
+                    color: 'positive',
+                    group: false,
+                }),
+            );
+    }
+}
diff --git a/src/composables/getColAlign.js b/src/composables/getColAlign.js
new file mode 100644
index 000000000..a930fd7d8
--- /dev/null
+++ b/src/composables/getColAlign.js
@@ -0,0 +1,22 @@
+export function getColAlign(col) {
+    let align;
+    switch (col.component) {
+        case 'time':
+        case 'date':
+        case 'select':
+            align = 'left';
+            break;
+        case 'number':
+            align = 'right';
+            break;
+        case 'checkbox':
+            align = 'center';
+            break;
+        default:
+            align = col?.align;
+    }
+
+    if (/^is[A-Z]/.test(col.name) || /^has[A-Z]/.test(col.name)) align = 'center';
+
+    return 'text-' + (align ?? 'center');
+}
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index bd3cecf08..fcc61972a 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -57,6 +57,7 @@ export function useArrayData(key, userOptions) {
             'navigate',
             'mapKey',
             'keepData',
+            'oneRecord',
         ];
         if (typeof userOptions === 'object') {
             for (const option in userOptions) {
@@ -112,7 +113,11 @@ export function useArrayData(key, userOptions) {
         store.isLoading = false;
         canceller = null;
 
-        processData(response.data, { map: !!store.mapKey, append });
+        processData(response.data, {
+            map: !!store.mapKey,
+            append,
+            oneRecord: store.oneRecord,
+        });
 
         return response;
     }
@@ -314,7 +319,11 @@ export function useArrayData(key, userOptions) {
         return { params, limit };
     }
 
-    function processData(data, { map = true, append = true }) {
+    function processData(data, { map = true, append = true, oneRecord = false }) {
+        if (oneRecord) {
+            store.data = Array.isArray(data) ? data[0] : data;
+            return;
+        }
         if (!append) {
             store.data = [];
             store.map = new Map();
diff --git a/src/composables/useRole.js b/src/composables/useRole.js
index 3ec65dd0a..ff54b409c 100644
--- a/src/composables/useRole.js
+++ b/src/composables/useRole.js
@@ -27,6 +27,15 @@ export function useRole() {
 
         return false;
     }
+    function likeAny(roles) {
+        const roleStore = state.getRoles();
+        for (const role of roles) {
+            if (!roleStore.value.findIndex((rs) => rs.startsWith(role)) !== -1)
+                return true;
+        }
+
+        return false;
+    }
     function isEmployee() {
         return hasAny(['employee']);
     }
@@ -35,6 +44,7 @@ export function useRole() {
         isEmployee,
         fetch,
         hasAny,
+        likeAny,
         state,
     };
 }
diff --git a/src/css/app.scss b/src/css/app.scss
index a002db9d2..994ae7ff1 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -21,7 +21,10 @@ body.body--light {
     .q-header .q-toolbar {
         color: var(--vn-text-color);
     }
+
+    --vn-color-negative: $negative;
 }
+
 body.body--dark {
     --vn-header-color: #5d5d5d;
     --vn-page-color: #222;
@@ -37,6 +40,8 @@ body.body--dark {
     --vn-text-color-contrast: black;
 
     background-color: var(--vn-page-color);
+
+    --vn-color-negative: $negative;
 }
 
 a {
@@ -75,7 +80,6 @@ a {
     text-decoration: underline;
 }
 
-// Removes chrome autofill background
 input:-webkit-autofill,
 select:-webkit-autofill {
     color: var(--vn-text-color);
@@ -149,11 +153,6 @@ select:-webkit-autofill {
     cursor: pointer;
 }
 
-.vn-table-separation-row {
-    height: 16px !important;
-    background-color: var(--vn-section-color) !important;
-}
-
 /* Estilo para el asterisco en campos requeridos */
 .q-field.required .q-field__label:after {
     content: ' *';
@@ -212,6 +211,10 @@ select:-webkit-autofill {
     justify-content: center;
 }
 
+.q-card__section[dense] {
+    padding: 0;
+}
+
 input[type='number'] {
     -moz-appearance: textfield;
 }
@@ -226,10 +229,12 @@ input::-webkit-inner-spin-button {
     max-width: 100%;
 }
 
-.q-table__container {
-    /* ===== Scrollbar CSS ===== /
-    / Firefox */
+.remove-bg {
+    filter: brightness(1.1);
+    mix-blend-mode: multiply;
+}
 
+.q-table__container {
     * {
         scrollbar-width: auto;
         scrollbar-color: var(--vn-label-color) transparent;
@@ -270,8 +275,6 @@ input::-webkit-inner-spin-button {
             font-size: 11pt;
         }
         td {
-            font-size: 11pt;
-            border-top: 1px solid var(--vn-page-color);
             border-collapse: collapse;
         }
     }
@@ -315,9 +318,6 @@ input::-webkit-inner-spin-button {
     max-width: fit-content;
 }
 
-.row > .column:has(.q-checkbox) {
-    max-width: fit-content;
-}
 .q-field__inner {
     .q-field__control {
         min-height: auto !important;
diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss
index d6e992437..22c6d2b56 100644
--- a/src/css/quasar.variables.scss
+++ b/src/css/quasar.variables.scss
@@ -13,7 +13,7 @@
 // Tip: Use the "Theme Builder" on Quasar's documentation website.
 // Tip: to add new colors https://quasar.dev/style/color-palette/#adding-your-own-colors
 $primary: #ec8916;
-$secondary: $primary;
+$secondary: #89be34;
 $positive: #c8e484;
 $negative: #fb5252;
 $info: #84d0e2;
@@ -30,7 +30,9 @@ $color-spacer: #7979794d;
 $border-thin-light: 1px solid $color-spacer-light;
 $primary-light: #f5b351;
 $dark-shadow-color: black;
-$layout-shadow-dark: 0 0 10px 2px #00000033, 0 0px 10px #0000003d;
+$layout-shadow-dark:
+    0 0 10px 2px #00000033,
+    0 0px 10px #0000003d;
 $spacing-md: 16px;
 $color-font-secondary: #777;
 $width-xs: 400px;
diff --git a/src/filters/toDate.js b/src/filters/toDate.js
index 8fe8f3836..002797af5 100644
--- a/src/filters/toDate.js
+++ b/src/filters/toDate.js
@@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
 export default function (value, options = {}) {
     if (!value) return;
 
+    if (!isValidDate(value)) return null;
+
     if (!options.dateStyle && !options.timeStyle) {
         options.day = '2-digit';
         options.month = '2-digit';
@@ -10,7 +12,12 @@ export default function (value, options = {}) {
     }
 
     const { locale } = useI18n();
-    const date = new Date(value);
+    const newDate = new Date(value);
 
-    return new Intl.DateTimeFormat(locale.value, options).format(date);
+    return new Intl.DateTimeFormat(locale.value, options).format(newDate);
+}
+// handle 0000-00-00
+function isValidDate(date) {
+    const parsedDate = new Date(date);
+    return parsedDate instanceof Date && !isNaN(parsedDate.getTime());
 }
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 7d0f3e0b2..9a60e9da1 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -33,6 +33,7 @@ globals:
     reset: Reset
     close: Close
     cancel: Cancel
+    isSaveAndContinue: Save and continue
     clone: Clone
     confirm: Confirm
     assign: Assign
@@ -156,6 +157,7 @@ globals:
     changeState: Change state
     raid: 'Raid {daysInForward} days'
     isVies: Vies
+    noData: No data available
     pageTitles:
         logIn: Login
         addressEdit: Update address
@@ -168,6 +170,7 @@ globals:
         workCenters: Work centers
         modes: Modes
         zones: Zones
+        negative: Negative
         zonesList: List
         deliveryDays: Delivery days
         upcomingDeliveries: Upcoming deliveries
@@ -175,6 +178,7 @@ globals:
         alias: Alias
         aliasUsers: Users
         subRoles: Subroles
+        myAccount: Mi cuenta
         inheritedRoles: Inherited Roles
         customers: Customers
         customerCreate: New customer
@@ -333,10 +337,13 @@ globals:
         wasteRecalc: Waste recaclulate
         operator: Operator
         parking: Parking
+        vehicleList: Vehicles
+        vehicle: Vehicle
     unsavedPopup:
         title: Unsaved changes will be lost
         subtitle: Are you sure exit without saving?
     params:
+        description: Description
         clientFk: Client id
         salesPersonFk: Sales person
         warehouseFk: Warehouse
@@ -359,7 +366,13 @@ globals:
         correctingFk: Rectificative
         daysOnward: Days onward
         countryFk: Country
+        countryCodeFk: Country
         companyFk: Company
+    model: Model
+    fuel: Fuel
+    active: Active
+    inactive: Inactive
+    deliveryPoint: Delivery point
 errors:
     statusUnauthorized: Access denied
     statusInternalServerError: An internal server error has ocurred
@@ -398,6 +411,106 @@ cau:
     subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
     inputLabel: Explain why this error should not appear
     askPrivileges: Ask for privileges
+entry:
+    list:
+        newEntry: New entry
+        tableVisibleColumns:
+            isExcludedFromAvailable: Exclude from inventory
+            isOrdered: Ordered
+            isConfirmed: Ready to label
+            isReceived: Received
+            isRaid: Raid
+            landed: Date
+            supplierFk: Supplier
+            reference: Ref/Alb/Guide
+            invoiceNumber: Invoice
+            agencyModeId: Agency
+            isBooked: Booked
+            companyFk: Company
+            evaNotes: Notes
+            warehouseOutFk: Origin
+            warehouseInFk: Destiny
+            entryTypeDescription: Entry type
+            invoiceAmount: Import
+            travelFk: Travel
+    summary:
+        invoiceAmount: Amount
+        commission: Commission
+        currency: Currency
+        invoiceNumber: Invoice number
+        ordered: Ordered
+        booked: Booked
+        excludedFromAvailable: Inventory
+        travelReference: Reference
+        travelAgency: Agency
+        travelShipped: Shipped
+        travelDelivered: Delivered
+        travelLanded: Landed
+        travelReceived: Received
+        buys: Buys
+        stickers: Stickers
+        package: Package
+        packing: Pack.
+        grouping: Group.
+        buyingValue: Buying value
+        import: Import
+        pvp: PVP
+    basicData:
+        travel: Travel
+        currency: Currency
+        commission: Commission
+        observation: Observation
+        booked: Booked
+        excludedFromAvailable: Inventory
+    buys:
+        observations: Observations
+        packagingFk: Box
+        color: Color
+        printedStickers: Printed stickers
+    notes:
+        observationType: Observation type
+    latestBuys:
+        tableVisibleColumns:
+            image: Picture
+            itemFk: Item ID
+            weightByPiece: Weight/Piece
+            isActive: Active
+            family: Family
+            entryFk: Entry
+            freightValue: Freight value
+            comissionValue: Commission value
+            packageValue: Package value
+            isIgnored: Is ignored
+            price2: Grouping
+            price3: Packing
+            minPrice: Min
+            ektFk: Ekt
+            packingOut: Package out
+            landing: Landing
+            isExcludedFromAvailable: Exclude from inventory
+            isRaid: Raid
+            invoiceNumber: Invoice
+            reference: Ref/Alb/Guide
+    params:
+        isExcludedFromAvailable: Excluir del inventario
+        isOrdered: Pedida
+        isConfirmed: Lista para etiquetar
+        isReceived: Recibida
+        isRaid: Redada
+        landed: Fecha
+        supplierFk: Proveedor
+        invoiceNumber: Nº Factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Agencia
+        isBooked: Asentado
+        companyFk: Empresa
+        travelFk: Envio
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeDescription: Tipo entrada
+        invoiceAmount: Importe
+        dated: Fecha
 ticket:
     params:
         ticketFk: Ticket ID
@@ -627,6 +740,8 @@ wagon:
         name: Name
 
 supplier:
+    search: Search supplier
+    searchInfo: Search supplier by id or name
     list:
         payMethod: Pay method
         account: Account
@@ -716,6 +831,8 @@ travel:
         CloneTravelAndEntries: Clone travel and his entries
         deleteTravel: Delete travel
         AddEntry: Add entry
+        availabled: Availabled
+        availabledHour: Availabled hour
         thermographs: Thermographs
         hb: HB
     basicData:
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 7ca9e4b4c..846c442ea 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -33,9 +33,11 @@ globals:
     reset: Restaurar
     close: Cerrar
     cancel: Cancelar
+    isSaveAndContinue: Guardar y continuar
     clone: Clonar
     confirm: Confirmar
     assign: Asignar
+    replace: Sustituir
     back: Volver
     yes: Si
     no: No
@@ -48,6 +50,7 @@ globals:
     rowRemoved: Fila eliminada
     pleaseWait: Por favor espera...
     noPinnedModules: No has fijado ningún módulo
+    split: Split
     enterToConfirm: Pulsa Enter para confirmar
     summary:
         basicData: Datos básicos
@@ -56,8 +59,8 @@ globals:
     today: Hoy
     yesterday: Ayer
     dateFormat: es-ES
-    microsip: Abrir en MicroSIP
     noSelectedRows: No tienes ninguna línea seleccionada
+    microsip: Abrir en MicroSIP
     downloadCSVSuccess: Descarga de CSV exitosa
     reference: Referencia
     agency: Agencia
@@ -77,8 +80,10 @@ globals:
     requiredField: Campo obligatorio
     class: clase
     type: Tipo
-    reason: motivo
+    reason: Motivo
+    removeSelection: Eliminar selección
     noResults: Sin resultados
+    results: resultados
     system: Sistema
     notificationSent: Notificación enviada
     warehouse: Almacén
@@ -156,6 +161,7 @@ globals:
     changeState: Cambiar estado
     raid: 'Redada {daysInForward} días'
     isVies: Vies
+    noData: Datos no disponibles
     pageTitles:
         logIn: Inicio de sesión
         addressEdit: Modificar consignatario
@@ -167,6 +173,7 @@ globals:
         agency: Agencia
         workCenters: Centros de trabajo
         modes: Modos
+        negative: Tickets negativos
         zones: Zonas
         zonesList: Listado
         deliveryDays: Días de entrega
@@ -287,9 +294,9 @@ globals:
         buyRequest: Peticiones de compra
         wasteBreakdown: Deglose de mermas
         itemCreate: Nuevo artículo
-        tax: 'IVA'
-        botanical: 'Botánico'
-        barcode: 'Código de barras'
+        tax: IVA
+        botanical: Botánico
+        barcode: Código de barras
         itemTypeCreate: Nueva familia
         family: Familia
         lastEntries: Últimas entradas
@@ -333,10 +340,13 @@ globals:
         wasteRecalc: Recalcular mermas
         operator: Operario
         parking: Parking
+        vehicleList: Vehículos
+        vehicle: Vehículo
     unsavedPopup:
         title: Los cambios que no haya guardado se perderán
         subtitle: ¿Seguro que quiere salir sin guardar?
     params:
+        description: Descripción
         clientFk: Id cliente
         salesPersonFk: Comercial
         warehouseFk: Almacén
@@ -350,13 +360,14 @@ globals:
         from: Desde
         to: Hasta
         supplierFk: Proveedor
-        supplierRef: Ref. proveedor
+        supplierRef: Nº factura
         serial: Serie
         amount: Importe
         awbCode: AWB
         daysOnward: Días adelante
         packing: ITP
         countryFk: País
+        countryCodeFk: País
         companyFk: Empresa
 errors:
     statusUnauthorized: Acceso denegado
@@ -394,6 +405,87 @@ cau:
     subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
     inputLabel: Explique el motivo por el que no deberia aparecer este fallo
     askPrivileges: Solicitar permisos
+entry:
+    list:
+        newEntry: Nueva entrada
+        tableVisibleColumns:
+            isExcludedFromAvailable: Excluir del inventario
+            isOrdered: Pedida
+            isConfirmed: Lista para etiquetar
+            isReceived: Recibida
+            isRaid: Redada
+            landed: Fecha
+            supplierFk: Proveedor
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
+            agencyModeId: Agencia
+            isBooked: Asentado
+            companyFk: Empresa
+            travelFk: Envio
+            evaNotes: Notas
+            warehouseOutFk: Origen
+            warehouseInFk: Destino
+            entryTypeDescription: Tipo entrada
+            invoiceAmount: Importe
+    summary:
+        invoiceAmount: Importe
+        commission: Comisión
+        currency: Moneda
+        invoiceNumber: Núm. factura
+        ordered: Pedida
+        booked: Contabilizada
+        excludedFromAvailable: Inventario
+        travelReference: Referencia
+        travelAgency: Agencia
+        travelShipped: F. envio
+        travelWarehouseOut: Alm. salida
+        travelDelivered: Enviada
+        travelLanded: F. entrega
+        travelReceived: Recibida
+        buys: Compras
+        stickers: Etiquetas
+        package: Embalaje
+        packing: Pack.
+        grouping: Group.
+        buyingValue: Coste
+        import: Importe
+        pvp: PVP
+    basicData:
+        travel: Envío
+        currency: Moneda
+        observation: Observación
+        commission: Comisión
+        booked: Asentado
+        excludedFromAvailable: Inventario
+    buys:
+        observations: Observaciónes
+        packagingFk: Embalaje
+        color: Color
+        printedStickers: Etiquetas impresas
+    notes:
+        observationType: Tipo de observación
+    latestBuys:
+        tableVisibleColumns:
+            image: Foto
+            itemFk: Id Artículo
+            weightByPiece: Peso (gramos)/tallo
+            isActive: Activo
+            family: Familia
+            entryFk: Entrada
+            freightValue: Porte
+            comissionValue: Comisión
+            packageValue: Embalaje
+            isIgnored: Ignorado
+            price2: Grouping
+            price3: Packing
+            minPrice: Min
+            ektFk: Ekt
+            packingOut: Embalaje envíos
+            landing: Llegada
+            isExcludedFromAvailable: Excluir del inventario
+            isRaid: Redada
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
 ticket:
     params:
         ticketFk: ID de ticket
@@ -407,6 +499,38 @@ ticket:
         freightItemName: Nombre
         packageItemName: Embalaje
         longName: Descripción
+    pageTitles:
+        tickets: Tickets
+        list: Listado
+        ticketCreate: Nuevo ticket
+        summary: Resumen
+        basicData: Datos básicos
+        boxing: Encajado
+        sms: Sms
+        notes: Notas
+        sale: Lineas del pedido
+        dms: Gestión documental
+        negative: Tickets negativos
+        volume: Volumen
+        observation: Notas
+        ticketAdvance: Adelantar tickets
+        futureTickets: Tickets a futuro
+        expedition: Expedición
+        purchaseRequest: Petición de compra
+        weeklyTickets: Tickets programados
+        saleTracking: Líneas preparadas
+        services: Servicios
+        tracking: Estados
+        components: Componentes
+        pictures: Fotos
+        packages: Bultos
+    list:
+        nickname: Alias
+        state: Estado
+        shipped: Enviado
+        landed: Entregado
+        salesPerson: Comercial
+        total: Total
     card:
         customerId: ID cliente
         customerCard: Ficha del cliente
@@ -453,15 +577,11 @@ ticket:
         consigneeStreet: Dirección
     create:
         address: Dirección
-order:
-    field:
-        salesPersonFk: Comercial
-    form:
-        clientFk: Cliente
-        addressFk: Dirección
-        agencyModeFk: Agencia
-    list:
-        newOrder: Nuevo Pedido
+invoiceOut:
+    card:
+        issued: Fecha emisión
+        customerCard: Ficha del cliente
+        ticketList: Listado de tickets
     summary:
         issued: Fecha
         dued: Fecha límite
@@ -472,6 +592,71 @@ order:
         fee: Cuota
         tickets: Tickets
         totalWithVat: Importe
+    globalInvoices:
+        errors:
+            chooseValidClient: Selecciona un cliente válido
+            chooseValidCompany: Selecciona una empresa válida
+            chooseValidPrinter: Selecciona una impresora válida
+            chooseValidSerialType: Selecciona una tipo de serie válida
+            fillDates: La fecha de la factura y la fecha máxima deben estar completas
+            invoiceDateLessThanMaxDate: La fecha de la factura no puede ser menor que la fecha máxima
+            invoiceWithFutureDate: Existe una factura con una fecha futura
+            noTicketsToInvoice: No existen tickets para facturar
+            criticalInvoiceError: Error crítico en la facturación proceso detenido
+            invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
+        table:
+            addressId: Id dirección
+            streetAddress: Dirección fiscal
+        statusCard:
+            percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
+            pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
+    negativeBases:
+        clientId: Id cliente
+        base: Base
+        active: Activo
+        hasToInvoice: Facturar
+        verifiedData: Datos comprobados
+        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
+        priority: Prioridad
+        newShelving: Nuevo Carro
+    summary:
+        recyclable: Reciclable
+parking:
+    pickingOrder: Orden de recogida
+    row: Fila
+    column: Columna
+    searchBar:
+        info: Puedes buscar por código de parking
+        label: Buscar parking...
 department:
     chat: Chat
     bossDepartment: Jefe de departamento
@@ -632,8 +817,8 @@ wagon:
         volumeNotEmpty: El volumen no puede estar vacío
         typeNotEmpty: El tipo no puede estar vacío
         maxTrays: Has alcanzado el número máximo de bandejas
-        minHeightBetweenTrays: 'La distancia mínima entre bandejas es '
-        maxWagonHeight: 'La altura máxima del vagón es '
+        minHeightBetweenTrays: La distancia mínima entre bandejas es
+        maxWagonHeight: La altura máxima del vagón es
         uncompleteTrays: Hay bandejas sin completar
     params:
         label: Etiqueta
@@ -641,6 +826,8 @@ wagon:
         volume: Volumen
         name: Nombre
 supplier:
+    search: Buscar proveedor
+    searchInfo: Buscar proveedor por id o nombre
     list:
         payMethod: Método de pago
         account: Cuenta
@@ -731,6 +918,8 @@ travel:
         deleteTravel: Eliminar envío
         AddEntry: Añadir entrada
         thermographs: Termógrafos
+        availabled: F. Disponible
+        availabledHour: Hora Disponible
         hb: HB
     basicData:
         daysInForward: Desplazamiento automatico (redada)
@@ -779,7 +968,7 @@ components:
     cardDescriptor:
         mainList: Listado principal
         summary: Resumen
-        moreOptions: 'Más opciones'
+        moreOptions: Más opciones
     leftMenu:
         addToPinned: Añadir a fijados
         removeFromPinned: Eliminar de fijados
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 2a84e5aa1..3ad1c79bc 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -2,7 +2,7 @@
 import Navbar from 'src/components/NavBar.vue';
 </script>
 <template>
-    <QLayout view="hHh LpR fFf" v-shortcut>
+    <QLayout view="hHh LpR fFf">
         <Navbar />
         <RouterView></RouterView>
         <QFooter v-if="$q.platform.is.mobile"></QFooter>
diff --git a/src/layouts/OutLayout.vue b/src/layouts/OutLayout.vue
index 4ccc6bf9e..eba57c198 100644
--- a/src/layouts/OutLayout.vue
+++ b/src/layouts/OutLayout.vue
@@ -1,12 +1,12 @@
 <script setup>
 import { Dark, Quasar } from 'quasar';
-import { computed } from 'vue';
+import { computed, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { localeEquivalence } from 'src/i18n/index';
 import quasarLang from 'src/utils/quasarLang';
+import { langs } from 'src/boot/defaults/constants.js';
 
 const { t, locale } = useI18n();
-
 const userLocale = computed({
     get() {
         return locale.value;
@@ -28,7 +28,6 @@ const darkMode = computed({
         Dark.set(value);
     },
 });
-const langs = ['en', 'es'];
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountAliasList.vue b/src/pages/Account/AccountAliasList.vue
index f6016fb6c..19682286c 100644
--- a/src/pages/Account/AccountAliasList.vue
+++ b/src/pages/Account/AccountAliasList.vue
@@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n';
 import { ref, computed } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import VnSection from 'src/components/common/VnSection.vue';
+import exprBuilder from './Alias/AliasExprBuilder';
 
 const tableRef = ref();
 const { t } = useI18n();
@@ -31,15 +32,6 @@ const columns = computed(() => [
         create: true,
     },
 ]);
-
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : { alias: { like: `%${value}%` } };
-    }
-};
 </script>
 
 <template>
diff --git a/src/pages/Account/AccountExprBuilder.js b/src/pages/Account/AccountExprBuilder.js
new file mode 100644
index 000000000..6497a9d30
--- /dev/null
+++ b/src/pages/Account/AccountExprBuilder.js
@@ -0,0 +1,18 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'nickname':
+            return { [param]: { like: `%${value}%` } };
+        case 'roleFk':
+            return { [param]: value };
+    }
+};
diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue
index ea8daba0d..976af1d19 100644
--- a/src/pages/Account/AccountList.vue
+++ b/src/pages/Account/AccountList.vue
@@ -4,15 +4,16 @@ import { computed, ref } from 'vue';
 import VnTable from 'components/VnTable/VnTable.vue';
 import AccountSummary from './Card/AccountSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import exprBuilder from './AccountExprBuilder.js';
+import filter from './Card/AccountFilter.js';
 import VnSection from 'src/components/common/VnSection.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
-const filter = {
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
+const tableRef = ref();
+
 const dataKey = 'AccountList';
 const roles = ref([]);
 const columns = computed(() => [
@@ -117,25 +118,6 @@ const columns = computed(() => [
         ],
     },
 ]);
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'nickname':
-            return { [param]: { like: `%${value}%` } };
-        case 'roleFk':
-            return { [param]: value };
-    }
-}
 </script>
 <template>
     <FetchData url="VnRoles" @on-fetch="(data) => (roles = data)" auto-load />
diff --git a/src/pages/Account/Alias/AliasExprBuilder.js b/src/pages/Account/Alias/AliasExprBuilder.js
new file mode 100644
index 000000000..f7a5a104c
--- /dev/null
+++ b/src/pages/Account/Alias/AliasExprBuilder.js
@@ -0,0 +1,8 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : { alias: { like: `%${value}%` } };
+    }
+};
diff --git a/src/pages/Account/Alias/Card/AliasCard.vue b/src/pages/Account/Alias/Card/AliasCard.vue
index 3a814edc0..f37bd7d0f 100644
--- a/src/pages/Account/Alias/Card/AliasCard.vue
+++ b/src/pages/Account/Alias/Card/AliasCard.vue
@@ -1,21 +1,13 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AliasDescriptor from './AliasDescriptor.vue';
-const { t } = useI18n();
 </script>
 
 <template>
     <VnCardBeta
         data-key="Alias"
-        base-url="MailAliases"
+        url="MailAliases"
         :descriptor="AliasDescriptor"
         search-data-key="AccountAliasList"
-        :searchbar-props="{
-            url: 'MailAliases',
-            info: t('mailAlias.searchInfo'),
-            label: t('mailAlias.search'),
-            searchUrl: 'table',
-        }"
     />
 </template>
diff --git a/src/pages/Account/Alias/Card/AliasDescriptor.vue b/src/pages/Account/Alias/Card/AliasDescriptor.vue
index 2e01fad01..671ef7fbc 100644
--- a/src/pages/Account/Alias/Card/AliasDescriptor.vue
+++ b/src/pages/Account/Alias/Card/AliasDescriptor.vue
@@ -7,7 +7,6 @@ import { useQuasar } from 'quasar';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 
@@ -29,9 +28,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.alias, entity.id));
-
 const removeAlias = () => {
     quasar
         .dialog({
@@ -55,11 +51,8 @@ const removeAlias = () => {
     <CardDescriptor
         ref="descriptor"
         :url="`MailAliases/${entityId}`"
-        module="Alias"
-        @on-fetch="setData"
-        data-key="aliasData"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        data-key="Alias"
+        title="alias"
     >
         <template #menu>
             <QItem v-ripple clickable @click="removeAlias()">
diff --git a/src/pages/Account/Alias/Card/AliasSummary.vue b/src/pages/Account/Alias/Card/AliasSummary.vue
index 1f76fe7c2..b4b9abd25 100644
--- a/src/pages/Account/Alias/Card/AliasSummary.vue
+++ b/src/pages/Account/Alias/Card/AliasSummary.vue
@@ -1,13 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
-import { useArrayData } from 'src/composables/useArrayData';
-
 const route = useRoute();
 const { t } = useI18n();
 
@@ -18,20 +16,15 @@ const $props = defineProps({
     },
 });
 
-const { store } = useArrayData('Alias');
-const alias = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
 </script>
 
 <template>
-    <CardSummary
-        ref="summary"
-        :url="`MailAliases/${entityId}`"
-        @on-fetch="(data) => (alias = data)"
-        data-key="MailAliasesSummary"
-    >
-        <template #header> {{ alias.id }} - {{ alias.alias }} </template>
-        <template #body>
+    <CardSummary ref="summary" :url="`MailAliases/${entityId}`" data-key="Alias">
+        <template #header="{ entity: alias }">
+            {{ alias.id }} - {{ alias.alias }}
+        </template>
+        <template #body="{ entity: alias }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
diff --git a/src/pages/Account/Card/AccountBasicData.vue b/src/pages/Account/Card/AccountBasicData.vue
index e6c9da6fe..393f9eb80 100644
--- a/src/pages/Account/Card/AccountBasicData.vue
+++ b/src/pages/Account/Card/AccountBasicData.vue
@@ -1,46 +1,20 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
 import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-import { ref, watch } from 'vue';
-
-const route = useRoute();
-const { t } = useI18n();
-const formModelRef = ref(null);
-
-const accountFilter = {
-    where: { id: route.params.id },
-    fields: ['id', 'email', 'nickname', 'name', 'accountStateFk', 'packages', 'pickup'],
-    include: [],
-};
-
-watch(
-    () => route.params.id,
-    () => formModelRef.value.reset()
-);
 </script>
 <template>
-    <FormModel
-        ref="formModelRef"
-        url="VnUsers/preview"
-        :url-update="`VnUsers/${route.params.id}/update-user`"
-        :filter="accountFilter"
-        model="Accounts"
-        auto-load
-        @on-data-saved="formModelRef.fetch()"
-    >
+    <FormModel :url-update="`VnUsers/${$route.params.id}/update-user`" model="Account">
         <template #form="{ data }">
             <div class="q-gutter-y-sm">
-                <VnInput v-model="data.name" :label="t('account.card.nickname')" />
-                <VnInput v-model="data.nickname" :label="t('account.card.alias')" />
-                <VnInput v-model="data.email" :label="t('globals.params.email')" />
+                <VnInput v-model="data.name" :label="$t('account.card.nickname')" />
+                <VnInput v-model="data.nickname" :label="$t('account.card.alias')" />
+                <VnInput v-model="data.email" :label="$t('globals.params.email')" />
                 <VnSelect
                     url="Languages"
                     v-model="data.lang"
-                    :label="t('account.card.lang')"
+                    :label="$t('account.card.lang')"
                     option-value="code"
                     option-label="code"
                 />
@@ -49,7 +23,7 @@ watch(
                     table="user"
                     column="twoFactor"
                     v-model="data.twoFactor"
-                    :label="t('account.card.twoFactor')"
+                    :label="$t('account.card.twoFactor')"
                     option-value="code"
                     option-label="code"
                 />
diff --git a/src/pages/Account/Card/AccountCard.vue b/src/pages/Account/Card/AccountCard.vue
index 35ff7e732..a5037e301 100644
--- a/src/pages/Account/Card/AccountCard.vue
+++ b/src/pages/Account/Card/AccountCard.vue
@@ -1,8 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import AccountDescriptor from './AccountDescriptor.vue';
+import filter from './AccountFilter.js';
 </script>
-
 <template>
-    <VnCardBeta data-key="AccountId" :descriptor="AccountDescriptor" />
+    <VnCardBeta
+        url="VnUsers/preview"
+        :id-in-where="true"
+        data-key="Account"
+        :descriptor="AccountDescriptor"
+        :filter="filter"
+    />
 </template>
diff --git a/src/pages/Account/Card/AccountDescriptor.vue b/src/pages/Account/Card/AccountDescriptor.vue
index 4e5328de6..49328fe87 100644
--- a/src/pages/Account/Card/AccountDescriptor.vue
+++ b/src/pages/Account/Card/AccountDescriptor.vue
@@ -1,36 +1,18 @@
 <script setup>
 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 VnImg from 'src/components/ui/VnImg.vue';
+import filter from './AccountFilter.js';
 import useHasAccount from 'src/composables/useHasAccount.js';
 
-const $props = defineProps({
-    id: {
-        type: Number,
-        required: false,
-        default: null,
-    },
-});
+const $props = defineProps({ id: { type: Number, default: null } });
 
 const route = useRoute();
-const { t } = useI18n();
-const entityId = computed(() => {
-    return $props.id || route.params.id;
-});
-const data = ref(useCardDescription());
+const entityId = computed(() => $props.id || route.params.id);
 const hasAccount = ref();
-const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
-
-const filter = {
-    where: { id: entityId },
-    fields: ['id', 'nickname', 'name', 'role'],
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
 
 onMounted(async () => {
     hasAccount.value = await useHasAccount(entityId.value);
@@ -41,12 +23,9 @@ onMounted(async () => {
     <CardDescriptor
         ref="descriptor"
         :url="`VnUsers/preview`"
-        :filter="filter"
-        module="Account"
-        @on-fetch="setData"
-        data-key="AccountId"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        :filter="{ ...filter, where: { id: entityId } }"
+        data-key="Account"
+        title="nickname"
     >
         <template #menu>
             <AccountDescriptorMenu :entity-id="entityId" />
@@ -62,7 +41,7 @@ onMounted(async () => {
                                 <QIcon name="vn:claims" />
                             </div>
                             <div class="text-grey-5" style="opacity: 0.4">
-                                {{ t('account.imageNotFound') }}
+                                {{ $t('account.imageNotFound') }}
                             </div>
                         </div>
                     </div>
@@ -70,8 +49,8 @@ onMounted(async () => {
             </VnImg>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('account.card.nickname')" :value="entity.name" />
-            <VnLv :label="t('account.card.role')" :value="entity.role.name" />
+            <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
+            <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
         </template>
         <template #actions="{ entity }">
             <QCardActions class="q-gutter-x-md">
@@ -84,7 +63,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
+                    <QTooltip>{{ $t('account.card.deactivated') }}</QTooltip>
                 </QIcon>
                 <QIcon
                     color="primary"
@@ -95,7 +74,7 @@ onMounted(async () => {
                     size="sm"
                     class="fill-icon"
                 >
-                    <QTooltip>{{ t('account.card.enabled') }}</QTooltip>
+                    <QTooltip>{{ $t('account.card.enabled') }}</QTooltip>
                 </QIcon>
             </QCardActions>
         </template>
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 961323d3a..30584c61f 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -12,6 +12,7 @@ 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';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const $props = defineProps({
     hasAccount: {
@@ -29,7 +30,7 @@ const router = useRouter();
 const state = useState();
 const user = state.getUser();
 const { notify } = useQuasar();
-const account = computed(() => useArrayData('AccountId').store.data[0]);
+const account = computed(() => useArrayData('Account').store.data[0]);
 account.value.hasAccount = hasAccount.value;
 const entityId = computed(() => +route.params.id);
 const hasitManagementAccess = ref();
@@ -124,18 +125,14 @@ onMounted(() => {
         :promise="sync"
     >
         <template #customHTML>
-            {{ shouldSyncPassword }}
-            <QCheckbox
-                :label="t('account.card.actions.sync.checkbox')"
+            <VnCheckbox
                 v-model="shouldSyncPassword"
-                class="full-width"
+                :label="t('account.card.actions.sync.checkbox')"
+                :info="t('account.card.actions.sync.tooltip')"
                 clearable
                 clear-icon="close"
-            >
-                <QIcon style="padding-left: 10px" color="primary" name="info" size="sm">
-                    <QTooltip>{{ t('account.card.actions.sync.tooltip') }}</QTooltip>
-                </QIcon></QCheckbox
-            >
+                color="primary"
+            />
             <VnInputPassword
                 v-if="shouldSyncPassword"
                 :label="t('login.password')"
@@ -155,7 +152,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => deleteAccount()
+                () => deleteAccount(),
             )
         "
     >
@@ -174,7 +171,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.enableAccount.title'),
                 t('account.card.actions.enableAccount.subtitle'),
-                () => updateStatusAccount(true)
+                () => updateStatusAccount(true),
             )
         "
     >
@@ -188,7 +185,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.disableAccount.title'),
                 t('account.card.actions.disableAccount.subtitle'),
-                () => updateStatusAccount(false)
+                () => updateStatusAccount(false),
             )
         "
     >
@@ -203,7 +200,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.activateUser.title'),
                 t('account.card.actions.activateUser.title'),
-                () => updateStatusUser(true)
+                () => updateStatusUser(true),
             )
         "
     >
@@ -217,7 +214,7 @@ onMounted(() => {
             openConfirmationModal(
                 t('account.card.actions.deactivateUser.title'),
                 t('account.card.actions.deactivateUser.title'),
-                () => updateStatusUser(false)
+                () => updateStatusUser(false),
             )
         "
     >
diff --git a/src/pages/Account/Card/AccountFilter.js b/src/pages/Account/Card/AccountFilter.js
new file mode 100644
index 000000000..017876564
--- /dev/null
+++ b/src/pages/Account/Card/AccountFilter.js
@@ -0,0 +1,3 @@
+export default {
+    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
+};
diff --git a/src/pages/Account/Card/AccountMailAlias.vue b/src/pages/Account/Card/AccountMailAlias.vue
index ef1707cf2..7a060cff1 100644
--- a/src/pages/Account/Card/AccountMailAlias.vue
+++ b/src/pages/Account/Card/AccountMailAlias.vue
@@ -86,7 +86,7 @@ watch(
     () => route.params.id,
     () => {
         getAccountData();
-    }
+    },
 );
 
 onMounted(async () => await getAccountData(false));
@@ -130,7 +130,8 @@ onMounted(async () => await getAccountData(false));
                                             openConfirmationModal(
                                                 t('User will be removed from alias'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () => deleteMailAlias(row, rows, rowIndex)
+                                                () =>
+                                                    deleteMailAlias(row, rows, rowIndex),
                                             )
                                         "
                                     >
@@ -157,7 +158,7 @@ onMounted(async () => await getAccountData(false));
                 icon="add"
                 color="primary"
                 @click="openCreateMailAliasForm()"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Account/Card/AccountSummary.vue b/src/pages/Account/Card/AccountSummary.vue
index ca17c7975..f7a16e8c3 100644
--- a/src/pages/Account/Card/AccountSummary.vue
+++ b/src/pages/Account/Card/AccountSummary.vue
@@ -1,58 +1,41 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
-
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-
-import { useArrayData } from 'src/composables/useArrayData';
+import filter from './AccountFilter.js';
 import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
 
+const $props = defineProps({ id: { type: Number, default: 0 } });
+
 const route = useRoute();
-const { t } = useI18n();
-
-const $props = defineProps({
-    id: {
-        type: Number,
-        default: 0,
-    },
-});
-const { store } = useArrayData('Account');
-const account = ref(store.data);
-
 const entityId = computed(() => $props.id || route.params.id);
-const filter = {
-    where: { id: entityId },
-    fields: ['id', 'nickname', 'name', 'role'],
-    include: { relation: 'role', scope: { fields: ['id', 'name'] } },
-};
 </script>
 
 <template>
     <CardSummary
-        data-key="AccountId"
+        data-key="Account"
+        ref="AccountSummary"
         url="VnUsers/preview"
         :filter="filter"
-        @on-fetch="(data) => (account = data)"
     >
-        <template #header>{{ account.id }} - {{ account.nickname }}</template>
-        <template #menu="">
+        <template #header="{ entity }">{{ entity.id }} - {{ entity.nickname }}</template>
+        <template #menu>
             <AccountDescriptorMenu :entity-id="entityId" />
         </template>
-        <template #body>
+        <template #body="{ entity }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <router-link
                         :to="{ name: 'AccountBasicData', params: { id: entityId } }"
                         class="header header-link"
                     >
-                        {{ t('globals.pageTitles.basicData') }}
+                        {{ $t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </router-link>
                 </QCardSection>
-                <VnLv :label="t('account.card.nickname')" :value="account.name" />
-                <VnLv :label="t('account.card.role')" :value="account.role.name" />
+                <VnLv :label="$t('account.card.nickname')" :value="entity.name" />
+                <VnLv :label="$t('account.card.role')" :value="entity.role?.name" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/AccountRoles.vue b/src/pages/Account/Role/AccountRoles.vue
index 3c3d6b243..02f5400c6 100644
--- a/src/pages/Account/Role/AccountRoles.vue
+++ b/src/pages/Account/Role/AccountRoles.vue
@@ -5,6 +5,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
 import { useRoute } from 'vue-router';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import RoleSummary from './Card/RoleSummary.vue';
+import exprBuilder from './RoleExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const route = useRoute();
@@ -66,24 +67,7 @@ const columns = computed(() => [
         ],
     },
 ]);
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'search':
-            return /^\d+$/.test(value)
-                ? { id: value }
-                : {
-                      or: [
-                          { name: { like: `%${value}%` } },
-                          { nickname: { like: `%${value}%` } },
-                      ],
-                  };
-        case 'name':
-        case 'description':
-            return { [param]: { like: `%${value}%` } };
-    }
-};
 </script>
-
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Account/Role/Card/RoleBasicData.vue b/src/pages/Account/Role/Card/RoleBasicData.vue
index 1de9ff387..de70b0fb6 100644
--- a/src/pages/Account/Role/Card/RoleBasicData.vue
+++ b/src/pages/Account/Role/Card/RoleBasicData.vue
@@ -1,24 +1,16 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
-const route = useRoute();
-const { t } = useI18n();
 </script>
 <template>
-    <FormModel :url="`VnRoles/${route.params.id}`" model="VnRole" auto-load>
+    <FormModel model="Role" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <div class="col">
-                    <VnInput v-model="data.name" :label="t('globals.name')" />
-                </div>
+                <VnInput v-model="data.name" :label="$t('globals.name')" />
             </VnRow>
             <VnRow>
-                <div class="col">
-                    <VnInput v-model="data.description" :label="t('role.description')" />
-                </div>
+                <VnInput v-model="data.description" :label="$t('role.description')" />
             </VnRow>
         </template>
     </FormModel>
diff --git a/src/pages/Account/Role/Card/RoleCard.vue b/src/pages/Account/Role/Card/RoleCard.vue
index 7664deca8..ef5b9db04 100644
--- a/src/pages/Account/Role/Card/RoleCard.vue
+++ b/src/pages/Account/Role/Card/RoleCard.vue
@@ -3,5 +3,10 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoleDescriptor from './RoleDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Role" :descriptor="RoleDescriptor" />
+    <VnCardBeta
+        url="VnRoles"
+        data-key="Role"
+        :id-in-where="true"
+        :descriptor="RoleDescriptor"
+    />
 </template>
diff --git a/src/pages/Account/Role/Card/RoleDescriptor.vue b/src/pages/Account/Role/Card/RoleDescriptor.vue
index 0a555346d..517517af0 100644
--- a/src/pages/Account/Role/Card/RoleDescriptor.vue
+++ b/src/pages/Account/Role/Card/RoleDescriptor.vue
@@ -1,10 +1,9 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
 const $props = defineProps({
@@ -26,11 +25,6 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.name, entity.id));
-const filter = {
-    where: { id: entityId },
-};
 const removeRole = async () => {
     await axios.delete(`VnRoles/${entityId.value}`);
     notify(t('Role removed'), 'positive');
@@ -39,13 +33,9 @@ const removeRole = async () => {
 
 <template>
     <CardDescriptor
-        :url="`VnRoles/${entityId}`"
-        :filter="filter"
-        module="Role"
-        @on-fetch="setData"
+        url="VnRoles"
+        :filter="{ where: { id: entityId } }"
         data-key="Role"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :summary="$props.summary"
     >
         <template #menu>
diff --git a/src/pages/Account/Role/Card/RoleSummary.vue b/src/pages/Account/Role/Card/RoleSummary.vue
index f0daa77fb..410f90b17 100644
--- a/src/pages/Account/Role/Card/RoleSummary.vue
+++ b/src/pages/Account/Role/Card/RoleSummary.vue
@@ -1,10 +1,9 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import { useArrayData } from 'src/composables/useArrayData';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -16,24 +15,18 @@ const $props = defineProps({
     },
 });
 
-const { store } = useArrayData('Role');
-const role = ref(store.data);
 const entityId = computed(() => $props.id || route.params.id);
-const filter = {
-    where: { id: entityId },
-};
 </script>
 
 <template>
     <CardSummary
         ref="summary"
-        :url="`VnRoles/${entityId}`"
-        :filter="filter"
-        @on-fetch="(data) => (role = data)"
+        url="VnRoles"
+        :filter="{ where: { id: entityId } }"
         data-key="Role"
     >
-        <template #header> {{ role.id }} - {{ role.name }} </template>
-        <template #body>
+        <template #header="{ entity }"> {{ entity.id }} - {{ entity.name }} </template>
+        <template #body="{ entity }">
             <QCard class="vn-one">
                 <QCardSection class="q-pa-none">
                     <a
@@ -44,9 +37,9 @@ const filter = {
                         <QIcon name="open_in_new" />
                     </a>
                 </QCardSection>
-                <VnLv :label="t('role.id')" :value="role.id" />
-                <VnLv :label="t('globals.name')" :value="role.name" />
-                <VnLv :label="t('role.description')" :value="role.description" />
+                <VnLv :label="t('role.id')" :value="entity.id" />
+                <VnLv :label="t('globals.name')" :value="entity.name" />
+                <VnLv :label="t('role.description')" :value="entity.description" />
             </QCard>
         </template>
     </CardSummary>
diff --git a/src/pages/Account/Role/Card/SubRoles.vue b/src/pages/Account/Role/Card/SubRoles.vue
index 0077f12b0..99cf5e8f0 100644
--- a/src/pages/Account/Role/Card/SubRoles.vue
+++ b/src/pages/Account/Role/Card/SubRoles.vue
@@ -63,7 +63,7 @@ watch(
         store.url = urlPath.value;
         store.filter = filter.value;
         fetchSubRoles();
-    }
+    },
 );
 
 const fetchSubRoles = () => paginateRef.value.fetch();
@@ -109,7 +109,7 @@ const redirectToRoleSummary = (id) =>
                                             openConfirmationModal(
                                                 t('El rol va a ser eliminado'),
                                                 t('¿Seguro que quieres continuar?'),
-                                                () => deleteSubRole(row, rows, rowIndex)
+                                                () => deleteSubRole(row, rows, rowIndex),
                                             )
                                         "
                                     >
@@ -131,7 +131,7 @@ const redirectToRoleSummary = (id) =>
             <QBtn
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
                 color="primary"
                 @click="openCreateSubRoleForm()"
             >
diff --git a/src/pages/Account/Role/RoleExprBuilder.js b/src/pages/Account/Role/RoleExprBuilder.js
new file mode 100644
index 000000000..cc4fab399
--- /dev/null
+++ b/src/pages/Account/Role/RoleExprBuilder.js
@@ -0,0 +1,16 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return /^\d+$/.test(value)
+                ? { id: value }
+                : {
+                      or: [
+                          { name: { like: `%${value}%` } },
+                          { nickname: { like: `%${value}%` } },
+                      ],
+                  };
+        case 'name':
+        case 'description':
+            return { [param]: { like: `%${value}%` } };
+    }
+};
diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue
index 63b0b7c0d..67034da1a 100644
--- a/src/pages/Claim/Card/ClaimBasicData.vue
+++ b/src/pages/Claim/Card/ClaimBasicData.vue
@@ -28,7 +28,6 @@ const workersOptions = ref([]);
         model="Claim"
         :url-update="`Claims/updateClaim/${route.params.id}`"
         auto-load
-        :reload="true"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Claim/Card/ClaimCard.vue b/src/pages/Claim/Card/ClaimCard.vue
index e1e000815..05f3b53a8 100644
--- a/src/pages/Claim/Card/ClaimCard.vue
+++ b/src/pages/Claim/Card/ClaimCard.vue
@@ -4,10 +4,11 @@ import ClaimDescriptor from './ClaimDescriptor.vue';
 import filter from './ClaimFilter.js';
 </script>
 <template>
-    <VnCardBeta 
-        data-key="Claim" 
-        base-url="Claims" 
-        :descriptor="ClaimDescriptor" 
+    <VnCardBeta
+        data-key="Claim"
+        url="Claims"
+        :descriptor="ClaimDescriptor"
+        search-data-key="ClaimList"
         :filter="filter"
     />
 </template>
diff --git a/src/pages/Claim/Card/ClaimDescriptor.vue b/src/pages/Claim/Card/ClaimDescriptor.vue
index 02b63dd8e..4551c58fe 100644
--- a/src/pages/Claim/Card/ClaimDescriptor.vue
+++ b/src/pages/Claim/Card/ClaimDescriptor.vue
@@ -3,12 +3,10 @@ import { ref, computed, onMounted } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toDateHourMinSec, toPercentage } from 'src/filters';
-import { useState } from 'src/composables/useState';
 import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
 import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { getUrl } from 'src/composables/getUrl';
 import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
@@ -23,7 +21,6 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const state = useState();
 const { t } = useI18n();
 const salixUrl = ref();
 const entityId = computed(() => {
@@ -39,12 +36,7 @@ const STATE_COLOR = {
 function stateColor(code) {
     return STATE_COLOR[code];
 }
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    if (!entity) return;
-    data.value = useCardDescription(entity?.client?.name, entity.id);
-    state.set('ClaimDescriptor', entity);
-};
+
 onMounted(async () => {
     salixUrl.value = await getUrl('');
 });
@@ -54,9 +46,7 @@ onMounted(async () => {
     <CardDescriptor
         :url="`Claims/${entityId}`"
         :filter="filter"
-        module="Claim"
         title="client.name"
-        @on-fetch="setData"
         data-key="Claim"
     >
         <template #menu="{ entity }">
@@ -95,7 +85,7 @@ onMounted(async () => {
                     />
                 </template>
             </VnLv>
-            <VnLv :label="t('claim.zone')">
+            <VnLv v-if="entity.ticket?.zone?.id" :label="t('claim.zone')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticket?.zone?.name }}
@@ -107,11 +97,10 @@ onMounted(async () => {
                 :label="t('claim.province')"
                 :value="entity.ticket?.address?.province?.name"
             />
-            <VnLv :label="t('claim.ticketId')">
+            <VnLv v-if="entity.ticketFk" :label="t('claim.ticketId')">
                 <template #value>
                     <span class="link">
                         {{ entity.ticketFk }}
-
                         <TicketDescriptorProxy :id="entity.ticketFk" />
                     </span>
                 </template>
diff --git a/src/pages/Claim/Card/ClaimLines.vue b/src/pages/Claim/Card/ClaimLines.vue
index 33fadd020..dee03b95d 100644
--- a/src/pages/Claim/Card/ClaimLines.vue
+++ b/src/pages/Claim/Card/ClaimLines.vue
@@ -317,7 +317,13 @@ async function saveWhenHasChanges() {
     </div>
 
     <QPageSticky position="bottom-right" :offset="[25, 25]">
-        <QBtn fab color="primary" shortcut="+" icon="add" @click="showImportDialog()" />
+        <QBtn
+            fab
+            color="primary"
+            v-shortcut="'+'"
+            icon="add"
+            @click="showImportDialog()"
+        />
     </QPageSticky>
 </template>
 
diff --git a/src/pages/Claim/Card/ClaimNotes.vue b/src/pages/Claim/Card/ClaimNotes.vue
index 134ee33ab..cc6e33779 100644
--- a/src/pages/Claim/Card/ClaimNotes.vue
+++ b/src/pages/Claim/Card/ClaimNotes.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed } from 'vue';
+import { computed, useAttrs } from 'vue';
 import { useRoute } from 'vue-router';
 import { useState } from 'src/composables/useState';
 import VnNotes from 'src/components/ui/VnNotes.vue';
@@ -7,6 +7,7 @@ import VnNotes from 'src/components/ui/VnNotes.vue';
 const route = useRoute();
 const state = useState();
 const user = state.getUser();
+const $attrs = useAttrs();
 
 const $props = defineProps({
     id: { type: [Number, String], default: null },
diff --git a/src/pages/Claim/Card/ClaimPhoto.vue b/src/pages/Claim/Card/ClaimPhoto.vue
index d4321d8eb..d4acc9bbe 100644
--- a/src/pages/Claim/Card/ClaimPhoto.vue
+++ b/src/pages/Claim/Card/ClaimPhoto.vue
@@ -61,7 +61,7 @@ watch(
     () => {
         claimDmsFilter.value.where.id = router.currentRoute.value.params.id;
         claimDmsRef.value.fetch();
-    }
+    },
 );
 
 function openDialog(dmsId) {
@@ -248,7 +248,7 @@ function onDrag() {
             <QBtn
                 fab
                 @click="inputFile.nativeEl.click()"
-                shortcut="+"
+                v-shortcut="'+'"
                 icon="add"
                 color="primary"
             >
diff --git a/src/pages/Claim/ClaimList.vue b/src/pages/Claim/ClaimList.vue
index 63fd035da..41d0c5598 100644
--- a/src/pages/Claim/ClaimList.vue
+++ b/src/pages/Claim/ClaimList.vue
@@ -132,7 +132,7 @@ const STATE_COLOR = {
         prefix="claim"
         :array-data-props="{
             url: 'Claims/filter',
-            order: ['cs.priority ASC', 'created ASC'],
+            order: 'cs.priority ASC, created ASC',
         }"
     >
         <template #advanced-menu>
diff --git a/src/pages/Customer/Card/CustomerAddress.vue b/src/pages/Customer/Card/CustomerAddress.vue
index 1b0d1dde1..f1799d0cc 100644
--- a/src/pages/Customer/Card/CustomerAddress.vue
+++ b/src/pages/Customer/Card/CustomerAddress.vue
@@ -61,7 +61,7 @@ watch(
     (newValue) => {
         if (!newValue) return;
         getClientData(newValue);
-    }
+    },
 );
 
 const getClientData = async (id) => {
@@ -137,7 +137,7 @@ const toCustomerAddressEdit = (addressId) => {
                         <QIcon
                             :style="{
                                 'font-variation-settings': `'FILL' ${isDefaultAddress(
-                                    item
+                                    item,
                                 )}`,
                             }"
                             color="primary"
@@ -150,7 +150,7 @@ const toCustomerAddressEdit = (addressId) => {
                                     t(
                                         isDefaultAddress(item)
                                             ? 'Default address'
-                                            : 'Set as default'
+                                            : 'Set as default',
                                     )
                                 }}
                             </QTooltip>
@@ -216,7 +216,7 @@ const toCustomerAddressEdit = (addressId) => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New consignee') }}
diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue
index 04ef5f882..11db92eab 100644
--- a/src/pages/Customer/Card/CustomerBalance.vue
+++ b/src/pages/Customer/Card/CustomerBalance.vue
@@ -158,7 +158,7 @@ const columns = computed(() => [
                     openConfirmationModal(
                         t('Send compensation'),
                         t('Do you want to report compensation to the client by mail?'),
-                        () => sendEmail(`Receipts/${id}/balance-compensation-email`)
+                        () => sendEmail(`Receipts/${id}/balance-compensation-email`),
                     ),
             },
         ],
@@ -291,7 +291,7 @@ const showBalancePdf = ({ id }) => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New payment') }}
diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue
index e9a349e0b..36ec4763e 100644
--- a/src/pages/Customer/Card/CustomerBasicData.vue
+++ b/src/pages/Customer/Card/CustomerBasicData.vue
@@ -54,10 +54,10 @@ function onBeforeSave(formData, originalData) {
         auto-load
     />
     <FormModel
-        :url="`Clients/${route.params.id}`"
+        :url-update="`Clients/${route.params.id}`"
         auto-load
-        model="customer"
         :mapper="onBeforeSave"
+        model="Customer"
     >
         <template #form="{ data, validate }">
             <VnRow>
diff --git a/src/pages/Customer/Card/CustomerBillingData.vue b/src/pages/Customer/Card/CustomerBillingData.vue
index f1e78d9e5..cc894d01e 100644
--- a/src/pages/Customer/Card/CustomerBillingData.vue
+++ b/src/pages/Customer/Card/CustomerBillingData.vue
@@ -27,7 +27,7 @@ const getBankEntities = (data, formData) => {
 </script>
 
 <template>
-    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="customer">
+    <FormModel :url-update="`Clients/${route.params.id}`" auto-load model="Customer">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnSelect
diff --git a/src/pages/Customer/Card/CustomerCard.vue b/src/pages/Customer/Card/CustomerCard.vue
index f46884834..75fcb98fa 100644
--- a/src/pages/Customer/Card/CustomerCard.vue
+++ b/src/pages/Customer/Card/CustomerCard.vue
@@ -5,8 +5,8 @@ import CustomerDescriptor from './CustomerDescriptor.vue';
 
 <template>
     <VnCardBeta
-        data-key="Client"
-        base-url="Clients"
+        data-key="Customer"
+        :url="`Clients/${$route.params.id}/getCard`"
         :descriptor="CustomerDescriptor"
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerConsumption.vue b/src/pages/Customer/Card/CustomerConsumption.vue
index f0d8dea47..f3949bb32 100644
--- a/src/pages/Customer/Card/CustomerConsumption.vue
+++ b/src/pages/Customer/Card/CustomerConsumption.vue
@@ -61,6 +61,23 @@ const columns = computed(() => [
         columnFilter: false,
         cardVisible: true,
     },
+    {
+        align: 'left',
+        name: 'buyerId',
+        label: t('customer.params.buyerId'),
+        component: 'select',
+        attrs: {
+            url: 'TicketRequests/getItemTypeWorker',
+            optionLabel: 'nickname',
+            optionValue: 'id',
+
+            fields: ['id', 'nickname'],
+            sortBy: ['nickname ASC'],
+            optionFilter: 'firstName',
+        },
+        cardVisible: false,
+        visible: false,
+    },
     {
         name: 'description',
         align: 'left',
@@ -74,6 +91,7 @@ const columns = computed(() => [
         name: 'quantity',
         label: t('globals.quantity'),
         cardVisible: true,
+        visible: true,
         columnFilter: {
             inWhere: true,
         },
@@ -119,7 +137,7 @@ const openSendEmailDialog = async () => {
     openConfirmationModal(
         t('The consumption report will be sent'),
         t('Please, confirm'),
-        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email })
+        () => sendCampaignMetricsEmail({ address: arrayData.store.data.email }),
     );
 };
 const sendCampaignMetricsEmail = ({ address }) => {
@@ -138,11 +156,11 @@ const updateDateParams = (value, params) => {
     const campaign = campaignList.value.find((c) => c.id === value);
     if (!campaign) return;
 
-    const { dated, previousDays, scopeDays } = campaign;
-    const _date = new Date(dated);
-    const [from, to] = dateRange(_date);
-    params.from = new Date(from.setDate(from.getDate() - previousDays)).toISOString();
-    params.to = new Date(to.setDate(to.getDate() + scopeDays)).toISOString();
+    const { dated, scopeDays } = campaign;
+    const from = new Date(dated);
+    from.setDate(from.getDate() - scopeDays);
+    params.from = from;
+    params.to = dated;
     return params;
 };
 </script>
@@ -152,7 +170,7 @@ const updateDateParams = (value, params) => {
         v-if="campaignList"
         data-key="CustomerConsumption"
         url="Clients/consumption"
-        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"        
+        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"
         :filter="{ where: { clientFk: route.params.id } }"
         :columns="columns"
         search-url="consumption"
@@ -200,29 +218,60 @@ const updateDateParams = (value, params) => {
             <div v-if="row.subName" class="subName">
                 {{ row.subName }}
             </div>
-            <FetchedTags :item="row" :max-length="3" />
+            <FetchedTags :item="row" />
         </template>
         <template #moreFilterPanel="{ params }">
             <div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
+                <VnSelect
+                    :filled="true"
+                    class="q-px-sm q-pt-none fit"
+                    url="ItemTypes"
+                    v-model="params.typeId"
+                    :label="t('item.list.typeName')"
+                    :fields="['id', 'name', 'categoryFk']"
+                    :include="'category'"
+                    :sortBy="'name ASC'"
+                    dense
+                >
+                    <template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                <QItemLabel caption>{{
+                                    scope.opt?.category?.name
+                                }}</QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelect>
+                <VnSelect
+                    :filled="true"
+                    class="q-px-sm q-pt-none fit"
+                    url="ItemCategories"
+                    v-model="params.categoryId"
+                    :label="t('item.list.category')"
+                    :fields="['id', 'name']"
+                    :sortBy="'name ASC'"
+                    dense
+                />
                 <VnSelect
                     v-model="params.campaign"
                     :options="campaignList"
                     :label="t('globals.campaign')"
                     :filled="true"
                     class="q-px-sm q-pt-none fit"
-                    dense
-                    option-label="code"
+                    :option-label="(opt) => t(opt.code)"
+                    :fields="['id', 'code', 'dated', 'scopeDays']"
                     @update:model-value="(data) => updateDateParams(data, params)"
+                    dense
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
                             <QItemSection>
-                                <QItemLabel>
-                                    {{ scope.opt?.code }}
-                                    {{
-                                        new Date(scope.opt?.dated).getFullYear()
-                                    }}</QItemLabel
-                                >
+                                <QItemLabel> {{ t(scope.opt?.code) }} </QItemLabel>
+                                <QItemLabel caption>
+                                    {{ new Date(scope.opt?.dated).getFullYear() }}
+                                </QItemLabel>
                             </QItemSection>
                         </QItem>
                     </template>
@@ -247,7 +296,21 @@ const updateDateParams = (value, params) => {
 </template>
 
 <i18n>
+en:
+
+    valentinesDay: Valentine's Day
+    mothersDay: Mother's Day
+    allSaints: All Saints' Day
+    frenchMothersDay: Mother's Day in France
 es:
     Enter a new search: Introduce una nueva búsqueda
     Group by items: Agrupar por artículos
+    valentinesDay: Día de San Valentín
+    mothersDay: Día de la Madre
+    allSaints: Día de Todos los Santos
+    frenchMothersDay: (Francia) Día de la Madre
+    Campaign consumption: Consumo campaña
+    Campaign: Campaña
+    From: Desde
+    To: Hasta
 </i18n>
diff --git a/src/pages/Customer/Card/CustomerContacts.vue b/src/pages/Customer/Card/CustomerContacts.vue
index c420f650e..d03f71244 100644
--- a/src/pages/Customer/Card/CustomerContacts.vue
+++ b/src/pages/Customer/Card/CustomerContacts.vue
@@ -62,7 +62,7 @@ const customerContactsRef = ref(null);
                                 color="primary"
                                 flat
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                             >
                                 <QTooltip>
                                     {{ t('Add contact') }}
diff --git a/src/pages/Customer/Card/CustomerCreditContracts.vue b/src/pages/Customer/Card/CustomerCreditContracts.vue
index 7dc53db72..a49faeb8d 100644
--- a/src/pages/Customer/Card/CustomerCreditContracts.vue
+++ b/src/pages/Customer/Card/CustomerCreditContracts.vue
@@ -195,7 +195,7 @@ const updateData = () => {
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('New contract') }}
diff --git a/src/pages/Customer/Card/CustomerDescriptor.vue b/src/pages/Customer/Card/CustomerDescriptor.vue
index d7a8a59a1..89f9d9449 100644
--- a/src/pages/Customer/Card/CustomerDescriptor.vue
+++ b/src/pages/Customer/Card/CustomerDescriptor.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { onMounted, ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
@@ -11,6 +11,15 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
+import { useState } from 'src/composables/useState';
+const state = useState();
+
+const customer = ref();
+
+onMounted(async () => {
+    customer.value = state.get('Customer');
+    if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
+});
 
 const customerDebt = ref();
 const customerCredit = ref();
@@ -46,13 +55,10 @@ const debtWarning = computed(() => {
 
 <template>
     <CardDescriptor
-        module="Customer"
         :url="`Clients/${entityId}/getCard`"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
         :summary="$props.summary"
-        data-key="customer"
+        data-key="Customer"
+        @on-fetch="setData"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -61,7 +67,7 @@ const debtWarning = computed(() => {
         <template #body="{ entity }">
             <VnLv
                 :label="t('customer.summary.payMethod')"
-                :value="entity.payMethod.name"
+                :value="entity.payMethod?.name"
             />
 
             <VnLv
@@ -90,7 +96,7 @@ const debtWarning = computed(() => {
             </VnLv>
             <VnLv
                 :label="t('customer.extendedList.tableVisibleColumns.businessTypeFk')"
-                :value="entity.businessType.description"
+                :value="entity.businessType?.description"
             />
         </template>
         <template #icons="{ entity }">
@@ -103,7 +109,21 @@ const debtWarning = computed(() => {
                 >
                     <QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
                 </QIcon>
-                <QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
+
+                <QIcon
+                    v-if="entity?.substitutionAllowed"
+                    name="help"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('Allowed substitution') }}</QTooltip>
+                </QIcon>
+                <QIcon
+                    v-if="customer?.isFreezed"
+                    name="vn:frozen"
+                    size="xs"
+                    color="primary"
+                >
                     <QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
                 </QIcon>
                 <QIcon
@@ -143,13 +163,13 @@ const debtWarning = computed(() => {
                         <br />
                         {{
                             t('unpaidDated', {
-                                dated: toDate(customer.unpaid.dated),
+                                dated: toDate(customer.unpaid?.dated),
                             })
                         }}
                         <br />
                         {{
                             t('unpaidAmount', {
-                                amount: toCurrency(customer.unpaid.amount),
+                                amount: toCurrency(customer.unpaid?.amount),
                             })
                         }}
                     </QTooltip>
diff --git a/src/pages/Customer/Card/CustomerDescriptorMenu.vue b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
index fb78eab69..aea45721c 100644
--- a/src/pages/Customer/Card/CustomerDescriptorMenu.vue
+++ b/src/pages/Customer/Card/CustomerDescriptorMenu.vue
@@ -61,6 +61,16 @@ const openCreateForm = (type) => {
         .join('&');
     useOpenURL(`/#/${type}/list?${params}`);
 };
+const updateSubstitutionAllowed = async () => {
+    try {
+        await axios.patch(`Clients/${route.params.id}`, {
+            substitutionAllowed: !$props.customer.substitutionAllowed,
+        });
+        notify('globals.notificationSent', 'positive');
+    } catch (error) {
+        notify(error.message, 'positive');
+    }
+};
 </script>
 
 <template>
@@ -69,6 +79,13 @@ const openCreateForm = (type) => {
             {{ t('globals.pageTitles.createTicket') }}
         </QItemSection>
     </QItem>
+    <QItem v-ripple clickable>
+        <QItemSection @click="updateSubstitutionAllowed()">{{
+            $props.customer.substitutionAllowed
+                ? t('Disable substitution')
+                : t('Allow substitution')
+        }}</QItemSection>
+    </QItem>
     <QItem v-ripple clickable>
         <QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
     </QItem>
diff --git a/src/pages/Customer/Card/CustomerFileManagement.vue b/src/pages/Customer/Card/CustomerFileManagement.vue
index 134d8dbd6..b565db6e7 100644
--- a/src/pages/Customer/Card/CustomerFileManagement.vue
+++ b/src/pages/Customer/Card/CustomerFileManagement.vue
@@ -236,7 +236,7 @@ const toCustomerFileManagementCreate = () => {
             @click.stop="toCustomerFileManagementCreate()"
             color="primary"
             fab
-            shortcut="+"
+            v-shortcut="'+'"
             icon="add"
         />
         <QTooltip>
diff --git a/src/pages/Customer/Card/CustomerFiscalData.vue b/src/pages/Customer/Card/CustomerFiscalData.vue
index ceeb70bb6..93909eb9c 100644
--- a/src/pages/Customer/Card/CustomerFiscalData.vue
+++ b/src/pages/Customer/Card/CustomerFiscalData.vue
@@ -12,6 +12,7 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 import { getDifferences, getUpdatedValues } from 'src/filters';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 
@@ -73,7 +74,7 @@ async function acceptPropagate({ isEqualizated }) {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateFiscalData`"
         auto-load
-        model="customer"
+        model="Customer"
         :mapper="onBeforeSave"
         observe-form-changes
         @on-data-saved="checkEtChanges"
@@ -151,14 +152,11 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
             <VnRow>
                 <QCheckbox :label="t('Has to invoice')" v-model="data.hasToInvoice" />
-                <div>
-                    <QCheckbox :label="t('globals.isVies')" v-model="data.isVies" />
-                    <QIcon name="info" class="cursor-info q-ml-sm" size="sm">
-                        <QTooltip>
-                            {{ t('whenActivatingIt') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isVies"
+                    :label="t('globals.isVies')"
+                    :info="t('whenActivatingIt')"
+                />
             </VnRow>
 
             <VnRow>
@@ -170,17 +168,11 @@ async function acceptPropagate({ isEqualizated }) {
             </VnRow>
 
             <VnRow>
-                <div>
-                    <QCheckbox
-                        :label="t('Is equalizated')"
-                        v-model="data.isEqualizated"
-                    />
-                    <QIcon class="cursor-info q-ml-sm" name="info" size="sm">
-                        <QTooltip>
-                            {{ t('inOrderToInvoice') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isEqualizated"
+                    :label="t('Is equalizated')"
+                    :info="t('inOrderToInvoice')"
+                />
                 <QCheckbox :label="t('Daily invoice')" v-model="data.hasDailyInvoice" />
             </VnRow>
 
diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue
index b85174696..189b59904 100644
--- a/src/pages/Customer/Card/CustomerNotes.vue
+++ b/src/pages/Customer/Card/CustomerNotes.vue
@@ -23,5 +23,6 @@ const noteFilter = computed(() => {
         :body="{ clientFk: route.params.id }"
         style="overflow-y: auto"
         :select-type="true"
+        required
     />
 </template>
diff --git a/src/pages/Customer/Card/CustomerSamples.vue b/src/pages/Customer/Card/CustomerSamples.vue
index f12691112..19a7f8759 100644
--- a/src/pages/Customer/Card/CustomerSamples.vue
+++ b/src/pages/Customer/Card/CustomerSamples.vue
@@ -104,7 +104,7 @@ const tableRef = ref();
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('Send sample') }}
diff --git a/src/pages/Customer/Card/CustomerWebAccess.vue b/src/pages/Customer/Card/CustomerWebAccess.vue
index 3c4106846..809f10918 100644
--- a/src/pages/Customer/Card/CustomerWebAccess.vue
+++ b/src/pages/Customer/Card/CustomerWebAccess.vue
@@ -27,7 +27,7 @@ async function hasCustomerRole() {
     <FormModel
         :url-update="`Clients/${route.params.id}/updateUser`"
         :filter="filter"
-        model="customer"
+        model="Customer"
         :mapper="
             ({ account }) => {
                 const { name, email, active } = account;
diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue
index 9b883daad..1c5a08304 100644
--- a/src/pages/Customer/CustomerFilter.vue
+++ b/src/pages/Customer/CustomerFilter.vue
@@ -51,11 +51,7 @@ const exprBuilder = (param, value) => {
             </QItem>
             <QItem class="q-mb-sm">
                 <QItemSection>
-                    <VnInput
-                        :label="t('globals.name')"
-                        v-model="params.name"
-                        is-outlined
-                    />
+                    <VnInput :label="t('Name')" v-model="params.name" is-outlined />
                 </QItemSection>
             </QItem>
             <QItem class="q-mb-sm">
diff --git a/src/pages/Customer/CustomerList.vue b/src/pages/Customer/CustomerList.vue
index 2f2dd5978..0bfca7910 100644
--- a/src/pages/Customer/CustomerList.vue
+++ b/src/pages/Customer/CustomerList.vue
@@ -274,6 +274,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'isActive',
         label: t('customer.summary.isActive'),
+        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => !value,
@@ -312,6 +313,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'isFreezed',
         label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
+        component: 'checkbox',
         chip: {
             color: null,
             condition: (value) => value,
@@ -429,7 +431,7 @@ function handleLocation(data, location) {
             <VnTable
                 ref="tableRef"
                 :data-key="dataKey"
-                url="Clients/filter"
+                url="Clients/extendedListFilter"
                 :create="{
                     urlCreate: 'Clients/createWithUser',
                     title: t('globals.pageTitles.customerCreate'),
diff --git a/src/pages/Customer/Defaulter/CustomerDefaulter.vue b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
index eca2ad596..dc4ac9162 100644
--- a/src/pages/Customer/Defaulter/CustomerDefaulter.vue
+++ b/src/pages/Customer/Defaulter/CustomerDefaulter.vue
@@ -9,7 +9,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import CustomerDefaulterAddObservation from './CustomerDefaulterAddObservation.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 
diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue
index d650bbbda..f852c160a 100644
--- a/src/pages/Customer/components/CustomerAddressEdit.vue
+++ b/src/pages/Customer/components/CustomerAddressEdit.vue
@@ -233,7 +233,7 @@ function handleLocation(data, location) {
                             postcode: data.postalCode,
                             city: data.city,
                             province: data.province,
-                            country: data.province.country,
+                            country: data.province?.country,
                         }"
                         @update:model-value="(location) => handleLocation(data, location)"
                     ></VnLocation>
@@ -336,7 +336,7 @@ function handleLocation(data, location) {
                 class="cursor-pointer add-icon q-mt-md"
                 flat
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>
                     {{ t('Add note') }}
diff --git a/src/pages/Customer/components/CustomerNewPayment.vue b/src/pages/Customer/components/CustomerNewPayment.vue
index c2c38b55a..8f61bac89 100644
--- a/src/pages/Customer/components/CustomerNewPayment.vue
+++ b/src/pages/Customer/components/CustomerNewPayment.vue
@@ -84,7 +84,7 @@ function setPaymentType(accounting) {
     viewReceipt.value = isCash.value;
     if (accountingType.value.daysInFuture)
         initialData.payed.setDate(
-            initialData.payed.getDate() + accountingType.value.daysInFuture
+            initialData.payed.getDate() + accountingType.value.daysInFuture,
         );
     maxAmount.value = accountingType.value && accountingType.value.maxAmount;
 
@@ -114,7 +114,7 @@ function onBeforeSave(data) {
     if (isCash.value && shouldSendEmail.value && !data.email)
         return notify(t('There is no assigned email for this client'), 'negative');
 
-    data.bankFk = data.bankFk.id;
+    data.bankFk = data.bankFk?.id;
     return data;
 }
 
@@ -189,7 +189,7 @@ async function getAmountPaid() {
             :url-create="urlCreate"
             :mapper="onBeforeSave"
             @on-data-saved="onDataSaved"
-            :prevent-submit="true"
+            prevent-submit
         >
             <template #form="{ data, validate }">
                 <span ref="closeButton" class="row justify-end close-icon" v-close-popup>
diff --git a/src/pages/Customer/components/CustomerSamplesCreate.vue b/src/pages/Customer/components/CustomerSamplesCreate.vue
index 754693672..1294a5d25 100644
--- a/src/pages/Customer/components/CustomerSamplesCreate.vue
+++ b/src/pages/Customer/components/CustomerSamplesCreate.vue
@@ -18,6 +18,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import CustomerSamplesPreview from 'src/pages/Customer/components/CustomerSamplesPreview.vue';
 import FormPopup from 'src/components/FormPopup.vue';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const { dialogRef, onDialogOK } = useDialogPluginComponent();
 
@@ -39,7 +40,7 @@ const optionsSamplesVisible = ref([]);
 const sampleType = ref({ hasPreview: false });
 const initialData = reactive({});
 const entityId = computed(() => route.params.id);
-const customer = computed(() => state.get('customer'));
+const customer = computed(() => useArrayData('Customer').store?.data);
 const filterEmailUsers = { where: { userFk: user.value.id } };
 const filterClientsAddresses = {
     include: [
@@ -65,9 +66,9 @@ const filterSamplesVisible = {
 defineEmits(['confirm', ...useDialogPluginComponent.emits]);
 
 onBeforeMount(async () => {
-    initialData.clientFk = customer.value.id;
-    initialData.recipient = customer.value.email;
-    initialData.recipientId = customer.value.id;
+    initialData.clientFk = customer.value?.id;
+    initialData.recipient = customer.value?.email;
+    initialData.recipientId = customer.value?.id;
 });
 
 const setEmailUser = (data) => {
diff --git a/src/pages/Customer/locale/en.yml b/src/pages/Customer/locale/en.yml
index 118f04a31..b6d495335 100644
--- a/src/pages/Customer/locale/en.yml
+++ b/src/pages/Customer/locale/en.yml
@@ -107,6 +107,9 @@ customer:
         defaulterSinced: Defaulted Since
         hasRecovery: Has Recovery
         socialName: Social name
+        typeId: Type
+        buyerId: Buyer
+        categoryId: Category
         city: City
         phone: Phone
         postcode: Postcode
diff --git a/src/pages/Customer/locale/es.yml b/src/pages/Customer/locale/es.yml
index 7c33ffee8..f50d049da 100644
--- a/src/pages/Customer/locale/es.yml
+++ b/src/pages/Customer/locale/es.yml
@@ -108,6 +108,9 @@ customer:
         hasRecovery: Tiene recobro
         socialName: Razón social
         campaign: Campaña
+        typeId: Familia
+        buyerId: Comprador
+        categoryId: Reino
         city: Ciudad
         phone: Teléfono
         postcode: Código postal
diff --git a/src/pages/Entry/Card/EntryBasicData.vue b/src/pages/Entry/Card/EntryBasicData.vue
index 689eea686..6462ed24a 100644
--- a/src/pages/Entry/Card/EntryBasicData.vue
+++ b/src/pages/Entry/Card/EntryBasicData.vue
@@ -1,30 +1,32 @@
 <script setup>
-import { ref } from 'vue';
+import { onMounted, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useRole } from 'src/composables/useRole';
+import { useState } from 'src/composables/useState';
+import { checkEntryLock } from 'src/composables/checkEntryLock';
 import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
-import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
-import FilterTravelForm from 'src/components/FilterTravelForm.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
-import { toDate } from 'src/filters';
+import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
 import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 
 const route = useRoute();
 const { t } = useI18n();
 const { hasAny } = useRole();
 const isAdministrative = () => hasAny(['administrative']);
+const state = useState();
+const user = state.getUser().fn();
 
 const companiesOptions = ref([]);
 const currenciesOptions = ref([]);
 
-const onFilterTravelSelected = (formData, id) => {
-    formData.travelFk = id;
-};
+onMounted(() => {
+    checkEntryLock(route.params.id, user.id);
+});
 </script>
 
 <template>
@@ -52,46 +54,24 @@ const onFilterTravelSelected = (formData, id) => {
     >
         <template #form="{ data }">
             <VnRow>
+                <VnSelectTravelExtended
+                    :data="data"
+                    v-model="data.travelFk"
+                    :onFilterTravelSelected="(data, result) => (data.travelFk = result)"
+                />
                 <VnSelectSupplier
                     v-model="data.supplierFk"
                     hide-selected
                     :required="true"
-                    map-options
                 />
-                <VnSelectDialog
-                    :label="t('entry.basicData.travel')"
-                    v-model="data.travelFk"
-                    url="Travels/filter"
-                    :fields="['id', 'warehouseInName']"
-                    option-value="id"
-                    option-label="warehouseInName"
-                    map-options
-                    hide-selected
-                    :required="true"
-                    action-icon="filter_alt"
-                >
-                    <template #form>
-                        <FilterTravelForm
-                            @travel-selected="onFilterTravelSelected(data, $event)"
-                        />
-                    </template>
-                    <template #option="scope">
-                        <QItem v-bind="scope.itemProps">
-                            <QItemSection>
-                                <QItemLabel>
-                                    {{ scope.opt?.agencyModeName }} -
-                                    {{ scope.opt?.warehouseInName }}
-                                    ({{ toDate(scope.opt?.shipped) }}) →
-                                    {{ scope.opt?.warehouseOutName }}
-                                    ({{ toDate(scope.opt?.landed) }})
-                                </QItemLabel>
-                            </QItemSection>
-                        </QItem>
-                    </template>
-                </VnSelectDialog>
             </VnRow>
             <VnRow>
                 <VnInput v-model="data.reference" :label="t('globals.reference')" />
+                <VnInputNumber
+                    v-model="data.invoiceAmount"
+                    :label="t('entry.summary.invoiceAmount')"
+                    :positive="false"
+                />
             </VnRow>
             <VnRow>
                 <VnInput
@@ -113,8 +93,7 @@ const onFilterTravelSelected = (formData, id) => {
                 <VnInputNumber
                     :label="t('entry.summary.commission')"
                     v-model="data.commission"
-                    step="1"
-                    autofocus
+                    :step="1"
                     :positive="false"
                 />
                 <VnSelect
@@ -161,7 +140,7 @@ const onFilterTravelSelected = (formData, id) => {
                     :label="t('entry.summary.excludedFromAvailable')"
                 />
                 <QCheckbox
-                    v-if="isAdministrative()"
+                    :disable="!isAdministrative()"
                     v-model="data.isBooked"
                     :label="t('entry.basicData.booked')"
                 />
diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue
index 6194ce5b8..81578c609 100644
--- a/src/pages/Entry/Card/EntryBuys.vue
+++ b/src/pages/Entry/Card/EntryBuys.vue
@@ -1,478 +1,806 @@
 <script setup>
-import { ref, computed } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
+import { useStateStore } from 'stores/useStateStore';
+import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import { QBtn } from 'quasar';
+import { onMounted, ref } from 'vue';
 
-import VnPaginate from 'src/components/ui/VnPaginate.vue';
-import VnSelect from 'components/common/VnSelect.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import FetchedTags from 'components/ui/FetchedTags.vue';
-import VnConfirm from 'components/ui/VnConfirm.vue';
+import { useState } from 'src/composables/useState';
+
+import FetchData from 'src/components/FetchData.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
 import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
-
-import { useQuasar } from 'quasar';
-import { toCurrency } from 'src/filters';
+import FetchedTags from 'src/components/ui/FetchedTags.vue';
+import VnColor from 'src/components/common/VnColor.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
 import axios from 'axios';
-import useNotify from 'src/composables/useNotify.js';
+import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
+import { checkEntryLock } from 'src/composables/checkEntryLock';
 
-const quasar = useQuasar();
-const route = useRoute();
-const router = useRouter();
-const { t } = useI18n();
-const { notify } = useNotify();
-
-const rowsSelected = ref([]);
-const entryBuysPaginateRef = ref(null);
-const originalRowDataCopy = ref(null);
-
-const getInputEvents = (colField, props) => {
-    return colField === 'packagingFk'
-        ? { 'update:modelValue': () => saveChange(colField, props) }
-        : {
-              'keyup.enter': () => saveChange(colField, props),
-              blur: () => saveChange(colField, props),
-          };
-};
-
-const tableColumnComponents = computed(() => ({
-    item: {
-        component: QBtn,
-        props: {
-            color: 'primary',
-            flat: true,
-        },
-        event: () => ({}),
+const $props = defineProps({
+    id: {
+        type: Number,
+        default: null,
     },
-    quantity: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
+    editableMode: {
+        type: Boolean,
+        default: true,
     },
-    packagingFk: {
-        component: VnSelect,
-        props: {
-            'option-value': 'id',
-            'option-label': 'id',
-            'emit-value': true,
-            'map-options': true,
-            'use-input': true,
-            'hide-selected': true,
-            url: 'Packagings',
-            fields: ['id'],
-            where: { freightItemFk: true },
-            'sort-by': 'id ASC',
-            dense: true,
-        },
-        event: getInputEvents,
+    tableHeight: {
+        type: String,
+        default: null,
     },
-    stickers: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    printedStickers: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            class: 'input-number',
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    weight: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    packing: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    grouping: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    buyingValue: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    price2: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    price3: {
-        component: VnInput,
-        props: {
-            type: 'number',
-            min: 0,
-            dense: true,
-        },
-        event: getInputEvents,
-    },
-    import: {
-        component: 'span',
-        props: {},
-        event: () => ({}),
-    },
-}));
-
-const entriesTableColumns = computed(() => {
-    return [
-        {
-            label: t('globals.item'),
-            field: 'itemFk',
-            name: 'item',
-            align: 'left',
-        },
-        {
-            label: t('globals.quantity'),
-            field: 'quantity',
-            name: 'quantity',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.package'),
-            field: 'packagingFk',
-            name: 'packagingFk',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.stickers'),
-            field: 'stickers',
-            name: 'stickers',
-            align: 'left',
-        },
-        {
-            label: t('entry.buys.printedStickers'),
-            field: 'printedStickers',
-            name: 'printedStickers',
-            align: 'left',
-        },
-        {
-            label: t('globals.weight'),
-            field: 'weight',
-            name: 'weight',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.packing'),
-            field: 'packing',
-            name: 'packing',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.grouping'),
-            field: 'grouping',
-            name: 'grouping',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.buyingValue'),
-            field: 'buyingValue',
-            name: 'buyingValue',
-            align: 'left',
-            format: (value) => toCurrency(value),
-        },
-        {
-            label: t('item.fixedPrice.groupingPrice'),
-            field: 'price2',
-            name: 'price2',
-            align: 'left',
-        },
-        {
-            label: t('item.fixedPrice.packingPrice'),
-            field: 'price3',
-            name: 'price3',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.import'),
-            name: 'import',
-            align: 'left',
-            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
-        },
-    ];
 });
 
-const copyOriginalRowsData = (rows) => {
-    originalRowDataCopy.value = JSON.parse(JSON.stringify(rows));
-};
-
-const saveChange = async (field, { rowIndex, row }) => {
-    if (originalRowDataCopy.value[rowIndex][field] == row[field]) return;
-    await axios.patch(`Buys/${row.id}`, row);
-    originalRowDataCopy.value[rowIndex][field] = row[field];
-};
-
-const openRemoveDialog = async () => {
-    quasar
-        .dialog({
-            component: VnConfirm,
-            componentProps: {
-                title: t('Confirm deletion'),
-                message: t(
-                    `Are you sure you want to delete this buy${
-                        rowsSelected.value.length > 1 ? 's' : ''
-                    }?`
-                ),
-                data: rowsSelected.value,
+const state = useState();
+const user = state.getUser().fn();
+const stateStore = useStateStore();
+const { t } = useI18n();
+const route = useRoute();
+const selectedRows = ref([]);
+const entityId = ref($props.id ?? route.params.id);
+const entryBuysRef = ref();
+const footerFetchDataRef = ref();
+const footer = ref({});
+const columns = [
+    {
+        align: 'center',
+        labelAbbreviation: 'NV',
+        label: t('Ignore'),
+        toolTip: t('Ignored for available'),
+        name: 'isIgnored',
+        component: 'checkbox',
+        attrs: {
+            toggleIndeterminate: false,
+        },
+        create: true,
+        width: '25px',
+    },
+    {
+        label: t('Buyer'),
+        name: 'workerFk',
+        component: 'select',
+        attrs: {
+            url: 'Workers/search',
+            fields: ['id', 'nickname'],
+            optionLabel: 'nickname',
+            optionValue: 'id',
+        },
+        visible: false,
+    },
+    {
+        label: t('Family'),
+        name: 'itemTypeFk',
+        component: 'select',
+        attrs: {
+            url: 'itemTypes',
+            fields: ['id', 'name'],
+            optionLabel: 'name',
+            optionValue: 'id',
+        },
+        visible: false,
+    },
+    {
+        name: 'id',
+        isId: true,
+        visible: false,
+        isEditable: false,
+        columnFilter: false,
+    },
+    {
+        name: 'entryFk',
+        isId: true,
+        visible: false,
+        isEditable: false,
+        disable: true,
+        create: true,
+        columnFilter: false,
+    },
+    {
+        align: 'center',
+        label: 'Id',
+        name: 'itemFk',
+        component: 'number',
+        isEditable: false,
+        width: '35px',
+    },
+    {
+        labelAbbreviation: '',
+        label: 'Color',
+        name: 'hex',
+        columnSearch: false,
+        isEditable: false,
+        width: '9px',
+        component: 'select',
+        attrs: {
+            url: 'Inks',
+            fields: ['id', 'name'],
+        },
+    },
+    {
+        align: 'center',
+        label: t('Article'),
+        name: 'name',
+        component: 'select',
+        attrs: {
+            url: 'Items',
+            fields: ['id', 'name'],
+            optionLabel: 'name',
+            optionValue: 'id',
+        },
+        width: '85px',
+        isEditable: false,
+    },
+    {
+        align: 'center',
+        label: t('Article'),
+        name: 'itemFk',
+        visible: false,
+        create: true,
+        columnFilter: false,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Siz.'),
+        label: t('Size'),
+        toolTip: t('Size'),
+        component: 'number',
+        name: 'size',
+        width: '35px',
+        isEditable: false,
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Sti.'),
+        label: t('Stickers'),
+        toolTip: t('Printed Stickers/Stickers'),
+        name: 'stickers',
+        component: 'input',
+        create: true,
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['quantity'] = value * row['packing'];
+                row['amount'] = row['quantity'] * row['buyingValue'];
             },
-        })
-        .onOk(async () => {
-            await deleteBuys();
-            const notifyMessage = t(
-                `Buy${rowsSelected.value.length > 1 ? 's' : ''} deleted`
-            );
-            notify(notifyMessage, 'positive');
-        });
-};
+        },
+        width: '35px',
+    },
+    {
+        align: 'center',
+        label: t('Bucket'),
+        name: 'packagingFk',
+        component: 'select',
+        attrs: {
+            url: 'packagings',
+            fields: ['id'],
+            optionLabel: 'id',
+            optionValue: 'id',
+        },
+        create: true,
+        width: '40px',
+    },
+    {
+        align: 'center',
+        label: 'Kg',
+        name: 'weight',
+        component: 'number',
+        create: true,
+        width: '35px',
+        format: (row) => parseFloat(row['weight']).toFixed(1),
+    },
+    {
+        labelAbbreviation: 'P',
+        label: 'Packing',
+        toolTip: 'Packing',
+        name: 'packing',
+        component: 'number',
+        create: true,
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                const oldPacking = oldValue === 1 || oldValue === null ? 1 : oldValue;
+                row['weight'] = (row['weight'] * value) / oldPacking;
+                row['quantity'] = row['stickers'] * value;
+                row['amount'] = row['quantity'] * row['buyingValue'];
+            },
+        },
+        width: '30px',
+        style: (row) => {
+            if (row.groupingMode === 'grouping')
+                return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'GM',
+        label: t('Grouping selector'),
+        toolTip: t('Grouping selector'),
+        name: 'groupingMode',
+        component: 'toggle',
+        attrs: {
+            'toggle-indeterminate': true,
+            trueValue: 'grouping',
+            falseValue: 'packing',
+            indeterminateValue: null,
+        },
+        size: 'xs',
+        width: '25px',
+        create: true,
+        rightFilter: false,
+        getIcon: (value) => {
+            switch (value) {
+                case 'grouping':
+                    return 'toggle_on';
+                case 'packing':
+                    return 'toggle_off';
+                default:
+                    return 'minimize';
+            }
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'G',
+        label: 'Grouping',
+        toolTip: 'Grouping',
+        name: 'grouping',
+        component: 'number',
+        width: '30px',
+        create: true,
+        style: (row) => {
+            if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        label: t('Quantity'),
+        name: 'quantity',
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['amount'] = value * row['buyingValue'];
+            },
+        },
+        width: '45px',
+        create: true,
+        style: getQuantityStyle,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Cost'),
+        label: t('Buying value'),
+        toolTip: t('Buying value'),
+        name: 'buyingValue',
+        create: true,
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['amount'] = row['quantity'] * value;
+            },
+        },
+        width: '45px',
+        format: (row) => parseFloat(row['buyingValue']).toFixed(3),
+    },
+    {
+        align: 'center',
+        label: t('Amount'),
+        name: 'amount',
+        width: '45px',
+        component: 'number',
+        attrs: {
+            positive: false,
+        },
+        isEditable: false,
+        format: (row) => parseFloat(row['amount']).toFixed(2),
+        style: getAmountStyle,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Pack.'),
+        label: t('Package'),
+        toolTip: t('Package'),
+        name: 'price2',
+        component: 'number',
+        width: '35px',
+        create: true,
+        format: (row) => parseFloat(row['price2']).toFixed(2),
+    },
+    {
+        align: 'center',
+        label: t('Box'),
+        name: 'price3',
+        component: 'number',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                row['price2'] = row['price2'] * (value / oldValue);
+            },
+        },
+        width: '35px',
+        create: true,
+        format: (row) => parseFloat(row['price3']).toFixed(2),
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'CM',
+        label: t('Check min price'),
+        toolTip: t('Check min price'),
+        name: 'hasMinPrice',
+        attrs: {
+            toggleIndeterminate: false,
+        },
+        component: 'checkbox',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                await axios.patch(`Items/${row['itemFk']}`, {
+                    hasMinPrice: value,
+                });
+            },
+        },
+        width: '25px',
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Min.',
+        label: t('Minimum price'),
+        toolTip: t('Minimum price'),
+        name: 'minPrice',
+        component: 'number',
+        cellEvent: {
+            'update:modelValue': async (value, oldValue, row) => {
+                await axios.patch(`Items/${row['itemFk']}`, {
+                    minPrice: value,
+                });
+            },
+        },
+        width: '35px',
+        style: (row) => {
+            if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
+        },
+        format: (row) => parseFloat(row['minPrice']).toFixed(2),
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('P.Sen'),
+        label: t('Packing sent'),
+        toolTip: t('Packing sent'),
+        name: 'packingOut',
+        component: 'number',
+        isEditable: false,
+        width: '40px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        labelAbbreviation: t('Com.'),
+        label: t('Comment'),
+        toolTip: t('Comment'),
+        name: 'comment',
+        component: 'input',
+        isEditable: false,
+        width: '50px',
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Prod.',
+        label: t('Producer'),
+        toolTip: t('Producer'),
+        name: 'subName',
+        isEditable: false,
+        width: '45px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+    {
+        align: 'center',
+        label: t('Tags'),
+        name: 'tags',
+        width: '125px',
+        columnSearch: false,
+    },
+    {
+        align: 'center',
+        labelAbbreviation: 'Comp.',
+        label: t('Company'),
+        toolTip: t('Company'),
+        name: 'company_name',
+        component: 'input',
+        isEditable: false,
+        width: '35px',
+        style: () => {
+            return { color: 'var(--vn-label-color)' };
+        },
+    },
+];
 
-const deleteBuys = async () => {
-    await axios.post('Buys/deleteBuys', { buys: rowsSelected.value });
-    entryBuysPaginateRef.value.fetch();
-};
+function getQuantityStyle(row) {
+    if (row?.quantity !== row?.stickers * row?.packing)
+        return { color: 'var(--q-negative)' };
+}
+function getAmountStyle(row) {
+    if (row?.isChecked) return { color: 'var(--q-positive)' };
+    return { color: 'var(--vn-label-color)' };
+}
 
-const importBuys = () => {
-    router.push({ name: 'EntryBuysImport' });
-};
+async function beforeSave(data, getChanges) {
+    try {
+        const changes = data.updates;
+        if (!changes) return data;
+        const patchPromises = [];
 
-const toggleGroupingMode = async (buy, mode) => {
-    const groupingMode = mode === 'grouping' ? mode : 'packing';
-    const newGroupingMode = buy.groupingMode === groupingMode ? null : groupingMode;
-    const params = {
-        groupingMode: newGroupingMode,
-    };
-    await axios.patch(`Buys/${buy.id}`, params);
-    buy.groupingMode = newGroupingMode;
-};
+        for (const change of changes) {
+            let patchData = {};
 
-const lockIconType = (groupingMode, mode) => {
-    if (mode === 'packing') {
-        return groupingMode === 'packing' ? 'lock' : 'lock_open';
-    } else {
-        return groupingMode === 'grouping' ? 'lock' : 'lock_open';
+            if ('hasMinPrice' in change.data) {
+                patchData.hasMinPrice = change.data?.hasMinPrice;
+                delete change.data.hasMinPrice;
+            }
+            if ('minPrice' in change.data) {
+                patchData.minPrice = change.data?.minPrice;
+                delete change.data.minPrice;
+            }
+
+            if (Object.keys(patchData).length > 0) {
+                const promise = axios
+                    .get('Buys/findOne', {
+                        params: {
+                            filter: {
+                                fields: ['itemFk'],
+                                where: { id: change.where.id },
+                            },
+                        },
+                    })
+                    .then((buy) => {
+                        return axios.patch(`Items/${buy.data.itemFk}`, patchData);
+                    })
+                    .catch((error) => {
+                        console.error('Error processing change: ', change, error);
+                    });
+
+                patchPromises.push(promise);
+            }
+        }
+
+        await Promise.all(patchPromises);
+
+        data.updates = changes.filter((change) => Object.keys(change.data).length > 0);
+
+        return data;
+    } catch (error) {
+        console.error('Error in beforeSave:', error);
+        throw error;
     }
-};
+}
+
+function invertQuantitySign(rows, sign) {
+    for (const row of rows) {
+        if (sign > 0) row.quantity = Math.abs(row.quantity);
+        else if (row.quantity > 0) row.quantity = -row.quantity;
+    }
+}
+function setIsChecked(rows, value) {
+    for (const row of rows) {
+        row.isChecked = value;
+    }
+    footerFetchDataRef.value.fetch();
+}
+
+async function setBuyUltimate(itemFk, data) {
+    if (!itemFk) return;
+    const buyUltimate = await axios.get(`Entries/getBuyUltimate`, {
+        params: {
+            itemFk,
+            warehouseFk: user.warehouseFk,
+            date: Date.vnNew(),
+        },
+    });
+    const buyUltimateData = buyUltimate.data[0];
+
+    const allowedKeys = columns
+        .filter((col) => col.create === true)
+        .map((col) => col.name);
+
+    allowedKeys.forEach((key) => {
+        if (buyUltimateData.hasOwnProperty(key) && key !== 'entryFk') {
+            if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
+        }
+    });
+}
+
+onMounted(() => {
+    stateStore.rightDrawer = false;
+    if ($props.editableMode) checkEntryLock(entityId.value, user.id);
+});
 </script>
-
 <template>
-    <VnSubToolbar>
-        <template #st-actions>
-            <QBtnGroup push style="column-gap: 10px">
-                <slot name="moreBeforeActions" />
-                <QBtn
-                    :label="t('globals.remove')"
-                    color="primary"
-                    icon="delete"
-                    flat
-                    @click="openRemoveDialog()"
-                    :disable="!rowsSelected?.length"
-                    :title="t('globals.remove')"
-                />
-            </QBtnGroup>
-        </template>
-    </VnSubToolbar>
-    <VnPaginate
-        ref="entryBuysPaginateRef"
-        data-key="EntryBuys"
-        :url="`Entries/${route.params.id}/getBuys`"
-        @on-fetch="copyOriginalRowsData($event)"
-        auto-load
-    >
-        <template #body="{ rows }">
-            <QTable
-                :rows="rows"
-                :columns="entriesTableColumns"
-                selection="multiple"
-                row-key="id"
-                class="full-width q-mt-md"
-                :grid="$q.screen.lt.md"
-                v-model:selected="rowsSelected"
-                :no-data-label="t('globals.noResults')"
+    <Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown() && editableMode">
+        <QBtnGroup push style="column-gap: 1px">
+            <QBtnDropdown
+                label="+/-"
+                color="primary"
+                flat
+                :title="t('Invert quantity value')"
+                :disable="!selectedRows.length"
+                data-cy="change-quantity-sign"
             >
-                <template #body="props">
-                    <QTr>
-                        <QTd>
-                            <QCheckbox v-model="props.selected" />
-                        </QTd>
-                        <QTd
-                            v-for="col in props.cols"
-                            :key="col.name"
-                            style="max-width: 100px"
-                        >
-                            <component
-                                :is="tableColumnComponents[col.name].component"
-                                v-bind="tableColumnComponents[col.name].props"
-                                v-model="props.row[col.field]"
-                                v-on="
-                                    tableColumnComponents[col.name].event(
-                                        col.field,
-                                        props
-                                    )
-                                "
+                <QList>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                flat
+                                @click="invertQuantitySign(selectedRows, -1)"
+                                data-cy="set-negative-quantity"
                             >
-                                <template
-                                    v-if="
-                                        col.name === 'grouping' || col.name === 'packing'
-                                    "
-                                    #append
-                                >
-                                    <QBtn
-                                        :icon="
-                                            lockIconType(props.row.groupingMode, col.name)
-                                        "
-                                        @click="toggleGroupingMode(props.row, col.name)"
-                                        class="cursor-pointer"
-                                        size="sm"
-                                        flat
-                                        dense
-                                        unelevated
-                                        push
-                                        :style="{
-                                            'font-variation-settings': `'FILL' ${
-                                                lockIconType(
-                                                    props.row.groupingMode,
-                                                    col.name
-                                                ) === 'lock'
-                                                    ? 1
-                                                    : 0
-                                            }`,
-                                        }"
-                                    />
-                                </template>
-                                <template
-                                    v-if="col.name === 'item' || col.name === 'import'"
-                                >
-                                    {{ col.value }}
-                                </template>
-                                <ItemDescriptorProxy
-                                    v-if="col.name === 'item'"
-                                    :id="props.row.item.id"
-                                />
-                            </component>
-                        </QTd>
-                    </QTr>
-                    <QTr no-hover class="full-width infoRow" style="column-span: all">
-                        <QTd />
-                        <QTd cols>
-                            <span>{{ props.row.item.itemType.code }}</span>
-                        </QTd>
-                        <QTd>
-                            <span>{{ props.row.item.size }}</span>
-                        </QTd>
-                        <QTd>
-                            <span>{{ toCurrency(props.row.item.minPrice) }}</span>
-                        </QTd>
-                        <QTd colspan="7">
-                            <span>{{ props.row.item.concept }}</span>
-                            <span v-if="props.row.item.subName" class="subName">
-                                {{ props.row.item.subName }}
-                            </span>
-                            <FetchedTags :item="props.row.item" />
-                        </QTd>
-                    </QTr>
-                </template>
-                <template #item="props">
-                    <div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
-                        <QCard bordered flat>
-                            <QCardSection>
-                                <QCheckbox v-model="props.selected" dense />
-                            </QCardSection>
-                            <QSeparator />
-                            <QList dense>
-                                <QItem v-for="col in props.cols" :key="col.name">
-                                    <component
-                                        :is="tableColumnComponents[col.name].component"
-                                        v-bind="tableColumnComponents[col.name].props"
-                                        v-model="props.row[col.field]"
-                                        v-on="
-                                            tableColumnComponents[col.name].event(
-                                                col.field,
-                                                props
-                                            )
-                                        "
-                                        class="full-width"
-                                    >
-                                        <template
-                                            v-if="
-                                                col.name === 'item' ||
-                                                col.name === 'import'
-                                            "
-                                        >
-                                            {{ col.label + ': ' + col.value }}
-                                        </template>
-                                    </component>
-                                </QItem>
-                            </QList>
-                        </QCard>
-                    </div>
-                </template>
-            </QTable>
+                                <span style="font-size: large">-</span>
+                            </QBtn>
+                        </QItemSection>
+                    </QItem>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                flat
+                                @click="invertQuantitySign(selectedRows, 1)"
+                                data-cy="set-positive-quantity"
+                            >
+                                <span style="font-size: large">+</span>
+                            </QBtn>
+                        </QItemSection>
+                    </QItem>
+                </QList>
+            </QBtnDropdown>
+            <QBtnDropdown
+                icon="price_check"
+                color="primary"
+                flat
+                :title="t('Check buy amount')"
+                :disable="!selectedRows.length"
+                data-cy="check-buy-amount"
+            >
+                <QList>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                size="sm"
+                                icon="check"
+                                flat
+                                @click="setIsChecked(selectedRows, true)"
+                                data-cy="check-amount"
+                            />
+                        </QItemSection>
+                    </QItem>
+                    <QItem>
+                        <QItemSection>
+                            <QBtn
+                                size="sm"
+                                icon="close"
+                                flat
+                                @click="setIsChecked(selectedRows, false)"
+                                data-cy="uncheck-amount"
+                            />
+                        </QItemSection>
+                    </QItem>
+                </QList>
+            </QBtnDropdown>
+        </QBtnGroup>
+    </Teleport>
+    <FetchData
+        ref="footerFetchDataRef"
+        :url="`Entries/${entityId}/getBuyList`"
+        :params="{ groupBy: 'GROUP BY b.entryFk' }"
+        @on-fetch="(data) => (footer = data[0])"
+        auto-load
+    />
+    <VnTable
+        ref="entryBuysRef"
+        data-key="EntryBuys"
+        :url="`Entries/${entityId}/getBuyList`"
+        save-url="Buys/crud"
+        :disable-option="{ card: true }"
+        v-model:selected="selectedRows"
+        @on-fetch="() => footerFetchDataRef.fetch()"
+        :table="
+            editableMode
+                ? {
+                      'row-key': 'id',
+                      selection: 'multiple',
+                  }
+                : {}
+        "
+        :create="
+            editableMode
+                ? {
+                      urlCreate: 'Buys',
+                      title: t('Create buy'),
+                      onDataSaved: () => {
+                          entryBuysRef.reload();
+                      },
+                      formInitialData: { entryFk: entityId, isIgnored: false },
+                      showSaveAndContinueBtn: true,
+                  }
+                : null
+        "
+        :create-complement="{
+            isFullWidth: true,
+            containerStyle: {
+                display: 'flex',
+                'flex-wrap': 'wrap',
+                gap: '16px',
+                position: 'relative',
+                height: '450px',
+            },
+            columnGridStyle: {
+                'max-width': '50%',
+                flex: 1,
+                'margin-right': '30px',
+            },
+        }"
+        :is-editable="editableMode"
+        :without-header="!editableMode"
+        :with-filters="editableMode"
+        :right-search="true"
+        :right-search-icon="true"
+        :row-click="false"
+        :columns="columns"
+        :beforeSaveFn="beforeSave"
+        class="buyList"
+        :table-height="$props.tableHeight ?? '84vh'"
+        auto-load
+        footer
+        data-cy="entry-buys"
+    >
+        <template #column-hex="{ row }">
+            <VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
         </template>
-    </VnPaginate>
-
-    <QPageSticky :offset="[20, 20]">
-        <QBtn fab icon="upload" color="primary" @click="importBuys()" />
-        <QTooltip class="text-no-wrap">
-            {{ t('Import buys') }}
-        </QTooltip>
-    </QPageSticky>
+        <template #column-name="{ row }">
+            <span class="link">
+                {{ row?.name }}
+                <ItemDescriptorProxy :id="row?.itemFk" />
+            </span>
+        </template>
+        <template #column-tags="{ row }">
+            <FetchedTags :item="row" :columns="3" />
+        </template>
+        <template #column-stickers="{ row }">
+            <span :class="editableMode ? 'editable-text' : ''">
+                <span style="color: var(--vn-label-color)">
+                    {{ row.printedStickers }}
+                </span>
+                <span>/{{ row.stickers }}</span>
+            </span>
+        </template>
+        <template #column-footer-stickers>
+            <div>
+                <span style="color: var(--vn-label-color)">
+                    {{ footer?.printedStickers }}</span
+                >
+                <span>/</span>
+                <span data-cy="footer-stickers">{{ footer?.stickers }}</span>
+            </div>
+        </template>
+        <template #column-footer-weight>
+            {{ footer?.weight }}
+        </template>
+        <template #column-footer-quantity>
+            <span :style="getQuantityStyle(footer)" data-cy="footer-quantity">
+                {{ footer?.quantity }}
+            </span>
+        </template>
+        <template #column-footer-amount>
+            <span :style="getAmountStyle(footer)" data-cy="footer-amount">
+                {{ footer?.amount }}
+            </span>
+        </template>
+        <template #column-create-itemFk="{ data }">
+            <VnSelect
+                url="Items/search"
+                v-model="data.itemFk"
+                :label="t('Article')"
+                :fields="['id', 'name', 'size', 'producerName']"
+                :filter-options="['id', 'name', 'size', 'producerName']"
+                option-label="name"
+                option-value="id"
+                @update:modelValue="
+                    async (value) => {
+                        await setBuyUltimate(value, data);
+                    }
+                "
+                :required="true"
+                data-cy="itemFk-create-popup"
+                sort-by="nickname DESC"
+            >
+                <template #option="scope">
+                    <QItem v-bind="scope.itemProps">
+                        <QItemSection>
+                            <QItemLabel>
+                                {{ scope.opt.name }}
+                            </QItemLabel>
+                            <QItemLabel caption>
+                                #{{ scope.opt.id }}, {{ scope.opt?.size }},
+                                {{ scope.opt?.producerName }}
+                            </QItemLabel>
+                        </QItemSection>
+                    </QItem>
+                </template>
+            </VnSelect>
+        </template>
+        <template #column-create-groupingMode="{ data }">
+            <VnSelectEnum
+                :label="t('Grouping mode')"
+                v-model="data.groupingMode"
+                schema="vn"
+                table="buy"
+                column="groupingMode"
+                option-value="groupingMode"
+                option-label="groupingMode"
+            />
+        </template>
+        <template #previous-create-dialog="{ data }">
+            <div
+                style="position: absolute"
+                :class="{ 'centered-container': !data.itemFk }"
+            >
+                <ItemDescriptor :id="data.itemFk" v-if="data.itemFk" />
+                <div v-else>
+                    <span>{{ t('globals.noData') }}</span>
+                </div>
+            </div>
+        </template>
+    </VnTable>
 </template>
-
-<style lang="scss" scoped>
-.q-table--horizontal-separator tbody tr:nth-child(odd) > td {
-    border-bottom-width: 0px;
-    border-top-width: 2px;
-    border-color: var(--vn-text-color);
-}
-.infoRow > td {
-    color: var(--vn-label-color);
-}
-</style>
-
 <i18n>
 es:
-    Import buys: Importar compras
-    Buy deleted: Compra eliminada
-    Buys deleted: Compras eliminadas
-    Confirm deletion: Confirmar eliminación
-    Are you sure you want to delete this buy?: Seguro que quieres eliminar esta compra?
-    Are you sure you want to delete this buys?: Seguro que quieres eliminar estas compras?
+    Article: Artículo
+    Siz.: Med.
+    Size: Medida
+    Sti.: Eti.
+    Bucket: Cubo
+    Quantity: Cantidad
+    Amount: Importe
+    Pack.: Paq.
+    Package: Paquete
+    Box: Caja
+    P.Sen: P.Env
+    Packing sent: Packing envíos
+    Com.: Ref.
+    Comment: Referencia
+    Minimum price: Precio mínimo
+    Stickers: Etiquetas
+    Printed Stickers/Stickers: Etiquetas impresas/Etiquetas
+    Cost: Cost.
+    Buying value: Coste
+    Producer: Productor
+    Company: Compañia
+    Tags: Etiquetas
+    Grouping mode: Modo de agrupación
+    C.min: P.min
+    Ignore: Ignorar
+    Ignored for available: Ignorado para disponible
+    Grouping selector: Selector de grouping
+    Check min price: Marcar precio mínimo
+    Create buy: Crear compra
+    Invert quantity value: Invertir valor de cantidad
+    Check buy amount: Marcar como correcta la cantidad de compra
 </i18n>
+<style lang="scss" scoped>
+.centered-container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    position: absolute;
+    width: 40%;
+    height: 100%;
+}
+</style>
diff --git a/src/pages/Entry/Card/EntryCard.vue b/src/pages/Entry/Card/EntryCard.vue
index e00623a21..be82289f4 100644
--- a/src/pages/Entry/Card/EntryCard.vue
+++ b/src/pages/Entry/Card/EntryCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import EntryDescriptor from './EntryDescriptor.vue';
-import filter from './EntryFilter.js'
+import filter from './EntryFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Entry"
-        base-url="Entries"
+        url="Entries"
         :descriptor="EntryDescriptor"
-        :user-filter="filter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Entry/Card/EntryDescriptor.vue b/src/pages/Entry/Card/EntryDescriptor.vue
index 19d13e51a..69b300cb2 100644
--- a/src/pages/Entry/Card/EntryDescriptor.vue
+++ b/src/pages/Entry/Card/EntryDescriptor.vue
@@ -1,12 +1,19 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
-import { useRoute } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
-import CardDescriptor from 'components/ui/CardDescriptor.vue';
-import VnLv from 'src/components/ui/VnLv.vue';
 import { toDate } from 'src/filters';
 import { getUrl } from 'src/composables/getUrl';
-import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
+import { useQuasar } from 'quasar';
+import { usePrintService } from 'composables/usePrintService';
+import CardDescriptor from 'components/ui/CardDescriptor.vue';
+import VnLv from 'src/components/ui/VnLv.vue';
+import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
+import axios from 'axios';
+
+const quasar = useQuasar();
+const { push } = useRouter();
+const { openReport } = usePrintService();
 
 const $props = defineProps({
     id: {
@@ -83,12 +90,63 @@ const getEntryRedirectionFilter = (entry) => {
         to,
     });
 };
+
+function showEntryReport() {
+    openReport(`Entries/${entityId.value}/entry-order-pdf`);
+}
+
+function showNotification(type, message) {
+    quasar.notify({
+        type: type,
+        message: t(message),
+    });
+}
+
+async function recalculateRates(entity) {
+    try {
+        const entryConfig = await axios.get('EntryConfigs/findOne');
+        if (entryConfig.data?.inventorySupplierFk === entity.supplierFk) {
+            showNotification(
+                'negative',
+                'Cannot recalculate prices because this is an inventory entry',
+            );
+            return;
+        }
+
+        await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);
+        showNotification('positive', 'Entry prices recalculated');
+    } catch (error) {
+        showNotification('negative', 'Failed to recalculate rates');
+        console.error(error);
+    }
+}
+
+async function cloneEntry() {
+    try {
+        const response = await axios.post(`Entries/${entityId.value}/cloneEntry`);
+        push({ path: `/entry/${response.data}` });
+        showNotification('positive', 'Entry cloned');
+    } catch (error) {
+        showNotification('negative', 'Failed to clone entry');
+        console.error(error);
+    }
+}
+
+async function deleteEntry() {
+    try {
+        await axios.post(`Entries/${entityId.value}/deleteEntry`);
+        push({ path: `/entry/list` });
+        showNotification('positive', 'Entry deleted');
+    } catch (error) {
+        showNotification('negative', 'Failed to delete entry');
+        console.error(error);
+    }
+}
 </script>
 
 <template>
     <CardDescriptor
         ref="entryDescriptorRef"
-        module="Entry"
         :url="`Entries/${entityId}`"
         :userFilter="entryFilter"
         title="supplier.nickname"
@@ -96,15 +154,56 @@ const getEntryRedirectionFilter = (entry) => {
         width="lg-width"
     >
         <template #menu="{ entity }">
-            <EntryDescriptorMenu :id="entity.id" />
+            <QItem
+                v-ripple
+                clickable
+                @click="showEntryReport(entity)"
+                data-cy="show-entry-report"
+            >
+                <QItemSection>{{ t('Show entry report') }}</QItemSection>
+            </QItem>
+            <QItem
+                v-ripple
+                clickable
+                @click="recalculateRates(entity)"
+                data-cy="recalculate-rates"
+            >
+                <QItemSection>{{ t('Recalculate rates') }}</QItemSection>
+            </QItem>
+            <QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry">
+                <QItemSection>{{ t('Clone') }}</QItemSection>
+            </QItem>
+            <QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry">
+                <QItemSection>{{ t('Delete') }}</QItemSection>
+            </QItem>
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
-            <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
-            <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
+            <VnLv :label="t('Travel')">
+                <template #value>
+                    <span class="link" v-if="entity?.travelFk">
+                        {{ entity.travel?.agency?.name }}
+                        {{ entity.travel?.warehouseOut?.code }} &rarr;
+                        {{ entity.travel?.warehouseIn?.code }}
+                        <TravelDescriptorProxy :id="entity?.travelFk" />
+                    </span>
+                </template>
+            </VnLv>
             <VnLv
-                :label="t('globals.warehouseOut')"
-                :value="entity.travel?.warehouseOut?.name"
+                :label="t('entry.summary.travelShipped')"
+                :value="toDate(entity.travel?.shipped)"
+            />
+            <VnLv
+                :label="t('entry.summary.travelLanded')"
+                :value="toDate(entity.travel?.landed)"
+            />
+            <VnLv :label="t('entry.summary.currency')" :value="entity?.currency?.code" />
+            <VnLv
+                :label="t('entry.summary.invoiceAmount')"
+                :value="entity?.invoiceAmount"
+            />
+            <VnLv
+                :label="t('entry.summary.entryType')"
+                :value="entity?.entryType?.description"
             />
         </template>
         <template #icons="{ entity }">
@@ -131,6 +230,14 @@ const getEntryRedirectionFilter = (entry) => {
                         }}</QTooltip
                     >
                 </QIcon>
+                <QIcon
+                    v-if="!entity?.travelFk"
+                    name="vn:deletedTicket"
+                    size="xs"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('This entry is deleted') }}</QTooltip>
+                </QIcon>
             </QCardActions>
         </template>
         <template #actions="{ entity }">
@@ -143,21 +250,6 @@ const getEntryRedirectionFilter = (entry) => {
                 >
                     <QTooltip>{{ t('Supplier card') }}</QTooltip>
                 </QBtn>
-                <QBtn
-                    :to="{
-                        name: 'TravelMain',
-                        query: {
-                            params: JSON.stringify({
-                                agencyModeFk: entity.travel?.agencyModeFk,
-                            }),
-                        },
-                    }"
-                    size="md"
-                    icon="local_airport"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('All travels with current agency') }}</QTooltip>
-                </QBtn>
                 <QBtn
                     :to="{
                         name: 'EntryMain',
@@ -177,10 +269,24 @@ const getEntryRedirectionFilter = (entry) => {
 </template>
 <i18n>
 es:
+    Travel: Envío
     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
     Inventory entry: Es inventario
     Virtual entry: Es una redada
+    shipped: Enviado
+    landed: Recibido
+    This entry is deleted: Esta entrada está eliminada
+    Cannot recalculate prices because this is an inventory entry: No se pueden recalcular los precios porque es una entrada de inventario
+    Entry deleted: Entrada eliminada
+    Entry cloned: Entrada clonada
+    Entry prices recalculated: Precios de la entrada recalculados
+    Failed to recalculate rates: No se pudieron recalcular las tarifas
+    Failed to clone entry: No se pudo clonar la entrada
+    Failed to delete entry: No se pudo eliminar la entrada
+    Recalculate rates: Recalcular tarifas
+    Clone: Clonar
+    Delete: Eliminar
 </i18n>
diff --git a/src/pages/Entry/Card/EntryFilter.js b/src/pages/Entry/Card/EntryFilter.js
index 3ff62cf27..d9fd1c2be 100644
--- a/src/pages/Entry/Card/EntryFilter.js
+++ b/src/pages/Entry/Card/EntryFilter.js
@@ -9,6 +9,7 @@ export default {
                     'shipped',
                     'agencyModeFk',
                     'warehouseOutFk',
+                    'warehouseInFk',
                     'daysInForward',
                 ],
                 include: [
@@ -21,13 +22,13 @@ export default {
                     {
                         relation: 'warehouseOut',
                         scope: {
-                            fields: ['name'],
+                            fields: ['name', 'code'],
                         },
                     },
                     {
                         relation: 'warehouseIn',
                         scope: {
-                            fields: ['name'],
+                            fields: ['name', 'code'],
                         },
                     },
                 ],
@@ -39,5 +40,17 @@ export default {
                 fields: ['id', 'nickname'],
             },
         },
+        {
+            relation: 'currency',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'entryType',
+            scope: {
+                fields: ['code', 'description'],
+            },
+        },
     ],
 };
diff --git a/src/pages/Entry/Card/EntryNotes.vue b/src/pages/Entry/Card/EntryNotes.vue
index 55cac0437..459c3b069 100644
--- a/src/pages/Entry/Card/EntryNotes.vue
+++ b/src/pages/Entry/Card/EntryNotes.vue
@@ -17,7 +17,7 @@ const selected = ref([]);
 
 const sortEntryObservationOptions = (data) => {
     entryObservationsOptions.value = [...data].sort((a, b) =>
-        a.description.localeCompare(b.description)
+        a.description.localeCompare(b.description),
     );
 };
 
@@ -142,7 +142,7 @@ const columns = computed(() => [
             fab
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             @click="entryObservationsRef.insert()"
         />
     </QPageSticky>
diff --git a/src/pages/Entry/Card/EntrySummary.vue b/src/pages/Entry/Card/EntrySummary.vue
index 8c46fb6e6..c40e2ba46 100644
--- a/src/pages/Entry/Card/EntrySummary.vue
+++ b/src/pages/Entry/Card/EntrySummary.vue
@@ -2,19 +2,17 @@
 import { onMounted, ref, computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
+import { toDate } from 'src/filters';
+import { getUrl } from 'src/composables/getUrl';
+import axios from 'axios';
 
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-
-import { toDate, toCurrency, toCelsius } from 'src/filters';
-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 EntryBuys from './EntryBuys.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
+import VnToSummary from 'src/components/ui/VnToSummary.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -33,117 +31,6 @@ const entry = ref();
 const entryBuys = ref([]);
 const entryUrl = ref();
 
-onMounted(async () => {
-    entryUrl.value = (await getUrl('entry/')) + entityId.value;
-});
-
-const tableColumnComponents = {
-    quantity: {
-        component: () => 'span',
-        props: () => {},
-    },
-    stickers: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    packagingFk: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    weight: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    packing: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    grouping: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    buyingValue: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    amount: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-    pvp: {
-        component: () => 'span',
-        props: () => {},
-        event: () => {},
-    },
-};
-
-const entriesTableColumns = computed(() => {
-    return [
-        {
-            label: t('globals.quantity'),
-            field: 'quantity',
-            name: 'quantity',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.stickers'),
-            field: 'stickers',
-            name: 'stickers',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.package'),
-            field: 'packagingFk',
-            name: 'packagingFk',
-            align: 'left',
-        },
-        {
-            label: t('globals.weight'),
-            field: 'weight',
-            name: 'weight',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.packing'),
-            field: 'packing',
-            name: 'packing',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.grouping'),
-            field: 'grouping',
-            name: 'grouping',
-            align: 'left',
-        },
-        {
-            label: t('entry.summary.buyingValue'),
-            field: 'buyingValue',
-            name: 'buyingValue',
-            align: 'left',
-            format: (value) => toCurrency(value),
-        },
-        {
-            label: t('entry.summary.import'),
-            name: 'amount',
-            align: 'left',
-            format: (_, row) => toCurrency(row.buyingValue * row.quantity),
-        },
-        {
-            label: t('entry.summary.pvp'),
-            name: 'pvp',
-            align: 'left',
-            format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
-        },
-    ];
-});
-
 async function setEntryData(data) {
     if (data) entry.value = data;
     await fetchEntryBuys();
@@ -153,14 +40,18 @@ const fetchEntryBuys = async () => {
     const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
     if (data) entryBuys.value = data;
 };
-</script>
 
+onMounted(async () => {
+    entryUrl.value = (await getUrl('entry/')) + entityId.value;
+});
+</script>
 <template>
     <CardSummary
         ref="summaryRef"
         :url="`Entries/${entityId}/getEntry`"
         @on-fetch="(data) => setEntryData(data)"
         data-key="EntrySummary"
+        data-cy="entry-summary"
     >
         <template #header-left>
             <VnToSummary
@@ -173,159 +64,154 @@ 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
                     :url="`#/entry/${entityId}/basic-data`"
                     :text="t('globals.summary.basicData')"
                 />
-                <VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
-                <VnLv
-                    :label="t('entry.summary.currency')"
-                    :value="entry.currency?.name"
-                />
-                <VnLv :label="t('globals.company')" :value="entry.company.code" />
-                <VnLv :label="t('globals.reference')" :value="entry.reference" />
-                <VnLv
-                    :label="t('entry.summary.invoiceNumber')"
-                    :value="entry.invoiceNumber"
-                />
-                <VnLv
-                    :label="t('entry.basicData.initialTemperature')"
-                    :value="toCelsius(entry.initialTemperature)"
-                />
-                <VnLv
-                    :label="t('entry.basicData.finalTemperature')"
-                    :value="toCelsius(entry.finalTemperature)"
-                />
+                <div class="card-group">
+                    <div class="card-content">
+                        <VnLv
+                            :label="t('entry.summary.commission')"
+                            :value="entry?.commission"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.currency')"
+                            :value="entry?.currency?.name"
+                        />
+                        <VnLv
+                            :label="t('globals.company')"
+                            :value="entry?.company?.code"
+                        />
+                        <VnLv :label="t('globals.reference')" :value="entry?.reference" />
+                        <VnLv
+                            :label="t('entry.summary.invoiceNumber')"
+                            :value="entry?.invoiceNumber"
+                        />
+                    </div>
+                    <div class="card-content">
+                        <VnCheckbox
+                            :label="t('entry.summary.ordered')"
+                            v-model="entry.isOrdered"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('globals.confirmed')"
+                            v-model="entry.isConfirmed"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.booked')"
+                            v-model="entry.isBooked"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.excludedFromAvailable')"
+                            v-model="entry.isExcludedFromAvailable"
+                            :disable="true"
+                            size="xs"
+                        />
+                    </div>
+                </div>
             </QCard>
-            <QCard class="vn-one">
+            <QCard class="vn-one" v-if="entry?.travelFk">
                 <VnTitle
-                    :url="`#/entry/${entityId}/basic-data`"
-                    :text="t('globals.summary.basicData')"
+                    :url="`#/travel/${entry.travel.id}/summary`"
+                    :text="t('Travel')"
                 />
-                <VnLv :label="t('entry.summary.travelReference')">
-                    <template #value>
-                        <span class="link">
-                            {{ entry.travel.ref }}
-                            <TravelDescriptorProxy :id="entry.travel.id" />
-                        </span>
-                    </template>
-                </VnLv>
-                <VnLv
-                    :label="t('entry.summary.travelAgency')"
-                    :value="entry.travel.agency?.name"
-                />
-                <VnLv
-                    :label="t('globals.shipped')"
-                    :value="toDate(entry.travel.shipped)"
-                />
-                <VnLv
-                    :label="t('globals.warehouseOut')"
-                    :value="entry.travel.warehouseOut?.name"
-                />
-                <VnLv
-                    :label="t('entry.summary.travelDelivered')"
-                    :value="entry.travel.isDelivered"
-                />
-                <VnLv :label="t('globals.landed')" :value="toDate(entry.travel.landed)" />
-                <VnLv
-                    :label="t('globals.warehouseIn')"
-                    :value="entry.travel.warehouseIn?.name"
-                />
-                <VnLv
-                    :label="t('entry.summary.travelReceived')"
-                    :value="entry.travel.isReceived"
-                />
-            </QCard>
-            <QCard class="vn-one">
-                <VnTitle :url="`#/travel/${entityId}/summary`" :text="t('Travel data')" />
-                <VnRow class="block">
-                    <VnLv :label="t('entry.summary.ordered')" :value="entry.isOrdered" />
-                    <VnLv :label="t('globals.confirmed')" :value="entry.isConfirmed" />
-                    <VnLv :label="t('entry.summary.booked')" :value="entry.isBooked" />
-                    <VnLv
-                        :label="t('entry.summary.excludedFromAvailable')"
-                        :value="entry.isExcludedFromAvailable"
-                    />
-                </VnRow>
+                <div class="card-group">
+                    <div class="card-content">
+                        <VnLv :label="t('entry.summary.travelReference')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entry.travel.ref }}
+                                    <TravelDescriptorProxy :id="entry.travel.id" />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv
+                            :label="t('entry.summary.travelAgency')"
+                            :value="entry.travel.agency?.name"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.travelShipped')"
+                            :value="toDate(entry.travel.shipped)"
+                        />
+                        <VnLv
+                            :label="t('globals.warehouseOut')"
+                            :value="entry.travel.warehouseOut?.name"
+                        />
+                        <VnLv
+                            :label="t('entry.summary.travelLanded')"
+                            :value="toDate(entry.travel.landed)"
+                        />
+                        <VnLv
+                            :label="t('globals.warehouseIn')"
+                            :value="entry.travel.warehouseIn?.name"
+                        />
+                    </div>
+                    <div class="card-content">
+                        <VnCheckbox
+                            :label="t('entry.summary.travelDelivered')"
+                            v-model="entry.travel.isDelivered"
+                            :disable="true"
+                            size="xs"
+                        />
+                        <VnCheckbox
+                            :label="t('entry.summary.travelReceived')"
+                            v-model="entry.travel.isReceived"
+                            :disable="true"
+                            size="xs"
+                        />
+                    </div>
+                </div>
             </QCard>
             <QCard class="vn-max">
                 <VnTitle
                     :url="`#/entry/${entityId}/buys`"
                     :text="t('entry.summary.buys')"
                 />
-                <QTable
-                    :rows="entryBuys"
-                    :columns="entriesTableColumns"
-                    row-key="index"
-                    class="full-width q-mt-md"
-                    :no-data-label="t('globals.noResults')"
-                >
-                    <template #body="{ cols, row, rowIndex }">
-                        <QTr no-hover>
-                            <QTd v-for="col in cols" :key="col?.name">
-                                <component
-                                    :is="tableColumnComponents[col?.name].component()"
-                                    v-bind="tableColumnComponents[col?.name].props()"
-                                    @click="tableColumnComponents[col?.name].event()"
-                                    class="col-content"
-                                >
-                                    <template
-                                        v-if="
-                                            col?.name !== 'observation' &&
-                                            col?.name !== 'isConfirmed'
-                                        "
-                                        >{{ col.value }}</template
-                                    >
-                                    <QTooltip v-if="col.toolTip">{{
-                                        col.toolTip
-                                    }}</QTooltip>
-                                </component>
-                            </QTd>
-                        </QTr>
-                        <QTr no-hover>
-                            <QTd>
-                                <span>{{ row.item.itemType.code }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ row.item.id }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ row.item.size }}</span>
-                            </QTd>
-                            <QTd>
-                                <span>{{ toCurrency(row.item.minPrice) }}</span>
-                            </QTd>
-                            <QTd colspan="6">
-                                <span>{{ row.item.concept }}</span>
-                                <span v-if="row.item.subName" class="subName">
-                                    {{ row.item.subName }}
-                                </span>
-                                <FetchedTags :item="row.item" />
-                            </QTd>
-                        </QTr>
-                        <!-- Esta última row es utilizada para agregar un espaciado y así marcar una diferencia visual entre los diferentes buys -->
-                        <QTr v-if="rowIndex !== entryBuys.length - 1">
-                            <QTd colspan="10" class="vn-table-separation-row" />
-                        </QTr>
-                    </template>
-                </QTable>
+                <EntryBuys
+                    v-if="entityId"
+                    :id="Number(entityId)"
+                    :editable-mode="false"
+                    table-height="49vh"
+                />
             </QCard>
         </template>
     </CardSummary>
 </template>
-
 <style lang="scss" scoped>
-.separation-row {
-    background-color: var(--vn-section-color) !important;
+.card-group {
+    display: flex;
+    flex-direction: column;
+}
+
+.card-content {
+    display: flex;
+    flex-direction: column;
+    text-overflow: ellipsis;
+    > div {
+        max-height: 24px;
+    }
+}
+
+@media (min-width: 1010px) {
+    .card-group {
+        flex-direction: row;
+    }
+    .card-content {
+        flex: 1;
+        margin-right: 16px;
+    }
 }
 </style>
-
 <i18n>
 es:
-    Travel data: Datos envío
+    Travel: Envío
+    InvoiceIn data: Datos factura
 </i18n>
diff --git a/src/pages/Entry/EntryFilter.vue b/src/pages/Entry/EntryFilter.vue
index 0f632c0ef..8c60918a8 100644
--- a/src/pages/Entry/EntryFilter.vue
+++ b/src/pages/Entry/EntryFilter.vue
@@ -19,6 +19,7 @@ const props = defineProps({
 
 const currenciesOptions = ref([]);
 const companiesOptions = ref([]);
+const entryFilterPanel = ref();
 </script>
 
 <template>
@@ -38,7 +39,7 @@ const companiesOptions = ref([]);
         @on-fetch="(data) => (currenciesOptions = data)"
         auto-load
     />
-    <VnFilterPanel :data-key="props.dataKey" :search-button="true">
+    <VnFilterPanel ref="entryFilterPanel" :data-key="props.dataKey" :search-button="true">
         <template #tags="{ tag, formatFn }">
             <div class="q-gutter-x-xs">
                 <strong>{{ t(`entryFilter.params.${tag.label}`) }}: </strong>
@@ -48,70 +49,65 @@ const companiesOptions = ref([]);
         <template #body="{ params, searchFn }">
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.search"
-                        :label="t('entryFilter.params.search')"
-                        is-outlined
-                    />
+                    <QCheckbox
+                        :label="t('params.isExcludedFromAvailable')"
+                        v-model="params.isExcludedFromAvailable"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('params.isExcludedFromAvailable') }}
+                        </QTooltip>
+                    </QCheckbox>
+                </QItemSection>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('params.isOrdered')"
+                        v-model="params.isOrdered"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isOrdered') }}
+                        </QTooltip>
+                    </QCheckbox>
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.reference"
-                        :label="t('entryFilter.params.reference')"
-                        is-outlined
-                    />
+                    <QCheckbox
+                        :label="t('params.isReceived')"
+                        v-model="params.isReceived"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isReceived') }}
+                        </QTooltip>
+                    </QCheckbox>
+                </QItemSection>
+                <QItemSection>
+                    <QCheckbox
+                        :label="t('entry.list.tableVisibleColumns.isConfirmed')"
+                        v-model="params.isConfirmed"
+                        toggle-indeterminate
+                    >
+                        <QTooltip>
+                            {{ t('entry.list.tableVisibleColumns.isConfirmed') }}
+                        </QTooltip>
+                    </QCheckbox>
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInput
-                        v-model="params.invoiceNumber"
-                        :label="t('entryFilter.params.invoiceNumber')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.travelFk"
-                        :label="t('entryFilter.params.travelFk')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('entryFilter.params.companyFk')"
-                        v-model="params.companyFk"
+                    <VnInputDate
+                        :label="t('params.landed')"
+                        v-model="params.landed"
                         @update:model-value="searchFn()"
-                        :options="companiesOptions"
-                        option-value="id"
-                        option-label="code"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
+                        is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnSelect
-                        :label="t('entryFilter.params.currencyFk')"
-                        v-model="params.currencyFk"
-                        @update:model-value="searchFn()"
-                        :options="currenciesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
+                    <VnInput v-model="params.id" label="Id" is-outlined />
                 </QItemSection>
             </QItem>
             <QItem>
@@ -125,62 +121,165 @@ const companiesOptions = ref([]);
                         rounded
                     />
                 </QItemSection>
-            </QItem>
-            <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.created')"
-                        v-model="params.created"
-                        @update:model-value="searchFn()"
+                    <VnInput
+                        v-model="params.invoiceNumber"
+                        :label="t('params.invoiceNumber')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.from')"
-                        v-model="params.from"
-                        @update:model-value="searchFn()"
+                    <VnInput
+                        v-model="params.reference"
+                        :label="t('entry.list.tableVisibleColumns.reference')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <VnInputDate
-                        :label="t('entryFilter.params.to')"
-                        v-model="params.to"
+                    <VnSelect
+                        :label="t('params.agencyModeId')"
+                        v-model="params.agencyModeId"
                         @update:model-value="searchFn()"
+                        url="AgencyModes"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.evaNotes"
+                        :label="t('params.evaNotes')"
                         is-outlined
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isBooked')"
-                        v-model="params.isBooked"
-                        toggle-indeterminate
-                    />
-                </QItemSection>
-                <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isConfirmed')"
-                        v-model="params.isConfirmed"
-                        toggle-indeterminate
+                    <VnSelect
+                        :label="t('params.warehouseOutFk')"
+                        v-model="params.warehouseOutFk"
+                        @update:model-value="searchFn()"
+                        url="Warehouses"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
                     />
                 </QItemSection>
             </QItem>
             <QItem>
                 <QItemSection>
-                    <QCheckbox
-                        :label="t('entryFilter.params.isOrdered')"
-                        v-model="params.isOrdered"
-                        toggle-indeterminate
+                    <VnSelect
+                        :label="t('params.warehouseInFk')"
+                        v-model="params.warehouseInFk"
+                        @update:model-value="searchFn()"
+                        url="Warehouses"
+                        :fields="['id', 'name']"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    >
+                        <template #option="scope">
+                            <QItem v-bind="scope.itemProps">
+                                <QItemSection>
+                                    <QItemLabel>
+                                        {{ scope.opt?.name }}
+                                    </QItemLabel>
+                                    <QItemLabel caption>
+                                        {{ `#${scope.opt?.id} , ${scope.opt?.nickname}` }}
+                                    </QItemLabel>
+                                </QItemSection>
+                            </QItem>
+                        </template>
+                    </VnSelect>
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.invoiceNumber"
+                        :label="t('params.invoiceNumber')"
+                        is-outlined
+                    />
+                </QItemSection>
+            </QItem>
+
+            <QItem>
+                <QItemSection>
+                    <VnSelect
+                        :label="t('params.entryTypeCode')"
+                        v-model="params.entryTypeCode"
+                        @update:model-value="searchFn()"
+                        url="EntryTypes"
+                        :fields="['code', 'description']"
+                        option-value="code"
+                        option-label="description"
+                        hide-selected
+                        dense
+                        outlined
+                        rounded
+                    />
+                </QItemSection>
+            </QItem>
+            <QItem>
+                <QItemSection>
+                    <VnInput
+                        v-model="params.evaNotes"
+                        :label="t('params.evaNotes')"
+                        is-outlined
                     />
                 </QItemSection>
             </QItem>
         </template>
     </VnFilterPanel>
 </template>
+
+<i18n>
+en:
+    params:
+        isExcludedFromAvailable: Inventory
+        isOrdered: Ordered
+        isReceived: Received
+        isConfirmed: Confirmed
+        isRaid: Raid
+        landed: Date
+        id: Id
+        supplierFk: Supplier
+        invoiceNumber: Invoice number
+        reference: Ref/Alb/Guide
+        agencyModeId: Agency mode
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeCode: Entry type
+        hasToShowDeletedEntries: Show deleted entries
+es:
+    params:
+        isExcludedFromAvailable: Inventario
+        isOrdered: Pedida
+        isConfirmed: Confirmado
+        isReceived: Recibida
+        isRaid: Raid
+        landed: Fecha
+        id: Id
+        supplierFk: Proveedor
+        invoiceNumber: Núm. factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Modo agencia
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeCode: Tipo de entrada
+        hasToShowDeletedEntries: Mostrar entradas eliminadas
+</i18n>
diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue
index 3172c6d0e..3c96a2302 100644
--- a/src/pages/Entry/EntryList.vue
+++ b/src/pages/Entry/EntryList.vue
@@ -1,21 +1,25 @@
 <script setup>
+import axios from 'axios';
+import VnSection from 'src/components/common/VnSection.vue';
 import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useState } from 'src/composables/useState';
+import { onBeforeMount } from 'vue';
+
 import EntryFilter from './EntryFilter.vue';
 import VnTable from 'components/VnTable/VnTable.vue';
-import { toCelsius, toDate } from 'src/filters';
-import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import EntrySummary from './Card/EntrySummary.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
-import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
-import VnSection from 'src/components/common/VnSection.vue';
+import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
+import { toDate } from 'src/filters';
 
 const { t } = useI18n();
 const tableRef = ref();
+const defaultEntry = ref({});
+const state = useState();
+const user = state.getUser();
 const dataKey = 'EntryList';
 
-const { viewSummary } = useSummaryDialog();
-const entryFilter = {
+const entryQueryFilter = {
     include: [
         {
             relation: 'suppliers',
@@ -40,44 +44,58 @@ const entryFilter = {
 
 const columns = computed(() => [
     {
-        name: 'status',
-        columnFilter: false,
+        labelAbbreviation: 'Ex',
+        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
+        toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
+        name: 'isExcludedFromAvailable',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('globals.id'),
-        name: 'id',
-        isId: true,
-        chip: {
-            condition: () => true,
-        },
+        labelAbbreviation: 'Pe',
+        label: t('entry.list.tableVisibleColumns.isOrdered'),
+        toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
+        name: 'isOrdered',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('globals.reference'),
-        name: 'reference',
-        isTitle: true,
-        component: 'input',
-        columnField: {
-            component: null,
-        },
-        create: true,
-        cardVisible: true,
+        labelAbbreviation: 'LE',
+        label: t('entry.list.tableVisibleColumns.isConfirmed'),
+        toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
+        name: 'isConfirmed',
+        component: 'checkbox',
+        width: '35px',
     },
     {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.created'),
-        name: 'created',
-        create: true,
-        cardVisible: true,
+        labelAbbreviation: 'Re',
+        label: t('entry.list.tableVisibleColumns.isReceived'),
+        toolTip: t('entry.list.tableVisibleColumns.isReceived'),
+        name: 'isReceived',
+        component: 'checkbox',
+        width: '35px',
+    },
+    {
+        label: t('entry.list.tableVisibleColumns.landed'),
+        name: 'landed',
         component: 'date',
         columnField: {
             component: null,
         },
-        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.created)),
+        format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
+        width: '105px',
+    },
+    {
+        label: t('globals.id'),
+        name: 'id',
+        isId: true,
+        component: 'number',
+        chip: {
+            condition: () => true,
+        },
+        width: '50px',
     },
     {
-        align: 'left',
         label: t('entry.list.tableVisibleColumns.supplierFk'),
         name: 'supplierFk',
         create: true,
@@ -86,165 +104,213 @@ const columns = computed(() => [
         attrs: {
             url: 'suppliers',
             fields: ['id', 'name'],
-        },
-        columnField: {
-            component: null,
+            where: { order: 'name DESC' },
         },
         format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
+        width: '110px',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isBooked'),
-        name: 'isBooked',
+        label: t('entry.list.tableVisibleColumns.invoiceNumber'),
+        name: 'invoiceNumber',
+        component: 'input',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.reference'),
+        name: 'reference',
+        isTitle: true,
+        component: 'input',
+        columnField: {
+            component: null,
+        },
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isConfirmed'),
-        name: 'isConfirmed',
+        label: 'AWB',
+        name: 'awbCode',
+        component: 'input',
+        width: '100px',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.agencyModeId'),
+        name: 'agencyModeId',
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
+        component: 'select',
+        attrs: {
+            url: 'agencyModes',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyModeName),
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.isOrdered'),
-        name: 'isOrdered',
+        label: t('entry.list.tableVisibleColumns.evaNotes'),
+        name: 'evaNotes',
+        component: 'input',
+    },
+    {
+        align: 'left',
+        label: t('entry.list.tableVisibleColumns.warehouseOutFk'),
+        name: 'warehouseOutFk',
         cardVisible: true,
-        create: true,
-        component: 'checkbox',
+        component: 'select',
+        attrs: {
+            url: 'warehouses',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseOutName),
+        width: '65px',
     },
     {
         align: 'left',
-        label: t('entry.list.tableVisibleColumns.companyFk'),
+        label: t('entry.list.tableVisibleColumns.warehouseInFk'),
+        name: 'warehouseInFk',
+        cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'warehouses',
+            fields: ['id', 'name'],
+        },
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseInName),
+        width: '65px',
+    },
+    {
+        align: 'left',
+        labelAbbreviation: t('Type'),
+        label: t('entry.list.tableVisibleColumns.entryTypeDescription'),
+        toolTip: t('entry.list.tableVisibleColumns.entryTypeDescription'),
+        name: 'entryTypeCode',
+        component: 'select',
+        attrs: {
+            url: 'entryTypes',
+            fields: ['code', 'description'],
+            optionValue: 'code',
+            optionLabel: 'description',
+        },
+        width: '65px',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.entryTypeDescription),
+    },
+    {
         name: 'companyFk',
+        label: t('entry.list.tableVisibleColumns.companyFk'),
+        cardVisible: false,
+        visible: false,
+        create: true,
         component: 'select',
         attrs: {
-            url: 'companies',
-            fields: ['id', 'code'],
+            optionValue: 'id',
             optionLabel: 'code',
-            optionValue: 'id',
+            url: 'Companies',
         },
-        columnField: {
-            component: null,
-        },
-        create: true,
-
-        format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
     },
     {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.travelFk'),
         name: 'travelFk',
-        component: 'select',
-        attrs: {
-            url: 'travels',
-            fields: ['id', 'ref'],
-            optionLabel: 'ref',
-            optionValue: 'id',
-        },
-        columnField: {
-            component: null,
-        },
+        label: t('entry.list.tableVisibleColumns.travelFk'),
+        cardVisible: false,
+        visible: false,
         create: true,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
-    },
-    {
-        align: 'left',
-        label: t('entry.list.tableVisibleColumns.invoiceAmount'),
-        name: 'invoiceAmount',
-        cardVisible: true,
-    },
-    {
-        align: 'left',
-        name: 'initialTemperature',
-        label: t('entry.basicData.initialTemperature'),
-        field: 'initialTemperature',
-        format: (row) => toCelsius(row.initialTemperature),
-    },
-    {
-        align: 'left',
-        name: 'finalTemperature',
-        label: t('entry.basicData.finalTemperature'),
-        field: 'finalTemperature',
-        format: (row) => toCelsius(row.finalTemperature),
-    },
-    {
-        label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
-        name: 'isExcludedFromAvailable',
-        columnFilter: {
-            inWhere: true,
-        },
-    },
-    {
-        align: 'right',
-        name: 'tableActions',
-        actions: [
-            {
-                title: t('components.smartCard.viewSummary'),
-                icon: 'preview',
-                action: (row) => viewSummary(row.id, EntrySummary),
-                isPrimary: true,
-            },
-        ],
     },
 ]);
+function getBadgeAttrs(row) {
+    const date = row.landed;
+    let today = Date.vnNew();
+    today.setHours(0, 0, 0, 0);
+    let timeTicket = new Date(date);
+    timeTicket.setHours(0, 0, 0, 0);
+
+    let timeDiff = today - timeTicket;
+
+    if (timeDiff > 0) return { color: 'info', 'text-color': 'black' };
+    if (timeDiff < 0) return { color: 'warning', 'text-color': 'black' };
+    switch (row.entryTypeCode) {
+        case 'regularization':
+        case 'life':
+        case 'internal':
+        case 'inventory':
+            if (!row.isOrdered || !row.isConfirmed)
+                return { color: 'negative', 'text-color': 'black' };
+            break;
+        case 'product':
+        case 'packaging':
+        case 'devaluation':
+        case 'payment':
+        case 'transport':
+            if (
+                row.invoiceAmount === null ||
+                (row.invoiceNumber === null && row.reference === null) ||
+                !row.isOrdered ||
+                !row.isConfirmed
+            )
+                return { color: 'negative', 'text-color': 'black' };
+            break;
+        default:
+            break;
+    }
+    return { color: 'transparent' };
+}
+
+onBeforeMount(async () => {
+    defaultEntry.value = (await axios.get('EntryConfigs/findOne')).data;
+});
 </script>
 
 <template>
     <VnSection
         :data-key="dataKey"
-        :columns="columns"
         prefix="entry"
         url="Entries/filter"
         :array-data-props="{
             url: 'Entries/filter',
-            order: 'id DESC',
-            userFilter: entryFilter,
+            order: 'landed DESC',
+            userFilter: EntryFilter,
         }"
     >
         <template #advanced-menu>
-            <EntryFilter data-key="EntryList" />
+            <EntryFilter :data-key="dataKey" />
         </template>
         <template #body>
             <VnTable
+                v-if="defaultEntry.defaultSupplierFk"
                 ref="tableRef"
                 :data-key="dataKey"
+                url="Entries/filter"
+                :filter="entryQueryFilter"
+                order="landed DESC"
                 :create="{
                     urlCreate: 'Entries',
-                    title: t('entry.list.newEntry'),
+                    title: t('Create entry'),
                     onDataSaved: ({ id }) => tableRef.redirect(id),
-                    formInitialData: {},
+                    formInitialData: {
+                        supplierFk: defaultEntry.defaultSupplierFk,
+                        dated: Date.vnNew(),
+                        companyFk: user?.companyFk,
+                    },
                 }"
                 :columns="columns"
                 redirect="entry"
                 :right-search="false"
             >
-                <template #column-status="{ row }">
-                    <div class="row q-gutter-xs">
-                        <QIcon
-                            v-if="!!row.isExcludedFromAvailable"
-                            name="vn:inventory"
-                            color="primary"
-                        >
-                            <QTooltip>{{
-                                t(
-                                    'entry.list.tableVisibleColumns.isExcludedFromAvailable',
-                                )
-                            }}</QTooltip>
-                        </QIcon>
-                        <QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
-                            <QTooltip>
-                                {{
-                                    t('globals.raid', {
-                                        daysInForward: row.daysInForward,
-                                    })
-                                }}</QTooltip
-                            >
-                        </QIcon>
-                    </div>
+                <template #column-landed="{ row }">
+                    <QBadge
+                        v-if="row?.travelFk"
+                        v-bind="getBadgeAttrs(row)"
+                        class="q-pa-sm"
+                        style="font-size: 14px"
+                    >
+                        {{ toDate(row.landed) }}
+                    </QBadge>
                 </template>
                 <template #column-supplierFk="{ row }">
                     <span class="link" @click.stop>
@@ -252,13 +318,27 @@ const columns = computed(() => [
                         <SupplierDescriptorProxy :id="row.supplierFk" />
                     </span>
                 </template>
-                <template #column-travelFk="{ row }">
-                    <span class="link" @click.stop>
-                        {{ row.travelRef }}
-                        <TravelDescriptorProxy :id="row.travelFk" />
-                    </span>
+                <template #column-create-travelFk="{ data }">
+                    <VnSelectTravelExtended
+                        :data="data"
+                        v-model="data.travelFk"
+                        :onFilterTravelSelected="
+                            (data, result) => (data.travelFk = result)
+                        "
+                        data-cy="entry-travel-select"
+                    />
                 </template>
             </VnTable>
         </template>
     </VnSection>
 </template>
+
+<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
+    Create entry: Crear entrada
+    Type: Tipo
+</i18n>
diff --git a/src/pages/Entry/EntryStockBought.vue b/src/pages/Entry/EntryStockBought.vue
index fa0bdc12e..4bd0fe640 100644
--- a/src/pages/Entry/EntryStockBought.vue
+++ b/src/pages/Entry/EntryStockBought.vue
@@ -34,18 +34,20 @@ const columns = computed(() => [
         label: t('entryStockBought.buyer'),
         isTitle: true,
         component: 'select',
+        isEditable: false,
         cardVisible: true,
         create: true,
         attrs: {
             url: 'Workers/activeWithInheritedRole',
-            fields: ['id', 'name'],
+            fields: ['id', 'name', 'nickname'],
             where: { role: 'buyer' },
             optionFilter: 'firstName',
-            optionLabel: 'name',
+            optionLabel: 'nickname',
             optionValue: 'id',
             useLike: false,
         },
         columnFilter: false,
+        width: '70px',
     },
     {
         align: 'center',
@@ -55,6 +57,7 @@ const columns = computed(() => [
         create: true,
         component: 'number',
         summation: true,
+        width: '50px',
     },
     {
         align: 'center',
@@ -78,6 +81,7 @@ const columns = computed(() => [
         actions: [
             {
                 title: t('entryStockBought.viewMoreDetails'),
+                name: 'searchBtn',
                 icon: 'search',
                 isPrimary: true,
                 action: (row) => {
@@ -91,6 +95,7 @@ const columns = computed(() => [
                 },
             },
         ],
+        'data-cy': 'table-actions',
     },
 ]);
 
@@ -158,7 +163,7 @@ function round(value) {
                 @on-fetch="
                     (data) => {
                         travel = data.find(
-                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh'
+                            (data) => data.warehouseIn?.code.toLowerCase() === 'vnh',
                         );
                     }
                 "
@@ -179,6 +184,7 @@ function round(value) {
                         @click="openDialog()"
                         :title="t('entryStockBought.editTravel')"
                         color="primary"
+                        data-cy="edit-travel"
                     />
                 </div>
             </VnRow>
@@ -239,10 +245,11 @@ function round(value) {
                 table-height="80vh"
                 auto-load
                 :column-search="false"
+                :without-header="true"
             >
                 <template #column-workerFk="{ row }">
                     <span class="link" @click.stop>
-                        {{ row?.worker?.user?.name }}
+                        {{ row?.worker?.user?.nickname }}
                         <WorkerDescriptorProxy :id="row?.workerFk" />
                     </span>
                 </template>
@@ -279,10 +286,11 @@ function round(value) {
     justify-content: center;
 }
 .column {
+    min-width: 40%;
+    margin-top: 5%;
     display: flex;
     flex-direction: column;
     align-items: center;
-    min-width: 35%;
 }
 .text-negative {
     color: $negative !important;
diff --git a/src/pages/Entry/EntryStockBoughtDetail.vue b/src/pages/Entry/EntryStockBoughtDetail.vue
index 812171825..1a37994d9 100644
--- a/src/pages/Entry/EntryStockBoughtDetail.vue
+++ b/src/pages/Entry/EntryStockBoughtDetail.vue
@@ -21,7 +21,7 @@ const $props = defineProps({
 const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&dated=${$props.dated}`;
 const columns = [
     {
-        align: 'left',
+        align: 'right',
         label: t('Entry'),
         name: 'entryFk',
         isTitle: true,
@@ -29,7 +29,7 @@ const columns = [
         columnFilter: false,
     },
     {
-        align: 'left',
+        align: 'right',
         name: 'itemFk',
         label: t('Item'),
         columnFilter: false,
@@ -44,21 +44,21 @@ const columns = [
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         name: 'volume',
         label: t('Volume'),
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         label: t('Packaging'),
         name: 'packagingFk',
         columnFilter: false,
         cardVisible: true,
     },
     {
-        align: 'left',
+        align: 'right',
         label: 'Packing',
         name: 'packing',
         columnFilter: false,
@@ -73,12 +73,14 @@ const columns = [
                 ref="tableRef"
                 data-key="StockBoughtsDetail"
                 :url="customUrl"
-                order="itemName DESC"
+                order="volume DESC"
                 :columns="columns"
                 :right-search="false"
                 :disable-infinite-scroll="true"
                 :disable-option="{ card: true }"
                 :limit="0"
+                :without-header="true"
+                :with-filters="false"
                 auto-load
             >
                 <template #column-entryFk="{ row }">
@@ -99,16 +101,14 @@ const columns = [
 </template>
 <style lang="css" scoped>
 .container {
-    max-width: 50vw;
+    max-width: 100%;
+    width: 50%;
     overflow: auto;
     justify-content: center;
     align-items: center;
     margin: auto;
     background-color: var(--vn-section-color);
-    padding: 4px;
-}
-.container > div > div > .q-table__top.relative-position.row.items-center {
-    background-color: red !important;
+    padding: 2%;
 }
 </style>
 <i18n>
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index 80f3491a8..88b16cb03 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -1,21 +1,36 @@
 entry:
+    lock:
+        title: Lock entry
+        message: This entry has been locked by {userName} for {time} minutes. Do you want to unlock it?
+        success: The entry has been locked successfully
     list:
         newEntry: New entry
         tableVisibleColumns:
-            created: Creation
-            supplierFk: Supplier
-            isBooked: Booked
-            isConfirmed: Confirmed
+            isExcludedFromAvailable: Exclude from inventory
             isOrdered: Ordered
+            isConfirmed: Ready to label
+            isReceived: Received
+            isRaid: Raid
+            landed: Date
+            supplierFk: Supplier
+            reference: Ref/Alb/Guide
+            invoiceNumber: Invoice
+            agencyModeId: Agency
+            isBooked: Booked
             companyFk: Company
-            travelFk: Travel
-            isExcludedFromAvailable: Inventory
+            evaNotes: Notes
+            warehouseOutFk: Origin
+            warehouseInFk: Destiny
+            entryTypeDescription: Entry type
             invoiceAmount: Import
+            travelFk: Travel
+            dated: Dated
         inventoryEntry: Inventory entry
     summary:
         commission: Commission
         currency: Currency
         invoiceNumber: Invoice number
+        invoiceAmount: Invoice amount
         ordered: Ordered
         booked: Booked
         excludedFromAvailable: Inventory
@@ -33,6 +48,7 @@ entry:
         buyingValue: Buying value
         import: Import
         pvp: PVP
+        entryType: Entry type
     basicData:
         travel: Travel
         currency: Currency
@@ -69,17 +85,55 @@ entry:
             landing: Landing
             isExcludedFromAvailable: Es inventory
     params:
-        toShipped: To
-        fromShipped: From
-        daysOnward: Days onward
-        daysAgo: Days ago
-        warehouseInFk: Warehouse in
+        isExcludedFromAvailable: Exclude from inventory
+        isOrdered: Ordered
+        isConfirmed: Ready to label
+        isReceived: Received
+        isIgnored: Ignored
+        isRaid: Raid
+        landed: Date
+        supplierFk: Supplier
+        reference: Ref/Alb/Guide
+        invoiceNumber: Invoice
+        agencyModeId: Agency
+        isBooked: Booked
+        companyFk: Company
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeDescription: Entry type
+        invoiceAmount: Import
+        travelFk: Travel
+        dated: Dated
+        itemFk: Item id
+        hex: Color
+        name: Item name
+        size: Size
+        stickers: Stickers
+        packagingFk: Packaging
+        weight: Kg
+        groupingMode: Grouping selector
+        grouping: Grouping
+        quantity: Quantity
+        buyingValue: Buying value
+        price2: Package
+        price3: Box
+        minPrice: Minumum price
+        hasMinPrice: Has minimum price
+        packingOut: Packing out
+        comment: Comment
+        subName: Supplier name
+        tags: Tags
+        company_name: Company name
+        itemTypeFk: Item type
+        workerFk: Worker id
     search: Search entries
     searchInfo: You can search by entry reference
     descriptorMenu:
         showEntryReport: Show entry report
 entryFilter:
     params:
+        isExcludedFromAvailable: Exclude from inventory
         invoiceNumber: Invoice number
         travelFk: Travel
         companyFk: Company
@@ -91,8 +145,16 @@ entryFilter:
         isBooked: Booked
         isConfirmed: Confirmed
         isOrdered: Ordered
+        isReceived: Received
         search: General search
         reference: Reference
+        landed: Landed
+        id: Id
+        agencyModeId: Agency
+        evaNotes: Notes
+        warehouseOutFk: Origin
+        warehouseInFk: Destiny
+        entryTypeCode: Entry type
 myEntries:
     id: ID
     landed: Landed
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index a5b968016..3025d64cb 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -1,21 +1,36 @@
 entry:
+    lock:
+        title: Entrada bloqueada
+        message: Esta entrada ha sido bloqueada por {userName} hace {time} minutos. ¿Quieres desbloquearla?
+        success: La entrada ha sido bloqueada correctamente
     list:
         newEntry: Nueva entrada
         tableVisibleColumns:
-            created: Creación
-            supplierFk: Proveedor
-            isBooked: Asentado
-            isConfirmed: Confirmado
+            isExcludedFromAvailable: Excluir del inventario
             isOrdered: Pedida
+            isConfirmed: Lista para etiquetar
+            isReceived: Recibida
+            isRaid: Redada
+            landed: Fecha
+            supplierFk: Proveedor
+            invoiceNumber: Nº Factura
+            reference: Ref/Alb/Guía
+            agencyModeId: Agencia
+            isBooked: Asentado
             companyFk: Empresa
             travelFk: Envio
-            isExcludedFromAvailable: Inventario
+            evaNotes: Notas
+            warehouseOutFk: Origen
+            warehouseInFk: Destino
+            entryTypeDescription: Tipo entrada
             invoiceAmount: Importe
+            dated: Fecha
         inventoryEntry: Es inventario
     summary:
         commission: Comisión
         currency: Moneda
         invoiceNumber: Núm. factura
+        invoiceAmount: Importe
         ordered: Pedida
         booked: Contabilizada
         excludedFromAvailable: Inventario
@@ -34,12 +49,13 @@ entry:
         buyingValue: Coste
         import: Importe
         pvp: PVP
+        entryType: Tipo entrada
     basicData:
         travel: Envío
         currency: Moneda
         observation: Observación
         commission: Comisión
-        booked: Asentado
+        booked: Contabilizada
         excludedFromAvailable: Inventario
         initialTemperature: Ini °C
         finalTemperature: Fin °C
@@ -69,31 +85,70 @@ entry:
             packingOut: Embalaje envíos
             landing: Llegada
             isExcludedFromAvailable: Es inventario
-    params:
-        toShipped: Hasta
-        fromShipped: Desde
-        warehouseInFk: Alm. entrada
-        daysOnward: Días adelante
-        daysAgo: Días atras
-    descriptorMenu:
-        showEntryReport: Ver informe del pedido
+
     search: Buscar entradas
     searchInfo: Puedes buscar por referencia de entrada
+    params:
+        isExcludedFromAvailable: Excluir del inventario
+        isOrdered: Pedida
+        isConfirmed: Lista para etiquetar
+        isReceived: Recibida
+        isRaid: Redada
+        isIgnored: Ignorado
+        landed: Fecha
+        supplierFk: Proveedor
+        invoiceNumber: Nº Factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Agencia
+        isBooked: Asentado
+        companyFk: Empresa
+        travelFk: Envio
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeDescription: Tipo entrada
+        invoiceAmount: Importe
+        dated: Fecha
+        itemFk: Id artículo
+        hex: Color
+        name: Nombre artículo
+        size: Medida
+        stickers: Etiquetas
+        packagingFk: Embalaje
+        weight: Kg
+        groupinMode: Selector de grouping
+        grouping: Grouping
+        quantity: Quantity
+        buyingValue: Precio de compra
+        price2: Paquete
+        price3: Caja
+        minPrice: Precio mínimo
+        hasMinPrice: Tiene precio mínimo
+        packingOut: Packing out
+        comment: Referencia
+        subName: Nombre proveedor
+        tags: Etiquetas
+        company_name: Nombre empresa
+        itemTypeFk: Familia
+        workerFk: Comprador
 entryFilter:
     params:
-        invoiceNumber: Núm. factura
-        travelFk: Envío
-        companyFk: Empresa
-        currencyFk: Moneda
-        supplierFk: Proveedor
-        from: Desde
-        to: Hasta
-        created: Fecha creación
-        isBooked: Asentado
-        isConfirmed: Confirmado
+        isExcludedFromAvailable: Inventario
         isOrdered: Pedida
-        search: Búsqueda general
-        reference: Referencia
+        isConfirmed: Confirmado
+        isReceived: Recibida
+        isRaid: Raid
+        landed: Fecha
+        id: Id
+        supplierFk: Proveedor
+        invoiceNumber: Núm. factura
+        reference: Ref/Alb/Guía
+        agencyModeId: Modo agencia
+        evaNotes: Notas
+        warehouseOutFk: Origen
+        warehouseInFk: Destino
+        entryTypeCode: Tipo de entrada
+        hasToShowDeletedEntries: Mostrar entradas eliminadas
 myEntries:
     id: ID
     landed: F. llegada
diff --git a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
index c01ec4ab4..905ddebb2 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue
@@ -125,7 +125,7 @@ function deleteFile(dmsFk) {
                 <VnInput
                     clearable
                     clear-icon="close"
-                    :label="t('Supplier ref')"
+                    :label="t('invoiceIn.supplierRef')"
                     v-model="data.supplierRef"
                 />
             </VnRow>
@@ -149,6 +149,7 @@ function deleteFile(dmsFk) {
                     option-value="id"
                     option-label="id"
                     :filter-options="['id', 'name']"
+                    data-cy="UnDeductibleVatSelect"
                 >
                     <template #option="scope">
                         <QItem v-bind="scope.itemProps">
@@ -215,7 +216,7 @@ function deleteFile(dmsFk) {
                         v-else
                         icon="add_circle"
                         round
-                        shortcut="+"
+                        v-shortcut="'+'"
                         padding="xs"
                         @click="
                             () => {
@@ -310,7 +311,6 @@ function deleteFile(dmsFk) {
         supplierFk: Supplier
     es:
         supplierFk: Proveedor
-        Supplier ref: Ref. proveedor
         Expedition date: Fecha expedición
         Operation date: Fecha operación
         Undeductible VAT: Iva no deducible
diff --git a/src/pages/InvoiceIn/Card/InvoiceInCard.vue b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
index 8aa35f4d8..34cc26437 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInCard.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInCard.vue
@@ -1,47 +1,18 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import InvoiceInDescriptor from './InvoiceInDescriptor.vue';
+import { onBeforeRouteUpdate } from 'vue-router';
+import { setRectificative } from '../composables/setRectificative';
+import filter from './InvoiceInFilter.js';
 
-const filter = {
-    include: [
-        {
-            relation: 'supplier',
-            scope: {
-                include: {
-                    relation: 'contacts',
-                    scope: { where: { email: { neq: null } } },
-                },
-            },
-        },
-        { relation: 'invoiceInDueDay' },
-        { relation: 'company' },
-        { relation: 'currency' },
-        {
-            relation: 'dms',
-            scope: {
-                fields: [
-                    'dmsTypeFk',
-                    'reference',
-                    'hardCopyNumber',
-                    'workerFk',
-                    'description',
-                    'hasFile',
-                    'file',
-                    'created',
-                    'companyFk',
-                    'warehouseFk',
-                ],
-            },
-        },
-    ],
-};
+onBeforeRouteUpdate(async (to) => await setRectificative(to));
 </script>
 
 <template>
     <VnCardBeta
         data-key="InvoiceIn"
-        base-url="InvoiceIns"
+        url="InvoiceIns"
         :descriptor="InvoiceInDescriptor"
-        :user-filter="filter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index da7bd4426..3843f5bf7 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -7,6 +7,7 @@ import { toCurrency, toDate } from 'src/filters';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
+import filter from './InvoiceInFilter.js';
 import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
 
 const $props = defineProps({ id: { type: Number, default: null } });
@@ -16,33 +17,10 @@ const { t } = useI18n();
 const cardDescriptorRef = ref();
 const entityId = computed(() => $props.id || +currentRoute.value.params.id);
 const totalAmount = ref();
-
-const filter = {
-    include: [
-        {
-            relation: 'supplier',
-            scope: {
-                include: {
-                    relation: 'contacts',
-                    scope: {
-                        where: {
-                            email: { neq: null },
-                        },
-                    },
-                },
-            },
-        },
-        {
-            relation: 'invoiceInDueDay',
-        },
-        {
-            relation: 'company',
-        },
-        {
-            relation: 'currency',
-        },
-    ],
-};
+const config = ref();
+const cplusRectificationTypes = ref([]);
+const siiTypeInvoiceIns = ref([]);
+const invoiceCorrectionTypes = ref([]);
 const invoiceInCorrection = reactive({ correcting: [], corrected: null });
 const routes = reactive({
     getSupplier: (id) => {
@@ -112,7 +90,6 @@ async function setInvoiceCorrection(id) {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
-        module="InvoiceIn"
         data-key="InvoiceIn"
         :url="`InvoiceIns/${entityId}`"
         :filter="filter"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
index c3ab635c8..8b039ec27 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptorMenu.vue
@@ -186,7 +186,7 @@ const createInvoiceInCorrection = async () => {
                 clickable
                 @click="book(entityId)"
             >
-                <QItemSection>{{ t('invoiceIn.descriptorMenu.toBook') }}</QItemSection>
+                <QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
             </QItem>
         </template>
     </InvoiceInToBook>
@@ -197,7 +197,7 @@ const createInvoiceInCorrection = async () => {
         @click="triggerMenu('unbook')"
     >
         <QItemSection>
-            {{ t('invoiceIn.descriptorMenu.toUnbook') }}
+            {{ t('invoiceIn.descriptorMenu.unbook') }}
         </QItemSection>
     </QItem>
     <QItem
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
index 23387ff74..20cc1cc71 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDueDay.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, onBeforeMount } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import axios from 'axios';
@@ -11,6 +11,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import useNotify from 'src/composables/useNotify.js';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+import { toCurrency } from 'filters/index';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -24,7 +25,7 @@ const invoiceInFormRef = ref();
 const invoiceId = +route.params.id;
 const filter = { where: { invoiceInFk: invoiceId } };
 const areRows = ref(false);
-
+const totals = ref();
 const columns = computed(() => [
     {
         name: 'duedate',
@@ -63,6 +64,8 @@ const columns = computed(() => [
     },
 ]);
 
+const totalAmount = computed(() => getTotal(invoiceInFormRef.value.formData, 'amount'));
+
 const isNotEuro = (code) => code != 'EUR';
 
 async function insert() {
@@ -70,6 +73,10 @@ async function insert() {
     await invoiceInFormRef.value.reload();
     notify(t('globals.dataSaved'), 'positive');
 }
+
+onBeforeMount(async () => {
+    totals.value = (await axios.get(`InvoiceIns/${invoiceId}/getTotals`)).data;
+});
 </script>
 <template>
     <CrudModel
@@ -144,7 +151,7 @@ async function insert() {
                         <QTd />
                         <QTd />
                         <QTd>
-                            {{ getTotal(rows, 'amount', { currency: 'default' }) }}
+                            {{ toCurrency(totalAmount) }}
                         </QTd>
                         <QTd>
                             <template v-if="isNotEuro(invoiceIn.currency.code)">
@@ -222,10 +229,19 @@ async function insert() {
         <QBtn
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             size="lg"
             round
-            @click="!areRows ? insert() : invoiceInFormRef.insert()"
+            @click="
+                () => {
+                    if (!areRows) insert();
+                    else
+                        invoiceInFormRef.insert({
+                            amount: (totals.totalTaxableBase - totalAmount).toFixed(2),
+                            invoiceInFk: invoiceId,
+                        });
+                }
+            "
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInFilter.js b/src/pages/InvoiceIn/Card/InvoiceInFilter.js
new file mode 100644
index 000000000..6df8b5830
--- /dev/null
+++ b/src/pages/InvoiceIn/Card/InvoiceInFilter.js
@@ -0,0 +1,33 @@
+export default {
+    include: [
+        {
+            relation: 'supplier',
+            scope: {
+                include: {
+                    relation: 'contacts',
+                    scope: { where: { email: { neq: null } } },
+                },
+            },
+        },
+        { relation: 'invoiceInDueDay' },
+        { relation: 'company' },
+        { relation: 'currency' },
+        {
+            relation: 'dms',
+            scope: {
+                fields: [
+                    'dmsTypeFk',
+                    'reference',
+                    'hardCopyNumber',
+                    'workerFk',
+                    'description',
+                    'hasFile',
+                    'file',
+                    'created',
+                    'companyFk',
+                    'warehouseFk',
+                ],
+            },
+        },
+    ],
+};
diff --git a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
index e529ea6cd..6f8642313 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInIntrastat.vue
@@ -218,7 +218,7 @@ const columns = computed(() => [
         <QBtn
             color="primary"
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             size="lg"
             round
             @click="invoiceInFormRef.insert()"
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index e546638f2..d358601d3 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -193,7 +193,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
             <InvoiceIntoBook>
                 <template #content="{ book }">
                     <QBtn
-                        :label="t('To book')"
+                        :label="t('Book')"
                         color="orange-11"
                         text-color="black"
                         @click="book(entityId)"
@@ -224,10 +224,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                         </span>
                     </template>
                 </VnLv>
-                <VnLv
-                    :label="t('invoiceIn.list.supplierRef')"
-                    :value="entity.supplierRef"
-                />
+                <VnLv :label="t('invoiceIn.supplierRef')" :value="entity.supplierRef" />
                 <VnLv
                     :label="t('invoiceIn.summary.currency')"
                     :value="entity.currency?.code"
@@ -357,7 +354,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                 entity.totals.totalTaxableBaseForeignValue &&
                                 toCurrency(
                                     entity.totals.totalTaxableBaseForeignValue,
-                                    currency
+                                    currency,
                                 )
                             }}</QTd>
                         </QTr>
@@ -392,7 +389,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
                                     entity.totals.totalDueDayForeignValue &&
                                     toCurrency(
                                         entity.totals.totalDueDayForeignValue,
-                                        currency
+                                        currency,
                                     )
                                 }}
                             </QTd>
@@ -472,5 +469,5 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
         Search invoice: Buscar factura recibida
         You can search by invoice reference: Puedes buscar por referencia de la factura
         Totals: Totales
-        To book: Contabilizar
+        Book: Contabilizar
 </i18n>
diff --git a/src/pages/InvoiceIn/Card/InvoiceInVat.vue b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
index f99e060b8..e77453bc0 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInVat.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInVat.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, nextTick } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useArrayData } from 'src/composables/useArrayData';
@@ -25,7 +25,6 @@ const sageTaxTypes = ref([]);
 const sageTransactionTypes = ref([]);
 const rowsSelected = ref([]);
 const invoiceInFormRef = ref();
-const expenseRef = ref();
 
 defineProps({
     actionIcon: {
@@ -97,6 +96,20 @@ const columns = computed(() => [
     },
 ]);
 
+const taxableBaseTotal = computed(() => {
+    return getTotal(invoiceInFormRef.value.formData, 'taxableBase');
+});
+
+const taxRateTotal = computed(() => {
+    return getTotal(invoiceInFormRef.value.formData, null, {
+        cb: taxRate,
+    });
+});
+
+const combinedTotal = computed(() => {
+    return +taxableBaseTotal.value + +taxRateTotal.value;
+});
+
 const filter = {
     fields: [
         'id',
@@ -117,7 +130,7 @@ const isNotEuro = (code) => code != 'EUR';
 function taxRate(invoiceInTax) {
     const sageTaxTypeId = invoiceInTax.taxTypeSageFk;
     const taxRateSelection = sageTaxTypes.value.find(
-        (transaction) => transaction.id == sageTaxTypeId
+        (transaction) => transaction.id == sageTaxTypeId,
     );
     const taxTypeSage = taxRateSelection?.rate ?? 0;
     const taxableBase = invoiceInTax?.taxableBase ?? 0;
@@ -125,35 +138,26 @@ function taxRate(invoiceInTax) {
     return ((taxTypeSage / 100) * taxableBase).toFixed(2);
 }
 
-function autocompleteExpense(evt, row, col) {
+function autocompleteExpense(evt, row, col, ref) {
     const val = evt.target.value;
     if (!val) return;
 
     const param = isNaN(val) ? row[col.model] : val;
     const lookup = expenses.value.find(
-        ({ id }) => id == useAccountShortToStandard(param)
+        ({ id }) => id == useAccountShortToStandard(param),
     );
 
-    expenseRef.value.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
+    ref.vnSelectDialogRef.vnSelectRef.toggleOption(lookup);
 }
 
-const taxableBaseTotal = computed(() => {   
-    return getTotal(invoiceInFormRef.value.formData, 'taxableBase', );
-});
-
-const taxRateTotal = computed(() => {
-    return getTotal(invoiceInFormRef.value.formData, null, {
-        cb: taxRate,
+function setCursor(ref) {
+    nextTick(() => {
+        const select = ref.vnSelectDialogRef
+            ? ref.vnSelectDialogRef.vnSelectRef
+            : ref.vnSelectRef;
+        select.$el.querySelector('input').setSelectionRange(0, 0);
     });
-});
-
-
-const combinedTotal = computed(() => {
-    return +taxableBaseTotal.value + +taxRateTotal.value;
-});
-
-
-
+}
 </script>
 <template>
     <FetchData
@@ -191,14 +195,24 @@ const combinedTotal = computed(() => {
                 <template #body-cell-expense="{ row, col }">
                     <QTd>
                         <VnSelectDialog
-                            ref="expenseRef"
+                            :ref="`expenseRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'name']"
                             :tooltip="t('Create a new expense')"
-                            @keydown.tab="autocompleteExpense($event, row, col)"
+                            @keydown.tab="
+                                autocompleteExpense(
+                                    $event,
+                                    row,
+                                    col,
+                                    $refs[`expenseRef-${row.$index}`],
+                                )
+                            "
+                            @update:model-value="
+                                setCursor($refs[`expenseRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -214,7 +228,7 @@ const combinedTotal = computed(() => {
                     </QTd>
                 </template>
                 <template #body-cell-taxablebase="{ row }">
-                    <QTd>
+                    <QTd shrink>
                         <VnInputNumber
                             clear-icon="close"
                             v-model="row.taxableBase"
@@ -225,12 +239,16 @@ const combinedTotal = computed(() => {
                 <template #body-cell-sageiva="{ row, col }">
                     <QTd>
                         <VnSelect
+                            :ref="`sageivaRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'vat']"
                             data-cy="vat-sageiva"
+                            @update:model-value="
+                                setCursor($refs[`sageivaRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -248,11 +266,15 @@ const combinedTotal = computed(() => {
                 <template #body-cell-sagetransaction="{ row, col }">
                     <QTd>
                         <VnSelect
+                            :ref="`sagetransactionRef-${row.$index}`"
                             v-model="row[col.model]"
                             :options="col.options"
                             :option-value="col.optionValue"
                             :option-label="col.optionLabel"
                             :filter-options="['id', 'transaction']"
+                            @update:model-value="
+                                setCursor($refs[`sagetransactionRef-${row.$index}`])
+                            "
                         >
                             <template #option="scope">
                                 <QItem v-bind="scope.itemProps">
@@ -270,7 +292,7 @@ const combinedTotal = computed(() => {
                     </QTd>
                 </template>
                 <template #body-cell-foreignvalue="{ row }">
-                    <QTd>
+                    <QTd shrink>
                         <VnInputNumber
                             :class="{
                                 'no-pointer-events': !isNotEuro(currency),
@@ -283,7 +305,7 @@ const combinedTotal = computed(() => {
                                     row.taxableBase = await getExchange(
                                         val,
                                         row.currencyFk,
-                                        invoiceIn.issued
+                                        invoiceIn.issued,
                                     );
                                 }
                             "
@@ -426,7 +448,7 @@ const combinedTotal = computed(() => {
             color="primary"
             icon="add"
             size="lg"
-            shortcut="+"
+            v-shortcut="'+'"
             round
             @click="invoiceInFormRef.insert()"
         >
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index e1723e3b1..0960d0d6c 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -29,6 +29,7 @@ const cols = computed(() => [
         name: 'isBooked',
         label: t('invoiceIn.isBooked'),
         columnFilter: false,
+        component: 'checkbox',
     },
     {
         align: 'left',
@@ -56,7 +57,7 @@ const cols = computed(() => [
     {
         align: 'left',
         name: 'supplierRef',
-        label: t('invoiceIn.list.supplierRef'),
+        label: t('invoiceIn.supplierRef'),
     },
     {
         align: 'left',
@@ -177,7 +178,7 @@ const cols = computed(() => [
                         :required="true"
                     />
                     <VnInput
-                        :label="t('invoiceIn.list.supplierRef')"
+                        :label="t('invoiceIn.supplierRef')"
                         v-model="data.supplierRef"
                     />
                     <VnSelect
diff --git a/src/pages/InvoiceIn/InvoiceInToBook.vue b/src/pages/InvoiceIn/InvoiceInToBook.vue
index 95ce8155a..5bdbe197b 100644
--- a/src/pages/InvoiceIn/InvoiceInToBook.vue
+++ b/src/pages/InvoiceIn/InvoiceInToBook.vue
@@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import { useArrayData } from 'src/composables/useArrayData';
+import qs from 'qs';
 const { notify, dialog } = useQuasar();
 const { t } = useI18n();
 
@@ -12,29 +13,51 @@ defineExpose({ checkToBook });
 const { store } = useArrayData();
 
 async function checkToBook(id) {
-    let directBooking = true;
+    let messages = [];
+
+    const hasProblemWithTax = (
+        await axios.get('InvoiceInTaxes/count', {
+            params: {
+                where: JSON.stringify({
+                    invoiceInFk: id,
+                    or: [{ taxTypeSageFk: null }, { transactionTypeSageFk: null }],
+                }),
+            },
+        })
+    ).data?.count;
+
+    if (hasProblemWithTax)
+        messages.push(t('The VAT and Transaction fields have not been informed'));
 
     const { data: totals } = await axios.get(`InvoiceIns/${id}/getTotals`);
     const taxableBaseNotEqualDueDay = totals.totalDueDay != totals.totalTaxableBase;
     const vatNotEqualDueDay = totals.totalDueDay != totals.totalVat;
 
-    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay) directBooking = false;
+    if (taxableBaseNotEqualDueDay && vatNotEqualDueDay)
+        messages.push(t('The sum of the taxable bases does not match the due dates'));
 
-    const { data: dueDaysCount } = await axios.get('InvoiceInDueDays/count', {
-        where: {
-            invoiceInFk: id,
-            dueDated: { gte: Date.vnNew() },
-        },
-    });
+    const dueDaysCount = (
+        await axios.get('InvoiceInDueDays/count', {
+            params: {
+                where: JSON.stringify({
+                    invoiceInFk: id,
+                    dueDated: { gte: Date.vnNew() },
+                }),
+            },
+        })
+    ).data?.count;
 
-    if (dueDaysCount) directBooking = false;
+    if (dueDaysCount) messages.push(t('Some due dates are less than or equal to today'));
 
-    if (directBooking) return toBook(id);
-
-    dialog({
-        component: VnConfirm,
-        componentProps: { title: t('Are you sure you want to book this invoice?') },
-    }).onOk(async () => await toBook(id));
+    if (!messages.length) toBook(id);
+    else
+        dialog({
+            component: VnConfirm,
+            componentProps: {
+                title: t('Are you sure you want to book this invoice?'),
+                message: messages.reduce((acc, msg) => `${acc}<p>${msg}</p>`, ''),
+            },
+        }).onOk(() => toBook(id));
 }
 
 async function toBook(id) {
@@ -59,4 +82,7 @@ async function toBook(id) {
 es:
     Are you sure you want to book this invoice?: ¿Estás seguro de querer asentar esta factura?
     It was not able to book the invoice: No se pudo contabilizar la factura
+    Some due dates are less than or equal to today: Algún vencimiento tiene una fecha menor o igual que hoy
+    The sum of the taxable bases does not match the due dates: La suma de las bases imponibles no coincide con la de los vencimientos
+    The VAT and Transaction fields have not been informed: No se han informado los campos de iva y/o transacción
 </i18n>
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index 6b21b316b..548e6c201 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Search incoming invoices by ID or supplier fiscal name
     serial: Serial
     isBooked: Is booked
+    supplierRef: Invoice nº
     list:
         ref: Reference
         supplier: Supplier
-        supplierRef: Supplier ref.
         file: File
         issued: Issued
         dueDated: Due dated
@@ -19,8 +19,6 @@ invoiceIn:
         unbook: Unbook
         delete: Delete
         clone: Clone
-        toBook: To book
-        toUnbook: To unbook
         deleteInvoice: Delete invoice
         invoiceDeleted: invoice deleted
         cloneInvoice: Clone invoice
@@ -70,4 +68,3 @@ invoiceIn:
         isBooked: Is booked
         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 3f27c895c..142d95f92 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -3,10 +3,10 @@ invoiceIn:
     searchInfo: Buscar facturas recibidas por ID o nombre fiscal del proveedor
     serial: Serie
     isBooked: Contabilizada
+    supplierRef: Nº factura
     list:
         ref: Referencia
         supplier: Proveedor
-        supplierRef: Ref. proveedor
         issued: F. emisión
         dueDated: F. vencimiento
         file: Fichero
@@ -15,12 +15,10 @@ invoiceIn:
     descriptor:
         ticketList: Listado de tickets
     descriptorMenu:
-        book: Asentar
-        unbook: Desasentar
+        book: Contabilizar
+        unbook: Descontabilizar
         delete: Eliminar
         clone: Clonar
-        toBook: Contabilizar
-        toUnbook: Descontabilizar
         deleteInvoice: Eliminar factura
         invoiceDeleted: Factura eliminada
         cloneInvoice: Clonar factura
@@ -68,4 +66,3 @@ invoiceIn:
         isBooked: Contabilizada
         account: Cuenta contable
         correctingFk: Rectificativa
-
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
index 93e3fe042..a50c9d247 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutCard.vue
@@ -1,11 +1,13 @@
 <script setup>
 import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
 import VnCardBeta from 'components/common/VnCardBeta.vue';
+import filter from './InvoiceOutFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="InvoiceOut"
-        base-url="InvoiceOuts"
+        url="InvoiceOuts"
+        :filter="filter"
         :descriptor="InvoiceOutDescriptor"
     />
 </template>
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
index 209f1531e..dfaf6c109 100644
--- a/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
+++ b/src/pages/InvoiceOut/Card/InvoiceOutDescriptor.vue
@@ -8,8 +8,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import VnLv from 'src/components/ui/VnLv.vue';
 import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import { toCurrency, toDate } from 'src/filters';
+import filter from './InvoiceOutFilter.js';
 
 const $props = defineProps({
     id: {
@@ -26,42 +26,20 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const filter = {
-    include: [
-        {
-            relation: 'company',
-            scope: {
-                fields: ['id', 'code'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'name', 'email'],
-            },
-        },
-    ],
-};
-
 const descriptor = ref();
 
 function ticketFilter(invoice) {
     return JSON.stringify({ refFk: invoice.ref });
 }
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.id));
 </script>
 
 <template>
     <CardDescriptor
         ref="descriptor"
-        module="InvoiceOut"
         :url="`InvoiceOuts/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
-        data-key="invoiceOutData"
+        title="ref"
+        data-key="InvoiceOut"
         width="lg-width"
     >
         <template #menu="{ entity, menuRef }">
diff --git a/src/pages/InvoiceOut/Card/InvoiceOutFilter.js b/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
new file mode 100644
index 000000000..48b20faf6
--- /dev/null
+++ b/src/pages/InvoiceOut/Card/InvoiceOutFilter.js
@@ -0,0 +1,16 @@
+export default {
+    include: [
+        {
+            relation: 'company',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'name', 'email'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Item/Card/ItemBarcode.vue b/src/pages/Item/Card/ItemBarcode.vue
index 6db5943c7..590b524cd 100644
--- a/src/pages/Item/Card/ItemBarcode.vue
+++ b/src/pages/Item/Card/ItemBarcode.vue
@@ -92,7 +92,7 @@ const submit = async (rows) => {
                             class="cursor-pointer fill-icon-on-hover"
                             color="primary"
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                         >
                             <QTooltip>
diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index 4c96401f3..df7e71684 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -11,6 +11,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
 import FilterItemForm from 'src/components/FilterItemForm.vue';
 import CreateIntrastatForm from './CreateIntrastatForm.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -54,9 +55,8 @@ const onIntrastatCreated = (response, formData) => {
         auto-load
     />
     <FormModel
-        :url="`Items/${route.params.id}`"
         :url-update="`Items/${route.params.id}`"
-        model="item"
+        model="Item"
         auto-load
         :clear-store-on-unmount="false"
     >
@@ -209,30 +209,20 @@ const onIntrastatCreated = (response, formData) => {
                 />
             </VnRow>
             <VnRow class="row q-gutter-md q-mb-md">
-                <div>
-                    <QCheckbox
-                        v-model="data.isFragile"
-                        :label="t('item.basicData.isFragile')"
-                        class="q-mr-sm"
-                    />
-                    <QIcon name="info" class="cursor-pointer" size="xs">
-                        <QTooltip max-width="300px">
-                            {{ t('item.basicData.isFragileTooltip') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
-                <div>
-                    <QCheckbox
-                        v-model="data.isPhotoRequested"
-                        :label="t('item.basicData.isPhotoRequested')"
-                        class="q-mr-sm"
-                    />
-                    <QIcon name="info" class="cursor-pointer" size="xs">
-                        <QTooltip>
-                            {{ t('item.basicData.isPhotoRequestedTooltip') }}
-                        </QTooltip>
-                    </QIcon>
-                </div>
+                <VnCheckbox
+                    v-model="data.isFragile"
+                    :label="t('item.basicData.isFragile')"
+                    :info="t('item.basicData.isFragileTooltip')"
+                    class="q-mr-sm"
+                    size="xs"
+                />
+                <VnCheckbox
+                    v-model="data.isPhotoRequested"
+                    :label="t('item.basicData.isPhotoRequested')"
+                    :info="t('item.basicData.isPhotoRequestedTooltip')"
+                    class="q-mr-sm"
+                    size="xs"
+                />
             </VnRow>
             <VnRow>
                 <VnInput
diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index 4894d94fc..a40d81589 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -7,8 +7,8 @@ import FetchData from 'components/FetchData.vue';
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
-import CreateGenusForm from './CreateGenusForm.vue';
-import CreateSpecieForm from './CreateSpecieForm.vue';
+import CreateGenusForm from '../components/CreateGenusForm.vue';
+import CreateSpecieForm from '../components/CreateSpecieForm.vue';
 
 const route = useRoute();
 const { t } = useI18n();
diff --git a/src/pages/Item/Card/ItemCard.vue b/src/pages/Item/Card/ItemCard.vue
index 2546982eb..610b77a02 100644
--- a/src/pages/Item/Card/ItemCard.vue
+++ b/src/pages/Item/Card/ItemCard.vue
@@ -5,7 +5,7 @@ import ItemDescriptor from './ItemDescriptor.vue';
 <template>
     <VnCardBeta
         data-key="Item"
-        base-url="Items"
+        :url="`Items/${$route.params.id}/getCard`"
         :descriptor="ItemDescriptor"
     />
 </template>
diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index c6fee8540..a4c58ef4b 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -7,7 +7,6 @@ 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 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';
@@ -35,6 +34,10 @@ const $props = defineProps({
         type: Number,
         default: null,
     },
+    proxyRender: {
+        type: Boolean,
+        default: false,
+    },
 });
 
 const route = useRoute();
@@ -55,10 +58,8 @@ onMounted(async () => {
     mounted.value = true;
 });
 
-const data = ref(useCardDescription());
 const setData = async (entity) => {
     if (!entity) return;
-    data.value = useCardDescription(entity.name, entity.id);
     await updateStock();
 };
 
@@ -90,10 +91,7 @@ const updateStock = async () => {
 
 <template>
     <CardDescriptor
-        data-key="ItemData"
-        module="Item"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        data-key="Item"
         :summary="$props.summary"
         :url="`Items/${entityId}/getCard`"
         @on-fetch="setData"
@@ -117,7 +115,7 @@ const updateStock = async () => {
                 <template #value>
                     <span class="link">
                         {{ entity.itemType?.worker?.user?.name }}
-                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id" />
+                        <WorkerDescriptorProxy :id="entity.itemType?.worker?.id ?? NaN" />
                     </span>
                 </template>
             </VnLv>
@@ -152,7 +150,7 @@ const updateStock = async () => {
             </QCardActions>
         </template>
         <template #actions="{}">
-            <QCardActions class="row justify-center">
+            <QCardActions class="row justify-center" v-if="proxyRender">
                 <QBtn
                     :to="{
                         name: 'ItemDiary',
@@ -165,6 +163,16 @@ const updateStock = async () => {
                 >
                     <QTooltip>{{ t('item.descriptor.itemDiary') }}</QTooltip>
                 </QBtn>
+                <QBtn
+                    :to="{
+                        name: 'ItemLastEntries',
+                    }"
+                    size="md"
+                    icon="vn:regentry"
+                    color="primary"
+                >
+                    <QTooltip>{{ t('item.descriptor.itemLastEntries') }}</QTooltip>
+                </QBtn>
             </QCardActions>
         </template>
     </CardDescriptor>
diff --git a/src/pages/Item/Card/ItemDescriptorProxy.vue b/src/pages/Item/Card/ItemDescriptorProxy.vue
index 2ffc9080f..f686e8221 100644
--- a/src/pages/Item/Card/ItemDescriptorProxy.vue
+++ b/src/pages/Item/Card/ItemDescriptorProxy.vue
@@ -4,7 +4,7 @@ import ItemSummary from './ItemSummary.vue';
 
 const $props = defineProps({
     id: {
-        type: Number,
+        type: [Number, String],
         required: true,
     },
     dated: {
@@ -21,9 +21,8 @@ const $props = defineProps({
     },
 });
 </script>
-
 <template>
-    <QPopupProxy>
+    <QPopupProxy style="max-width: 10px">
         <ItemDescriptor
             v-if="$props.id"
             :id="$props.id"
@@ -31,6 +30,7 @@ const $props = defineProps({
             :dated="dated"
             :sale-fk="saleFk"
             :warehouse-fk="warehouseFk"
+            :proxy-render="true"
         />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Item/Card/ItemShelving.vue b/src/pages/Item/Card/ItemShelving.vue
index 7ad60c9e0..b29e2a2a5 100644
--- a/src/pages/Item/Card/ItemShelving.vue
+++ b/src/pages/Item/Card/ItemShelving.vue
@@ -110,10 +110,16 @@ const columns = computed(() => [
         attrs: { inWhere: true },
         align: 'left',
     },
+    {
+        label: t('globals.visible'),
+        name: 'stock',
+        attrs: { inWhere: true },
+        align: 'left',
+    },
 ]);
 
 const totalLabels = computed(() =>
-    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2)
+    rows.value.reduce((acc, row) => acc + row.stock / row.packing, 0).toFixed(2),
 );
 
 const removeLines = async () => {
@@ -157,7 +163,7 @@ watchEffect(selectedRows);
                     openConfirmationModal(
                         t('shelvings.removeConfirmTitle'),
                         t('shelvings.removeConfirmSubtitle'),
-                        removeLines
+                        removeLines,
                     )
                 "
             >
diff --git a/src/pages/Item/Card/ItemTags.vue b/src/pages/Item/Card/ItemTags.vue
index 5a7d7f818..ab26b9cae 100644
--- a/src/pages/Item/Card/ItemTags.vue
+++ b/src/pages/Item/Card/ItemTags.vue
@@ -178,7 +178,7 @@ const insertTag = (rows) => {
                             @click="insertTag(rows)"
                             color="primary"
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             fab
                             data-cy="createNewTag"
                         >
diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 1c4382fbd..fdfa1d3d1 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -65,10 +65,19 @@ const columns = computed(() => [
         name: 'name',
         ...defaultColumnAttrs,
         create: true,
+        columnFilter: {
+            component: 'select',
+            attrs: {
+                url: 'Items',
+                fields: ['id', 'name', 'subName'],
+                optionLabel: 'name',
+                optionValue: 'name',
+                uppercase: false,
+            },
+        },
     },
     {
         label: t('item.fixedPrice.groupingPrice'),
-        field: 'rate2',
         name: 'rate2',
         ...defaultColumnAttrs,
         component: 'input',
@@ -76,7 +85,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.packingPrice'),
-        field: 'rate3',
         name: 'rate3',
         ...defaultColumnAttrs,
         component: 'input',
@@ -85,7 +93,6 @@ const columns = computed(() => [
 
     {
         label: t('item.fixedPrice.minPrice'),
-        field: 'minPrice',
         name: 'minPrice',
         ...defaultColumnAttrs,
         component: 'input',
@@ -108,7 +115,6 @@ const columns = computed(() => [
     },
     {
         label: t('item.fixedPrice.ended'),
-        field: 'ended',
         name: 'ended',
         ...defaultColumnAttrs,
         columnField: {
@@ -124,7 +130,6 @@ const columns = computed(() => [
 
     {
         label: t('globals.warehouse'),
-        field: 'warehouseFk',
         name: 'warehouseFk',
         ...defaultColumnAttrs,
         columnClass: 'shrink',
@@ -415,7 +420,6 @@ function handleOnDataSave({ CrudModelRef }) {
             'row-key': 'id',
             selection: 'multiple',
         }"
-        :use-model="true"
         v-model:selected="rowsSelected"
         :create-as-dialog="false"
         :create="{
diff --git a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
index b4032ff8a..475dffd8b 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeBasicData.vue
@@ -40,12 +40,7 @@ const itemPackingTypesOptions = ref([]);
         }"
         auto-load
     />
-    <FormModel
-        :url="`ItemTypes/${route.params.id}`"
-        :url-update="`ItemTypes/${route.params.id}`"
-        model="itemTypeBasicData"
-        auto-load
-    >
+    <FormModel :url-update="`ItemTypes/${route.params.id}`" model="ItemType" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.code" :label="t('itemType.shared.code')" />
diff --git a/src/pages/Item/ItemType/Card/ItemTypeCard.vue b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
index fa51e428e..84e810de5 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeCard.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ItemTypeDescriptor from 'src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue';
+import filter from './ItemTypeFilter.js';
 </script>
 
 <template>
     <VnCardBeta
-        data-key="ItemTypeSummary"
-        base-url="ItemTypes"
+        data-key="ItemType"
+        url="ItemTypes"
+        :filter="filter"
         :descriptor="ItemTypeDescriptor"
     />
 </template>
diff --git a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
index 09d3dbce5..725fb30aa 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeDescriptor.vue
@@ -1,12 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-import useCardDescription from 'src/composables/useCardDescription';
+import filter from './ItemTypeFilter.js';
 
 const $props = defineProps({
     id: {
@@ -20,46 +19,31 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const itemTypeFilter = {
-    include: [
-        { relation: 'worker' },
-        { relation: 'category' },
-        { relation: 'itemPackingType' },
-        { relation: 'temperature' },
-    ],
-};
-
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
-
 <template>
     <CardDescriptor
-        module="ItemType"
         :url="`ItemTypes/${entityId}`"
-        :filter="itemTypeFilter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="itemTypeDescriptor"
-        @on-fetch="setData"
+        :filter="filter"
+        title="code"
+        data-key="ItemType"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('itemType.shared.code')" :value="entity.code" />
-            <VnLv :label="t('itemType.shared.name')" :value="entity.name" />
-            <VnLv :label="t('itemType.shared.worker')">
+            <VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
+            <VnLv :label="$t('itemType.shared.name')" :value="entity.name" />
+            <VnLv :label="$t('itemType.shared.worker')">
                 <template #value>
                     <span class="link">{{ entity.worker?.firstName }}</span>
                     <WorkerDescriptorProxy :id="entity.worker?.id" />
                 </template>
             </VnLv>
-            <VnLv :label="t('itemType.shared.category')" :value="entity.category?.name" />
+            <VnLv
+                :label="$t('itemType.shared.category')"
+                :value="entity.category?.name"
+            />
         </template>
     </CardDescriptor>
 </template>
-
diff --git a/src/pages/Item/ItemType/Card/ItemTypeFilter.js b/src/pages/Item/ItemType/Card/ItemTypeFilter.js
new file mode 100644
index 000000000..5651d368d
--- /dev/null
+++ b/src/pages/Item/ItemType/Card/ItemTypeFilter.js
@@ -0,0 +1,8 @@
+export default {
+    include: [
+        { relation: 'worker' },
+        { relation: 'category' },
+        { relation: 'itemPackingType' },
+        { relation: 'temperature' },
+    ],
+};
diff --git a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
index 9ba774ca4..3b63c4b63 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
@@ -3,7 +3,7 @@ import { ref, computed, onUpdated } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
-
+import filter from './ItemTypeFilter.js';
 import CardSummary from 'components/ui/CardSummary.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
@@ -21,15 +21,6 @@ const $props = defineProps({
     },
 });
 
-const itemTypeFilter = {
-    include: [
-        { relation: 'worker' },
-        { relation: 'category' },
-        { relation: 'itemPackingType' },
-        { relation: 'temperature' },
-    ],
-};
-
 const entityId = computed(() => $props.id || route.params.id);
 const summaryRef = ref();
 const itemType = ref();
@@ -43,8 +34,8 @@ async function setItemTypeData(data) {
     <CardSummary
         ref="summaryRef"
         :url="`ItemTypes/${entityId}`"
-        data-key="ItemTypeSummary"
-        :filter="itemTypeFilter"
+        data-key="ItemType"
+        :filter="filter"
         @on-fetch="(data) => setItemTypeData(data)"
         class="full-width"
     >
diff --git a/src/pages/Item/Card/CreateGenusForm.vue b/src/pages/Item/components/CreateGenusForm.vue
similarity index 100%
rename from src/pages/Item/Card/CreateGenusForm.vue
rename to src/pages/Item/components/CreateGenusForm.vue
diff --git a/src/pages/Item/Card/CreateSpecieForm.vue b/src/pages/Item/components/CreateSpecieForm.vue
similarity index 100%
rename from src/pages/Item/Card/CreateSpecieForm.vue
rename to src/pages/Item/components/CreateSpecieForm.vue
diff --git a/src/pages/Item/components/ItemProposal.vue b/src/pages/Item/components/ItemProposal.vue
new file mode 100644
index 000000000..d2dbea7b3
--- /dev/null
+++ b/src/pages/Item/components/ItemProposal.vue
@@ -0,0 +1,332 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import { toCurrency } from 'filters/index';
+import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+import axios from 'axios';
+import notifyResults from 'src/utils/notifyResults';
+import FetchData from 'components/FetchData.vue';
+
+const MATCH = 'match';
+
+const { t } = useI18n();
+const $props = defineProps({
+    itemLack: {
+        type: Object,
+        required: true,
+        default: () => {},
+    },
+    replaceAction: {
+        type: Boolean,
+        required: false,
+        default: false,
+    },
+    sales: {
+        type: Array,
+        required: false,
+        default: () => [],
+    },
+});
+const proposalSelected = ref([]);
+const ticketConfig = ref({});
+const proposalTableRef = ref(null);
+
+const sale = computed(() => $props.sales[0]);
+const saleFk = computed(() => sale.value.saleFk);
+const filter = computed(() => ({
+    itemFk: $props.itemLack.itemFk,
+    sales: saleFk.value,
+}));
+
+const defaultColumnAttrs = {
+    align: 'center',
+    sortable: false,
+};
+const emit = defineEmits(['onDialogClosed', 'itemReplaced']);
+
+const conditionalValuePrice = (price) =>
+    price > 1 + ticketConfig.value.lackAlertPrice / 100 ? 'match' : 'not-match';
+
+const columns = computed(() => [
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.available'),
+        name: 'available',
+        field: 'available',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+        columnClass: 'shrink',
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.counter'),
+        name: 'counter',
+        field: 'counter',
+        columnClass: 'shrink',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+
+    {
+        align: 'left',
+        sortable: true,
+        label: t('proposal.longName'),
+        name: 'longName',
+        field: 'longName',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.color'),
+        name: 'tag5',
+        field: 'value5',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.stems'),
+        name: 'tag6',
+        field: 'value6',
+        columnClass: 'expand',
+    },
+    {
+        align: 'left',
+        sortable: true,
+        label: t('item.list.producer'),
+        name: 'tag7',
+        field: 'value7',
+        columnClass: 'expand',
+    },
+
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.price2'),
+        name: 'price2',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.minQuantity'),
+        name: 'minQuantity',
+        field: 'minQuantity',
+        style: 'max-width: 75px',
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        ...defaultColumnAttrs,
+        label: t('proposal.located'),
+        name: 'located',
+        field: 'located',
+    },
+    {
+        align: 'right',
+        label: '',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('Replace'),
+                icon: 'change_circle',
+                show: (row) => isSelectionAvailable(row),
+                action: change,
+                isPrimary: true,
+            },
+        ],
+    },
+]);
+
+function extractMatchValues(obj) {
+    return Object.keys(obj)
+        .filter((key) => key.startsWith(MATCH))
+        .map((key) => parseInt(key.replace(MATCH, ''), 10));
+}
+const gradientStyle = (value) => {
+    let color = 'white';
+    const perc = parseFloat(value);
+    switch (true) {
+        case perc >= 0 && perc < 33:
+            color = 'primary';
+            break;
+        case perc >= 33 && perc < 66:
+            color = 'warning';
+            break;
+
+        default:
+            color = 'secondary';
+            break;
+    }
+    return color;
+};
+const statusConditionalValue = (row) => {
+    const matches = extractMatchValues(row);
+    const value = matches.reduce((acc, i) => acc + row[`${MATCH}${i}`], 0);
+    return 100 * (value / matches.length);
+};
+
+const isSelectionAvailable = (itemProposal) => {
+    const { price2 } = itemProposal;
+    const salePrice = sale.value.price;
+    const byPrice = (100 * price2) / salePrice > ticketConfig.value.lackAlertPrice;
+    if (byPrice) {
+        return byPrice;
+    }
+    const byQuantity =
+        (100 * itemProposal.available) / Math.abs($props.itemLack.lack) <
+        ticketConfig.value.lackAlertPrice;
+    return byQuantity;
+};
+
+async function change({ itemFk: substitutionFk }) {
+    try {
+        const promises = $props.sales.map(({ saleFk, quantity }) => {
+            const params = {
+                saleFk,
+                substitutionFk,
+                quantity,
+            };
+            return axios.post('Sales/replaceItem', params);
+        });
+        const results = await Promise.allSettled(promises);
+
+        notifyResults(results, 'saleFk');
+        emit('itemReplaced', {
+            type: 'refresh',
+            quantity: quantity.value,
+            itemProposal: proposalSelected.value[0],
+        });
+        proposalSelected.value = [];
+    } catch (error) {
+        console.error(error);
+    }
+}
+
+async function handleTicketConfig(data) {
+    ticketConfig.value = data[0];
+}
+</script>
+<template>
+    <FetchData
+        url="TicketConfigs"
+        :filter="{ fields: ['lackAlertPrice'] }"
+        @on-fetch="handleTicketConfig"
+        auto-load
+    />
+
+    <VnTable
+        v-if="ticketConfig"
+        auto-load
+        data-cy="proposalTable"
+        ref="proposalTableRef"
+        data-key="ItemsGetSimilar"
+        url="Items/getSimilar"
+        :user-filter="filter"
+        :columns="columns"
+        class="full-width q-mt-md"
+        row-key="id"
+        :row-click="change"
+        :is-editable="false"
+        :right-search="false"
+        :without-header="true"
+        :disable-option="{ card: true, table: true }"
+    >
+        <template #column-longName="{ row }">
+            <QTd
+                class="flex"
+                style="max-width: 100%; flex-shrink: 50px; flex-wrap: nowrap"
+            >
+                <div
+                    class="middle full-width"
+                    :class="[`proposal-${gradientStyle(statusConditionalValue(row))}`]"
+                >
+                    <QTooltip> {{ statusConditionalValue(row) }}% </QTooltip>
+                </div>
+                <div style="flex: 2 0 100%; align-content: center">
+                    <div>
+                        <span class="link">{{ row.longName }}</span>
+                        <ItemDescriptorProxy :id="row.id" />
+                    </div>
+                </div>
+            </QTd>
+        </template>
+        <template #column-tag5="{ row }">
+            <span :class="{ match: !row.match5 }">{{ row.value5 }}</span>
+        </template>
+        <template #column-tag6="{ row }">
+            <span :class="{ match: !row.match6 }">{{ row.value6 }}</span>
+        </template>
+        <template #column-tag7="{ row }">
+            <span :class="{ match: !row.match7 }">{{ row.value7 }}</span>
+        </template>
+        <template #column-counter="{ row }">
+            <span
+                :class="{
+                    match: row.counter === 1,
+                    'not-match': row.counter !== 1,
+                }"
+                >{{ row.counter }}</span
+            >
+        </template>
+        <template #column-minQuantity="{ row }">
+            {{ row.minQuantity }}
+        </template>
+        <template #column-price2="{ row }">
+            <div class="flex column items-center content-center">
+                <VnStockValueDisplay :value="(sales[0].price - row.price2) / 100" />
+                <span :class="[conditionalValuePrice(row.price2)]">{{
+                    toCurrency(row.price2)
+                }}</span>
+            </div>
+        </template>
+    </VnTable>
+</template>
+<style lang="scss" scoped>
+@import 'src/css/quasar.variables.scss';
+.middle {
+    float: left;
+    margin-right: 2px;
+    flex: 2 0 5px;
+}
+.match {
+    color: $negative;
+}
+.not-match {
+    color: inherit;
+}
+.proposal-warning {
+    background-color: $warning;
+}
+.proposal-secondary {
+    background-color: $secondary;
+}
+.proposal-primary {
+    background-color: $primary;
+}
+.text {
+    margin: 0.05rem;
+    padding: 1px;
+    border: 1px solid var(--vn-label-color);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: smaller;
+}
+</style>
diff --git a/src/pages/Item/components/ItemProposalProxy.vue b/src/pages/Item/components/ItemProposalProxy.vue
new file mode 100644
index 000000000..7da0ce398
--- /dev/null
+++ b/src/pages/Item/components/ItemProposalProxy.vue
@@ -0,0 +1,56 @@
+<script setup>
+import ItemProposal from './ItemProposal.vue';
+import { useDialogPluginComponent } from 'quasar';
+
+const $props = defineProps({
+    itemLack: {
+        type: Object,
+        required: true,
+        default: () => {},
+    },
+    replaceAction: {
+        type: Boolean,
+        required: false,
+        default: false,
+    },
+    sales: {
+        type: Array,
+        required: false,
+        default: () => [],
+    },
+});
+const { dialogRef } = useDialogPluginComponent();
+const emit = defineEmits([
+    'onDialogClosed',
+    'itemReplaced',
+    ...useDialogPluginComponent.emits,
+]);
+defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
+</script>
+<template>
+    <QDialog ref="dialogRef" transition-show="scale" transition-hide="scale">
+        <QCard class="dialog-width">
+            <QCardSection class="row items-center q-pb-none">
+                <span class="text-h6 text-grey">{{ $t('Item proposal') }}</span>
+                <QSpace />
+                <QBtn icon="close" flat round dense v-close-popup />
+            </QCardSection>
+            <QCardSection>
+                <ItemProposal
+                    v-bind="$props"
+                    @item-replaced="
+                        (data) => {
+                            emit('itemReplaced', data);
+                            dialogRef.hide();
+                        }
+                    "
+                ></ItemProposal
+            ></QCardSection>
+        </QCard>
+    </QDialog>
+</template>
+<style lang="scss" scoped>
+.dialog-width {
+    max-width: $width-lg;
+}
+</style>
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index bc73abb12..9d27fc96e 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -112,6 +112,7 @@ item:
         available: Available
         warehouseText: 'Calculated on the warehouse of { warehouseName }'
         itemDiary: Item diary
+        itemLastEntries: Last entries
         producer: Producer
         clone:
             title: All its properties will be copied
@@ -130,6 +131,7 @@ item:
         origin: Orig.
         userName: Buyer
         weight: Weight
+        color: Color
         weightByPiece: Weight/stem
         stemMultiplier: Multiplier
         producer: Producer
@@ -215,4 +217,24 @@ item:
         specie: Specie
     search: 'Search item'
     searchInfo: 'You can search by id'
-    regularizeStock: Regularize stock
\ No newline at end of file
+    regularizeStock: Regularize stock
+itemProposal: Items proposal
+proposal:
+    difference: Difference
+    title: Items proposal
+    itemFk: Item
+    longName: Name
+    subName: Producer
+    value5: value5
+    value6: value6
+    value7: value7
+    value8: value8
+    available: Available
+    minQuantity: minQuantity
+    price2: Price
+    located: Located
+    counter: Counter
+    groupingPrice: Grouping Price
+    itemOldPrice: itemOld Price
+    status: State
+    quantityToReplace: Quanity to replace
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index dd5074f5f..935f5160b 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -118,6 +118,7 @@ item:
         available: Disponible
         warehouseText: 'Calculado sobre el almacén de { warehouseName }'
         itemDiary: Registro de compra-venta
+        itemLastEntries: Últimas entradas
         producer: Productor
         clone:
             title: Todas sus propiedades serán copiadas
@@ -135,6 +136,7 @@ item:
         size: Medida
         origin: Orig.
         weight: Peso
+        color: Color
         weightByPiece: Peso/tallo
         userName: Comprador
         stemMultiplier: Multiplicador
@@ -220,5 +222,30 @@ item:
         achieved: 'Conseguido'
         concept: 'Concepto'
         state: 'Estado'
-    search: 'Buscar artículo'
-    searchInfo: 'Puedes buscar por id'
+itemProposal: Artículos similares
+proposal:
+    substitutionAvailable: Sustitución disponible
+    notSubstitutionAvailableByPrice: Sustitución no disponible, 30% de diferencia por precio o cantidad
+    compatibility: Compatibilidad
+    title: Items de sustitución para los tickets seleccionados
+    itemFk: Item
+    longName: Nombre
+    subName: Productor
+    value5: value5
+    value6: value6
+    value7: value7
+    value8: value8
+    available: Disponible
+    minQuantity: Min. cantidad
+    price2: Precio
+    located: Ubicado
+    counter: Contador
+    difference: Diferencial
+    groupingPrice: Precio Grouping
+    itemOldPrice: Precio itemOld
+    status: Estado
+    quantityToReplace: Cantidad a reemplazar
+    replace: Sustituir
+    replaceAndConfirm: Sustituir y confirmar precio
+search: 'Buscar artículo'
+searchInfo: 'Puedes buscar por id'
diff --git a/src/pages/Monitor/MonitorOrders.vue b/src/pages/Monitor/MonitorOrders.vue
index 4efab56fb..873f8abb4 100644
--- a/src/pages/Monitor/MonitorOrders.vue
+++ b/src/pages/Monitor/MonitorOrders.vue
@@ -157,7 +157,7 @@ const openTab = (id) =>
                         openConfirmationModal(
                             $t('globals.deleteConfirmTitle'),
                             $t('salesOrdersTable.deleteConfirmMessage'),
-                            removeOrders
+                            removeOrders,
                         )
                     "
                 >
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index 21324087c..496c8761a 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -38,6 +38,7 @@ salesTicketsTable:
     payMethod: Pay method
     department: Department
     packing: ITP
+    hasItemLost: Item lost
 searchBar:
     label: Search tickets
     info: Search tickets by id or alias
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index 30afb1904..f6a29879f 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -39,6 +39,7 @@ salesTicketsTable:
     payMethod: Método de pago
     department: Departamento
     packing: ITP
+    hasItemLost: Artículo perdido
 searchBar:
     label: Buscar tickets
     info: Buscar tickets por identificador o alias
diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index b91e7d229..d1bd48c9e 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -110,7 +110,7 @@ const getSelectedTagValues = async (tag) => {
             </div>
             <QBtn
                 icon="add_circle"
-                shortcut="+"
+                v-shortcut="'+'"
                 flat
                 class="filter-icon q-mb-md"
                 size="md"
diff --git a/src/pages/Order/Card/OrderBasicData.vue b/src/pages/Order/Card/OrderBasicData.vue
index 8594a05f4..9c02d7494 100644
--- a/src/pages/Order/Card/OrderBasicData.vue
+++ b/src/pages/Order/Card/OrderBasicData.vue
@@ -14,7 +14,6 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 const { t } = useI18n();
 const route = useRoute();
 const state = useState();
-const ORDER_MODEL = 'order';
 
 const isNew = Boolean(!route.params.id);
 const clientList = ref([]);
@@ -32,7 +31,7 @@ const fetchAddressList = async (addressId) => {
     });
     addressList.value = data;
     if (addressList.value?.length === 1) {
-        state.get(ORDER_MODEL).addressFk = addressList.value[0].id;
+        state.get('Order').addressFk = addressList.value[0].id;
     }
 };
 
@@ -91,9 +90,8 @@ const onClientChange = async (clientId) => {
     <VnSubToolbar v-if="isNew" />
     <div class="q-pa-md">
         <FormModel
-            :url="`Orders/${route.params.id}`"
             :url-update="`Orders/${route.params.id}/updateBasicData`"
-            :model="ORDER_MODEL"
+            model="Order"
             :filter="orderFilter"
             @on-fetch="fetchOrderDetails"
             auto-load
diff --git a/src/pages/Order/Card/OrderCard.vue b/src/pages/Order/Card/OrderCard.vue
index 823815f59..ad5c73a87 100644
--- a/src/pages/Order/Card/OrderCard.vue
+++ b/src/pages/Order/Card/OrderCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
+import filter from './OrderFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Order"
-        base-url="Orders"
+        url="Orders"
+        :filter="filter"
         :descriptor="OrderDescriptor"
     />
 </template>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 262f503fd..76e608983 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -184,7 +184,7 @@ function addOrder(value, field, params) {
                         {{
                             t(
                                 categoryList.find((c) => c.id == customTag.value)?.name ||
-                                    ''
+                                    '',
                             )
                         }}
                     </strong>
@@ -296,7 +296,7 @@ function addOrder(value, field, params) {
                     <template #append>
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             color="primary"
                             size="md"
diff --git a/src/pages/Order/Card/OrderCatalogItemDialog.vue b/src/pages/Order/Card/OrderCatalogItemDialog.vue
index 77f6a8405..766945e4d 100644
--- a/src/pages/Order/Card/OrderCatalogItemDialog.vue
+++ b/src/pages/Order/Card/OrderCatalogItemDialog.vue
@@ -20,7 +20,7 @@ const props = defineProps({
 });
 const state = useState();
 
-const orderData = computed(() => state.get('orderData'));
+const orderData = computed(() => state.get('Order'));
 
 const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
 const isLoading = ref(false);
@@ -39,11 +39,11 @@ const addToOrder = async () => {
     });
 
     const { data: orderTotal } = await axios.get(
-        `Orders/${Number(route.params.id)}/getTotal`
+        `Orders/${Number(route.params.id)}/getTotal`,
     );
 
     state.set('orderTotal', orderTotal);
-    state.set('orderData', {
+    state.set('Order', {
         ...orderData.value,
         items,
     });
@@ -56,7 +56,7 @@ const canAddToOrder = () => {
     if (canAddToOrder) {
         const excedQuantity = prices.value.reduce(
             (acc, { quantity }) => acc + quantity,
-            0
+            0,
         );
         if (excedQuantity > props.item.available) {
             canAddToOrder = false;
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index 0d5f0146f..0d18864dc 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -4,8 +4,7 @@ import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { toCurrency, toDate } from 'src/filters';
 import { useState } from 'src/composables/useState';
-import useCardDescription from 'src/composables/useCardDescription';
-
+import filter from './OrderFilter.js';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import FetchData from 'components/FetchData.vue';
@@ -24,44 +23,15 @@ const $props = defineProps({
 const route = useRoute();
 const state = useState();
 const { t } = useI18n();
-const data = ref(useCardDescription());
 const getTotalRef = ref();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const filter = {
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['name'] } },
-        {
-            relation: 'address',
-            scope: { fields: ['nickname'] },
-        },
-        { relation: 'rows', scope: { fields: ['id'] } },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'salesPersonFk',
-                    'name',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                ],
-                include: {
-                    relation: 'salesPersonUser',
-                    scope: { fields: ['id', 'name'] },
-                },
-            },
-        },
-    ],
-};
-
 const setData = (entity) => {
     if (!entity) return;
     getTotalRef.value && getTotalRef.value.fetch();
-    data.value = useCardDescription(entity?.client?.name, entity?.id);
     state.set('orderTotal', total);
 };
 
@@ -87,11 +57,9 @@ const total = ref(0);
         ref="descriptor"
         :url="`Orders/${entityId}`"
         :filter="filter"
-        module="Order"
-        :title="data.title"
-        :subtitle="data.subtitle"
+        title="client.name"
         @on-fetch="setData"
-        data-key="orderData"
+        data-key="Order"
     >
         <template #body="{ entity }">
             <VnLv
diff --git a/src/pages/Order/Card/OrderFilter.js b/src/pages/Order/Card/OrderFilter.js
new file mode 100644
index 000000000..3e521b92c
--- /dev/null
+++ b/src/pages/Order/Card/OrderFilter.js
@@ -0,0 +1,26 @@
+export default {
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['name'] } },
+        {
+            relation: 'address',
+            scope: { fields: ['nickname'] },
+        },
+        { relation: 'rows', scope: { fields: ['id'] } },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'salesPersonFk',
+                    'name',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                ],
+                include: {
+                    relation: 'salesPersonUser',
+                    scope: { fields: ['id', 'name'] },
+                },
+            },
+        },
+    ],
+};
diff --git a/src/pages/Order/Card/OrderLines.vue b/src/pages/Order/Card/OrderLines.vue
index cf219a244..1b864de6f 100644
--- a/src/pages/Order/Card/OrderLines.vue
+++ b/src/pages/Order/Card/OrderLines.vue
@@ -21,7 +21,7 @@ const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
 const quasar = useQuasar();
-const descriptorData = useArrayData('orderData');
+const descriptorData = useArrayData('Order');
 const componentKey = ref(0);
 const tableLinesRef = ref();
 const order = ref();
@@ -238,7 +238,7 @@ watch(
         lineFilter.value.where.orderFk = router.currentRoute.value.params.id;
 
         tableLinesRef.value.reload();
-    }
+    },
 );
 </script>
 
diff --git a/src/pages/Order/Card/OrderSummary.vue b/src/pages/Order/Card/OrderSummary.vue
index a289688e4..a4bdb2881 100644
--- a/src/pages/Order/Card/OrderSummary.vue
+++ b/src/pages/Order/Card/OrderSummary.vue
@@ -27,7 +27,7 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const summary = ref();
 const quasar = useQuasar();
-const descriptorData = useArrayData('orderData');
+const descriptorData = useArrayData('Order');
 const detailsColumns = ref([
     {
         name: 'item',
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 21cb5ed7e..40990f329 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -71,8 +71,9 @@ const columns = computed(() => [
         format: (row) => row?.name,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'isConfirmed',
+        component: 'checkbox',
         label: t('module.isConfirmed'),
     },
     {
@@ -95,7 +96,9 @@ const columns = computed(() => [
         columnField: {
             component: null,
         },
-        style: 'color="positive"',
+        style: () => {
+            return { color: 'positive' };
+        },
     },
     {
         align: 'left',
diff --git a/src/pages/Route/Agency/AgencyList.vue b/src/pages/Route/Agency/AgencyList.vue
index 4322b9bc8..5c2904bf3 100644
--- a/src/pages/Route/Agency/AgencyList.vue
+++ b/src/pages/Route/Agency/AgencyList.vue
@@ -51,7 +51,6 @@ const columns = computed(() => [
         name: 'isAnyVolumeAllowed',
         component: 'checkbox',
         cardVisible: true,
-        disable: true,
     },
     {
         align: 'right',
@@ -72,7 +71,7 @@ const columns = computed(() => [
         :data-key
         :columns="columns"
         prefix="agency"
-        :right-filter="false"
+        :right-filter="true"
         :array-data-props="{
             url: 'Agencies',
             order: 'name',
@@ -83,6 +82,7 @@ const columns = computed(() => [
             <VnTable
                 :data-key
                 :columns="columns"
+                is-editable="false"
                 :right-search="false"
                 :use-model="true"
                 redirect="route/agency"
diff --git a/src/pages/Route/Agency/Card/AgencyBasicData.vue b/src/pages/Route/Agency/Card/AgencyBasicData.vue
index 599058b3e..4270b136c 100644
--- a/src/pages/Route/Agency/Card/AgencyBasicData.vue
+++ b/src/pages/Route/Agency/Card/AgencyBasicData.vue
@@ -21,7 +21,7 @@ const warehouses = ref([]);
         @on-fetch="(data) => (warehouses = data)"
         auto-load
     />
-    <FormModel :url="`Agencies/${routeId}`" model="agency" auto-load>
+    <FormModel :update-url="`Agencies/${routeId}`" model="Agency" auto-load>
         <template #form="{ data }">
             <VnRow>
                 <VnInput v-model="data.name" :label="t('globals.name')" />
diff --git a/src/pages/Route/Agency/Card/AgencyCard.vue b/src/pages/Route/Agency/Card/AgencyCard.vue
index 35685790a..7dc31f8ba 100644
--- a/src/pages/Route/Agency/Card/AgencyCard.vue
+++ b/src/pages/Route/Agency/Card/AgencyCard.vue
@@ -3,5 +3,5 @@ import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Agency" base-url="Agencies" :descriptor="AgencyDescriptor" />
+    <VnCardBeta data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" />
 </template>
diff --git a/src/pages/Route/Agency/Card/AgencyDescriptor.vue b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
index b9772037c..a0472c6c3 100644
--- a/src/pages/Route/Agency/Card/AgencyDescriptor.vue
+++ b/src/pages/Route/Agency/Card/AgencyDescriptor.vue
@@ -22,7 +22,6 @@ const card = computed(() => store.data);
 </script>
 <template>
     <CardDescriptor
-        module="Agency"
         data-key="Agency"
         :url="`Agencies/${entityId}`"
         :title="card?.name"
diff --git a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
index 7cabf396d..9a9213868 100644
--- a/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
+++ b/src/pages/Route/Agency/Card/AgencyWorkcenter.vue
@@ -88,7 +88,7 @@ async function deleteWorCenter(id) {
         </VnPaginate>
     </div>
     <QPageSticky :offset="[18, 18]">
-        <QBtn @click.stop="dialog.show()" color="primary" fab shortcut="+" icon="add">
+        <QBtn @click.stop="dialog.show()" color="primary" fab v-shortcut="'+'" icon="add">
             <QDialog ref="dialog">
                 <FormModelPopup
                     :title="t('Add work center')"
diff --git a/src/pages/Route/Card/RouteCard.vue b/src/pages/Route/Card/RouteCard.vue
index 81b6cfa16..c178dc6bf 100644
--- a/src/pages/Route/Card/RouteCard.vue
+++ b/src/pages/Route/Card/RouteCard.vue
@@ -1,12 +1,13 @@
 <script setup>
 import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
+import filter from './RouteFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Route"
-        base-url="Routes"
-        custom-url="Routes/filter"
+        url="Routes"
+        :filter="filter"
         :descriptor="RouteDescriptor"
     />
 </template>
diff --git a/src/pages/Route/Card/RouteDescriptor.vue b/src/pages/Route/Card/RouteDescriptor.vue
index 68c08b821..503cd1941 100644
--- a/src/pages/Route/Card/RouteDescriptor.vue
+++ b/src/pages/Route/Card/RouteDescriptor.vue
@@ -1,13 +1,14 @@
 <script setup>
 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 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDate } from 'src/filters';
 import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
+import filter from './RouteFilter.js';
+import useCardDescription from 'src/composables/useCardDescription';
 import axios from 'axios';
+
 const $props = defineProps({
     id: {
         type: Number,
@@ -17,7 +18,6 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
 const zone = ref();
 const zoneId = ref();
 const entityId = computed(() => {
@@ -36,81 +36,31 @@ const getZone = async () => {
     const { data: zoneData } = await axios.get(`Zones/${zoneId.value}`);
     zone.value = zoneData.name;
 };
-
-const filter = {
-    fields: [
-        'id',
-        'workerFk',
-        'agencyModeFk',
-        'dated',
-        'm3',
-        'warehouseFk',
-        'description',
-        'vehicleFk',
-        'kmStart',
-        'kmEnd',
-        'started',
-        'finished',
-        'cost',
-        'isOk',
-    ],
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
-        {
-            relation: 'vehicle',
-            scope: { fields: ['id', 'm3'] },
-        },
-        {
-            relation: 'ticket',
-            scope: {
-                fields: ['id', 'name', 'zoneFk'],
-                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
-            },
-        },
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: {
-                        fields: ['id'],
-                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
-                    },
-                },
-            },
-        },
-    ],
-};
 const data = ref(useCardDescription());
 const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 onMounted(async () => {
     getZone();
 });
 </script>
-
 <template>
     <CardDescriptor
-        module="Route"
         :url="`Routes/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="routeData"
-        @on-fetch="setData"
+        :title="null"
+        data-key="Route"
         width="lg-width"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('Date')" :value="toDate(entity?.dated)" />
-            <VnLv :label="t('Agency')" :value="entity?.agencyMode?.name" />
-            <VnLv :label="t('Zone')" :value="zone" />
+            <VnLv :label="$t('Date')" :value="toDate(entity?.dated)" />
+            <VnLv :label="$t('Agency')" :value="entity?.agencyMode?.name" />
+            <VnLv :label="$t('Zone')" :value="zone" />
             <VnLv
-                :label="t('Volume')"
+                :label="$t('Volume')"
                 :value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty(
                     entity?.vehicle?.m3,
                 )} m³`"
             />
-            <VnLv :label="t('Description')" :value="entity?.description" />
+            <VnLv :label="$t('Description')" :value="entity?.description" />
         </template>
         <template #menu="{ entity }">
             <RouteDescriptorMenu :route="entity" />
diff --git a/src/pages/Route/Card/RouteFilter.js b/src/pages/Route/Card/RouteFilter.js
new file mode 100644
index 000000000..90ee71bf7
--- /dev/null
+++ b/src/pages/Route/Card/RouteFilter.js
@@ -0,0 +1,39 @@
+export default {
+    fields: [
+        'code',
+        'id',
+        'workerFk',
+        'agencyModeFk',
+        'created',
+        'm3',
+        'warehouseFk',
+        'description',
+        'vehicleFk',
+        'kmStart',
+        'kmEnd',
+        'started',
+        'finished',
+        'cost',
+        'isOk',
+    ],
+    include: [
+        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
+        {
+            relation: 'vehicle',
+            scope: { fields: ['id', 'm3'] },
+        },
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: {
+                        fields: ['id'],
+                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
+                    },
+                },
+            },
+        },
+    ],
+};
diff --git a/src/pages/Route/Card/RouteFilter.vue b/src/pages/Route/Card/RouteFilter.vue
index 72bfed1da..21858102b 100644
--- a/src/pages/Route/Card/RouteFilter.vue
+++ b/src/pages/Route/Card/RouteFilter.vue
@@ -100,7 +100,7 @@ const emit = defineEmits(['search']);
                     <VnSelect
                         :label="t('Vehicle')"
                         v-model="params.vehicleFk"
-                        url="Vehicles"
+                        url="Vehicles/active"
                         sort-by="numberPlate ASC"
                         option-value="id"
                         option-label="numberPlate"
diff --git a/src/pages/Route/Card/RouteForm.vue b/src/pages/Route/Card/RouteForm.vue
index 633ff44bc..667204b15 100644
--- a/src/pages/Route/Card/RouteForm.vue
+++ b/src/pages/Route/Card/RouteForm.vue
@@ -11,6 +11,7 @@ import VnInputDate from 'components/common/VnInputDate.vue';
 import VnInput from 'components/common/VnInput.vue';
 import axios from 'axios';
 import VnInputTime from 'components/common/VnInputTime.vue';
+import filter from './RouteFilter.js';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
 
 const { t } = useI18n();
@@ -27,52 +28,6 @@ const defaultInitialData = {
     isOk: false,
 };
 const maxDistance = ref();
-
-const routeFilter = {
-    fields: [
-        'id',
-        'workerFk',
-        'agencyModeFk',
-        'dated',
-        'm3',
-        'warehouseFk',
-        'description',
-        'vehicleFk',
-        'kmStart',
-        'kmEnd',
-        'started',
-        'finished',
-        'cost',
-        'isOk',
-    ],
-    include: [
-        { relation: 'agencyMode', scope: { fields: ['id', 'name'] } },
-        {
-            relation: 'vehicle',
-            scope: { fields: ['id', 'm3'] },
-        },
-        {
-            relation: 'ticket',
-            scope: {
-                fields: ['id', 'name', 'zoneFk'],
-                include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
-            },
-        },
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: {
-                        fields: ['id'],
-                        include: { relation: 'emailUser', scope: { fields: ['email'] } },
-                    },
-                },
-            },
-        },
-    ],
-};
 const onSave = (data, response) => {
     if (isNew) {
         axios.post(`Routes/${response?.id}/updateWorkCenter`);
@@ -89,11 +44,10 @@ const onSave = (data, response) => {
         sort-by="id ASC"
     />
     <FormModel
-        :url="isNew ? null : `Routes/${route.params?.id}`"
         :url-create="isNew ? 'Routes' : null"
         :observe-form-changes="!isNew"
-        :filter="routeFilter"
-        model="route"
+        :filter="filter"
+        model="Route"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -104,7 +58,7 @@ const onSave = (data, response) => {
                 <VnSelect
                     :label="t('Vehicle')"
                     v-model="data.vehicleFk"
-                    url="Vehicles"
+                    url="Vehicles/active"
                     sort-by="numberPlate ASC"
                     option-value="id"
                     option-label="numberPlate"
diff --git a/src/pages/Route/Roadmap/RoadmapBasicData.vue b/src/pages/Route/Roadmap/RoadmapBasicData.vue
index 2fe805362..a9e6059c3 100644
--- a/src/pages/Route/Roadmap/RoadmapBasicData.vue
+++ b/src/pages/Route/Roadmap/RoadmapBasicData.vue
@@ -11,17 +11,16 @@ import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
 const { t } = useI18n();
 const router = useRouter();
 
-const filter = { include: [{ relation: 'supplier' }] };
 const onSave = (data, response) => {
     router.push({ name: 'RoadmapSummary', params: { id: response?.id } });
 };
 </script>
 <template>
     <FormModel
+        :update-url="`Roadmaps/${$route.params?.id}`"
         :url="`Roadmaps/${$route.params?.id}`"
         observe-form-changes
-        :filter="filter"
-        model="roadmap"
+        model="Roadmap"
         auto-load
         @on-data-saved="onSave"
     >
diff --git a/src/pages/Route/Roadmap/RoadmapCard.vue b/src/pages/Route/Roadmap/RoadmapCard.vue
index 0b81de673..48ba516a1 100644
--- a/src/pages/Route/Roadmap/RoadmapCard.vue
+++ b/src/pages/Route/Roadmap/RoadmapCard.vue
@@ -3,5 +3,5 @@ import VnCardBeta from 'components/common/VnCardBeta.vue';
 import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Roadmap" base-url="Roadmaps" :descriptor="RoadmapDescriptor" />
+    <VnCardBeta data-key="Roadmap" url="Roadmaps" :descriptor="RoadmapDescriptor" />
 </template>
diff --git a/src/pages/Route/Roadmap/RoadmapDescriptor.vue b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
index 788173688..baa864a15 100644
--- a/src/pages/Route/Roadmap/RoadmapDescriptor.vue
+++ b/src/pages/Route/Roadmap/RoadmapDescriptor.vue
@@ -1,13 +1,13 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import { dashIfEmpty, toDateHourMin } from 'src/filters';
 import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
 import RoadmapDescriptorMenu from 'pages/Route/Roadmap/RoadmapDescriptorMenu.vue';
+import filter from 'pages/Route/Roadmap/RoadmapFilter.js';
 
 const $props = defineProps({
     id: {
@@ -23,22 +23,10 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = { include: [{ relation: 'supplier' }] };
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
 
 <template>
-    <CardDescriptor
-        module="Roadmap"
-        :url="`Roadmaps/${entityId}`"
-        :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="Roadmap"
-        @on-fetch="setData"
-    >
+    <CardDescriptor :url="`Roadmaps/${entityId}`" :filter="filter" data-key="Roadmap">
         <template #body="{ entity }">
             <VnLv :label="t('Roadmap')" :value="entity?.name" />
             <VnLv :label="t('ETD')" :value="toDateHourMin(entity?.etd)" />
diff --git a/src/pages/Route/Roadmap/RoadmapFilter.js b/src/pages/Route/Roadmap/RoadmapFilter.js
new file mode 100644
index 000000000..0ae890363
--- /dev/null
+++ b/src/pages/Route/Roadmap/RoadmapFilter.js
@@ -0,0 +1,3 @@
+export default {
+    include: [{ relation: 'supplier' }],
+};
diff --git a/src/pages/Route/Roadmap/RoadmapStops.vue b/src/pages/Route/Roadmap/RoadmapStops.vue
index d8215ea49..e4085d572 100644
--- a/src/pages/Route/Roadmap/RoadmapStops.vue
+++ b/src/pages/Route/Roadmap/RoadmapStops.vue
@@ -68,7 +68,7 @@ const updateDefaultStop = (data) => {
                         <QBtn
                             flat
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             class="cursor-pointer"
                             color="primary"
                             @click="roadmapStopsCrudRef.insert()"
diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue
index 1fbb1897d..0c1c2b903 100644
--- a/src/pages/Route/Roadmap/RoadmapSummary.vue
+++ b/src/pages/Route/Roadmap/RoadmapSummary.vue
@@ -67,7 +67,6 @@ const filter = {
             },
         },
     ],
-    where: { id: entityId },
 };
 </script>
 
@@ -76,7 +75,7 @@ const filter = {
         <CardSummary
             data-key="RoadmapSummary"
             ref="summary"
-            :url="`Roadmaps`"
+            :url="`Roadmaps/${entityId}`"
             :filter="filter"
         >
             <template #header-left>
diff --git a/src/pages/Route/RouteExtendedList.vue b/src/pages/Route/RouteExtendedList.vue
index 7cc00aa5c..f32dcd0d9 100644
--- a/src/pages/Route/RouteExtendedList.vue
+++ b/src/pages/Route/RouteExtendedList.vue
@@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import { useQuasar } from 'quasar';
-import { toDate } from 'src/filters';
+import { dashIfEmpty, toDate, toHour } from 'src/filters';
 import { useRouter } from 'vue-router';
 import { usePrintService } from 'src/composables/usePrintService';
 
@@ -38,7 +38,7 @@ const routeFilter = {
 };
 const columns = computed(() => [
     {
-        align: 'left',
+        align: 'center',
         name: 'id',
         label: 'Id',
         chip: {
@@ -48,7 +48,7 @@ const columns = computed(() => [
         columnFilter: false,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'workerFk',
         label: t('route.Worker'),
         create: true,
@@ -68,10 +68,10 @@ const columns = computed(() => [
         },
         useLike: false,
         cardVisible: true,
-        format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.workerUserName),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'agencyModeFk',
         label: t('route.Agency'),
         isTitle: true,
@@ -87,17 +87,17 @@ const columns = computed(() => [
             },
         },
         columnClass: 'expand',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.agencyName),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'vehicleFk',
         label: t('route.Vehicle'),
         cardVisible: true,
         create: true,
         component: 'select',
         attrs: {
-            url: 'vehicles',
-            fields: ['id', 'numberPlate'],
+            url: 'vehicles/active',
             optionLabel: 'numberPlate',
             optionFilterValue: 'numberPlate',
             find: {
@@ -108,29 +108,31 @@ const columns = computed(() => [
         columnFilter: {
             inWhere: true,
         },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.vehiclePlateNumber),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'dated',
         label: t('route.Date'),
         columnFilter: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ date }) => toDate(date),
+        format: ({ dated }, dashIfEmpty) =>
+            dated === '0000-00-00' ? dashIfEmpty(null) : toDate(dated),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'from',
         label: t('route.From'),
         visible: false,
         cardVisible: true,
         create: true,
         component: 'date',
-        format: ({ date }) => toDate(date),
+        format: ({ from }) => toDate(from),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'to',
         label: t('route.To'),
         visible: false,
@@ -147,18 +149,20 @@ const columns = computed(() => [
         columnClass: 'shrink',
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'started',
         label: t('route.hourStarted'),
         component: 'time',
         columnFilter: false,
+        format: ({ started }) => toHour(started),
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'finished',
         label: t('route.hourFinished'),
         component: 'time',
         columnFilter: false,
+        format: ({ finished }) => toHour(finished),
     },
     {
         align: 'center',
@@ -177,7 +181,7 @@ const columns = computed(() => [
         visible: false,
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'description',
         label: t('route.Description'),
         isTitle: true,
@@ -186,7 +190,7 @@ const columns = computed(() => [
         field: 'description',
     },
     {
-        align: 'left',
+        align: 'center',
         name: 'isOk',
         label: t('route.Served'),
         component: 'checkbox',
@@ -300,60 +304,62 @@ const openTicketsDialog = (id) => {
             <RouteFilter data-key="RouteList" />
         </template>
     </RightMenu>
-    <VnTable
-        class="route-list"
-        ref="tableRef"
-        data-key="RouteList"
-        url="Routes/filter"
-        :columns="columns"
-        :right-search="false"
-        :is-editable="true"
-        :filter="routeFilter"
-        redirect="route"
-        :row-click="false"
-        :create="{
-            urlCreate: 'Routes',
-            title: t('route.createRoute'),
-            onDataSaved: ({ id }) => tableRef.redirect(id),
-            formInitialData: {},
-        }"
-        save-url="Routes/crud"
-        :disable-option="{ card: true }"
-        table-height="85vh"
-        v-model:selected="selectedRows"
-        :table="{
-            'row-key': 'id',
-            selection: 'multiple',
-        }"
-    >
-        <template #moreBeforeActions>
-            <QBtn
-                icon="vn:clone"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="confirmationDialog = true"
-            >
-                <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
-            </QBtn>
-            <QBtn
-                icon="cloud_download"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="showRouteReport"
-            >
-                <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
-            </QBtn>
-            <QBtn
-                icon="check"
-                color="primary"
-                class="q-mr-sm"
-                :disable="!selectedRows?.length"
-                @click="markAsServed()"
-            >
-                <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
-            </QBtn>
-        </template>
-    </VnTable>
+    <QPage class="q-px-md">
+        <VnTable
+            class="route-list"
+            ref="tableRef"
+            data-key="RouteList"
+            url="Routes/filter"
+            :columns="columns"
+            :right-search="false"
+            :is-editable="true"
+            :filter="routeFilter"
+            redirect="route"
+            :row-click="false"
+            :create="{
+                urlCreate: 'Routes',
+                title: t('route.createRoute'),
+                onDataSaved: ({ id }) => tableRef.redirect(id),
+                formInitialData: {},
+            }"
+            save-url="Routes/crud"
+            :disable-option="{ card: true }"
+            table-height="85vh"
+            v-model:selected="selectedRows"
+            :table="{
+                'row-key': 'id',
+                selection: 'multiple',
+            }"
+        >
+            <template #moreBeforeActions>
+                <QBtn
+                    icon="vn:clone"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="confirmationDialog = true"
+                >
+                    <QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
+                </QBtn>
+                <QBtn
+                    icon="cloud_download"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="showRouteReport"
+                >
+                    <QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
+                </QBtn>
+                <QBtn
+                    icon="check"
+                    color="primary"
+                    class="q-mr-sm"
+                    :disable="!selectedRows?.length"
+                    @click="markAsServed()"
+                >
+                    <QTooltip>{{ t('route.Mark as served') }}</QTooltip>
+                </QBtn>
+            </template>
+        </VnTable>
+    </QPage>
 </template>
diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue
index bc3227f6c..9dad8ba22 100644
--- a/src/pages/Route/RouteList.vue
+++ b/src/pages/Route/RouteList.vue
@@ -38,6 +38,17 @@ const columns = computed(() => [
         align: 'left',
         name: 'workerFk',
         label: t('route.Worker'),
+        component: 'select',
+        attrs: {
+            url: 'Workers/activeWithInheritedRole',
+            fields: ['id', 'name'],
+            useLike: false,
+            optionFilter: 'firstName',
+            find: {
+                value: 'workerFk',
+                label: 'workerUserName',
+            },
+        },
         create: true,
         cardVisible: true,
         format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
@@ -48,6 +59,15 @@ const columns = computed(() => [
         name: 'agencyName',
         label: t('route.Agency'),
         cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'agencyModes',
+            fields: ['id', 'name'],
+            find: {
+                value: 'agencyModeFk',
+                label: 'agencyName',
+            },
+        },
         create: true,
         columnClass: 'expand',
         columnFilter: false,
@@ -57,6 +77,17 @@ const columns = computed(() => [
         name: 'vehiclePlateNumber',
         label: t('route.Vehicle'),
         cardVisible: true,
+        component: 'select',
+        attrs: {
+            url: 'vehicles',
+            fields: ['id', 'numberPlate'],
+            optionLabel: 'numberPlate',
+            optionFilterValue: 'numberPlate',
+            find: {
+                value: 'vehicleFk',
+                label: 'vehiclePlateNumber',
+            },
+        },
         create: true,
         columnFilter: false,
     },
diff --git a/src/pages/Route/RouteTickets.vue b/src/pages/Route/RouteTickets.vue
index 1416f77ce..adc7dfdaa 100644
--- a/src/pages/Route/RouteTickets.vue
+++ b/src/pages/Route/RouteTickets.vue
@@ -120,8 +120,8 @@ const deletePriorities = async () => {
     try {
         await Promise.all(
             selectedRows.value.map((ticket) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: null })
-            )
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: null }),
+            ),
         );
     } finally {
         refreshKey.value++;
@@ -132,8 +132,8 @@ const setOrderedPriority = async () => {
     try {
         await Promise.all(
             ticketList.value.map((ticket, index) =>
-                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 })
-            )
+                axios.patch(`Tickets/${ticket?.id}/`, { priority: index + 1 }),
+            ),
         );
     } finally {
         refreshKey.value++;
@@ -162,7 +162,7 @@ const setHighestPriority = async (ticket, ticketList) => {
 const goToBuscaman = async (ticket = null) => {
     await openBuscaman(
         routeEntity.value?.vehicleFk,
-        ticket ? [ticket] : selectedRows.value
+        ticket ? [ticket] : selectedRows.value,
     );
 };
 
@@ -393,7 +393,13 @@ const openSmsDialog = async () => {
             </VnPaginate>
         </div>
         <QPageSticky :offset="[20, 20]">
-            <QBtn fab icon="add" shortcut="+" color="primary" @click="openTicketsDialog">
+            <QBtn
+                fab
+                icon="add"
+                v-shortcut="'+'"
+                color="primary"
+                @click="openTicketsDialog"
+            >
                 <QTooltip>
                     {{ t('Add ticket') }}
                 </QTooltip>
diff --git a/src/pages/Route/Vehicle/Card/VehicleBasicData.vue b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
new file mode 100644
index 000000000..e78bc6edd
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue
@@ -0,0 +1,162 @@
+<script setup>
+import { ref } from 'vue';
+import FormModel from 'components/FormModel.vue';
+import FetchData from 'src/components/FetchData.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnRow from 'components/ui/VnRow.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+
+const warehouses = ref([]);
+const companies = ref([]);
+const countries = ref([]);
+const fuelTypes = ref([]);
+const bankPolicies = ref([]);
+const deliveryPoints = ref([]);
+</script>
+<template>
+    <FetchData
+        url="Warehouses"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (warehouses = data)"
+        auto-load
+    />
+    <FetchData
+        url="Companies"
+        :filter="{ fields: ['id', 'code'] }"
+        @on-fetch="(data) => (companies = data)"
+        auto-load
+    />
+    <FetchData
+        url="Countries"
+        :filter="{ fields: ['code'] }"
+        @on-fetch="(data) => (countries = data)"
+        auto-load
+    />
+    <FetchData
+        url="FuelTypes"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (fuelTypes = data)"
+        auto-load
+    />
+    <FetchData
+        url="DeliveryPoints"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (deliveryPoints = data)"
+        auto-load
+    />
+    <FormModel model="Vehicle" :url-update="`Vehicles/${$route.params.id}`">
+        <template #form="{ data }">
+            <VnRow>
+                <VnInput v-model="data.description" :label="$t('globals.description')" />
+                <VnInput v-model="data.numberPlate" :label="$t('vehicle.numberPlate')" />
+            </VnRow>
+            <VnRow>
+                <VnInput
+                    v-model="data.model"
+                    :label="$t('globals.model')"
+                    :required="true"
+                />
+                <VnSelect
+                    url="VehicleTypes"
+                    v-model="data.vehicleTypeFk"
+                    :label="$t('globals.type')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnInput
+                    v-model="data.tradeMark"
+                    :label="$t('vehicle.tradeMark')"
+                    :required="true"
+                />
+                <VnInput v-model="data.chassis" :label="$t('vehicle.chassis')" />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    v-model="data.fuelTypeFk"
+                    :label="$t('globals.fuel')"
+                    :options="fuelTypes"
+                />
+                <VnSelect
+                    v-model="data.deliveryPointFk"
+                    :label="$t('globals.deliveryPoint')"
+                    :options="deliveryPoints"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    v-model="data.companyFk"
+                    :label="$t('globals.company')"
+                    :options="companies"
+                    option-label="code"
+                />
+                <VnSelect
+                    v-model="data.warehouseFk"
+                    :label="$t('globals.warehouse')"
+                    :options="warehouses"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="Suppliers"
+                    :filter="{ fields: ['id', 'name'] }"
+                    v-model="data.supplierFk"
+                    :label="$t('globals.supplier')"
+                />
+                <VnSelect
+                    url="Suppliers"
+                    :filter="{ fields: ['id', 'name'] }"
+                    v-model="data.supplierCoolerFk"
+                    :label="$t('vehicle.supplierCooler')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="BankPolicies"
+                    :filter="{ fields: ['id', 'ref'] }"
+                    v-model="data.bankPolicyFk"
+                    :label="$t('vehicle.leasing')"
+                    :options="bankPolicies"
+                    option-label="ref"
+                    option-value="id"
+                />
+                <VnInput v-model="data.leasing" :label="$t('vehicle.nLeasing')" />
+            </VnRow>
+            <VnRow>
+                <VnInputNumber v-model="data.import" :label="$t('globals.amount')" />
+                <VnInputNumber
+                    v-model="data.importCooler"
+                    :label="$t('vehicle.amountCooler')"
+                />
+            </VnRow>
+            <VnRow>
+                <VnSelect
+                    url="Ppes"
+                    option-label="id"
+                    v-model="data.ppeFk"
+                    :label="$t('vehicle.ppe')"
+                />
+                <VnSelect
+                    v-model="data.countryCodeFk"
+                    :label="$t('globals.country')"
+                    :options="countries"
+                    option-label="code"
+                    option-value="code"
+                />
+            </VnRow>
+            <VnRow>
+                <VnInput v-model="data.vin" :label="$t('vehicle.vin')" />
+                <span :style="{ 'align-self': $q.screen.gt.xs ? 'end' : 'unset' }">
+                    <QCheckbox
+                        v-model="data.isActive"
+                        :label="$t('vehicle.isActive')"
+                        :false-value="0"
+                        :true-value="1"
+                        dense
+                        class="q-mt-sm"
+                    />
+                </span>
+            </VnRow>
+        </template>
+    </FormModel>
+</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleCard.vue b/src/pages/Route/Vehicle/Card/VehicleCard.vue
new file mode 100644
index 000000000..f59420aa2
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleCard.vue
@@ -0,0 +1,13 @@
+<script setup>
+import VnCardBeta from 'components/common/VnCardBeta.vue';
+import VehicleDescriptor from './VehicleDescriptor.vue';
+import VehicleFilter from '../VehicleFilter.js';
+</script>
+<template>
+    <VnCardBeta
+        data-key="Vehicle"
+        url="Vehicles"
+        :filter="VehicleFilter"
+        :descriptor="VehicleDescriptor"
+    />
+</template>
diff --git a/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
new file mode 100644
index 000000000..d9a2434ab
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue
@@ -0,0 +1,49 @@
+<script setup>
+import VnLv from 'src/components/ui/VnLv.vue';
+import CardDescriptor from 'components/ui/CardDescriptor.vue';
+import axios from 'axios';
+import useNotify from 'src/composables/useNotify.js';
+
+const { notify } = useNotify();
+</script>
+<template>
+    <CardDescriptor
+        :url="`Vehicles/${$route.params.id}`"
+        data-key="Vehicle"
+        title="numberPlate"
+        :to-module="{ name: 'VehicleList' }"
+    >
+        <template #menu="{ entity }">
+            <QItem
+                data-cy="delete"
+                v-ripple
+                clickable
+                @click="
+                    async () => {
+                        try {
+                            await axios.delete(`Vehicles/${entity.id}`);
+                            notify('vehicle.remove', 'positive');
+                            $router.push({ name: 'VehicleList' });
+                        } catch (e) {
+                            throw e;
+                        }
+                    }
+                "
+            >
+                <QItemSection>
+                    {{ $t('vehicle.delete') }}
+                </QItemSection>
+            </QItem>
+        </template>
+        <template #body="{ entity }">
+            <VnLv :label="$t('vehicle.numberPlate')" :value="entity.numberPlate" />
+            <VnLv :label="$t('vehicle.tradeMark')" :value="entity.tradeMark" />
+            <VnLv :label="$t('globals.model')" :value="entity.model" />
+            <VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
+        </template>
+    </CardDescriptor>
+</template>
+<i18n>
+es:
+    Vehicle removed: Vehículo eliminado
+</i18n>
diff --git a/src/pages/Route/Vehicle/Card/VehicleSummary.vue b/src/pages/Route/Vehicle/Card/VehicleSummary.vue
new file mode 100644
index 000000000..981870cb2
--- /dev/null
+++ b/src/pages/Route/Vehicle/Card/VehicleSummary.vue
@@ -0,0 +1,127 @@
+<script setup>
+import { computed } from 'vue';
+import { useRoute } from 'vue-router';
+import CardSummary from 'components/ui/CardSummary.vue';
+import VnLv from 'src/components/ui/VnLv.vue';
+import VnTitle from 'src/components/common/VnTitle.vue';
+import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
+import VehicleFilter from '../VehicleFilter.js';
+import { downloadFile } from 'src/composables/downloadFile';
+import { dashIfEmpty } from 'src/filters';
+
+const props = defineProps({ id: { type: [Number, String], default: null } });
+
+const route = useRoute();
+const entityId = computed(() => props.id || +route.params.id);
+const links = {
+    'basic-data': `#/vehicle/${entityId.value}/basic-data`,
+    notes: `#/vehicle/${entityId.value}/notes`,
+    dms: `#/vehicle/${entityId.value}/dms`,
+    'invoice-in': `#/vehicle/${entityId.value}/invoice-in`,
+    events: `#/vehicle/${entityId.value}/events`,
+};
+</script>
+<template>
+    <CardSummary data-key="Vehicle" :url="`Vehicles/${entityId}`" :filter="VehicleFilter">
+        <template #header="{ entity }">
+            <div>{{ entity.id }} - {{ entity.numberPlate }}</div>
+        </template>
+        <template #body="{ entity }">
+            <QCard class="vn-one">
+                <QCardSection dense>
+                    <VnTitle
+                        :url="links['basic-data']"
+                        :text="$t('globals.pageTitles.basicData')"
+                    />
+                </QCardSection>
+                <QCardSection content>
+                    <QList dense>
+                        <VnLv
+                            :label="$t('globals.description')"
+                            :value="entity.description"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.tradeMark')"
+                            :value="entity.tradeMark"
+                        />
+                        <VnLv :label="$t('globals.model')" :value="entity.model" />
+                        <VnLv :label="$t('globals.supplier')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entity.supplier?.name }}
+                                    <SupplierDescriptorProxy :id="entity.supplierFk" />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('vehicle.supplierCooler')">
+                            <template #value>
+                                <span class="link">
+                                    {{ entity.supplierCooler?.name }}
+                                    <SupplierDescriptorProxy
+                                        :id="entity.supplierCoolerFk"
+                                    />
+                                </span>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('vehicle.vin')" :value="entity.vin" />
+                    </QList>
+                    <QList dense>
+                        <VnLv :label="$t('vehicle.chassis')" :value="entity.chassis" />
+                        <VnLv
+                            :label="$t('globals.fuel')"
+                            :value="entity.fuelType?.name"
+                        />
+                        <VnLv :label="$t('vehicle.ppe')" :value="entity.ppeFk" />
+                        <VnLv :label="$t('vehicle.nLeasing')" :value="entity.leasing" />
+                        <VnLv
+                            :label="$t('vehicle.leasing')"
+                            :value="entity.bankPolicy?.ref"
+                        >
+                            <template #value>
+                                <span v-text="dashIfEmpty(entity.bankPolicy?.name)" />
+                                <QBtn
+                                    v-if="entity.bankPolicy?.dmsFk"
+                                    class="q-ml-xs"
+                                    color="primary"
+                                    flat
+                                    dense
+                                    icon="cloud_download"
+                                    @click="downloadFile(entity.bankPolicy?.dmsFk)"
+                                >
+                                    <QTooltip>{{ $t('globals.download') }}</QTooltip>
+                                </QBtn>
+                            </template>
+                        </VnLv>
+                        <VnLv :label="$t('globals.amount')" :value="entity.import" />
+                    </QList>
+                    <QList dense>
+                        <VnLv
+                            :label="$t('globals.warehouse')"
+                            :value="entity.warehouse?.name"
+                        />
+                        <VnLv
+                            :label="$t('globals.company')"
+                            :value="entity.company?.code"
+                        />
+                        <VnLv
+                            :label="$t('globals.deliveryPoint')"
+                            :value="entity.deliveryPoint?.name"
+                        />
+                        <VnLv
+                            :label="$t('globals.country')"
+                            :value="entity.countryCodeFk"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.isKmTruckRate')"
+                            :value="!!entity.isKmTruckRate"
+                        />
+                        <VnLv
+                            :label="$t('vehicle.isActive')"
+                            :value="!!entity.isActive"
+                        />
+                    </QList>
+                </QCardSection>
+            </QCard>
+        </template>
+    </CardSummary>
+</template>
diff --git a/src/pages/Route/Vehicle/VehicleFilter.js b/src/pages/Route/Vehicle/VehicleFilter.js
new file mode 100644
index 000000000..cbf5cc621
--- /dev/null
+++ b/src/pages/Route/Vehicle/VehicleFilter.js
@@ -0,0 +1,76 @@
+export default {
+    fields: [
+        'id',
+        'description',
+        'isActive',
+        'isKmTruckRate',
+        'warehouseFk',
+        'companyFk',
+        'numberPlate',
+        'chassis',
+        'supplierFk',
+        'supplierCoolerFk',
+        'tradeMark',
+        'fuelTypeFk',
+        'import',
+        'importCooler',
+        'vin',
+        'model',
+        'ppeFk',
+        'countryCodeFk',
+        'leasing',
+        'bankPolicyFk',
+        'vehicleTypeFk',
+        'deliveryPointFk',
+    ],
+    include: [
+        {
+            relation: 'warehouse',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'company',
+            scope: {
+                fields: ['id', 'code'],
+            },
+        },
+        {
+            relation: 'supplier',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'supplierCooler',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'fuelType',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'bankPolicy',
+            scope: {
+                fields: ['id', 'ref', 'dmsFk'],
+            },
+        },
+        {
+            relation: 'ppe',
+            scope: {
+                fields: ['id'],
+            },
+        },
+        {
+            relation: 'deliveryPoint',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Route/Vehicle/VehicleList.vue b/src/pages/Route/Vehicle/VehicleList.vue
new file mode 100644
index 000000000..e5b945010
--- /dev/null
+++ b/src/pages/Route/Vehicle/VehicleList.vue
@@ -0,0 +1,224 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+import VnTable from 'components/VnTable/VnTable.vue';
+import FetchData from 'src/components/FetchData.vue';
+import { useSummaryDialog } from 'src/composables/useSummaryDialog';
+import VehicleSummary from 'src/pages/Route/Vehicle/Card/VehicleSummary.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnSection from 'src/components/common/VnSection.vue';
+
+const { t } = useI18n();
+const { viewSummary } = useSummaryDialog();
+const warehouses = ref([]);
+const companies = ref([]);
+const countries = ref([]);
+const vehicleStates = ref([]);
+const vehicleTypes = ref([]);
+
+const columns = computed(() => [
+    {
+        name: 'isActive',
+        columnFilter: false,
+        align: 'center',
+    },
+    {
+        name: 'id',
+        label: t('globals.id'),
+        isId: true,
+        chip: {
+            condition: () => true,
+        },
+    },
+    {
+        name: 'description',
+        label: t('globals.description'),
+    },
+    {
+        name: 'tradeMark',
+        label: t('vehicle.tradeMark'),
+        cardVisible: true,
+    },
+    {
+        name: 'numberPlate',
+        label: t('vehicle.numberPlate'),
+        isTitle: true,
+    },
+    {
+        name: 'vehicleTypeFk',
+        label: t('globals.type'),
+        format: (row) => row.type,
+        columnFilter: {
+            component: 'select',
+            name: 'vehicleTypeFk',
+            options: vehicleTypes.value,
+        },
+        cardVisible: true,
+    },
+    {
+        name: 'vehicleStateFk',
+        label: t('globals.state'),
+        columnFilter: {
+            component: 'select',
+            name: 'vehicleStateFk',
+            optionLabel: 'state',
+            options: vehicleStates.value,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(row.state),
+    },
+    {
+        name: 'chassis',
+        label: t('vehicle.chassis'),
+    },
+    {
+        name: 'leasing',
+        label: t('vehicle.leasing'),
+    },
+    {
+        name: 'warehouseFk',
+        label: t('globals.warehouse'),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.warehouse),
+        columnFilter: {
+            component: 'select',
+            name: 'warehouseFk',
+            options: warehouses.value,
+        },
+        cardVisible: true,
+    },
+    {
+        name: 'companyFk',
+        label: t('globals.company'),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.company),
+        columnFilter: {
+            component: 'select',
+            name: 'companyFk',
+            optionLabel: 'code',
+            options: companies.value,
+        },
+    },
+    {
+        name: 'countryCodeFk',
+        label: t('globals.country'),
+        columnFilter: {
+            component: 'select',
+            name: 'countryCodeFk',
+            optionValue: 'code',
+            optionLabel: 'code',
+            options: countries.value,
+        },
+    },
+    {
+        align: 'right',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('components.smartCard.openSummary'),
+                icon: 'preview',
+                action: (row) => viewSummary(row.id, VehicleSummary),
+            },
+        ],
+    },
+]);
+</script>
+<template>
+    <FetchData
+        url="Warehouses"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (warehouses = data)"
+        auto-load
+    />
+    <FetchData
+        url="Companies"
+        :filter="{ fields: ['id', 'code'] }"
+        @on-fetch="(data) => (companies = data)"
+        auto-load
+    />
+    <FetchData
+        url="Countries"
+        :filter="{ fields: ['name', 'code'] }"
+        @on-fetch="(data) => (countries = data)"
+        auto-load
+    />
+    <FetchData
+        url="VehicleStates"
+        :filter="{ fields: ['id', 'state'] }"
+        @on-fetch="(data) => (vehicleStates = data)"
+        auto-load
+    />
+    <FetchData
+        url="VehicleTypes"
+        :filter="{ fields: ['id', 'name'] }"
+        @on-fetch="(data) => (vehicleTypes = data)"
+        auto-load
+    />
+    <VnSection
+        data-key="VehicleList"
+        :columns="columns"
+        prefix="vehicle"
+        :array-data-props="{
+            url: 'Vehicles/filter',
+        }"
+    >
+        <template #body>
+            <VnTable
+                ref="tableRef"
+                data-key="VehicleList"
+                :columns="columns"
+                redirect="route/vehicle"
+                :create="{
+                    urlCreate: 'Vehicles',
+                    title: t('vehicle.create'),
+                    onDataSaved: ({ id }) => $refs.tableRef.redirect(id),
+                    formInitialData: { isActive: true, isKmTruckRate: false },
+                }"
+                :use-model="true"
+                :right-search="false"
+            >
+                <template #column-isActive="{ row }">
+                    <span>
+                        <QIcon
+                            v-if="!row.isActive"
+                            name="vn:inactive-car"
+                            color="primary"
+                            size="xs"
+                        >
+                            <QTooltip>{{ $t('globals.inactive') }}</QTooltip>
+                        </QIcon>
+                    </span>
+                </template>
+                <template #more-create-dialog="{ data }">
+                    <VnInput
+                        v-model="data.numberPlate"
+                        :label="$t('vehicle.numberPlate')"
+                        :uppercase="true"
+                    />
+                    <VnInput v-model="data.tradeMark" :label="$t('vehicle.tradeMark')" />
+                    <VnInput v-model="data.model" :label="$t('globals.model')" />
+                    <VnSelect
+                        v-model="data.vehicleTypeFk"
+                        :label="$t('globals.type')"
+                        :options="vehicleTypes"
+                    />
+                    <VnSelect
+                        v-model="data.warehouseFk"
+                        :label="$t('globals.warehouse')"
+                        :options="warehouses"
+                    />
+                    <VnSelect
+                        v-model="data.countryCodeFk"
+                        :label="$t('globals.country')"
+                        option-value="code"
+                        option-label="name"
+                        :options="countries"
+                    />
+                    <VnInput
+                        v-model="data.description"
+                        :label="$t('globals.description')"
+                    />
+                    <QCheckbox to v-model="data.isActive" :label="$t('globals.active')" />
+                </template>
+            </VnTable>
+        </template>
+    </VnSection>
+</template>
diff --git a/src/pages/Route/Vehicle/locale/en.yml b/src/pages/Route/Vehicle/locale/en.yml
new file mode 100644
index 000000000..c92022f9d
--- /dev/null
+++ b/src/pages/Route/Vehicle/locale/en.yml
@@ -0,0 +1,20 @@
+vehicle:
+    tradeMark: Trade Mark
+    numberPlate: Nº Plate
+    chassis: Chassis
+    leasing: Leasing
+    isKmTruckRate: Trailer
+    delete: Delete Vehicle
+    supplierCooler: Supplier Cooler
+    vin: VIN
+    ppe: Ppe
+    isActive: Active
+    nLeasing: Nº Leasing
+    create: Create Vehicle
+    amountCooler: Amount cooler
+    remove: Vehicle removed
+    search: Search Vehicle
+    searchInfo: Search by id or number plate
+    params:
+        vehicleTypeFk: Type
+        vehicleStateFk: State
diff --git a/src/pages/Route/Vehicle/locale/es.yml b/src/pages/Route/Vehicle/locale/es.yml
new file mode 100644
index 000000000..c878f97ac
--- /dev/null
+++ b/src/pages/Route/Vehicle/locale/es.yml
@@ -0,0 +1,20 @@
+vehicle:
+    tradeMark: Marca
+    numberPlate: Matrícula
+    chassis: Nº de bastidor
+    leasing: Leasing
+    isKmTruckRate: Trailer
+    delete: Eliminar vehículo
+    supplierCooler: Proveedor Frío
+    vin: VIN
+    ppe: Nº Inmovilizado
+    create: Crear vehículo
+    amountCooler: Importe frío
+    isActive: Activo
+    nLeasing: Nº leasing
+    remove: Vehículo eliminado
+    search: Buscar Vehículo
+    searchInfo: Buscar por id o matrícula
+    params:
+        vehicleTypeFk: Tipo
+        vehicleStateFk: Estado
diff --git a/src/pages/Shelving/Card/ShelvingCard.vue b/src/pages/Shelving/Card/ShelvingCard.vue
index 41a0db33c..9e0ac8ad2 100644
--- a/src/pages/Shelving/Card/ShelvingCard.vue
+++ b/src/pages/Shelving/Card/ShelvingCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import ShelvingDescriptor from 'pages/Shelving/Card/ShelvingDescriptor.vue';
+import filter from './ShelvingFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Shelving"
-        base-url="Shelvings"
+        url="Shelvings"
+        :filter="filter"
         :descriptor="ShelvingDescriptor"
     />
 </template>
diff --git a/src/pages/Shelving/Card/ShelvingDescriptor.vue b/src/pages/Shelving/Card/ShelvingDescriptor.vue
index b1ff4a8ae..5e618aa7f 100644
--- a/src/pages/Shelving/Card/ShelvingDescriptor.vue
+++ b/src/pages/Shelving/Card/ShelvingDescriptor.vue
@@ -1,12 +1,12 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-import useCardDescription from 'composables/useCardDescription';
 import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
+import filter from './ShelvingFilter.js';
 
 const $props = defineProps({
     id: {
@@ -22,35 +22,13 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
-const data = ref(useCardDescription());
-const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
 </script>
-
 <template>
     <CardDescriptor
-        module="Shelving"
         :url="`Shelvings/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        data-key="Shelvings"
-        @on-fetch="setData"
+        title="code"
+        data-key="Shelving"
     >
         <template #body="{ entity }">
             <VnLv :label="t('globals.code')" :value="entity.code" />
diff --git a/src/pages/Shelving/Card/ShelvingFilter.js b/src/pages/Shelving/Card/ShelvingFilter.js
new file mode 100644
index 000000000..e302e1b9c
--- /dev/null
+++ b/src/pages/Shelving/Card/ShelvingFilter.js
@@ -0,0 +1,15 @@
+export default {
+    include: [
+        {
+            relation: 'worker',
+            scope: {
+                fields: ['id'],
+                include: {
+                    relation: 'user',
+                    scope: { fields: ['nickname'] },
+                },
+            },
+        },
+        { relation: 'parking' },
+    ],
+};
diff --git a/src/pages/Shelving/Card/ShelvingForm.vue b/src/pages/Shelving/Card/ShelvingForm.vue
index 3bbd94a0a..078058342 100644
--- a/src/pages/Shelving/Card/ShelvingForm.vue
+++ b/src/pages/Shelving/Card/ShelvingForm.vue
@@ -1,5 +1,4 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import { computed } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import VnRow from 'components/ui/VnRow.vue';
@@ -7,8 +6,8 @@ import FormModel from 'components/FormModel.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
+import filter from './ShelvingFilter.js';
 
-const { t } = useI18n();
 const route = useRoute();
 const router = useRouter();
 const entityId = computed(() => route.params.id ?? null);
@@ -20,22 +19,6 @@ const defaultInitialData = {
     isRecyclable: false,
 };
 
-const shelvingFilter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
-
 const onSave = (shelving, newShelving) => {
     if (isNew) {
         router.push({ name: 'ShelvingBasicData', params: { id: newShelving?.id } });
@@ -45,11 +28,10 @@ const onSave = (shelving, newShelving) => {
 <template>
     <VnSubToolbar v-if="isNew" />
     <FormModel
-        :url="isNew ? null : `Shelvings/${entityId}`"
         :url-create="isNew ? 'Shelvings' : null"
         :observe-form-changes="!isNew"
-        :filter="shelvingFilter"
-        model="shelving"
+        :filter="filter"
+        model="Shelving"
         :auto-load="!isNew"
         :form-initial-data="isNew ? defaultInitialData : null"
         @on-data-saved="onSave"
@@ -58,7 +40,7 @@ const onSave = (shelving, newShelving) => {
             <VnRow>
                 <VnInput
                     v-model="data.code"
-                    :label="t('globals.code')"
+                    :label="$t('globals.code')"
                     :rules="validate('Shelving.code')"
                 />
                 <VnSelect
@@ -68,7 +50,7 @@ const onSave = (shelving, newShelving) => {
                     option-label="code"
                     :filter-options="['id', 'code']"
                     :fields="['id', 'code']"
-                    :label="t('shelving.list.parking')"
+                    :label="$t('shelving.list.parking')"
                     :rules="validate('Shelving.parkingFk')"
                 />
             </VnRow>
@@ -76,12 +58,12 @@ const onSave = (shelving, newShelving) => {
                 <VnInput
                     v-model="data.priority"
                     type="number"
-                    :label="t('shelving.list.priority')"
+                    :label="$t('shelving.list.priority')"
                     :rules="validate('Shelving.priority')"
                 />
                 <QCheckbox
                     v-model="data.isRecyclable"
-                    :label="t('shelving.summary.recyclable')"
+                    :label="$t('shelving.summary.recyclable')"
                     :rules="validate('Shelving.isRecyclable')"
                 />
             </VnRow>
diff --git a/src/pages/Shelving/Card/ShelvingSearchbar.vue b/src/pages/Shelving/Card/ShelvingSearchbar.vue
index bfc8ad4f5..741b11663 100644
--- a/src/pages/Shelving/Card/ShelvingSearchbar.vue
+++ b/src/pages/Shelving/Card/ShelvingSearchbar.vue
@@ -1,15 +1,15 @@
 <script setup>
 import VnSearchbar from 'components/ui/VnSearchbar.vue';
-import {useI18n} from "vue-i18n";
-const { t } = useI18n();
+import exprBuilder from '../ShelvingExprBuilder.js';
 </script>
 
 <template>
     <VnSearchbar
         data-key="ShelvingList"
         url="Shelvings"
-        :label="t('Search shelving')"
-        :info="t('You can search by shelving reference')"
+        :label="$t('Search shelving')"
+        :info="$t('You can search by shelving reference')"
+        :expr-builder="exprBuilder"
     />
 </template>
 
diff --git a/src/pages/Shelving/Card/ShelvingSummary.vue b/src/pages/Shelving/Card/ShelvingSummary.vue
index 39fa4639f..f89ff4d78 100644
--- a/src/pages/Shelving/Card/ShelvingSummary.vue
+++ b/src/pages/Shelving/Card/ShelvingSummary.vue
@@ -1,10 +1,10 @@
 <script setup>
 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 filter from './ShelvingFilter.js';
 import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
 
 const $props = defineProps({
@@ -14,25 +14,9 @@ const $props = defineProps({
     },
 });
 const route = useRoute();
-const { t } = useI18n();
+
 const summary = ref({});
 const entityId = computed(() => $props.id || route.params.id);
-
-const filter = {
-    include: [
-        {
-            relation: 'worker',
-            scope: {
-                fields: ['id'],
-                include: {
-                    relation: 'user',
-                    scope: { fields: ['nickname'] },
-                },
-            },
-        },
-        { relation: 'parking' },
-    ],
-};
 </script>
 
 <template>
@@ -41,7 +25,7 @@ const filter = {
             ref="summary"
             :url="`Shelvings/${entityId}`"
             :filter="filter"
-            data-key="ShelvingSummary"
+            data-key="Shelving"
         >
             <template #header="{ entity }">
                 <div>{{ entity.code }}</div>
@@ -58,16 +42,19 @@ const filter = {
                         class="header header-link"
                         :to="{ name: 'ShelvingBasicData', params: { id: entityId } }"
                     >
-                        {{ t('globals.pageTitles.basicData') }}
+                        {{ $t('globals.pageTitles.basicData') }}
                         <QIcon name="open_in_new" />
                     </RouterLink>
-                    <VnLv :label="t('globals.code')" :value="entity.code" />
+                    <VnLv :label="$t('globals.code')" :value="entity.code" />
                     <VnLv
-                        :label="t('shelving.list.parking')"
+                        :label="$t('shelving.list.parking')"
                         :value="entity.parking?.code"
                     />
-                    <VnLv :label="t('shelving.list.priority')" :value="entity.priority" />
-                    <VnLv v-if="entity.worker" :label="t('globals.worker')">
+                    <VnLv
+                        :label="$t('shelving.list.priority')"
+                        :value="entity.priority"
+                    />
+                    <VnLv v-if="entity.worker" :label="$t('globals.worker')">
                         <template #value>
                             <VnUserLink
                                 :name="entity.worker?.user?.nickname"
@@ -76,7 +63,7 @@ const filter = {
                         </template>
                     </VnLv>
                     <VnLv
-                        :label="t('shelving.summary.recyclable')"
+                        :label="$t('shelving.summary.recyclable')"
                         :value="entity.isRecyclable"
                     />
                 </QCard>
diff --git a/src/pages/Parking/Card/ParkingBasicData.vue b/src/pages/Shelving/Parking/Card/ParkingBasicData.vue
similarity index 68%
rename from src/pages/Parking/Card/ParkingBasicData.vue
rename to src/pages/Shelving/Parking/Card/ParkingBasicData.vue
index 550a0684e..3de358002 100644
--- a/src/pages/Parking/Card/ParkingBasicData.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingBasicData.vue
@@ -1,16 +1,11 @@
 <script setup>
-import { ref, computed } from 'vue';
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
+import { ref } from 'vue';
 import VnRow from 'components/ui/VnRow.vue';
 import FetchData from 'src/components/FetchData.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import FormModel from 'components/FormModel.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
-const { t } = useI18n();
-const route = useRoute();
-const parkingId = computed(() => route.params?.id || null);
 const sectors = ref([]);
 const sectorFilter = { fields: ['id', 'description'] };
 
@@ -27,18 +22,21 @@ const filter = {
         @on-fetch="(data) => (sectors = data)"
         auto-load
     />
-    <FormModel :url="`Parkings/${parkingId}`" model="parking" :filter="filter" auto-load>
+    <FormModel model="Parking" auto-load>
         <template #form="{ data }">
             <VnRow>
-                <VnInput v-model="data.code" :label="t('globals.code')" />
-                <VnInput v-model="data.pickingOrder" :label="t('parking.pickingOrder')" />
+                <VnInput v-model="data.code" :label="$t('globals.code')" />
+                <VnInput
+                    v-model="data.pickingOrder"
+                    :label="$t('parking.pickingOrder')"
+                />
             </VnRow>
             <VnRow>
                 <VnSelect
                     v-model="data.sectorFk"
                     option-value="id"
                     option-label="description"
-                    :label="t('parking.sector')"
+                    :label="$t('parking.sector')"
                     :options="sectors"
                     use-input
                     input-debounce="0"
diff --git a/src/pages/Parking/Card/ParkingCard.vue b/src/pages/Shelving/Parking/Card/ParkingCard.vue
similarity index 53%
rename from src/pages/Parking/Card/ParkingCard.vue
rename to src/pages/Shelving/Parking/Card/ParkingCard.vue
index 1cd2df7b7..b32c1b7d3 100644
--- a/src/pages/Parking/Card/ParkingCard.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingCard.vue
@@ -1,12 +1,14 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import ParkingDescriptor from 'pages/Parking/Card/ParkingDescriptor.vue';
+import ParkingDescriptor from 'pages/Shelving/Parking/Card/ParkingDescriptor.vue';
+import filter from './ParkingFilter.js';
 </script>
 
 <template>
     <VnCardBeta
         data-key="Parking"
-        base-url="Parkings"
+        url="Parkings"
+        :filter="filter"
         :descriptor="ParkingDescriptor"
     />
 </template>
diff --git a/src/pages/Parking/Card/ParkingDescriptor.vue b/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
similarity index 58%
rename from src/pages/Parking/Card/ParkingDescriptor.vue
rename to src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
index d36ea16fc..46c9f8ea0 100644
--- a/src/pages/Parking/Card/ParkingDescriptor.vue
+++ b/src/pages/Shelving/Parking/Card/ParkingDescriptor.vue
@@ -1,10 +1,9 @@
 <script setup>
 import { computed } from 'vue';
-import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'components/ui/VnLv.vue';
-
+import filter from './ParkingFilter.js';
 const props = defineProps({
     id: {
         type: Number,
@@ -13,18 +12,11 @@ const props = defineProps({
     },
 });
 
-const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => props.id || route.params.id);
-
-const filter = {
-    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
-    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
-};
 </script>
 <template>
     <CardDescriptor
-        module="Parking"
         data-key="Parking"
         :url="`Parkings/${entityId}`"
         title="code"
@@ -32,9 +24,9 @@ const filter = {
         :to-module="{ name: 'ParkingList' }"
     >
         <template #body="{ entity }">
-            <VnLv :label="t('globals.code')" :value="entity.code" />
-            <VnLv :label="t('parking.pickingOrder')" :value="entity.pickingOrder" />
-            <VnLv :label="t('parking.sector')" :value="entity.sector?.description" />
+            <VnLv :label="$t('globals.code')" :value="entity.code" />
+            <VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
+            <VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
         </template>
     </CardDescriptor>
 </template>
diff --git a/src/pages/Shelving/Parking/Card/ParkingFilter.js b/src/pages/Shelving/Parking/Card/ParkingFilter.js
new file mode 100644
index 000000000..fd1855c45
--- /dev/null
+++ b/src/pages/Shelving/Parking/Card/ParkingFilter.js
@@ -0,0 +1,4 @@
+export default {
+    fields: ['id', 'sectorFk', 'code', 'pickingOrder', 'row', 'column'],
+    include: [{ relation: 'sector', scope: { fields: ['id', 'description'] } }],
+};
diff --git a/src/pages/Parking/Card/ParkingLog.vue b/src/pages/Shelving/Parking/Card/ParkingLog.vue
similarity index 100%
rename from src/pages/Parking/Card/ParkingLog.vue
rename to src/pages/Shelving/Parking/Card/ParkingLog.vue
diff --git a/src/pages/Parking/Card/ParkingSummary.vue b/src/pages/Shelving/Parking/Card/ParkingSummary.vue
similarity index 100%
rename from src/pages/Parking/Card/ParkingSummary.vue
rename to src/pages/Shelving/Parking/Card/ParkingSummary.vue
diff --git a/src/pages/Shelving/Parking/ParkingExprBuilder.js b/src/pages/Shelving/Parking/ParkingExprBuilder.js
new file mode 100644
index 000000000..16d2262c8
--- /dev/null
+++ b/src/pages/Shelving/Parking/ParkingExprBuilder.js
@@ -0,0 +1,10 @@
+export default (param, value) => {
+    switch (param) {
+        case 'code':
+            return { [param]: { like: `%${value}%` } };
+        case 'sectorFk':
+            return { [param]: value };
+        case 'search':
+            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
+    }
+};
diff --git a/src/pages/Parking/ParkingFilter.vue b/src/pages/Shelving/Parking/ParkingFilter.vue
similarity index 100%
rename from src/pages/Parking/ParkingFilter.vue
rename to src/pages/Shelving/Parking/ParkingFilter.vue
diff --git a/src/pages/Parking/ParkingList.vue b/src/pages/Shelving/Parking/ParkingList.vue
similarity index 90%
rename from src/pages/Parking/ParkingList.vue
rename to src/pages/Shelving/Parking/ParkingList.vue
index bce87126e..fe6c93ba5 100644
--- a/src/pages/Parking/ParkingList.vue
+++ b/src/pages/Shelving/Parking/ParkingList.vue
@@ -9,6 +9,7 @@ import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import ParkingFilter from './ParkingFilter.vue';
 import ParkingSummary from './Card/ParkingSummary.vue';
+import exprBuilder from './ParkingExprBuilder.js';
 import VnSection from 'src/components/common/VnSection.vue';
 
 const stateStore = useStateStore();
@@ -23,19 +24,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
 const filter = {
     fields: ['id', 'sectorFk', 'code', 'pickingOrder'],
 };
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'code':
-            return { [param]: { like: `%${value}%` } };
-        case 'sectorFk':
-            return { [param]: value };
-        case 'search':
-            return { or: [{ code: { like: `%${value}%` } }, { id: value }] };
-    }
-}
 </script>
-
 <template>
     <VnSection
         :data-key="dataKey"
diff --git a/src/pages/Parking/locale/en.yml b/src/pages/Shelving/Parking/locale/en.yml
similarity index 100%
rename from src/pages/Parking/locale/en.yml
rename to src/pages/Shelving/Parking/locale/en.yml
diff --git a/src/pages/Parking/locale/es.yml b/src/pages/Shelving/Parking/locale/es.yml
similarity index 100%
rename from src/pages/Parking/locale/es.yml
rename to src/pages/Shelving/Parking/locale/es.yml
diff --git a/src/pages/Shelving/ShelvingExprBuilder.js b/src/pages/Shelving/ShelvingExprBuilder.js
new file mode 100644
index 000000000..b9aad8a71
--- /dev/null
+++ b/src/pages/Shelving/ShelvingExprBuilder.js
@@ -0,0 +1,10 @@
+export default (param, value) => {
+    switch (param) {
+        case 'search':
+            return { code: { like: `%${value}%` } };
+        case 'parkingFk':
+        case 'userFk':
+        case 'isRecyclable':
+            return { [param]: value };
+    }
+};
diff --git a/src/pages/Shelving/ShelvingList.vue b/src/pages/Shelving/ShelvingList.vue
index cf158e76b..4e0c21100 100644
--- a/src/pages/Shelving/ShelvingList.vue
+++ b/src/pages/Shelving/ShelvingList.vue
@@ -1,6 +1,5 @@
 <script setup>
 import VnPaginate from 'components/ui/VnPaginate.vue';
-import { useI18n } from 'vue-i18n';
 import CardList from 'components/ui/CardList.vue';
 import VnLv from 'components/ui/VnLv.vue';
 import { useRouter } from 'vue-router';
@@ -8,9 +7,9 @@ import ShelvingFilter from 'pages/Shelving/Card/ShelvingFilter.vue';
 import ShelvingSummary from 'pages/Shelving/Card/ShelvingSummary.vue';
 import { useSummaryDialog } from 'src/composables/useSummaryDialog';
 import VnSection from 'src/components/common/VnSection.vue';
+import exprBuilder from './ShelvingExprBuilder.js';
 
 const router = useRouter();
-const { t } = useI18n();
 const { viewSummary } = useSummaryDialog();
 const dataKey = 'ShelvingList';
 
@@ -21,17 +20,6 @@ const filter = {
 function navigate(id) {
     router.push({ path: `/shelving/${id}` });
 }
-
-function exprBuilder(param, value) {
-    switch (param) {
-        case 'search':
-            return { code: { like: `%${value}%` } };
-        case 'parkingFk':
-        case 'userFk':
-        case 'isRecyclable':
-            return { [param]: value };
-    }
-}
 </script>
 
 <template>
@@ -62,18 +50,18 @@ function exprBuilder(param, value) {
                             >
                                 <template #list-items>
                                     <VnLv
-                                        :label="t('shelving.list.parking')"
-                                        :title-label="t('shelving.list.parking')"
+                                        :label="$t('shelving.list.parking')"
+                                        :title-label="$t('shelving.list.parking')"
                                         :value="row.parking?.code"
                                     />
                                     <VnLv
-                                        :label="t('shelving.list.priority')"
+                                        :label="$t('shelving.list.priority')"
                                         :value="row?.priority"
                                     />
                                 </template>
                                 <template #actions>
                                     <QBtn
-                                        :label="t('components.smartCard.openSummary')"
+                                        :label="$t('components.smartCard.openSummary')"
                                         @click.stop="viewSummary(row.id, ShelvingSummary)"
                                         color="primary"
                                     />
@@ -84,9 +72,9 @@ function exprBuilder(param, value) {
                 </div>
                 <QPageSticky :offset="[20, 20]">
                     <RouterLink :to="{ name: 'ShelvingCreate' }">
-                        <QBtn fab icon="add" color="primary" shortcut="+" />
+                        <QBtn fab icon="add" color="primary" v-shortcut="'+'" />
                         <QTooltip>
-                            {{ t('shelving.list.newShelving') }}
+                            {{ $t('shelving.list.newShelving') }}
                         </QTooltip>
                     </RouterLink>
                 </QPageSticky>
diff --git a/src/pages/Supplier/Card/SupplierAccounts.vue b/src/pages/Supplier/Card/SupplierAccounts.vue
index 4a6901d1d..365eb67a1 100644
--- a/src/pages/Supplier/Card/SupplierAccounts.vue
+++ b/src/pages/Supplier/Card/SupplierAccounts.vue
@@ -71,7 +71,7 @@ function bankEntityFilter(val, update) {
         filteredBankEntitiesOptions.value = bankEntitiesOptions.value.filter(
             (bank) =>
                 bank.bic.toLowerCase().startsWith(needle) ||
-                bank.name.toLowerCase().includes(needle)
+                bank.name.toLowerCase().includes(needle),
         );
     });
 }
@@ -170,7 +170,7 @@ function bankEntityFilter(val, update) {
                             <QIcon name="info" class="cursor-pointer">
                                 <QTooltip>{{
                                     t(
-                                        'Name of the bank account holder if different from the provider'
+                                        'Name of the bank account holder if different from the provider',
                                     )
                                 }}</QTooltip>
                             </QIcon>
@@ -194,7 +194,7 @@ function bankEntityFilter(val, update) {
                     <QBtn
                         flat
                         icon="add"
-                        shortcut="+"
+                        v-shortcut
                         class="cursor-pointer"
                         color="primary"
                         @click="supplierAccountRef.insert()"
diff --git a/src/pages/Supplier/Card/SupplierAddresses.vue b/src/pages/Supplier/Card/SupplierAddresses.vue
index e568962ff..c4c0ab7be 100644
--- a/src/pages/Supplier/Card/SupplierAddresses.vue
+++ b/src/pages/Supplier/Card/SupplierAddresses.vue
@@ -89,7 +89,7 @@ const redirectToUpdateView = (addressData) => {
                 icon="add"
                 color="primary"
                 @click="redirectToCreateView()"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip>
                 {{ t('New address') }}
diff --git a/src/pages/Supplier/Card/SupplierAgencyTerm.vue b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
index 99b672cc4..ab21f1f76 100644
--- a/src/pages/Supplier/Card/SupplierAgencyTerm.vue
+++ b/src/pages/Supplier/Card/SupplierAgencyTerm.vue
@@ -114,7 +114,7 @@ const redirectToCreateView = () => {
             icon="add"
             color="primary"
             @click="redirectToCreateView()"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip>
             {{ t('supplier.agencyTerms.addRow') }}
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index f6c13b7af..631700a4a 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -19,9 +19,8 @@ const companySizes = [
 </script>
 <template>
     <FormModel
-        :url="`Suppliers/${route.params.id}`"
         :url-update="`Suppliers/${route.params.id}`"
-        model="supplier"
+        model="Supplier"
         auto-load
         :clear-store-on-unmount="false"
         @on-data-saved="arrayData.fetch({})"
diff --git a/src/pages/Supplier/Card/SupplierCard.vue b/src/pages/Supplier/Card/SupplierCard.vue
index 594026d18..e30f79f96 100644
--- a/src/pages/Supplier/Card/SupplierCard.vue
+++ b/src/pages/Supplier/Card/SupplierCard.vue
@@ -1,19 +1,13 @@
 <script setup>
-import VnCard from 'components/common/VnCard.vue';
 import SupplierDescriptor from './SupplierDescriptor.vue';
-import SupplierListFilter from '../SupplierListFilter.vue';
+import VnCardBeta from 'src/components/common/VnCardBeta.vue';
+import filter from './SupplierFilter.js';
 </script>
 <template>
-    <VnCard
+    <VnCardBeta
         data-key="Supplier"
-        base-url="Suppliers"
+        url="Suppliers"
         :descriptor="SupplierDescriptor"
-        :filter-panel="SupplierListFilter"
-        search-data-key="SupplierList"
-        :searchbar-props="{
-            url: 'Suppliers/filter',
-            searchUrl: 'table',
-            label: 'Search suppliers',
-        }"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue
index 8a7021fb3..718de95dd 100644
--- a/src/pages/Supplier/Card/SupplierConsumption.vue
+++ b/src/pages/Supplier/Card/SupplierConsumption.vue
@@ -16,6 +16,7 @@ import axios from 'axios';
 import { useStateStore } from 'stores/useStateStore';
 import { useState } from 'src/composables/useState';
 import { useArrayData } from 'composables/useArrayData';
+import RightMenu from 'src/components/common/RightMenu.vue';
 
 const state = useState();
 const stateStore = useStateStore();
@@ -173,59 +174,59 @@ onMounted(async () => {
             </div>
         </div>
     </Teleport>
-    <QPage class="column items-center q-pa-md">
-        <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
+    <RightMenu>
+        <template #right-panel>
             <SupplierConsumptionFilter data-key="SupplierConsumption" />
-        </Teleport>
-        <QTable
-            :rows="rows"
-            row-key="id"
-            hide-header
-            class="full-width q-mt-md"
-            :no-data-label="t('No results')"
-        >
-            <template #body="{ row }">
-                <QTr>
-                    <QTd no-hover>
-                        <span class="label">{{ t('supplier.consumption.entry') }}: </span>
-                        <span>{{ row.id }}</span>
-                    </QTd>
-                    <QTd no-hover>
-                        <span class="label">{{ t('globals.date') }}: </span>
-                        <span>{{ toDate(row.shipped) }}</span></QTd
-                    >
-                    <QTd colspan="6" no-hover>
-                        <span class="label">{{ t('globals.reference') }}: </span>
-                        <span>{{ row.invoiceNumber }}</span>
-                    </QTd>
-                </QTr>
-                <QTr v-for="(buy, index) in row.buys" :key="index">
-                    <QTd no-hover>
-                        <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
-                        <ItemDescriptorProxy :id="buy.itemFk" />
-                    </QTd>
+        </template>
+    </RightMenu>
+    <QTable
+        :rows="rows"
+        row-key="id"
+        hide-header
+        class="full-width q-mt-md"
+        :no-data-label="t('No results')"
+    >
+        <template #body="{ row }">
+            <QTr>
+                <QTd no-hover>
+                    <span class="label">{{ t('supplier.consumption.entry') }}: </span>
+                    <span>{{ row.id }}</span>
+                </QTd>
+                <QTd no-hover>
+                    <span class="label">{{ t('globals.date') }}: </span>
+                    <span>{{ toDate(row.shipped) }}</span></QTd
+                >
+                <QTd colspan="6" no-hover>
+                    <span class="label">{{ t('globals.reference') }}: </span>
+                    <span>{{ row.invoiceNumber }}</span>
+                </QTd>
+            </QTr>
+            <QTr v-for="(buy, index) in row.buys" :key="index">
+                <QTd no-hover>
+                    <QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
+                    <ItemDescriptorProxy :id="buy.itemFk" />
+                </QTd>
 
-                    <QTd no-hover>
-                        <span>{{ buy.subName }}</span>
-                        <FetchedTags :item="buy" />
-                    </QTd>
-                    <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
-                    <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
-                    <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
-                </QTr>
-                <QTr>
-                    <QTd colspan="5" no-hover>
-                        <span class="label">{{ t('Total entry') }}: </span>
-                        <span>{{ row.total }} €</span>
-                    </QTd>
-                    <QTd no-hover>
-                        <span class="label">{{ t('Total stems') }}: </span>
-                        <span>{{ row.quantity }}</span>
-                    </QTd>
-                </QTr>
-            </template>
-        </QTable>
-    </QPage>
+                <QTd no-hover>
+                    <span>{{ buy.subName }}</span>
+                    <FetchedTags :item="buy" />
+                </QTd>
+                <QTd no-hover> {{ dashIfEmpty(buy.quantity) }}</QTd>
+                <QTd no-hover> {{ dashIfEmpty(buy.price) }}</QTd>
+                <QTd colspan="2" no-hover> {{ dashIfEmpty(buy.total) }}</QTd>
+            </QTr>
+            <QTr>
+                <QTd colspan="5" no-hover>
+                    <span class="label">{{ t('Total entry') }}: </span>
+                    <span>{{ row.total }} €</span>
+                </QTd>
+                <QTd no-hover>
+                    <span class="label">{{ t('Total stems') }}: </span>
+                    <span>{{ row.quantity }}</span>
+                </QTd>
+            </QTr>
+        </template>
+    </QTable>
 </template>
 
 <style scoped lang="scss">
diff --git a/src/pages/Supplier/Card/SupplierContacts.vue b/src/pages/Supplier/Card/SupplierContacts.vue
index 6781c8d34..f96d92ab1 100644
--- a/src/pages/Supplier/Card/SupplierContacts.vue
+++ b/src/pages/Supplier/Card/SupplierContacts.vue
@@ -78,7 +78,7 @@ const insertRow = () => {
                     <QBtn
                         flat
                         icon="add"
-                        shortcut="+"
+                        v-shortcut="'+'"
                         class="cursor-pointer"
                         color="primary"
                         @click="insertRow()"
diff --git a/src/pages/Supplier/Card/SupplierDescriptor.vue b/src/pages/Supplier/Card/SupplierDescriptor.vue
index 37c9c1cff..462bdf853 100644
--- a/src/pages/Supplier/Card/SupplierDescriptor.vue
+++ b/src/pages/Supplier/Card/SupplierDescriptor.vue
@@ -7,8 +7,8 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 
 import { toDateString } from 'src/filters';
-import useCardDescription from 'src/composables/useCardDescription';
 import { getUrl } from 'src/composables/getUrl';
+import filter from './SupplierFilter.js';
 import { useArrayData } from 'src/composables/useArrayData';
 
 const $props = defineProps({
@@ -28,42 +28,6 @@ const { t } = useI18n();
 const url = ref();
 const arrayData = useArrayData();
 
-const filter = {
-    fields: [
-        'id',
-        'name',
-        'nickname',
-        'nif',
-        'payMethodFk',
-        'payDemFk',
-        'payDay',
-        'isActive',
-        'isReal',
-        'isTrucker',
-        'account',
-    ],
-    include: [
-        {
-            relation: 'payMethod',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'payDem',
-            scope: {
-                fields: ['id', 'payDem'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: ['id', 'fi'],
-            },
-        },
-    ],
-};
-
 onMounted(async () => {
     url.value = await getUrl('');
 });
@@ -72,11 +36,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
-
 const supplier = computed(() => arrayData.store.data);
 
 const getEntryQueryParams = (supplier) => {
@@ -103,13 +62,9 @@ const getEntryQueryParams = (supplier) => {
 
 <template>
     <CardDescriptor
-        module="Supplier"
         :url="`Suppliers/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :filter="filter"
-        @on-fetch="setData"
-        data-key="supplierDescriptor"
+        data-key="Supplier"
         :summary="$props.summary"
     >
         <template #body="{ entity }">
diff --git a/src/pages/Supplier/Card/SupplierFilter.js b/src/pages/Supplier/Card/SupplierFilter.js
new file mode 100644
index 000000000..3ce5c3de2
--- /dev/null
+++ b/src/pages/Supplier/Card/SupplierFilter.js
@@ -0,0 +1,35 @@
+export default {
+    fields: [
+        'id',
+        'name',
+        'nickname',
+        'nif',
+        'payMethodFk',
+        'payDemFk',
+        'payDay',
+        'isActive',
+        'isSerious',
+        'isTrucker',
+        'account',
+    ],
+    include: [
+        {
+            relation: 'payMethod',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'payDem',
+            scope: {
+                fields: ['id', 'payDem'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: ['id', 'fi'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index e569eb236..ecee5b76b 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -10,6 +10,7 @@ import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnLocation from 'src/components/common/VnLocation.vue';
 import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -182,18 +183,11 @@ function handleLocation(data, location) {
                         v-model="data.isTrucker"
                         :label="t('supplier.fiscalData.isTrucker')"
                     />
-                    <div class="row items-center">
-                        <QCheckbox v-model="data.isVies" :label="t('globals.isVies')" />
-                        <QIcon name="info" size="xs" class="cursor-pointer q-ml-sm">
-                            <QTooltip>
-                                {{
-                                    t(
-                                        'When activating it, do not enter the country code in the ID field.'
-                                    )
-                                }}
-                            </QTooltip>
-                        </QIcon>
-                    </div>
+                    <VnCheckbox
+                        v-model="data.isVies"
+                        :label="t('globals.isVies')" 
+                        :info="t('whenActivatingIt')" 
+                    />
                 </div>
             </VnRow>
         </template>
@@ -201,6 +195,8 @@ function handleLocation(data, location) {
 </template>
 
 <i18n>
+en:
+    whenActivatingIt: When activating it, do not enter the country code in the ID field.
 es:
-    When activating it, do not enter the country code in the ID field.: Al activarlo, no informar el código del país en el campo nif
+    whenActivatingIt: Al activarlo, no informar el código del país en el campo nif.
 </i18n>
diff --git a/src/pages/Supplier/SupplierList.vue b/src/pages/Supplier/SupplierList.vue
index 85cc11857..600790745 100644
--- a/src/pages/Supplier/SupplierList.vue
+++ b/src/pages/Supplier/SupplierList.vue
@@ -2,14 +2,15 @@
 import { computed, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnTable from 'components/VnTable/VnTable.vue';
-import VnSearchbar from 'components/ui/VnSearchbar.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
-import SupplierListFilter from './SupplierListFilter.vue';
+import VnSection from 'src/components/common/VnSection.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import FetchData from 'src/components/FetchData.vue';
 
 const { t } = useI18n();
 const tableRef = ref();
-
+const dataKey = 'SupplierList';
+const provincesOptions = ref([]);
 const columns = computed(() => [
     {
         align: 'left',
@@ -104,38 +105,62 @@ const columns = computed(() => [
     },
 ]);
 </script>
-
 <template>
-    <VnSearchbar data-key="SuppliersList" :limit="20" :label="t('Search suppliers')" />
-    <RightMenu>
-        <template #right-panel>
-            <SupplierListFilter data-key="SuppliersList" />
-        </template>
-    </RightMenu>
-    <VnTable
-        ref="tableRef"
-        data-key="SuppliersList"
-        url="Suppliers/filter"
-        redirect="supplier"
-        :create="{
-            urlCreate: 'Suppliers/newSupplier',
-            title: t('Create Supplier'),
-            onDataSaved: ({ id }) => tableRef.redirect(id),
-            formInitialData: {},
-            mapper: (data) => {
-                data.name = data.socialName;
-
-                return data;
-            },
-        }"
-        :right-search="false"
-        order="id ASC"
+    <FetchData
+        url="Provinces"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
+        @on-fetch="(data) => (provincesOptions = data)"
+        auto-load
+    />
+    <VnSection
+        :data-key="dataKey"
         :columns="columns"
+        prefix="supplier"
+        :array-data-props="{
+            url: 'Suppliers/filter',
+            order: 'id ASC',
+        }"
     >
-        <template #more-create-dialog="{ data }">
-            <VnInput :label="t('globals.name')" v-model="data.socialName" :uppercase="true" />
-            </template>
-    </VnTable>
+        <template #body>
+            <VnTable
+                ref="tableRef"
+                :data-key="dataKey"
+                :create="{
+                    urlCreate: 'Suppliers/newSupplier',
+                    title: t('Create Supplier'),
+                    onDataSaved: ({ id }) => tableRef.redirect(id),
+                    formInitialData: {},
+                    mapper: (data) => {
+                        data.name = data.socialName;
+                        delete data.socialName;
+                        return data;
+                    },
+                }"
+                :columns="columns"
+                redirect="supplier"
+                :right-search="false"
+            >
+                <template #more-create-dialog="{ data }">
+                    <VnInput
+                        :label="t('globals.name')"
+                        v-model="data.socialName"
+                        :uppercase="true"
+                    />
+                </template>
+            </VnTable>
+        </template>
+        <template #moreFilterPanel="{ params, searchFn }">
+            <VnSelect
+                :label="t('globals.params.provinceFk')"
+                v-model="params.provinceFk"
+                @update:model-value="searchFn()"
+                :options="provincesOptions"
+                filled
+                dense
+                class="q-px-sm q-pr-lg"
+            />
+        </template>
+    </VnSection>
 </template>
 
 <i18n>
diff --git a/src/pages/Supplier/SupplierListFilter.vue b/src/pages/Supplier/SupplierListFilter.vue
deleted file mode 100644
index b170a35cc..000000000
--- a/src/pages/Supplier/SupplierListFilter.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<script setup>
-import { ref } from 'vue';
-import { useI18n } from 'vue-i18n';
-
-import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import FetchData from 'components/FetchData.vue';
-
-const props = defineProps({
-    dataKey: {
-        type: String,
-        required: true,
-    },
-});
-
-const { t } = useI18n();
-
-const provincesOptions = ref([]);
-const countriesOptions = ref([]);
-</script>
-
-<template>
-    <FetchData
-        url="Provinces"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
-        @on-fetch="(data) => (provincesOptions = data)"
-        auto-load
-    />
-    <FetchData
-        url="countries"
-        :filter="{ fields: ['id', 'name'], order: 'name ASC'}"
-        @on-fetch="(data) => (countriesOptions = data)"
-        auto-load
-    />
-    <VnFilterPanel
-        :data-key="props.dataKey"
-        :search-button="true"
-        :unremovable-params="['supplierFk']"
-    >
-        <template #tags="{ tag, formatFn }">
-            <div class="q-gutter-x-xs">
-                <strong>{{ t(`params.${tag.label}`) }}: </strong>
-                <span>{{ formatFn(tag.value) }}</span>
-            </div>
-        </template>
-        <template #body="{ params, searchFn }">
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.search"
-                        :label="t('params.search')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput
-                        v-model="params.nickname"
-                        :label="t('params.nickname')"
-                        is-outlined
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnInput v-model="params.nif" :label="t('params.nif')" is-outlined />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.provinceFk')"
-                        v-model="params.provinceFk"
-                        @update:model-value="searchFn()"
-                        :options="provincesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-            <QItem>
-                <QItemSection>
-                    <VnSelect
-                        :label="t('params.countryFk')"
-                        v-model="params.countryFk"
-                        @update:model-value="searchFn()"
-                        :options="countriesOptions"
-                        option-value="id"
-                        option-label="name"
-                        hide-selected
-                        dense
-                        outlined
-                        rounded
-                    />
-                </QItemSection>
-            </QItem>
-        </template>
-    </VnFilterPanel>
-</template>
-
-<i18n>
-en:
-    params:
-        search: General search
-        nickname: Alias
-        nif: Tax number
-        provinceFk: Province
-        countryFk: Country
-es:
-    params:
-        search: Búsqueda general
-        nickname: Alias
-        nif: NIF/CIF
-        provinceFk: Provincia
-        countryFk: País
-</i18n>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
index c6a85c287..055c9a0ff 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
@@ -9,8 +9,9 @@ import FetchData from 'components/FetchData.vue';
 import { useStateStore } from 'stores/useStateStore';
 import { toCurrency } from 'filters/index';
 import { useRole } from 'src/composables/useRole';
+import VnCheckbox from 'src/components/common/VnCheckbox.vue';
 
-const haveNegatives = defineModel('haveNegatives', { type: Boolean, required: true });
+const haveNegatives = defineModel('have-negatives', { type: Boolean, required: true });
 const formData = defineModel({ type: Object, required: true });
 
 const stateStore = useStateStore();
@@ -182,22 +183,19 @@ onMounted(async () => {
         </QCard>
         <QCard
             v-if="haveNegatives"
-            class="q-pa-md q-mb-md q-ma-md color-vn-text"
+            class="q-pa-xs q-mb-md q-ma-md color-vn-text"
             bordered
             flat
             style="border-color: black"
         >
             <QCardSection horizontal class="flex row items-center">
-                <QCheckbox
-                    :label="t('basicData.withoutNegatives')"
+                <VnCheckbox
                     v-model="formData.withoutNegatives"
+                    :label="t('basicData.withoutNegatives')"
+                    :info="t('basicData.withoutNegativesInfo')"
                     :toggle-indeterminate="false"
+                    size="xs"
                 />
-                <QIcon name="info" size="xs" class="q-ml-sm">
-                    <QTooltip max-width="350px">
-                        {{ t('basicData.withoutNegativesInfo') }}
-                    </QTooltip>
-                </QIcon>
             </QCardSection>
         </QCard>
     </QDrawer>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index cf4481537..9d70fea38 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -260,7 +260,7 @@ async function getZone(options) {
         auto-load
     />
     <QForm>
-        <VnRow>
+        <VnRow class="row q-gutter-md q-mb-md no-wrap">
             <VnSelect
                 :label="t('ticketList.client')"
                 v-model="clientId"
@@ -296,7 +296,7 @@ async function getZone(options) {
                 :rules="validate('ticketList.warehouse')"
             />
         </VnRow>
-        <VnRow>
+        <VnRow class="row q-gutter-md q-mb-md no-wrap">
             <VnSelect
                 :label="t('basicData.address')"
                 v-model="addressId"
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index 89249b899..ef2eb75d6 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -1,7 +1,7 @@
 <script setup>
-import { ref, onBeforeMount } from 'vue';
+import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRoute, useRouter } from 'vue-router';
+import { useRouter } from 'vue-router';
 
 import TicketBasicData from './TicketBasicData.vue';
 import TicketBasicDataForm from './TicketBasicDataForm.vue';
@@ -9,104 +9,69 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
+import { useArrayData } from 'src/composables/useArrayData';
 
 const { notify } = useNotify();
-const route = useRoute();
 const router = useRouter();
 const { t } = useI18n();
 const stepperRef = ref(null);
 const { openConfirmationModal } = useVnConfirm();
 
 const step = ref(1);
-const formData = ref({});
-const initialDataLoaded = ref(false);
-const haveNegatives = ref(false);
+const haveNegatives = ref(true);
 
-const ticketFilter = {
-    include: [
-        { relation: 'address' },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'salesPersonFk',
-                    'name',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                    'credit',
-                    'email',
-                    'phone',
-                    'mobile',
-                    'hasElectronicInvoice',
-                ],
-                include: {
-                    relation: 'salesPersonUser',
-                    scope: { fields: ['id', 'name'] },
-                },
-            },
-        },
-        { relation: 'invoiceOut' },
-    ],
-};
-
-const getTicketData = async () => {
-    const params = { filter: JSON.stringify(ticketFilter) };
-    const { data } = await axios.get(`tickets/${route.params.id}`, { params });
-    formData.value = data;
-    initialDataLoaded.value = true;
-};
+const ticket = computed(() => useArrayData('Ticket').store?.data);
 
 const isFormInvalid = () => {
     return (
-        !formData.value.clientFk ||
-        !formData.value.addressFk ||
-        !formData.value.agencyModeFk ||
-        !formData.value.companyFk ||
-        !formData.value.shipped ||
-        !formData.value.landed ||
-        !formData.value.zoneFk
+        !ticket.value.clientFk ||
+        !ticket.value.addressFk ||
+        !ticket.value.agencyModeFk ||
+        !ticket.value.companyFk ||
+        !ticket.value.shipped ||
+        !ticket.value.landed ||
+        !ticket.value.zoneFk
     );
 };
 
 const getPriceDifference = async () => {
     const params = {
-        landed: formData.value.landed,
-        addressId: formData.value.addressFk,
-        agencyModeId: formData.value.agencyModeFk,
-        zoneId: formData.value.zoneFk,
-        warehouseId: formData.value.warehouseFk,
-        shipped: formData.value.shipped,
+        landed: ticket.value.landed,
+        addressId: ticket.value.addressFk,
+        agencyModeId: ticket.value.agencyModeFk,
+        zoneId: ticket.value.zoneFk,
+        warehouseId: ticket.value.warehouseFk,
+        shipped: ticket.value.shipped,
     };
     const { data } = await axios.post(
-        `tickets/${formData.value.id}/priceDifference`,
+        `tickets/${ticket.value.id}/priceDifference`,
         params
     );
-    formData.value.sale = data;
+    ticket.value.sale = data;
 };
 
 const submit = async () => {
-    if (!formData.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
+    if (!ticket.value.option) return notify(t('basicData.chooseAnOption'), 'negative');
 
     const params = {
-        clientFk: formData.value.clientFk,
-        nickname: formData.value.nickname,
-        agencyModeFk: formData.value.agencyModeFk,
-        addressFk: formData.value.addressFk,
-        zoneFk: formData.value.zoneFk,
-        warehouseFk: formData.value.warehouseFk,
-        companyFk: formData.value.companyFk,
-        shipped: formData.value.shipped,
-        landed: formData.value.landed,
-        isDeleted: formData.value.isDeleted,
-        option: formData.value.option,
-        isWithoutNegatives: formData.value.withoutNegatives,
-        withWarningAccept: formData.value.withWarningAccept,
+        clientFk: ticket.value.clientFk,
+        nickname: ticket.value.nickname,
+        agencyModeFk: ticket.value.agencyModeFk,
+        addressFk: ticket.value.addressFk,
+        zoneFk: ticket.value.zoneFk,
+        warehouseFk: ticket.value.warehouseFk,
+        companyFk: ticket.value.companyFk,
+        shipped: ticket.value.shipped,
+        landed: ticket.value.landed,
+        isDeleted: ticket.value.isDeleted,
+        option: ticket.value.option,
+        isWithoutNegatives: ticket.value.withoutNegatives,
+        withWarningAccept: ticket.value.withWarningAccept,
         keepPrice: false,
     };
 
     const { data } = await axios.post(
-        `tickets/${formData.value.id}/componentUpdate`,
+        `tickets/${ticket.value.id}/componentUpdate`,
         params
     );
 
@@ -118,7 +83,7 @@ const submit = async () => {
 };
 
 const submitWithNegatives = async () => {
-    formData.value.withWarningAccept = true;
+    ticket.value.withWarningAccept = true;
     submit();
 };
 
@@ -130,7 +95,7 @@ const onNextStep = async () => {
         await getPriceDifference();
         stepperRef.value.next();
     } else if (step.value === 2) {
-        if (haveNegatives.value && !formData.value.withoutNegatives)
+        if (haveNegatives.value && !ticket.value.withoutNegatives)
             openConfirmationModal(
                 t('basicData.negativesConfirmTitle'),
                 t('basicData.negativesConfirmMessage'),
@@ -139,11 +104,10 @@ const onNextStep = async () => {
         else submit();
     }
 };
-
-onBeforeMount(async () => await getTicketData());
 </script>
 <template>
     <QStepper
+        v-if="ticket"
         v-model="step"
         ref="stepperRef"
         color="primary"
@@ -155,10 +119,10 @@ onBeforeMount(async () => await getTicketData());
         }"
     >
         <QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
-            <TicketBasicDataForm v-if="initialDataLoaded" v-model="formData" />
+            <TicketBasicDataForm v-model="ticket" />
         </QStep>
         <QStep :name="2" :title="t('basicData.priceDifference')">
-            <TicketBasicData v-model="formData" v-model:have-negatives="haveNegatives" />
+            <TicketBasicData v-model="ticket" v-model:have-negatives="haveNegatives" />
         </QStep>
         <template #navigation>
             <QStepperNavigation class="flex justify-between">
diff --git a/src/pages/Ticket/Card/TicketCard.vue b/src/pages/Ticket/Card/TicketCard.vue
index 6886a8e57..e22d5799a 100644
--- a/src/pages/Ticket/Card/TicketCard.vue
+++ b/src/pages/Ticket/Card/TicketCard.vue
@@ -1,7 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
 import TicketDescriptor from './TicketDescriptor.vue';
+import filter from './TicketFilter.js';
 </script>
 <template>
-    <VnCardBeta data-key="Ticket" base-url="Tickets" :descriptor="TicketDescriptor" />
+    <VnCardBeta
+        data-key="Ticket"
+        url="Tickets"
+        :descriptor="TicketDescriptor"
+        :filter="filter"
+    />
 </template>
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index 842607e0c..5936ffc28 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -19,7 +19,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
 const route = useRoute();
 const { t } = useI18n();
 const salesRef = ref(null);
-const arrayData = useArrayData('ticketData');
+const arrayData = useArrayData('Ticket');
 const { store } = arrayData;
 
 const ticketData = computed(() => store.data);
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index c9849d631..c5f3233b1 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -6,9 +6,11 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
 import CardDescriptor from 'components/ui/CardDescriptor.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import { toDateTimeFormat } from 'src/filters/date';
+import filter from './TicketFilter.js';
+import FetchData from 'src/components/FetchData.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const $props = defineProps({
     id: {
@@ -28,100 +30,24 @@ const { t } = useI18n();
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const filter = {
-    include: [
-        {
-            relation: 'address',
-            scope: {
-                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
-            },
-        },
-        {
-            relation: 'client',
-            scope: {
-                fields: [
-                    'id',
-                    'name',
-                    'salesPersonFk',
-                    'phone',
-                    'mobile',
-                    'email',
-                    'isActive',
-                    'isFreezed',
-                    'isTaxDataChecked',
-                    'hasElectronicInvoice',
-                ],
-                include: [
-                    {
-                        relation: 'user',
-                        scope: {
-                            fields: ['id', 'lang'],
-                        },
-                    },
-                    { relation: 'salesPersonUser' },
-                ],
-            },
-        },
-        {
-            relation: 'ticketState',
-            scope: {
-                include: { relation: 'state' },
-            },
-        },
-        {
-            relation: 'warehouse',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['id', 'name'],
-            },
-        },
-        {
-            relation: 'zone',
-            scope: {
-                fields: [
-                    'agencyModeFk',
-                    'bonus',
-                    'hour',
-                    'id',
-                    'isVolumetric',
-                    'itemMaxSize',
-                    'm3Max',
-                    'name',
-                    'price',
-                    'travelingDays',
-                ],
-            },
-        },
-    ],
-};
-
-const data = ref(useCardDescription());
+const problems = ref({});
 
 function ticketFilter(ticket) {
     return JSON.stringify({ clientFk: ticket.clientFk });
 }
-
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
 </script>
 
 <template>
+    <FetchData
+        :url="`Tickets/${entityId}/getTicketProblems`"
+        auto-load
+        @on-fetch="(data) => ([problems] = data)"
+    />
     <CardDescriptor
-        module="Ticket"
         :url="`Tickets/${entityId}`"
         :filter="filter"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        @on-fetch="setData"
+        data-key="Ticket"
         :summary="$props.summary"
-        data-key="ticketData"
         width="lg-width"
     >
         <template #menu="{ entity }">
@@ -167,48 +93,9 @@ const setData = (entity) => {
             <VnLv :label="t('globals.warehouse')" :value="entity.warehouse?.name" />
             <VnLv :label="t('globals.alias')" :value="entity.nickname" />
         </template>
-        <template #icons="{ entity }">
-            <QCardActions class="q-gutter-x-md">
-                <QIcon
-                    v-if="entity.client.isActive == false"
-                    name="vn:disabled"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client inactive') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.client.isFreezed == true"
-                    name="vn:frozen"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client Frozen') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity?.problem?.includes('hasRisk')"
-                    name="vn:risk"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client has debt') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.client.isTaxDataChecked == false"
-                    name="vn:no036"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('Client not checked') }}</QTooltip>
-                </QIcon>
-                <QIcon
-                    v-if="entity.isDeleted == true"
-                    name="vn:deletedTicket"
-                    size="xs"
-                    color="primary"
-                >
-                    <QTooltip>{{ t('This ticket is deleted') }}</QTooltip>
-                </QIcon>
+        <template #icons>
+            <QCardActions class="q-gutter-x-xs">
+                <TicketProblems :row="problems" />
             </QCardActions>
         </template>
         <template #actions="{ entity }">
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index 166e86978..f8084ff2f 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -40,7 +40,7 @@ const expeditionsFilter = computed(() => ({
     order: ['created DESC'],
 }));
 
-const ticketArrayData = useArrayData('ticketData');
+const ticketArrayData = useArrayData('Ticket');
 const ticketStore = ticketArrayData.store;
 const ticketData = computed(() => ticketStore.data);
 
diff --git a/src/pages/Ticket/Card/TicketFilter.js b/src/pages/Ticket/Card/TicketFilter.js
new file mode 100644
index 000000000..7846f1658
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketFilter.js
@@ -0,0 +1,72 @@
+export default {
+    include: [
+        {
+            relation: 'address',
+            scope: {
+                fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
+            },
+        },
+        {
+            relation: 'client',
+            scope: {
+                fields: [
+                    'id',
+                    'name',
+                    'salesPersonFk',
+                    'phone',
+                    'mobile',
+                    'email',
+                    'isActive',
+                    'isFreezed',
+                    'isTaxDataChecked',
+                    'hasElectronicInvoice',
+                    'credit',
+                ],
+                include: [
+                    {
+                        relation: 'user',
+                        scope: {
+                            fields: ['id', 'lang'],
+                        },
+                    },
+                    { relation: 'salesPersonUser' },
+                ],
+            },
+        },
+        {
+            relation: 'ticketState',
+            scope: {
+                include: { relation: 'state' },
+            },
+        },
+        {
+            relation: 'warehouse',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'zone',
+            scope: {
+                fields: [
+                    'agencyModeFk',
+                    'bonus',
+                    'hour',
+                    'id',
+                    'isVolumetric',
+                    'itemMaxSize',
+                    'm3Max',
+                    'name',
+                    'price',
+                    'travelingDays',
+                ],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index f558b71cc..feb88bf84 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -32,7 +32,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketNotesCrudRef.value.reload();
-    }
+    },
 );
 function handleDelete(row) {
     ticketNotesCrudRef.value.remove([row]);
@@ -105,7 +105,7 @@ async function handleSave() {
                     <VnRow v-if="observationTypes.length > rows.length">
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketPackage.vue b/src/pages/Ticket/Card/TicketPackage.vue
index 8ebdb4401..5fbf4c800 100644
--- a/src/pages/Ticket/Card/TicketPackage.vue
+++ b/src/pages/Ticket/Card/TicketPackage.vue
@@ -41,7 +41,7 @@ watch(
         crudModelFilter.where.ticketFk = route.params.id;
         store.filter = crudModelFilter;
         await ticketPackagingsCrudRef.value.reload();
-    }
+    },
 );
 </script>
 
@@ -118,7 +118,7 @@ watch(
                     <VnRow>
                         <QBtn
                             icon="add_circle"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             flat
                             class="fill-icon-on-hover q-ml-md"
                             color="primary"
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index f5fb50ecf..6f02a2ce6 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -14,7 +14,7 @@ import VnImg from 'src/components/ui/VnImg.vue';
 
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import TicketSaleMoreActions from './TicketSaleMoreActions.vue';
-import TicketTransfer from './TicketTransfer.vue';
+import TicketTransferProxy from './TicketTransferProxy.vue';
 
 import { toCurrency, toPercentage } from 'src/filters';
 import { useArrayData } from 'composables/useArrayData';
@@ -23,6 +23,7 @@ import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
 import VnTable from 'src/components/VnTable/VnTable.vue';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 const route = useRoute();
@@ -34,7 +35,7 @@ const editPriceProxyRef = ref(null);
 const editManaProxyRef = ref(null);
 const stateBtnDropdownRef = ref(null);
 const quasar = useQuasar();
-const arrayData = useArrayData('ticketData');
+const arrayData = useArrayData('Ticket');
 const { store } = arrayData;
 const selectedRows = ref([]);
 const hasSelectedRows = computed(() => selectedRows.value.length > 0);
@@ -626,8 +627,9 @@ watch(
                     @click="setTransferParams()"
                     data-cy="ticketSaleTransferBtn"
                 >
-                    <QTooltip>{{ t('Transfer lines') }}</QTooltip>
-                    <TicketTransfer
+                    <QTooltip>{{ t('ticketSale.transferLines') }}</QTooltip>
+                    <TicketTransferProxy
+                        class="full-width"
                         :transfer="transfer"
                         :ticket="store.data"
                         @refresh-data="resetChanges()"
@@ -697,53 +699,7 @@ watch(
         :disabled-attr="isTicketEditable"
     >
         <template #column-statusIcons="{ row }">
-            <router-link
-                v-if="row.claim?.claimFk"
-                :to="{ name: 'ClaimBasicData', params: { id: row.claim?.claimFk } }"
-            >
-                <QIcon color="primary" name="vn:claims" size="xs">
-                    <QTooltip>
-                        {{ t('ticketSale.claim') }}:
-                        {{ row.claim?.claimFk }}
-                    </QTooltip>
-                </QIcon>
-            </router-link>
-            <QIcon v-if="row.visible < 0" color="primary" name="warning" size="xs">
-                <QTooltip>
-                    {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.reserved"
-                color="primary"
-                name="vn:reserva"
-                size="xs"
-                data-cy="ticketSaleReservedIcon"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.reserved') }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.itemShortage"
-                color="primary"
-                name="vn:unavailable"
-                size="xs"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.noVisible') }}
-                </QTooltip>
-            </QIcon>
-            <QIcon
-                v-if="row.hasComponentLack"
-                color="primary"
-                name="vn:components"
-                size="xs"
-            >
-                <QTooltip>
-                    {{ t('ticketSale.hasComponentLack') }}
-                </QTooltip>
-            </QIcon>
+            <TicketProblems :row="row" />
         </template>
         <template #body-cell-picture="{ row }">
             <QTd>
@@ -881,7 +837,7 @@ watch(
             color="primary"
             fab
             icon="add"
-            shortcut="+"
+            v-shortcut="'+'"
             data-cy="ticketSaleAddToBasketBtn"
         />
         <QTooltip class="text-no-wrap">
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index d045eadee..6ce69a6aa 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -40,7 +40,7 @@ watch(
     async () => {
         store.filter = crudModelFilter.value;
         await ticketServiceCrudRef.value.reload();
-    }
+    },
 );
 
 onMounted(async () => await getDefaultTaxClass());
@@ -59,7 +59,7 @@ const createRefund = async () => {
         t('service.createRefundSuccess', {
             ticketId: refundTicket.id,
         }),
-        'positive'
+        'positive',
     );
     router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
 };
@@ -225,7 +225,7 @@ async function handleSave() {
             color="primary"
             icon="add"
             @click="ticketServiceCrudRef.insert()"
-            shortcut="+"
+            v-shortcut="'+'"
         />
     </QPageSticky>
 </template>
diff --git a/src/pages/Ticket/Card/TicketSplit.vue b/src/pages/Ticket/Card/TicketSplit.vue
new file mode 100644
index 000000000..e79057266
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketSplit.vue
@@ -0,0 +1,37 @@
+<script setup>
+import { ref } from 'vue';
+
+import VnInputDate from 'src/components/common/VnInputDate.vue';
+import split from './components/split';
+const emit = defineEmits(['ticketTransfered']);
+
+const $props = defineProps({
+    ticket: {
+        type: [Array, Object],
+        default: () => {},
+    },
+});
+
+const splitDate = ref(Date.vnNew());
+
+const splitSelectedRows = async () => {
+    const tickets = Array.isArray($props.ticket) ? $props.ticket : [$props.ticket];
+    await split(tickets, splitDate.value);
+    emit('ticketTransfered', tickets);
+};
+</script>
+
+<template>
+    <VnInputDate class="q-mr-sm" :label="$t('New date')" v-model="splitDate" clearable />
+    <QBtn class="q-mr-sm" color="primary" label="Split" @click="splitSelectedRows"></QBtn>
+</template>
+<style lang="scss">
+.q-table__bottom.row.items-center.q-table__bottom--nodata {
+    border-top: none;
+}
+</style>
+<i18n>
+es:
+    Sales to transfer: Líneas a transferir
+    Destination ticket: Ticket destinatario
+</i18n>
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 8cb518823..5838efa88 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -20,6 +20,7 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnToSummary from 'src/components/ui/VnToSummary.vue';
 import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const route = useRoute();
 const { notify } = useNotify();
@@ -40,7 +41,7 @@ const editableStates = ref([]);
 const ticketUrl = ref();
 const grafanaUrl = 'https://grafana.verdnatura.es';
 const stateBtnDropdownRef = ref();
-const descriptorData = useArrayData('ticketData');
+const descriptorData = useArrayData('Ticket');
 
 onMounted(async () => {
     ticketUrl.value = (await getUrl('ticket/')) + entityId.value + '/';
@@ -320,83 +321,7 @@ onMounted(async () => {
                     <template #body="props">
                         <QTr :props="props">
                             <QTd class="q-gutter-x-xs">
-                                <QBtn
-                                    flat
-                                    round
-                                    icon="vn:claims"
-                                    v-if="props.row.claim"
-                                    color="primary"
-                                    :to="{
-                                        name: 'ClaimCard',
-                                        params: {
-                                            id: props.row.claim.claimFk,
-                                        },
-                                    }"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.claim') }}:
-                                        {{ props.row.claim.claimFk }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QBtn
-                                    flat
-                                    round
-                                    icon="vn:claims"
-                                    v-if="props.row.claimBeginning"
-                                    color="primary"
-                                    :to="{
-                                        name: 'ClaimCard',
-                                        params: {
-                                            id: props.row.claimBeginning.claimFk,
-                                        },
-                                    }"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.claim') }}:
-                                        {{ props.row.claimBeginning.claimFk }}
-                                    </QTooltip>
-                                </QBtn>
-                                <QIcon
-                                    name="warning"
-                                    v-show="props.row.visible < 0"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('globals.visible') }}:
-                                        {{ props.row.visible }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:reserved"
-                                    v-show="props.row.reserved"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.reserved') }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:unavailable"
-                                    v-show="props.row.itemShortage"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.itemShortage') }}
-                                    </QTooltip>
-                                </QIcon>
-                                <QIcon
-                                    name="vn:components"
-                                    v-show="props.row.hasComponentLack"
-                                    color="primary"
-                                    size="xs"
-                                >
-                                    <QTooltip>
-                                        {{ t('ticket.summary.hasComponentLack') }}
-                                    </QTooltip>
-                                </QIcon>
+                                <TicketProblems :row="props.row" />
                             </QTd>
                             <QTd>
                                 <QBtn class="link" flat>
diff --git a/src/pages/Ticket/Card/TicketTracking.vue b/src/pages/Ticket/Card/TicketTracking.vue
index f4b8544d3..acf464fb1 100644
--- a/src/pages/Ticket/Card/TicketTracking.vue
+++ b/src/pages/Ticket/Card/TicketTracking.vue
@@ -19,7 +19,7 @@ watch(
     async (val) => {
         paginateFilter.where.ticketFk = val;
         paginateRef.value.fetch();
-    }
+    },
 );
 
 const paginateFilter = reactive({
@@ -119,7 +119,7 @@ const openCreateModal = () => createTrackingDialogRef.value.show();
                 color="primary"
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('tracking.addState') }}
diff --git a/src/pages/Ticket/Card/TicketTransfer.vue b/src/pages/Ticket/Card/TicketTransfer.vue
index 005d74a0e..ffa964c92 100644
--- a/src/pages/Ticket/Card/TicketTransfer.vue
+++ b/src/pages/Ticket/Card/TicketTransfer.vue
@@ -1,11 +1,11 @@
 <script setup>
 import { ref, computed, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
-
 import VnInput from 'src/components/common/VnInput.vue';
 import TicketTransferForm from './TicketTransferForm.vue';
 
 import { toDateFormat } from 'src/filters/date.js';
+const emit = defineEmits(['ticketTransfered']);
 
 const $props = defineProps({
     mana: {
@@ -21,16 +21,15 @@ const $props = defineProps({
         default: () => {},
     },
     ticket: {
-        type: Object,
+        type: [Array, Object],
         default: () => {},
     },
 });
 
+onMounted(() => (_transfer.value = $props.transfer));
 const { t } = useI18n();
-const QPopupProxyRef = ref(null);
 const transferFormRef = ref(null);
 const _transfer = ref();
-
 const transferLinesColumns = computed(() => [
     {
         label: t('ticketList.id'),
@@ -86,76 +85,74 @@ const handleRowClick = (row) => {
         transferFormRef.value.transferSales(ticketId);
     }
 };
-
-onMounted(() => (_transfer.value = $props.transfer));
 </script>
 
 <template>
-    <QPopupProxy ref="QPopupProxyRef" data-cy="ticketTransferPopup">
-        <QCard class="q-px-md" style="display: flex; width: 80vw">
-            <QTable
-                :rows="transfer.sales"
-                :columns="transferLinesColumns"
-                :title="t('Sales to transfer')"
-                row-key="id"
-                :pagination="{ rowsPerPage: 0 }"
-                class="full-width q-mt-md"
-                :no-data-label="t('globals.noResults')"
-            >
-                <template #body-cell-quantity="{ row }">
-                    <QTd @click.stop>
-                        <VnInput
-                            v-model.number="row.quantity"
-                            :clearable="false"
-                            style="max-width: 60px"
-                        />
-                    </QTd>
-                </template>
-            </QTable>
-            <QSeparator vertical spaced />
-            <QTable
-                v-if="transfer.lastActiveTickets"
-                :rows="transfer.lastActiveTickets"
-                :columns="destinationTicketColumns"
-                :title="t('Destination ticket')"
-                row-key="id"
-                class="full-width q-mt-md"
-                @row-click="(_, row) => handleRowClick(row)"
-            >
-                <template #body-cell-address="{ row }">
-                    <QTd @click.stop>
-                        <span>
-                            {{ row.nickname }}
-                            {{ row.name }}
-                            {{ row.street }}
-                            {{ row.postalCode }}
-                            {{ row.city }}
-                        </span>
-                        <QTooltip>
-                            {{ row.nickname }}
-                            {{ row.name }}
-                            {{ row.street }}
-                            {{ row.postalCode }}
-                            {{ row.city }}
-                        </QTooltip>
-                    </QTd>
-                </template>
+    <QTable
+        :rows="transfer.sales"
+        :columns="transferLinesColumns"
+        :title="t('Sales to transfer')"
+        row-key="id"
+        :pagination="{ rowsPerPage: 0 }"
+        class="full-width q-mt-md"
+        :no-data-label="t('globals.noResults')"
+    >
+        <template #body-cell-quantity="{ row }">
+            <QTd @click.stop>
+                <VnInput
+                    v-model.number="row.quantity"
+                    :clearable="false"
+                    style="max-width: 60px"
+                />
+            </QTd>
+        </template>
+    </QTable>
+    <QSeparator vertical spaced />
+    <QTable
+        v-if="transfer.lastActiveTickets"
+        :rows="transfer.lastActiveTickets"
+        :columns="destinationTicketColumns"
+        :title="t('Destination ticket')"
+        row-key="id"
+        class="full-width q-mt-md"
+        @row-click="(_, row) => handleRowClick(row)"
+        :no-data-label="t('globals.noResults')"
+        :pagination="{ rowsPerPage: 0 }"
+    >
+        <template #body-cell-address="{ row }">
+            <QTd @click.stop>
+                <span>
+                    {{ row.nickname }}
+                    {{ row.name }}
+                    {{ row.street }}
+                    {{ row.postalCode }}
+                    {{ row.city }}
+                </span>
+                <QTooltip>
+                    {{ row.nickname }}
+                    {{ row.name }}
+                    {{ row.street }}
+                    {{ row.postalCode }}
+                    {{ row.city }}
+                </QTooltip>
+            </QTd>
+        </template>
 
-                <template #no-data>
-                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-                </template>
-                <template #bottom>
-                    <TicketTransferForm ref="transferFormRef" v-bind="$props" />
-                </template>
-            </QTable>
-        </QCard>
-    </QPopupProxy>
+        <template #no-data>
+            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+        </template>
+        <template #bottom>
+            <TicketTransferForm ref="transferFormRef" v-bind="$props" />
+        </template>
+    </QTable>
 </template>
-
+<style lang="scss">
+.q-table__bottom.row.items-center.q-table__bottom--nodata {
+    border-top: none;
+}
+</style>
 <i18n>
 es:
     Sales to transfer: Líneas a transferir
     Destination ticket: Ticket destinatario
-    Transfer to ticket: Transferir a ticket
-    New ticket: Nuevo ticket
 </i18n>
diff --git a/src/pages/Ticket/Card/TicketTransferProxy.vue b/src/pages/Ticket/Card/TicketTransferProxy.vue
new file mode 100644
index 000000000..3f3f018df
--- /dev/null
+++ b/src/pages/Ticket/Card/TicketTransferProxy.vue
@@ -0,0 +1,54 @@
+<script setup>
+import { ref } from 'vue';
+import TicketTransfer from './TicketTransfer.vue';
+import Split from './TicketSplit.vue';
+const emit = defineEmits(['ticketTransfered']);
+
+const $props = defineProps({
+    mana: {
+        type: Number,
+        default: null,
+    },
+    newPrice: {
+        type: Number,
+        default: 0,
+    },
+    transfer: {
+        type: Object,
+        default: () => {},
+    },
+    ticket: {
+        type: [Array, Object],
+        default: () => {},
+    },
+    split: {
+        type: Boolean,
+        default: false,
+    },
+});
+
+const popupProxyRef = ref(null);
+const splitRef = ref(null);
+const transferRef = ref(null);
+</script>
+
+<template>
+    <QPopupProxy ref="popupProxyRef" data-cy="ticketTransferPopup">
+        <div class="flex row items-center q-ma-lg" v-if="$props.split">
+            <Split
+                ref="splitRef"
+                @splitSelectedRows="splitSelectedRows"
+                :ticket="$props.ticket"
+            />
+        </div>
+
+        <div v-else>
+            <TicketTransfer
+                ref="transferRef"
+                :ticket="$props.ticket"
+                :sales="$props.sales"
+                :transfer="$props.transfer"
+            />
+        </div>
+    </QPopupProxy>
+</template>
diff --git a/src/pages/Ticket/Card/components/split.js b/src/pages/Ticket/Card/components/split.js
new file mode 100644
index 000000000..afa1d5cd6
--- /dev/null
+++ b/src/pages/Ticket/Card/components/split.js
@@ -0,0 +1,22 @@
+import axios from 'axios';
+import notifyResults from 'src/utils/notifyResults';
+
+export default async function (data, date) {
+    const reducedData = data.reduce((acc, item) => {
+        const existing = acc.find(({ ticketFk }) => ticketFk === item.id);
+        if (existing) {
+            existing.sales.push(item.saleFk);
+        } else {
+            acc.push({ ticketFk: item.id, sales: [item.saleFk], date });
+        }
+        return acc;
+    }, []);
+
+    const promises = reducedData.map((params) => axios.post(`Tickets/split`, params));
+
+    const results = await Promise.allSettled(promises);
+
+    notifyResults(results, 'ticketFk');
+
+    return results;
+}
diff --git a/src/pages/Ticket/Negative/TicketLackDetail.vue b/src/pages/Ticket/Negative/TicketLackDetail.vue
new file mode 100644
index 000000000..dcf835d03
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackDetail.vue
@@ -0,0 +1,198 @@
+<script setup>
+import { computed, onMounted, onUnmounted, ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+import ChangeQuantityDialog from './components/ChangeQuantityDialog.vue';
+import ChangeStateDialog from './components/ChangeStateDialog.vue';
+import ChangeItemDialog from './components/ChangeItemDialog.vue';
+import TicketTransferProxy from '../Card/TicketTransferProxy.vue';
+import FetchData from 'src/components/FetchData.vue';
+import { useStateStore } from 'stores/useStateStore';
+import { useState } from 'src/composables/useState';
+
+import { useRoute } from 'vue-router';
+import TicketLackTable from './TicketLackTable.vue';
+import VnPopupProxy from 'src/components/common/VnPopupProxy.vue';
+import ItemProposalProxy from 'src/pages/Item/components/ItemProposalProxy.vue';
+
+import { useQuasar } from 'quasar';
+const quasar = useQuasar();
+const { t } = useI18n();
+const editableStates = ref([]);
+const stateStore = useStateStore();
+const tableRef = ref();
+const changeItemDialogRef = ref(null);
+const changeStateDialogRef = ref(null);
+const changeQuantityDialogRef = ref(null);
+const showProposalDialog = ref(false);
+const showChangeQuantityDialog = ref(false);
+const selectedRows = ref([]);
+const route = useRoute();
+onMounted(() => {
+    stateStore.rightDrawer = false;
+});
+onUnmounted(() => {
+    stateStore.rightDrawer = true;
+});
+
+const entityId = computed(() => route.params.id);
+const item = ref({});
+
+const itemProposalSelected = ref(null);
+const reload = async () => {
+    tableRef.value.tableRef.reload();
+};
+defineExpose({ reload });
+const filter = computed(() => ({
+    scopeDays: route.query.days,
+    showType: true,
+    alertLevelCode: 'FREE',
+    date: Date.vnNew(),
+    warehouseFk: useState().getUser().value.warehouseFk,
+}));
+const itemProposalEvt = (data) => {
+    const { itemProposal } = data;
+    itemProposalSelected.value = itemProposal;
+    reload();
+};
+
+function onBuysFetched(data) {
+    Object.assign(item.value, data[0]);
+}
+const showItemProposal = () => {
+    quasar
+        .dialog({
+            component: ItemProposalProxy,
+            componentProps: {
+                itemLack: tableRef.value.itemLack,
+                replaceAction: true,
+                sales: selectedRows.value,
+            },
+        })
+        .onOk(itemProposalEvt);
+};
+</script>
+
+<template>
+    <FetchData
+        url="States/editableStates"
+        @on-fetch="(data) => (editableStates = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Items/${entityId}/getCard`"
+        :fields="['longName']"
+        @on-fetch="(data) => (item = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Buys/latestBuysFilter`"
+        :fields="['longName']"
+        :filter="{ where: { 'i.id': entityId } }"
+        @on-fetch="onBuysFetched"
+        auto-load
+    />
+
+    <TicketLackTable
+        ref="tableRef"
+        :filter="filter"
+        @update:selection="({ value }, _) => (selectedRows = value)"
+    >
+        <template #top-right>
+            <QBtnGroup push class="q-mr-lg" style="column-gap: 1px">
+                <QBtn
+                    data-cy="transferLines"
+                    color="primary"
+                    :disable="!(selectedRows.length === 1)"
+                >
+                    <template #default>
+                        <QIcon name="vn:splitline" />
+                        <QIcon name="vn:ticket" />
+
+                        <QTooltip>{{ t('ticketSale.transferLines') }} </QTooltip>
+                        <TicketTransferProxy
+                            ref="transferFormRef"
+                            split="true"
+                            :ticket="selectedRows"
+                            :transfer="{
+                                sales: selectedRows,
+                                lastActiveTickets: selectedRows.map((row) => row.id),
+                            }"
+                            @ticket-transfered="reload"
+                        ></TicketTransferProxy>
+                    </template>
+                </QBtn>
+                <QBtn
+                    color="primary"
+                    @click="showProposalDialog = true"
+                    :disable="selectedRows.length < 1"
+                    data-cy="itemProposal"
+                >
+                    <QIcon
+                        name="import_export"
+                        class="rotate-90"
+                        @click="showItemProposal"
+                    ></QIcon>
+                    <QTooltip bottom anchor="bottom right">
+                        {{ t('itemProposal') }}
+                    </QTooltip>
+                </QBtn>
+                <VnPopupProxy
+                    data-cy="changeItem"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeItem.title')"
+                >
+                    <template #extraIcon> <QIcon name="vn:item" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeItemDialog
+                            ref="changeItemDialogRef"
+                            @update-item="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy>
+                <VnPopupProxy
+                    data-cy="changeState"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeState.title')"
+                >
+                    <template #extraIcon> <QIcon name="vn:eye" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeStateDialog
+                            ref="changeStateDialogRef"
+                            @update-state="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy>
+                <VnPopupProxy
+                    data-cy="changeQuantity"
+                    icon="sync"
+                    :disable="selectedRows.length < 1"
+                    :tooltip="t('negative.detail.modal.changeQuantity.title')"
+                    @click="showChangeQuantityDialog = true"
+                >
+                    <template #extraIcon> <QIcon name="exposure" /> </template>
+                    <template v-slot="{ popup }">
+                        <ChangeQuantityDialog
+                            ref="changeQuantityDialogRef"
+                            @update-quantity="popup.hide()"
+                            :selected-rows="selectedRows"
+                    /></template>
+                </VnPopupProxy> </QBtnGroup
+        ></template>
+    </TicketLackTable>
+</template>
+<style lang="scss" scoped>
+.list-enter-active,
+.list-leave-active {
+    transition: all 1s ease;
+}
+.list-enter-from,
+.list-leave-to {
+    opacity: 0;
+    background-color: $primary;
+}
+.q-table.q-table__container > div:first-child {
+    border-radius: unset;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/TicketLackFilter.vue b/src/pages/Ticket/Negative/TicketLackFilter.vue
new file mode 100644
index 000000000..3762f453d
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackFilter.vue
@@ -0,0 +1,175 @@
+<script setup>
+import { ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+import FetchData from 'components/FetchData.vue';
+import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+const { t } = useI18n();
+const props = defineProps({
+    dataKey: {
+        type: String,
+        required: true,
+    },
+});
+
+const to = Date.vnNew();
+to.setDate(to.getDate() + 1);
+
+const warehouses = ref();
+const categoriesOptions = ref([]);
+const itemTypesRef = ref(null);
+const itemTypesOptions = ref([]);
+
+const itemTypesFilter = {
+    fields: ['id', 'name', 'categoryFk'],
+    include: 'category',
+    order: 'name ASC',
+    where: {},
+};
+const onCategoryChange = async (categoryFk, search) => {
+    if (!categoryFk) {
+        itemTypesFilter.where.categoryFk = null;
+        delete itemTypesFilter.where.categoryFk;
+    } else {
+        itemTypesFilter.where.categoryFk = categoryFk;
+    }
+    search();
+    await itemTypesRef.value.fetch();
+};
+const emit = defineEmits(['set-user-params']);
+
+const setUserParams = (params) => {
+    emit('set-user-params', params);
+};
+</script>
+
+<template>
+    <FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
+    <FetchData
+        url="ItemCategories"
+        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
+        @on-fetch="(data) => (categoriesOptions = data)"
+        auto-load
+    />
+
+    <FetchData
+        ref="itemTypesRef"
+        url="ItemTypes"
+        :filter="itemTypesFilter"
+        @on-fetch="(data) => (itemTypesOptions = data)"
+        auto-load
+    />
+
+    <VnFilterPanel
+        :data-key="props.dataKey"
+        :search-button="true"
+        @set-user-params="setUserParams"
+    >
+        <template #tags="{ tag, formatFn }">
+            <div class="q-gutter-x-xs">
+                <strong>{{ t(`negative.${tag.label}`) }}</strong>
+                <span>{{ formatFn(tag.value) }}</span>
+            </div>
+        </template>
+        <template #body="{ params, searchFn }">
+            <QList dense class="q-gutter-y-sm q-mt-sm">
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.days"
+                            :label="t('negative.days')"
+                            dense
+                            is-outlined
+                            type="number"
+                            @update:model-value="
+                                (value) => {
+                                    setUserParams(params);
+                                }
+                            "
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.id"
+                            :label="t('negative.id')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.producer"
+                            :label="t('negative.producer')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection>
+                        <VnInput
+                            v-model="params.origen"
+                            :label="t('negative.origen')"
+                            dense
+                            is-outlined
+                        />
+                    </QItemSection> </QItem
+                ><QItem>
+                    <QItemSection v-if="categoriesOptions">
+                        <VnSelect
+                            :label="t('negative.categoryFk')"
+                            v-model="params.categoryFk"
+                            @update:model-value="
+                                ($event) => onCategoryChange($event, searchFn)
+                            "
+                            :options="categoriesOptions"
+                            option-value="id"
+                            option-label="name"
+                            hide-selected
+                            dense
+                            outlined
+                            rounded
+                        /> </QItemSection
+                    ><QItemSection v-else>
+                        <QSkeleton class="full-width" type="QSelect" />
+                    </QItemSection>
+                </QItem>
+                <QItem>
+                    <QItemSection v-if="itemTypesOptions">
+                        <VnSelect
+                            :label="t('negative.type')"
+                            v-model="params.typeFk"
+                            @update:model-value="searchFn()"
+                            :options="itemTypesOptions"
+                            option-value="id"
+                            option-label="name"
+                            hide-selected
+                            dense
+                            outlined
+                            rounded
+                        >
+                            <template #option="scope">
+                                <QItem v-bind="scope.itemProps">
+                                    <QItemSection>
+                                        <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                        <QItemLabel caption>{{
+                                            scope.opt?.category?.name
+                                        }}</QItemLabel>
+                                    </QItemSection>
+                                </QItem>
+                            </template>
+                        </VnSelect> </QItemSection
+                    ><QItemSection v-else>
+                        <QSkeleton class="full-width" type="QSelect" />
+                    </QItemSection>
+                </QItem>
+            </QList>
+        </template>
+    </VnFilterPanel>
+</template>
diff --git a/src/pages/Ticket/Negative/TicketLackList.vue b/src/pages/Ticket/Negative/TicketLackList.vue
new file mode 100644
index 000000000..d1e8b823a
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackList.vue
@@ -0,0 +1,227 @@
+<script setup>
+import { computed, ref, reactive } from 'vue';
+import { useI18n } from 'vue-i18n';
+import { useStateStore } from 'stores/useStateStore';
+import VnTable from 'components/VnTable/VnTable.vue';
+import { onBeforeMount } from 'vue';
+import { dashIfEmpty, toDate, toHour } from 'src/filters';
+import { useRouter } from 'vue-router';
+import { useState } from 'src/composables/useState';
+import { useRole } from 'src/composables/useRole';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import RightMenu from 'src/components/common/RightMenu.vue';
+import TicketLackFilter from './TicketLackFilter.vue';
+onBeforeMount(() => {
+    stateStore.$state.rightDrawer = true;
+});
+const router = useRouter();
+const stateStore = useStateStore();
+const { t } = useI18n();
+const selectedRows = ref([]);
+const tableRef = ref();
+const filterParams = ref({});
+const negativeParams = reactive({
+    days: useRole().likeAny('buyer') ? 2 : 0,
+    warehouseFk: useState().getUser().value.warehouseFk,
+});
+const redirectToCreateView = ({ itemFk }) => {
+    router.push({
+        name: 'NegativeDetail',
+        params: { id: itemFk },
+        query: { days: filterParams.value.days ?? negativeParams.days },
+    });
+};
+const columns = computed(() => [
+    {
+        name: 'date',
+        align: 'center',
+        label: t('negative.date'),
+        format: ({ timed }) => toDate(timed),
+        sortable: true,
+        cardVisible: true,
+        isId: true,
+        columnFilter: {
+            component: 'date',
+        },
+    },
+    {
+        columnClass: 'shrink',
+        name: 'timed',
+        align: 'center',
+        label: t('negative.timed'),
+        format: ({ timed }) => toHour(timed),
+        sortable: true,
+        cardVisible: true,
+        columnFilter: {
+            component: 'time',
+        },
+    },
+    {
+        name: 'itemFk',
+        align: 'center',
+        label: t('negative.id'),
+        format: ({ itemFk }) => itemFk,
+        sortable: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'longName',
+        align: 'center',
+        label: t('negative.longName'),
+        field: ({ longName }) => longName,
+
+        sortable: true,
+        headerStyle: 'width: 350px',
+        cardVisible: true,
+        columnClass: 'expand',
+    },
+    {
+        name: 'producer',
+        align: 'center',
+        label: t('negative.supplier'),
+        field: ({ producer }) => dashIfEmpty(producer),
+        sortable: true,
+        columnClass: 'shrink',
+    },
+    {
+        name: 'inkFk',
+        align: 'center',
+        label: t('negative.colour'),
+        field: ({ inkFk }) => inkFk,
+        sortable: true,
+        cardVisible: true,
+    },
+    {
+        name: 'size',
+        align: 'center',
+        label: t('negative.size'),
+        field: ({ size }) => size,
+        sortable: true,
+        cardVisible: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'category',
+        align: 'center',
+        label: t('negative.origen'),
+        field: ({ category }) => dashIfEmpty(category),
+        sortable: true,
+        cardVisible: true,
+    },
+    {
+        name: 'lack',
+        align: 'center',
+        label: t('negative.lack'),
+        field: ({ lack }) => lack,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+            columnClass: 'shrink',
+        },
+        sortable: true,
+        headerStyle: 'padding-center: 33px',
+        cardVisible: true,
+    },
+    {
+        name: 'tableActions',
+        align: 'center',
+        actions: [
+            {
+                title: t('Open details'),
+                icon: 'edit',
+                action: redirectToCreateView,
+                isPrimary: true,
+            },
+        ],
+    },
+]);
+
+const setUserParams = (params) => {
+    filterParams.value = params;
+};
+</script>
+
+<template>
+    <RightMenu>
+        <template #right-panel>
+            <TicketLackFilter data-key="NegativeList" @set-user-params="setUserParams" />
+        </template>
+    </RightMenu>
+    {{ filterRef }}
+    <VnTable
+        ref="tableRef"
+        data-key="NegativeList"
+        :url="`Tickets/itemLack`"
+        :order="['itemFk DESC, date DESC, timed DESC']"
+        :user-params="negativeParams"
+        auto-load
+        :columns="columns"
+        default-mode="table"
+        :right-search="false"
+        :is-editable="false"
+        :use-model="true"
+        :map-key="false"
+        :row-click="redirectToCreateView"
+        v-model:selected="selectedRows"
+        :create="false"
+        :crud-model="{
+            disableInfiniteScroll: true,
+        }"
+        :table="{
+            'row-key': 'itemFk',
+            selection: 'multiple',
+        }"
+    >
+        <template #column-itemFk="{ row }">
+            <div
+                style="display: flex; justify-content: space-around; align-items: center"
+            >
+                <span @click.stop>{{ row.itemFk }}</span>
+            </div>
+        </template>
+        <template #column-longName="{ row }">
+            <span class="link" @click.stop>
+                {{ row.longName }}
+                <ItemDescriptorProxy :id="row.itemFk" />
+            </span>
+        </template>
+    </VnTable>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+.q-btn-group > .q-btn-item:not(:first-child) {
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/TicketLackTable.vue b/src/pages/Ticket/Negative/TicketLackTable.vue
new file mode 100644
index 000000000..176e8f7ad
--- /dev/null
+++ b/src/pages/Ticket/Negative/TicketLackTable.vue
@@ -0,0 +1,356 @@
+<script setup>
+import FetchedTags from 'components/ui/FetchedTags.vue';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import { computed, ref, watch } from 'vue';
+import { useI18n } from 'vue-i18n';
+import axios from 'axios';
+import FetchData from 'src/components/FetchData.vue';
+import { toDate, toHour } from 'src/filters';
+import useNotify from 'src/composables/useNotify.js';
+import ZoneDescriptorProxy from 'pages/Zone/Card/ZoneDescriptorProxy.vue';
+import { useRoute } from 'vue-router';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+import TicketDescriptorProxy from '../Card/TicketDescriptorProxy.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
+
+const $props = defineProps({
+    filter: {
+        type: Object,
+        default: () => ({}),
+    },
+});
+
+watch(
+    () => $props.filter,
+    (v) => {
+        filterLack.value.where = v;
+        tableRef.value.reload(filterLack);
+    },
+);
+
+const filterLack = ref({
+    include: [
+        {
+            relation: 'workers',
+            scope: {
+                fields: ['id', 'firstName'],
+            },
+        },
+    ],
+    where: { ...$props.filter },
+    order: 'ts.alertLevelCode ASC',
+});
+
+const selectedRows = ref([]);
+const { t } = useI18n();
+const { notify } = useNotify();
+const entityId = computed(() => route.params.id);
+const item = ref({});
+const route = useRoute();
+const columns = computed(() => [
+    {
+        name: 'status',
+        align: 'center',
+        sortable: false,
+        columnClass: 'shrink',
+        columnFilter: false,
+    },
+    {
+        name: 'ticketFk',
+        label: t('negative.detail.ticketFk'),
+        align: 'center',
+        sortable: true,
+        columnFilter: {
+            component: 'input',
+            type: 'number',
+        },
+    },
+    {
+        name: 'shipped',
+        label: t('negative.detail.shipped'),
+        field: 'shipped',
+        align: 'center',
+        format: ({ shipped }) => toDate(shipped),
+        sortable: true,
+        columnFilter: {
+            component: 'date',
+            columnClass: 'shrink',
+        },
+    },
+    {
+        name: 'minTimed',
+        label: t('negative.detail.theoreticalhour'),
+        field: 'minTimed',
+        align: 'center',
+        sortable: true,
+        component: 'time',
+        columnFilter: {},
+    },
+    {
+        name: 'alertLevelCode',
+        label: t('negative.detail.state'),
+        columnFilter: {
+            name: 'alertLevelCode',
+            component: 'select',
+            attrs: {
+                url: 'AlertLevels',
+                fields: ['name', 'code'],
+                optionLabel: 'code',
+                optionValue: 'code',
+            },
+        },
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'zoneName',
+        label: t('negative.detail.zoneName'),
+        field: 'zoneName',
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'nickname',
+        label: t('negative.detail.nickname'),
+        field: 'nickname',
+        align: 'center',
+        sortable: true,
+    },
+    {
+        name: 'quantity',
+        label: t('negative.detail.quantity'),
+        field: 'quantity',
+        sortable: true,
+        component: 'input',
+        type: 'number',
+    },
+]);
+
+const emit = defineEmits(['update:selection']);
+const itemLack = ref(null);
+const fetchItemLack = ref(null);
+const tableRef = ref(null);
+defineExpose({ tableRef, itemLack });
+watch(selectedRows, () => emit('update:selection', selectedRows));
+const getInputEvents = ({ col, ...rows }) => ({
+    'update:modelValue': () => saveChange(col.name, rows),
+    'keyup.enter': () => saveChange(col.name, rows),
+});
+const saveChange = async (field, { row }) => {
+    try {
+        switch (field) {
+            case 'alertLevelCode':
+                await axios.post(`Tickets/state`, {
+                    ticketFk: row.ticketFk,
+                    code: row[field],
+                });
+                break;
+
+            case 'quantity':
+                await axios.post(`Sales/${row.saleFk}/updateQuantity`, {
+                    quantity: +row.quantity,
+                });
+                break;
+        }
+        notify('globals.dataSaved', 'positive');
+        fetchItemLack.value.fetch();
+    } catch (err) {
+        console.error('Error saving changes', err);
+        f;
+    }
+};
+
+function onBuysFetched(data) {
+    Object.assign(item.value, data[0]);
+}
+</script>
+
+<template>
+    <FetchData
+        ref="fetchItemLack"
+        :url="`Tickets/itemLack`"
+        :params="{ id: entityId }"
+        @on-fetch="(data) => (itemLack = data[0])"
+        auto-load
+    />
+    <FetchData
+        :url="`Items/${entityId}/getCard`"
+        :fields="['longName']"
+        @on-fetch="(data) => (item = data)"
+        auto-load
+    />
+    <FetchData
+        :url="`Buys/latestBuysFilter`"
+        :fields="['longName']"
+        :filter="{ where: { 'i.id': entityId } }"
+        @on-fetch="onBuysFetched"
+        auto-load
+    />
+    <VnTable
+        ref="tableRef"
+        data-key="NegativeItem"
+        :map-key="false"
+        :url="`Tickets/itemLack/${entityId}`"
+        :columns="columns"
+        auto-load
+        :create="false"
+        :create-as-dialog="false"
+        :use-model="true"
+        :filter="filterLack"
+        :order="['ts.alertLevelCode ASC']"
+        :table="{
+            'row-key': 'id',
+            selection: 'multiple',
+        }"
+        dense
+        :is-editable="true"
+        :row-click="false"
+        :right-search="false"
+        :right-search-icon="false"
+        v-model:selected="selectedRows"
+        :disable-option="{ card: true }"
+    >
+        <template #top-left>
+            <div style="display: flex; align-items: center" v-if="itemLack">
+                <!-- <VnImg :id="itemLack.itemFk" class="rounded image-wrapper"></VnImg> -->
+                <div class="flex column" style="align-items: center">
+                    <QBadge
+                        ref="badgeLackRef"
+                        class="q-ml-xs"
+                        text-color="white"
+                        :color="itemLack.lack === 0 ? 'positive' : 'negative'"
+                        :label="itemLack.lack"
+                    />
+                </div>
+                <div class="flex column left" style="align-items: flex-start">
+                    <QBtn flat class="link text-blue">
+                        {{ item?.longName ?? item.name }}
+                        <ItemDescriptorProxy :id="entityId" />
+                        <FetchedTags class="q-ml-md" :item="item" :columns="7" />
+                    </QBtn>
+                </div>
+            </div>
+        </template>
+        <template #top-right>
+            <slot name="top-right" />
+        </template>
+
+        <template #column-status="{ row }">
+            <QTd style="min-width: 150px">
+                <div class="icon-container">
+                    <QIcon
+                        v-if="row.isBasket"
+                        name="vn:basket"
+                        color="primary"
+                        class="cursor-pointer"
+                        size="xs"
+                    >
+                        <QTooltip>{{ t('negative.detail.isBasket') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasToIgnore"
+                        name="star"
+                        color="primary"
+                        class="cursor-pointer fill-icon"
+                        size="xs"
+                    >
+                        <QTooltip>{{ t('negative.detail.hasToIgnore') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.hasObservation"
+                        name="change_circle"
+                        color="primary"
+                        class="cursor-pointer"
+                        size="xs"
+                    >
+                        <QTooltip>{{
+                            t('negative.detail.hasObservation')
+                        }}</QTooltip> </QIcon
+                    ><QIcon
+                        v-if="row.isRookie"
+                        name="vn:Person"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.isRookie') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.peticionCompra"
+                        name="vn:buyrequest"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.peticionCompra') }}</QTooltip>
+                    </QIcon>
+                    <QIcon
+                        v-if="row.turno"
+                        name="vn:calendar"
+                        size="xs"
+                        color="primary"
+                        class="cursor-pointer"
+                    >
+                        <QTooltip>{{ t('negative.detail.turno') }}</QTooltip>
+                    </QIcon>
+                </div></QTd
+            >
+        </template>
+        <template #column-nickname="{ row }">
+            <span class="link" @click.stop>
+                {{ row.nickname }}
+                <CustomerDescriptorProxy :id="row.customerId" />
+            </span>
+        </template>
+        <template #column-ticketFk="{ row }">
+            <span class="q-pa-sm link">
+                {{ row.id }}
+                <TicketDescriptorProxy :id="row.id" />
+            </span>
+        </template>
+        <template #column-alertLevelCode="props">
+            <VnSelect
+                url="States/editableStates"
+                auto-load
+                hide-selected
+                option-value="id"
+                option-label="name"
+                v-model="props.row.alertLevelCode"
+                v-on="getInputEvents(props)"
+            />
+        </template>
+
+        <template #column-zoneName="{ row }">
+            <span class="link">{{ row.zoneName }}</span>
+            <ZoneDescriptorProxy :id="row.zoneFk" />
+        </template>
+        <template #column-quantity="props">
+            <VnInputNumber
+                v-model.number="props.row.quantity"
+                v-on="getInputEvents(props)"
+            ></VnInputNumber>
+        </template>
+    </VnTable>
+</template>
+<style lang="scss" scoped>
+.icon-container {
+    display: grid;
+    grid-template-columns: repeat(3, 0.2fr);
+    row-gap: 5px; /* Ajusta el espacio entre los iconos según sea necesario */
+}
+.icon-container > * {
+    width: 100%;
+    height: auto;
+}
+.list-enter-active,
+.list-leave-active {
+    transition: all 1s ease;
+}
+.list-enter-from,
+.list-leave-to {
+    opacity: 0;
+    background-color: $primary;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeItemDialog.vue b/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
new file mode 100644
index 000000000..e419b85c0
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeItemDialog.vue
@@ -0,0 +1,90 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import notifyResults from 'src/utils/notifyResults';
+const emit = defineEmits(['update-item']);
+
+const showChangeItemDialog = ref(false);
+const newItem = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+
+const updateItem = async () => {
+    try {
+        showChangeItemDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
+            axios.post(`Sales/replaceItem`, {
+                saleFk,
+                substitutionFk: newItem.value,
+                quantity,
+            }),
+        );
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'saleFk');
+        emit('update-item', newItem.value);
+    } catch (err) {
+        console.error('Error updating item:', err);
+        return err;
+    }
+};
+</script>
+
+<template>
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            {{ showChangeItemDialog }}
+            <span>{{ $t('negative.detail.modal.changeItem.title') }}</span>
+            <VnSelect
+                url="Items/WithName"
+                :fields="['id', 'name']"
+                :sort-by="['id DESC']"
+                :options="items"
+                option-label="name"
+                option-value="id"
+                v-model="newItem"
+            >
+            </VnSelect>
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newItem"
+                @click="updateItem"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue b/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
new file mode 100644
index 000000000..2e9aac4f0
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeQuantityDialog.vue
@@ -0,0 +1,84 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnInput from 'src/components/common/VnInput.vue';
+import notifyResults from 'src/utils/notifyResults';
+
+const showChangeQuantityDialog = ref(false);
+const newQuantity = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+const emit = defineEmits(['update-quantity']);
+const updateQuantity = async () => {
+    try {
+        showChangeQuantityDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ saleFk }) =>
+            axios.post(`Sales/${saleFk}/updateQuantity`, {
+                saleFk,
+                quantity: +newQuantity.value,
+            }),
+        );
+
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'saleFk');
+
+        emit('update-quantity', newQuantity.value);
+    } catch (err) {
+        return err;
+    }
+};
+</script>
+
+<template>
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            <span>{{ $t('negative.detail.modal.changeQuantity.title') }}</span>
+            <VnInput
+                type="number"
+                :min="0"
+                :label="$t('negative.detail.modal.changeQuantity.placeholder')"
+                v-model="newQuantity"
+            />
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newQuantity || newQuantity < 0"
+                @click="updateQuantity"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/Negative/components/ChangeStateDialog.vue b/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
new file mode 100644
index 000000000..1acc7e0ef
--- /dev/null
+++ b/src/pages/Ticket/Negative/components/ChangeStateDialog.vue
@@ -0,0 +1,91 @@
+<script setup>
+import { ref } from 'vue';
+import axios from 'axios';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import FetchData from 'components/FetchData.vue';
+import notifyResults from 'src/utils/notifyResults';
+
+const emit = defineEmits(['update-state']);
+const editableStates = ref([]);
+const showChangeStateDialog = ref(false);
+const newState = ref(null);
+const $props = defineProps({
+    selectedRows: {
+        type: Array,
+        default: () => [],
+    },
+});
+const updateState = async () => {
+    try {
+        showChangeStateDialog.value = true;
+        const rowsToUpdate = $props.selectedRows.map(({ id }) =>
+            axios.post(`Tickets/state`, {
+                ticketFk: id,
+                code: newState.value,
+            }),
+        );
+        const result = await Promise.allSettled(rowsToUpdate);
+        notifyResults(result, 'ticketFk');
+
+        emit('update-state', newState.value);
+    } catch (err) {
+        return err;
+    }
+};
+</script>
+
+<template>
+    <FetchData
+        url="States/editableStates"
+        @on-fetch="(data) => (editableStates = data)"
+        auto-load
+    />
+    <QCard class="q-pa-sm">
+        <QCardSection class="row items-center justify-center column items-stretch">
+            <span>{{ $t('negative.detail.modal.changeState.title') }}</span>
+            <VnSelect
+                :label="$t('negative.detail.modal.changeState.placeholder')"
+                v-model="newState"
+                :options="editableStates"
+                option-label="name"
+                option-value="code"
+            />
+        </QCardSection>
+        <QCardActions align="right">
+            <QBtn :label="$t('globals.cancel')" color="primary" flat v-close-popup />
+            <QBtn
+                :label="$t('globals.confirm')"
+                color="primary"
+                :disable="!newState"
+                @click="updateState"
+                unelevated
+                autofocus
+            /> </QCardActions
+    ></QCard>
+</template>
+
+<style lang="scss" scoped>
+.list {
+    max-height: 100%;
+    padding: 15px;
+    width: 100%;
+}
+
+.grid-style-transition {
+    transition:
+        transform 0.28s,
+        background-color 0.28s;
+}
+
+#true {
+    background-color: $positive;
+}
+
+#false {
+    background-color: $negative;
+}
+
+div.q-dialog__inner > div {
+    max-width: fit-content !important;
+}
+</style>
diff --git a/src/pages/Ticket/TicketFuture.vue b/src/pages/Ticket/TicketFuture.vue
index 0d216bed4..92911cd25 100644
--- a/src/pages/Ticket/TicketFuture.vue
+++ b/src/pages/Ticket/TicketFuture.vue
@@ -1,24 +1,22 @@
 <script setup>
-import { onMounted, ref, computed, reactive } from 'vue';
+import { ref, computed, reactive, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 
-import FetchData from 'components/FetchData.vue';
-import VnInput from 'src/components/common/VnInput.vue';
-import VnSelect from 'src/components/common/VnSelect.vue';
 import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
 import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
 import TicketFutureFilter from './TicketFutureFilter.vue';
 
 import { dashIfEmpty, toCurrency } from 'src/filters';
 import { useVnConfirm } from 'composables/useVnConfirm';
-import { useArrayData } from 'composables/useArrayData';
 import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import useNotify from 'src/composables/useNotify.js';
 import { useState } from 'src/composables/useState';
 import { toDateTimeFormat } from 'src/filters/date.js';
 import axios from 'axios';
+import TicketProblems from 'src/components/TicketProblems.vue';
 
 const state = useState();
 const { t } = useI18n();
@@ -26,214 +24,126 @@ const { openConfirmationModal } = useVnConfirm();
 const { notify } = useNotify();
 const user = state.getUser();
 
-const itemPackingTypesOptions = ref([]);
 const selectedTickets = ref([]);
-
-const exprBuilder = (param, value) => {
-    switch (param) {
-        case 'id':
-            return { id: value };
-        case 'futureId':
-            return { futureId: value };
-        case 'liters':
-            return { liters: value };
-        case 'lines':
-            return { lines: value };
-        case 'iptColFilter':
-            return { ipt: { like: `%${value}%` } };
-        case 'futureIptColFilter':
-            return { futureIpt: { like: `%${value}%` } };
-        case 'totalWithVat':
-            return { totalWithVat: value };
-    }
-};
-
+const vnTableRef = ref({});
+const originElRef = ref(null);
+const destinationElRef = ref(null);
 const userParams = reactive({
     futureScopeDays: Date.vnNew().toISOString(),
     originScopeDays: Date.vnNew().toISOString(),
     warehouseFk: user.value.warehouseFk,
 });
 
-const arrayData = useArrayData('FutureTickets', {
-    url: 'Tickets/getTicketsFuture',
-    userParams: userParams,
-    exprBuilder: exprBuilder,
-});
-const { store } = arrayData;
-
-const params = reactive({
-    futureScopeDays: Date.vnNew(),
-    originScopeDays: Date.vnNew(),
-    warehouseFk: user.value.warehouseFk,
-});
-
-const applyColumnFilter = async (col) => {
-    const paramKey = col.columnFilter?.filterParamKey || col.field;
-    params[paramKey] = col.columnFilter.filterValue;
-    await arrayData.addFilter({ params });
-};
-
-const getInputEvents = (col) => {
-    return col.columnFilter.type === 'select'
-        ? { 'update:modelValue': () => applyColumnFilter(col) }
-        : {
-              'keyup.enter': () => applyColumnFilter(col),
-          };
-};
-
-const tickets = computed(() => store.data);
-
 const ticketColumns = computed(() => [
     {
-        label: t('futureTickets.problems'),
+        label: '',
         name: 'problems',
+        headerClass: 'horizontal-separator',
         align: 'left',
-        columnFilter: null,
+        columnFilter: false,
     },
     {
         label: t('advanceTickets.ticketId'),
-        name: 'ticketId',
+        name: 'id',
         align: 'center',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            filterParamKey: 'id',
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('futureTickets.shipped'),
         name: 'shipped',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
+        columnFilter: false,
+        headerClass: 'horizontal-separator',
     },
     {
+        align: 'center',
+        class: 'shrink',
         label: t('advanceTickets.ipt'),
         name: 'ipt',
-        field: 'ipt',
-        align: 'left',
-        sortable: true,
         columnFilter: {
-            component: VnSelect,
-            filterParamKey: 'iptColFilter',
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
+            component: 'select',
             attrs: {
-                options: itemPackingTypesOptions.value,
-                'option-value': 'code',
-                'option-label': 'description',
-                dense: true,
+                url: 'itemPackingTypes',
+                fields: ['code', 'description'],
+                where: { isActive: true },
+                optionValue: 'code',
+                optionLabel: 'description',
+                inWhere: false,
             },
         },
-        format: (val) => dashIfEmpty(val),
+        format: (row, dashIfEmpty) => dashIfEmpty(row.ipt),
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('ticketList.state'),
         name: 'state',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
+        columnFilter: false,
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('advanceTickets.liters'),
         name: 'liters',
-        field: 'liters',
         align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        headerClass: 'horizontal-separator',
     },
     {
         label: t('advanceTickets.import'),
-        field: 'import',
         name: 'import',
         align: 'left',
-        sortable: true,
+        headerClass: 'horizontal-separator',
+        columnFilter: false,
+        format: (row) => toCurrency(row.totalWithVat),
     },
     {
         label: t('futureTickets.availableLines'),
         name: 'lines',
         field: 'lines',
         align: 'center',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.lines),
     },
     {
         label: t('advanceTickets.futureId'),
         name: 'futureId',
-        align: 'left',
-        sortable: true,
-        columnFilter: {
-            component: VnInput,
-            type: 'text',
-            filterValue: null,
-            filterParamKey: 'futureId',
-            event: getInputEvents,
-            attrs: {
-                dense: true,
-            },
-        },
+        align: 'center',
+        headerClass: 'horizontal-separator vertical-separator ',
+        columnClass: 'vertical-separator',
     },
     {
         label: t('futureTickets.futureShipped'),
         name: 'futureShipped',
         align: 'left',
-        sortable: true,
-        columnFilter: null,
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        columnFilter: false,
+        format: (row) => toDateTimeFormat(row.futureShipped),
     },
-
     {
+        align: 'center',
         label: t('advanceTickets.futureIpt'),
+        class: 'shrink',
         name: 'futureIpt',
-        field: 'futureIpt',
-        align: 'left',
-        sortable: true,
         columnFilter: {
-            component: VnSelect,
-            filterParamKey: 'futureIptColFilter',
-            type: 'select',
-            filterValue: null,
-            event: getInputEvents,
+            component: 'select',
             attrs: {
-                options: itemPackingTypesOptions.value,
-                'option-value': 'code',
-                'option-label': 'description',
-                dense: true,
+                url: 'itemPackingTypes',
+                fields: ['code', 'description'],
+                where: { isActive: true },
+                optionValue: 'code',
+                optionLabel: 'description',
             },
         },
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        format: (row, dashIfEmpty) => dashIfEmpty(row.futureIpt),
     },
     {
         label: t('advanceTickets.futureState'),
         name: 'futureState',
         align: 'right',
-        sortable: true,
-        columnFilter: null,
-        format: (val) => dashIfEmpty(val),
+        headerClass: 'horizontal-separator',
+        class: 'expand',
+        columnFilter: false,
+        format: (row, dashIfEmpty) => dashIfEmpty(row.futureState),
     },
 ]);
 
@@ -258,26 +168,51 @@ const moveTicketsFuture = async () => {
     await axios.post('Tickets/merge', params);
     notify(t('advanceTickets.moveTicketSuccess'), 'positive');
     selectedTickets.value = [];
-    arrayData.fetch({ append: false });
+    vnTableRef.value.reload();
 };
-onMounted(async () => {
-    await arrayData.fetch({ append: false });
-});
+
+watch(
+    () => vnTableRef.value.tableRef?.$el,
+    ($el) => {
+        if (!$el) return;
+        const head = $el.querySelector('thead');
+        const firstRow = $el.querySelector('thead > tr');
+
+        const newRow = document.createElement('tr');
+        destinationElRef.value = document.createElement('th');
+        originElRef.value = document.createElement('th');
+
+        newRow.classList.add('bg-header');
+        destinationElRef.value.classList.add('text-uppercase', 'color-vn-label');
+        originElRef.value.classList.add('text-uppercase', 'color-vn-label');
+
+        destinationElRef.value.setAttribute('colspan', '7');
+        originElRef.value.setAttribute('colspan', '9');
+
+        originElRef.value.textContent = `${t('advanceTickets.origin')}`;
+        destinationElRef.value.textContent = `${t('advanceTickets.destination')}`;
+
+        newRow.append(destinationElRef.value, originElRef.value);
+        head.insertBefore(newRow, firstRow);
+    },
+    { once: true, inmmediate: true },
+);
+
+watch(
+    () => vnTableRef.value.params,
+    () => {
+        if (originElRef.value && destinationElRef.value) {
+            destinationElRef.value.textContent = `${t('advanceTickets.origin')}`;
+            originElRef.value.textContent = `${t('advanceTickets.destination')}`;
+        }
+    },
+    { deep: true },
+);
 </script>
 
 <template>
-    <FetchData
-        url="itemPackingTypes"
-        :filter="{
-            fields: ['code', 'description'],
-            order: 'description ASC',
-            where: { isActive: true },
-        }"
-        auto-load
-        @on-fetch="(data) => (itemPackingTypesOptions = data)"
-    />
     <VnSearchbar
-        data-key="FutureTickets"
+        data-key="futureTicket"
         :label="t('Search ticket')"
         :info="t('futureTickets.searchInfo')"
     />
@@ -293,7 +228,7 @@ onMounted(async () => {
                         t(`futureTickets.moveTicketDialogSubtitle`, {
                             selectedTickets: selectedTickets.length,
                         }),
-                        moveTicketsFuture
+                        moveTicketsFuture,
                     )
                 "
             >
@@ -305,235 +240,135 @@ onMounted(async () => {
     </VnSubToolbar>
     <RightMenu>
         <template #right-panel>
-            <TicketFutureFilter data-key="FutureTickets" />
+            <TicketFutureFilter data-key="futureTickets" />
         </template>
     </RightMenu>
     <QPage class="column items-center q-pa-md">
-        <QTable
-            :rows="tickets"
+        <VnTable
+            data-key="futureTickets"
+            ref="vnTableRef"
+            url="Tickets/getTicketsFuture"
+            search-url="futureTickets"
+            :user-params="userParams"
+            :limit="0"
             :columns="ticketColumns"
-            row-key="id"
-            selection="multiple"
+            :table="{
+                'row-key': '$index',
+                selection: 'multiple',
+            }"
             v-model:selected="selectedTickets"
-            :pagination="{ rowsPerPage: 0 }"
-            :no-data-label="t('globals.noResults')"
-            style="max-width: 99%"
+            :right-search="false"
+            auto-load
+            :disable-option="{ card: true }"
         >
-            <template #header="props">
-                <QTr>
-                    <QTh class="horizontal-separator" />
-                    <QTh
-                        class="horizontal-separator text-uppercase color-vn-label"
-                        colspan="8"
-                        translate
-                    >
-                        {{ t('advanceTickets.origin') }}
-                    </QTh>
-                    <QTh
-                        class="horizontal-separator text-uppercase color-vn-label"
-                        colspan="4"
-                        translate
-                    >
-                        {{ t('advanceTickets.destination') }}
-                    </QTh>
-                </QTr>
-                <QTr>
-                    <QTh>
-                        <QCheckbox v-model="props.selected" />
-                    </QTh>
-                    <QTh
-                        v-for="(col, index) in ticketColumns"
-                        :key="index"
-                        :class="{ 'vertical-separator': col.name === 'futureId' }"
-                    >
-                        {{ col.label }}
-                    </QTh>
-                </QTr>
-            </template>
-            <template #top-row="{ cols }">
-                <QTr>
-                    <QTd />
-                    <QTd
-                        v-for="(col, index) in cols"
-                        :key="index"
-                        style="max-width: 100px"
-                    >
-                        <component
-                            :is="col.columnFilter.component"
-                            v-if="col.columnFilter"
-                            v-model="col.columnFilter.filterValue"
-                            v-bind="col.columnFilter.attrs"
-                            v-on="col.columnFilter.event(col)"
-                            dense
-                        />
-                    </QTd>
-                </QTr>
-            </template>
-            <template #header-cell-availableLines="{ col }">
-                <QTh class="vertical-separator">
-                    {{ col.label }}
-                </QTh>
-            </template>
-            <template #body-cell-problems="{ row }">
-                <QTd class="q-gutter-x-xs">
+            <template #column-problems="{ row }">
+                <span class="q-gutter-x-xs">
                     <QIcon
-                        v-if="row.isTaxDataChecked === 0"
+                        v-if="row.futureAgencyFk !== row.agencyFk && row.agencyFk"
                         color="primary"
-                        name="vn:no036"
+                        name="vn:agency-term"
                         size="xs"
+                        class="q-mr-xs"
                     >
-                        <QTooltip>
-                            {{ t('futureTickets.noVerified') }}
+                        <QTooltip class="column">
+                            <span>
+                                {{
+                                    t('advanceTickets.originAgency', {
+                                        agency: row.futureAgency,
+                                    })
+                                }}
+                            </span>
+                            <span>
+                                {{
+                                    t('advanceTickets.destinationAgency', {
+                                        agency: row.agency,
+                                    })
+                                }}
+                            </span>
                         </QTooltip>
                     </QIcon>
-                    <QIcon
-                        v-if="row.hasTicketRequest"
-                        color="primary"
-                        name="vn:buyrequest"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.purchaseRequest') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.itemShortage"
-                        color="primary"
-                        name="vn:unavailable"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('ticketSale.noVisible') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.isFreezed"
-                        color="primary"
-                        name="vn:frozen"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.clientFrozen') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon v-if="row.risk" color="primary" name="vn:risk" size="xs">
-                        <QTooltip>
-                            {{ t('futureTickets.risk') }}: {{ row.risk }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasComponentLack"
-                        color="primary"
-                        name="vn:components"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.componentLack') }}
-                        </QTooltip>
-                    </QIcon>
-                    <QIcon
-                        v-if="row.hasRounding"
-                        color="primary"
-                        name="sync_problem"
-                        size="xs"
-                    >
-                        <QTooltip>
-                            {{ t('futureTickets.rounding') }}
-                        </QTooltip>
-                    </QIcon>
-                </QTd>
+                    <TicketProblems :row />
+                </span>
             </template>
-            <template #body-cell-ticketId="{ row }">
-                <QTd>
-                    <QBtn flat class="link">
-                        {{ row.id }}
-                        <TicketDescriptorProxy :id="row.id" />
-                    </QBtn>
-                </QTd>
+            <template #column-id="{ row }">
+                <QBtn flat class="link" @click.stop dense>
+                    {{ row.id }}
+                    <TicketDescriptorProxy :id="row.id" />
+                </QBtn>
             </template>
-            <template #body-cell-shipped="{ row }">
-                <QTd class="shipped">
-                    <QBadge
-                        text-color="black"
-                        :color="getDateQBadgeColor(row.shipped)"
-                        class="q-ma-none"
-                    >
-                        {{ toDateTimeFormat(row.shipped) }}
-                    </QBadge>
-                </QTd>
+            <template #column-shipped="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="getDateQBadgeColor(row.shipped)"
+                    class="q-ma-none"
+                >
+                    {{ toDateTimeFormat(row.shipped) }}
+                </QBadge>
             </template>
-            <template #body-cell-state="{ row }">
-                <QTd>
-                    <QBadge
-                        text-color="black"
-                        :color="row.classColor"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ row.state }}
-                    </QBadge>
-                </QTd>
+            <template #column-state="{ row }">
+                <QBadge
+                    v-if="row.state"
+                    text-color="black"
+                    :color="row.classColor"
+                    class="q-ma-none"
+                    dense
+                >
+                    {{ row.state }}
+                </QBadge>
+                <span v-else> {{ dashIfEmpty(row.state) }}</span>
             </template>
-            <template #body-cell-import="{ row }">
-                <QTd>
-                    <QBadge
-                        :text-color="
-                            totalPriceColor(row.totalWithVat) === 'warning'
-                                ? 'black'
-                                : 'white'
-                        "
-                        :color="totalPriceColor(row.totalWithVat)"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ toCurrency(row.totalWithVat || 0) }}
-                    </QBadge>
-                </QTd>
+            <template #column-import="{ row }">
+                <QBadge
+                    :text-color="
+                        totalPriceColor(row.totalWithVat) === 'warning'
+                            ? 'black'
+                            : 'white'
+                    "
+                    :color="totalPriceColor(row.totalWithVat)"
+                    class="q-ma-none"
+                    dense
+                >
+                    {{ toCurrency(row.totalWithVat || 0) }}
+                </QBadge>
             </template>
-            <template #body-cell-futureId="{ row }">
-                <QTd class="vertical-separator">
-                    <QBtn flat class="link" dense>
-                        {{ row.futureId }}
-                        <TicketDescriptorProxy :id="row.futureId" />
-                    </QBtn>
-                </QTd>
+            <template #column-futureId="{ row }">
+                <QBtn flat class="link" @click.stop dense>
+                    {{ row.futureId }}
+                    <TicketDescriptorProxy :id="row.futureId" />
+                </QBtn>
             </template>
-            <template #body-cell-futureShipped="{ row }">
-                <QTd class="shipped">
-                    <QBadge
-                        text-color="black"
-                        :color="getDateQBadgeColor(row.futureShipped)"
-                        class="q-ma-none"
-                    >
-                        {{ toDateTimeFormat(row.futureShipped) }}
-                    </QBadge>
-                </QTd>
+            <template #column-futureShipped="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="getDateQBadgeColor(row.futureShipped)"
+                    class="q-ma-none"
+                >
+                    {{ toDateTimeFormat(row.futureShipped) }}
+                </QBadge>
             </template>
-            <template #body-cell-futureState="{ row }">
-                <QTd>
-                    <QBadge
-                        text-color="black"
-                        :color="row.futureClassColor"
-                        class="q-ma-none"
-                        dense
-                    >
-                        {{ row.futureState }}
-                    </QBadge>
-                </QTd>
+            <template #column-futureState="{ row }">
+                <QBadge
+                    text-color="black"
+                    :color="row.futureClassColor"
+                    class="q-mr-xs"
+                    dense
+                >
+                    {{ row.futureState }}
+                </QBadge>
             </template>
-        </QTable>
+        </VnTable>
     </QPage>
 </template>
 
 <style scoped lang="scss">
-.shipped {
-    min-width: 132px;
-}
-.vertical-separator {
+:deep(.vertical-separator) {
     border-left: 4px solid white !important;
 }
 
-.horizontal-separator {
+:deep(.horizontal-separator) {
+    border-top: 4px solid white !important;
+}
+:deep(.horizontal-bottom-separator) {
     border-bottom: 4px solid white !important;
 }
 </style>
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index d28b0af71..64e060a39 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -12,7 +12,7 @@ import axios from 'axios';
 import { onMounted } from 'vue';
 
 const { t } = useI18n();
-const props = defineProps({
+defineProps({
     dataKey: {
         type: String,
         required: true,
@@ -58,7 +58,7 @@ onMounted(async () => {
         auto-load
     />
     <VnFilterPanel
-        :data-key="props.dataKey"
+        :data-key
         :un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
     >
         <template #tags="{ tag, formatFn }">
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index f11b32c3a..cdbb22d9b 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -23,6 +23,8 @@ ticketSale:
     hasComponentLack: Component lack
     ok: Ok
     more: More
+    transferLines: Transfer lines(no basket)/ Split
+    transferBasket: Some row selected is basket
 advanceTickets:
     preparation: Preparation
     origin: Origin
@@ -188,7 +190,6 @@ ticketList:
     accountPayment: Account payment
     sendDocuware: Set delivered and send delivery note(s) to the tablet
     addPayment: Add payment
-    date: Date
     company: Company
     amount: Amount
     reference: Reference
@@ -202,9 +203,89 @@ ticketList:
     creditCard: Credit card
     transfers: Transfers
     province: Province
-    warehouse: Warehouse
-    hour: Hour
     closure: Closure
     toLines: Go to lines
     addressNickname: Address nickname
     ref: Reference
+    rounding: Rounding
+    noVerifiedData: No verified data
+    purchaseRequest: Purchase request
+    notVisible: Not visible
+    clientFrozen: Client frozen
+    componentLack: Component lack
+negative:
+    hour: Hour
+    id: Id Article
+    longName: Article
+    supplier: Supplier
+    colour: Colour
+    size: Size
+    origen: Origin
+    value: Negative
+    itemFk: Article
+    producer: Producer
+    warehouse: Warehouse
+    warehouseFk: Warehouse
+    category: Category
+    categoryFk: Family
+    type: Type
+    typeFk: Type
+    lack: Negative
+    inkFk: inkFk
+    timed: timed
+    date: Date
+    minTimed: minTimed
+    negativeAction: Negative
+    totalNegative: Total negatives
+    days: Days
+    buttonsUpdate:
+        item: Item
+        state: State
+        quantity: Quantity
+    modalOrigin:
+        title: Update negatives
+        question: Select a state to update
+    modalSplit:
+        title: Confirm split selected
+        question: Select a state to update
+    detail:
+        saleFk: Sale
+        itemFk: Article
+        ticketFk: Ticket
+        code: Code
+        nickname: Alias
+        name: Name
+        zoneName: Agency name
+        shipped: Date
+        theoreticalhour: Theoretical hour
+        agName: Agency
+        quantity: Quantity
+        alertLevelCode: Group state
+        state: State
+        peticionCompra: Ticket request
+        isRookie: Is rookie
+        turno: Turn line
+        isBasket: Basket
+        hasObservation: Has substitution
+        hasToIgnore: VIP
+        modal:
+            changeItem:
+                title: Update item reference
+                placeholder: New item
+            changeState:
+                title: Update tickets state
+                placeholder: New state
+            changeQuantity:
+                title: Update tickets quantity
+                placeholder: New quantity
+            split:
+                title: Are you sure you want to split selected tickets?
+                subTitle: Confirm split action
+            handleSplited:
+                title: Handle splited  tickets
+                subTitle: Confirm date and agency
+    split:
+        ticket: Old ticket
+        newTicket: New ticket
+        status: Result
+        message: Message
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index 945da8367..75d3c6a2b 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -127,6 +127,8 @@ ticketSale:
     ok: Ok
     more: Más
     address: Consignatario
+    transferLines: Transferir líneas(no cesta)/ Separar
+    transferBasket: No disponible para una cesta
     size: Medida
 ticketComponents:
     serie: Serie
@@ -213,3 +215,84 @@ ticketList:
     toLines: Ir a lineas
     addressNickname: Alias consignatario
     ref: Referencia
+negative:
+    hour: Hora
+    id: Id Articulo
+    longName: Articulo
+    supplier: Productor
+    colour: Color
+    size: Medida
+    origen: Origen
+    value: Negativo
+    warehouseFk: Almacen
+    producer: Producer
+    category: Categoría
+    categoryFk: Familia
+    typeFk: Familia
+    warehouse: Almacen
+    lack: Negativo
+    inkFk: Color
+    timed: Hora
+    date: Fecha
+    minTimed: Hora
+    type: Tipo
+    negativeAction: Negativo
+    totalNegative: Total negativos
+    days: Rango de dias
+    buttonsUpdate:
+        item: artículo
+        state: Estado
+        quantity: Cantidad
+    modalOrigin:
+        title: Actualizar negativos
+        question: Seleccione un estado para guardar
+    modalSplit:
+        title: Confirmar acción de split
+        question: Selecciona un estado
+    detail:
+        saleFk: Línea
+        itemFk: Artículo
+        ticketFk: Ticket
+        code: code
+        nickname: Alias
+        name: Nombre
+        zoneName: Agencia
+        shipped: F. envío
+        theoreticalhour: Hora teórica
+        agName: Agencia
+        quantity: Cantidad
+        alertLevelCode: Estado agrupado
+        state: Estado
+        peticionCompra: Petición compra
+        isRookie: Cliente nuevo
+        turno: Linea turno
+        isBasket: Cesta
+        hasObservation: Tiene sustitución
+        hasToIgnore: VIP
+        modal:
+            changeItem:
+                title: Actualizar referencia artículo
+                placeholder: Nuevo articulo
+            changeState:
+                title: Actualizar estado
+                placeholder: Nuevo estado
+            changeQuantity:
+                title: Actualizar cantidad
+                placeholder: Nueva cantidad
+            split:
+                title: ¿Seguro de separar los tickets seleccionados?
+                subTitle: Confirma separar tickets seleccionados
+            handleSplited:
+                title: Gestionar tickets spliteados
+                subTitle: Confir fecha y agencia
+    split:
+        ticket: Ticket viejo
+        newTicket: Ticket nuevo
+        status: Estado
+        message: Mensaje
+    rounding: Redondeo
+    noVerifiedData: Sin datos comprobados
+    purchaseRequest: Petición de compra
+    notVisible: No visible
+    clientFrozen: Cliente congelado
+    componentLack: Faltan componentes
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index 4b9aa28ed..b1adc8126 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnInputDate from 'components/common/VnInputDate.vue';
+import VnInputTime from 'components/common/VnInputTime.vue';
 
 const route = useRoute();
 const { t } = useI18n();
@@ -53,7 +54,16 @@ const warehousesOptionsIn = ref([]);
                 <VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
                 <VnInputDate v-model="data.landed" :label="t('globals.landed')" />
             </VnRow>
-
+            <VnRow>
+                <VnInputDate
+                    v-model="data.availabled"
+                    :label="t('travel.summary.availabled')" 
+                    />
+                <VnInputTime
+                    v-model="data.availabled"
+                    :label="t('travel.summary.availabledHour')"
+                />
+            </VnRow>
             <VnRow>
                 <VnSelect
                     :label="t('globals.warehouseOut')"
@@ -101,10 +111,3 @@ const warehousesOptionsIn = ref([]);
         </template>
     </FormModel>
 </template>
-
-<i18n>
-es:
-    raidDays: El travel se desplaza automáticamente cada día para estar desde hoy al número de días indicado. Si se deja vacio no se moverá
-en:
-    raidDays: The travel adjusts itself daily to match the number of days set, starting from today. If left blank, it won’t move
-</i18n>
diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue
index 445675b90..cb09eafd6 100644
--- a/src/pages/Travel/Card/TravelCard.vue
+++ b/src/pages/Travel/Card/TravelCard.vue
@@ -1,43 +1,13 @@
 <script setup>
 import TravelDescriptor from './TravelDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
-
-const userFilter = {
-    fields: [
-        'id',
-        'ref',
-        'shipped',
-        'landed',
-        'totalEntries',
-        'warehouseInFk',
-        'warehouseOutFk',
-        'cargoSupplierFk',
-        'agencyModeFk',
-        'isRaid',
-        'isDelivered',
-        'isReceived',
-    ],
-    include: [
-        {
-            relation: 'warehouseIn',
-            scope: {
-                fields: ['name'],
-            },
-        },
-        {
-            relation: 'warehouseOut',
-            scope: {
-                fields: ['name'],
-            },
-        },
-    ],
-};
+import filter from './TravelFilter.js';
 </script>
 <template>
     <VnCardBeta
         data-key="Travel"
-        base-url="Travels"
+        url="Travels"
         :descriptor="TravelDescriptor"
-        :user-filter="userFilter"
+        :filter="filter"
     />
 </template>
diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue
index 72acf91b8..922f89f33 100644
--- a/src/pages/Travel/Card/TravelDescriptor.vue
+++ b/src/pages/Travel/Card/TravelDescriptor.vue
@@ -32,7 +32,6 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
 
 <template>
     <CardDescriptor
-        module="Travel"
         :url="`Travels/${entityId}`"
         :title="data.title"
         :subtitle="data.subtitle"
diff --git a/src/pages/Travel/Card/TravelFilter.js b/src/pages/Travel/Card/TravelFilter.js
index f5f4520fd..05436834f 100644
--- a/src/pages/Travel/Card/TravelFilter.js
+++ b/src/pages/Travel/Card/TravelFilter.js
@@ -11,6 +11,7 @@ export default {
         'agencyModeFk',
         'isRaid',
         'daysInForward',
+        'availabled',
     ],
     include: [
         {
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index 16d42f104..9f9552611 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -10,6 +10,8 @@ import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'
 import FetchData from 'src/components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import { toDate, toCurrency, toCelsius } from 'src/filters';
+import { toDateTimeFormat } from 'src/filters/date.js';
+import { dashIfEmpty } from 'src/filters';
 import axios from 'axios';
 import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
 
@@ -333,6 +335,12 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
                 <VnLv :label="t('globals.reference')" :value="travel.ref" />
                 <VnLv label="m³" :value="travel.m3" />
                 <VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
+                <VnLv
+                    :label="t('travel.summary.availabled')"
+                    :value="
+                        dashIfEmpty(toDateTimeFormat(travel.availabled))
+                    "
+                />
             </QCard>
             <QCard class="full-width">
                 <VnTitle :text="t('travel.summary.entries')" />
diff --git a/src/pages/Travel/Card/TravelThermographs.vue b/src/pages/Travel/Card/TravelThermographs.vue
index 2946c8814..2376bd6d2 100644
--- a/src/pages/Travel/Card/TravelThermographs.vue
+++ b/src/pages/Travel/Card/TravelThermographs.vue
@@ -217,7 +217,7 @@ const removeThermograph = async (id) => {
             icon="add"
             color="primary"
             @click="redirectToThermographForm('create')"
-            shortcut="+"
+            v-shortcut="'+'"
         />
         <QTooltip class="text-no-wrap">
             {{ t('Add thermograph') }}
diff --git a/src/pages/Travel/ExtraCommunityFilter.vue b/src/pages/Travel/ExtraCommunityFilter.vue
index 371f06340..29d342334 100644
--- a/src/pages/Travel/ExtraCommunityFilter.vue
+++ b/src/pages/Travel/ExtraCommunityFilter.vue
@@ -113,7 +113,7 @@ warehouses();
                         <template #append>
                             <QBtn
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 flat
                                 dense
                                 size="12px"
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index e90c01be2..b227afcb2 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -10,6 +10,9 @@ import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
 import TravelFilter from './TravelFilter.vue';
 import VnInputNumber from 'src/components/common/VnInputNumber.vue';
 import VnSection from 'src/components/common/VnSection.vue';
+import VnInputTime from 'src/components/common/VnInputTime.vue';
+import VnInputDate from 'src/components/common/VnInputDate.vue';
+import { toDateTimeFormat } from 'src/filters/date';
 
 const { viewSummary } = useSummaryDialog();
 const router = useRouter();
@@ -167,6 +170,17 @@ const columns = computed(() => [
         cardVisible: true,
         create: true,
     },
+    {
+        align: 'left',
+        name: 'availabled',
+        label: t('travel.summary.availabled'),
+        component: 'input',
+        columnClass: 'expand',
+        columnField: {
+            component: null,
+        },
+        format: (row, dashIfEmpty) => dashIfEmpty(toDateTimeFormat(row.availabled)),
+    },
     {
         align: 'right',
         label: '',
@@ -269,6 +283,16 @@ const columns = computed(() => [
                         :class="{ 'is-active': row.isReceived }"
                     />
                 </template>
+                <template #more-create-dialog="{ data }">
+                    <VnInputDate
+                        v-model="data.availabled"
+                        :label="t('travel.summary.availabled')"
+                    />
+                    <VnInputTime
+                        v-model="data.availabled"
+                        :label="t('travel.summary.availabledHour')"
+                    />
+                </template>
                 <template #moreFilterPanel="{ params }">
                     <VnInputNumber
                         :label="t('params.scopeDays')"
diff --git a/src/pages/Wagon/Card/WagonCard.vue b/src/pages/Wagon/Card/WagonCard.vue
index ed6c83778..644a30ffa 100644
--- a/src/pages/Wagon/Card/WagonCard.vue
+++ b/src/pages/Wagon/Card/WagonCard.vue
@@ -2,5 +2,5 @@
 import VnCard from 'components/common/VnCard.vue';
 </script>
 <template>
-    <VnCard data-key="Wagon" base-url="Wagons" />
+    <VnCard data-key="Wagon" url="Wagons" />
 </template>
diff --git a/src/pages/Wagon/Type/WagonTypeList.vue b/src/pages/Wagon/Type/WagonTypeList.vue
index c0943c58e..4c0b078a7 100644
--- a/src/pages/Wagon/Type/WagonTypeList.vue
+++ b/src/pages/Wagon/Type/WagonTypeList.vue
@@ -96,7 +96,13 @@ async function remove(row) {
         >
         </VnTable>
         <QPageSticky :offset="[18, 18]">
-            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
+            <QBtn
+                @click.stop="dialog.show()"
+                color="primary"
+                fab
+                icon="add"
+                v-shortcut="'+'"
+            >
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Create new Wagon type')"
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
index 6a13e3f39..fcf0f0369 100644
--- a/src/pages/Worker/Card/WorkerBasicData.vue
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -1,6 +1,5 @@
 <script setup>
-import { ref, onBeforeMount } from 'vue';
-import { useRoute } from 'vue-router';
+import { ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnInputDate from 'src/components/common/VnInputDate.vue';
 import FetchData from 'components/FetchData.vue';
@@ -11,18 +10,13 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 
 const { t } = useI18n();
+const form = ref();
 const educationLevels = ref([]);
 const countries = ref([]);
 const maritalStatus = [
     { code: 'M', name: t('Married') },
     { code: 'S', name: t('Single') },
 ];
-const advancedSummary = ref({});
-
-onBeforeMount(async () => {
-    advancedSummary.value =
-        (await useAdvancedSummary('Workers', +useRoute().params.id)) ?? {};
-});
 </script>
 <template>
     <FetchData
@@ -38,14 +32,15 @@ onBeforeMount(async () => {
         auto-load
     />
     <FormModel
-        :filter="{ where: { id: +$route.params.id } }"
-        url="Workers/summary"
+        ref="form"
         :url-update="`Workers/${$route.params.id}`"
         auto-load
         model="Worker"
         @on-fetch="
             async (data) => {
-                Object.assign(data, advancedSummary);
+                Object.assign(data, (await useAdvancedSummary('Workers', data.id)) ?? {});
+                await $nextTick();
+                if (form) form.hasChanges = false;
             }
         "
     >
diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue
index 5ca95a1a4..df4616011 100644
--- a/src/pages/Worker/Card/WorkerCalendar.vue
+++ b/src/pages/Worker/Card/WorkerCalendar.vue
@@ -1,7 +1,8 @@
 <script setup>
-import { nextTick, ref, watch } from 'vue';
+import { nextTick, ref, watch, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter } from 'vue-router';
+import { useAcl } from 'src/composables/useAcl';
 
 import WorkerCalendarFilter from 'pages/Worker/Card/WorkerCalendarFilter.vue';
 import FetchData from 'components/FetchData.vue';
@@ -9,10 +10,17 @@ import WorkerCalendarItem from 'pages/Worker/Card/WorkerCalendarItem.vue';
 import RightMenu from 'src/components/common/RightMenu.vue';
 
 import axios from 'axios';
+import VnNotes from 'src/components/ui/VnNotes.vue';
+import { useStateStore } from 'src/stores/useStateStore';
+const stateStore = useStateStore();
 
 const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
+const acl = useAcl();
+const canSeeNotes = computed(() =>
+    acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
+);
 const workerIsFreelance = ref();
 const WorkerFreelanceRef = ref();
 const workerCalendarFilterRef = ref(null);
@@ -26,6 +34,10 @@ const contractHolidays = ref(null);
 const yearHolidays = ref(null);
 const eventsMap = ref({});
 const festiveEventsMap = ref({});
+const saveUrl = ref();
+const body = {
+    workerFk: route.params.id,
+};
 
 const onFetchActiveContract = (data) => {
     if (!data) return;
@@ -67,7 +79,7 @@ const onFetchAbsences = (data) => {
                     name: holidayName,
                     isFestive: true,
                 },
-                true
+                true,
             );
         });
     }
@@ -146,7 +158,7 @@ watch(
     async () => {
         await nextTick();
         await activeContractRef.value.fetch();
-    }
+    },
 );
 watch([year, businessFk], () => refreshData());
 </script>
@@ -181,6 +193,20 @@ watch([year, businessFk], () => refreshData());
             />
         </template>
     </RightMenu>
+    <Teleport to="#st-data" v-if="stateStore.isSubToolbarShown() && canSeeNotes">
+        <VnNotes
+            :just-input="true"
+            :url="`Workers/${route.params.id}/business`"
+            :filter="{ fields: ['id', 'notes', 'workerFk'] }"
+            :save-url="saveUrl"
+            @on-fetch="
+                (data) => {
+                    saveUrl = `Businesses/${data.id}`;
+                }
+            "
+            :body="body"
+        />
+    </Teleport>
     <QPage class="column items-center">
         <QCard v-if="workerIsFreelance">
             <QCardSection class="text-center">
diff --git a/src/pages/Worker/Card/WorkerCalendarFilter.vue b/src/pages/Worker/Card/WorkerCalendarFilter.vue
index 67b7df907..48fc4094b 100644
--- a/src/pages/Worker/Card/WorkerCalendarFilter.vue
+++ b/src/pages/Worker/Card/WorkerCalendarFilter.vue
@@ -180,8 +180,6 @@ const yearList = ref(generateYears());
                     :is-clearable="false"
                 />
             </QItemSection>
-        </QItem>
-        <QItem>
             <QItemSection>
                 <VnSelect
                     :label="t('Contract')"
diff --git a/src/pages/Worker/Card/WorkerCard.vue b/src/pages/Worker/Card/WorkerCard.vue
index 1ada15a33..3b7a62025 100644
--- a/src/pages/Worker/Card/WorkerCard.vue
+++ b/src/pages/Worker/Card/WorkerCard.vue
@@ -3,5 +3,10 @@ import WorkerDescriptor from './WorkerDescriptor.vue';
 import VnCardBeta from 'src/components/common/VnCardBeta.vue';
 </script>
 <template>
-    <VnCardBeta data-key="Worker" custom-url="Workers/summary" :descriptor="WorkerDescriptor" />
+    <VnCardBeta
+        data-key="Worker"
+        url="Workers/summary"
+        :id-in-where="true"
+        :descriptor="WorkerDescriptor"
+    />
 </template>
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index d87fd4a54..de3f634e2 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -10,7 +10,7 @@ import axios from 'axios';
 import VnImg from 'src/components/ui/VnImg.vue';
 import EditPictureForm from 'components/EditPictureForm.vue';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 
 const $props = defineProps({
     id: {
@@ -21,7 +21,7 @@ const $props = defineProps({
     dataKey: {
         type: String,
         required: false,
-        default: 'workerData',
+        default: 'Worker',
     },
 });
 const image = ref(null);
@@ -50,9 +50,8 @@ const handlePhotoUpdated = (evt = false) => {
 <template>
     <CardDescriptor
         ref="cardDescriptorRef"
-        module="Worker"
         :data-key="dataKey"
-        url="Workers/descriptor"
+        url="Workers/summary"
         :filter="{ where: { id: entityId } }"
         title="user.nickname"
         @on-fetch="getIsExcluded"
@@ -152,7 +151,7 @@ const handlePhotoUpdated = (evt = false) => {
                 <QBtn
                     :to="{
                         name: 'AccountCard',
-                        params: { id: entity.user.id },
+                        params: { id: entity.user?.id },
                     }"
                     size="md"
                     icon="face"
diff --git a/src/pages/Worker/Card/WorkerDescriptorProxy.vue b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
index 43deb7821..a142570f9 100644
--- a/src/pages/Worker/Card/WorkerDescriptorProxy.vue
+++ b/src/pages/Worker/Card/WorkerDescriptorProxy.vue
@@ -12,11 +12,6 @@ const $props = defineProps({
 
 <template>
     <QPopupProxy>
-        <WorkerDescriptor
-            v-if="$props.id"
-            :id="$props.id"
-            :summary="WorkerSummary"
-            data-key="workerDescriptorProxy"
-        />
+        <WorkerDescriptor v-if="$props.id" :id="$props.id" :summary="WorkerSummary" />
     </QPopupProxy>
 </template>
diff --git a/src/pages/Worker/Card/WorkerFormation.vue b/src/pages/Worker/Card/WorkerFormation.vue
index 6fd5a4eae..e8680f7dd 100644
--- a/src/pages/Worker/Card/WorkerFormation.vue
+++ b/src/pages/Worker/Card/WorkerFormation.vue
@@ -94,6 +94,7 @@ const columns = computed(() => [
         align: 'left',
         name: 'hasDiploma',
         label: t('worker.formation.tableVisibleColumns.hasDiploma'),
+        component: 'checkbox',
         create: true,
     },
     {
@@ -118,7 +119,7 @@ const columns = computed(() => [
         :url="`Workers/${entityId}/trainingCourse`"
         :url-create="`Workers/${entityId}/trainingCourse`"
         save-url="TrainingCourses/crud"
-        :filter="courseFilter"
+        :user-filter="courseFilter"
         :create="{
             urlCreate: 'trainingCourses',
             title: t('Create training course'),
diff --git a/src/pages/Worker/Card/WorkerMedical.vue b/src/pages/Worker/Card/WorkerMedical.vue
index c220df76a..c04f6496b 100644
--- a/src/pages/Worker/Card/WorkerMedical.vue
+++ b/src/pages/Worker/Card/WorkerMedical.vue
@@ -3,11 +3,23 @@ import { ref, computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import VnTable from 'components/VnTable/VnTable.vue';
+import { dashIfEmpty } from 'src/filters';
 const tableRef = ref();
 const { t } = useI18n();
 const route = useRoute();
 const entityId = computed(() => route.params.id);
 
+const centerFilter = {
+    include: [
+        {
+            relation: 'center',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+    ],
+};
+
 const columns = [
     {
         align: 'left',
@@ -36,6 +48,9 @@ const columns = [
             url: 'medicalCenters',
             fields: ['id', 'name'],
         },
+        format: (row, dashIfEmpty) => {
+            return dashIfEmpty(row.center?.name);
+        },
     },
     {
         align: 'left',
@@ -84,6 +99,7 @@ const columns = [
         ref="tableRef"
         data-key="WorkerMedical"
         :url="`Workers/${entityId}/medicalReview`"
+        :user-filter="centerFilter"
         save-url="MedicalReviews/crud"
         :create="{
             urlCreate: 'medicalReviews',
diff --git a/src/pages/Worker/Card/WorkerOperator.vue b/src/pages/Worker/Card/WorkerOperator.vue
index cdacc72c0..6faeefe67 100644
--- a/src/pages/Worker/Card/WorkerOperator.vue
+++ b/src/pages/Worker/Card/WorkerOperator.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
 import FetchData from 'components/FetchData.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
@@ -19,6 +19,7 @@ const trainsData = ref([]);
 const machinesData = ref([]);
 const route = useRoute();
 const routeId = computed(() => route.params.id);
+const selected = ref([]);
 
 const initialData = computed(() => {
     return {
@@ -41,6 +42,21 @@ async function insert() {
     await axios.post('Operators', initialData.value);
     crudModelRef.value.reload();
 }
+
+watch(
+    () => crudModelRef.value?.formData,
+    (formData) => {
+        if (formData && formData.length) {
+            if (JSON.stringify(selected.value) !== JSON.stringify(formData)) {
+                selected.value = formData;
+            }
+        } else if (selected.value.length > 0) {
+            selected.value = [];
+        }
+    },
+    { immediate: true, deep: true }
+);
+
 </script>
 
 <template>
@@ -67,6 +83,7 @@ async function insert() {
             :data-required="{ workerFk: route.params.id }"
             ref="crudModelRef"
             search-url="operator"
+            :selected="selected"
             auto-load
         >
             <template #body="{ rows }">
diff --git a/src/pages/Worker/Card/WorkerPda.vue b/src/pages/Worker/Card/WorkerPda.vue
index f6cb92aac..47e13cf6d 100644
--- a/src/pages/Worker/Card/WorkerPda.vue
+++ b/src/pages/Worker/Card/WorkerPda.vue
@@ -101,7 +101,7 @@ function reloadData() {
                                 openConfirmationModal(
                                     t(`Remove PDA`),
                                     t('Do you want to remove this PDA?'),
-                                    () => deallocatePDA(row.deviceProductionFk)
+                                    () => deallocatePDA(row.deviceProductionFk),
                                 )
                             "
                         >
@@ -114,7 +114,13 @@ function reloadData() {
             </template>
         </VnPaginate>
         <QPageSticky :offset="[18, 18]">
-            <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
+            <QBtn
+                @click.stop="dialog.show()"
+                color="primary"
+                fab
+                icon="add"
+                v-shortcut="'+'"
+            >
                 <QDialog ref="dialog">
                     <FormModelPopup
                         :title="t('Add new device')"
diff --git a/src/pages/Worker/Card/WorkerPit.vue b/src/pages/Worker/Card/WorkerPit.vue
index d9ac1a02c..3de60d6a0 100644
--- a/src/pages/Worker/Card/WorkerPit.vue
+++ b/src/pages/Worker/Card/WorkerPit.vue
@@ -222,7 +222,7 @@ const deleteRelative = async (id) => {
                                 color="primary"
                                 flat
                                 icon="add"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 style="flex: 0"
                                 data-cy="addRelative"
                             />
diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 992f6ec71..78c5dfd82 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -9,7 +9,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
 import VnUserLink from 'src/components/ui/VnUserLink.vue';
 import VnTitle from 'src/components/common/VnTitle.vue';
 import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
 import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
 
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index c580e5202..7def6e94c 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -64,17 +64,17 @@ const selectedCalendarDates = ref([]);
 // Date formateada para bindear al componente QDate
 const selectedDateFormatted = ref(toDateString(defaultDate.value));
 
-const arrayData = useArrayData('workerData');
+const arrayData = useArrayData('Worker');
 const acl = useAcl();
 const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear());
 const worker = computed(() => arrayData.store?.data);
 const canSend = computed(() =>
-    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }])
+    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]),
 );
 const canUpdate = computed(() =>
     acl.hasAny([
         { model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' },
-    ])
+    ]),
 );
 const isHimself = computed(() => user.value.id === Number(route.params.id));
 
@@ -100,7 +100,7 @@ const getHeaderFormattedDate = (date) => {
 };
 
 const formattedWeekTotalHours = computed(() =>
-    secondsToHoursMinutes(weekTotalHours.value)
+    secondsToHoursMinutes(weekTotalHours.value),
 );
 
 const onInputChange = async (date) => {
@@ -320,7 +320,7 @@ const getFinishTime = () => {
     today.setHours(0, 0, 0, 0);
 
     let todayInWeek = weekDays.value.find(
-        (day) => day.dated.getTime() === today.getTime()
+        (day) => day.dated.getTime() === today.getTime(),
     );
 
     if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
@@ -472,7 +472,7 @@ onMounted(async () => {
                         openConfirmationModal(
                             t('Send time control email'),
                             t('Are you sure you want to send it?'),
-                            resendEmail
+                            resendEmail,
                         )
                     "
                 >
@@ -561,7 +561,7 @@ onMounted(async () => {
                                 @show-worker-time-form="
                                     showWorkerTimeForm(
                                         { id: hour.id, entryCode: hour.direction },
-                                        'edit'
+                                        'edit',
                                     )
                                 "
                                 class="hour-chip"
@@ -577,7 +577,7 @@ onMounted(async () => {
                             </span>
                             <QBtn
                                 icon="add_circle"
-                                shortcut="+"
+                                v-shortcut="'+'"
                                 flat
                                 color="primary"
                                 class="fill-icon cursor-pointer"
diff --git a/src/pages/Department/Card/DepartmentBasicData.vue b/src/pages/Worker/Department/Card/DepartmentBasicData.vue
similarity index 73%
rename from src/pages/Department/Card/DepartmentBasicData.vue
rename to src/pages/Worker/Department/Card/DepartmentBasicData.vue
index b13aed2d3..66210be7b 100644
--- a/src/pages/Department/Card/DepartmentBasicData.vue
+++ b/src/pages/Worker/Department/Card/DepartmentBasicData.vue
@@ -1,27 +1,16 @@
 <script setup>
-import { useRoute } from 'vue-router';
-import { useI18n } from 'vue-i18n';
-
 import FormModel from 'components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
-
-const route = useRoute();
-const { t } = useI18n();
 </script>
 <template>
-    <FormModel
-        :url="`Departments/${route.params.id}`"
-        model="department"
-        auto-load
-        class="full-width"
-    >
+    <FormModel model="Department" auto-load class="full-width">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
-                    :label="t('globals.name')"
+                    :label="$t('globals.name')"
                     v-model="data.name"
                     :rules="validate('globals.name')"
                     clearable
@@ -29,33 +18,33 @@ const { t } = useI18n();
                 />
                 <VnInput
                     v-model="data.code"
-                    :label="t('globals.code')"
+                    :label="$t('globals.code')"
                     :rules="validate('globals.code')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnInput
-                    :label="t('department.chat')"
+                    :label="$t('department.chat')"
                     v-model="data.chatName"
                     :rules="validate('department.chat')"
                     clearable
                 />
                 <VnInput
                     v-model="data.notificationEmail"
-                    :label="t('globals.params.email')"
+                    :label="$t('globals.params.email')"
                     :rules="validate('globals.params.email')"
                     clearable
                 />
             </VnRow>
             <VnRow>
                 <VnSelectWorker
-                    :label="t('department.bossDepartment')"
+                    :label="$t('department.bossDepartment')"
                     v-model="data.workerFk"
                     :rules="validate('department.bossDepartment')"
                 />
                 <VnSelect
-                    :label="t('department.selfConsumptionCustomer')"
+                    :label="$t('department.selfConsumptionCustomer')"
                     v-model="data.clientFk"
                     url="Clients"
                     option-value="id"
@@ -67,11 +56,11 @@ const { t } = useI18n();
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.telework')"
+                    :label="$t('department.telework')"
                     v-model="data.isTeleworking"
                 />
                 <QCheckbox
-                    :label="t('department.notifyOnErrors')"
+                    :label="$t('department.notifyOnErrors')"
                     v-model="data.hasToMistake"
                     :false-value="0"
                     :true-value="1"
@@ -79,17 +68,17 @@ const { t } = useI18n();
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.worksInProduction')"
+                    :label="$t('department.worksInProduction')"
                     v-model="data.isProduction"
                 />
                 <QCheckbox
-                    :label="t('department.hasToRefill')"
+                    :label="$t('department.hasToRefill')"
                     v-model="data.hasToRefill"
                 />
             </VnRow>
             <VnRow>
                 <QCheckbox
-                    :label="t('department.hasToSendMail')"
+                    :label="$t('department.hasToSendMail')"
                     v-model="data.hasToSendMail"
                 />
             </VnRow>
diff --git a/src/pages/Department/Card/DepartmentCard.vue b/src/pages/Worker/Department/Card/DepartmentCard.vue
similarity index 70%
rename from src/pages/Department/Card/DepartmentCard.vue
rename to src/pages/Worker/Department/Card/DepartmentCard.vue
index 4b9fe419c..2e3f11521 100644
--- a/src/pages/Department/Card/DepartmentCard.vue
+++ b/src/pages/Worker/Department/Card/DepartmentCard.vue
@@ -1,13 +1,13 @@
 <script setup>
 import VnCardBeta from 'components/common/VnCardBeta.vue';
-import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
+import DepartmentDescriptor from 'pages/Worker/Department/Card/DepartmentDescriptor.vue';
 </script>
 <template>
     <VnCardBeta
         class="q-pa-md column items-center"
         v-bind="{ ...$attrs }"
         data-key="Department"
-        base-url="Departments"
+        url="Departments"
         :descriptor="DepartmentDescriptor"
     />
 </template>
diff --git a/src/pages/Department/Card/DepartmentDescriptor.vue b/src/pages/Worker/Department/Card/DepartmentDescriptor.vue
similarity index 84%
rename from src/pages/Department/Card/DepartmentDescriptor.vue
rename to src/pages/Worker/Department/Card/DepartmentDescriptor.vue
index b219ccfe1..4b7dfd9b8 100644
--- a/src/pages/Department/Card/DepartmentDescriptor.vue
+++ b/src/pages/Worker/Department/Card/DepartmentDescriptor.vue
@@ -5,7 +5,6 @@ import { useI18n } from 'vue-i18n';
 import { useVnConfirm } from 'composables/useVnConfirm';
 import VnLv from 'src/components/ui/VnLv.vue';
 import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
-import useCardDescription from 'src/composables/useCardDescription';
 
 import axios from 'axios';
 import useNotify from 'src/composables/useNotify.js';
@@ -32,15 +31,6 @@ const entityId = computed(() => {
     return $props.id || route.params.id;
 });
 
-const department = ref();
-
-const data = ref(useCardDescription());
-
-const setData = (entity) => {
-    if (!entity) return;
-    data.value = useCardDescription(entity.name, entity.id);
-};
-
 const removeDepartment = async () => {
     await axios.post(`/Departments/${entityId.value}/removeChild`, entityId.value);
     router.push({ name: 'WorkerDepartment' });
@@ -52,19 +42,10 @@ const { openConfirmationModal } = useVnConfirm();
 <template>
     <CardDescriptor
         ref="DepartmentDescriptorRef"
-        module="Department"
         :url="`Departments/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
         :summary="$props.summary"
         :to-module="{ name: 'WorkerDepartment' }"
-        @on-fetch="
-            (data) => {
-                department = data;
-                setData(data);
-            }
-        "
-        data-key="department"
+        data-key="Department"
     >
         <template #menu="{}">
             <QItem
@@ -74,7 +55,7 @@ const { openConfirmationModal } = useVnConfirm();
                     openConfirmationModal(
                         t('Are you sure you want to delete it?'),
                         t('Delete department'),
-                        removeDepartment
+                        removeDepartment,
                     )
                 "
             >
diff --git a/src/pages/Department/Card/DepartmentDescriptorProxy.vue b/src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue
similarity index 100%
rename from src/pages/Department/Card/DepartmentDescriptorProxy.vue
rename to src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue
diff --git a/src/pages/Department/Card/DepartmentSummary.vue b/src/pages/Worker/Department/Card/DepartmentSummary.vue
similarity index 99%
rename from src/pages/Department/Card/DepartmentSummary.vue
rename to src/pages/Worker/Department/Card/DepartmentSummary.vue
index 3d481601f..3719137e4 100644
--- a/src/pages/Department/Card/DepartmentSummary.vue
+++ b/src/pages/Worker/Department/Card/DepartmentSummary.vue
@@ -27,7 +27,7 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="DepartmentSummary"
+        data-key="Department"
         ref="summary"
         :url="`Departments/${entityId}`"
         class="full-width"
diff --git a/src/pages/Department/Card/DepartmentSummaryDialog.vue b/src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue
similarity index 100%
rename from src/pages/Department/Card/DepartmentSummaryDialog.vue
rename to src/pages/Worker/Department/Card/DepartmentSummaryDialog.vue
diff --git a/src/pages/Worker/WorkerDepartmentTree.vue b/src/pages/Worker/WorkerDepartmentTree.vue
index 9abf4e312..9baf5ee57 100644
--- a/src/pages/Worker/WorkerDepartmentTree.vue
+++ b/src/pages/Worker/WorkerDepartmentTree.vue
@@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useState } from 'src/composables/useState';
 import { useQuasar } from 'quasar';
-import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
+import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
 import CreateDepartmentChild from './CreateDepartmentChild.vue';
 import axios from 'axios';
 import { useRouter } from 'vue-router';
@@ -173,7 +173,7 @@ function handleEvent(type, event, node) {
                             color="primary"
                             flat
                             icon="add"
-                            shortcut="+"
+                            v-shortcut="'+'"
                             class="cursor-pointer"
                             @click.stop="showCreateNodeForm(node.id)"
                         >
diff --git a/src/pages/Zone/Card/ZoneBasicData.vue b/src/pages/Zone/Card/ZoneBasicData.vue
index cbeeff2e9..03013f011 100644
--- a/src/pages/Zone/Card/ZoneBasicData.vue
+++ b/src/pages/Zone/Card/ZoneBasicData.vue
@@ -1,5 +1,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
+import { ref } from 'vue';
+import FetchData from 'components/FetchData.vue';
 import FormModel from 'src/components/FormModel.vue';
 import VnRow from 'components/ui/VnRow.vue';
 import VnInput from 'src/components/common/VnInput.vue';
@@ -7,10 +9,23 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 
 const { t } = useI18n();
+const validAddresses = ref([]);
+const addresses = ref([]);
+
+const setFilteredAddresses = (data) => {
+    const validIds = new Set(validAddresses.value.map((item) => item.addressFk));
+    addresses.value = data.filter((address) => validIds.has(address.id));
+};
 </script>
 
 <template>
-    <FormModel :url="`Zones/${$route.params.id}`" auto-load model="zone">
+    <FetchData
+        url="RoadmapAddresses"
+        auto-load
+        @on-fetch="(data) => (validAddresses = data)"
+    />
+    <FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
+    <FormModel auto-load model="Zone">
         <template #form="{ data, validate }">
             <VnRow>
                 <VnInput
@@ -18,15 +33,15 @@ const { t } = useI18n();
                     :label="t('Name')"
                     clearable
                     v-model="data.name"
+                    :required="true"
                 />
             </VnRow>
-
             <VnRow>
                 <VnSelect
                     v-model="data.agencyModeFk"
                     :rules="validate('zone.agencyModeFk')"
-                     url="AgencyModes/isActive"
-                     :fields="['id', 'name']"
+                    url="AgencyModes/isActive"
+                    :fields="['id', 'name']"
                     :label="t('Agency')"
                     emit-value
                     map-options
@@ -69,7 +84,7 @@ const { t } = useI18n();
                     type="number"
                     min="0"
                 />
-                <VnInputTime v-model="data.hour" :label="t('Closing')" />
+                <VnInputTime v-model="data.hour" :label="t('Closing')" :required="true" />
             </VnRow>
 
             <VnRow>
@@ -78,7 +93,7 @@ const { t } = useI18n();
                     :label="t('Price')"
                     type="number"
                     min="0"
-                    required="true"
+                    :required="true"
                     clearable
                 />
                 <VnInput
@@ -86,7 +101,7 @@ const { t } = useI18n();
                     :label="t('Price optimum')"
                     type="number"
                     min="0"
-                    required="true"
+                    :required="true"
                     clearable
                 />
             </VnRow>
@@ -103,12 +118,14 @@ const { t } = useI18n();
                     v-model="data.addressFk"
                     option-value="id"
                     option-label="nickname"
-                    url="Addresses"
+                    :options="addresses"
                     :fields="['id', 'nickname']"
                     sort-by="id"
                     hide-selected
                     map-options
                     :rules="validate('data.addressFk')"
+                    :filter-options="['id']"
+                    :where="filterWhere"
                 />
             </VnRow>
             <VnRow>
diff --git a/src/pages/Zone/Card/ZoneCard.vue b/src/pages/Zone/Card/ZoneCard.vue
index a470cd5bd..41daff5c0 100644
--- a/src/pages/Zone/Card/ZoneCard.vue
+++ b/src/pages/Zone/Card/ZoneCard.vue
@@ -1,13 +1,12 @@
 <script setup>
-import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import { computed } from 'vue';
 
 import VnCard from 'components/common/VnCard.vue';
 import ZoneDescriptor from './ZoneDescriptor.vue';
 import ZoneFilterPanel from '../ZoneFilterPanel.vue';
+import filter from './ZoneFilter.js';
 
-const { t } = useI18n();
 const route = useRoute();
 const routeName = computed(() => route.name);
 
@@ -19,15 +18,16 @@ function notIsLocations(ifIsFalse, ifIsTrue) {
 
 <template>
     <VnCard
-        data-key="zone"
-        :base-url="notIsLocations('Zones', undefined)"
+        data-key="Zone"
+        :url="notIsLocations('Zones', undefined)"
         :descriptor="ZoneDescriptor"
+        :filter="filter"
         :filter-panel="notIsLocations(ZoneFilterPanel, undefined)"
         :search-data-key="notIsLocations('ZoneList', undefined)"
         :searchbar-props="{
             url: notIsLocations('Zones', 'ZoneLocations'),
-            label: notIsLocations(t('list.searchZone'), t('list.searchLocation')),
-            info: t('list.searchInfo'),
+            label: notIsLocations($t('list.searchZone'), $t('list.searchLocation')),
+            info: $t('list.searchInfo'),
             whereFilter: notIsLocations((value) => {
                 return /^\d+$/.test(value)
                     ? { id: value }
diff --git a/src/pages/Zone/Card/ZoneDescriptor.vue b/src/pages/Zone/Card/ZoneDescriptor.vue
index 8355c219e..27676212e 100644
--- a/src/pages/Zone/Card/ZoneDescriptor.vue
+++ b/src/pages/Zone/Card/ZoneDescriptor.vue
@@ -1,15 +1,14 @@
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } 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 { toTimeFormat } from 'src/filters/date';
 import { toCurrency } from 'filters/index';
 
-import useCardDescription from 'src/composables/useCardDescription';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
+import filter from './ZoneFilter.js';
 
 const $props = defineProps({
     id: {
@@ -20,49 +19,22 @@ const $props = defineProps({
 });
 
 const route = useRoute();
-const { t } = useI18n();
-
-const filter = {
-    include: [
-        {
-            relation: 'agencyMode',
-            scope: {
-                fields: ['name', 'id'],
-            },
-        },
-    ],
-};
-
 const entityId = computed(() => {
     return $props.id || route.params.id;
 });
-
-const data = ref(useCardDescription());
-const setData = (entity) => {
-    data.value = useCardDescription(entity.ref, entity.id);
-};
 </script>
 
 <template>
-    <CardDescriptor
-        module="Zone"
-        :url="`Zones/${entityId}`"
-        :title="data.title"
-        :subtitle="data.subtitle"
-        :filter="filter"
-        @on-fetch="setData"
-        data-key="zoneData"
-    >
+    <CardDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
         <template #menu="{ entity }">
             <ZoneDescriptorMenuItems :zone="entity" />
         </template>
         <template #body="{ entity }">
-            <VnLv :label="t('list.agency')" :value="entity.agencyMode.name" />
-            <VnLv :label="t('zone.closing')" :value="toTimeFormat(entity.hour)" />
-            <VnLv :label="t('zone.travelingDays')" :value="entity.travelingDays" />
-            <VnLv :label="t('list.price')" :value="toCurrency(entity.price)" />
-            <VnLv :label="t('zone.bonus')" :value="toCurrency(entity.bonus)" />
+            <VnLv :label="$t('list.agency')" :value="entity.agencyMode?.name" />
+            <VnLv :label="$t('zone.closing')" :value="toTimeFormat(entity.hour)" />
+            <VnLv :label="$t('zone.travelingDays')" :value="entity.travelingDays" />
+            <VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
+            <VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
         </template>
     </CardDescriptor>
 </template>
-
diff --git a/src/pages/Zone/Card/ZoneEvents.vue b/src/pages/Zone/Card/ZoneEvents.vue
index a5806bab9..1e6debd25 100644
--- a/src/pages/Zone/Card/ZoneEvents.vue
+++ b/src/pages/Zone/Card/ZoneEvents.vue
@@ -78,13 +78,13 @@ const onZoneEventFormClose = () => {
                         {
                             isNewMode: true,
                         },
-                        true
+                        true,
                     )
                 "
                 color="primary"
                 fab
                 icon="add"
-                shortcut="+"
+                v-shortcut="'+'"
             />
             <QTooltip class="text-no-wrap">
                 {{ t('eventsInclusionForm.addEvent') }}
diff --git a/src/pages/Zone/Card/ZoneFilter.js b/src/pages/Zone/Card/ZoneFilter.js
new file mode 100644
index 000000000..3298c7c8a
--- /dev/null
+++ b/src/pages/Zone/Card/ZoneFilter.js
@@ -0,0 +1,10 @@
+export default {
+    include: [
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['name', 'id'],
+            },
+        },
+    ],
+};
diff --git a/src/pages/Zone/Card/ZoneSearchbar.vue b/src/pages/Zone/Card/ZoneSearchbar.vue
index f7a59e97f..d1188a1e8 100644
--- a/src/pages/Zone/Card/ZoneSearchbar.vue
+++ b/src/pages/Zone/Card/ZoneSearchbar.vue
@@ -22,15 +22,50 @@ const exprBuilder = (param, value) => {
             return /^\d+$/.test(value) ? { id: value } : { name: { like: `%${value}%` } };
     }
 };
+
+const tableFilter = {
+    include: [
+        {
+            relation: 'agencyMode',
+            scope: {
+                fields: ['id', 'name'],
+            },
+        },
+        {
+            relation: 'address',
+            scope: {
+                fields: ['id', 'nickname', 'provinceFk', 'postalCode'],
+                include: [
+                    {
+                        relation: 'province',
+                        scope: {
+                            fields: ['id', 'name'],
+                        },
+                    },
+                    {
+                        relation: 'postcode',
+                        scope: {
+                            fields: ['code', 'townFk'],
+                            include: {
+                                relation: 'town',
+                                scope: {
+                                    fields: ['id', 'name'],
+                                },
+                            },
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+};
 </script>
 
 <template>
     <VnSearchbar
         data-key="ZonesList"
         url="Zones"
-        :filter="{
-            include: { relation: 'agencyMode', scope: { fields: ['name'] } },
-        }"
+        :filter="tableFilter"
         :expr-builder="exprBuilder"
         :label="t('list.searchZone')"
         :info="t('list.searchInfo')"
diff --git a/src/pages/Zone/Card/ZoneSummary.vue b/src/pages/Zone/Card/ZoneSummary.vue
index 124802633..5b29b495b 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 filter from './ZoneFilter.js';
 import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
 
 const route = useRoute();
@@ -26,19 +27,6 @@ const $props = defineProps({
 const entityId = computed(() => $props.id || route.params.id);
 const zoneUrl = ref();
 
-const filter = computed(() => {
-    const filter = {
-        include: {
-            relation: 'agencyMode',
-            fields: ['name'],
-        },
-        where: {
-            id: entityId,
-        },
-    };
-    return filter;
-});
-
 const columns = computed(() => [
     {
         label: t('list.name'),
@@ -72,9 +60,9 @@ onMounted(async () => {
 
 <template>
     <CardSummary
-        data-key="ZoneSummary"
+        data-key="Zone"
         ref="summary"
-        url="Zones/findOne"
+        :url="`Zones/${entityId}`"
         :filter="filter"
     >
         <template #header="{ entity }">
diff --git a/src/pages/Zone/Card/ZoneWarehouses.vue b/src/pages/Zone/Card/ZoneWarehouses.vue
index c96735697..165e9c840 100644
--- a/src/pages/Zone/Card/ZoneWarehouses.vue
+++ b/src/pages/Zone/Card/ZoneWarehouses.vue
@@ -109,7 +109,7 @@ const openCreateWarehouseForm = () => createWarehouseDialogRef.value.show();
                 icon="add"
                 color="primary"
                 @click="openCreateWarehouseForm()"
-                shortcut="+"
+                v-shortcut="'+'"
             >
                 <QTooltip>{{ t('warehouses.add') }}</QTooltip>
             </QBtn>
diff --git a/src/pages/Zone/Delivery/ZoneDeliveryList.vue b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
index 975cbdb67..e3ec8cb2d 100644
--- a/src/pages/Zone/Delivery/ZoneDeliveryList.vue
+++ b/src/pages/Zone/Delivery/ZoneDeliveryList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
+            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
index 5a7f0bb4c..7b5c2ddbc 100644
--- a/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
+++ b/src/pages/Zone/Upcoming/ZoneUpcomingList.vue
@@ -74,7 +74,7 @@ async function remove(row) {
             </VnPaginate>
         </div>
         <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" shortcut="+" color="primary" />
+            <QBtn @click="create" fab icon="add" v-shortcut="'+'" color="primary" />
         </QPageSticky>
     </QPage>
 </template>
diff --git a/src/router/modules/account/aliasCard.js b/src/router/modules/account/aliasCard.js
index cbbd31e51..a5b00f44b 100644
--- a/src/router/modules/account/aliasCard.js
+++ b/src/router/modules/account/aliasCard.js
@@ -3,7 +3,7 @@ export default {
     path: ':id',
     component: () => import('src/pages/Account/Alias/Card/AliasCard.vue'),
     redirect: { name: 'AliasSummary' },
-    meta: { menu: ['AliasBasicData', 'AliasUsers'] },
+    meta: { moduleName: 'Alias', menu: ['AliasBasicData', 'AliasUsers'] },
     children: [
         {
             name: 'AliasSummary',
diff --git a/src/router/modules/account/roleCard.js b/src/router/modules/account/roleCard.js
index c36ce71b9..f8100071f 100644
--- a/src/router/modules/account/roleCard.js
+++ b/src/router/modules/account/roleCard.js
@@ -4,6 +4,7 @@ export default {
     component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
     redirect: { name: 'RoleSummary' },
     meta: {
+        moduleName: 'Role',
         menu: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
     },
     children: [
diff --git a/src/router/modules/entry.js b/src/router/modules/entry.js
index f362c7653..b5656dc5f 100644
--- a/src/router/modules/entry.js
+++ b/src/router/modules/entry.js
@@ -6,13 +6,7 @@ const entryCard = {
     component: () => import('src/pages/Entry/Card/EntryCard.vue'),
     redirect: { name: 'EntrySummary' },
     meta: {
-        menu: [
-            'EntryBasicData',
-            'EntryBuys',
-            'EntryNotes',
-            'EntryDms',
-            'EntryLog',
-        ],
+        menu: ['EntryBasicData', 'EntryBuys', 'EntryNotes', 'EntryDms', 'EntryLog'],
     },
     children: [
         {
@@ -91,7 +85,7 @@ export default {
             'EntryLatestBuys',
             'EntryStockBought',
             'EntryWasteRecalc',
-        ]
+        ],
     },
     component: RouterView,
     redirect: { name: 'EntryMain' },
@@ -103,7 +97,7 @@ export default {
             redirect: { name: 'EntryIndexMain' },
             children: [
                 {
-                    path:'',
+                    path: '',
                     name: 'EntryIndexMain',
                     redirect: { name: 'EntryList' },
                     component: () => import('src/pages/Entry/EntryList.vue'),
@@ -115,6 +109,7 @@ export default {
                                 title: 'list',
                                 icon: 'view_list',
                             },
+                            component: () => import('src/pages/Entry/EntryList.vue'),
                         },
                         entryCard,
                     ],
@@ -127,7 +122,7 @@ export default {
                         icon: 'add',
                     },
                     component: () => import('src/pages/Entry/EntryCreate.vue'),
-                },                
+                },
                 {
                     path: 'my',
                     name: 'MyEntries',
@@ -167,4 +162,4 @@ export default {
             ],
         },
     ],
-};
\ No newline at end of file
+};
diff --git a/src/router/modules/route.js b/src/router/modules/route.js
index 946ad3e15..835324d20 100644
--- a/src/router/modules/route.js
+++ b/src/router/modules/route.js
@@ -160,6 +160,36 @@ const roadmapCard = {
     ],
 };
 
+const vehicleCard = {
+    path: ':id',
+    name: 'VehicleCard',
+    component: () => import('src/pages/Route/Vehicle/Card/VehicleCard.vue'),
+    redirect: { name: 'VehicleSummary' },
+    meta: {
+        menu: ['VehicleBasicData'],
+    },
+    children: [
+        {
+            name: 'VehicleSummary',
+            path: 'summary',
+            meta: {
+                title: 'summary',
+                icon: 'view_list',
+            },
+            component: () => import('src/pages/Route/Vehicle/Card/VehicleSummary.vue'),
+        },
+        {
+            name: 'VehicleBasicData',
+            path: 'basic-data',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+            },
+            component: () => import('src/pages/Route/Vehicle/Card/VehicleBasicData.vue'),
+        },
+    ],
+};
+
 export default {
     name: 'Route',
     path: '/route',
@@ -174,6 +204,7 @@ export default {
             'RouteRoadmap',
             'CmrList',
             'AgencyList',
+            'VehicleList',
         ],
     },
     component: RouterView,
@@ -280,6 +311,27 @@ export default {
                         agencyCard,
                     ],
                 },
+                {
+                    path: 'vehicle',
+                    name: 'RouteVehicle',
+                    redirect: { name: 'VehicleList' },
+                    meta: {
+                        title: 'vehicle',
+                        icon: 'directions_car',
+                    },
+                    component: () => import('src/pages/Route/Vehicle/VehicleList.vue'),
+                    children: [
+                        {
+                            path: 'list',
+                            name: 'VehicleList',
+                            meta: {
+                                title: 'vehicleList',
+                                icon: 'directions_car',
+                            },
+                        },
+                        vehicleCard,
+                    ],
+                },
             ],
         },
     ],
diff --git a/src/router/modules/shelving.js b/src/router/modules/shelving.js
index 55fb04278..c085dd8dc 100644
--- a/src/router/modules/shelving.js
+++ b/src/router/modules/shelving.js
@@ -3,7 +3,7 @@ import { RouterView } from 'vue-router';
 const parkingCard = {
     name: 'ParkingCard',
     path: ':id',
-    component: () => import('src/pages/Parking/Card/ParkingCard.vue'),
+    component: () => import('src/pages/Shelving/Parking/Card/ParkingCard.vue'),
     redirect: { name: 'ParkingSummary' },
     meta: {
         menu: ['ParkingBasicData', 'ParkingLog'],
@@ -16,7 +16,7 @@ const parkingCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () => import('src/pages/Parking/Card/ParkingSummary.vue'),
+            component: () => import('src/pages/Shelving/Parking/Card/ParkingSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -25,7 +25,8 @@ const parkingCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () => import('src/pages/Parking/Card/ParkingBasicData.vue'),
+            component: () =>
+                import('src/pages/Shelving/Parking/Card/ParkingBasicData.vue'),
         },
         {
             path: 'log',
@@ -34,7 +35,7 @@ const parkingCard = {
                 title: 'log',
                 icon: 'history',
             },
-            component: () => import('src/pages/Parking/Card/ParkingLog.vue'),
+            component: () => import('src/pages/Shelving/Parking/Card/ParkingLog.vue'),
         },
     ],
 };
@@ -127,7 +128,7 @@ export default {
                         title: 'parkingList',
                         icon: 'view_list',
                     },
-                    component: () => import('src/pages/Parking/ParkingList.vue'),
+                    component: () => import('src/pages/Shelving/Parking/ParkingList.vue'),
                     children: [
                         {
                             path: 'list',
diff --git a/src/router/modules/supplier.js b/src/router/modules/supplier.js
index 4ece4c784..19763cdf3 100644
--- a/src/router/modules/supplier.js
+++ b/src/router/modules/supplier.js
@@ -1,19 +1,12 @@
 import { RouterView } from 'vue-router';
 
-export default {
-    path: '/supplier',
-    name: 'Supplier',
+const supplierCard = {
+    name: 'SupplierCard',
+    path: ':id',
+    component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
+    redirect: { name: 'SupplierSummary' },
     meta: {
-        title: 'suppliers',
-        icon: 'vn:supplier',
-        moduleName: 'Supplier',
-        keyBinding: 'p',
-    },
-    component: RouterView,
-    redirect: { name: 'SupplierMain' },
-    menus: {
-        main: ['SupplierList'],
-        card: [
+        menu: [
             'SupplierBasicData',
             'SupplierFiscalData',
             'SupplierBillingData',
@@ -27,21 +20,165 @@ export default {
             'SupplierDms',
         ],
     },
+    children: [
+        {
+            name: 'SupplierSummary',
+            path: 'summary',
+            meta: {
+                title: 'summary',
+                icon: 'launch',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierSummary.vue'),
+        },
+        {
+            path: 'basic-data',
+            name: 'SupplierBasicData',
+            meta: {
+                title: 'basicData',
+                icon: 'vn:settings',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBasicData.vue'),
+        },
+        {
+            path: 'fiscal-data',
+            name: 'SupplierFiscalData',
+            meta: {
+                title: 'fiscalData',
+                icon: 'vn:dfiscales',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
+        },
+        {
+            path: 'billing-data',
+            name: 'SupplierBillingData',
+            meta: {
+                title: 'billingData',
+                icon: 'vn:payment',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBillingData.vue'),
+        },
+        {
+            path: 'log',
+            name: 'SupplierLog',
+            meta: {
+                title: 'log',
+                icon: 'vn:History',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
+        },
+        {
+            path: 'account',
+            name: 'SupplierAccounts',
+            meta: {
+                title: 'accounts',
+                icon: 'vn:credit',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAccounts.vue'),
+        },
+        {
+            path: 'contact',
+            name: 'SupplierContacts',
+            meta: {
+                title: 'contacts',
+                icon: 'contact_phone',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierContacts.vue'),
+        },
+        {
+            path: 'address',
+            name: 'SupplierAddresses',
+            meta: {
+                title: 'addresses',
+                icon: 'vn:delivery',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAddresses.vue'),
+        },
+        {
+            path: 'address/create',
+            name: 'SupplierAddressesCreate',
+            component: () =>
+                import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
+        },
+        {
+            path: 'balance',
+            name: 'SupplierBalance',
+            meta: {
+                title: 'balance',
+                icon: 'balance',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierBalance.vue'),
+        },
+        {
+            path: 'consumption',
+            name: 'SupplierConsumption',
+            meta: {
+                title: 'consumption',
+                icon: 'show_chart',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierConsumption.vue'),
+        },
+        {
+            path: 'agency-term',
+            name: 'SupplierAgencyTerm',
+            meta: {
+                title: 'agencyTerm',
+                icon: 'vn:agency-term',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
+        },
+        {
+            path: 'dms',
+            name: 'SupplierDms',
+            meta: {
+                title: 'dms',
+                icon: 'smb_share',
+            },
+            component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
+        },
+        {
+            path: 'agency-term/create',
+            name: 'SupplierAgencyTermCreate',
+            component: () =>
+                import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
+        },
+    ],
+};
+
+export default {
+    name: 'Supplier',
+    path: '/supplier',
+    meta: {
+        title: 'suppliers',
+        icon: 'vn:supplier',
+        moduleName: 'Supplier',
+        keyBinding: 'p',
+        menu: ['SupplierList'],
+    },
+    component: RouterView,
+    redirect: { name: 'SupplierMain' },
     children: [
         {
             path: '',
             name: 'SupplierMain',
             component: () => import('src/components/common/VnModule.vue'),
-            redirect: { name: 'SupplierList' },
+            redirect: { name: 'SupplierIndexMain' },
             children: [
                 {
-                    path: 'list',
-                    name: 'SupplierList',
-                    meta: {
-                        title: 'list',
-                        icon: 'view_list',
-                    },
+                    path: '',
+                    name: 'SupplierIndexMain',
+                    redirect: { name: 'SupplierList' },
                     component: () => import('src/pages/Supplier/SupplierList.vue'),
+                    children: [
+                        {
+                            path: 'list',
+                            name: 'SupplierList',
+                            meta: {
+                                title: 'list',
+                                icon: 'view_list',
+                            },
+                        },
+                        supplierCard,
+                    ],
                 },
                 {
                     path: 'create',
@@ -54,143 +191,5 @@ export default {
                 },
             ],
         },
-        {
-            name: 'SupplierCard',
-            path: ':id',
-            component: () => import('src/pages/Supplier/Card/SupplierCard.vue'),
-            redirect: { name: 'SupplierSummary' },
-            children: [
-                {
-                    name: 'SupplierSummary',
-                    path: 'summary',
-                    meta: {
-                        title: 'summary',
-                        icon: 'launch',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierSummary.vue'),
-                },
-                {
-                    path: 'basic-data',
-                    name: 'SupplierBasicData',
-                    meta: {
-                        title: 'basicData',
-                        icon: 'vn:settings',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBasicData.vue'),
-                },
-                {
-                    path: 'fiscal-data',
-                    name: 'SupplierFiscalData',
-                    meta: {
-                        title: 'fiscalData',
-                        icon: 'vn:dfiscales',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierFiscalData.vue'),
-                },
-                {
-                    path: 'billing-data',
-                    name: 'SupplierBillingData',
-                    meta: {
-                        title: 'billingData',
-                        icon: 'vn:payment',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBillingData.vue'),
-                },
-                {
-                    path: 'log',
-                    name: 'SupplierLog',
-                    meta: {
-                        title: 'log',
-                        icon: 'vn:History',
-                    },
-                    component: () => import('src/pages/Supplier/Card/SupplierLog.vue'),
-                },
-                {
-                    path: 'account',
-                    name: 'SupplierAccounts',
-                    meta: {
-                        title: 'accounts',
-                        icon: 'vn:credit',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAccounts.vue'),
-                },
-                {
-                    path: 'contact',
-                    name: 'SupplierContacts',
-                    meta: {
-                        title: 'contacts',
-                        icon: 'contact_phone',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierContacts.vue'),
-                },
-                {
-                    path: 'address',
-                    name: 'SupplierAddresses',
-                    meta: {
-                        title: 'addresses',
-                        icon: 'vn:delivery',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAddresses.vue'),
-                },
-                {
-                    path: 'address/create',
-                    name: 'SupplierAddressesCreate',
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
-                },
-                {
-                    path: 'balance',
-                    name: 'SupplierBalance',
-                    meta: {
-                        title: 'balance',
-                        icon: 'balance',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierBalance.vue'),
-                },
-                {
-                    path: 'consumption',
-                    name: 'SupplierConsumption',
-                    meta: {
-                        title: 'consumption',
-                        icon: 'show_chart',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierConsumption.vue'),
-                },
-                {
-                    path: 'agency-term',
-                    name: 'SupplierAgencyTerm',
-                    meta: {
-                        title: 'agencyTerm',
-                        icon: 'vn:agency-term',
-                    },
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAgencyTerm.vue'),
-                },
-                {
-                    path: 'dms',
-                    name: 'SupplierDms',
-                    meta: {
-                        title: 'dms',
-                        icon: 'smb_share',
-                    },
-                    component: () => import('src/pages/Supplier/Card/SupplierDms.vue'),
-                },
-                {
-                    path: 'agency-term/create',
-                    name: 'SupplierAgencyTermCreate',
-                    component: () =>
-                        import('src/pages/Supplier/Card/SupplierAgencyTermCreate.vue'),
-                },
-            ],
-        },
     ],
 };
diff --git a/src/router/modules/ticket.js b/src/router/modules/ticket.js
index e5b423f64..bfcb78787 100644
--- a/src/router/modules/ticket.js
+++ b/src/router/modules/ticket.js
@@ -192,7 +192,13 @@ export default {
         icon: 'vn:ticket',
         moduleName: 'Ticket',
         keyBinding: 't',
-        menu: ['TicketList', 'TicketAdvance', 'TicketWeekly', 'TicketFuture'],
+        menu: [
+            'TicketList',
+            'TicketAdvance',
+            'TicketWeekly',
+            'TicketFuture',
+            'TicketNegative',
+        ],
     },
     component: RouterView,
     redirect: { name: 'TicketMain' },
@@ -229,6 +235,32 @@ export default {
                     },
                     component: () => import('src/pages/Ticket/TicketCreate.vue'),
                 },
+                {
+                    path: 'negative',
+                    redirect: { name: 'TicketNegative' },
+                    children: [
+                        {
+                            name: 'TicketNegative',
+                            meta: {
+                                title: 'negative',
+                                icon: 'exposure',
+                            },
+                            component: () =>
+                                import('src/pages/Ticket/Negative/TicketLackList.vue'),
+                            path: '',
+                        },
+                        {
+                            name: 'NegativeDetail',
+                            path: ':id',
+                            meta: {
+                                title: 'summary',
+                                icon: 'launch',
+                            },
+                            component: () =>
+                                import('src/pages/Ticket/Negative/TicketLackDetail.vue'),
+                        },
+                    ],
+                },
                 {
                     path: 'weekly',
                     name: 'TicketWeekly',
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index 1d013c596..3eb95a96e 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -201,9 +201,10 @@ const workerCard = {
 const departmentCard = {
     name: 'DepartmentCard',
     path: ':id',
-    component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
+    component: () => import('src/pages/Worker/Department/Card/DepartmentCard.vue'),
     redirect: { name: 'DepartmentSummary' },
     meta: {
+        moduleName: 'Department',
         menu: ['DepartmentBasicData'],
     },
     children: [
@@ -214,7 +215,8 @@ const departmentCard = {
                 title: 'summary',
                 icon: 'launch',
             },
-            component: () => import('src/pages/Department/Card/DepartmentSummary.vue'),
+            component: () =>
+                import('src/pages/Worker/Department/Card/DepartmentSummary.vue'),
         },
         {
             path: 'basic-data',
@@ -223,7 +225,8 @@ const departmentCard = {
                 title: 'basicData',
                 icon: 'vn:settings',
             },
-            component: () => import('src/pages/Department/Card/DepartmentBasicData.vue'),
+            component: () =>
+                import('src/pages/Worker/Department/Card/DepartmentBasicData.vue'),
         },
     ],
 };
diff --git a/src/stores/__tests__/useNavigationStore.spec.js b/src/stores/__tests__/useNavigationStore.spec.js
new file mode 100644
index 000000000..c5df6157e
--- /dev/null
+++ b/src/stores/__tests__/useNavigationStore.spec.js
@@ -0,0 +1,153 @@
+import { setActivePinia, createPinia } from 'pinia';
+import { describe, beforeEach, afterEach, it, expect, vi, beforeAll } from 'vitest';
+import { useNavigationStore } from '../useNavigationStore';
+import axios from 'axios';
+
+let store;
+
+vi.mock('src/router/modules', () => [
+    { name: 'Item', meta: {} },
+    { name: 'Shelving', meta: {} },
+    { name: 'Order', meta: {} },
+]);
+
+vi.mock('src/filters', () => ({
+    toLowerCamel: vi.fn((name) => name.toLowerCase()),
+}));
+
+const modulesMock = [
+    {
+        name: 'Item',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'item',
+        isPinned: true,
+    },
+    {
+        name: 'Shelving',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'shelving',
+        isPinned: false,
+    },
+    {
+        name: 'Order',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'order',
+        isPinned: false,
+    },
+];
+
+const pinnedModulesMock = [
+    {
+        name: 'Item',
+        children: null,
+        title: 'globals.pageTitles.undefined',
+        icon: undefined,
+        module: 'item',
+        isPinned: true,
+    },
+];
+
+describe('useNavigationStore', () => {
+    beforeEach(() => {
+        setActivePinia(createPinia());
+        vi.spyOn(axios, 'get').mockResolvedValue({ data: true });
+        store = useNavigationStore();
+        store.getModules = vi.fn().mockReturnValue({
+            value: modulesMock,
+        });
+        store.getPinnedModules = vi.fn().mockReturnValue({
+            value: pinnedModulesMock,
+        });
+    });
+    afterEach(() => {
+        vi.clearAllMocks();
+    });
+
+    it('should return modules with correct structure', () => {
+        const store = useNavigationStore();
+        const modules = store.getModules();
+
+        expect(modules.value).toEqual(modulesMock);
+    });
+
+    it('should return pinned modules', () => {
+        const store = useNavigationStore();
+        const pinnedModules = store.getPinnedModules();
+
+        expect(pinnedModules.value).toEqual(pinnedModulesMock);
+    });
+
+    it('should toggle pinned modules', () => {
+        const store = useNavigationStore();
+
+        store.togglePinned('item');
+        store.togglePinned('shelving');
+        expect(store.pinnedModules).toEqual(['item', 'shelving']);
+
+        store.togglePinned('item');
+        expect(store.pinnedModules).toEqual(['shelving']);
+    });
+
+    it('should fetch pinned modules', async () => {
+        vi.spyOn(axios, 'get').mockResolvedValue({
+            data: [{ id: 1, workerFk: 9, moduleFk: 'order', position: 1 }],
+        });
+        const store = useNavigationStore();
+        await store.fetchPinned();
+
+        expect(store.pinnedModules).toEqual(['order']);
+    });
+
+    it('should add menu item correctly', () => {
+        const store = useNavigationStore();
+        const module = 'customer';
+        const parent = [];
+        const route = {
+            name: 'customer',
+            title: 'Customer',
+            icon: 'customer',
+            meta: {
+                keyBinding: 'ctrl+shift+c',
+                name: 'customer',
+                title: 'Customer',
+                icon: 'customer',
+                menu: 'customer',
+                menuChildren: [{ name: 'customer', title: 'Customer', icon: 'customer' }],
+            },
+        };
+
+        const result = store.addMenuItem(module, route, parent);
+        const expectedItem = {
+            children: [
+                {
+                    icon: 'customer',
+                    name: 'customer',
+                    title: 'globals.pageTitles.Customer',
+                },
+            ],
+            icon: 'customer',
+            keyBinding: 'ctrl+shift+c',
+            name: 'customer',
+            title: 'globals.pageTitles.Customer',
+        };
+        expect(result).toEqual(expectedItem);
+        expect(parent.length).toBe(1);
+        expect(parent).toEqual([expectedItem]);
+    });
+
+    it('should not add menu item if condition is not met', () => {
+        const store = useNavigationStore();
+        const module = 'testModule';
+        const route = { meta: { hidden: true, menuchildren: {} } };
+        const parent = [];
+        const result = store.addMenuItem(module, route, parent);
+        expect(result).toBeUndefined();
+        expect(parent.length).toBe(0);
+    });
+});
diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js
index 8d62fdb4a..b3996d1e3 100644
--- a/src/stores/useArrayDataStore.js
+++ b/src/stores/useArrayDataStore.js
@@ -19,6 +19,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
         page: 1,
         mapKey: 'id',
         keepData: false,
+        oneRecord: false,
     };
 
     function get(key) {
diff --git a/src/utils/notifyResults.js b/src/utils/notifyResults.js
new file mode 100644
index 000000000..e87ad6c6f
--- /dev/null
+++ b/src/utils/notifyResults.js
@@ -0,0 +1,19 @@
+import { Notify } from 'quasar';
+
+export default function (results, key) {
+    results.forEach((result, index) => {
+        if (result.status === 'fulfilled') {
+            const data = JSON.parse(result.value.config.data);
+            Notify.create({
+                type: 'positive',
+                message: `Operación (${index + 1}) ${data[key]} completada con éxito.`,
+            });
+        } else {
+            const data = JSON.parse(result.reason.config.data);
+            Notify.create({
+                type: 'negative',
+                message: `Operación (${index + 1}) ${data[key]} fallida: ${result.reason.message}`,
+            });
+        }
+    });
+}
diff --git a/test/cypress/integration/Order/orderCatalog.spec.js b/test/cypress/integration/Order/orderCatalog.spec.js
index 9e01eb915..a106d0e8a 100644
--- a/test/cypress/integration/Order/orderCatalog.spec.js
+++ b/test/cypress/integration/Order/orderCatalog.spec.js
@@ -45,7 +45,6 @@ describe('OrderCatalog', () => {
         ).type('{enter}');
         cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
         cy.dataCy('catalogFilterValueDialogBtn').last().click();
-        cy.get('[data-cy="catalogFilterValueDialogTagSelect"]').click();
         cy.selectOption("[data-cy='catalogFilterValueDialogTagSelect']", 'Tallos');
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').focus();
         cy.dataCy('catalogFilterValueDialogValueInput').find('input').type('2');
diff --git a/test/cypress/integration/entry/stockBought.spec.js b/test/cypress/integration/entry/stockBought.spec.js
index 193d9e448..b282a19a5 100644
--- a/test/cypress/integration/entry/stockBought.spec.js
+++ b/test/cypress/integration/entry/stockBought.spec.js
@@ -6,6 +6,7 @@ describe('EntryStockBought', () => {
     });
     it('Should edit the reserved space', () => {
         cy.get('.q-field__native.q-placeholder').should('have.value', '01/01/2001');
+        cy.get('[data-col-field="reserve"][data-row-index="0"]').click();
         cy.get('input[name="reserve"]').type('10{enter}');
         cy.get('button[title="Save"]').click();
         cy.checkNotification('Data saved');
@@ -15,25 +16,35 @@ describe('EntryStockBought', () => {
         cy.get('input[aria-label="Reserve"]').type('1');
         cy.get('input[aria-label="Date"]').eq(1).clear();
         cy.get('input[aria-label="Date"]').eq(1).type('01-01');
-        cy.get('input[aria-label="Buyer"]').type('buyerboss{downarrow}{enter}');
+        cy.get('input[aria-label="Buyer"]').type('buyerBossNick');
+        cy.get('div[role="listbox"] > div > div[role="option"]')
+            .eq(0)
+            .should('be.visible')
+            .click();
+
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data created');
+
+        cy.get('[data-col-field="reserve"][data-row-index="1"]').click().clear();
+        cy.get('[data-cy="searchBtn"]').eq(1).click();
+        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata')
+            .should('have.text', 'warningNo data available')
+            .type('{esc}');
+        cy.get('[data-col-field="reserve"][data-row-index="1"]')
+            .click()
+            .type('{backspace}{enter}');
+        cy.get('[data-cy="crudModelDefaultSaveBtn"]').should('be.enabled').click();
+        cy.get('.q-notification__message').eq(1).should('have.text', 'Data saved');
     });
     it('Should check detail for the buyer', () => {
-        cy.get(':nth-child(1) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
+        cy.get('[data-cy="searchBtn"]').eq(0).click();
         cy.get('tBody > tr').eq(1).its('length').should('eq', 1);
     });
-    it('Should check detail for the buyerBoss and had no content', () => {
-        cy.get(':nth-child(2) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
-        cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata').should(
-            'have.text',
-            'warningNo data available'
-        );
-    });
+
     it('Should edit travel m3 and refresh', () => {
-        cy.get('.vn-row > div > .q-btn > .q-btn__content > .q-icon').click();
-        cy.get('input[aria-label="m3"]').clear();
-        cy.get('input[aria-label="m3"]').type('60');
-        cy.get('.q-mt-lg > .q-btn--standard > .q-btn__content > .block').click();
+        cy.get('[data-cy="edit-travel"]').should('be.visible').click();
+        cy.get('input[aria-label="m3"]').clear().type('60');
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.vn-row > div > :nth-child(2)').should('have.text', '60');
     });
 });
diff --git a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
index 2016fca6d..11ca1bb59 100644
--- a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
@@ -1,9 +1,9 @@
 /// <reference types="cypress" />
 describe('InvoiceInBasicData', () => {
-    const formInputs = '.q-form > .q-card input';
     const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
-    const documentBtns = '[data-cy="dms-buttons"] button';
     const dialogInputs = '.q-dialog input';
+    const resetBtn = '.q-btn-group--push > .q-btn--flat';
+    const getDocumentBtns = (opt) => `[data-cy="dms-buttons"]  > :nth-child(${opt})`;
 
     beforeEach(() => {
         cy.login('developer');
@@ -11,13 +11,16 @@ describe('InvoiceInBasicData', () => {
     });
 
     it('should edit the provideer and supplier ref', () => {
-        cy.selectOption(firstFormSelect, 'Bros');
-        cy.get('[title="Reset"]').click();
-        cy.get(formInputs).eq(1).type('{selectall}4739');
-        cy.saveCard();
+        cy.dataCy('UnDeductibleVatSelect').type('4751000000');
+        cy.get('.q-menu .q-item').contains('4751000000').click();
+        cy.get(resetBtn).click();
 
-        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Plants nick');
-        cy.get(formInputs).eq(1).invoke('val').should('eq', '4739');
+        cy.waitForElement('#formModel').within(() => {
+            cy.dataCy('vnSupplierSelect').type('Bros nick');
+        })
+        cy.get('.q-menu .q-item').contains('Bros nick').click();
+        cy.saveCard();
+        cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Bros nick');
     });
 
     it('should edit, remove and create the dms data', () => {
@@ -25,18 +28,18 @@ describe('InvoiceInBasicData', () => {
         const secondInput = "I don't know what posting here!";
 
         //edit
-        cy.get(documentBtns).eq(1).click();
+        cy.get(getDocumentBtns(2)).click();
         cy.get(dialogInputs).eq(0).type(`{selectall}${firtsInput}`);
         cy.get('textarea').type(`{selectall}${secondInput}`);
         cy.get('[data-cy="FormModelPopup_save"]').click();
-        cy.get(documentBtns).eq(1).click();
+        cy.get(getDocumentBtns(2)).click();
         cy.get(dialogInputs).eq(0).invoke('val').should('eq', firtsInput);
         cy.get('textarea').invoke('val').should('eq', secondInput);
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
 
         //remove
-        cy.get(documentBtns).eq(2).click();
+        cy.get(getDocumentBtns(3)).click();
         cy.get('[data-cy="VnConfirm_confirm"]').click();
         cy.checkNotification('Data saved');
 
@@ -46,7 +49,7 @@ describe('InvoiceInBasicData', () => {
             'test/cypress/fixtures/image.jpg',
             {
                 force: true,
-            }
+            },
         );
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('Data saved');
diff --git a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
index f8b403a45..1e7ce1003 100644
--- a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
@@ -36,7 +36,7 @@ describe('InvoiceInVat', () => {
         cy.get(dialogInputs).eq(0).type(randomInt);
         cy.get(dialogInputs).eq(1).type('This is a dummy expense');
 
-        cy.get('button[type="submit"]').click();
+        cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data created');
     });
 });
diff --git a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
index 4f28cc490..4d530de05 100644
--- a/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
+++ b/test/cypress/integration/invoiceOut/invoiceOutNegativeBases.spec.js
@@ -22,9 +22,7 @@ describe('InvoiceOut negative bases', () => {
     });
 
     it('should filter and download as CSV', () => {
-        cy.get(
-            ':nth-child(7) > .full-width > :nth-child(1) > .column > div.q-px-xs > .q-field > .q-field__inner > .q-field__control'
-        ).type('23{enter}');
+        cy.get('input[name="ticketFk"]').type('23{enter}');
         cy.get('#subToolbar > .q-btn').click();
         cy.checkNotification('CSV downloaded successfully');
     });
diff --git a/test/cypress/integration/item/ItemProposal.spec.js b/test/cypress/integration/item/ItemProposal.spec.js
new file mode 100644
index 000000000..b3ba9f676
--- /dev/null
+++ b/test/cypress/integration/item/ItemProposal.spec.js
@@ -0,0 +1,11 @@
+/// <reference types="cypress" />
+describe('ItemProposal', () => {
+    beforeEach(() => {
+        const ticketId = 1;
+
+        cy.login('developer');
+        cy.visit(`/#/ticket/${ticketId}/summary`);
+    });
+
+    describe('Handle item proposal selected', () => {});
+});
diff --git a/test/cypress/integration/item/itemTag.spec.js b/test/cypress/integration/item/itemTag.spec.js
index 17423bc51..425eaffe6 100644
--- a/test/cypress/integration/item/itemTag.spec.js
+++ b/test/cypress/integration/item/itemTag.spec.js
@@ -16,10 +16,7 @@ describe('Item tag', () => {
         cy.dataCy(newTag).should('be.visible').click().type('Genero{enter}');
         cy.dataCy('tagGeneroValue').eq(1).should('be.visible');
         cy.dataCy(saveBtn).click();
-        cy.get('.q-notification__message').should(
-            'have.text',
-            "The tag or priority can't be repeated for an item",
-        );
+        cy.checkNotification("The tag or priority can't be repeated for an item");
     });
 
     it('should add a new tag', () => {
diff --git a/test/cypress/integration/parking/parkingBasicData.spec.js b/test/cypress/integration/parking/parkingBasicData.spec.js
index 0d130d335..f64f23ec8 100644
--- a/test/cypress/integration/parking/parkingBasicData.spec.js
+++ b/test/cypress/integration/parking/parkingBasicData.spec.js
@@ -13,11 +13,11 @@ describe('ParkingBasicData', () => {
         cy.get(sectorOpt).click();
 
         cy.get(codeInput).eq(0).clear();
-        cy.get(codeInput).eq(0).type(123);
+        cy.get(codeInput).eq(0).type('900-001');
 
         cy.saveCard();
 
         cy.get(sectorSelect).should('have.value', 'Second sector');
-        cy.get(codeInput).should('have.value', 123);
+        cy.get(codeInput).should('have.value', '900-001');
     });
 });
diff --git a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
index 796738127..5679ceba1 100644
--- a/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/route/agency/agencyWorkCenter.spec.js
@@ -15,6 +15,7 @@ describe.skip('AgencyWorkCenter', () => {
 
         // expect error when duplicate
         cy.get(createButton).click();
+        cy.selectOption(workCenterCombobox, 'workCenterOne');
         cy.get('[data-cy="FormModelPopup_save"]').click();
         cy.checkNotification('This workCenter is already assigned to this agency');
         cy.get('[data-cy="FormModelPopup_cancel"]').click();
diff --git a/test/cypress/integration/route/routeList.spec.js b/test/cypress/integration/route/routeList.spec.js
index 5ff157d2a..04278cfc5 100644
--- a/test/cypress/integration/route/routeList.spec.js
+++ b/test/cypress/integration/route/routeList.spec.js
@@ -4,9 +4,6 @@ describe('Route', () => {
         cy.login('developer');
         cy.visit(`/#/route/extended-list`);
     });
-    const getVnSelect =
-        '> :nth-child(1) > .column > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
-    const getRowColumn = (row, column) => `:nth-child(${row}) > :nth-child(${column})`;
 
     it('Route list create route', () => {
         cy.addBtnClick();
@@ -17,15 +14,23 @@ describe('Route', () => {
 
     it('Route list search and edit', () => {
         cy.get('#searchbar input').type('{enter}');
-        cy.get('input[name="description"]').type('routeTestOne{enter}');
+        cy.get('[data-col-field="description"][data-row-index="0"]')
+            .click()
+            .type('routeTestOne{enter}');
         cy.get('.q-table tr')
             .its('length')
             .then((rowCount) => {
                 expect(rowCount).to.be.greaterThan(0);
             });
-        cy.get(getRowColumn(1, 3) + getVnSelect).type('{downArrow}{enter}');
-        cy.get(getRowColumn(1, 4) + getVnSelect).type('{downArrow}{enter}');
-        cy.get(getRowColumn(1, 5) + getVnSelect).type('{downArrow}{enter}');
+        cy.get('[data-col-field="workerFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
+        cy.get('[data-col-field="agencyModeFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
+        cy.get('[data-col-field="vehicleFk"][data-row-index="0"]')
+            .click()
+            .type('{downArrow}{enter}');
         cy.get('button[title="Save"]').click();
         cy.get('.q-notification__message').should('have.text', 'Data saved');
     });
diff --git a/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
new file mode 100644
index 000000000..64b9ca0a0
--- /dev/null
+++ b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js
@@ -0,0 +1,13 @@
+describe('Vehicle', () => {
+    beforeEach(() => {
+        cy.viewport(1920, 1080);
+        cy.login('deliveryAssistant');
+        cy.visit(`/#/route/vehicle/7`);
+    });
+
+    it('should delete a vehicle', () => {
+        cy.openActionsDescriptor();
+        cy.get('[data-cy="delete"]').click();
+        cy.checkNotification('Vehicle removed');
+    });
+});
diff --git a/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js b/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
new file mode 100644
index 000000000..9ea1cff63
--- /dev/null
+++ b/test/cypress/integration/ticket/negative/TicketLackDetail.spec.js
@@ -0,0 +1,147 @@
+/// <reference types="cypress" />
+describe('Ticket Lack detail', () => {
+    beforeEach(() => {
+        cy.login('developer');
+        cy.intercept('GET', /\/api\/Tickets\/itemLack\/5.*$/, {
+            statusCode: 200,
+            body: [
+                {
+                    saleFk: 33,
+                    code: 'OK',
+                    ticketFk: 142,
+                    nickname: 'Malibu Point',
+                    shipped: '2000-12-31T23:00:00.000Z',
+                    hour: 0,
+                    quantity: 50,
+                    agName: 'Super-Man delivery',
+                    alertLevel: 0,
+                    stateName: 'OK',
+                    stateId: 3,
+                    itemFk: 5,
+                    price: 1.79,
+                    alertLevelCode: 'FREE',
+                    zoneFk: 9,
+                    zoneName: 'Zone superMan',
+                    theoreticalhour: '2011-11-01T22:59:00.000Z',
+                    isRookie: 1,
+                    turno: 1,
+                    peticionCompra: 1,
+                    hasObservation: 1,
+                    hasToIgnore: 1,
+                    isBasket: 1,
+                    minTimed: 0,
+                    customerId: 1104,
+                    customerName: 'Tony Stark',
+                    observationTypeCode: 'administrative',
+                },
+            ],
+        }).as('getItemLack');
+
+        cy.visit('/#/ticket/negative/5');
+        cy.wait('@getItemLack');
+    });
+    describe('Table actions', () => {
+        it.skip('should display only one row in the lack list', () => {
+            cy.location('href').should('contain', '#/ticket/negative/5');
+
+            cy.get('[data-cy="changeItem"]').should('be.disabled');
+            cy.get('[data-cy="changeState"]').should('be.disabled');
+            cy.get('[data-cy="changeQuantity"]').should('be.disabled');
+            cy.get('[data-cy="itemProposal"]').should('be.disabled');
+            cy.get('[data-cy="transferLines"]').should('be.disabled');
+            cy.get('tr.cursor-pointer > :nth-child(1)').click();
+            cy.get('[data-cy="changeItem"]').should('be.enabled');
+            cy.get('[data-cy="changeState"]').should('be.enabled');
+            cy.get('[data-cy="changeQuantity"]').should('be.enabled');
+            cy.get('[data-cy="itemProposal"]').should('be.enabled');
+            cy.get('[data-cy="transferLines"]').should('be.enabled');
+        });
+    });
+    describe('Item proposal', () => {
+        beforeEach(() => {
+            cy.get('tr.cursor-pointer > :nth-child(1)').click();
+
+            cy.intercept('GET', /\/api\/Items\/getSimilar\?.*$/, {
+                statusCode: 200,
+                body: [
+                    {
+                        id: 1,
+                        longName: 'Ranged weapon longbow 50cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 0,
+                        match6: 0,
+                        match7: 0,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 20,
+                        calc_id: 6,
+                        counter: 0,
+                        minQuantity: 1,
+                        visible: null,
+                        price2: 1,
+                    },
+                    {
+                        id: 2,
+                        longName: 'Ranged weapon longbow 100cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 0,
+                        match6: 1,
+                        match7: 0,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 50,
+                        calc_id: 6,
+                        counter: 1,
+                        minQuantity: 5,
+                        visible: null,
+                        price2: 10,
+                    },
+                    {
+                        id: 3,
+                        longName: 'Ranged weapon longbow 200cm',
+                        subName: 'Stark Industries',
+                        tag5: 'Color',
+                        value5: 'Brown',
+                        match5: 1,
+                        match6: 1,
+                        match7: 1,
+                        match8: 1,
+                        tag6: 'Categoria',
+                        value6: '+1 precission',
+                        tag7: 'Tallos',
+                        value7: '1',
+                        tag8: null,
+                        value8: null,
+                        available: 185,
+                        calc_id: 6,
+                        counter: 10,
+                        minQuantity: 10,
+                        visible: null,
+                        price2: 100,
+                    },
+                ],
+            }).as('getItemGetSimilar');
+            cy.get('[data-cy="itemProposal"]').click();
+            cy.wait('@getItemGetSimilar');
+        });
+        describe('Replace item if', () => {
+            it.only('Quantity is less than available', () => {
+                cy.get(':nth-child(1) > .text-right  > .q-btn').click();
+            });
+        });
+    });
+});
diff --git a/test/cypress/integration/ticket/negative/TicketLackList.spec.js b/test/cypress/integration/ticket/negative/TicketLackList.spec.js
new file mode 100644
index 000000000..01ab4f621
--- /dev/null
+++ b/test/cypress/integration/ticket/negative/TicketLackList.spec.js
@@ -0,0 +1,36 @@
+/// <reference types="cypress" />
+describe('Ticket Lack list', () => {
+    beforeEach(() => {
+        cy.login('developer');
+        cy.intercept('GET', /Tickets\/itemLack\?.*$/, {
+            statusCode: 200,
+            body: [
+                {
+                    itemFk: 5,
+                    longName: 'Ranged weapon pistol 9mm',
+                    warehouseFk: 1,
+                    producer: null,
+                    size: 15,
+                    category: null,
+                    warehouse: 'Warehouse One',
+                    lack: -50,
+                    inkFk: 'SLV',
+                    timed: '2025-01-25T22:59:00.000Z',
+                    minTimed: '23:59',
+                    originFk: 'Holand',
+                },
+            ],
+        }).as('getLack');
+
+        cy.visit('/#/ticket/negative');
+    });
+
+    describe('Table actions', () => {
+        it('should display only one row in the lack list', () => {
+            cy.wait('@getLack', { timeout: 10000 });
+
+            cy.get('.q-virtual-scroll__content > :nth-child(1) > .sticky').click();
+            cy.location('href').should('contain', '#/ticket/negative/5');
+        });
+    });
+});
diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js
index 2984a4ee4..593021e6e 100644
--- a/test/cypress/integration/ticket/ticketList.spec.js
+++ b/test/cypress/integration/ticket/ticketList.spec.js
@@ -53,4 +53,29 @@ describe('TicketList', () => {
         cy.checkNotification('Data created');
         cy.url().should('match', /\/ticket\/\d+\/summary/);
     });
+
+    it('should show the corerct problems', () => {
+        cy.intercept('GET', '**/api/Tickets/filter*', (req) => {
+            req.headers['cache-control'] = 'no-cache';
+            req.headers['pragma'] = 'no-cache';
+            req.headers['expires'] = '0';
+
+            req.on('response', (res) => {
+                delete res.headers['if-none-match'];
+                delete res.headers['if-modified-since'];
+            });
+        }).as('ticket');
+
+        cy.get('[data-cy="Warehouse_select"]').type('Warehouse Five');
+        cy.get('.q-menu .q-item').contains('Warehouse Five').click();
+        cy.wait('@ticket').then((interception) => {
+            const data = interception.response.body[1];
+            expect(data.hasComponentLack).to.equal(1);
+            expect(data.isTooLittle).to.equal(1);
+            expect(data.hasItemShortage).to.equal(1);
+        });
+        cy.get('.icon-components').should('exist');
+        cy.get('.icon-unavailable').should('exist');
+        cy.get('.icon-isTooLittle').should('exist');
+    });
 });
diff --git a/test/cypress/integration/vnComponent/VnShortcut.spec.js b/test/cypress/integration/vnComponent/VnShortcut.spec.js
index b49b4e964..e08c44635 100644
--- a/test/cypress/integration/vnComponent/VnShortcut.spec.js
+++ b/test/cypress/integration/vnComponent/VnShortcut.spec.js
@@ -28,6 +28,17 @@ describe('VnShortcuts', () => {
             });
 
             cy.url().should('include', module);
+            if (['monitor', 'claim'].includes(module)) {
+                return;
+            }
+            cy.waitForElement('.q-page').should('exist');
+            cy.dataCy('vnTableCreateBtn').should('exist');
+            cy.get('.q-page').trigger('keydown', {
+                ctrlKey: true,
+                altKey: true,
+                key: '+',
+            });
+            cy.get('#formModel').should('exist');
         });
     }
 });
diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js
index 95a075fb3..70ded3f79 100644
--- a/test/cypress/integration/zone/zoneBasicData.spec.js
+++ b/test/cypress/integration/zone/zoneBasicData.spec.js
@@ -1,5 +1,6 @@
 describe('ZoneBasicData', () => {
     const priceBasicData = '[data-cy="Price_input"]';
+    const saveBtn = '.q-btn-group > .q-btn--standard';
 
     beforeEach(() => {
         cy.viewport(1280, 720);
@@ -8,20 +9,27 @@ describe('ZoneBasicData', () => {
     });
 
     it('should throw an error if the name is empty', () => {
-        cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.intercept('GET', /\/api\/Zones\/4./).as('zone');
+
+        cy.wait('@zone').then(() => {
+            cy.get('[data-cy="zone-basic-data-name"] input').type(
+                '{selectall}{backspace}',
+            );
+        });
+
+        cy.get(saveBtn).click();
         cy.checkNotification("can't be blank");
     });
 
     it('should throw an error if the price is empty', () => {
         cy.get(priceBasicData).clear();
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.get(saveBtn).click();
         cy.checkNotification('cannot be blank');
     });
 
     it("should edit the basicData's zone", () => {
         cy.get('.q-card > :nth-child(1)').type(' modified');
-        cy.get('.q-btn-group > .q-btn--standard').click();
+        cy.get(saveBtn).click();
         cy.checkNotification('Data saved');
     });
 });
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 92b38dc94..bc8158b62 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -89,36 +89,55 @@ Cypress.Commands.add('getValue', (selector) => {
 });
 
 // Fill Inputs
-Cypress.Commands.add('selectOption', (selector, option, timeout = 5000) => {
+Cypress.Commands.add('selectOption', (selector, option, timeout = 2500) => {
     cy.waitForElement(selector, timeout);
-    cy.get(selector).click();
-    cy.get(selector).invoke('data', 'url').as('dataUrl');
-    cy.get(selector)
-        .clear()
-        .type(option)
-        .then(() => {
-            cy.get('.q-menu', { timeout })
-                .should('be.visible') // Asegurarse de que el menú está visible
-                .and('exist') // Verificar que el menú existe
-                .then(() => {
-                    cy.get('@dataUrl').then((url) => {
-                        if (url) {
-                            // Esperar a que el menú no esté visible (desaparezca)
-                            cy.get('.q-menu').should('not.be.visible');
-                            // Ahora esperar a que el menú vuelva a aparecer
-                            cy.get('.q-menu').should('be.visible').and('exist');
-                        }
-                    });
-                });
-        });
 
-    // Finalmente, seleccionar la opción deseada
-    cy.get('.q-menu:visible') // Asegurarse de que estamos dentro del menú visible
-        .find('.q-item') // Encontrar los elementos de las opciones
-        .contains(option) // Verificar que existe una opción que contenga el texto deseado
-        .click(); // Hacer clic en la opción
+    cy.get(selector, { timeout })
+        .should('exist')
+        .should('be.visible')
+        .click()
+        .then(($el) => {
+            cy.wrap($el.is('input') ? $el : $el.find('input'))
+                .invoke('attr', 'aria-controls')
+                .then((ariaControl) => selectItem(selector, option, ariaControl));
+        });
 });
 
+function selectItem(selector, option, ariaControl, hasWrite = true) {
+    if (!hasWrite) cy.wait(100);
+
+    getItems(ariaControl).then((items) => {
+        const matchingItem = items
+            .toArray()
+            .find((item) => item.innerText.includes(option));
+        if (matchingItem) return cy.wrap(matchingItem).click();
+
+        if (hasWrite) cy.get(selector).clear().type(option, { delay: 0 });
+        return selectItem(selector, option, ariaControl, false);
+    });
+}
+
+function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) {
+    // Se intenta obtener la lista de opciones del desplegable de manera recursiva
+    return cy
+        .get('#' + ariaControl, { timeout })
+        .should('exist')
+        .find('.q-item')
+        .should('exist')
+        .then(($items) => {
+            if (!$items?.length || $items.first().text().trim() === '') {
+                if (Cypress._.now() - startTime > timeout) {
+                    throw new Error(
+                        `getItems: Tiempo de espera (${timeout}ms) excedido.`,
+                    );
+                }
+                return getItems(ariaControl, startTime, timeout);
+            }
+
+            return cy.wrap($items);
+        });
+}
+
 Cypress.Commands.add('countSelectOptions', (selector, option) => {
     cy.waitForElement(selector);
     cy.get(selector).click({ force: true });
diff --git a/test/cypress/support/waitUntil.js b/test/cypress/support/waitUntil.js
index 5fb47a2d8..359f8643f 100644
--- a/test/cypress/support/waitUntil.js
+++ b/test/cypress/support/waitUntil.js
@@ -1,7 +1,7 @@
 const waitUntil = (subject, checkFunction, originalOptions = {}) => {
     if (!(checkFunction instanceof Function)) {
         throw new Error(
-            '`checkFunction` parameter should be a function. Found: ' + checkFunction
+            '`checkFunction` parameter should be a function. Found: ' + checkFunction,
         );
     }
 

From 0b3e8dedf9a3dfde8e414c12e071d4a8a08f9019 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 25 Feb 2025 09:56:16 +0100
Subject: [PATCH 28/28] fix: merge revert

---
 src/components/FormModel.vue | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index c1cd80ce3..182eeaafe 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -307,38 +307,6 @@ async function onKeyup(evt) {
     }
 }
 
-async function onKeyup(evt) {
-    if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
-        const input = evt.target;
-        if (input.type == 'textarea' && evt.shiftKey) {
-            let { selectionStart, selectionEnd } = input;
-            input.value =
-                input.value.substring(0, selectionStart) +
-                '\n' +
-                input.value.substring(selectionEnd);
-            selectionStart = selectionEnd = selectionStart + 1;
-            return;
-        }
-        await save();
-    }
-}
-
-async function onKeyup(evt) {
-    if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
-        const input = evt.target;
-        if (input.type == 'textarea' && evt.shiftKey) {
-            let { selectionStart, selectionEnd } = input;
-            input.value =
-                input.value.substring(0, selectionStart) +
-                '\n' +
-                input.value.substring(selectionEnd);
-            selectionStart = selectionEnd = selectionStart + 1;
-            return;
-        }
-        await save();
-    }
-}
-
 defineExpose({
     save,
     isLoading,