import { Inject, Service } from 'typedi'; import { query } from 'express-validator'; import { NextFunction, Router, Request, Response, ValidationChain, } from 'express'; import BaseFinancialReportController from '../BaseFinancialReportController'; import { AbilitySubject, ICashFlowStatementDOO, ReportsAction, } from '@/interfaces'; import CashFlowTable from '@/services/FinancialStatements/CashFlow/CashFlowTable'; import HasTenancyService from '@/services/Tenancy/TenancyService'; import CashflowAccountTransactionsService from '@/services/FinancialStatements/CashflowAccountTransactions/CashflowAccountTransactionsService'; import { ServiceError } from '@/exceptions'; import CheckPolicies from '@/api/middleware/CheckPolicies'; @Service() export default class CashFlowAccountTransactionsController extends BaseFinancialReportController { @Inject() tenancy: HasTenancyService; @Inject() cashflowAccountTransactions: CashflowAccountTransactionsService; /** * Router constructor. */ router() { const router = Router(); router.get( '/', CheckPolicies( ReportsAction.READ_CASHFLOW_ACCOUNT_TRANSACTION, AbilitySubject.Report ), this.validationSchema, this.validationResult, this.asyncMiddleware(this.cashFlow), this.catchServiceErrors ); return router; } /** * Cashflow account transactions validation schecma. * @returns {ValidationChain[]} */ get validationSchema(): ValidationChain[] { return [ query('account_id').exists().isInt().toInt(), query('page').optional().isNumeric().toInt(), query('page_size').optional().isNumeric().toInt(), ]; } /** * Retrieve the cashflow account transactions statment to json response. * @param {ICashFlowStatement} cashFlow - */ private transformJsonResponse(casahflowAccountTransactions) { const { transactions, pagination } = casahflowAccountTransactions; return { transactions: this.transfromToResponse(transactions), pagination: this.transfromToResponse(pagination), }; } /** * Transformes the report statement to table rows. * @param {ITransactionsByVendorsStatement} statement - */ private transformToTableRows( cashFlowDOO: ICashFlowStatementDOO, tenantId: number ) { const i18n = this.tenancy.i18n(tenantId); const cashFlowTable = new CashFlowTable(cashFlowDOO, i18n); return { table: { data: cashFlowTable.tableRows(), columns: cashFlowTable.tableColumns(), }, query: this.transfromToResponse(cashFlowDOO.query), meta: this.transfromToResponse(cashFlowDOO.meta), }; } /** * Retrieve the cash flow statment. * @param {Request} req * @param {Response} res * @param {NextFunction} next * @returns {Response} */ private cashFlow = async ( req: Request, res: Response, next: NextFunction ) => { const { tenantId } = req; const query = this.matchedQueryData(req); try { const cashFlowAccountTransactions = await this.cashflowAccountTransactions.cashflowAccountTransactions( tenantId, query ); 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(cashFlow, tenantId)); case 'json': default: return res .status(200) .send(this.transformJsonResponse(cashFlowAccountTransactions)); } } catch (error) { next(error); } }; /** * Catches the service errors. * @param {Error} error - Error. * @param {Request} req - Request. * @param {Response} res - Response. * @param {NextFunction} next - */ private catchServiceErrors( error, req: Request, res: Response, next: NextFunction ) { if (error instanceof ServiceError) { if (error.errorType === 'ACCOUNT_ID_HAS_INVALID_TYPE') { return res.boom.badRequest( 'The given account id should be cash, bank or credit card type.', { errors: [{ type: 'ACCOUNT_ID_HAS_INVALID_TYPE', code: 200 }], } ); } if (error.errorType === 'account_not_found') { return res.boom.notFound('The given account not found.', { errors: [{ type: 'ACCOUNT.NOT.FOUND', code: 100 }], }); } } next(error); } }