diff --git a/packages/server/src/api/controllers/Cashflow/DeleteCashflowTransaction.ts b/packages/server/src/api/controllers/Cashflow/DeleteCashflowTransaction.ts index 4d94022da..1d0edece0 100644 --- a/packages/server/src/api/controllers/Cashflow/DeleteCashflowTransaction.ts +++ b/packages/server/src/api/controllers/Cashflow/DeleteCashflowTransaction.ts @@ -3,14 +3,15 @@ import { Router, Request, Response, NextFunction } from 'express'; import { param } from 'express-validator'; import BaseController from '../BaseController'; import { ServiceError } from '@/exceptions'; -import { DeleteCashflowTransaction } from '../../../services/Cashflow/DeleteCashflowTransactionService'; import CheckPolicies from '@/api/middleware/CheckPolicies'; + import { AbilitySubject, CashflowAction } from '@/interfaces'; +import { CashflowApplication } from '@/services/Cashflow/CashflowApplication'; @Service() export default class DeleteCashflowTransactionController extends BaseController { @Inject() - private deleteCashflowService: DeleteCashflowTransaction; + private cashflowApplication: CashflowApplication; /** * Controller router. @@ -44,7 +45,7 @@ export default class DeleteCashflowTransactionController extends BaseController try { const { oldCashflowTransaction } = - await this.deleteCashflowService.deleteCashflowTransaction( + await this.cashflowApplication.deleteTransaction( tenantId, transactionId ); diff --git a/packages/server/src/api/controllers/Cashflow/GetCashflowAccounts.ts b/packages/server/src/api/controllers/Cashflow/GetCashflowAccounts.ts index b84dad4eb..d1bc97e0a 100644 --- a/packages/server/src/api/controllers/Cashflow/GetCashflowAccounts.ts +++ b/packages/server/src/api/controllers/Cashflow/GetCashflowAccounts.ts @@ -7,14 +7,12 @@ import GetCashflowTransactionsService from '@/services/Cashflow/GetCashflowTrans import { ServiceError } from '@/exceptions'; import CheckPolicies from '@/api/middleware/CheckPolicies'; import { AbilitySubject, CashflowAction } from '@/interfaces'; +import { CashflowApplication } from '@/services/Cashflow/CashflowApplication'; @Service() export default class GetCashflowAccounts extends BaseController { @Inject() - private getCashflowAccountsService: GetCashflowAccountsService; - - @Inject() - private getCashflowTransactionsService: GetCashflowTransactionsService; + private cashflowApplication: CashflowApplication; /** * Controller router. @@ -62,10 +60,7 @@ export default class GetCashflowAccounts extends BaseController { try { const cashflowAccounts = - await this.getCashflowAccountsService.getCashflowAccounts( - tenantId, - filter - ); + await this.cashflowApplication.getCashflowAccounts(tenantId, filter); return res.status(200).send({ cashflow_accounts: this.transfromToResponse(cashflowAccounts), diff --git a/packages/server/src/api/controllers/Cashflow/GetCashflowTransaction.ts b/packages/server/src/api/controllers/Cashflow/GetCashflowTransaction.ts index 80d610f48..9e7169859 100644 --- a/packages/server/src/api/controllers/Cashflow/GetCashflowTransaction.ts +++ b/packages/server/src/api/controllers/Cashflow/GetCashflowTransaction.ts @@ -6,11 +6,12 @@ import GetCashflowTransactionsService from '@/services/Cashflow/GetCashflowTrans import { ServiceError } from '@/exceptions'; import CheckPolicies from '@/api/middleware/CheckPolicies'; import { AbilitySubject, CashflowAction } from '@/interfaces'; +import { CashflowApplication } from '@/services/Cashflow/CashflowApplication'; @Service() export default class GetCashflowAccounts extends BaseController { @Inject() - private getCashflowTransactionsService: GetCashflowTransactionsService; + private cashflowApplication: CashflowApplication; /** * Controller router. @@ -43,11 +44,11 @@ export default class GetCashflowAccounts extends BaseController { const { transactionId } = req.params; try { - const cashflowTransaction = - await this.getCashflowTransactionsService.getCashflowTransaction( - tenantId, - transactionId - ); + const cashflowTransaction = await this.cashflowApplication.getTransaction( + tenantId, + transactionId + + ); return res.status(200).send({ cashflow_transaction: this.transfromToResponse(cashflowTransaction), diff --git a/packages/server/src/api/controllers/Cashflow/NewCashflowTransaction.ts b/packages/server/src/api/controllers/Cashflow/NewCashflowTransaction.ts index d0953d8d8..a1af70c15 100644 --- a/packages/server/src/api/controllers/Cashflow/NewCashflowTransaction.ts +++ b/packages/server/src/api/controllers/Cashflow/NewCashflowTransaction.ts @@ -1,18 +1,14 @@ import { Service, Inject } from 'typedi'; -import { check, oneOf } from 'express-validator'; +import { ValidationChain, check, param, query } from 'express-validator'; import { Router, Request, Response, NextFunction } from 'express'; import BaseController from '../BaseController'; import { ServiceError } from '@/exceptions'; -import NewCashflowTransactionService from '@/services/Cashflow/NewCashflowTransactionService'; import CheckPolicies from '@/api/middleware/CheckPolicies'; import { AbilitySubject, CashflowAction } from '@/interfaces'; import { CashflowApplication } from '@/services/Cashflow/CashflowApplication'; @Service() export default class NewCashflowTransactionController extends BaseController { - @Inject() - private newCashflowTranscationService: NewCashflowTransactionService; - @Inject() private cashflowApplication: CashflowApplication; @@ -29,6 +25,8 @@ export default class NewCashflowTransactionController extends BaseController { ); router.get( '/transactions/:id/uncategorized', + this.getUncategorizedTransactionsValidationSchema, + this.validationResult, this.asyncMiddleware(this.getUncategorizedCashflowTransactions), this.catchServiceErrors ); @@ -62,6 +60,18 @@ export default class NewCashflowTransactionController extends BaseController { return router; } + /** + * Getting uncategorized transactions validation schema. + * @returns {ValidationChain} + */ + public get getUncategorizedTransactionsValidationSchema() { + return [ + param('id').exists().isNumeric().toInt(), + query('page').optional().isNumeric().toInt(), + query('page_size').optional().isNumeric().toInt(), + ]; + } + /** * Categorize as expense validation schema. */ @@ -112,7 +122,7 @@ export default class NewCashflowTransactionController extends BaseController { check('branch_id').optional({ nullable: true }).isNumeric().toInt(), check('publish').default(false).isBoolean().toBoolean(), ]; - }√ + } /** * Creates a new cashflow transaction. @@ -130,7 +140,7 @@ export default class NewCashflowTransactionController extends BaseController { try { const cashflowTransaction = - await this.newCashflowTranscationService.newCashflowTransaction( + await this.cashflowApplication.createTransaction( tenantId, ownerContributionDTO, userId @@ -159,7 +169,7 @@ export default class NewCashflowTransactionController extends BaseController { const { id: cashflowTransactionId } = req.params; try { - const data= await this.cashflowApplication.uncategorizeTransaction( + const data = await this.cashflowApplication.uncategorizeTransaction( tenantId, cashflowTransactionId ); @@ -229,9 +239,9 @@ export default class NewCashflowTransactionController extends BaseController { /** * Retrieves the uncategorized cashflow transactions. - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next */ public getUncategorizedCashflowTransaction = async ( req: Request, @@ -240,7 +250,7 @@ export default class NewCashflowTransactionController extends BaseController { ) => { const { tenantId } = req; const { id: transactionId } = req.params; - + try { const data = await this.cashflowApplication.getUncategorizedTransaction( tenantId, @@ -254,9 +264,9 @@ export default class NewCashflowTransactionController extends BaseController { /** * Retrieves the uncategorized cashflow transactions. - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next */ public getUncategorizedCashflowTransactions = async ( req: Request, @@ -265,11 +275,13 @@ export default class NewCashflowTransactionController extends BaseController { ) => { const { tenantId } = req; const { id: accountId } = req.params; - + const query = this.matchedQueryData(req); + try { const data = await this.cashflowApplication.getUncategorizedTransactions( tenantId, - accountId + accountId, + query ); return res.status(200).send(data); @@ -337,9 +349,9 @@ export default class NewCashflowTransactionController extends BaseController { errors: [ { type: 'UNCATEGORIZED_TRANSACTION_TYPE_INVALID', - code: 4100, - } - ] + code: 4100, + }, + ], }); } } diff --git a/packages/server/src/interfaces/CashflowService.ts b/packages/server/src/interfaces/CashflowService.ts index 5b446571d..acce307db 100644 --- a/packages/server/src/interfaces/CashflowService.ts +++ b/packages/server/src/interfaces/CashflowService.ts @@ -156,3 +156,8 @@ export interface CategorizeTransactionAsExpenseDTO { description: string; branchId?: number; } + +export interface IGetUncategorizedTransactionsQuery { + page?: number; + pageSize?: number; +} diff --git a/packages/server/src/services/Cashflow/CashflowApplication.ts b/packages/server/src/services/Cashflow/CashflowApplication.ts index 2fb1ff7bb..6688c9016 100644 --- a/packages/server/src/services/Cashflow/CashflowApplication.ts +++ b/packages/server/src/services/Cashflow/CashflowApplication.ts @@ -5,19 +5,33 @@ import { CategorizeCashflowTransaction } from './CategorizeCashflowTransaction'; import { CategorizeTransactionAsExpenseDTO, CreateUncategorizedTransactionDTO, + ICashflowAccountsFilter, + ICashflowNewCommandDTO, ICategorizeCashflowTransactioDTO, - IUncategorizedCashflowTransaction, + IGetUncategorizedTransactionsQuery, } from '@/interfaces'; import { CategorizeTransactionAsExpense } from './CategorizeTransactionAsExpense'; import { GetUncategorizedTransactions } from './GetUncategorizedTransactions'; import { CreateUncategorizedTransaction } from './CreateUncategorizedTransaction'; import { GetUncategorizedTransaction } from './GetUncategorizedTransaction'; +import NewCashflowTransactionService from './NewCashflowTransactionService'; +import GetCashflowAccountsService from './GetCashflowAccountsService'; +import { GetCashflowTransactionService } from './GetCashflowTransactionsService'; @Service() export class CashflowApplication { + @Inject() + private createTransactionService: NewCashflowTransactionService; + @Inject() private deleteTransactionService: DeleteCashflowTransaction; + @Inject() + private getCashflowAccountsService: GetCashflowAccountsService; + + @Inject() + private getCashflowTransactionService: GetCashflowTransactionService; + @Inject() private uncategorizeTransactionService: UncategorizeCashflowTransaction; @@ -36,6 +50,25 @@ export class CashflowApplication { @Inject() private createUncategorizedTransactionService: CreateUncategorizedTransaction; + /** + * Creates a new cashflow transaction. + * @param {number} tenantId + * @param {ICashflowNewCommandDTO} transactionDTO + * @param {number} userId + * @returns + */ + public createTransaction( + tenantId: number, + transactionDTO: ICashflowNewCommandDTO, + userId?: number + ) { + return this.createTransactionService.newCashflowTransaction( + tenantId, + transactionDTO, + userId + ); + } + /** * Deletes the given cashflow transaction. * @param {number} tenantId @@ -49,6 +82,35 @@ export class CashflowApplication { ); } + /** + * Retrieves specific cashflow transaction. + * @param {number} tenantId + * @param {number} cashflowTransactionId + * @returns + */ + public getTransaction(tenantId: number, cashflowTransactionId: number) { + return this.getCashflowTransactionService.getCashflowTransaction( + tenantId, + cashflowTransactionId + ); + } + + /** + * Retrieves the cashflow accounts. + * @param {number} tenantId + * @param {ICashflowAccountsFilter} filterDTO + * @returns + */ + public getCashflowAccounts( + tenantId: number, + filterDTO: ICashflowAccountsFilter + ) { + return this.getCashflowAccountsService.getCashflowAccounts( + tenantId, + filterDTO + ); + } + /** * Creates a new uncategorized cash transaction. * @param {number} tenantId @@ -105,7 +167,6 @@ export class CashflowApplication { * @param {number} tenantId * @param {number} cashflowTransactionId * @param {CategorizeTransactionAsExpenseDTO} transactionDTO - * @returns */ public categorizeAsExpense( tenantId: number, @@ -122,20 +183,23 @@ export class CashflowApplication { /** * Retrieves the uncategorized cashflow transactions. * @param {number} tenantId - * @returns {} */ - public getUncategorizedTransactions(tenantId: number, accountId: number) { + public getUncategorizedTransactions( + tenantId: number, + accountId: number, + query: IGetUncategorizedTransactionsQuery + ) { return this.getUncategorizedTransactionsService.getTransactions( tenantId, - accountId + accountId, + query ); } /** - * - * @param {number} tenantId - * @param {number} uncategorizedTransactionId - * @returns + * Retrieves specific uncategorized transaction. + * @param {number} tenantId + * @param {number} uncategorizedTransactionId */ public getUncategorizedTransaction( tenantId: number, diff --git a/packages/server/src/services/Cashflow/GetCashflowTransactionsService.ts b/packages/server/src/services/Cashflow/GetCashflowTransactionsService.ts index 42bf7ca9e..64afd2194 100644 --- a/packages/server/src/services/Cashflow/GetCashflowTransactionsService.ts +++ b/packages/server/src/services/Cashflow/GetCashflowTransactionsService.ts @@ -7,7 +7,7 @@ import { ServiceError } from '@/exceptions'; import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; @Service() -export default class GetCashflowTransactionsService { +export class GetCashflowTransactionService { @Inject() private tenancy: HasTenancyService; diff --git a/packages/server/src/services/Cashflow/GetUncategorizedTransactions.ts b/packages/server/src/services/Cashflow/GetUncategorizedTransactions.ts index 41cfa2e85..36606f582 100644 --- a/packages/server/src/services/Cashflow/GetUncategorizedTransactions.ts +++ b/packages/server/src/services/Cashflow/GetUncategorizedTransactions.ts @@ -2,6 +2,7 @@ import { Inject, Service } from 'typedi'; import HasTenancyService from '../Tenancy/TenancyService'; import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; import { UncategorizedTransactionTransformer } from './UncategorizedTransactionTransformer'; +import { IGetUncategorizedTransactionsQuery } from '@/interfaces'; @Service() export class GetUncategorizedTransactions { @@ -16,16 +17,26 @@ export class GetUncategorizedTransactions { * @param {number} tenantId - Tenant id. * @param {number} accountId - Account Id. */ - public async getTransactions(tenantId: number, accountId: number) { + public async getTransactions( + tenantId: number, + accountId: number, + query: IGetUncategorizedTransactionsQuery + ) { const { UncategorizedCashflowTransaction } = this.tenancy.models(tenantId); + // Parsed query with default values. + const _query = { + page: 1, + pageSize: 20, + ...query, + }; const { results, pagination } = await UncategorizedCashflowTransaction.query() .where('accountId', accountId) .where('categorized', false) .withGraphFetched('account') .orderBy('date', 'DESC') - .pagination(0, 1000); + .pagination(_query.page - 1, _query.pageSize); const data = await this.transformer.transform( tenantId,