feat(server): validate the max depth level of the parent account.

This commit is contained in:
a.bouhuolia
2023-02-14 23:47:24 +02:00
parent e3a072e267
commit 8a5fbfc041
6 changed files with 80 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ import DynamicListingService from '@/services/DynamicListing/DynamicListService'
import { DATATYPES_LENGTH } from '@/data/DataTypes';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { AccountsApplication } from '@/services/Accounts/AccountsApplication';
import { MAX_ACCOUNTS_CHART_DEPTH } from 'services/Accounts/constants';
@Service()
export default class AccountsController extends BaseController {
@@ -494,6 +495,22 @@ export default class AccountsController extends BaseController {
}
);
}
if (error.errorType === 'PARENT_ACCOUNT_EXCEEDED_THE_DEPTH_LEVEL') {
return res.boom.badRequest(
'The parent account exceeded the depth level of accounts chart.',
{
errors: [
{
type: 'PARENT_ACCOUNT_EXCEEDED_THE_DEPTH_LEVEL',
code: 1500,
data: {
maxDepth: MAX_ACCOUNTS_CHART_DEPTH,
},
},
],
}
);
}
}
next(error);
}

View File

@@ -3,7 +3,7 @@ import TenancyService from '@/services/Tenancy/TenancyService';
import { ServiceError } from '@/exceptions';
import { IAccountDTO, IAccount, IAccountCreateDTO } from '@/interfaces';
import AccountTypesUtils from '@/lib/AccountTypes';
import { ERRORS } from './constants';
import { ERRORS, MAX_ACCOUNTS_CHART_DEPTH } from './constants';
@Service()
export class CommandAccountValidators {
@@ -154,13 +154,13 @@ export class CommandAccountValidators {
* parent account.
* @param {IAccountCreateDTO} accountDTO
* @param {IAccount} parentAccount
* @param {string} baseCurrency -
* @param {string} baseCurrency -
* @throws {ServiceError(ERRORS.ACCOUNT_CURRENCY_NOT_SAME_PARENT_ACCOUNT)}
*/
public validateCurrentSameParentAccount = (
accountDTO: IAccountCreateDTO,
parentAccount: IAccount,
baseCurrency: string,
baseCurrency: string
) => {
// If the account DTO currency not assigned and the parent account has no base currency.
if (
@@ -208,4 +208,24 @@ export class CommandAccountValidators {
}
return account;
}
/**
* Validates the max depth level of accounts chart.
* @param {numebr} tenantId - Tenant id.
* @param {number} parentAccountId - Parent account id.
*/
public async validateMaxParentAccountDepthLevels(
tenantId: number,
parentAccountId: number
) {
const { accountRepository } = this.tenancy.repositories(tenantId);
const accountsGraph = await accountRepository.getDependencyGraph();
const parentDependantsIds = accountsGraph.dependantsOf(parentAccountId);
if (parentDependantsIds.length >= MAX_ACCOUNTS_CHART_DEPTH) {
throw new ServiceError(ERRORS.PARENT_ACCOUNT_EXCEEDED_THE_DEPTH_LEVEL);
}
}
}

View File

@@ -70,6 +70,11 @@ export class CreateAccount {
parentAccount,
baseCurrency
);
// Validates the max depth level of accounts chart.
await this.validator.validateMaxParentAccountDepthLevels(
tenantId,
accountDTO.parentAccountId
);
}
// Validates the given account type supports the multi-currency.
this.validator.validateAccountTypeSupportCurrency(accountDTO, baseCurrency);

View File

@@ -13,8 +13,12 @@ export const ERRORS = {
CLOSE_ACCOUNT_AND_TO_ACCOUNT_NOT_SAME_TYPE:
'close_account_and_to_account_not_same_type',
ACCOUNTS_NOT_FOUND: 'accounts_not_found',
ACCOUNT_TYPE_NOT_SUPPORTS_MULTI_CURRENCY: 'ACCOUNT_TYPE_NOT_SUPPORTS_MULTI_CURRENCY',
ACCOUNT_CURRENCY_NOT_SAME_PARENT_ACCOUNT: 'ACCOUNT_CURRENCY_NOT_SAME_PARENT_ACCOUNT',
ACCOUNT_TYPE_NOT_SUPPORTS_MULTI_CURRENCY:
'ACCOUNT_TYPE_NOT_SUPPORTS_MULTI_CURRENCY',
ACCOUNT_CURRENCY_NOT_SAME_PARENT_ACCOUNT:
'ACCOUNT_CURRENCY_NOT_SAME_PARENT_ACCOUNT',
PARENT_ACCOUNT_EXCEEDED_THE_DEPTH_LEVEL:
'PARENT_ACCOUNT_EXCEEDED_THE_DEPTH_LEVEL',
};
// Default views columns.
@@ -27,6 +31,8 @@ export const DEFAULT_VIEW_COLUMNS = [
{ key: 'currencyCode', label: 'Currency' },
];
export const MAX_ACCOUNTS_CHART_DEPTH = 5;
// Accounts default views.
export const DEFAULT_VIEWS = [
{
@@ -43,7 +49,12 @@ export const DEFAULT_VIEWS = [
slug: 'liabilities',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'liability' },
{
fieldKey: 'root_type',
index: 1,
comparator: 'equals',
value: 'liability',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
@@ -52,7 +63,12 @@ export const DEFAULT_VIEWS = [
slug: 'equity',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'equity' },
{
fieldKey: 'root_type',
index: 1,
comparator: 'equals',
value: 'equity',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
@@ -61,7 +77,12 @@ export const DEFAULT_VIEWS = [
slug: 'income',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'income' },
{
fieldKey: 'root_type',
index: 1,
comparator: 'equals',
value: 'income',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
@@ -70,7 +91,12 @@ export const DEFAULT_VIEWS = [
slug: 'expenses',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'expense' },
{
fieldKey: 'root_type',
index: 1,
comparator: 'equals',
value: 'expense',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},