diff --git a/src/boot/axios.js b/src/boot/axios.js
index 9b32275bd..99a163cca 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -5,8 +5,10 @@ import useNotify from 'src/composables/useNotify.js';
 
 const session = useSession();
 const { notify } = useNotify();
+const baseUrl = '/api/';
 
-axios.defaults.baseURL = '/api/';
+axios.defaults.baseURL = baseUrl;
+const axiosNoError = axios.create({ baseURL: baseUrl });
 
 const onRequest = (config) => {
     const token = session.getToken();
@@ -79,5 +81,7 @@ const onResponseError = (error) => {
 
 axios.interceptors.request.use(onRequest, onRequestError);
 axios.interceptors.response.use(onResponse, onResponseError);
+axiosNoError.interceptors.request.use(onRequest);
+axiosNoError.interceptors.response.use(onResponse);
 
-export { onRequest, onResponseError };
+export { onRequest, onResponseError, axiosNoError };
diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue
index 570d0cbfe..26160929c 100644
--- a/src/components/common/VnInput.vue
+++ b/src/components/common/VnInput.vue
@@ -67,9 +67,13 @@ const mixinRules = [
     requiredFieldRule,
     ...($attrs.rules ?? []),
     (val) => {
-        const { min } = vnInputRef.value.$attrs;
+        const { min, max } = vnInputRef.value.$attrs;
         if (!min) return null;
         if (min >= 0) if (Math.floor(val) < min) return t('inputMin', { value: min });
+        if (!max) return null;
+        if (max > 0) {
+            if (Math.floor(val) > max) return t('inputMax', { value: max });
+        }
     },
 ];
 </script>
@@ -116,8 +120,10 @@ const mixinRules = [
 <i18n>
     en:
         inputMin: Must be more than {value}
+        inputMax: Must be less than {value}
     es:
         inputMin: Debe ser mayor a {value}
+        inputMax: Debe ser menor a {value}
 </i18n>
 <style lang="scss">
 .q-field__append {
diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue
index 96e47d6d7..fd8993d6f 100644
--- a/src/components/common/VnInputDate.vue
+++ b/src/components/common/VnInputDate.vue
@@ -2,6 +2,7 @@
 import { onMounted, watch, computed, ref } from 'vue';
 import { date } from 'quasar';
 import { useI18n } from 'vue-i18n';
+import { useAttrs } from 'vue';
 
 const model = defineModel({ type: [String, Date] });
 const $props = defineProps({
@@ -14,29 +15,19 @@ const $props = defineProps({
         default: true,
     },
 });
+import { useValidator } from 'src/composables/useValidator';
+const { validations } = useValidator();
 
 const { t } = useI18n();
-const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
+const requiredFieldRule = (val) => validations().required($attrs.required, val);
 
 const dateFormat = 'DD/MM/YYYY';
 const isPopupOpen = ref();
 const hover = ref();
 const mask = ref();
+const $attrs = useAttrs();
 
-onMounted(() => {
-    // fix quasar bug
-    mask.value = '##/##/####';
-});
-
-const styleAttrs = computed(() => {
-    return $props.isOutlined
-        ? {
-              dense: true,
-              outlined: true,
-              rounded: true,
-          }
-        : {};
-});
+const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 
 const formattedDate = computed({
     get() {
@@ -48,15 +39,12 @@ const formattedDate = computed({
         let newDate;
         if (value) {
             // parse input
-            if (value.includes('/')) {
-                if (value.length == 6) value = value + new Date().getFullYear();
-                if (value.length >= 10) {
-                    if (value.at(2) == '/') value = value.split('/').reverse().join('/');
-                    value = date.formatDate(
-                        new Date(value).toISOString(),
-                        'YYYY-MM-DDTHH:mm:ss.SSSZ'
-                    );
-                }
+            if (value.includes('/') && value.length >= 10) {
+                if (value.at(2) == '/') value = value.split('/').reverse().join('/');
+                value = date.formatDate(
+                    new Date(value).toISOString(),
+                    'YYYY-MM-DDTHH:mm:ss.SSSZ'
+                );
             }
             const [year, month, day] = value.split('-').map((e) => parseInt(e));
             newDate = new Date(year, month - 1, day);
@@ -79,12 +67,25 @@ const formattedDate = computed({
 const popupDate = computed(() =>
     model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
 );
-
+onMounted(() => {
+    // fix quasar bug
+    mask.value = '##/##/####';
+});
 watch(
     () => model.value,
     (val) => (formattedDate.value = val),
     { immediate: true }
 );
+
+const styleAttrs = computed(() => {
+    return $props.isOutlined
+        ? {
+              dense: true,
+              outlined: true,
+              rounded: true,
+          }
+        : {};
+});
 </script>
 
 <template>
@@ -96,9 +97,10 @@ watch(
             placeholder="dd/mm/aaaa"
             v-bind="{ ...$attrs, ...styleAttrs }"
             :class="{ required: $attrs.required }"
-            :rules="$attrs.required ? [requiredFieldRule] : null"
+            :rules="mixinRules"
             :clearable="false"
             @click="isPopupOpen = true"
+            hide-bottom-space
         >
             <template #append>
                 <QIcon
diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue
index b3478bb23..42ec79479 100644
--- a/src/components/common/VnInputTime.vue
+++ b/src/components/common/VnInputTime.vue
@@ -1,8 +1,10 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { date } from 'quasar';
-
+import { useValidator } from 'src/composables/useValidator';
+const { validations } = useValidator();
+const $attrs = useAttrs();
 const model = defineModel({ type: String });
 const props = defineProps({
     timeOnly: {
@@ -16,8 +18,8 @@ const props = defineProps({
 });
 const initialDate = ref(model.value ?? Date.vnNew());
 const { t } = useI18n();
-const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
-
+const requiredFieldRule = (val) => validations().required($attrs.required, val);
+const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const dateFormat = 'HH:mm';
 const isPopupOpen = ref();
 const hover = ref();
@@ -74,9 +76,10 @@ function dateToTime(newDate) {
             v-bind="{ ...$attrs, ...styleAttrs }"
             :class="{ required: $attrs.required }"
             style="min-width: 100px"
-            :rules="$attrs.required ? [requiredFieldRule] : null"
+            :rules="mixinRules"
             @click="isPopupOpen = false"
             type="time"
+            hide-bottom-space
         >
             <template #append>
                 <QIcon
diff --git a/src/components/common/VnLocation.vue b/src/components/common/VnLocation.vue
index 8256ec5b0..b6cbfbafd 100644
--- a/src/components/common/VnLocation.vue
+++ b/src/components/common/VnLocation.vue
@@ -2,21 +2,37 @@
 import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
 import VnSelectDialog from 'components/common/VnSelectDialog.vue';
 import { useI18n } from 'vue-i18n';
-
+import { ref } from 'vue';
 const { t } = useI18n();
-const value = defineModel({ type: [String, Number, Object] });
+const emit = defineEmits(['update:model-value', 'update:options']);
 
+const props = defineProps({
+    location: {
+        type: Object,
+        default: null,
+    },
+});
+const modelValue = ref(
+    props.location
+        ? `${props.location?.postcode} - ${props.location?.city}(${props.location?.province?.name}), ${props.location?.country?.name}`
+        : null
+);
 function showLabel(data) {
     return `${data.code} - ${data.town}(${data.province}), ${data.country}`;
 }
+const handleModelValue = (data) => {
+    emit('update:model-value', data);
+};
 </script>
 <template>
     <VnSelectDialog
-        v-model="value"
-        option-value="code"
+        v-model="modelValue"
         option-filter-value="search"
-        :option-label="(opt) => showLabel(opt)"
+        :option-label="
+            (opt) => (typeof modelValue === 'string' ? modelValue : showLabel(opt))
+        "
         url="Postcodes/filter"
+        @update:model-value="handleModelValue"
         :use-like="false"
         :label="t('Location')"
         :placeholder="t('search_by_postalcode')"
@@ -27,7 +43,14 @@ function showLabel(data) {
         :emit-value="false"
     >
         <template #form>
-            <CreateNewPostcode @on-data-saved="(newValue) => (value = newValue)" />
+            <CreateNewPostcode
+                @on-data-saved="
+                    (newValue) => {
+                        modelValue = newValue;
+                        emit('update:model-value', newValue);
+                    }
+                "
+            />
         </template>
         <template #option="{ itemProps, opt }">
             <QItem v-bind="itemProps">
diff --git a/src/components/common/VnSectionMain.vue b/src/components/common/VnSectionMain.vue
index 0c1641ce1..9975b1011 100644
--- a/src/components/common/VnSectionMain.vue
+++ b/src/components/common/VnSectionMain.vue
@@ -20,6 +20,8 @@ onMounted(() => (stateStore.leftDrawer = $props.leftDrawer));
         </QScrollArea>
     </QDrawer>
     <QPageContainer>
-        <RouterView></RouterView>
+        <QPage>
+            <RouterView />
+        </QPage>
     </QPageContainer>
 </template>
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 1e3a32f48..ed842103f 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -1,7 +1,8 @@
 <script setup>
-import { ref, toRefs, computed, watch, onMounted } from 'vue';
+import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
 import { useI18n } from 'vue-i18n';
 import FetchData from 'src/components/FetchData.vue';
+import { useValidator } from 'src/composables/useValidator';
 const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
 
 const $props = defineProps({
@@ -82,10 +83,11 @@ const $props = defineProps({
         default: false,
     },
 });
-
+const { validations } = useValidator();
+const requiredFieldRule = (val) => validations().required($attrs.required, val);
+const $attrs = useAttrs();
 const { t } = useI18n();
-const requiredFieldRule = (val) => val ?? t('globals.fieldRequired');
-
+const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
 const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
     toRefs($props);
 const myOptions = ref([]);
@@ -248,8 +250,9 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
         ref="vnSelectRef"
         lazy-rules
         :class="{ required: $attrs.required }"
-        :rules="$attrs.required ? [requiredFieldRule] : null"
+        :rules="mixinRules"
         virtual-scroll-slice-size="options.length"
+        hide-bottom-space
     >
         <template v-if="isClearable" #append>
             <QIcon
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 47a29fc91..0b7c08e2b 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -105,6 +105,7 @@ globals:
     weight: Weight
     pageTitles:
         logIn: Login
+        addressEdit: Update address
         summary: Summary
         basicData: Basic data
         log: Logs
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 61db6b381..be657c792 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -107,6 +107,7 @@ globals:
     weight: Peso
     pageTitles:
         logIn: Inicio de sesión
+        addressEdit: Modificar consignatario
         summary: Resumen
         basicData: Datos básicos
         log: Historial
diff --git a/src/pages/Customer/Card/CustomerAddress.vue b/src/pages/Customer/Card/CustomerAddress.vue
index d76707079..166c33e1a 100644
--- a/src/pages/Customer/Card/CustomerAddress.vue
+++ b/src/pages/Customer/Card/CustomerAddress.vue
@@ -5,15 +5,12 @@ import { useRoute, useRouter } from 'vue-router';
 
 import axios from 'axios';
 
-import FetchData from 'components/FetchData.vue';
-
 const { t } = useI18n();
 const route = useRoute();
 const router = useRouter();
 
 const addresses = ref([]);
 const client = ref(null);
-const provincesLocation = ref([]);
 
 const addressFilter = {
     fields: [
@@ -41,7 +38,13 @@ const addressFilter = {
         {
             relation: 'province',
             scope: {
-                fields: ['id', 'name'],
+                fields: ['id', 'name', 'countryFk'],
+                include: [
+                    {
+                        relation: 'country',
+                        scope: { fields: ['id', 'name'] },
+                    },
+                ],
             },
         },
     ],
@@ -83,13 +86,6 @@ const getClientData = async (id) => {
     }
 };
 
-const setProvince = (provinceFk) => {
-    const result = provincesLocation.value.filter(
-        (province) => province.id === provinceFk
-    );
-    return result[0]?.name || '';
-};
-
 const isDefaultAddress = (address) => {
     return client?.value?.defaultAddressFk === address.id ? 1 : 0;
 };
@@ -128,12 +124,6 @@ const toCustomerAddressEdit = (addressId) => {
 </script>
 
 <template>
-    <FetchData
-        @on-fetch="(data) => (provincesLocation = data)"
-        auto-load
-        url="Provinces/location"
-    />
-
     <div class="full-width flex justify-center">
         <QCard class="card-width q-pa-lg" v-if="addresses.length">
             <QCardSection>
@@ -177,7 +167,7 @@ const toCustomerAddressEdit = (addressId) => {
                         <div>{{ item.street }}</div>
                         <div>
                             {{ item.postalCode }} - {{ item.city }},
-                            {{ setProvince(item.provinceFk) }}
+                            {{ item.province.name }}
                         </div>
                         <div>
                             {{ item.phone }}
diff --git a/src/pages/Customer/Card/CustomerFiscalData.vue b/src/pages/Customer/Card/CustomerFiscalData.vue
index c2adace5e..d8c07a46f 100644
--- a/src/pages/Customer/Card/CustomerFiscalData.vue
+++ b/src/pages/Customer/Card/CustomerFiscalData.vue
@@ -94,7 +94,7 @@ function handleLocation(data, location) {
                 <VnLocation
                     :rules="validate('Worker.postcode')"
                     :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
-                    v-model="data.postcode"
+                    :location="data"
                     @update:model-value="(location) => handleLocation(data, location)"
                 />
             </VnRow>
diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue
index 0aa46f85d..2252a96dc 100644
--- a/src/pages/Customer/components/CustomerAddressEdit.vue
+++ b/src/pages/Customer/components/CustomerAddressEdit.vue
@@ -177,7 +177,12 @@ function handleLocation(data, location) {
                     <VnLocation
                         :rules="validate('Worker.postcode')"
                         :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
-                        v-model="data.postalCode"
+                        :location="{
+                            postcode: data.postalCode,
+                            city: data.city,
+                            province: data.province,
+                            country: data.province.country,
+                        }"
                         @update:model-value="(location) => handleLocation(data, location)"
                     ></VnLocation>
                 </div>
diff --git a/src/pages/Supplier/Card/SupplierAddresses.vue b/src/pages/Supplier/Card/SupplierAddresses.vue
index 4bb6d5622..f46a3be19 100644
--- a/src/pages/Supplier/Card/SupplierAddresses.vue
+++ b/src/pages/Supplier/Card/SupplierAddresses.vue
@@ -26,7 +26,13 @@ const addressesFilter = {
         {
             relation: 'province',
             scope: {
-                fields: ['id', 'name'],
+                fields: ['id', 'name', 'countryFk'],
+                include: [
+                    {
+                        relation: 'country',
+                        scope: { fields: ['id', 'name'] },
+                    },
+                ],
             },
         },
     ],
diff --git a/src/pages/Supplier/Card/SupplierAddressesCreate.vue b/src/pages/Supplier/Card/SupplierAddressesCreate.vue
index 6e51ee94e..290373039 100644
--- a/src/pages/Supplier/Card/SupplierAddressesCreate.vue
+++ b/src/pages/Supplier/Card/SupplierAddressesCreate.vue
@@ -21,6 +21,7 @@ const newAddressForm = reactive({
     provinceFk: null,
     phone: null,
     mobile: null,
+    province: null,
 });
 
 const onDataSaved = () => {
@@ -84,7 +85,16 @@ function handleLocation(data, location) {
                     <VnLocation
                         :rules="validate('Worker.postcode')"
                         :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
-                        v-model="data.location"
+                        :location="
+                            data.postalCode
+                                ? {
+                                      postcode: data.postalCode,
+                                      city: data.city,
+                                      province: data.province,
+                                      country: data.province.country,
+                                  }
+                                : null
+                        "
                         @update:model-value="(location) => handleLocation(data, location)"
                     >
                     </VnLocation>
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index 65c34c4ed..60cd6770b 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -19,8 +19,8 @@ const sageTransactionTypesOptions = ref([]);
 const supplierActivitiesOptions = ref([]);
 
 function handleLocation(data, location) {
-    const { town, code, provinceFk, countryFk } = location ?? {};
-    data.postCode = code;
+    const { town, label, provinceFk, countryFk } = location ?? {};
+    data.postCode = label;
     data.city = town;
     data.provinceFk = provinceFk;
     data.countryFk = countryFk;
@@ -51,6 +51,23 @@ function handleLocation(data, location) {
         :url="`Suppliers/${route.params.id}`"
         :url-update="`Suppliers/${route.params.id}/updateFiscalData`"
         model="supplier"
+        :filter="{
+            fields: ['id', 'name', 'city', 'postCode', 'countryFk', 'provinceFk'],
+            include: [
+                {
+                    relation: 'province',
+                    scope: {
+                        fields: ['id', 'name'],
+                    },
+                },
+                {
+                    relation: 'country',
+                    scope: {
+                        fields: ['id', 'name'],
+                    },
+                },
+            ],
+        }"
         auto-load
         :clear-store-on-unmount="false"
     >
@@ -130,7 +147,12 @@ function handleLocation(data, location) {
                 <VnLocation
                     :rules="validate('Worker.postcode')"
                     :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
-                    v-model="data.postCode"
+                    :location="{
+                        postcode: data.postCode,
+                        city: data.city,
+                        province: data.province,
+                        country: data.country,
+                    }"
                     @update:model-value="(location) => handleLocation(data, location)"
                 >
                 </VnLocation>
diff --git a/src/pages/Wagon/Type/WagonTypeList.vue b/src/pages/Wagon/Type/WagonTypeList.vue
index 7615dea02..2f0d55fbe 100644
--- a/src/pages/Wagon/Type/WagonTypeList.vue
+++ b/src/pages/Wagon/Type/WagonTypeList.vue
@@ -2,14 +2,13 @@
 import { ref, computed } from 'vue';
 import axios from 'axios';
 import { useQuasar } from 'quasar';
-import VnPaginate from 'src/components/ui/VnPaginate.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useI18n } from 'vue-i18n';
 import { useRouter } from 'vue-router';
-import CardList from 'components/ui/CardList.vue';
 import FormModelPopup from 'src/components/FormModelPopup.vue';
 import VnInput from 'src/components/common/VnInput.vue';
 import VnRow from 'src/components/ui/VnRow.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
 
 const quasar = useQuasar();
 const arrayData = useArrayData('WagonTypeList');
@@ -17,7 +16,7 @@ const store = arrayData.store;
 const dialog = ref();
 const { push } = useRouter();
 const { t } = useI18n();
-const paginate = ref();
+const tableRef = ref();
 
 const initialData = computed(() => {
     return {
@@ -25,10 +24,46 @@ const initialData = computed(() => {
     };
 });
 
-function reloadData() {
-    initialData.value.name = null;
-    paginate.value.fetch();
-}
+const columns = computed(() => [
+    {
+        align: 'left',
+        name: 'id',
+        label: t('ID'),
+        isId: true,
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'name',
+        label: t('Name'),
+        isTitle: true,
+    },
+    {
+        align: 'left',
+        name: 'divisible',
+        label: t('Divisible'),
+        cardVisible: true,
+        component: 'checkbox',
+    },
+    {
+        align: 'right',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('components.smartCard.openCard'),
+                icon: 'arrow_forward',
+                isPrimary: true,
+                action: (row) => navigate(row.id, row.name),
+            },
+            {
+                title: t('wagon.list.remove'),
+                icon: 'delete',
+                isPrimary: true,
+                action: (row) => remove(row),
+            },
+        ],
+    },
+]);
 
 function navigate(id, name) {
     push({ path: `/wagon/type/${id}/edit`, query: { name } });
@@ -41,51 +76,25 @@ async function remove(row) {
         type: 'positive',
     });
     store.data.splice(store.data.indexOf(row), 1);
+    window.location.reload();
 }
 </script>
 
 <template>
     <QPage class="column items-center q-pa-md">
-        <div class="vn-card-list">
-            <VnPaginate
-                ref="paginate"
-                data-key="WagonTypeList"
-                url="WagonTypes"
-                order="id DESC"
-                auto-load
-            >
-                <template #body="{ rows }">
-                    <CardList
-                        v-for="row of rows"
-                        :key="row.id"
-                        :title="(row.name || '').toString()"
-                        :id="row.id"
-                        @click="navigate(row.id, row.name)"
-                    >
-                        <template #list-items>
-                            <QCheckbox
-                                :label="t('Divisble')"
-                                :model-value="row.divisible"
-                                disable
-                            />
-                        </template>
-                        <template #actions>
-                            <QBtn
-                                :label="t('components.smartCard.openCard')"
-                                @click.stop="navigate(row.id, row.name)"
-                                outline
-                            />
-                            <QBtn
-                                :label="t('wagon.list.remove')"
-                                @click.stop="remove(row)"
-                                color="primary"
-                                style="margin-top: 15px"
-                            />
-                        </template>
-                    </CardList>
-                </template>
-            </VnPaginate>
-        </div>
+        <VnTable
+            ref="tableRef"
+            data-key="WagonTypeList"
+            url="WagonTypes"
+            :columns="columns"
+            auto-load
+            order="id DESC"
+            :right-search="false"
+            :column-search="false"
+            :default-mode="'card'"
+            :disable-option="{ table: true }"
+        >
+        </VnTable>
         <QPageSticky :offset="[18, 18]">
             <QBtn @click.stop="dialog.show()" color="primary" fab icon="add" shortcut="+">
                 <QDialog ref="dialog">
@@ -94,7 +103,7 @@ async function remove(row) {
                         url-create="WagonTypes"
                         model="WagonType"
                         :form-initial-data="initialData"
-                        @on-data-saved="reloadData()"
+                        @on-data-saved="window.location.reload()"
                         auto-load
                     >
                         <template #form-inputs="{ data }">
diff --git a/src/pages/Wagon/WagonList.vue b/src/pages/Wagon/WagonList.vue
index c4824b861..129e803f5 100644
--- a/src/pages/Wagon/WagonList.vue
+++ b/src/pages/Wagon/WagonList.vue
@@ -1,12 +1,13 @@
 <script setup>
 import axios from 'axios';
 import { useQuasar } from 'quasar';
-import VnPaginate from 'src/components/ui/VnPaginate.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import { useI18n } from 'vue-i18n';
 import { useRouter } from 'vue-router';
-import CardList from 'components/ui/CardList.vue';
-import VnLv from 'components/ui/VnLv.vue';
+import VnTable from 'src/components/VnTable/VnTable.vue';
+import { computed } from 'vue';
+import VnSelect from 'src/components/common/VnSelect.vue';
+import VnInput from 'src/components/common/VnInput.vue';
 
 const quasar = useQuasar();
 const arrayData = useArrayData('WagonList');
@@ -23,14 +24,56 @@ const filter = {
     },
 };
 
+const columns = computed(() => [
+    {
+        align: 'left',
+        name: 'label',
+        label: t('Label'),
+        isTitle: true,
+    },
+    {
+        align: 'left',
+        name: 'plate',
+        label: t('wagon.list.plate'),
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'volume',
+        label: t('wagon.list.volume'),
+        cardVisible: true,
+    },
+    {
+        align: 'left',
+        name: 'name',
+        label: t('wagon.list.type'),
+        cardVisible: true,
+        format: (row) => row?.type?.name,
+    },
+    {
+        align: 'right',
+        name: 'tableActions',
+        actions: [
+            {
+                title: t('components.smartCard.openCard'),
+                icon: 'arrow_forward',
+                isPrimary: true,
+                action: (row) => navigate(row.id),
+            },
+            {
+                title: t('wagon.list.remove'),
+                icon: 'delete',
+                isPrimary: true,
+                action: (row) => remove(row),
+            },
+        ],
+    },
+]);
+
 function navigate(id) {
     router.push({ path: `/wagon/${id}/edit` });
 }
 
-function create() {
-    router.push({ path: `/wagon/create` });
-}
-
 async function remove(row) {
     try {
         await axios.delete(`Wagons/${row.id}`).then(async () => {
@@ -39,6 +82,7 @@ async function remove(row) {
                 type: 'positive',
             });
             store.data.splice(store.data.indexOf(row), 1);
+            window.location.reload();
         });
     } catch (error) {
         //
@@ -48,53 +92,83 @@ async function remove(row) {
 
 <template>
     <QPage class="column items-center q-pa-md">
-        <div class="vn-card-list">
-            <VnPaginate
-                data-key="WagonList"
-                url="/Wagons"
-                order="id DESC"
-                :filter="filter"
-                auto-load
-            >
-                <template #body="{ rows }">
-                    <CardList
-                        v-for="row of rows"
-                        :key="row.id"
-                        :title="(row.label || '').toString()"
-                        :id="row.id"
-                        @click="navigate(row.id)"
-                    >
-                        <template #list-items>
-                            <VnLv
-                                :label="t('wagon.list.plate')"
-                                :title-label="t('wagon.list.plate')"
-                                :value="row.plate"
-                            />
-                            <VnLv :label="t('wagon.list.volume')" :value="row?.volume" />
-                            <VnLv
-                                :label="t('wagon.list.type')"
-                                :value="row?.type?.name"
-                            />
-                        </template>
-                        <template #actions>
-                            <QBtn
-                                :label="t('components.smartCard.openCard')"
-                                @click.stop="navigate(row.id)"
-                                outline
-                            />
-                            <QBtn
-                                :label="t('wagon.list.remove')"
-                                @click.stop="remove(row)"
-                                color="primary"
-                                style="margin-top: 15px"
-                            />
-                        </template>
-                    </CardList>
-                </template>
-            </VnPaginate>
-        </div>
-        <QPageSticky position="bottom-right" :offset="[18, 18]">
-            <QBtn @click="create" fab icon="add" color="primary" shortcut="+" />
-        </QPageSticky>
+        <VnTable
+            ref="tableRef"
+            data-key="WagonList"
+            url="Wagons"
+            :filter="filter"
+            :columns="columns"
+            auto-load
+            order="id DESC"
+            :right-search="false"
+            :column-search="false"
+            :default-mode="'card'"
+            :disable-option="{ table: true }"
+            :create="{
+                urlCreate: 'Wagons',
+                title: t('Create new wagon'),
+                onDataSaved: () => {
+                    window.location.reload();
+                },
+                formInitialData: {},
+            }"
+        >
+            <template #more-create-dialog="{ data }">
+                <VnInput
+                    filled
+                    v-model="data.label"
+                    :label="t('wagon.create.label')"
+                    type="number"
+                    min="0"
+                    :rules="[(val) => !!val || t('wagon.warnings.labelNotEmpty')]"
+                />
+                <VnInput
+                    filled
+                    v-model="data.plate"
+                    :label="t('wagon.create.plate')"
+                    :rules="[(val) => !!val || t('wagon.warnings.plateNotEmpty')]"
+                />
+                <VnInput
+                    filled
+                    v-model="data.volume"
+                    :label="t('wagon.create.volume')"
+                    type="number"
+                    min="0"
+                    :rules="[(val) => !!val || t('wagon.warnings.volumeNotEmpty')]"
+                />
+                <VnSelect
+                    url="WagonTypes"
+                    filled
+                    v-model="data.typeFk"
+                    use-input
+                    fill-input
+                    hide-selected
+                    input-debounce="0"
+                    option-label="name"
+                    option-value="id"
+                    emit-value
+                    map-options
+                    :label="t('wagon.create.type')"
+                    :options="filteredWagonTypes"
+                    :rules="[(val) => !!val || t('wagon.warnings.typeNotEmpty')]"
+                    @filter="filterType"
+                >
+                    <template v-if="data.typeFk" #append>
+                        <QIcon
+                            name="cancel"
+                            @click.stop.prevent="data.typeFk = null"
+                            class="cursor-pointer"
+                        />
+                    </template>
+                    <template #no-option>
+                        <QItem>
+                            <QItemSection class="text-grey">
+                                {{ t('wagon.warnings.noData') }}
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelect>
+            </template>
+        </VnTable>
     </QPage>
 </template>
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index abf60a078..9ae91f8ce 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -2,6 +2,7 @@
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import { onMounted, ref, computed, onBeforeMount, nextTick, reactive } from 'vue';
+import { axiosNoError } from 'src/boot/axios';
 
 import FetchData from 'components/FetchData.vue';
 import WorkerTimeHourChip from 'pages/Worker/Card/WorkerTimeHourChip.vue';
@@ -12,7 +13,6 @@ import WorkerTimeControlCalendar from 'pages/Worker/Card/WorkerTimeControlCalend
 
 import useNotify from 'src/composables/useNotify.js';
 import axios from 'axios';
-import { useRole } from 'src/composables/useRole';
 import { useAcl } from 'src/composables/useAcl';
 import { useWeekdayStore } from 'src/stores/useWeekdayStore';
 import { useStateStore } from 'stores/useStateStore';
@@ -63,13 +63,16 @@ const selectedCalendarDates = ref([]);
 const selectedDateFormatted = ref(toDateString(defaultDate.value));
 
 const arrayData = useArrayData('workerData');
-
+const acl = useAcl();
 const worker = computed(() => arrayData.store?.data);
-
-const isHr = computed(() => useRole().hasAny(['hr']));
-
-const canSend = computed(() => useAcl().hasAny('WorkerTimeControl', 'sendMail', 'WRITE'));
-
+const canSend = computed(() =>
+    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));
 
 const columns = computed(() => {
@@ -257,58 +260,32 @@ const fetchHours = async () => {
     }
 };
 
-const fetchWorkerTimeControlMails = async (filter) => {
-    try {
-        const { data } = await axios.get('WorkerTimeControlMails', {
-            params: { filter: JSON.stringify(filter) },
-        });
-
-        return data;
-    } catch (err) {
-        console.error('Error fetching worker time control mails');
-    }
-};
-
 const fetchWeekData = async () => {
+    const where = {
+        year: selectedDate.value.getFullYear(),
+        week: selectedWeekNumber.value,
+    };
     try {
-        const filter = {
-            where: {
-                workerFk: route.params.id,
-                year: selectedDate.value ? selectedDate.value?.getFullYear() : null,
-                week: selectedWeekNumber.value,
-            },
-        };
+        const mail = (
+            await axiosNoError.get(`Workers/${route.params.id}/mail`, {
+                params: { filter: { where } },
+            })
+        ).data[0];
 
-        const data = await fetchWorkerTimeControlMails(filter);
-        if (!data.length) {
-            state.value = null;
-        } else {
-            const [mail] = data;
+        if (!mail) state.value = null;
+        else {
             state.value = mail.state;
             reason.value = mail.reason;
         }
 
-        await canBeResend();
+        canResend.value = !!(
+            await axiosNoError.get('WorkerTimeControlMails/count', { params: { where } })
+        ).data.count;
     } catch (err) {
         console.error('Error fetching week data');
     }
 };
 
-const canBeResend = async () => {
-    canResend.value = false;
-
-    const filter = {
-        where: {
-            year: selectedDate.value.getFullYear(),
-            week: selectedWeekNumber.value,
-        },
-        limit: 1,
-    };
-
-    const data = await fetchWorkerTimeControlMails(filter);
-    if (data.length) canResend.value = true;
-};
-
 const setHours = (data) => {
     for (const weekDay of weekDays.value) {
         if (data) {
@@ -449,7 +426,7 @@ onMounted(async () => {
         <div>
             <QBtnGroup push class="q-gutter-x-sm" flat>
                 <QBtn
-                    v-if="isHimself && state"
+                    v-if="canUpdate && state"
                     :label="t('Satisfied')"
                     color="primary"
                     type="submit"
@@ -457,7 +434,7 @@ onMounted(async () => {
                     @click="isSatisfied()"
                 />
                 <QBtn
-                    v-if="isHimself && state"
+                    v-if="canUpdate && state"
                     :label="t('Not satisfied')"
                     color="primary"
                     type="submit"
@@ -468,7 +445,7 @@ onMounted(async () => {
             </QBtnGroup>
             <QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
                 <QBtn
-                    v-if="reason && state && (isHimself || isHr)"
+                    v-if="reason && state && canUpdate"
                     :label="t('Reason')"
                     color="primary"
                     type="submit"
diff --git a/src/pages/Worker/WorkerCreate.vue b/src/pages/Worker/WorkerCreate.vue
index 297aa4182..b51209879 100644
--- a/src/pages/Worker/WorkerCreate.vue
+++ b/src/pages/Worker/WorkerCreate.vue
@@ -194,7 +194,6 @@ async function autofillBic(worker) {
                     <VnLocation
                         :rules="validate('Worker.postcode')"
                         :roles-allowed-to-create="['deliveryAssistant']"
-                        v-model="data.location"
                         @update:model-value="(location) => handleLocation(data, location)"
                         :disable="formData.isFreelance"
                     >
diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue
index b8ef3f9d8..4c9964c0b 100644
--- a/src/pages/Worker/WorkerList.vue
+++ b/src/pages/Worker/WorkerList.vue
@@ -264,7 +264,6 @@ async function autofillBic(worker) {
                     <VnLocation
                         :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
                         :options="postcodesOptions"
-                        v-model="data.location"
                         @update:model-value="(location) => handleLocation(data, location)"
                         :disable="data.isFreelance"
                     >
diff --git a/src/router/modules/customer.js b/src/router/modules/customer.js
index 5b73ddc84..1b707f1a2 100644
--- a/src/router/modules/customer.js
+++ b/src/router/modules/customer.js
@@ -175,7 +175,7 @@ export default {
                                     path: 'edit',
                                     name: 'CustomerAddressEdit',
                                     meta: {
-                                        title: 'address-edit',
+                                        title: 'addressEdit',
                                     },
                                     component: () =>
                                         import(
diff --git a/test/cypress/integration/entry/entryDms.spec.js b/test/cypress/integration/entry/entryDms.spec.js
index ed4a3d79c..47dcdba9e 100644
--- a/test/cypress/integration/entry/entryDms.spec.js
+++ b/test/cypress/integration/entry/entryDms.spec.js
@@ -23,7 +23,7 @@ describe('EntryDms', () => {
             expect(value).to.have.length(newFileTd++);
             const newRowSelector = `tbody > :nth-child(${newFileTd})`;
             cy.waitForElement(newRowSelector);
-            cy.validateRow(newRowSelector, [u, u, u, u, 'ENTRADA ID 1']);
+            cy.validateRow(newRowSelector, [u, u, u, u, u, 'ENTRADA ID 1']);
 
             //Edit new dms
             const newDescription = 'entry id 1 modified';
@@ -38,7 +38,7 @@ describe('EntryDms', () => {
             cy.saveCard();
             cy.reload();
 
-            cy.validateRow(newRowSelector, [u, u, u, u, newDescription]);
+            cy.validateRow(newRowSelector, [u, u, u, u, u, newDescription]);
         });
     });
 });
diff --git a/test/cypress/integration/ticket/ticketDescriptor.spec.js b/test/cypress/integration/ticket/ticketDescriptor.spec.js
index 516b0f13d..8192b7c7c 100644
--- a/test/cypress/integration/ticket/ticketDescriptor.spec.js
+++ b/test/cypress/integration/ticket/ticketDescriptor.spec.js
@@ -5,7 +5,7 @@ describe('Ticket descriptor', () => {
     const warehouseValue = ':nth-child(1) > :nth-child(6) > .value > span';
     const summaryHeader = '.summaryHeader > div';
     const weight = 25;
-    const weightValue = ':nth-child(10) > .value > span';
+    const weightValue = '.summaryBody.row :nth-child(1) > :nth-child(9) > .value > span';
     beforeEach(() => {
         cy.login('developer');
         cy.viewport(1920, 1080);
diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js
index 30c1d6df2..3533a3c1f 100644
--- a/test/cypress/integration/vnComponent/vnLocation.spec.js
+++ b/test/cypress/integration/vnComponent/vnLocation.spec.js
@@ -18,7 +18,7 @@ describe('VnLocation', () => {
             cy.get(inputLocation).click();
             cy.get(inputLocation).clear();
             cy.get(inputLocation).type('al');
-            cy.get(locationOptions).should('have.length.at.least', 3);
+            cy.get(locationOptions).should('have.length.at.least', 4);
         });
         it('input filter location as "ecuador"', function () {
             cy.get(inputLocation).click();
@@ -33,11 +33,29 @@ describe('VnLocation', () => {
             cy.login('developer');
             cy.visit('/#/supplier/567/fiscal-data', { timeout: 7000 });
             cy.waitForElement('.q-form');
-            cy.get(createLocationButton).click();
         });
+        it('Fin by postalCode', () => {
+            const postCode = '46600';
+            const firstOption = '[role="listbox"] .q-item:nth-child(1)';
+
+            cy.get(inputLocation).click();
+            cy.get(inputLocation).clear();
+            cy.get(inputLocation).type(postCode);
+            cy.get(locationOptions).should('have.length.at.least', 2);
+            cy.get(firstOption).click();
+            cy.get('.q-btn-group > .q-btn--standard > .q-btn__content > .q-icon').click();
+            cy.reload();
+            cy.waitForElement('.q-form');
+            cy.get(inputLocation).should(
+                'have.value',
+                '46600 - Valencia(Province one), España'
+            );
+        });
+
         it('Create postCode', () => {
             const postCode = '1234475';
             const province = 'Valencia';
+            cy.get(createLocationButton).click();
             cy.get('.q-card > h1').should('have.text', 'New postcode');
             cy.get(dialogInputs).eq(0).clear();
             cy.get(dialogInputs).eq(0).type(postCode);
@@ -54,6 +72,7 @@ describe('VnLocation', () => {
         it('Create city', () => {
             const postCode = '9011';
             const province = 'Saskatchew';
+            cy.get(createLocationButton).click();
             cy.get(dialogInputs).eq(0).type(postCode);
             // city create button
             cy.get(