diff --git a/package.json b/package.json
index c638b6c32..9d14e8727 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
         "axios": "^1.4.0",
         "chromium": "^3.0.3",
         "croppie": "^2.6.5",
+        "moment": "^2.30.1",
         "pinia": "^2.1.3",
         "quasar": "^2.14.5",
         "validator": "^13.9.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 83dfa0469..7bf640347 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,6 +20,9 @@ dependencies:
   croppie:
     specifier: ^2.6.5
     version: 2.6.5
+  moment:
+    specifier: ^2.30.1
+    version: 2.30.1
   pinia:
     specifier: ^2.1.3
     version: 2.1.7(typescript@5.5.4)(vue@3.4.19)
@@ -832,8 +835,8 @@ packages:
       vue-i18n:
         optional: true
     dependencies:
-      '@intlify/message-compiler': 10.0.0
-      '@intlify/shared': 10.0.0
+      '@intlify/message-compiler': 11.0.0-rc.1
+      '@intlify/shared': 11.0.0-rc.1
       jsonc-eslint-parser: 1.4.1
       source-map: 0.6.1
       vue-i18n: 9.9.1(vue@3.4.19)
@@ -847,11 +850,11 @@ packages:
       '@intlify/message-compiler': 9.9.1
       '@intlify/shared': 9.9.1
 
-  /@intlify/message-compiler@10.0.0:
-    resolution: {integrity: sha512-OcaWc63NC/9p1cMdgoNKBj4d61BH8sUW1Hfs6YijTd9656ZR4rNqXAlRnBrfS5ABq0vjQjpa8VnyvH9hK49yBw==}
+  /@intlify/message-compiler@11.0.0-rc.1:
+    resolution: {integrity: sha512-TGw2uBfuTFTegZf/BHtUQBEKxl7Q/dVGLoqRIdw8lFsp9g/53sYn5iD+0HxIzdYjbWL6BTJMXCPUHp9PxDTRPw==}
     engines: {node: '>= 16'}
     dependencies:
-      '@intlify/shared': 10.0.0
+      '@intlify/shared': 11.0.0-rc.1
       source-map-js: 1.0.2
     dev: true
 
@@ -862,8 +865,8 @@ packages:
       '@intlify/shared': 9.9.1
       source-map-js: 1.0.2
 
-  /@intlify/shared@10.0.0:
-    resolution: {integrity: sha512-6ngLfI7DOTew2dcF9WMJx+NnMWghMBhIiHbGg+wRvngpzD5KZJZiJVuzMsUQE1a5YebEmtpTEfUrDp/NqVGdiw==}
+  /@intlify/shared@11.0.0-rc.1:
+    resolution: {integrity: sha512-8tR1xe7ZEbkabTuE/tNhzpolygUn9OaYp9yuYAF4MgDNZg06C3Qny80bes2/e9/Wm3aVkPUlCw6WgU7mQd0yEg==}
     engines: {node: '>= 16'}
     dev: true
 
@@ -887,7 +890,7 @@ packages:
         optional: true
     dependencies:
       '@intlify/bundle-utils': 4.0.0(vue-i18n@9.9.1)
-      '@intlify/shared': 10.0.0
+      '@intlify/shared': 11.0.0-rc.1
       '@rollup/pluginutils': 4.2.1
       '@vue/compiler-sfc': 3.4.19
       debug: 4.3.4(supports-color@8.1.1)
@@ -4960,6 +4963,10 @@ packages:
       uuid: 8.3.2
     dev: true
 
+  /moment@2.30.1:
+    resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+    dev: false
+
   /ms@2.0.0:
     resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
 
