fix: financial reports responses

This commit is contained in:
Ahmed Bouhuolia
2025-05-11 15:06:03 +02:00
parent 9ebd967fe7
commit c10cad4256
30 changed files with 80 additions and 134 deletions

View File

@@ -14,14 +14,13 @@ export class APAgingSummaryController {
@ApiOperation({ summary: 'Get payable aging summary' })
public async get(
@Query() filter: IAPAgingSummaryQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.APAgingSummaryApp.table(filter);
return this.APAgingSummaryApp.table(filter);
res.status(200).send(table);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const csv = await this.APAgingSummaryApp.csv(filter);
@@ -51,9 +50,7 @@ export class APAgingSummaryController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.APAgingSummaryApp.sheet(filter);
res.status(200).send(sheet);
return this.APAgingSummaryApp.sheet(filter);
}
}
}

View File

@@ -15,7 +15,7 @@ export class ARAgingSummaryController {
@ApiOperation({ summary: 'Get receivable aging summary' })
public async get(
@Query() filter: IARAgingSummaryQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the xlsx format.
@@ -30,9 +30,8 @@ export class ARAgingSummaryController {
res.send(buffer);
// Retrieves the table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.ARAgingSummaryApp.table(filter);
return this.ARAgingSummaryApp.table(filter);
res.status(200).send(table);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.ARAgingSummaryApp.csv(filter);
@@ -52,9 +51,7 @@ export class ARAgingSummaryController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.ARAgingSummaryApp.sheet(filter);
res.status(200).send(sheet);
return this.ARAgingSummaryApp.sheet(filter);
}
}
}

View File

@@ -21,14 +21,14 @@ export class BalanceSheetStatementController {
@ApiResponse({ status: 200, description: 'Balance sheet statement' })
public async balanceSheet(
@Query() query: IBalanceSheetQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.balanceSheetApp.table(query);
res.status(200).send(table);
return table;
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.balanceSheetApp.csv(query);
@@ -59,7 +59,7 @@ export class BalanceSheetStatementController {
} else {
const sheet = await this.balanceSheetApp.sheet(query);
res.status(200).send(sheet);
return sheet;
}
}
}

View File

@@ -1,7 +1,7 @@
// @ts-nocheck
import * as R from 'ramda';
import { isEmpty } from 'lodash';
import moment from 'moment';
import * as moment from 'moment';
import { I18nService } from 'nestjs-i18n';
import {
ICashFlowStatementSection,

View File

@@ -15,14 +15,12 @@ export class CashflowController {
@ApiOperation({ summary: 'Get cashflow statement report' })
async getCashflow(
@Query() query: ICashFlowStatementQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.cashflowSheetApp.table(query);
res.status(200).send(table);
return this.cashflowSheetApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.cashflowSheetApp.csv(query);
@@ -52,9 +50,7 @@ export class CashflowController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const cashflow = await this.cashflowSheetApp.sheet(query);
res.status(200).send(cashflow);
return this.cashflowSheetApp.sheet(query);
}
}
}

View File

@@ -17,7 +17,7 @@ export class CustomerBalanceSummaryController {
@ApiOperation({ summary: 'Get customer balance summary report' })
async customerBalanceSummary(
@Query() filter: ICustomerBalanceSummaryQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the xlsx format.
@@ -38,8 +38,8 @@ export class CustomerBalanceSummaryController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.customerBalanceSummaryApp.table(filter);
res.status(200).send(table);
return this.customerBalanceSummaryApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const buffer = await this.customerBalanceSummaryApp.pdf(filter);
@@ -51,8 +51,7 @@ export class CustomerBalanceSummaryController {
res.send(buffer);
// Retrieves the json format.
} else {
const sheet = await this.customerBalanceSummaryApp.sheet(filter);
res.status(200).send(sheet);
return this.customerBalanceSummaryApp.sheet(filter);
}
}
}

View File

