mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
feat(server): validate the max depth level of the parent account.
This commit is contained in:
@@ -9,6 +9,7 @@ import DynamicListingService from '@/services/DynamicListing/DynamicListService'
|
|||||||
import { DATATYPES_LENGTH } from '@/data/DataTypes';
|
import { DATATYPES_LENGTH } from '@/data/DataTypes';
|
||||||
import CheckPolicies from '@/api/middleware/CheckPolicies';
|
import CheckPolicies from '@/api/middleware/CheckPolicies';
|
||||||
import { AccountsApplication } from '@/services/Accounts/AccountsApplication';
|
import { AccountsApplication } from '@/services/Accounts/AccountsApplication';
|
||||||
|
import { MAX_ACCOUNTS_CHART_DEPTH } from 'services/Accounts/constants';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class AccountsController extends BaseController {
|
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);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import TenancyService from '@/services/Tenancy/TenancyService';
|
|||||||
import { ServiceError } from '@/exceptions';
|
import { ServiceError } from '@/exceptions';
|
||||||
import { IAccountDTO, IAccount, IAccountCreateDTO } from '@/interfaces';
|
import { IAccountDTO, IAccount, IAccountCreateDTO } from '@/interfaces';
|
||||||
import AccountTypesUtils from '@/lib/AccountTypes';
|
import AccountTypesUtils from '@/lib/AccountTypes';
|
||||||
import { ERRORS } from './constants';
|
import { ERRORS, MAX_ACCOUNTS_CHART_DEPTH } from './constants';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class CommandAccountValidators {
|
export class CommandAccountValidators {
|
||||||
@@ -160,7 +160,7 @@ export class CommandAccountValidators {
|
|||||||
public validateCurrentSameParentAccount = (
|
public validateCurrentSameParentAccount = (
|
||||||
accountDTO: IAccountCreateDTO,
|
accountDTO: IAccountCreateDTO,
|
||||||
parentAccount: IAccount,
|
parentAccount: IAccount,
|
||||||
baseCurrency: string,
|
baseCurrency: string
|
||||||
) => {
|
) => {
|
||||||
// If the account DTO currency not assigned and the parent account has no base currency.
|
// If the account DTO currency not assigned and the parent account has no base currency.
|
||||||
if (
|
if (
|
||||||
@@ -208,4 +208,24 @@ export class CommandAccountValidators {
|
|||||||
}
|
}
|
||||||
return account;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ export class CreateAccount {
|
|||||||
parentAccount,
|
parentAccount,
|
||||||
baseCurrency
|
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.
|
// Validates the given account type supports the multi-currency.
|
||||||
this.validator.validateAccountTypeSupportCurrency(accountDTO, baseCurrency);
|
this.validator.validateAccountTypeSupportCurrency(accountDTO, baseCurrency);
|
||||||
|
|||||||
@@ -13,8 +13,12 @@ export const ERRORS = {
|
|||||||
CLOSE_ACCOUNT_AND_TO_ACCOUNT_NOT_SAME_TYPE:
|
CLOSE_ACCOUNT_AND_TO_ACCOUNT_NOT_SAME_TYPE:
|
||||||
'close_account_and_to_account_not_same_type',
|
'close_account_and_to_account_not_same_type',
|
||||||
ACCOUNTS_NOT_FOUND: 'accounts_not_found',
|
ACCOUNTS_NOT_FOUND: 'accounts_not_found',
|
||||||
ACCOUNT_TYPE_NOT_SUPPORTS_MULTI_CURRENCY: '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_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.
|
// Default views columns.
|
||||||
@@ -27,6 +31,8 @@ export const DEFAULT_VIEW_COLUMNS = [
|
|||||||
{ key: 'currencyCode', label: 'Currency' },
|
{ key: 'currencyCode', label: 'Currency' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const MAX_ACCOUNTS_CHART_DEPTH = 5;
|
||||||
|
|
||||||
// Accounts default views.
|
// Accounts default views.
|
||||||
export const DEFAULT_VIEWS = [
|
export const DEFAULT_VIEWS = [
|
||||||
{
|
{
|
||||||
@@ -43,7 +49,12 @@ export const DEFAULT_VIEWS = [
|
|||||||
slug: 'liabilities',
|
slug: 'liabilities',
|
||||||
rolesLogicExpression: '1',
|
rolesLogicExpression: '1',
|
||||||
roles: [
|
roles: [
|
||||||
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'liability' },
|
{
|
||||||
|
fieldKey: 'root_type',
|
||||||
|
index: 1,
|
||||||
|
comparator: 'equals',
|
||||||
|
value: 'liability',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
columns: DEFAULT_VIEW_COLUMNS,
|
columns: DEFAULT_VIEW_COLUMNS,
|
||||||
},
|
},
|
||||||
@@ -52,7 +63,12 @@ export const DEFAULT_VIEWS = [
|
|||||||
slug: 'equity',
|
slug: 'equity',
|
||||||
rolesLogicExpression: '1',
|
rolesLogicExpression: '1',
|
||||||
roles: [
|
roles: [
|
||||||
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'equity' },
|
{
|
||||||
|
fieldKey: 'root_type',
|
||||||
|
index: 1,
|
||||||
|
comparator: 'equals',
|
||||||
|
value: 'equity',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
columns: DEFAULT_VIEW_COLUMNS,
|
columns: DEFAULT_VIEW_COLUMNS,
|
||||||
},
|
},
|
||||||
@@ -61,7 +77,12 @@ export const DEFAULT_VIEWS = [
|
|||||||
slug: 'income',
|
slug: 'income',
|
||||||
rolesLogicExpression: '1',
|
rolesLogicExpression: '1',
|
||||||
roles: [
|
roles: [
|
||||||
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'income' },
|
{
|
||||||
|
fieldKey: 'root_type',
|
||||||
|
index: 1,
|
||||||
|
comparator: 'equals',
|
||||||
|
value: 'income',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
columns: DEFAULT_VIEW_COLUMNS,
|
columns: DEFAULT_VIEW_COLUMNS,
|
||||||
},
|
},
|
||||||
@@ -70,7 +91,12 @@ export const DEFAULT_VIEWS = [
|
|||||||
slug: 'expenses',
|
slug: 'expenses',
|
||||||
rolesLogicExpression: '1',
|
rolesLogicExpression: '1',
|
||||||
roles: [
|
roles: [
|
||||||
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'expense' },
|
{
|
||||||
|
fieldKey: 'root_type',
|
||||||
|
index: 1,
|
||||||
|
comparator: 'equals',
|
||||||
|
value: 'expense',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
columns: DEFAULT_VIEW_COLUMNS,
|
columns: DEFAULT_VIEW_COLUMNS,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
"yup": "^0.28.1"
|
"yup": "^0.28.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "craco start",
|
"dev": "PORT=4000 craco start",
|
||||||
"build": "craco build",
|
"build": "craco build",
|
||||||
"test": "node scripts/test.js",
|
"test": "node scripts/test.js",
|
||||||
"storybook": "start-storybook -p 6006"
|
"storybook": "start-storybook -p 6006"
|
||||||
|
|||||||
@@ -208,10 +208,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: rgba(0, 82, 204, 0.6) auto 1px;
|
outline: 1px solid rgba(0, 82, 204, 0.7);
|
||||||
outline-offset: 1px;
|
outline-offset: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user