From b9ab091791a46d24b7087c2abe9878387840b0f1 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 21 Jan 2024 21:59:35 +0200 Subject: [PATCH 1/6] feat(server): wip purchases by items exporting --- .../src/interfaces/PurchasesByItemsSheet.ts | 54 +++++++++ .../PurchasesByItems/PurchasesByItems.ts | 10 +- .../PurchasesByItemsApplication.ts | 45 +++++++ .../PurchasesByItemsExport.ts | 43 +++++++ .../PurchasesByItemsService.ts | 6 +- .../PurchasesByItems/PurchasesByItemsTable.ts | 110 ++++++++++++++++++ .../PurchasesByItemsTableInjectable.ts | 13 +++ .../PurchasesByItems/_types.ts | 5 + 8 files changed, 277 insertions(+), 9 deletions(-) create mode 100644 packages/server/src/interfaces/PurchasesByItemsSheet.ts create mode 100644 packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts create mode 100644 packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsExport.ts create mode 100644 packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts create mode 100644 packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts create mode 100644 packages/server/src/services/FinancialStatements/PurchasesByItems/_types.ts diff --git a/packages/server/src/interfaces/PurchasesByItemsSheet.ts b/packages/server/src/interfaces/PurchasesByItemsSheet.ts new file mode 100644 index 0000000000..33c24d309a --- /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 ISalesByItemsSheet { + data: IPurchasesByItemsSheetData; + query: IPurchasesByItemsReportQuery; + meta: IPurchasesByItemsSheetMeta; +} + +export interface IPurchasesByItemsTable extends IFinancialTable { + query: IPurchasesByItemsReportQuery; + meta: IPurchasesByItemsSheetMeta; +} diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts index 0dba04f03d..32904ef221 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItems.ts @@ -11,7 +11,7 @@ import { IItem, } from '@/interfaces'; -export default class InventoryValuationReport extends FinancialSheet { +export class PurchasesByItems extends FinancialSheet { readonly baseCurrency: string; readonly items: IItem[]; readonly itemsTransactions: Map; @@ -159,7 +159,7 @@ export default class InventoryValuationReport extends FinancialSheet { * @param {IInventoryValuationItem[]} items * @returns {IInventoryValuationTotal} */ - totalSection(items: IInventoryValuationItem[]): IInventoryValuationTotal { + private totalSection(items: IInventoryValuationItem[]): IInventoryValuationTotal { const quantityPurchased = sumBy(items, (item) => item.quantityPurchased); const purchaseCost = sumBy(items, (item) => item.purchaseCost); @@ -176,12 +176,12 @@ export default class InventoryValuationReport extends FinancialSheet { /** * Retrieve the sheet data. - * @returns + * @returns {IInventoryValuationStatement} */ - reportData(): IInventoryValuationStatement { + public reportData(): IInventoryValuationStatement { 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..b2142a50af --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts @@ -0,0 +1,45 @@ +import { Service, Inject } from 'typedi'; +import { PurchasesByItemsExport } from './PurchasesByItemsExport'; +import { IPurchasesByItemsReportQuery } from '@/interfaces/PurchasesByItemsSheet'; + +@Service() +export class PurcahsesByItemsApplication { + @Inject() + private purchasesByItemsSheet: any; + + @Inject() + private purchasesByItemsTable: any; + + @Inject() + private purchasesByItemsExport: PurchasesByItemsExport; + + public sheet(tenantId: number, query: any) {} + + public table(tenantId: number, query: any) {} + + /** + * 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..2a96ac1e2c --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsExport.ts @@ -0,0 +1,43 @@ +import { Inject, Service } from 'typedi'; +import { TableSheet } from '@/lib/Xlsx/TableSheet'; +import { ISalesByItemsReportQuery } from '@/interfaces'; +import { PurchasesByItemsTableInjectable } from './PurchasesByItemsTableInjectable'; + +@Service() +export class PurchasesByItemsExport { + @Inject() + private purchasesByItemsTable: PurchasesByItemsTableInjectable; + + /** + * Retrieves the purchases by items sheet in XLSX format. + * @param {number} tenantId + * @param {ISalesByItemsReportQuery} query + * @returns {Promise} + */ + public async xlsx(tenantId: number, query: ISalesByItemsReportQuery) { + 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 {ISalesByItemsReportQuery} query + * @returns {Promise} + */ + public async csv( + tenantId: number, + query: ISalesByItemsReportQuery + ): 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..31f11afa7e 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts @@ -6,11 +6,11 @@ import { IInventoryValuationSheetMeta, } from '@/interfaces'; import TenancyService from '@/services/Tenancy/TenancyService'; -import PurchasesByItems from './PurchasesByItems'; +import { PurchasesByItems } from './PurchasesByItems'; import { Tenant } from '@/system/models'; @Service() -export default class InventoryValuationReportService { +export class PurchasesByItemsService { @Inject() private tenancy: TenancyService; @@ -63,7 +63,6 @@ export default class InventoryValuationReportService { * ------------- * @param {number} tenantId * @param {IBalanceSheetQuery} query - * * @return {IBalanceSheetStatement} */ public async purchasesByItems( @@ -106,7 +105,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..a8e1668ec4 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts @@ -0,0 +1,110 @@ +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, + IPurchasesByItemsTotal, +} from '@/interfaces/PurchasesByItemsSheet'; + +export class PurchasesByItemsTable extends R.compose( + FinancialTable, + FinancialSheetStructure +)(FinancialSheet) { + private data: any; + + /** + * 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: 'itemName' }, + { 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 Purchases', key: 'quantity_purchases' }, + { label: 'Purchase Amount', key: 'purchase_amount' }, + { label: 'Average Cost', 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.ITEM], + }; + 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..6fe514e571 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts @@ -0,0 +1,13 @@ +import { + IPurchasesByItemsReportQuery, + IPurchasesByItemsTable, +} from '@/interfaces/PurchasesByItemsSheet'; +import { Service } from 'typedi'; + +@Service() +export class PurchasesByItemsTableInjectable { + table( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise {} +} 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 From 82b8ec3e8010ae757ecf800da116038af27f3c0c Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 22 Jan 2024 18:05:13 +0200 Subject: [PATCH 2/6] feat: wip --- .../FinancialStatements/PurchasesByItem.ts | 7 ++-- .../src/interfaces/APAgingSummaryReport.ts | 3 -- .../services/Accounts/AccountsApplication.ts | 20 +++++++---- .../PurchasesByItemsApplication.ts | 13 ++++++-- .../PurchasesByItemsTableInjectable.ts | 33 ++++++++++++++++--- 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts index 5e7aacb09e..33d5ba8f0d 100644 --- a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts +++ b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts @@ -1,17 +1,16 @@ 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'; @Service() -export default class PurchasesByItemReportController extends BaseFinancialReportController { +export class PurchasesByItemReportController extends BaseFinancialReportController { @Inject() - purchasesByItemsService: PurchasesByItemsService; + private purchasesByItemsService: PurchasesByItemsService; /** * Router constructor. 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/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/PurchasesByItemsApplication.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts index b2142a50af..77e303f0a9 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts @@ -1,6 +1,7 @@ import { Service, Inject } from 'typedi'; import { PurchasesByItemsExport } from './PurchasesByItemsExport'; import { IPurchasesByItemsReportQuery } from '@/interfaces/PurchasesByItemsSheet'; +import { PurchasesByItemsTableInjectable } from './PurchasesByItemsTableInjectable'; @Service() export class PurcahsesByItemsApplication { @@ -8,14 +9,22 @@ export class PurcahsesByItemsApplication { private purchasesByItemsSheet: any; @Inject() - private purchasesByItemsTable: any; + private purchasesByItemsTable: PurchasesByItemsTableInjectable; @Inject() private purchasesByItemsExport: PurchasesByItemsExport; public sheet(tenantId: number, query: any) {} - public table(tenantId: number, query: any) {} + /** + * + * @param {number} tenantId + * @param {} query + * @returns + */ + public table(tenantId: number, query: IPurchasesByItemsReportQuery) { + return this.purchasesByItemsTable.table(tenantId, query); + } /** * Retrieves the purchases by items in csv format. diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts index 6fe514e571..066ac6f72d 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTableInjectable.ts @@ -2,12 +2,37 @@ import { IPurchasesByItemsReportQuery, IPurchasesByItemsTable, } from '@/interfaces/PurchasesByItemsSheet'; -import { Service } from 'typedi'; +import { Inject, Service } from 'typedi'; +import { PurchasesByItemsService } from './PurchasesByItemsService'; +import { PurchasesByItemsTable } from './PurchasesByItemsTable'; @Service() export class PurchasesByItemsTableInjectable { - table( + @Inject() + private purchasesByItemsSheet: PurchasesByItemsService; + + /** + * Retrieves the purchases by items table format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} filter + * @returns {Promise} + */ + public async table( tenantId: number, - query: IPurchasesByItemsReportQuery - ): Promise {} + 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, + }; + } } From e1f3cfc96f81e8d3ce164164f9123cbf6c4bc67b Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 22 Jan 2024 23:32:14 +0200 Subject: [PATCH 3/6] feat(server): purchases by items table format --- .../FinancialStatements/PurchasesByItem.ts | 55 ++++++++++++++----- .../PurchasesByItemsApplication.ts | 31 ++++++++--- .../PurchasesByItems/PurchasesByItemsTable.ts | 5 +- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts index 33d5ba8f0d..2e72587c02 100644 --- a/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts +++ b/packages/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts @@ -6,11 +6,13 @@ import BaseFinancialReportController from './BaseFinancialReportController'; 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 class PurchasesByItemReportController extends BaseFinancialReportController { +export default class PurchasesByItemReportController extends BaseFinancialReportController { @Inject() - private purchasesByItemsService: PurchasesByItemsService; + private purchasesByItemsApp: PurcahsesByItemsApplication; /** * Router constructor. @@ -62,20 +64,47 @@ export class PurchasesByItemReportController extends BaseFinancialReportControll * @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/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts index 77e303f0a9..e6086262a6 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsApplication.ts @@ -1,12 +1,16 @@ import { Service, Inject } from 'typedi'; import { PurchasesByItemsExport } from './PurchasesByItemsExport'; -import { IPurchasesByItemsReportQuery } from '@/interfaces/PurchasesByItemsSheet'; +import { + IPurchasesByItemsReportQuery, + IPurchasesByItemsTable, +} from '@/interfaces/PurchasesByItemsSheet'; import { PurchasesByItemsTableInjectable } from './PurchasesByItemsTableInjectable'; +import { PurchasesByItemsService } from './PurchasesByItemsService'; @Service() export class PurcahsesByItemsApplication { @Inject() - private purchasesByItemsSheet: any; + private purchasesByItemsSheet: PurchasesByItemsService; @Inject() private purchasesByItemsTable: PurchasesByItemsTableInjectable; @@ -14,15 +18,26 @@ export class PurcahsesByItemsApplication { @Inject() private purchasesByItemsExport: PurchasesByItemsExport; - public sheet(tenantId: number, query: any) {} + /** + * Retrieves the purchases by items in json format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns + */ + public sheet(tenantId: number, query: any) { + return this.purchasesByItemsSheet.purchasesByItems(tenantId, query); + } /** - * - * @param {number} tenantId - * @param {} query - * @returns + * Retrieves the purchases by items in table format. + * @param {number} tenantId + * @param {IPurchasesByItemsReportQuery} query + * @returns {Promise} */ - public table(tenantId: number, query: IPurchasesByItemsReportQuery) { + public table( + tenantId: number, + query: IPurchasesByItemsReportQuery + ): Promise { return this.purchasesByItemsTable.table(tenantId, query); } diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts index a8e1668ec4..12bcebf71e 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts @@ -7,6 +7,7 @@ import { FinancialSheetStructure } from '../FinancialSheetStructure'; import FinancialSheet from '../FinancialSheet'; import { IPurchasesByItemsItem, + IPurchasesByItemsSheetData, IPurchasesByItemsTotal, } from '@/interfaces/PurchasesByItemsSheet'; @@ -14,7 +15,7 @@ export class PurchasesByItemsTable extends R.compose( FinancialTable, FinancialSheetStructure )(FinancialSheet) { - private data: any; + private data: IPurchasesByItemsSheetData; /** * Constructor method. @@ -81,7 +82,7 @@ export class PurchasesByItemsTable extends R.compose( private totalNodeMap = (total: IPurchasesByItemsTotal): ITableRow => { const columns = this.commonTableAccessors(); const meta = { - rowTypes: [ROW_TYPE.ITEM], + rowTypes: [ROW_TYPE.TOTAL], }; return tableRowMapper(total, columns, meta); }; From fc786814eb052aefeac4a05651829f36e4dff1a0 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Tue, 23 Jan 2024 12:13:36 +0200 Subject: [PATCH 4/6] feat: purchases by items exporting --- .../PurchasesByItems/PurchasesByItemsTable.ts | 2 +- .../PurchasesByItemsActionsBar.tsx | 18 +- .../PurchasesByItemsProvider.tsx | 5 +- .../PurchasesByItemsTable.tsx | 8 +- .../PurchasesByItems/components.tsx | 162 +++++++++++------- .../PurchasesByItems/dynamicColumns.ts | 89 ++++++++++ .../src/hooks/query/financialReports.tsx | 54 +++++- 7 files changed, 255 insertions(+), 83 deletions(-) create mode 100644 packages/webapp/src/containers/FinancialStatements/PurchasesByItems/dynamicColumns.ts diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts index 12bcebf71e..23480de461 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsTable.ts @@ -32,7 +32,7 @@ export class PurchasesByItemsTable extends R.compose( */ private commonTableAccessors(): ITableColumnAccessor[] { return [ - { key: 'item_name', accessor: 'itemName' }, + { key: 'item_name', accessor: 'name' }, { key: 'quantity_purchases', accessor: 'quantityPurchasedFormatted' }, { key: 'purchase_amount', accessor: 'purchaseCostFormatted' }, { key: 'average_cost', accessor: 'averageCostPriceFormatted' }, 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={} /> -