From 47fd8f0be61ae25bf345960e0145aa3f08208658 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Tue, 21 Nov 2023 21:47:56 +0200 Subject: [PATCH] feat: export csv/xlsx financial reports --- .../FinancialStatements/BalanceSheet.ts | 4 +- .../CustomerBalanceSummary/index.ts | 116 ++++++++--------- .../InventoryDetails/index.ts | 115 ++++++++--------- .../FinancialStatements/ProfitLossSheet.ts | 63 +++++----- .../FinancialStatements/SalesByItems.ts | 15 +-- .../SalesTaxLiabilitySummary/index.ts | 83 +++++++----- .../VendorBalanceSummary/index.ts | 119 ++++++++---------- .../src/interfaces/CustomerBalanceSummary.ts | 9 +- packages/server/src/interfaces/Http.ts | 4 +- .../server/src/interfaces/InventoryDetails.ts | 17 +-- .../CashFlow/CashflowTableInjectable.ts | 2 +- .../SalesByItems/SalesByItemsService.ts | 4 - .../TrialBalanceSheetApplication.ts | 9 +- 13 files changed, 276 insertions(+), 284 deletions(-) diff --git a/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts b/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts index a265b4909..63943bd24 100644 --- a/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts +++ b/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts @@ -6,7 +6,6 @@ import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseFinancialReportController from './BaseFinancialReportController'; import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; import { BalanceSheetApplication } from '@/services/FinancialStatements/BalanceSheet/BalanceSheetApplication'; import { ACCEPT_TYPE } from '@/interfaces/Http'; @@ -81,6 +80,9 @@ export default class BalanceSheetStatementController extends BaseFinancialReport /** * Retrieve the balance sheet. + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next */ private async balanceSheet(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; diff --git a/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts index eb026e752..6c10543f5 100644 --- a/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts +++ b/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts @@ -1,29 +1,21 @@ import { Router, Request, Response, NextFunction } from 'express'; import { query } from 'express-validator'; import { Inject } from 'typedi'; -import { - AbilitySubject, - ICustomerBalanceSummaryStatement, - ReportsAction, -} from '@/interfaces'; +import { AbilitySubject, ReportsAction } from '@/interfaces'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; -import CustomerBalanceSummary from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService'; import BaseFinancialReportController from '../BaseFinancialReportController'; -import CustomerBalanceSummaryTableRows from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows'; import CheckPolicies from '@/api/middleware/CheckPolicies'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; +import { CustomerBalanceSummaryApplication } from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication'; export default class CustomerBalanceSummaryReportController extends BaseFinancialReportController { @Inject() - customerBalanceSummaryService: CustomerBalanceSummary; - - @Inject() - tenancy: HasTenancyService; + private customerBalanceSummaryApp: CustomerBalanceSummaryApplication; /** * Router constructor. */ - router() { + public router() { const router = Router(); router.get( @@ -42,7 +34,7 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia /** * Validation schema. */ - get validationSchema() { + private get validationSchema() { return [ ...this.sheetNumberFormatValidationSchema, @@ -62,75 +54,67 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia ]; } - /** - * Transformes the balance summary statement to table rows. - * @param {ICustomerBalanceSummaryStatement} statement - - */ - private transformToTableRows( - tenantId, - { data, query }: ICustomerBalanceSummaryStatement - ) { - const i18n = this.tenancy.i18n(tenantId); - const tableRows = new CustomerBalanceSummaryTableRows(data, query, i18n); - - return { - table: { - columns: tableRows.tableColumns(), - data: tableRows.tableRows(), - }, - query: this.transfromToResponse(query), - }; - } - - /** - * Transformes the balance summary statement to raw json. - * @param {ICustomerBalanceSummaryStatement} customerBalance - - */ - private transformToJsonResponse({ - data, - columns, - query, - }: ICustomerBalanceSummaryStatement) { - return { - data: this.transfromToResponse(data), - columns: this.transfromToResponse(columns), - query: this.transfromToResponse(query), - }; - } - /** * Retrieve payable aging summary report. * @param {Request} req - * @param {Response} res - * @param {NextFunction} next - */ - async customerBalanceSummary( + private async customerBalanceSummary( req: Request, res: Response, next: NextFunction ) { - const { tenantId, settings } = req; + const { tenantId } = req; const filter = this.matchedQueryData(req); try { - const customerBalanceSummary = - await this.customerBalanceSummaryService.customerBalanceSummary( + 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, + ]); + + // Retrieves the xlsx format. + if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { + const buffer = await this.customerBalanceSummaryApp.xlsx( tenantId, filter ); - const accept = this.accepts(req); - const acceptType = accept.types(['json', 'application/json+table']); + res.setHeader( + 'Content-Disposition', + 'attachment; filename=output.xlsx' + ); + res.setHeader( + 'Content-Type', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ); + return res.send(buffer); + // Retrieves the csv format. + } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { + const buffer = await this.customerBalanceSummaryApp.csv( + tenantId, + filter + ); + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); - switch (acceptType) { - case 'application/json+table': - return res - .status(200) - .send(this.transformToTableRows(tenantId, customerBalanceSummary)); - case 'application/json': - default: - return res - .status(200) - .send(this.transformToJsonResponse(customerBalanceSummary)); + return res.send(buffer); + // Retrieves the json table format. + } else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) { + const table = await this.customerBalanceSummaryApp.table( + tenantId, + filter + ); + return res.status(200).send(table); + } else { + const sheet = await this.customerBalanceSummaryApp.sheet( + tenantId, + filter + ); + return res.status(200).send(sheet); } } catch (error) { next(error); diff --git a/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts b/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts index 2f8df7722..07f91af4a 100644 --- a/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts +++ b/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts @@ -8,24 +8,20 @@ import { ValidationChain, } from 'express'; import BaseController from '@/api/controllers/BaseController'; -import InventoryDetailsService from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsService'; -import InventoryDetailsTable from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsTable'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; import { AbilitySubject, ReportsAction } from '@/interfaces'; +import { InventortyDetailsApplication } from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication'; import CheckPolicies from '@/api/middleware/CheckPolicies'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; @Service() export default class InventoryDetailsController extends BaseController { @Inject() - inventoryDetailsService: InventoryDetailsService; - - @Inject() - tenancy: HasTenancyService; + private inventoryItemDetailsApp: InventortyDetailsApplication; /** * Router constructor. */ - router() { + public router() { const router = Router(); router.get( @@ -45,7 +41,7 @@ export default class InventoryDetailsController extends BaseController { * Balance sheet validation schecma. * @returns {ValidationChain[]} */ - get validationSchema(): ValidationChain[] { + private get validationSchema(): ValidationChain[] { return [ query('number_format.precision') .optional() @@ -77,69 +73,66 @@ export default class InventoryDetailsController extends BaseController { } /** - * Retrieve the cashflow statment to json response. - * @param {ICashFlowStatement} cashFlow - - */ - private transformJsonResponse(inventoryDetails) { - const { data, query, meta } = inventoryDetails; - - return { - data: this.transfromToResponse(data), - query: this.transfromToResponse(query), - meta: this.transfromToResponse(meta), - }; - } - - /** - * Transformes the report statement to table rows. - */ - private transformToTableRows(inventoryDetails, tenantId: number) { - const i18n = this.tenancy.i18n(tenantId); - const inventoryDetailsTable = new InventoryDetailsTable( - inventoryDetails, - i18n - ); - - return { - table: { - data: inventoryDetailsTable.tableData(), - columns: inventoryDetailsTable.tableColumns(), - }, - query: this.transfromToResponse(inventoryDetails.query), - meta: this.transfromToResponse(inventoryDetails.meta), - }; - } - - /** - * Retrieve the cash flow statment. + * Retrieve the inventory item details sheet. * @param {Request} req * @param {Response} res * @param {NextFunction} next * @returns {Response} */ - async inventoryDetails(req: Request, res: Response, next: NextFunction) { - const { tenantId, settings } = req; + private async inventoryDetails( + req: Request, + res: Response, + next: NextFunction + ) { + const { tenantId } = req; const filter = { ...this.matchedQueryData(req), }; try { - const inventoryDetails = - await this.inventoryDetailsService.inventoryDetails(tenantId, filter); - const accept = this.accepts(req); - const acceptType = accept.types(['json', 'application/json+table']); - - switch (acceptType) { - case 'application/json+table': - return res - .status(200) - .send(this.transformToTableRows(inventoryDetails, tenantId)); - case 'json': - default: - return res - .status(200) - .send(this.transformJsonResponse(inventoryDetails)); + const acceptType = accept.types([ + ACCEPT_TYPE.APPLICATION_JSON, + ACCEPT_TYPE.APPLICATION_JSON_TABLE, + ACCEPT_TYPE.APPLICATION_CSV, + ACCEPT_TYPE.APPLICATION_XLSX, + ]); + // Retrieves the csv format. + if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { + const buffer = await this.inventoryItemDetailsApp.csv(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); + + return res.send(buffer); + // Retrieves the xlsx format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { + const buffer = await this.inventoryItemDetailsApp.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 table format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { + const table = await this.inventoryItemDetailsApp.table( + tenantId, + filter + ); + return res.status(200).send(table); + } else { + const sheet = await this.inventoryItemDetailsApp.sheet( + tenantId, + filter + ); + return res.status(200).send(sheet); } } catch (error) { next(error); diff --git a/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts b/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts index 0f57aa860..8c2404335 100644 --- a/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts +++ b/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts @@ -97,34 +97,41 @@ export default class ProfitLossSheetController extends BaseFinancialReportContro ACCEPT_TYPE.APPLICATION_CSV, ACCEPT_TYPE.APPLICATION_XLSX, ]); - // Retrieves the csv format. - if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { - const sheet = await this.profitLossSheetApp.csv(tenantId, filter); - - res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); - res.setHeader('Content-Type', 'text/csv'); - - return res.send(sheet); - // Retrieves the json table format. - } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { - const table = await this.profitLossSheetApp.table(tenantId, filter); - - return res.status(200).send(table); - // Retrieves the xlsx format. - } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { - const sheet = await this.profitLossSheetApp.xlsx(tenantId, filter); - - res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx'); - res.setHeader( - 'Content-Type', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - ); - return res.send(sheet); - // Retrieves the json format. - } else { - const sheet = await this.profitLossSheetApp.sheet(tenantId, filter); - - return res.status(200).send(sheet); + try { + // Retrieves the csv format. + if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { + const sheet = await this.profitLossSheetApp.csv(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); + + return res.send(sheet); + // Retrieves the json table format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { + const table = await this.profitLossSheetApp.table(tenantId, filter); + + return res.status(200).send(table); + // Retrieves the xlsx format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { + const sheet = await this.profitLossSheetApp.xlsx(tenantId, filter); + + res.setHeader( + 'Content-Disposition', + 'attachment; filename=output.xlsx' + ); + res.setHeader( + 'Content-Type', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ); + return res.send(sheet); + // Retrieves the json format. + } else { + const sheet = await this.profitLossSheetApp.sheet(tenantId, filter); + + return res.status(200).send(sheet); + } + } catch (error) { + next(error); } } } diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts index 759165bd1..d31954398 100644 --- a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts +++ b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts @@ -16,15 +16,12 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon /** * Router constructor. */ - router() { + public router() { const router = Router(); router.get( '/', - CheckPolicies( - ReportsAction.READ_SALES_BY_ITEMS, - AbilitySubject.Report - ), + CheckPolicies(ReportsAction.READ_SALES_BY_ITEMS, AbilitySubject.Report), this.validationSchema, this.validationResult, asyncMiddleware(this.purchasesByItems.bind(this)) @@ -35,7 +32,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon /** * Validation schema. */ - get validationSchema(): ValidationChain[] { + private get validationSchema(): ValidationChain[] { return [ query('from_date').optional().isISO8601(), query('to_date').optional().isISO8601(), @@ -63,7 +60,11 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon * @param {Request} req - * @param {Response} res - */ - async purchasesByItems(req: Request, res: Response, next: NextFunction) { + private async purchasesByItems( + req: Request, + res: Response, + next: NextFunction + ) { const { tenantId } = req; const filter = this.matchedQueryData(req); diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts index 56c837288..933b5c9c4 100644 --- a/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts +++ b/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts @@ -1,20 +1,21 @@ +import { Inject } from 'typedi'; import { Router, Request, Response, NextFunction } from 'express'; import { query } from 'express-validator'; -import { Inject } from 'typedi'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseFinancialReportController from '../BaseFinancialReportController'; import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; -import { SalesTaxLiabilitySummaryService } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService'; +import { SalesTaxLiabilitySummaryApplication } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; export default class SalesTaxLiabilitySummary extends BaseFinancialReportController { @Inject() - private salesTaxLiabilitySummaryService: SalesTaxLiabilitySummaryService; + private salesTaxLiabilitySummaryApp: SalesTaxLiabilitySummaryApplication; /** * Router constructor. */ - router() { + public router() { const router = Router(); router.get( @@ -31,8 +32,9 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl /** * Validation schema. + * @returns {ValidationChain[]} */ - get validationSchema() { + private get validationSchema() { return [ query('from_date').optional().isISO8601(), query('to_date').optional().isISO8601(), @@ -45,7 +47,7 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl * @param {Response} res - * @param {NextFunction} next - */ - async salesTaxLiabilitySummary( + private async salesTaxLiabilitySummary( req: Request, res: Response, next: NextFunction @@ -55,33 +57,52 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl try { const accept = this.accepts(req); - const acceptType = accept.types(['json', 'application/json+table']); + const acceptType = accept.types([ + ACCEPT_TYPE.APPLICATION_JSON, + ACCEPT_TYPE.APPLICATION_JSON_TABLE, + ACCEPT_TYPE.APPLICATION_CSV, + ACCEPT_TYPE.APPLICATION_XLSX, + ]); - switch (acceptType) { - case 'application/json+table': - const salesTaxLiabilityTable = - await this.salesTaxLiabilitySummaryService.salesTaxLiabilitySummaryTable( - tenantId, - filter - ); + // Retrieves the json table format. + if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { + const table = await this.salesTaxLiabilitySummaryApp.table( + tenantId, + filter + ); + return res.status(200).send(table); + // Retrieves the xlsx format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { + const buffer = await this.salesTaxLiabilitySummaryApp.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 csv format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { + const buffer = await this.salesTaxLiabilitySummaryApp.csv( + tenantId, + filter + ); + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); - return res.status(200).send({ - table: salesTaxLiabilityTable.table, - query: salesTaxLiabilityTable.query, - meta: salesTaxLiabilityTable.meta, - }); - case 'json': - default: - const salesTaxLiability = - await this.salesTaxLiabilitySummaryService.salesTaxLiability( - tenantId, - filter - ); - return res.status(200).send({ - data: salesTaxLiability.data, - query: salesTaxLiability.query, - meta: salesTaxLiability.meta, - }); + return res.send(buffer); + // Retrieves the json format. + } else { + const sheet = await this.salesTaxLiabilitySummaryApp.sheet( + tenantId, + filter + ); + return res.status(200).send(sheet); } } catch (error) { next(error); diff --git a/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts index e93891938..ade69cb62 100644 --- a/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts +++ b/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts @@ -3,27 +3,19 @@ import { query } from 'express-validator'; import { Inject } from 'typedi'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseFinancialReportController from '../BaseFinancialReportController'; -import VendorBalanceSummaryTableRows from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows'; -import VendorBalanceSummaryService from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService'; -import { - AbilitySubject, - IVendorBalanceSummaryStatement, - ReportsAction, -} from '@/interfaces'; +import { AbilitySubject, ReportsAction } from '@/interfaces'; import CheckPolicies from '@/api/middleware/CheckPolicies'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; +import { ACCEPT_TYPE } from '@/interfaces/Http'; +import { VendorBalanceSummaryApplication } from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication'; export default class VendorBalanceSummaryReportController extends BaseFinancialReportController { @Inject() - vendorBalanceSummaryService: VendorBalanceSummaryService; - - @Inject() - tenancy: HasTenancyService; + private vendorBalanceSummaryApp: VendorBalanceSummaryApplication; /** * Router constructor. */ - router() { + public router() { const router = Router(); router.get( @@ -41,7 +33,7 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR /** * Validation schema. */ - get validationSchema() { + private get validationSchema() { return [ ...this.sheetNumberFormatValidationSchema, query('as_date').optional().isISO8601(), @@ -59,73 +51,62 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR ]; } - /** - * Transformes the report statement to table rows. - * @param {IVendorBalanceSummaryStatement} statement - - */ - private transformToTableRows( - tenantId: number, - { data, query }: IVendorBalanceSummaryStatement - ) { - const i18n = this.tenancy.i18n(tenantId); - const tableData = new VendorBalanceSummaryTableRows( - data, - query, - i18n - ); - return { - table: { - columns: tableData.tableColumns(), - data: tableData.tableRows(), - }, - query, - }; - } - - /** - * Transformes the report statement to raw json. - * @param {IVendorBalanceSummaryStatement} statement - - */ - private transformToJsonResponse({ - data, - columns, - }: IVendorBalanceSummaryStatement) { - return { - data: this.transfromToResponse(data), - columns: this.transfromToResponse(columns), - query: this.transfromToResponse(query), - }; - } - /** * Retrieve vendors balance summary. * @param {Request} req - * @param {Response} res - * @param {NextFunction} next - */ - async vendorBalanceSummary(req: Request, res: Response, next: NextFunction) { - const { tenantId, settings } = req; + public async vendorBalanceSummary( + req: Request, + res: Response, + next: NextFunction + ) { + const { tenantId } = req; const filter = this.matchedQueryData(req); try { - const vendorBalanceSummary = - await this.vendorBalanceSummaryService.vendorBalanceSummary( + 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, + ]); + + // Retrieves the csv format. + if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { + const buffer = await this.vendorBalanceSummaryApp.csv(tenantId, filter); + + res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); + res.setHeader('Content-Type', 'text/csv'); + + return res.send(buffer); + } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { + const buffer = await this.vendorBalanceSummaryApp.xlsx( tenantId, filter ); - const accept = this.accepts(req); - const acceptType = accept.types(['json', 'application/json+table']); - - switch (acceptType) { - case 'application/json+table': - return res - .status(200) - .send(this.transformToTableRows(tenantId, vendorBalanceSummary)); - case 'json': - default: - return res - .status(200) - .send(this.transformToJsonResponse(vendorBalanceSummary)); + res.setHeader( + 'Content-Disposition', + 'attachment; filename=output.xlsx' + ); + res.setHeader('Content-Type', 'application/vnd.openxmlformats'); + return res.send(buffer); + // Retrieves the json table format. + } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { + const table = await this.vendorBalanceSummaryApp.table( + tenantId, + filter + ); + return res.status(200).send(table); + // Retrieves the json format. + } else { + const sheet = await this.vendorBalanceSummaryApp.sheet( + tenantId, + filter + ); + return res.status(200).send(sheet); } } catch (error) { next(error); diff --git a/packages/server/src/interfaces/CustomerBalanceSummary.ts b/packages/server/src/interfaces/CustomerBalanceSummary.ts index cda13f7c9..cf5b5900d 100644 --- a/packages/server/src/interfaces/CustomerBalanceSummary.ts +++ b/packages/server/src/interfaces/CustomerBalanceSummary.ts @@ -1,11 +1,10 @@ -import { INumberFormatQuery } from './FinancialStatements'; - import { IContactBalanceSummaryQuery, IContactBalanceSummaryAmount, IContactBalanceSummaryPercentage, IContactBalanceSummaryTotal, } from './ContactBalanceSummary'; +import { IFinancialTable } from './Table'; export interface ICustomerBalanceSummaryQuery extends IContactBalanceSummaryQuery { @@ -19,7 +18,7 @@ export interface ICustomerBalanceSummaryPercentage extends IContactBalanceSummaryPercentage {} export interface ICustomerBalanceSummaryCustomer { - id: number, + id: number; customerName: string; total: ICustomerBalanceSummaryAmount; percentageOfColumn?: ICustomerBalanceSummaryPercentage; @@ -47,3 +46,7 @@ export interface ICustomerBalanceSummaryService { query: ICustomerBalanceSummaryQuery ): Promise; } + +export interface ICustomerBalanceSummaryTable extends IFinancialTable { + query: ICustomerBalanceSummaryQuery; +} diff --git a/packages/server/src/interfaces/Http.ts b/packages/server/src/interfaces/Http.ts index 582c1f28d..2189cb106 100644 --- a/packages/server/src/interfaces/Http.ts +++ b/packages/server/src/interfaces/Http.ts @@ -1,9 +1,7 @@ - - export const ACCEPT_TYPE = { APPLICATION_PDF: 'application/pdf', APPLICATION_JSON: 'application/json', APPLICATION_JSON_TABLE: 'application/json+table', APPLICATION_XLSX: 'application/xlsx', APPLICATION_CSV: 'application/csv', -}; \ No newline at end of file +}; diff --git a/packages/server/src/interfaces/InventoryDetails.ts b/packages/server/src/interfaces/InventoryDetails.ts index 733cb588a..033ec269d 100644 --- a/packages/server/src/interfaces/InventoryDetails.ts +++ b/packages/server/src/interfaces/InventoryDetails.ts @@ -1,13 +1,12 @@ -import { - INumberFormatQuery, -} from './FinancialStatements'; +import { INumberFormatQuery } from './FinancialStatements'; +import { IFinancialTable } from './Table'; export interface IInventoryDetailsQuery { fromDate: Date | string; toDate: Date | string; numberFormat: INumberFormatQuery; noneTransactions: boolean; - itemsIds: number[] + itemsIds: number[]; warehousesIds?: number[]; branchesIds?: number[]; @@ -66,7 +65,7 @@ export interface IInventoryDetailsItemTransaction { cost: IInventoryDetailsNumber; value: IInventoryDetailsNumber; profitMargin: IInventoryDetailsNumber; - + rate: IInventoryDetailsNumber; runningQuantity: IInventoryDetailsNumber; @@ -80,7 +79,6 @@ export type IInventoryDetailsNode = | IInventoryDetailsItemTransaction; export type IInventoryDetailsData = IInventoryDetailsItem[]; - export interface IInventoryItemDetailMeta { isCostComputeRunning: boolean; organizationName: string; @@ -91,4 +89,9 @@ export interface IInvetoryItemDetailDOO { data: IInventoryDetailsData; query: IInventoryDetailsQuery; meta: IInventoryItemDetailMeta; -} \ No newline at end of file +} + +export interface IInvetoryItemDetailsTable extends IFinancialTable { + query: IInventoryDetailsQuery; + meta: IInventoryItemDetailMeta; +} diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts index a313a8260..0a54071f2 100644 --- a/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts +++ b/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts @@ -4,7 +4,7 @@ import HasTenancyService from "@/services/Tenancy/TenancyService"; import CashFlowTable from "./CashFlowTable"; import CashFlowStatementService from "./CashFlowService"; -@Service(); +@Service() export class CashflowTableInjectable { @Inject() private tenancy: HasTenancyService; diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts index 7570ef572..6f81e1489 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts @@ -87,10 +87,6 @@ export default class SalesByItemsReportService { ...this.defaultQuery, ...query, }; - this.logger.info('[sales_by_items] trying to calculate the report.', { - filter, - tenantId, - }); // Inventory items for sales report. const inventoryItems = await Item.query().onBuild((q) => { q.where('type', 'inventory'); diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts index 48c8384da..a771c8f15 100644 --- a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts +++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts @@ -1,7 +1,7 @@ import { Inject, Service } from 'typedi'; import { TrialBalanceSheetTableInjectable } from './TrialBalanceSheetTableInjectable'; import { TrialBalanceExportInjectable } from './TrialBalanceExportInjectable'; -import { ITrialBalanceSheetQuery } from '@/interfaces'; +import { ITrialBalanceSheetQuery, ITrialBalanceStatement } from '@/interfaces'; import TrialBalanceSheetService from './TrialBalanceSheetInjectable'; @Service() @@ -19,9 +19,12 @@ export class TrialBalanceSheetApplication { * Retrieves the trial balance sheet. * @param {number} tenantId * @param {ITrialBalanceSheetQuery} query - * @returns {} + * @returns {Promise} */ - public sheet(tenantId: number, query: ITrialBalanceSheetQuery) { + public sheet( + tenantId: number, + query: ITrialBalanceSheetQuery + ): Promise { return this.sheetService.trialBalanceSheet(tenantId, query); }