diff --git a/src/components/common/VnChangePassword.vue b/src/components/common/VnChangePassword.vue
index 79784f3c5..d8374498f 100644
--- a/src/components/common/VnChangePassword.vue
+++ b/src/components/common/VnChangePassword.vue
@@ -2,9 +2,9 @@
 import { ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import VnRow from '../ui/VnRow.vue';
-import VnInput from './VnInput.vue';
 import FetchData from '../FetchData.vue';
 import useNotify from 'src/composables/useNotify';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const props = defineProps({
     submitFn: { type: Function, default: () => {} },
@@ -70,19 +70,19 @@ defineExpose({ show: () => changePassDialog.value.show() });
             </QCardSection>
             <QForm ref="form">
                 <QCardSection>
-                    <VnInput
+                    <VnInputPassword
                         v-if="props.askOldPass"
                         :label="t('Old password')"
                         v-model="passwords.oldPassword"
-                        type="password"
                         :required="true"
+                        :toggle-visibility="true"
                         autofocus
                     />
-                    <VnInput
+                    <VnInputPassword
                         :label="t('New password')"
                         v-model="passwords.newPassword"
-                        type="password"
                         :required="true"
+                        :toggle-visibility="true"
                         :info="
                             t('passwordRequirements', {
                                 length: requirements.length,
@@ -95,10 +95,10 @@ defineExpose({ show: () => changePassDialog.value.show() });
                         autofocus
                     />
 
-                    <VnInput
+                    <VnInputPassword
                         :label="t('Repeat password')"
                         v-model="passwords.repeatPassword"
-                        type="password"
+                        :toggle-visibility="true"
                     />
                 </QCardSection>
             </QForm>
diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 3cecf760a..4c7445aab 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -45,6 +45,7 @@ const $props = defineProps({
 });
 
 const vnInputRef = ref(null);
+const showPassword = ref(false);
 const value = computed({
     get() {
         return $props.modelValue;
@@ -134,7 +135,7 @@ const handleInsertMode = (e) => {
             hide-bottom-space
             :data-cy="$attrs.dataCy ?? $attrs.label + '_input'"
         >
-            <template v-if="$slots.prepend" #prepend>
+            <template #prepend>
                 <slot name="prepend" />
             </template>
             <template #append>
@@ -158,7 +159,7 @@ const handleInsertMode = (e) => {
                             emit('remove');
                         }
                     "
-                ></QIcon>
+                />
                 <slot name="append" v-if="$slots.append && !$attrs.disabled" />
                 <QIcon v-if="info" name="info">
                     <QTooltip max-width="350px">
@@ -169,18 +170,3 @@ const handleInsertMode = (e) => {
         </QInput>
     </div>
 </template>
-<i18n>
-    en:
-        inputMin: Must be more than {value}
-        maxLength: The value exceeds {value} characters
-        inputMax: Must be less than {value}
-    es:
-        inputMin: Debe ser mayor a {value}
-        maxLength: El valor excede los {value} carácteres
-        inputMax: Debe ser menor a {value}
-</i18n>
-<style lang="scss">
-.q-field__append {
-    padding-inline: 0;
-}
-</style>
diff --git a/src/components/common/VnInputPassword.vue b/src/components/common/VnInputPassword.vue
new file mode 100644
index 000000000..56981c0c3
--- /dev/null
+++ b/src/components/common/VnInputPassword.vue
@@ -0,0 +1,31 @@
+<script setup>
+import VnInput from 'src/components/common/VnInput.vue';
+import { ref } from 'vue';
+
+const model = defineModel({ type: [Number, String] });
+const $props = defineProps({
+    toggleVisibility: {
+        type: Boolean,
+        default: false,
+    },
+});
+
+const showPassword = ref(false);
+</script>
+<template>
+    <VnInput
+        v-bind="{ ...$attrs }"
+        v-model="model"
+        :type="
+            $props.toggleVisibility ? (showPassword ? 'text' : 'password') : $attrs.type
+        "
+    >
+        <template #append v-if="toggleVisibility">
+            <QIcon
+                :name="showPassword ? 'visibility_off' : 'visibility'"
+                class="cursor-pointer"
+                @click="showPassword = !showPassword"
+            />
+        </template>
+    </VnInput>
+</template>
diff --git a/src/components/ui/__tests__/FetchedTags.spec.js b/src/components/ui/__tests__/FetchedTags.spec.js
new file mode 100644
index 000000000..3c658a80e
--- /dev/null
+++ b/src/components/ui/__tests__/FetchedTags.spec.js
@@ -0,0 +1,81 @@
+import { describe, expect, it } from 'vitest';
+import { createWrapper } from 'app/test/vitest/helper';
+import FetchedTags from 'src/components/ui/FetchedTags.vue';
+
+describe('tags computed property', () => {
+    it('returns an object with the correct keys and values', () => {
+        const vm = createWrapper(FetchedTags, {
+            props: {
+                item: {
+                    tag1: 'JavaScript',
+                    value1: 'Programming Language',
+                    tag2: 'Vue',
+                    value2: 'Framework',
+                    tag3: 'EmptyTag',
+                },
+                tag: 'tag',
+                value: 'value',
+                columns: 2,
+            },
+        }).vm;
+        expect(vm.tags).toEqual({
+            JavaScript: 'Programming Language',
+            Vue: 'Framework',
+            EmptyTag: '',
+        });
+    });
+
+    it('returns an empty object if the item prop is an empty object', () => {
+        const vm = createWrapper(FetchedTags, {
+            props: {
+                item: {},
+                tag: 'tag',
+                value: 'value',
+            },
+        }).vm;
+        expect(vm.tags).toEqual({});
+    });
+
+    it('should calculate the correct columnStyle when columns prop is defined', () => {
+        const vm = createWrapper(FetchedTags, {
+            props: {
+                item: {
+                    tag1: 'JavaScript',
+                    value1: 'Programming Language',
+                    tag2: 'Vue',
+                    value2: 'Framework',
+                    tag3: 'EmptyTag',
+                },
+                tag: 'tag',
+                value: 'value',
+                columns: 2,
+            },
+        }).vm;
+
+        const expectedStyle = {
+            'grid-template-columns': 'repeat(2, 1fr)',
+            'max-width': '8rem', 
+        };
+
+        expect(vm.columnStyle).toEqual(expectedStyle);
+    });
+
+    it('should return an empty object for columnStyle when columns prop is not defined', () => {
+        const vm = createWrapper(FetchedTags, {
+            props: {
+                item: {
+                    tag1: 'JavaScript',
+                    value1: 'Programming Language',
+                    tag2: 'Vue',
+                    value2: 'Framework',
+                    tag3: 'EmptyTag',
+                },
+                tag: 'tag',
+                value: 'value',
+                columns: null,
+            },
+        }).vm;
+
+        expect(vm.columnStyle).toEqual({});
+    });
+});
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 1f4234a00..c13c4f9a6 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -104,12 +104,14 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
 
         store.hasMoreData = limit && response.data.length >= limit;
 
-        processData(response.data, { map: !!store.mapKey, append });
-        if (!append && !isDialogOpened()) updateRouter && updateStateParams();
-
+        if (!append && !isDialogOpened() && updateRouter) {
+            if (updateStateParams(response.data)?.redirect) return;
+        }
         store.isLoading = false;
         canceller = null;
 
+        processData(response.data, { map: !!store.mapKey, append });
+
         return response;
     }
 
@@ -239,7 +241,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
         if (Object.values(store.userParams).length) await fetch({});
     }
 
-    function updateStateParams() {
+    function updateStateParams(data) {
         if (!route?.path) return;
         const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
         if (store?.searchUrl)
@@ -256,15 +258,15 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
             const { path } = matches.at(-1);
 
             const to =
-                store?.data?.length === 1
-                    ? path.replace(/\/(list|:id)|-list/, `/${store.data[0].id}`)
+                data?.length === 1
+                    ? path.replace(/\/(list|:id)|-list/, `/${data[0].id}`)
                     : path.replace(/:id.*/, '');
 
             if (route.path != to) {
                 const pushUrl = { path: to };
                 if (to.endsWith('/list') || to.endsWith('/'))
                     pushUrl.query = newUrl.query;
-                return router.push(pushUrl);
+                return router.push(pushUrl) && { redirect: true };
             }
         }
 
diff --git a/src/filters/toDateHourMin.js b/src/filters/toDateHourMin.js
index 2b6995c01..c813840cb 100644
--- a/src/filters/toDateHourMin.js
+++ b/src/filters/toDateHourMin.js
@@ -1,5 +1,6 @@
 export default function toDateHourMin(date) {
-    const dateHour = new Date(date).toLocaleDateString('es-ES', {
+    if (!date) return date;
+    return new Date(date).toLocaleDateString('es-ES', {
         timeZone: 'Europe/Madrid',
         year: 'numeric',
         month: '2-digit',
@@ -7,5 +8,4 @@ export default function toDateHourMin(date) {
         hour: '2-digit',
         minute: '2-digit',
     });
-    return dateHour;
 }
diff --git a/src/filters/toDateHourMinSec.js b/src/filters/toDateHourMinSec.js
index cfc9506fb..51df725e4 100644
--- a/src/filters/toDateHourMinSec.js
+++ b/src/filters/toDateHourMinSec.js
@@ -1,5 +1,6 @@
 export default function toDateHourMinSec(date) {
-    const dateHour = new Date(date).toLocaleDateString('es-ES', {
+    if (!date) return date;
+    return new Date(date).toLocaleDateString('es-ES', {
         timeZone: 'Europe/Madrid',
         year: 'numeric',
         month: '2-digit',
@@ -8,5 +9,4 @@ export default function toDateHourMinSec(date) {
         minute: '2-digit',
         second: '2-digit',
     });
-    return dateHour;
 }
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 038167281..71440760b 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -456,12 +456,26 @@ entry:
             packingOut: Package out
             landing: Landing
             isExcludedFromAvailable: Es inventory
+    params:
+        toShipped: To
+        fromShipped: From
+        warehouseiNFk: Warehouse
+        daysOnward: Days onward
+        daysAgo: Days ago
+        warehouseInFk: Warehouse in
 ticket:
     params:
         ticketFk: Ticket ID
         weekDay: Weekday
         agencyModeFk: Agency
         id: Worker
+        state: State
+        created: Created
+        externalId: External ID
+        counter: Counter
+        freightItemName: Freight item name
+        packageItemName: Package item name
+        longName: Long name
     card:
         customerId: Customer ID
         customerCard: Customer card
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 6a066cb15..3f0830f33 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -457,12 +457,25 @@ 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
 ticket:
     params:
         ticketFk: ID de ticket
         weekDay: Salida
         agencyModeFk: Agencia
         id: Comercial
+        created: Creado
+        state: Estado
+        externalId: ID externo
+        counter: Contador
+        freightItemName: Nombre
+        packageItemName: Embalaje
+        longName: Descripción
     card:
         customerId: ID cliente
         customerCard: Ficha del cliente
diff --git a/src/pages/Account/AccountCreate.vue b/src/pages/Account/AccountCreate.vue
index 6b7c049c8..b925ff06a 100644
--- a/src/pages/Account/AccountCreate.vue
+++ b/src/pages/Account/AccountCreate.vue
@@ -6,6 +6,7 @@ import FormModelPopup from 'components/FormModelPopup.vue';
 import VnSelect from 'src/components/common/VnSelect.vue';
 import FetchData from 'components/FetchData.vue';
 import VnInput from 'src/components/common/VnInput.vue';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const router = useRouter();
@@ -61,10 +62,10 @@ const redirectToAccountBasicData = (_, { id }) => {
                     hide-selected
                     :rules="validate('VnUser.roleFk')"
                 />
-                <VnInput
+                <VnInputPassword
                     v-model="data.password"
                     :label="t('ldap.password')"
-                    type="password"
+                    :toggle-visibility="true"
                     :rules="validate('VnUser.password')"
                 />
                 <QCheckbox
diff --git a/src/pages/Account/AccountLdap.vue b/src/pages/Account/AccountLdap.vue
index bb220aa2e..4710f961b 100644
--- a/src/pages/Account/AccountLdap.vue
+++ b/src/pages/Account/AccountLdap.vue
@@ -8,6 +8,7 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const { notify } = useNotify();
@@ -128,10 +129,9 @@ onMounted(async () => await getInitialLdapConfig());
                         :required="true"
                         :rules="validate('LdapConfig.rdn')"
                     />
-                    <VnInput
+                    <VnInputPassword
                         :label="t('ldap.password')"
                         clearable
-                        type="password"
                         v-model="data.password"
                         :required="true"
                         :rules="validate('LdapConfig.password')"
diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue
index c1c75fcee..ea8daba0d 100644
--- a/src/pages/Account/AccountList.vue
+++ b/src/pages/Account/AccountList.vue
@@ -4,9 +4,9 @@ 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 VnInput from 'src/components/common/VnInput.vue';
 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();
@@ -168,10 +168,9 @@ function exprBuilder(param, value) {
             >
                 <template #more-create-dialog="{ data }">
                     <QCardSection>
-                        <VnInput
+                        <VnInputPassword
                             :label="t('Password')"
                             v-model="data.password"
-                            type="password"
                             :required="true"
                             autocomplete="new-password"
                         />
diff --git a/src/pages/Account/AccountSamba.vue b/src/pages/Account/AccountSamba.vue
index 699a638eb..7b36de85f 100644
--- a/src/pages/Account/AccountSamba.vue
+++ b/src/pages/Account/AccountSamba.vue
@@ -8,6 +8,7 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const { t } = useI18n();
 const { notify } = useNotify();
@@ -143,10 +144,9 @@ onMounted(async () => await getInitialSambaConfig());
                         v-model="data.adUser"
                         :rules="validate('SambaConfigs.adUser')"
                     />
-                    <VnInput
+                    <VnInputPassword
                         :label="t('samba.passwordAD')"
                         clearable
-                        type="password"
                         v-model="data.adPassword"
                     />
                     <VnInput
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index 1780b4247..c091962fc 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -9,6 +9,7 @@ import { useArrayData } from 'src/composables/useArrayData';
 import VnConfirm from 'src/components/ui/VnConfirm.vue';
 import VnChangePassword from 'src/components/common/VnChangePassword.vue';
 import { useQuasar } from 'quasar';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const $props = defineProps({
     hasAccount: {
@@ -97,14 +98,13 @@ async function sync() {
                     <QTooltip>{{ t('account.card.actions.sync.tooltip') }}</QTooltip>
                 </QIcon></QCheckbox
             >
-            <QInput
+            <VnInputPassword
                 v-if="shouldSyncPassword"
                 :label="t('login.password')"
                 v-model="syncPassword"
                 class="full-width"
                 clearable
                 clear-icon="close"
-                type="password"
             />
         </template>
     </VnConfirm>
diff --git a/src/pages/Customer/locale/en.yml b/src/pages/Customer/locale/en.yml
index 1d2497ded..1918838b7 100644
--- a/src/pages/Customer/locale/en.yml
+++ b/src/pages/Customer/locale/en.yml
@@ -95,6 +95,7 @@ customer:
             isToBeMailed: Mailing
             hasSepaVnl: VNL B2B received
     params:
+        id: Id
         isWorker: Is Worker
         payMethod: Payment Method
         workerFk: Author
@@ -102,4 +103,15 @@ customer:
         created: Last Update Date
         creditInsurance: Credit Insurance
         defaulterSinced: Defaulted Since
-        hasRecovery: Has Recovery
\ No newline at end of file
+        hasRecovery: Has Recovery
+        socialName: Social name
+        city: City
+        phone: Phone
+        postcode: Postcode
+        campaign: Campaign
+        grouped: Grouped
+        search: Contains
+        itemId: Item Id
+        ticketFk: Ticket Id
+        description: Description
+        quantity: Quantity
diff --git a/src/pages/Customer/locale/es.yml b/src/pages/Customer/locale/es.yml
index 1b56f6805..d5db3df1b 100644
--- a/src/pages/Customer/locale/es.yml
+++ b/src/pages/Customer/locale/es.yml
@@ -97,6 +97,7 @@ customer:
             isToBeMailed: Env. emails
             hasSepaVnl: Recibido B2B VNL
     params:
+        id: ID
         isWorker: Es trabajador
         payMethod: F. Pago
         workerFk: Autor
@@ -104,4 +105,15 @@ customer:
         created: Fecha Ú. O.
         creditInsurance: Crédito A.
         defaulterSinced: Desde
-        hasRecovery: Tiene recobro
\ No newline at end of file
+        hasRecovery: Tiene recobro
+        socialName: Razón social
+        campaign: Campaña
+        city: Ciudad
+        phone: Teléfono
+        postcode: Código postal
+        grouped: Agrupado
+        search: Contiene
+        itemId: Id Artículo
+        ticketFk: Id Ticket
+        description: Descripción
+        quantity: Cantidad
diff --git a/src/pages/Entry/EntryBuysTableDialog.vue b/src/pages/Entry/EntryBuysTableDialog.vue
index 3975bff19..a2d8c9117 100644
--- a/src/pages/Entry/EntryBuysTableDialog.vue
+++ b/src/pages/Entry/EntryBuysTableDialog.vue
@@ -1,24 +1,24 @@
 <script setup>
-import { computed } from 'vue';
+import { computed, ref } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { QBtn } from 'quasar';
 
 import VnPaginate from 'src/components/ui/VnPaginate.vue';
 import { usePrintService } from 'composables/usePrintService';
-const { openReport } = usePrintService();
 
+const { openReport } = usePrintService();
+const buyRows = ref([]);
 const route = useRoute();
 const { t } = useI18n();
 const $props = defineProps({
     id: {
-        type: String,
+        type: Number,
         required: false,
         default: null,
     },
 });
 const entityId = computed(() => $props.id || route.params.id);
-
 const entriesTableColumns = computed(() => [
     {
         align: 'left',
@@ -63,34 +63,39 @@ const entriesTableColumns = computed(() => [
         field: 'grouping',
     },
 ]);
-</script>
 
+function downloadCSV(rows) {
+    const headers = ['id', 'itemFk', 'name', 'stickers', 'packing', 'comment'];
+
+    const csvRows = rows.map((row) => {
+        const buy = row;
+        const item = buy.item || {};
+
+        return [
+            buy.id,
+            buy.itemFk,
+            item.name || '',
+            buy.stickers,
+            buy.packing,
+            item.comment || '',
+        ].join(',');
+    });
+
+    const csvContent = [headers.join(','), ...csvRows].join('\n');
+
+    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
+    const url = URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.setAttribute('download', `${entityId.value}data.csv`);
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+}
+</script>
 <template>
     <QDialog ref="dialogRef">
         <QCard style="min-width: 800px">
-            <QCardSection class="row items-center q-pb-none">
-                <QAvatar
-                    :icon="icon"
-                    color="primary"
-                    text-color="white"
-                    size="xl"
-                    v-if="icon"
-                />
-                <span class="text-h6 text-grey">{{ title }}</span>
-                <QSpace />
-                <QBtn icon="close" :disable="isLoading" flat round dense v-close-popup />
-            </QCardSection>
-            <QCardActions align="right">
-                <QBtn
-                    :label="t('myEntries.printLabels')"
-                    color="primary"
-                    icon="print"
-                    :loading="isLoading"
-                    @click="openReport(`Entries/${entityId}/labelSupplier`)"
-                    unelevated
-                    autofocus
-                />
-            </QCardActions>
             <QCardSection class="row items-center">
                 <VnPaginate
                     ref="entryBuysPaginateRef"
@@ -101,6 +106,7 @@ const entriesTableColumns = computed(() => [
                 >
                     <template #body="{ rows }">
                         <QTable
+                            ref="buyRows"
                             :rows="rows"
                             :columns="entriesTableColumns"
                             row-key="id"
@@ -110,6 +116,26 @@ const entriesTableColumns = computed(() => [
                             :grid="$q.screen.lt.md"
                             :no-data-label="t('globals.noResults')"
                         >
+                            <template #top-left>
+                                <QBtn
+                                    :label="t('myEntries.downloadCsv')"
+                                    color="primary"
+                                    icon="csv"
+                                    @click="downloadCSV(rows)"
+                                    unelevated
+                                />
+                            </template>
+                            <template #top-right>
+                                <QBtn
+                                    class="q-mr-lg"
+                                    :label="t('myEntries.printLabels')"
+                                    color="primary"
+                                    icon="print"
+                                    @click="
+                                        openReport(`Entries/${entityId}/labelSupplier`)
+                                    "
+                                />
+                            </template>
                             <template #body="props">
                                 <QTr>
                                     <QTd v-for="col in props.cols" :key="col.name">
@@ -118,7 +144,6 @@ const entriesTableColumns = computed(() => [
                                     <QBtn
                                         icon="visibility"
                                         v-if="props.row.stickers > 0"
-                                        :loading="isLoading"
                                         @click="
                                             openReport(
                                                 `Entries/${props.row.id}/buy-label-supplier`
diff --git a/src/pages/Entry/MyEntries.vue b/src/pages/Entry/MyEntries.vue
index 91a29b190..dbe05eb88 100644
--- a/src/pages/Entry/MyEntries.vue
+++ b/src/pages/Entry/MyEntries.vue
@@ -102,7 +102,7 @@ const columns = computed(() => [
         actions: [
             {
                 title: t('myEntries.printLabels'),
-                icon: 'print',
+                icon: 'move_item',
                 isPrimary: true,
                 action: (row) => printBuys(row.id),
             },
diff --git a/src/pages/Entry/locale/en.yml b/src/pages/Entry/locale/en.yml
index 68cc9caa7..6e41566d0 100644
--- a/src/pages/Entry/locale/en.yml
+++ b/src/pages/Entry/locale/en.yml
@@ -17,13 +17,6 @@ myEntries:
     warehouseInFk: Warehouse in
     daysOnward: Days onward
     daysAgo: Days ago
+    downloadCsv: Download CSV
 wasteRecalc:
     recalcOk: The wastes were successfully recalculated
-entry:
-    params:
-        toShipped: To
-        fromShipped: From
-        warehouseiNFk: Warehouse
-        daysOnward: Days onward
-        daysAgo: Days ago
-        
\ No newline at end of file
diff --git a/src/pages/Entry/locale/es.yml b/src/pages/Entry/locale/es.yml
index cc9a4ff7b..7e627b09f 100644
--- a/src/pages/Entry/locale/es.yml
+++ b/src/pages/Entry/locale/es.yml
@@ -20,13 +20,6 @@ myEntries:
     warehouseInFk: Alm. entrada
     daysOnward: Días adelante
     daysAgo: Días atras
+    downloadCsv: Descargar CSV
 wasteRecalc:
     recalcOk: Se han recalculado las mermas correctamente
-entry:
-    params:
-        toShipped: Hasta
-        fromShipped: Desde
-        warehouseInFk: Alm. entrada
-        daysOnward: Días adelante
-        daysAgo: Días atras
-        
\ No newline at end of file
diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue
index 44b868ebd..a4c3566a9 100644
--- a/src/pages/Login/LoginMain.vue
+++ b/src/pages/Login/LoginMain.vue
@@ -3,7 +3,7 @@ import { ref } from 'vue';
 import { Notify } from 'quasar';
 import { useI18n } from 'vue-i18n';
 import { useRouter } from 'vue-router';
-
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 import { useSession } from 'src/composables/useSession';
 import { useLogin } from 'src/composables/useLogin';
 
@@ -63,11 +63,10 @@ async function onSubmit() {
             :rules="[(val) => (val && val.length > 0) || t('login.fieldRequired')]"
             color="primary"
         />
-        <VnInput
-            type="password"
+        <VnInputPassword
             v-model="password"
             :label="t('login.password')"
-            lazy-rules
+            :toggle-visibility="true"
             :rules="[(val) => (val && val.length > 0) || t('login.fieldRequired')]"
             class="red"
         />
diff --git a/src/pages/Login/ResetPassword.vue b/src/pages/Login/ResetPassword.vue
index 2751f1ceb..081801e0e 100644
--- a/src/pages/Login/ResetPassword.vue
+++ b/src/pages/Login/ResetPassword.vue
@@ -7,6 +7,7 @@ import axios from 'axios';
 
 import VnInput from 'components/common/VnInput.vue';
 import VnOutForm from 'components/ui/VnOutForm.vue';
+import VnInputPassword from 'src/components/common/VnInputPassword.vue';
 
 const quasar = useQuasar();
 const router = useRouter();
@@ -54,8 +55,7 @@ async function onSubmit() {
 <template>
     <VnOutForm @submit="onSubmit" :title="t('globals.pageTitles.resetPassword')">
         <template #default>
-            <VnInput
-                type="password"
+            <VnInputPassword
                 :label="t('login.password')"
                 v-model="newPassword"
                 :info="
@@ -72,9 +72,8 @@ async function onSubmit() {
                 <template #prepend>
                     <QIcon name="password" />
                 </template>
-            </VnInput>
-            <VnInput
-                type="password"
+            </VnInputPassword>
+            <VnInputPassword
                 :label="t('resetPassword.repeatPassword')"
                 v-model="repeatPassword"
                 required
@@ -82,7 +81,7 @@ async function onSubmit() {
                 <template #prepend>
                     <QIcon name="password" />
                 </template>
-            </VnInput>
+            </VnInputPassword>
         </template>
         <template #buttons>
             <QBtn
diff --git a/src/pages/Route/locale/en.yml b/src/pages/Route/locale/en.yml
index 420d18dfe..7a1f9e1c0 100644
--- a/src/pages/Route/locale/en.yml
+++ b/src/pages/Route/locale/en.yml
@@ -1,4 +1,18 @@
 route:
+    params:
+        etd: ETD
+        tractorPlate: Plate
+        price: Price
+        observations: Observations
+        id: ID
+        name: Name
+        cmrFk: CMR id
+        hasCmrDms: Attached in gestdoc
+        ticketFk: Ticketd id
+        routeFk: Route id
+        shipped: Shipped
+        agencyAgreement: Agency agreement
+        agencyModeName: Agency route
     Worker: Worker
     Agency: Agency
     Vehicle: Vehicle
diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue
index 5892811e6..b658ca5fb 100644
--- a/src/pages/Supplier/Card/SupplierSummary.vue
+++ b/src/pages/Supplier/Card/SupplierSummary.vue
@@ -39,6 +39,7 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
         :url="`Suppliers/${entityId}/getSummary`"
         @on-fetch="(data) => setData(data)"
         data-key="SupplierSummary"
+        module-name="Supplier"
     >
         <template #header>
             <span>{{ supplier.id }} - {{ supplier.name }}</span>
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index c6fd2b7fa..166e86978 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -201,7 +201,7 @@ const getExpeditionState = async (expedition) => {
 
 const openGrafana = (expeditionFk) => {
     useOpenURL(
-        `https://grafana.verdnatura.es/d/d552ab74-85b4-4e7f-a279-fab7cd9c6124/control-de-expediciones?orgId=1&var-expeditionFk=${expeditionFk}`
+        `https://grafana.verdnatura.es/d/de1njb6p5answd/control-de-expediciones?orgId=1&var-expeditionFk=${expeditionFk}`
     );
 };
 
diff --git a/src/pages/Travel/ExtraCommunity.vue b/src/pages/Travel/ExtraCommunity.vue
index 7d7c5f07d..dee9d923a 100644
--- a/src/pages/Travel/ExtraCommunity.vue
+++ b/src/pages/Travel/ExtraCommunity.vue
@@ -597,7 +597,7 @@ const getColor = (percentage) => {
                             v-if="entry.isCustomInspectionRequired"
                             name="warning"
                             color="negative"
-                            size="xs"
+                            size="md"
                             :title="t('requiresInspection')"
                         >
                         </QIcon>
@@ -627,7 +627,7 @@ const getColor = (percentage) => {
                         <QBtn
                             v-if="entry.evaNotes"
                             icon="comment"
-                            size="sm"
+                            size="md"
                             flat
                             color="primary"
                         >
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index 8d54cb810..65fbf4b43 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -22,6 +22,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
 import { useArrayData } from 'composables/useArrayData';
 import { toTimeFormat, secondsToHoursMinutes } from 'filters/date.js';
 import toDateString from 'filters/toDateString.js';
+import moment from 'moment';
 import { date } from 'quasar';
 
 const route = useRoute();
@@ -64,6 +65,7 @@ const selectedDateFormatted = ref(toDateString(defaultDate.value));
 
 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' }])
@@ -278,7 +280,7 @@ const fetchHours = async () => {
 
 const fetchWeekData = async () => {
     const where = {
-        year: selectedDate.value.getFullYear(),
+        year: selectedDateYear.value,
         week: selectedWeekNumber.value,
     };
     const mail = (
@@ -370,7 +372,7 @@ const showReasonForm = () => {
 
 const updateWorkerTimeControlMail = async (state, reason) => {
     const params = {
-        year: selectedDate.value.getFullYear(),
+        year: selectedDateYear.value,
         week: selectedWeekNumber.value,
         state,
     };
@@ -400,7 +402,7 @@ const resendEmail = async () => {
     const params = {
         recipient: worker.value[0]?.user?.emailUser?.email,
         week: selectedWeekNumber.value,
-        year: selectedDate.value.getFullYear(),
+        year: selectedDateYear.value,
         workerId: Number(route.params.id),
         state: 'SENDED',
     };
diff --git a/src/pages/Worker/Card/WorkerTimeControlCalendar.vue b/src/pages/Worker/Card/WorkerTimeControlCalendar.vue
index 2717a71f4..46ae4b698 100644
--- a/src/pages/Worker/Card/WorkerTimeControlCalendar.vue
+++ b/src/pages/Worker/Card/WorkerTimeControlCalendar.vue
@@ -102,8 +102,7 @@ const getWorkWeekElements = () => {
 };
 
 const paintWorkWeeks = async () => {
-    for (var i = 0; i < workWeeksElements.value.length; i++) {
-        const element = workWeeksElements.value[i];
+    for (const element of workWeeksElements.value) {
         const week = Number(element.innerHTML);
         const weekState = workerTimeControlMailsMap.value.get(week);
         const { className, title } = stateClasses[weekState] || {};
diff --git a/test/cypress/integration/outLogin/login.spec.js b/test/cypress/integration/outLogin/login.spec.js
index 3db223cdb..2bd5a8c3b 100755
--- a/test/cypress/integration/outLogin/login.spec.js
+++ b/test/cypress/integration/outLogin/login.spec.js
@@ -19,6 +19,7 @@ describe('Login', () => {
     it('should fail to log in using wrong password', () => {
         cy.get('input[aria-label="Username"]').type('employee');
         cy.get('input[aria-label="Password"]').type('wrongPassword');
+        cy.get('.q-field__append > .q-icon');
         cy.get('button[type="submit"]').click();
         cy.get('.q-notification__message').should(
             'have.text',