diff --git a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts index 5e7aacb09e..2e72587c02 100644 --- a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts +++ b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts @@ -1,17 +1,18 @@ import { Router, Request, Response, NextFunction } from 'express'; import { query, ValidationChain } from 'express-validator'; -import moment from 'moment'; import { Inject, Service } from 'typedi'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseFinancialReportController from './BaseFinancialReportController'; -import PurchasesByItemsService from '@/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService'; +import { PurchasesByItemsService } from '@/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService'; import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; +import { PurcahsesByItemsApplication } from '@/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication'; @Service() export default class PurchasesByItemReportController extends BaseFinancialReportController { @Inject() - purchasesByItemsService: PurchasesByItemsService; + private purchasesByItemsApp: PurcahsesByItemsApplication; /** * Router constructor. @@ -63,20 +64,47 @@ export default class PurchasesByItemReportController extends BaseFinancialReport * @param {Request} req - * @param {Response} res - */ - async purchasesByItems(req: Request, res: Response, next: NextFunction) { + public async purchasesByItems(req: Request, res: Response) { const { tenantId } = req; const filter = this.matchedQueryData(req); - try { - const { data, query, meta } = - await this.purchasesByItemsService.purchasesByItems(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_XLSX, + ACCEPT_TYPE.APPLICATION_CSV, + ]); + + // JSON table response format. + if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) { + const table = await this.purchasesByItemsApp.table(tenantId, filter); + + return res.status(200).send(table); + // CSV response format. + } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { + const buffer = await this.purchasesByItemsApp.csv(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); + + return res.send(buffer); + // Xlsx response format. + } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { + const buffer = await this.purchasesByItemsApp.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); + // Json response format. + } else { + const sheet = await this.purchasesByItemsApp.sheet(tenantId, filter); + + return res.status(200).send(sheet); } } } diff --git a/packages/server/src/interfaces/APAgingSummaryReport.ts b/packages/server/src/interfaces/APAgingSummaryReport.ts index 6bf7c83bb7..2d7a8a447a 100644 --- a/packages/server/src/interfaces/APAgingSummaryReport.ts +++ b/packages/server/src/interfaces/APAgingSummaryReport.ts @@ -1,13 +1,10 @@ import { IAgingPeriod, - IAgingPeriodTotal, - IAgingAmount, IAgingSummaryQuery, IAgingSummaryTotal, IAgingSummaryContact, IAgingSummaryData, } from './AgingReport'; -import { INumberFormatQuery } from './FinancialStatements'; import { IFinancialTable } from './Table'; export interface IAPAgingSummaryQuery extends IAgingSummaryQuery { diff --git a/packages/server/src/interfaces/PurchasesByItemsSheet.ts b/packages/server/src/interfaces/PurchasesByItemsSheet.ts new file mode 100644 index 0000000000..f08fb97afc --- /dev/null +++ b/packages/server/src/interfaces/PurchasesByItemsSheet.ts @@ -0,0 +1,54 @@ +import { INumberFormatQuery } from './FinancialStatements'; +import { IFinancialTable } from './Table'; + +export interface IPurchasesByItemsReportQuery { + fromDate: Date | string; + toDate: Date | string; + itemsIds: number[]; + numberFormat: INumberFormatQuery; + noneTransactions: boolean; + onlyActive: boolean; +} + +export interface IPurchasesByItemsSheetMeta { + organizationName: string; + baseCurrency: string; +} + +export interface IPurchasesByItemsItem { + id: number; + name: string; + code: string; + quantitySold: number; + soldCost: number; + averageSellPrice: number; + + quantitySoldFormatted: string; + soldCostFormatted: string; + averageSellPriceFormatted: string; + currencyCode: string; +} + +export interface IPurchasesByItemsTotal { + quantitySold: number; + soldCost: number; + quantitySoldFormatted: string; + soldCostFormatted: string; + currencyCode: string; +} + +export type IPurchasesByItemsSheetData = { + items: IPurchasesByItemsItem[]; + total: IPurchasesByItemsTotal; +}; + +export interface IPurchasesByItemsSheet { + data: IPurchasesByItemsSheetData; + query: IPurchasesByItemsReportQuery; + meta: IPurchasesByItemsSheetMeta; +} + +export interface IPurchasesByItemsTable extends IFinancialTable { + query: IPurchasesByItemsReportQuery; + meta: IPurchasesByItemsSheetMeta; +} diff --git a/packages/server/src/services/Accounts/AccountsApplication.ts b/packages/server/src/services/Accounts/AccountsApplication.ts index 5e7043b9aa..8182b30586 100644 --- a/packages/server/src/services/Accounts/AccountsApplication.ts +++ b/packages/server/src/services/Accounts/AccountsApplication.ts @@ -3,8 +3,10 @@ import { IAccount, IAccountCreateDTO, IAccountEditDTO, + IAccountResponse, IAccountsFilter, IAccountsTransactionsFilter, + IFilterMeta, IGetAccountTransactionPOJO, } from '@/interfaces'; import { CreateAccount } from './CreateAccount'; @@ -14,6 +16,7 @@ import { ActivateAccount } from './ActivateAccount'; import { GetAccounts } from './GetAccounts'; import { GetAccount } from './GetAccount'; import { GetAccountTransactions } from './GetAccountTransactions'; + @Service() export class AccountsApplication { @Inject() @@ -113,19 +116,22 @@ export class AccountsApplication { /** * Retrieves the accounts list. - * @param {number} tenantId - * @param {IAccountsFilter} filterDTO - * @returns + * @param {number} tenantId + * @param {IAccountsFilter} filterDTO + * @returns {Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }>} */ - public getAccounts = (tenantId: number, filterDTO: IAccountsFilter) => { + public getAccounts = ( + tenantId: number, + filterDTO: IAccountsFilter + ): Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }> => { return this.getAccountsService.getAccountsList(tenantId, filterDTO); }; /** * Retrieves the given account transactions. - * @param {number} tenantId - * @param {IAccountsTransactionsFilter} filter - * @returns {Promise} + * @param {number} tenantId + * @param {IAccountsTransactionsFilter} filter + * @returns {Promise} */ public getAccountsTransactions = ( tenantId: number, diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts index 0dba04f03d..b679334c6e 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts @@ -2,36 +2,34 @@ import { get, isEmpty, sumBy } from 'lodash'; import * as R from 'ramda'; import FinancialSheet from '../FinancialSheet'; import { allPassedConditionsPass, transformToMap } from 'utils'; +import { IAccountTransaction, IItem } from '@/interfaces'; import { - IAccountTransaction, - IInventoryValuationTotal, - IInventoryValuationItem, - IInventoryValuationReportQuery, - IInventoryValuationStatement, - IItem, -} from '@/interfaces'; - -export default class InventoryValuationReport extends FinancialSheet { + IPurchasesByItemsItem, + IPurchasesByItemsReportQuery, + IPurchasesByItemsSheetData, + IPurchasesByItemsTotal, +} from '@/interfaces/PurchasesByItemsSheet'; + +export class PurchasesByItems extends FinancialSheet { readonly baseCurrency: string; readonly items: IItem[]; readonly itemsTransactions: Map; - readonly query: IInventoryValuationReportQuery; + readonly query: IPurchasesByItemsReportQuery; /** * Constructor method. - * @param {IInventoryValuationReportQuery} query + * @param {IPurchasesByItemsReportQuery} query * @param {IItem[]} items * @param {IAccountTransaction[]} itemsTransactions * @param {string} baseCurrency */ constructor( - query: IInventoryValuationReportQuery, + query: IPurchasesByItemsReportQuery, items: IItem[], itemsTransactions: IAccountTransaction[], baseCurrency: string ) { super(); - this.baseCurrency = baseCurrency; this.items = items; this.itemsTransactions = transformToMap(itemsTransactions, 'itemId'); @@ -98,7 +96,7 @@ export default class InventoryValuationReport extends FinancialSheet { * @param {IInventoryValuationItem} item * @returns */ - private itemSectionMapper = (item: IItem): IInventoryValuationItem => { + private itemSectionMapper = (item: IItem): IPurchasesByItemsItem => { const meta = this.getItemTransaction(item.id); return { @@ -145,9 +143,9 @@ export default class InventoryValuationReport extends FinancialSheet { /** * Retrieve the items sections. - * @returns {IInventoryValuationItem[]} + * @returns {IPurchasesByItemsItem[]} */ - private itemsSection = (): IInventoryValuationItem[] => { + private itemsSection = (): IPurchasesByItemsItem[] => { return R.compose( R.when(this.isItemsPostFilter, this.itemsFilter), this.itemsMapper @@ -156,10 +154,10 @@ export default class InventoryValuationReport extends FinancialSheet { /** * Retrieve the total section of the sheet. - * @param {IInventoryValuationItem[]} items - * @returns {IInventoryValuationTotal} + * @param {IPurchasesByItemsItem[]} items + * @returns {IPurchasesByItemsTotal} */ - totalSection(items: IInventoryValuationItem[]): IInventoryValuationTotal { + private totalSection(items: IPurchasesByItemsItem[]): IPurchasesByItemsTotal { const quantityPurchased = sumBy(items, (item) => item.quantityPurchased); const purchaseCost = sumBy(items, (item) => item.purchaseCost); @@ -176,12 +174,12 @@ export default class InventoryValuationReport extends FinancialSheet { /** * Retrieve the sheet data. - * @returns + * @returns {IInventoryValuationStatement} */ - reportData(): IInventoryValuationStatement { + public reportData(): IPurchasesByItemsSheetData { const items = this.itemsSection(); const total = this.totalSection(items); - return items.length > 0 ? { items, total } : {}; + return { items, total }; } } diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts new file mode 100644 index 0000000000..c9a94bdbc8 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts @@ -0,0 +1,73 @@ +import { Service, Inject } from 'typedi'; +import { PurchasesByItemsExport } from './PurchasesByItemsExport'; +import { + IPurchasesByItemsReportQuery, + IPurchasesByItemsSheet, + IPurchasesByItemsTable, +} from '@/interfaces/PurchasesByItemsSheet'; +import { PurchasesByItemsTableInjectable } from './PurchasesByItemsTableInjectable'; +import { PurchasesByItemsService } from './PurchasesByItemsService'; + +@Service() +export class PurcahsesByItemsApplication { + @Inject() + private purchasesByItemsSheet: PurchasesByItemsService; + + @Inject() + private purchasesByItemsTable: PurchasesByItemsTableInjectable; + + @Inject() + private purchasesByItemsExport: PurchasesByItemsExport; + + /** + * Retrieves the purchases by items in json format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns + */ + public sheet( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + return this.purchasesByItemsSheet.purchasesByItems(tenantId, query); + } + + /** + * Retrieves the purchases by items in table format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} + */ + public table( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + return this.purchasesByItemsTable.table(tenantId, query); + } + + /** + * Retrieves the purchases by items in csv format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} + */ + public csv( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + return this.purchasesByItemsExport.csv(tenantId, query); + } + + /** + * Retrieves the purchases by items in xlsx format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} + */ + public xlsx( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + return this.purchasesByItemsExport.xlsx(tenantId, query); + } +} diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsExport.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsExport.ts new file mode 100644 index 0000000000..96ed4daf7f --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsExport.ts @@ -0,0 +1,46 @@ +import { Inject, Service } from 'typedi'; +import { TableSheet } from '@/lib/Xlsx/TableSheet'; +import { PurchasesByItemsTableInjectable } from './PurchasesByItemsTableInjectable'; +import { IPurchasesByItemsReportQuery } from '@/interfaces/PurchasesByItemsSheet'; + +@Service() +export class PurchasesByItemsExport { + @Inject() + private purchasesByItemsTable: PurchasesByItemsTableInjectable; + + /** + * Retrieves the purchases by items sheet in XLSX format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} + */ + public async xlsx( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + const table = await this.purchasesByItemsTable.table(tenantId, query); + + const tableSheet = new TableSheet(table.table); + const tableCsv = tableSheet.convertToXLSX(); + + return tableSheet.convertToBuffer(tableCsv, 'xlsx'); + } + + /** + * Retrieves the purchases by items sheet in CSV format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} + */ + public async csv( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { + const table = await this.purchasesByItemsTable.table(tenantId, query); + + const tableSheet = new TableSheet(table.table); + const tableCsv = tableSheet.convertToCSV(); + + return tableCsv; + } +} diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts index df4aee1adc..b9455be398 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts @@ -1,24 +1,24 @@ -import { Service, Inject } from 'typedi'; import moment from 'moment'; -import { - IInventoryValuationReportQuery, - IInventoryValuationStatement, - IInventoryValuationSheetMeta, -} from '@/interfaces'; +import { Service, Inject } from 'typedi'; import TenancyService from '@/services/Tenancy/TenancyService'; -import PurchasesByItems from './PurchasesByItems'; +import { PurchasesByItems } from './PurchasesByItems'; import { Tenant } from '@/system/models'; +import { + IPurchasesByItemsReportQuery, + IPurchasesByItemsSheet, + IPurchasesByItemsSheetMeta, +} from '@/interfaces/PurchasesByItemsSheet'; @Service() -export default class InventoryValuationReportService { +export class PurchasesByItemsService { @Inject() private tenancy: TenancyService; /** - * Defaults balance sheet filter query. - * @return {IBalanceSheetQuery} + * Defaults purchases by items filter query. + * @return {IPurchasesByItemsReportQuery} */ - get defaultQuery(): IInventoryValuationReportQuery { + get defaultQuery(): IPurchasesByItemsReportQuery { return { fromDate: moment().startOf('month').format('YYYY-MM-DD'), toDate: moment().format('YYYY-MM-DD'), @@ -40,7 +40,7 @@ export default class InventoryValuationReportService { * @param {number} tenantId - * @returns {IBalanceSheetMeta} */ - reportMetadata(tenantId: number): IInventoryValuationSheetMeta { + reportMetadata(tenantId: number): IPurchasesByItemsSheetMeta { const settings = this.tenancy.settings(tenantId); const organizationName = settings.get({ @@ -62,18 +62,13 @@ export default class InventoryValuationReportService { * Retrieve balance sheet statement. * ------------- * @param {number} tenantId - * @param {IBalanceSheetQuery} query - * - * @return {IBalanceSheetStatement} + * @param {IPurchasesByItemsReportQuery} query + * @return {Promise} */ public async purchasesByItems( tenantId: number, - query: IInventoryValuationReportQuery - ): Promise<{ - data: IInventoryValuationStatement; - query: IInventoryValuationReportQuery; - meta: IInventoryValuationSheetMeta; - }> { + query: IPurchasesByItemsReportQuery + ): Promise { const { Item, InventoryTransaction } = this.tenancy.models(tenantId); const tenant = await Tenant.query() @@ -106,7 +101,6 @@ export default class InventoryValuationReportService { builder.modify('filterDateRange', filter.fromDate, filter.toDate); } ); - const purchasesByItemsInstance = new PurchasesByItems( filter, inventoryItems, diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts new file mode 100644 index 0000000000..a7b6ee7352 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts @@ -0,0 +1,111 @@ +import * as R from 'ramda'; +import { ITableColumn, ITableColumnAccessor, ITableRow } from '@/interfaces'; +import { ROW_TYPE } from './_types'; +import { tableRowMapper } from '@/utils'; +import { FinancialTable } from '../FinancialTable'; +import { FinancialSheetStructure } from '../FinancialSheetStructure'; +import FinancialSheet from '../FinancialSheet'; +import { + IPurchasesByItemsItem, + IPurchasesByItemsSheetData, + IPurchasesByItemsTotal, +} from '@/interfaces/PurchasesByItemsSheet'; + +export class PurchasesByItemsTable extends R.compose( + FinancialTable, + FinancialSheetStructure +)(FinancialSheet) { + private data: IPurchasesByItemsSheetData; + + /** + * Constructor method. + * @param data + */ + constructor(data) { + super(); + this.data = data; + } + + /** + * Retrieves thge common table accessors. + * @returns {ITableColumnAccessor[]} + */ + private commonTableAccessors(): ITableColumnAccessor[] { + return [ + { key: 'item_name', accessor: 'name' }, + { key: 'quantity_purchases', accessor: 'quantityPurchasedFormatted' }, + { key: 'purchase_amount', accessor: 'purchaseCostFormatted' }, + { key: 'average_cost', accessor: 'averageCostPriceFormatted' }, + ]; + } + + /** + * Retrieves the common table columns. + * @returns {ITableColumn[]} + */ + private commonTableColumns(): ITableColumn[] { + return [ + { label: 'Item name', key: 'item_name' }, + { label: 'Quantity Purchased', key: 'quantity_purchases' }, + { label: 'Purchase Amount', key: 'purchase_amount' }, + { label: 'Average Price', key: 'average_cost' }, + ]; + } + + /** + * Maps the given item node to table row. + * @param {IPurchasesByItemsItem} item + * @returns {ITableRow} + */ + private itemMap = (item: IPurchasesByItemsItem): ITableRow => { + const columns = this.commonTableAccessors(); + const meta = { + rowTypes: [ROW_TYPE.ITEM], + }; + return tableRowMapper(item, columns, meta); + }; + + /** + * Maps the given items nodes to table rows. + * @param {IPurchasesByItemsItem[]} items - Items nodes. + * @returns {ITableRow[]} + */ + private itemsMap = (items: IPurchasesByItemsItem[]): ITableRow[] => { + return R.map(this.itemMap)(items); + }; + + /** + * Maps the given total node to table rows. + * @param {IPurchasesByItemsTotal} total + * @returns {ITableRow} + */ + private totalNodeMap = (total: IPurchasesByItemsTotal): ITableRow => { + const columns = this.commonTableAccessors(); + const meta = { + rowTypes: [ROW_TYPE.TOTAL], + }; + return tableRowMapper(total, columns, meta); + }; + + /** + * Retrieves the table columns. + * @returns {ITableColumn[]} + */ + public tableColumns(): ITableColumn[] { + const columns = this.commonTableColumns(); + return R.compose(this.tableColumnsCellIndexing)(columns); + } + + /** + * Retrieves the table rows. + * @returns {ITableRow[]} + */ + public tableData(): ITableRow[] { + const itemsRows = this.itemsMap(this.data.items); + const totalRow = this.totalNodeMap(this.data.total); + + return R.compose( + R.when(R.always(R.not(R.isEmpty(itemsRows))), R.append(totalRow)) + )(itemsRows) as ITableRow[]; + } +} diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts new file mode 100644 index 0000000000..066ac6f72d --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts @@ -0,0 +1,38 @@ +import { + IPurchasesByItemsReportQuery, + IPurchasesByItemsTable, +} from '@/interfaces/PurchasesByItemsSheet'; +import { Inject, Service } from 'typedi'; +import { PurchasesByItemsService } from './PurchasesByItemsService'; +import { PurchasesByItemsTable } from './PurchasesByItemsTable'; + +@Service() +export class PurchasesByItemsTableInjectable { + @Inject() + private purchasesByItemsSheet: PurchasesByItemsService; + + /** + * Retrieves the purchases by items table format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} filter + * @returns {Promise} + */ + public async table( + tenantId: number, + filter: IPurchasesByItemsReportQuery + ): Promise { + const { data, query, meta } = + await this.purchasesByItemsSheet.purchasesByItems(tenantId, filter); + + const table = new PurchasesByItemsTable(data); + + return { + table: { + columns: table.tableColumns(), + rows: table.tableData(), + }, + meta, + query, + }; + } +} diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/_types.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/_types.ts new file mode 100644 index 0000000000..d9fbb7dc00 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/_types.ts @@ -0,0 +1,5 @@ + +export enum ROW_TYPE { + TOTAL = 'TOTAL', + ITEM = 'ITEM' +} \ No newline at end of file diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.tsx index 4a5a817382..c3859939e0 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsActionsBar.tsx @@ -18,6 +18,7 @@ import withPurchasesByItems from './withPurchasesByItems'; import withPurchasesByItemsActions from './withPurchasesByItemsActions'; import { compose, saveInvoke } from '@/utils'; import { usePurchaseByItemsContext } from './PurchasesByItemsProvider'; +import { PurchasesByItemsExportMenu } from './components'; function PurchasesByItemsActionsBar({ // #withPurchasesByItems @@ -106,11 +107,18 @@ function PurchasesByItemsActionsBar({ icon={} text={} /> -