@@ -17,14 +17,12 @@ export class GeneralLedgerController {
@ApiOperation({ summary: 'Get general ledger report' })
public async getGeneralLedger(
@Query() query: IGeneralLedgerSheetQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.generalLedgerApplication.table(query);
res.status(200).send(table);
return this.generalLedgerApplication.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.generalLedgerApplication.csv(query);
@@ -53,9 +51,7 @@ export class GeneralLedgerController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.generalLedgerApplication.sheet(query);
res.status(200).send(sheet);
return this.generalLedgerApplication.sheet(query);
}
}
}

View File

@@ -16,7 +16,7 @@ export class InventoryItemDetailsController {
@ApiOperation({ summary: 'Get inventory item details' })
async inventoryItemDetails(
@Query() query: IInventoryDetailsQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
@@ -38,8 +38,7 @@ export class InventoryItemDetailsController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.inventoryItemDetailsApp.table(query);
res.status(200).send(table);
return this.inventoryItemDetailsApp.table(query);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const buffer = await this.inventoryItemDetailsApp.pdf(query);
@@ -50,9 +49,7 @@ export class InventoryItemDetailsController {
});
res.send(buffer);
} else {
const sheet = await this.inventoryItemDetailsApp.sheet(query);
res.status(200).send(sheet);
return this.inventoryItemDetailsApp.sheet(query);
}
}
}

View File

@@ -20,14 +20,12 @@ export class InventoryValuationController {
})
public async getInventoryValuationSheet(
@Query() query: IInventoryValuationReportQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.inventoryValuationApp.table(query);
res.status(200).send(table);
return this.inventoryValuationApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.inventoryValuationApp.csv(query);
@@ -57,9 +55,7 @@ export class InventoryValuationController {
res.status(200).send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.inventoryValuationApp.sheet(query);
res.status(200).send(sheet);
return this.inventoryValuationApp.sheet(query);
}
}
}

View File

@@ -15,14 +15,13 @@ export class JournalSheetController {
@ApiOperation({ summary: 'Journal report' })
async journalSheet(
@Query() query: IJournalReportQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.journalSheetApp.table(query);
res.status(200).send(table);
return this.journalSheetApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.journalSheetApp.csv(query);
@@ -51,9 +50,7 @@ export class JournalSheetController {
});
res.send(pdfContent);
} else {
const sheet = await this.journalSheetApp.sheet(query);
res.status(200).send(sheet);
return this.journalSheetApp.sheet(query);
}
}
}

View File

