diff --git a/src/composables/usePrintService.js b/src/composables/usePrintService.js
index edf9598b2..ff43c65a1 100644
--- a/src/composables/usePrintService.js
+++ b/src/composables/usePrintService.js
@@ -17,6 +17,7 @@ export function usePrintService() {
     }
 
     function openReport(path, params) {
+        if (typeof params === 'string') params = JSON.parse(params);
         params = Object.assign(
             {
                 access_token: getTokenMultimedia(),
diff --git a/src/pages/Customer/Card/CustomerConsumption.vue b/src/pages/Customer/Card/CustomerConsumption.vue
index 4d3da1116..a8c34991a 100644
--- a/src/pages/Customer/Card/CustomerConsumption.vue
+++ b/src/pages/Customer/Card/CustomerConsumption.vue
@@ -1,15 +1,181 @@
 <script setup>
+import { computed, ref, watch } from 'vue';
+import { useQuasar } from 'quasar';
+import { useI18n } from 'vue-i18n';
 import CustomerConsumptionFilter from './CustomerConsumptionFilter.vue';
 import { useStateStore } from 'src/stores/useStateStore';
+import VnTable from 'components/VnTable/VnTable.vue';
+import VnSubToolbar from 'components/ui/VnSubToolbar.vue';
+import { toDate } from 'src/filters';
+import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
+import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
+import FetchedTags from 'components/ui/FetchedTags.vue';
+import { useArrayData } from 'src/composables/useArrayData';
+import { useRoute } from 'vue-router';
+import { usePrintService } from 'src/composables/usePrintService';
+import SendEmailDialog from 'src/components/common/SendEmailDialog.vue';
+
+const { openReport, sendEmail } = usePrintService();
+const arrayData = useArrayData('Client');
+const { t } = useI18n();
+const quasar = useQuasar();
+
+const route = useRoute();
+const tableRef = ref();
+const filter = computed(() => ({
+    where: { and: [{ isPackaging: false }, { clientFk: route.params.id }] },
+    limit: 30,
+    skip: 10,
+}));
+
+const showActionBtns = computed(() => handleQueryParams());
+function handleQueryParams() {
+    const query = JSON.parse(route.query.table);
+    return query.from && query.to;
+}
+watch(
+    () => route.query,
+    () => {
+        showActionBtns.value = handleQueryParams();
+    }
+);
+const columns = computed(() => [
+    {
+        align: 'left',
+        name: 'itemFk',
+        label: t('Item'),
+        cardVisible: true,
+        columnFilter: {
+            inWhere: true,
+        },
+    },
+    {
+        align: 'left',
+        name: 'ticketFk',
+        label: t('Ticket'),
+        cardVisible: true,
+        columnFilter: {
+            inWhere: true,
+        },
+    },
+    {
+        align: 'left',
+        name: 'shipped',
+        label: t('Creation date'),
+        format: ({ shipped }) => toDate(shipped),
+        cardVisible: true,
+        columnFilter: {
+            inWhere: true,
+        },
+    },
+
+    {
+        align: 'left',
+        name: 'description',
+        label: t('Description'),
+        class: 'extend',
+        columnFilter: {
+            inWhere: true,
+        },
+    },
+    {
+        align: 'left',
+        name: 'quantity',
+        label: t('Quantity'),
+        cardVisible: true,
+        columnFilter: {
+            inWhere: true,
+        },
+    },
+]);
+function getParams() {
+    const query = JSON.parse(route.query.table);
+    return {
+        from: query.from,
+        to: query.to,
+        recipient: arrayData.store.data.email,
+        recipientId: arrayData.store.data.id,
+    };
+}
+const openReportPdf = () => {
+    openReport(`Clients/${route.params.id}/campaign-metrics-pdf`, getParams());
+};
+
+const openSendEmailDialog = async () => {
+    quasar.dialog({
+        component: SendEmailDialog,
+        componentProps: {
+            data: {
+                address: arrayData.store.data.email,
+            },
+            promise: sendCampaignMetricsEmail,
+        },
+    });
+};
+const sendCampaignMetricsEmail = ({ address }) => {
+    sendEmail(`Suppliers/${route.params.id}/campaign-metrics-email`, {
+        recipient: address,
+        ...getParams().value,
+    });
+};
 </script>
 
 <template>
     <Teleport to="#right-panel" v-if="useStateStore().isHeaderMounted()">
         <CustomerConsumptionFilter data-key="CustomerConsumption" />
     </Teleport>
+    <VnSubToolbar>
+        <template #st-actions>
+            <QBtn
+                color="primary"
+                icon-right="picture_as_pdf"
+                @click="openReportPdf()"
+                :disabled="!showActionBtns"
+            >
+                <QTooltip>{{ t('globals.downloadPdf') }}</QTooltip>
+            </QBtn>
+            <QBtn
+                color="primary"
+                icon-right="email"
+                @click="openSendEmailDialog()"
+                :disabled="!showActionBtns"
+            >
+                <QTooltip>{{ t('globals.downloadPdf') }}</QTooltip>
+            </QBtn>
+        </template>
+    </VnSubToolbar>
+    <VnTable
+        data-key="CustomerConsumption"
+        ref="tableRef"
+        :filter="filter"
+        url="Clients/Consumption"
+        :columns="columns"
+        :right-search="false"
+        :use-model="true"
+        auto-load
+        :order="['itemTypeFk', 'itemName', 'itemSize', 'description']"
+    >
+        <template #column-itemFk="{ row }">
+            <span class="link">
+                {{ row.itemFk }}
+                <ItemDescriptorProxy :id="row.itemFk" />
+            </span>
+            <!-- <FetchedTags :item="row" :max-length="6" /> -->
+        </template>
+        <template #column-description="{ row }">
+            <FetchedTags :item="row" :max-length="6" />
+        </template>
+        <template #column-ticketFk="{ row }">
+            <span class="link">
+                {{ row.ticketFk }}
+                <TicketDescriptorProxy :id="row.ticketFk" />
+            </span> </template
+    ></VnTable>
 </template>
 
 <i18n>
 es:
+    Group by item: Agrupar por artículo
+
     Enter a new search: Introduce una nueva búsqueda
 </i18n>
diff --git a/src/pages/Customer/Card/CustomerConsumptionFilter.vue b/src/pages/Customer/Card/CustomerConsumptionFilter.vue
index 91536e954..0f5148007 100644
--- a/src/pages/Customer/Card/CustomerConsumptionFilter.vue
+++ b/src/pages/Customer/Card/CustomerConsumptionFilter.vue
@@ -12,14 +12,23 @@ const { t } = useI18n();
 defineProps({ dataKey: { type: String, required: true } });
 </script>
 <template>
-    <VnFilterPanel :data-key="dataKey" :search-button="true">
+    <VnFilterPanel :data-key="dataKey" :search-button="true" :redirect="false">
         <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 }">
+        <template #body="{ params, searchFn }">
+            <QItem>
+                <QItemSection
+                    ><QCheckbox
+                        v-model="params.grouped"
+                        :label="t('Group by item')"
+                        @update:model-value="searchFn()"
+                        dense
+                /></QItemSection>
+            </QItem>
             <QItem>
                 <QItemSection>
                     <VnInput
@@ -145,6 +154,7 @@ defineProps({ dataKey: { type: String, required: true } });
 <i18n>
 en:
     params:
+        grouped: Group by item
         item: Item id
         buyer: Buyer
         type: Type
@@ -161,6 +171,7 @@ en:
         allSaints: All Saints' Day
 es:
     params:
+        grouped: Agrupar por artículo
         item: Id artículo
         buyer: Comprador
         type: Tipo