From 74fd76ce770297040bcd21a7eec4905a9d70a794 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 17 Jan 2024 00:24:13 +0200 Subject: [PATCH 1/6] feat(server): sales by items export csv & xlsx --- .../FinancialStatements/SalesByItems.ts | 28 ++++---- .../src/interfaces/SalesByItemsSheet.ts | 2 +- .../SalesByItems/SalesByItemsApplication.ts | 54 +++++++++++++++ .../SalesByItems/SalesByItemsExport.ts | 43 ++++++++++++ .../SalesByItems/SalesByItemsService.ts | 2 +- .../SalesByItems/SalesByItemsTable.ts | 65 +++++++++++++++++++ .../SalesByItemsTableInjectable.tsx | 33 ++++++++++ 7 files changed, 213 insertions(+), 14 deletions(-) create mode 100644 packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts create mode 100644 packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsExport.ts create mode 100644 packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts create mode 100644 packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTableInjectable.tsx diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts index d31954398..0952610f2 100644 --- a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts +++ b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts @@ -7,6 +7,7 @@ import BaseFinancialReportController from './BaseFinancialReportController'; import SalesByItemsReportService from '@/services/FinancialStatements/SalesByItems/SalesByItemsService'; import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; @Service() export default class SalesByItemsReportController extends BaseFinancialReportController { @@ -68,18 +69,21 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon const { tenantId } = req; const filter = this.matchedQueryData(req); - try { - const { data, query, meta } = await this.salesByItemsService.salesByItems( - tenantId, - filter - ); - return res.status(200).send({ - meta: this.transfromToResponse(meta), - data: this.transfromToResponse(data), - query: this.transfromToResponse(query), - }); - } catch (error) { - next(error); + const accept = this.accepts(req); + + const acceptType = accept.types([ + ACCEPT_TYPE.APPLICATION_JSON, + ACCEPT_TYPE.APPLICATION_JSON_TABLE, + ACCEPT_TYPE.APPLICATION_CSV, + ACCEPT_TYPE.APPLICATION_XLSX, + ]); + + if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { + } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { + } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { + } else { + await this.salesByItemsService.salesByItems(tenantId, filter); + return res.status(200).send({ meta, data, query }); } } } diff --git a/packages/server/src/interfaces/SalesByItemsSheet.ts b/packages/server/src/interfaces/SalesByItemsSheet.ts index 0e0a41f9e..2e253c49d 100644 --- a/packages/server/src/interfaces/SalesByItemsSheet.ts +++ b/packages/server/src/interfaces/SalesByItemsSheet.ts @@ -41,5 +41,5 @@ export interface ISalesByItemsTotal { export type ISalesByItemsSheetStatement = { items: ISalesByItemsItem[], total: ISalesByItemsTotal -} | {}; +}; diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts new file mode 100644 index 000000000..6fbd97459 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts @@ -0,0 +1,54 @@ +import { ISalesByItemsReportQuery } from '@/interfaces'; +import { SalesByItemsReportService } from './SalesByItemsService'; +import { SalesByItemsTableInjectable } from './SalesByItemsTableInjectable'; +import { SalesByItemsExport } from './SalesByItemsExport'; +import { Inject, Service } from 'typedi'; + +@Service() +export class SalesByItemsApplication { + @Inject() + private salesByItemsSheet: SalesByItemsReportService; + + @Inject() + private salesByItemsTable: SalesByItemsTableInjectable; + + @Inject() + private salesByItemsExport: SalesByItemsExport; + + /** + * Retrieves the sales by items report in json format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} filter + * @returns {Promise} + */ + public sheet(tenantId: number, filter: ISalesByItemsReportQuery) { + return this.salesByItemsSheet.salesByItems(tenantId, filter); + } + /** + * Retrieves the sales by items report in table format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} filter + * @returns {Promise} + */ + public table(tenantId: number, filter: ISalesByItemsReportQuery) { + return this.salesByItemsTable.table(tenantId, filter); + } + /** + * Retrieves the sales by items report in csv format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} filter + * @returns {Promise} + */ + public csv(tenantId: number, filter: ISalesByItemsReportQuery) { + return this.salesByItemsExport.csv(tenantId, filter); + } + /** + * Retrieves the sales by items report in xlsx format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} filter + * @returns {Promise} + */ + public xlsx(tenantId: number, filter: ISalesByItemsReportQuery) { + return this.salesByItemsExport.xlsx(tenantId, filter); + } +} diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsExport.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsExport.ts new file mode 100644 index 000000000..067aab546 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsExport.ts @@ -0,0 +1,43 @@ +import { Inject, Service } from 'typedi'; +import { TableSheet } from '@/lib/Xlsx/TableSheet'; +import { ISalesByItemsReportQuery } from '@/interfaces'; +import { SalesByItemsTableInjectable } from './SalesByItemsTableInjectable'; + +@Service() +export class SalesByItemsExport { + @Inject() + private salesByItemsTable: SalesByItemsTableInjectable; + + /** + * Retrieves the trial balance sheet in XLSX format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} query + * @returns {Promise} + */ + public async xlsx(tenantId: number, query: ISalesByItemsReportQuery) { + const table = await this.salesByItemsTable.table(tenantId, query); + + const tableSheet = new TableSheet(table.table); + const tableCsv = tableSheet.convertToXLSX(); + + return tableSheet.convertToBuffer(tableCsv, 'xlsx'); + } + + /** + * Retrieves the trial balance sheet in CSV format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} query + * @returns {Promise} + */ + public async csv( + tenantId: number, + query: ISalesByItemsReportQuery + ): Promise { + const table = await this.salesByItemsTable.table(tenantId, query); + + const tableSheet = new TableSheet(table.table); + const tableCsv = tableSheet.convertToCSV(); + + return tableCsv; + } +} diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts index 6f81e1489..086284d8e 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts @@ -10,7 +10,7 @@ import SalesByItems from './SalesByItems'; import { Tenant } from '@/system/models'; @Service() -export default class SalesByItemsReportService { +export class SalesByItemsReportService { @Inject() tenancy: TenancyService; diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts new file mode 100644 index 000000000..dad7126dc --- /dev/null +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts @@ -0,0 +1,65 @@ +import * as R from 'ramda'; +import { ISalesByItemsSheetStatement, ITableColumn, ITableData, ITableRow } from '@/interfaces'; +import { tableRowMapper } from '@/utils'; + +export class SalesByItemsTable { + private readonly data: ISalesByItemsSheetStatement; + + constructor(data: ISalesByItemsSheetStatement) { + this.data = data; + } + + private commonTableAccessors() { + return [ + { key: 'item_name', accessor: 'name' }, + { key: 'quantity', accessor: 'quantitySoldFormatted' }, + { key: 'sold', accessor: 'soldCostFormatted' }, + ]; + } + + private itemMap(item: any) { + const columns = this.commonTableAccessors(); + const meta = {}; + + return tableRowMapper(item, columns, meta); + } + + private itemsMap(items: any[]) { + return R.map(this.itemMap, items); + } + + /** + * + * @param total + * @returns + */ + private totalMap(total: any) { + const columns = this.commonTableAccessors(); + const meta = {}; + + return tableRowMapper(total, columns, meta); + } + + /** + * + * @returns {ITableRow[]} + */ + public tableData(): ITableRow[] { + const itemsRows = this.itemsMap(this.data.items); + const totalRow = this.totalMap(this.data.total); + + return [...itemsRows, totalRow]; + } + + /** + * Retrieves the table columns. + * @returns {ITableColumn[]} + */ + public tableColumns(): ITableColumn[] { + return [ + { key: 'item_name', label: 'Item Name' }, + { key: 'quantity', label: 'Quantity' }, + { key: 'sold_cost', label: 'Sold Cost' }, + ]; + } +} diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTableInjectable.tsx b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTableInjectable.tsx new file mode 100644 index 000000000..037ca7073 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTableInjectable.tsx @@ -0,0 +1,33 @@ +import { ISalesByItemsReportQuery } from '@/interfaces'; +import { Inject, Service } from 'typedi'; +import { SalesByItemsReportService } from './SalesByItemsService'; +import { SalesByItemsTable } from './SalesByItemsTable'; + +@Service() +export class SalesByItemsTableInjectable { + @Inject() + salesByItemSheet: SalesByItemsReportService; + + /** + * Retrieves the sales by items report in table format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} filter + * @returns {Promise} + */ + public async table(tenantId: number, filter: ISalesByItemsReportQuery) { + const { data, query, meta } = await this.salesByItemSheet.salesByItems( + tenantId, + filter + ); + const table = new SalesByItemsTable(data); + + return { + table: { + columns: table.tableColumns(), + rows: table.tableData(), + }, + meta, + query, + }; + } +} From 4a920176f42624e59443fde32142b6451ca65d7a Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 17 Jan 2024 18:49:38 +0200 Subject: [PATCH 2/6] feat(server): sales by items table --- .../FinancialStatements/SalesByItems.ts | 37 ++++++++--- .../SalesByItems/SalesByItemsApplication.ts | 3 + .../SalesByItems/SalesByItemsTable.ts | 62 +++++++++++++------ 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts index 0952610f2..ffc0cb959 100644 --- a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts +++ b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts @@ -1,18 +1,17 @@ import { Router, Request, Response, NextFunction } from 'express'; -import { query, ValidationChain } from 'express-validator'; -import moment from 'moment'; +import { query, ValidationChain, ValidationSchema } from 'express-validator'; import { Inject, Service } from 'typedi'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseFinancialReportController from './BaseFinancialReportController'; -import SalesByItemsReportService from '@/services/FinancialStatements/SalesByItems/SalesByItemsService'; import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; import { ACCEPT_TYPE } from '@/interfaces/Http'; +import { SalesByItemsApplication } from '@/services/FinancialStatements/SalesByItems/SalesByItemsApplication'; @Service() export default class SalesByItemsReportController extends BaseFinancialReportController { @Inject() - salesByItemsService: SalesByItemsReportService; + salesByItemsApp: SalesByItemsApplication; /** * Router constructor. @@ -32,6 +31,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon /** * Validation schema. + * @returns {ValidationChain[]} */ private get validationSchema(): ValidationChain[] { return [ @@ -68,7 +68,6 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon ) { const { tenantId } = req; const filter = this.matchedQueryData(req); - const accept = this.accepts(req); const acceptType = accept.types([ @@ -77,13 +76,33 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon ACCEPT_TYPE.APPLICATION_CSV, ACCEPT_TYPE.APPLICATION_XLSX, ]); - + // Retrieves the csv format. if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { + const buffer = await this.salesByItemsApp.csv(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); + + return res.send(buffer); + // Retrieves the json table format. + } else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) { + const table = await this.salesByItemsApp.table(tenantId, filter); + + return res.status(200).send(table); + // Retrieves the xlsx format. } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { - } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { + const buffer = this.salesByItemsApp.xlsx(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx'); + res.setHeader( + 'Content-Type', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ); + return res.send(buffer); + // Retrieves the json format. } else { - await this.salesByItemsService.salesByItems(tenantId, filter); - return res.status(200).send({ meta, data, query }); + const sheet = await this.salesByItemsApp.sheet(tenantId, filter); + return res.status(200).send(sheet); } } } diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts index 6fbd97459..d70cd703a 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsApplication.ts @@ -24,6 +24,7 @@ export class SalesByItemsApplication { public sheet(tenantId: number, filter: ISalesByItemsReportQuery) { return this.salesByItemsSheet.salesByItems(tenantId, filter); } + /** * Retrieves the sales by items report in table format. * @param {number} tenantId @@ -33,6 +34,7 @@ export class SalesByItemsApplication { public table(tenantId: number, filter: ISalesByItemsReportQuery) { return this.salesByItemsTable.table(tenantId, filter); } + /** * Retrieves the sales by items report in csv format. * @param {number} tenantId @@ -42,6 +44,7 @@ export class SalesByItemsApplication { public csv(tenantId: number, filter: ISalesByItemsReportQuery) { return this.salesByItemsExport.csv(tenantId, filter); } + /** * Retrieves the sales by items report in xlsx format. * @param {number} tenantId diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts index dad7126dc..33c39ccd6 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts @@ -1,47 +1,72 @@ import * as R from 'ramda'; -import { ISalesByItemsSheetStatement, ITableColumn, ITableData, ITableRow } from '@/interfaces'; +import { + ISalesByItemsItem, + ISalesByItemsSheetStatement, + ISalesByItemsTotal, + ITableColumn, + ITableRow, +} from '@/interfaces'; import { tableRowMapper } from '@/utils'; export class SalesByItemsTable { private readonly data: ISalesByItemsSheetStatement; + /** + * Constructor method. + * @param {ISalesByItemsSheetStatement} data + */ constructor(data: ISalesByItemsSheetStatement) { this.data = data; } + /** + * Retrieves the common table accessors. + * @returns {ITableColumn[]} + */ private commonTableAccessors() { return [ { key: 'item_name', accessor: 'name' }, - { key: 'quantity', accessor: 'quantitySoldFormatted' }, - { key: 'sold', accessor: 'soldCostFormatted' }, + { key: 'sold_quantity', accessor: 'quantitySoldFormatted' }, + { key: 'sold_amount', accessor: 'soldCostFormatted' }, + { key: 'average_price', accessor: 'averageSellPriceFormatted' }, ]; } - private itemMap(item: any) { + /** + * Maps the given item node to table row. + * @param {ISalesByItemsItem} item + * @returns {ITableRow} + */ + private itemMap = (item: ISalesByItemsItem): ITableRow => { const columns = this.commonTableAccessors(); const meta = {}; return tableRowMapper(item, columns, meta); - } - - private itemsMap(items: any[]) { - return R.map(this.itemMap, items); - } + }; /** - * - * @param total - * @returns + * Maps the given items nodes to table rows. + * @param {ISalesByItemsItem[]} items + * @returns {ITableRow[]} */ - private totalMap(total: any) { + private itemsMap = (items: ISalesByItemsItem[]): ITableRow[] => { + return R.map(this.itemMap, items); + }; + + /** + * Maps the given total node to table row. + * @param {ISalesByItemsTotal} total + * @returns {ITableRow[]} + */ + private totalMap = (total: ISalesByItemsTotal) => { const columns = this.commonTableAccessors(); const meta = {}; return tableRowMapper(total, columns, meta); - } + }; /** - * + * Retrieves the table rows. * @returns {ITableRow[]} */ public tableData(): ITableRow[] { @@ -57,9 +82,10 @@ export class SalesByItemsTable { */ public tableColumns(): ITableColumn[] { return [ - { key: 'item_name', label: 'Item Name' }, - { key: 'quantity', label: 'Quantity' }, - { key: 'sold_cost', label: 'Sold Cost' }, + { key: 'item_name', label: 'Item name' }, + { key: 'sold_quantity', label: 'Sold quantity' }, + { key: 'sold_amount', label: 'Sold amount' }, + { key: 'average_price', label: 'Average price' }, ]; } } From 471ce1b7af15ddd9d3e7169006e050ad229f3e9d Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Thu, 18 Jan 2024 14:39:56 +0200 Subject: [PATCH 3/6] feat(webapp): dynamic columns of sales by items sheet --- .../SalesByItems/SalesByItemsTable.ts | 23 +++-- .../SalesByItems/constants.ts | 6 ++ .../SalesByItems/SalesByItemProvider.tsx | 6 +- .../SalesByItems/SalesByItemsActionsBar.tsx | 18 +++- .../SalesByItems/SalesByItemsTable.tsx | 8 +- .../SalesByItems/components.tsx | 90 ++++++++++++++++- .../SalesByItems/dynamicColumns.ts | 77 +++++++++++++++ .../src/hooks/query/financialReports.tsx | 99 +++++++++++++------ 8 files changed, 277 insertions(+), 50 deletions(-) create mode 100644 packages/server/src/services/FinancialStatements/SalesByItems/constants.ts create mode 100644 packages/webapp/src/containers/FinancialStatements/SalesByItems/dynamicColumns.ts diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts index 33c39ccd6..f876e9a02 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsTable.ts @@ -7,8 +7,15 @@ import { ITableRow, } from '@/interfaces'; import { tableRowMapper } from '@/utils'; +import FinancialSheet from '../FinancialSheet'; +import { FinancialSheetStructure } from '../FinancialSheetStructure'; +import { FinancialTable } from '../FinancialTable'; +import { ROW_TYPE } from './constants'; -export class SalesByItemsTable { +export class SalesByItemsTable extends R.compose( + FinancialTable, + FinancialSheetStructure +)(FinancialSheet) { private readonly data: ISalesByItemsSheetStatement; /** @@ -16,6 +23,7 @@ export class SalesByItemsTable { * @param {ISalesByItemsSheetStatement} data */ constructor(data: ISalesByItemsSheetStatement) { + super(); this.data = data; } @@ -39,8 +47,9 @@ export class SalesByItemsTable { */ private itemMap = (item: ISalesByItemsItem): ITableRow => { const columns = this.commonTableAccessors(); - const meta = {}; - + const meta = { + rowTypes: [ROW_TYPE.ITEM], + }; return tableRowMapper(item, columns, meta); }; @@ -60,8 +69,9 @@ export class SalesByItemsTable { */ private totalMap = (total: ISalesByItemsTotal) => { const columns = this.commonTableAccessors(); - const meta = {}; - + const meta = { + rowTypes: [ROW_TYPE.TOTAL], + }; return tableRowMapper(total, columns, meta); }; @@ -81,11 +91,12 @@ export class SalesByItemsTable { * @returns {ITableColumn[]} */ public tableColumns(): ITableColumn[] { - return [ + const columns = [ { key: 'item_name', label: 'Item name' }, { key: 'sold_quantity', label: 'Sold quantity' }, { key: 'sold_amount', label: 'Sold amount' }, { key: 'average_price', label: 'Average price' }, ]; + return R.compose(this.tableColumnsCellIndexing)(columns); } } diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/constants.ts b/packages/server/src/services/FinancialStatements/SalesByItems/constants.ts new file mode 100644 index 000000000..0eb1e2311 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/SalesByItems/constants.ts @@ -0,0 +1,6 @@ + + +export enum ROW_TYPE { + ITEM = 'ITEM', + TOTAL = 'TOTAL', +} \ No newline at end of file diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.tsx index 8b06996dc..16c2ad44f 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.tsx @@ -1,7 +1,7 @@ // @ts-nocheck -import React, { createContext, useContext } from 'react'; +import { createContext, useContext } from 'react'; import FinancialReportPage from '../FinancialReportPage'; -import { useSalesByItems } from '@/hooks/query'; +import { useSalesByItemsTable } from '@/hooks/query'; import { transformFilterFormToQuery } from '../common'; const SalesByItemsContext = createContext(); @@ -12,7 +12,7 @@ function SalesByItemProvider({ query, ...props }) { isFetching, isLoading, refetch, - } = useSalesByItems( + } = useSalesByItemsTable( { ...transformFilterFormToQuery(query), }, diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsActionsBar.tsx index 56b025f35..9ac5a46a0 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsActionsBar.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsActionsBar.tsx @@ -19,6 +19,7 @@ import withSalesByItemsActions from './withSalesByItemsActions'; import { compose, saveInvoke } from '@/utils'; import { useSalesByItemsContext } from './SalesByItemProvider'; +import { SalesByItemsSheetExportMenu } from './components'; function SalesByItemsActionsBar({ // #withSalesByItems @@ -108,11 +109,18 @@ function SalesByItemsActionsBar({ icon={} text={} /> -