@@ -1,6 +1,6 @@
import { I18nService } from 'nestjs-i18n';
import { sumBy, chain, get, head } from 'lodash';
import moment from 'moment';
import * as moment from 'moment';
import {
IJournalReportEntriesGroup,
IJournalReportQuery,
@@ -9,17 +9,18 @@ import {
} from './JournalSheet.types';
import { FinancialSheet } from '../../common/FinancialSheet';
import { JournalSheetRepository } from './JournalSheetRepository';
import { Ledger } from '@/modules/Ledger/Ledger';
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
export class JournalSheet extends FinancialSheet {
readonly ledger: Ledger;
readonly query: IJournalReportQuery;
readonly repository: JournalSheetRepository;
readonly i18n: I18nService;
/**
* Constructor method.
* @param {IJournalReportQuery} query -
* @param {JournalSheetRepository} repository -
* @param {I18nService} i18n -
*/
constructor(
query: IJournalReportQuery,
@@ -130,6 +131,6 @@ export class JournalSheet extends FinancialSheet {
* @return {IJournalReport}
*/
reportData(): IJournalTableData {
return this.entriesWalker(this.ledger.entries);
return this.entriesWalker(this.repository.ledger.entries);
}
}

View File

@@ -1,9 +1,11 @@
import { Injectable } from '@nestjs/common';
import { JournalSheetService } from './JournalSheetService';
import { JournalSheetTableInjectable } from './JournalSheetTableInjectable';
import { JournalSheetExportInjectable } from './JournalSheetExport';
import { JournalSheetPdfInjectable } from './JournalSheetPdfInjectable';
import { IJournalReportQuery, IJournalTable } from './JournalSheet.types';
@Injectable()
export class JournalSheetApplication {
constructor(
private readonly journalSheetTable: JournalSheetTableInjectable,

View File

@@ -1,4 +1,4 @@
import moment from 'moment';
import * as moment from 'moment';
import { Injectable } from '@nestjs/common';
import { FinancialSheetMeta } from '../../common/FinancialSheetMeta';
import { IJournalReportQuery, IJournalSheetMeta } from './JournalSheet.types';

View File

@@ -1,8 +1,10 @@
import { Injectable } from '@nestjs/common';
import { I18nService } from 'nestjs-i18n';
import { JournalSheetService } from './JournalSheetService';
import { IJournalReportQuery, IJournalTable } from './JournalSheet.types';
import { JournalSheetTable } from './JournalSheetTable';
import { I18nService } from 'nestjs-i18n';
@Injectable()
export class JournalSheetTableInjectable {
constructor(
private readonly journalSheetService: JournalSheetService,

View File

@@ -1,3 +1,5 @@
import * as moment from 'moment';
export const HtmlTableCustomCss = `
table tr.row-type--total td{
font-weight: 600;

View File

@@ -23,7 +23,7 @@ export class ProfitLossSheetController {
@ApiOperation({ summary: 'Get profit/loss statement report' })
async profitLossSheet(
@Query() query: IProfitLossSheetQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the csv format.
@@ -36,9 +36,8 @@ export class ProfitLossSheetController {
res.send(sheet);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.profitLossSheetApp.table(query);
return this.profitLossSheetApp.table(query);
res.status(200).send(table);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
const sheet = await this.profitLossSheetApp.xlsx(query);
@@ -59,9 +58,7 @@ export class ProfitLossSheetController {
});
res.send(pdfContent);
} else {
const sheet = await this.profitLossSheetApp.sheet(query);
res.status(200).send(sheet);
return this.profitLossSheetApp.sheet(query);
}
}
}

View File

@@ -1,6 +1,6 @@
// @ts-nocheck
import * as R from 'ramda';
import moment from 'moment';
import * as moment from 'moment';
import { ITableColumn, ITableColumnAccessor } from '../../types/Table.types';
import { ProfitLossSheetTablePercentage } from './ProfitLossSheetTablePercentage';
import { ProfitLossTablePreviousPeriod } from './ProfitLossTablePreviousPeriod';

View File

@@ -17,14 +17,12 @@ export class PurchasesByItemReportController {
@ApiOperation({ summary: 'Get purchases by items report' })
async purchasesByItems(
@Query() filter: IPurchasesByItemsReportQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// JSON table response format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.purchasesByItemsApp.table(filter);
res.status(200).send(table);
return this.purchasesByItemsApp.table(filter);
// CSV response format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.purchasesByItemsApp.csv(filter);
@@ -54,9 +52,7 @@ export class PurchasesByItemReportController {
res.send(pdfContent);
// Json response format.
} else {
const sheet = await this.purchasesByItemsApp.sheet(filter);
res.status(200).send(sheet);
return this.purchasesByItemsApp.sheet(filter);
}
}
}

View File

@@ -23,7 +23,7 @@ export class SalesByItemsController {
@ApiOperation({ summary: 'Get sales by items report' })
public async salesByitems(
@Query() filter: ISalesByItemsReportQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the csv format.
@@ -36,9 +36,7 @@ export class SalesByItemsController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.salesByItemsApp.table(filter);
res.status(200).send(table);
return this.salesByItemsApp.table(filter);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
const buffer = this.salesByItemsApp.xlsx(filter);
@@ -59,8 +57,7 @@ export class SalesByItemsController {
});
res.send(pdfContent);
} else {
const sheet = await this.salesByItemsApp.sheet(filter);
res.status(200).send(sheet);
return this.salesByItemsApp.sheet(filter);
}
}
}

View File

@@ -1,9 +1,9 @@
import { Response } from 'express';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
import { SalesTaxLiabilitySummaryQuery } from './SalesTaxLiability.types';
import { AcceptType } from '@/constants/accept-type';
import { SalesTaxLiabilitySummaryApplication } from './SalesTaxLiabilitySummaryApplication';
import { Response } from 'express';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/sales-tax-liability-summary')
@ApiTags('reports')
@@ -20,16 +20,16 @@ export class SalesTaxLiabilitySummaryController {
@ApiOperation({ summary: 'Get sales tax liability summary report' })
public async getSalesTaxLiabilitySummary(
@Query() query: SalesTaxLiabilitySummaryQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.salesTaxLiabilitySummaryApp.table(query);
res.status(200).send(table);
return this.salesTaxLiabilitySummaryApp.table(query);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.salesTaxLiabilitySummaryApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
res.setHeader(
'Content-Type',
@@ -52,8 +52,7 @@ export class SalesTaxLiabilitySummaryController {
});
res.status(200).send(pdfContent);
} else {
const sheet = await this.salesTaxLiabilitySummaryApp.sheet(query);
res.status(200).send(sheet);
return this.salesTaxLiabilitySummaryApp.sheet(query);
}
}
}

View File

@@ -17,13 +17,12 @@ export class TransactionsByCustomerController {
@ApiResponse({ status: 200, description: 'Transactions by customer' })
async transactionsByCustomer(
@Query() filter: ITransactionsByCustomersFilter,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.transactionsByCustomersApp.table(filter);
res.status(200).send(table);
return this.transactionsByCustomersApp.table(filter);
// Retrieve the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
@@ -53,8 +52,7 @@ export class TransactionsByCustomerController {
});
res.send(pdfContent);
} else {
const sheet = await this.transactionsByCustomersApp.sheet(filter);
res.status(200).send(sheet);
return this.transactionsByCustomersApp.sheet(filter);
}
}
}

View File

@@ -17,7 +17,7 @@ export class TransactionsByVendorController {
@ApiResponse({ status: 200, description: 'Transactions by vendor' })
async transactionsByVendor(
@Query() filter: ITransactionsByVendorsFilter,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the xlsx format.
@@ -38,9 +38,7 @@ export class TransactionsByVendorController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.transactionsByVendorsApp.table(filter);
res.status(200).send(table);
return this.transactionsByVendorsApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.transactionsByVendorsApp.pdf(filter);
@@ -51,8 +49,7 @@ export class TransactionsByVendorController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.transactionsByVendorsApp.sheet(filter);
res.status(200).send(sheet);
return this.transactionsByVendorsApp.sheet(filter);
}
}
}

View File

@@ -18,7 +18,7 @@ export class TrialBalanceSheetController {
@ApiResponse({ status: 200, description: 'Trial balance sheet' })
async getTrialBalanceSheet(
@Query() query: ITrialBalanceSheetQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const filter = {
@@ -27,12 +27,11 @@ export class TrialBalanceSheetController {
};
// Retrieves in json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const { table, meta, query } =
await this.trialBalanceSheetApp.table(filter);
res.status(200).send({ table, meta, query });
return this.trialBalanceSheetApp.table(filter);
// Retrieves in xlsx format
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.trialBalanceSheetApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
res.setHeader(
'Content-Type',
@@ -50,6 +49,7 @@ export class TrialBalanceSheetController {
// Retrieves in pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.trialBalanceSheetApp.pdf(filter);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
@@ -57,9 +57,7 @@ export class TrialBalanceSheetController {
res.send(pdfContent);
// Retrieves in json format.
} else {
const { data, query, meta } =
await this.trialBalanceSheetApp.sheet(filter);
res.status(200).send({ data, query, meta });
return this.trialBalanceSheetApp.sheet(filter);
}
}
}

View File

@@ -17,7 +17,7 @@ export class VendorBalanceSummaryController {
@ApiResponse({ status: 200, description: 'Vendor balance summary' })
async vendorBalanceSummary(
@Query() filter: IVendorBalanceSummaryQuery,
@Res() res: Response,
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
// Retrieves the csv format.
@@ -38,9 +38,7 @@ export class VendorBalanceSummaryController {
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.vendorBalanceSummaryApp.table(filter);
res.status(200).send(table);
return this.vendorBalanceSummaryApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.vendorBalanceSummaryApp.pdf(filter);
@@ -52,8 +50,7 @@ export class VendorBalanceSummaryController {
res.send(pdfContent);
// Retrieves the json format.
} else {
const sheet = await this.vendorBalanceSummaryApp.sheet(filter);
res.status(200).send(sheet);
return this.vendorBalanceSummaryApp.sheet(filter);
}
}
}