Compare commits
6 Commits
v0.11.0
...
@bigcapita
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04b16a7d2f | ||
|
|
fd27136274 | ||
|
|
951e360405 | ||
|
|
d2242b7744 | ||
|
|
4e9b0ae24f | ||
|
|
e5ffb5661a |
@@ -60,15 +60,6 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"bug"
|
"bug"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "kochie",
|
|
||||||
"name": "Robert Koch",
|
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/10809884?v=4",
|
|
||||||
"profile": "https://me.kochie.io",
|
|
||||||
"contributions": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<td align="center" valign="top" width="14.28%"><a href="https://scheibling.se"><img src="https://avatars.githubusercontent.com/u/24367830?v=4?s=100" width="100px;" alt="Lars Scheibling"/><br /><sub><b>Lars Scheibling</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Ascheibling" title="Bug reports">🐛</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://scheibling.se"><img src="https://avatars.githubusercontent.com/u/24367830?v=4?s=100" width="100px;" alt="Lars Scheibling"/><br /><sub><b>Lars Scheibling</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Ascheibling" title="Bug reports">🐛</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suhaibaffan"><img src="https://avatars.githubusercontent.com/u/18115937?v=4?s=100" width="100px;" alt="Suhaib Affan"/><br /><sub><b>Suhaib Affan</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=suhaibaffan" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suhaibaffan"><img src="https://avatars.githubusercontent.com/u/18115937?v=4?s=100" width="100px;" alt="Suhaib Affan"/><br /><sub><b>Suhaib Affan</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=suhaibaffan" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KalliopiPliogka"><img src="https://avatars.githubusercontent.com/u/81677549?v=4?s=100" width="100px;" alt="Kalliopi Pliogka"/><br /><sub><b>Kalliopi Pliogka</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3AKalliopiPliogka" title="Bug reports">🐛</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KalliopiPliogka"><img src="https://avatars.githubusercontent.com/u/81677549?v=4?s=100" width="100px;" alt="Kalliopi Pliogka"/><br /><sub><b>Kalliopi Pliogka</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3AKalliopiPliogka" title="Bug reports">🐛</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://me.kochie.io"><img src="https://avatars.githubusercontent.com/u/10809884?v=4?s=100" width="100px;" alt="Robert Koch"/><br /><sub><b>Robert Koch</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=kochie" title="Code">💻</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -2,6 +2,5 @@
|
|||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"version": "independent",
|
"version": "independent",
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"useWorkspaces": true,
|
|
||||||
"packages": ["packages/*"]
|
"packages": ["packages/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "bigcapital-monorepo",
|
"name": "bigcapital-monorepo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"bootstrap": "lerna exec pnpm install",
|
||||||
"dev": "lerna run dev",
|
"dev": "lerna run dev",
|
||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"",
|
"dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"",
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
"lerna": "^6.4.1"
|
"lerna": "^6.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.x || 17.x || 18.x"
|
"node": "14.x"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:18.16.0-alpine as build
|
FROM node:14.20-alpine as build
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
@@ -83,25 +83,15 @@ WORKDIR /app
|
|||||||
|
|
||||||
RUN chown node:node /
|
RUN chown node:node /
|
||||||
|
|
||||||
# Install pnpm
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
|
|
||||||
# Copy application dependency manifests to the container image.
|
# Copy application dependency manifests to the container image.
|
||||||
COPY ./package*.json ./
|
COPY ./package*.json ./
|
||||||
COPY ./pnpm-lock.yaml ./pnpm-lock.yaml
|
|
||||||
COPY ./pnpm-workspace.yaml ./pnpm-workspace.yaml
|
|
||||||
COPY ./lerna.json ./lerna.json
|
|
||||||
COPY ./packages/server/package*.json ./packages/server/
|
COPY ./packages/server/package*.json ./packages/server/
|
||||||
|
|
||||||
# Install application dependencies
|
COPY ./lerna.json ./lerna.json
|
||||||
RUN apk update
|
|
||||||
RUN apk add python3 build-base chromium
|
|
||||||
|
|
||||||
# Set PYHTON env
|
# Install app dependencies for production.
|
||||||
ENV PYTHON=/usr/bin/python3
|
RUN npm install
|
||||||
|
RUN npm run bootstrap
|
||||||
# Install packages dependencies for production.
|
|
||||||
RUN pnpm install
|
|
||||||
|
|
||||||
COPY --chown=node:node ./packages/server ./packages/server
|
COPY --chown=node:node ./packages/server ./packages/server
|
||||||
|
|
||||||
|
|||||||
13698
packages/server/package-lock.json
generated
13698
packages/server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bigcapital/server",
|
"name": "@bigcapital/server",
|
||||||
"version": "0.10.2",
|
"version": "0.10.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/server.ts",
|
"main": "src/server.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"crypto-random-string": "^3.2.0",
|
"crypto-random-string": "^3.2.0",
|
||||||
"csurf": "^1.10.0",
|
"csurf": "^1.10.0",
|
||||||
"deep-map": "^2.0.0",
|
"deep-map": "^2.0.0",
|
||||||
"deepdash": "^5.3.9",
|
"deepdash": "^5.3.7",
|
||||||
"dotenv": "^8.1.0",
|
"dotenv": "^8.1.0",
|
||||||
"errorhandler": "^1.5.1",
|
"errorhandler": "^1.5.1",
|
||||||
"es6-weak-map": "^2.0.3",
|
"es6-weak-map": "^2.0.3",
|
||||||
@@ -95,7 +95,6 @@
|
|||||||
"rate-limiter-flexible": "^2.1.14",
|
"rate-limiter-flexible": "^2.1.14",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rtl-detect": "^1.0.4",
|
"rtl-detect": "^1.0.4",
|
||||||
"source-map-loader": "^4.0.1",
|
|
||||||
"ts-transformer-keys": "^0.4.2",
|
"ts-transformer-keys": "^0.4.2",
|
||||||
"tsyringe": "^4.3.0",
|
"tsyringe": "^4.3.0",
|
||||||
"typedi": "^0.8.0",
|
"typedi": "^0.8.0",
|
||||||
|
|||||||
@@ -587,7 +587,6 @@
|
|||||||
"balance_sheet.long_term_liabilities": "Long-Term Liabilities",
|
"balance_sheet.long_term_liabilities": "Long-Term Liabilities",
|
||||||
"balance_sheet.non_current_liabilities": "Non-Current Liabilities",
|
"balance_sheet.non_current_liabilities": "Non-Current Liabilities",
|
||||||
"balance_sheet.equity": "Equity",
|
"balance_sheet.equity": "Equity",
|
||||||
"balance_sheet.net_income": "Net Income",
|
|
||||||
|
|
||||||
"balance_sheet.account_name": "Account name",
|
"balance_sheet.account_name": "Account name",
|
||||||
"balance_sheet.total": "Total",
|
"balance_sheet.total": "Total",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
|
|||||||
/**
|
/**
|
||||||
* Router constructor.
|
* Router constructor.
|
||||||
*/
|
*/
|
||||||
public router() {
|
router() {
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
@@ -36,7 +36,7 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
|
|||||||
* Validation schema.
|
* Validation schema.
|
||||||
* @return {ValidationChain[]}
|
* @return {ValidationChain[]}
|
||||||
*/
|
*/
|
||||||
private get trialBalanceSheetValidationSchema(): ValidationChain[] {
|
get trialBalanceSheetValidationSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
...this.sheetNumberFormatValidationSchema,
|
...this.sheetNumberFormatValidationSchema,
|
||||||
query('basis').optional(),
|
query('basis').optional(),
|
||||||
@@ -59,37 +59,28 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
|
|||||||
/**
|
/**
|
||||||
* Retrieve the trial balance sheet.
|
* Retrieve the trial balance sheet.
|
||||||
*/
|
*/
|
||||||
private async trialBalanceSheet(
|
public async trialBalanceSheet(
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
) {
|
) {
|
||||||
const { tenantId } = req;
|
const { tenantId, settings } = req;
|
||||||
let filter = this.matchedQueryData(req);
|
let filter = this.matchedQueryData(req);
|
||||||
|
|
||||||
filter = {
|
filter = {
|
||||||
...filter,
|
...filter,
|
||||||
accountsIds: castArray(filter.accountsIds),
|
accountsIds: castArray(filter.accountsIds),
|
||||||
};
|
};
|
||||||
try {
|
|
||||||
const accept = this.accepts(req);
|
|
||||||
const acceptType = accept.types(['json', 'application/json+table']);
|
|
||||||
|
|
||||||
if (acceptType === 'application/json+table') {
|
try {
|
||||||
const { table, meta, query } =
|
const { data, query, meta } =
|
||||||
await this.trialBalanceSheetService.trialBalanceSheetTable(
|
await this.trialBalanceSheetService.trialBalanceSheet(tenantId, filter);
|
||||||
tenantId,
|
|
||||||
filter
|
return res.status(200).send({
|
||||||
);
|
data: this.transfromToResponse(data),
|
||||||
return res.status(200).send({ table, meta, query });
|
query: this.transfromToResponse(query),
|
||||||
} else {
|
meta: this.transfromToResponse(meta),
|
||||||
const { data, query, meta } =
|
});
|
||||||
await this.trialBalanceSheetService.trialBalanceSheet(
|
|
||||||
tenantId,
|
|
||||||
filter
|
|
||||||
);
|
|
||||||
return res.status(200).send({ data, query, meta });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,11 +149,6 @@ export default class ItemsController extends BaseController {
|
|||||||
.trim()
|
.trim()
|
||||||
.escape()
|
.escape()
|
||||||
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
check('sell_tax_rate_id').optional({ nullable: true }).isInt().toInt(),
|
|
||||||
check('purchase_tax_rate_id')
|
|
||||||
.optional({ nullable: true })
|
|
||||||
.isInt()
|
|
||||||
.toInt(),
|
|
||||||
check('category_id')
|
check('category_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
@@ -513,28 +508,6 @@ export default class ItemsController extends BaseController {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (error.errorType === 'PURCHASE_TAX_RATE_NOT_FOUND') {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [
|
|
||||||
{
|
|
||||||
type: 'PURCHASE_TAX_RATE_NOT_FOUND',
|
|
||||||
message: 'Purchase tax rate has not found.',
|
|
||||||
code: 410,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error.errorType === 'SELL_TAX_RATE_NOT_FOUND') {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [
|
|
||||||
{
|
|
||||||
type: 'SELL_TAX_RATE_NOT_FOUND',
|
|
||||||
message: 'Sell tax rate is not found.',
|
|
||||||
code: 420,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ export default class OrganizationController extends BaseController {
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/build',
|
'/build',
|
||||||
this.buildOrganizationValidationSchema,
|
this.organizationValidationSchema,
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
asyncMiddleware(this.build.bind(this)),
|
asyncMiddleware(this.build.bind(this)),
|
||||||
this.handleServiceErrors.bind(this)
|
this.handleServiceErrors.bind(this)
|
||||||
);
|
);
|
||||||
router.put(
|
router.put(
|
||||||
'/',
|
'/',
|
||||||
this.updateOrganizationValidationSchema,
|
this.organizationValidationSchema,
|
||||||
this.validationResult,
|
this.validationResult,
|
||||||
this.asyncMiddleware(this.updateOrganization.bind(this)),
|
this.asyncMiddleware(this.updateOrganization.bind(this)),
|
||||||
this.handleServiceErrors.bind(this)
|
this.handleServiceErrors.bind(this)
|
||||||
@@ -55,7 +55,7 @@ export default class OrganizationController extends BaseController {
|
|||||||
* Organization setup schema.
|
* Organization setup schema.
|
||||||
* @return {ValidationChain[]}
|
* @return {ValidationChain[]}
|
||||||
*/
|
*/
|
||||||
private get commonOrganizationValidationSchema(): ValidationChain[] {
|
private get organizationValidationSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('name').exists().trim(),
|
check('name').exists().trim(),
|
||||||
check('industry').optional({ nullable: true }).isString().trim().escape(),
|
check('industry').optional({ nullable: true }).isString().trim().escape(),
|
||||||
@@ -68,29 +68,6 @@ export default class OrganizationController extends BaseController {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build organization validation schema.
|
|
||||||
* @returns {ValidationChain[]}
|
|
||||||
*/
|
|
||||||
private get buildOrganizationValidationSchema(): ValidationChain[] {
|
|
||||||
return [...this.commonOrganizationValidationSchema];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update organization validation schema.
|
|
||||||
* @returns {ValidationChain[]}
|
|
||||||
*/
|
|
||||||
private get updateOrganizationValidationSchema(): ValidationChain[] {
|
|
||||||
return [
|
|
||||||
...this.commonOrganizationValidationSchema,
|
|
||||||
check('tax_number')
|
|
||||||
.optional({ nullable: true })
|
|
||||||
.isString()
|
|
||||||
.trim()
|
|
||||||
.escape(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds tenant database and migrate database schema.
|
* Builds tenant database and migrate database schema.
|
||||||
* @param {Request} req - Express request.
|
* @param {Request} req - Express request.
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ export default class BillsController extends BaseController {
|
|||||||
check('note').optional().trim().escape(),
|
check('note').optional().trim().escape(),
|
||||||
check('open').default(false).isBoolean().toBoolean(),
|
check('open').default(false).isBoolean().toBoolean(),
|
||||||
|
|
||||||
check('is_inclusive_tax').default(false).isBoolean().toBoolean(),
|
|
||||||
|
|
||||||
check('entries').isArray({ min: 1 }),
|
check('entries').isArray({ min: 1 }),
|
||||||
|
|
||||||
check('entries.*.index').exists().isNumeric().toInt(),
|
check('entries.*.index').exists().isNumeric().toInt(),
|
||||||
@@ -139,15 +137,6 @@ export default class BillsController extends BaseController {
|
|||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isNumeric()
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('entries.*.tax_code')
|
|
||||||
.optional({ nullable: true })
|
|
||||||
.trim()
|
|
||||||
.escape()
|
|
||||||
.isString(),
|
|
||||||
check('entries.*.tax_rate_id')
|
|
||||||
.optional({ nullable: true })
|
|
||||||
.isNumeric()
|
|
||||||
.toInt(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,16 +542,6 @@ export default class BillsController extends BaseController {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (error.errorType === 'ITEM_ENTRY_TAX_RATE_CODE_NOT_FOUND') {
|
|
||||||
return res.boom.badRequest(null, {
|
|
||||||
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_CODE_NOT_FOUND', code: 1800 }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error.errorType === 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND') {
|
|
||||||
return res.boom.badRequest(null, {
|
|
||||||
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND', code: 1900 }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
exports.up = (knex) => {
|
|
||||||
return knex.schema.table('bills', (table) => {
|
|
||||||
table.boolean('is_inclusive_tax').defaultTo(false);
|
|
||||||
table.decimal('tax_amount_withheld');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = (knex) => {
|
|
||||||
return knex.schema.table('bills', () => {});
|
|
||||||
};
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
exports.up = (knex) => {
|
|
||||||
return knex.schema.table('items', (table) => {
|
|
||||||
table
|
|
||||||
.integer('sell_tax_rate_id')
|
|
||||||
.unsigned()
|
|
||||||
.references('id')
|
|
||||||
.inTable('tax_rates');
|
|
||||||
table
|
|
||||||
.integer('purchase_tax_rate_id')
|
|
||||||
.unsigned()
|
|
||||||
.references('id')
|
|
||||||
.inTable('tax_rates');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = (knex) => {
|
|
||||||
return knex.schema.dropTableIfExists('tax_rates');
|
|
||||||
};
|
|
||||||
@@ -9,7 +9,6 @@ export enum BALANCE_SHEET_SCHEMA_NODE_TYPE {
|
|||||||
AGGREGATE = 'AGGREGATE',
|
AGGREGATE = 'AGGREGATE',
|
||||||
ACCOUNTS = 'ACCOUNTS',
|
ACCOUNTS = 'ACCOUNTS',
|
||||||
ACCOUNT = 'ACCOUNT',
|
ACCOUNT = 'ACCOUNT',
|
||||||
NET_INCOME = 'NET_INCOME',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BALANCE_SHEET_NODE_TYPE {
|
export enum BALANCE_SHEET_NODE_TYPE {
|
||||||
@@ -34,7 +33,6 @@ export enum BALANCE_SHEET_SCHEMA_NODE_ID {
|
|||||||
LOGN_TERM_LIABILITY = 'LOGN_TERM_LIABILITY',
|
LOGN_TERM_LIABILITY = 'LOGN_TERM_LIABILITY',
|
||||||
NON_CURRENT_LIABILITY = 'NON_CURRENT_LIABILITY',
|
NON_CURRENT_LIABILITY = 'NON_CURRENT_LIABILITY',
|
||||||
EQUITY = 'EQUITY',
|
EQUITY = 'EQUITY',
|
||||||
NET_INCOME = 'NET_INCOME',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balance sheet query.
|
// Balance sheet query.
|
||||||
@@ -89,6 +87,7 @@ export interface IBalanceSheetDOO {
|
|||||||
meta: IBalanceSheetMeta;
|
meta: IBalanceSheetMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface IBalanceSheetCommonNode {
|
export interface IBalanceSheetCommonNode {
|
||||||
total: IBalanceSheetTotal;
|
total: IBalanceSheetTotal;
|
||||||
horizontalTotals?: IBalanceSheetTotal[];
|
horizontalTotals?: IBalanceSheetTotal[];
|
||||||
@@ -109,7 +108,7 @@ export interface IBalanceSheetAggregateNode extends IBalanceSheetCommonNode {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE;
|
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE;
|
||||||
children?: IBalanceSheetDataNode[];
|
children?: (IBalanceSheetAggregateNode | IBalanceSheetAccountNode)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBalanceSheetTotal {
|
export interface IBalanceSheetTotal {
|
||||||
@@ -119,13 +118,6 @@ export interface IBalanceSheetTotal {
|
|||||||
date?: string | Date;
|
date?: string | Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBalanceSheetAccountsNode extends IBalanceSheetCommonNode {
|
|
||||||
id: number | string;
|
|
||||||
name: string;
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS;
|
|
||||||
children: IBalanceSheetAccountNode[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
|
export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
|
||||||
id: number;
|
id: number;
|
||||||
index: number;
|
index: number;
|
||||||
@@ -136,17 +128,7 @@ export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
|
|||||||
children?: IBalanceSheetAccountNode[];
|
children?: IBalanceSheetAccountNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBalanceSheetNetIncomeNode extends IBalanceSheetCommonNode {
|
export type IBalanceSheetDataNode = IBalanceSheetAggregateNode;
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IBalanceSheetDataNode =
|
|
||||||
| IBalanceSheetAggregateNode
|
|
||||||
| IBalanceSheetAccountNode
|
|
||||||
| IBalanceSheetAccountsNode
|
|
||||||
| IBalanceSheetNetIncomeNode;
|
|
||||||
|
|
||||||
export interface IBalanceSheetPercentageAmount {
|
export interface IBalanceSheetPercentageAmount {
|
||||||
amount: number;
|
amount: number;
|
||||||
@@ -168,16 +150,9 @@ export interface IBalanceSheetSchemaAccountNode {
|
|||||||
accountsTypes: string[];
|
accountsTypes: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBalanceSheetSchemaNetIncomeNode {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
type: BALANCE_SHEET_SCHEMA_NODE_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IBalanceSheetSchemaNode =
|
export type IBalanceSheetSchemaNode =
|
||||||
| IBalanceSheetSchemaAccountNode
|
| IBalanceSheetSchemaAccountNode
|
||||||
| IBalanceSheetSchemaAggregateNode
|
| IBalanceSheetSchemaAggregateNode;
|
||||||
| IBalanceSheetSchemaNetIncomeNode;
|
|
||||||
|
|
||||||
export interface IBalanceSheetDatePeriods {
|
export interface IBalanceSheetDatePeriods {
|
||||||
assocAccountNodeDatePeriods(node): any;
|
assocAccountNodeDatePeriods(node): any;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Knex } from 'knex';
|
|||||||
import { IDynamicListFilterDTO } from './DynamicFilter';
|
import { IDynamicListFilterDTO } from './DynamicFilter';
|
||||||
import { IItemEntry, IItemEntryDTO } from './ItemEntry';
|
import { IItemEntry, IItemEntryDTO } from './ItemEntry';
|
||||||
import { IBillLandedCost } from './LandedCost';
|
import { IBillLandedCost } from './LandedCost';
|
||||||
|
|
||||||
export interface IBillDTO {
|
export interface IBillDTO {
|
||||||
vendorId: number;
|
vendorId: number;
|
||||||
billNumber: string;
|
billNumber: string;
|
||||||
@@ -16,10 +15,10 @@ export interface IBillDTO {
|
|||||||
exchangeRate?: number;
|
exchangeRate?: number;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
entries: IItemEntryDTO[];
|
entries: IItemEntryDTO[];
|
||||||
|
|
||||||
branchId?: number;
|
branchId?: number;
|
||||||
warehouseId?: number;
|
warehouseId?: number;
|
||||||
projectId?: number;
|
projectId?: number;
|
||||||
isInclusiveTax?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBillEditDTO {
|
export interface IBillEditDTO {
|
||||||
@@ -81,15 +80,6 @@ export interface IBill {
|
|||||||
|
|
||||||
localAmount?: number;
|
localAmount?: number;
|
||||||
locatedLandedCosts?: IBillLandedCost[];
|
locatedLandedCosts?: IBillLandedCost[];
|
||||||
|
|
||||||
amountLocal: number;
|
|
||||||
subtotal: number;
|
|
||||||
subtotalLocal: number;
|
|
||||||
subtotalExcludingTax: number;
|
|
||||||
taxAmountWithheld: number;
|
|
||||||
taxAmountWithheldLocal: number;
|
|
||||||
total: number;
|
|
||||||
totalLocal: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBillsFilter extends IDynamicListFilterDTO {
|
export interface IBillsFilter extends IDynamicListFilterDTO {
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ export interface IItem {
|
|||||||
sellDescription: string;
|
sellDescription: string;
|
||||||
purchaseDescription: string;
|
purchaseDescription: string;
|
||||||
|
|
||||||
sellTaxRateId: number;
|
|
||||||
purchaseTaxRateId: number;
|
|
||||||
|
|
||||||
quantityOnHand: number;
|
quantityOnHand: number;
|
||||||
|
|
||||||
note: string;
|
note: string;
|
||||||
@@ -57,9 +54,6 @@ export interface IItemDTO {
|
|||||||
sellDescription: string;
|
sellDescription: string;
|
||||||
purchaseDescription: string;
|
purchaseDescription: string;
|
||||||
|
|
||||||
sellTaxRateId: number;
|
|
||||||
purchaseTaxRateId: number;
|
|
||||||
|
|
||||||
quantityOnHand: number;
|
quantityOnHand: number;
|
||||||
|
|
||||||
note: string;
|
note: string;
|
||||||
|
|||||||
@@ -7,25 +7,18 @@ export interface ILedger {
|
|||||||
filter(cb: (entry: ILedgerEntry) => boolean): ILedger;
|
filter(cb: (entry: ILedgerEntry) => boolean): ILedger;
|
||||||
|
|
||||||
whereAccountId(accountId: number): ILedger;
|
whereAccountId(accountId: number): ILedger;
|
||||||
whereAccountsIds(accountsIds: number[]): ILedger;
|
|
||||||
whereContactId(contactId: number): ILedger;
|
whereContactId(contactId: number): ILedger;
|
||||||
whereFromDate(fromDate: Date | string): ILedger;
|
whereFromDate(fromDate: Date | string): ILedger;
|
||||||
whereToDate(toDate: Date | string): ILedger;
|
whereToDate(toDate: Date | string): ILedger;
|
||||||
whereCurrencyCode(currencyCode: string): ILedger;
|
whereCurrencyCode(currencyCode: string): ILedger;
|
||||||
whereBranch(branchId: number): ILedger;
|
whereBranch(branchId: number): ILedger;
|
||||||
whereItem(itemId: number): ILedger;
|
whereItem(itemId: number): ILedger;
|
||||||
whereProject(projectId: number): ILedger;
|
|
||||||
|
|
||||||
getClosingBalance(): number;
|
getClosingBalance(): number;
|
||||||
getForeignClosingBalance(): number;
|
getForeignClosingBalance(): number;
|
||||||
getClosingDebit(): number;
|
|
||||||
getClosingCredit(): number;
|
|
||||||
|
|
||||||
getContactsIds(): number[];
|
getContactsIds(): number[];
|
||||||
getAccountsIds(): number[];
|
getAccountsIds(): number[];
|
||||||
|
|
||||||
reverse(): ILedger;
|
|
||||||
isEmpty(): boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILedgerEntry {
|
export interface ILedgerEntry {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export interface IOrganizationUpdateDTO {
|
|||||||
timezone: string;
|
timezone: string;
|
||||||
fiscalYear: string;
|
fiscalYear: string;
|
||||||
industry: string;
|
industry: string;
|
||||||
taxNumber: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IOrganizationBuildEventPayload {
|
export interface IOrganizationBuildEventPayload {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export interface ITaxRateCreatedPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ITaxRateEditingPayload {
|
export interface ITaxRateEditingPayload {
|
||||||
oldTaxRate: ITaxRate;
|
|
||||||
editTaxRateDTO: IEditTaxRateDTO;
|
editTaxRateDTO: IEditTaxRateDTO;
|
||||||
tenantId: number;
|
tenantId: number;
|
||||||
trx: Knex.Transaction;
|
trx: Knex.Transaction;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export interface ITrialBalanceAccount extends ITrialBalanceTotal {
|
|||||||
id: number;
|
id: number;
|
||||||
parentAccountId: number;
|
parentAccountId: number;
|
||||||
name: string;
|
name: string;
|
||||||
formattedName: string;
|
|
||||||
code: string;
|
code: string;
|
||||||
accountNormal: string;
|
accountNormal: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,6 @@ import { ProjectBillableBillSubscriber } from '@/services/Projects/Projects/Proj
|
|||||||
import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber';
|
import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber';
|
||||||
import { SaleInvoiceTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/SaleInvoiceTaxRateValidateSubscriber';
|
import { SaleInvoiceTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/SaleInvoiceTaxRateValidateSubscriber';
|
||||||
import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteInvoiceTaxTransactionsSubscriber';
|
import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteInvoiceTaxTransactionsSubscriber';
|
||||||
import { BillTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/BillTaxRateValidateSubscriber';
|
|
||||||
import { WriteBillTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteBillTaxTransactionsSubscriber';
|
|
||||||
import { SyncItemTaxRateOnEditTaxSubscriber } from '@/services/TaxRates/SyncItemTaxRateOnEditTaxSubscriber';
|
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return new EventPublisher();
|
return new EventPublisher();
|
||||||
@@ -191,14 +188,8 @@ export const susbcribers = () => {
|
|||||||
ProjectBillableExpensesSubscriber,
|
ProjectBillableExpensesSubscriber,
|
||||||
ProjectBillableBillSubscriber,
|
ProjectBillableBillSubscriber,
|
||||||
|
|
||||||
// Tax Rates - Sale Invoice
|
// Tax Rates
|
||||||
SaleInvoiceTaxRateValidateSubscriber,
|
SaleInvoiceTaxRateValidateSubscriber,
|
||||||
WriteInvoiceTaxTransactionsSubscriber,
|
WriteInvoiceTaxTransactionsSubscriber,
|
||||||
|
|
||||||
// Tax Rates - Bills
|
|
||||||
BillTaxRateValidateSubscriber,
|
|
||||||
WriteBillTaxTransactionsSubscriber,
|
|
||||||
|
|
||||||
SyncItemTaxRateOnEditTaxSubscriber
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -587,7 +587,6 @@
|
|||||||
"balance_sheet.long_term_liabilities": "Long-Term Liabilities",
|
"balance_sheet.long_term_liabilities": "Long-Term Liabilities",
|
||||||
"balance_sheet.non_current_liabilities": "Non-Current Liabilities",
|
"balance_sheet.non_current_liabilities": "Non-Current Liabilities",
|
||||||
"balance_sheet.equity": "Equity",
|
"balance_sheet.equity": "Equity",
|
||||||
"balance_sheet.net_income": "Net Income",
|
|
||||||
|
|
||||||
"balance_sheet.account_name": "Account name",
|
"balance_sheet.account_name": "Account name",
|
||||||
"balance_sheet.total": "Total",
|
"balance_sheet.total": "Total",
|
||||||
|
|||||||
@@ -13,109 +13,6 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
CustomViewBaseModel,
|
CustomViewBaseModel,
|
||||||
ModelSearchable,
|
ModelSearchable,
|
||||||
]) {
|
]) {
|
||||||
public amount: number;
|
|
||||||
public paymentAmount: number;
|
|
||||||
public landedCostAmount: number;
|
|
||||||
public allocatedCostAmount: number;
|
|
||||||
public isInclusiveTax: boolean;
|
|
||||||
public taxAmountWithheld: number;
|
|
||||||
public exchangeRate: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamps columns.
|
|
||||||
*/
|
|
||||||
get timestamps() {
|
|
||||||
return ['createdAt', 'updatedAt'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual attributes.
|
|
||||||
*/
|
|
||||||
static get virtualAttributes() {
|
|
||||||
return [
|
|
||||||
'balance',
|
|
||||||
'dueAmount',
|
|
||||||
'isOpen',
|
|
||||||
'isPartiallyPaid',
|
|
||||||
'isFullyPaid',
|
|
||||||
'isPaid',
|
|
||||||
'remainingDays',
|
|
||||||
'overdueDays',
|
|
||||||
'isOverdue',
|
|
||||||
'unallocatedCostAmount',
|
|
||||||
'localAmount',
|
|
||||||
'localAllocatedCostAmount',
|
|
||||||
'billableAmount',
|
|
||||||
'amountLocal',
|
|
||||||
'subtotal',
|
|
||||||
'subtotalLocal',
|
|
||||||
'subtotalExludingTax',
|
|
||||||
'taxAmountWithheldLocal',
|
|
||||||
'total',
|
|
||||||
'totalLocal',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoice amount in base currency.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get amountLocal() {
|
|
||||||
return this.amount * this.exchangeRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtotal. (Tax inclusive) if the tax inclusive is enabled.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get subtotal() {
|
|
||||||
return this.amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtotal in base currency. (Tax inclusive) if the tax inclusive is enabled.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get subtotalLocal() {
|
|
||||||
return this.amountLocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sale invoice amount excluding tax.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get subtotalExcludingTax() {
|
|
||||||
return this.isInclusiveTax
|
|
||||||
? this.subtotal - this.taxAmountWithheld
|
|
||||||
: this.subtotal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tax amount withheld in base currency.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get taxAmountWithheldLocal() {
|
|
||||||
return this.taxAmountWithheld * this.exchangeRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoice total. (Tax included)
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get total() {
|
|
||||||
return this.isInclusiveTax
|
|
||||||
? this.subtotal
|
|
||||||
: this.subtotal + this.taxAmountWithheld;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoice total in local currency. (Tax included)
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
get totalLocal() {
|
|
||||||
return this.total * this.exchangeRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
*/
|
*/
|
||||||
@@ -261,13 +158,40 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamps columns.
|
||||||
|
*/
|
||||||
|
get timestamps() {
|
||||||
|
return ['createdAt', 'updatedAt'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual attributes.
|
||||||
|
*/
|
||||||
|
static get virtualAttributes() {
|
||||||
|
return [
|
||||||
|
'balance',
|
||||||
|
'dueAmount',
|
||||||
|
'isOpen',
|
||||||
|
'isPartiallyPaid',
|
||||||
|
'isFullyPaid',
|
||||||
|
'isPaid',
|
||||||
|
'remainingDays',
|
||||||
|
'overdueDays',
|
||||||
|
'isOverdue',
|
||||||
|
'unallocatedCostAmount',
|
||||||
|
'localAmount',
|
||||||
|
'localAllocatedCostAmount',
|
||||||
|
'billableAmount',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoice amount in organization base currency.
|
* Invoice amount in organization base currency.
|
||||||
* @deprecated
|
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
get localAmount() {
|
get localAmount() {
|
||||||
return this.amountLocal;
|
return this.amount * this.exchangeRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,7 +231,7 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
get dueAmount() {
|
get dueAmount() {
|
||||||
return Math.max(this.total - this.balance, 0);
|
return Math.max(this.amount - this.balance, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,7 +247,7 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
get isPartiallyPaid() {
|
get isPartiallyPaid() {
|
||||||
return this.dueAmount !== this.total && this.dueAmount > 0;
|
return this.dueAmount !== this.amount && this.dueAmount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -384,7 +308,7 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
* Retrieves the calculated amount which have not been invoiced.
|
* Retrieves the calculated amount which have not been invoiced.
|
||||||
*/
|
*/
|
||||||
get billableAmount() {
|
get billableAmount() {
|
||||||
return Math.max(this.total - this.invoicedAmount, 0);
|
return Math.max(this.amount - this.invoicedAmount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,7 +326,6 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
const ItemEntry = require('models/ItemEntry');
|
const ItemEntry = require('models/ItemEntry');
|
||||||
const BillLandedCost = require('models/BillLandedCost');
|
const BillLandedCost = require('models/BillLandedCost');
|
||||||
const Branch = require('models/Branch');
|
const Branch = require('models/Branch');
|
||||||
const TaxRateTransaction = require('models/TaxRateTransaction');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vendor: {
|
vendor: {
|
||||||
@@ -450,21 +373,6 @@ export default class Bill extends mixin(TenantModel, [
|
|||||||
to: 'branches.id',
|
to: 'branches.id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Bill may has associated tax rate transactions.
|
|
||||||
*/
|
|
||||||
taxes: {
|
|
||||||
relation: Model.HasManyRelation,
|
|
||||||
modelClass: TaxRateTransaction.default,
|
|
||||||
join: {
|
|
||||||
from: 'bills.id',
|
|
||||||
to: 'tax_rate_transactions.referenceId',
|
|
||||||
},
|
|
||||||
filter(builder) {
|
|
||||||
builder.where('reference_type', 'Bill');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ export default class Item extends mixin(TenantModel, [
|
|||||||
const ItemEntry = require('models/ItemEntry');
|
const ItemEntry = require('models/ItemEntry');
|
||||||
const WarehouseTransferEntry = require('models/WarehouseTransferEntry');
|
const WarehouseTransferEntry = require('models/WarehouseTransferEntry');
|
||||||
const InventoryAdjustmentEntry = require('models/InventoryAdjustmentEntry');
|
const InventoryAdjustmentEntry = require('models/InventoryAdjustmentEntry');
|
||||||
const TaxRate = require('models/TaxRate');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
@@ -179,35 +178,11 @@ export default class Item extends mixin(TenantModel, [
|
|||||||
to: 'media.id',
|
to: 'media.id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Item may has sell tax rate.
|
|
||||||
*/
|
|
||||||
sellTaxRate: {
|
|
||||||
relation: Model.BelongsToOneRelation,
|
|
||||||
modelClass: TaxRate.default,
|
|
||||||
join: {
|
|
||||||
from: 'items.sellTaxRateId',
|
|
||||||
to: 'tax_rates.id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item may has purchase tax rate.
|
|
||||||
*/
|
|
||||||
purchaseTaxRate: {
|
|
||||||
relation: Model.BelongsToOneRelation,
|
|
||||||
modelClass: TaxRate.default,
|
|
||||||
join: {
|
|
||||||
from: 'items.purchaseTaxRateId',
|
|
||||||
to: 'tax_rates.id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static get secureDeleteRelations() {
|
static get secureDeleteRelations() {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -99,13 +99,6 @@ export default class ItemEntry extends TenantModel {
|
|||||||
: getExlusiveTaxAmount(this.amount, this.taxRate);
|
: getExlusiveTaxAmount(this.amount, this.taxRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static calcAmount(itemEntry) {
|
|
||||||
const { discount, quantity, rate } = itemEntry;
|
|
||||||
const total = quantity * rate;
|
|
||||||
|
|
||||||
return discount ? total - total * discount * 0.01 : total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item entry relations.
|
* Item entry relations.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { defaultTo, sumBy, uniqBy } from 'lodash';
|
import { defaultTo, uniqBy } from 'lodash';
|
||||||
import { IAccountTransaction, ILedger, ILedgerEntry } from '@/interfaces';
|
import { IAccountTransaction, ILedger, ILedgerEntry } from '@/interfaces';
|
||||||
|
|
||||||
export default class Ledger implements ILedger {
|
export default class Ledger implements ILedger {
|
||||||
@@ -49,15 +49,6 @@ export default class Ledger implements ILedger {
|
|||||||
return this.filter((entry) => entry.accountId === accountId);
|
return this.filter((entry) => entry.accountId === accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters entries by the given accounts ids then returns a new ledger.
|
|
||||||
* @param {number[]} accountIds
|
|
||||||
* @returns {ILedger}
|
|
||||||
*/
|
|
||||||
public whereAccountsIds(accountIds: number[]): ILedger {
|
|
||||||
return this.filter((entry) => accountIds.indexOf(entry.accountId) !== -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters entries that before or same the given date and returns a new ledger.
|
* Filters entries that before or same the given date and returns a new ledger.
|
||||||
* @param {Date|string} fromDate
|
* @param {Date|string} fromDate
|
||||||
@@ -139,22 +130,6 @@ export default class Ledger implements ILedger {
|
|||||||
return closingBalance;
|
return closingBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing credit of the entries.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
public getClosingCredit(): number {
|
|
||||||
return sumBy(this.entries, 'credit');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing debit of the entries.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
public getClosingDebit(): number {
|
|
||||||
return sumBy(this.entries, 'debit');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the closing balance of the entries.
|
* Retrieve the closing balance of the entries.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
import { defaultTo, isEmpty, sumBy } from 'lodash';
|
||||||
import FinancialSheet from '../FinancialSheet';
|
import FinancialSheet from '../FinancialSheet';
|
||||||
import {
|
import {
|
||||||
|
IBalanceSheetAggregateNode,
|
||||||
|
IBalanceSheetAccountNode,
|
||||||
|
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
||||||
IBalanceSheetQuery,
|
IBalanceSheetQuery,
|
||||||
INumberFormatQuery,
|
INumberFormatQuery,
|
||||||
|
IAccount,
|
||||||
IBalanceSheetSchemaNode,
|
IBalanceSheetSchemaNode,
|
||||||
|
IBalanceSheetSchemaAggregateNode,
|
||||||
IBalanceSheetDataNode,
|
IBalanceSheetDataNode,
|
||||||
|
IBalanceSheetSchemaAccountNode,
|
||||||
|
IBalanceSheetCommonNode,
|
||||||
} from '../../../interfaces';
|
} from '../../../interfaces';
|
||||||
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
||||||
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
|
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
|
||||||
@@ -16,14 +24,8 @@ import { FinancialSheetStructure } from '../FinancialSheetStructure';
|
|||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
import BalanceSheetRepository from './BalanceSheetRepository';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { BalanceSheetFiltering } from './BalanceSheetFiltering';
|
import { BalanceSheetFiltering } from './BalanceSheetFiltering';
|
||||||
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
|
|
||||||
import { BalanceSheetAggregators } from './BalanceSheetAggregators';
|
|
||||||
import { BalanceSheetAccounts } from './BalanceSheetAccounts';
|
|
||||||
|
|
||||||
export default class BalanceSheet extends R.compose(
|
export default class BalanceSheet extends R.compose(
|
||||||
BalanceSheetAggregators,
|
|
||||||
BalanceSheetAccounts,
|
|
||||||
BalanceSheetNetIncome,
|
|
||||||
BalanceSheetFiltering,
|
BalanceSheetFiltering,
|
||||||
BalanceSheetDatePeriods,
|
BalanceSheetDatePeriods,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
@@ -51,9 +53,6 @@ export default class BalanceSheet extends R.compose(
|
|||||||
*/
|
*/
|
||||||
readonly baseCurrency: string;
|
readonly baseCurrency: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Localization.
|
|
||||||
*/
|
|
||||||
readonly i18n: any;
|
readonly i18n: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,18 +77,216 @@ export default class BalanceSheet extends R.compose(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses report schema nodes.
|
* Retrieve the accounts node of accounts types.
|
||||||
* @param {IBalanceSheetSchemaNode[]} schema
|
* @param {string} accountsTypes
|
||||||
* @returns {IBalanceSheetDataNode[]}
|
* @returns {IAccount[]}
|
||||||
*/
|
*/
|
||||||
public parseSchemaNodes = (
|
private getAccountsByAccountTypes = (accountsTypes: string[]): IAccount[] => {
|
||||||
schema: IBalanceSheetSchemaNode[]
|
const mapAccountsByTypes = R.map((accountType) =>
|
||||||
): IBalanceSheetDataNode[] => {
|
defaultTo(this.repository.accountsByType.get(accountType), [])
|
||||||
|
);
|
||||||
|
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the aggregate schema node type.
|
||||||
|
* @param {IBalanceSheetSchemaAggregateNode} node - Schema node.
|
||||||
|
* @return {IBalanceSheetAggregateNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaAggregateNodeMapper = (
|
||||||
|
node: IBalanceSheetSchemaAggregateNode
|
||||||
|
): IBalanceSheetAggregateNode => {
|
||||||
|
const total = this.getTotalOfNodes(node.children);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: this.i18n.__(node.name),
|
||||||
|
id: node.id,
|
||||||
|
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
|
||||||
|
total: this.getTotalAmountMeta(total),
|
||||||
|
children: node.children,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose shema aggregate node of balance sheet schema.
|
||||||
|
* @param {IBalanceSheetSchemaAggregateNode} node
|
||||||
|
* @returns {IBalanceSheetSchemaAggregateNode}
|
||||||
|
*/
|
||||||
|
private schemaAggregateNodeCompose = (
|
||||||
|
node: IBalanceSheetSchemaAggregateNode
|
||||||
|
) => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
this.aggregatesSchemaParser,
|
this.aggregateNodeTotalMapper,
|
||||||
this.netIncomeSchemaParser,
|
this.reportSchemaAggregateNodeMapper
|
||||||
this.accountsSchemaParser
|
)(node);
|
||||||
)(schema) as IBalanceSheetDataNode[];
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the account model to report account node.
|
||||||
|
* @param {IAccount} account
|
||||||
|
* @returns {IBalanceSheetAccountNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaAccountNodeMapper = (
|
||||||
|
account: IAccount
|
||||||
|
): IBalanceSheetAccountNode => {
|
||||||
|
const total = this.repository.totalAccountsLedger
|
||||||
|
.whereAccountId(account.id)
|
||||||
|
.getClosingBalance();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: account.id,
|
||||||
|
index: account.index,
|
||||||
|
name: account.name,
|
||||||
|
code: account.code,
|
||||||
|
total: this.getAmountMeta(total),
|
||||||
|
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {IAccount} account
|
||||||
|
* @returns {IBalanceSheetAccountNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaAccountNodeComposer = (
|
||||||
|
account: IAccount
|
||||||
|
): IBalanceSheetAccountNode => {
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousYearActive,
|
||||||
|
this.previousYearAccountNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousPeriodActive,
|
||||||
|
this.previousPeriodAccountNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isDatePeriodsColumnsType,
|
||||||
|
this.assocAccountNodeDatePeriods
|
||||||
|
),
|
||||||
|
this.reportSchemaAccountNodeMapper
|
||||||
|
)(account);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the total of the given nodes.
|
||||||
|
* @param {IBalanceSheetCommonNode[]} nodes
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
private getTotalOfNodes = (nodes: IBalanceSheetCommonNode[]) => {
|
||||||
|
return sumBy(nodes, 'total.amount');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the report accounts node by the given accounts types.
|
||||||
|
* @param {string[]} accountsTypes
|
||||||
|
* @returns {}
|
||||||
|
*/
|
||||||
|
private getAccountsNodesByAccountTypes = (accountsTypes: string[]) => {
|
||||||
|
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
||||||
|
|
||||||
|
return R.compose(R.map(this.reportSchemaAccountNodeComposer))(accounts);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the accounts schema node type.
|
||||||
|
* @param {IBalanceSheetSchemaNode} node - Schema node.
|
||||||
|
* @returns {IBalanceSheetAccountNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaAccountsNodeMapper = (
|
||||||
|
node: IBalanceSheetSchemaAccountNode
|
||||||
|
): IBalanceSheetAccountNode => {
|
||||||
|
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
|
||||||
|
const total = this.getTotalOfNodes(accounts);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: node.id,
|
||||||
|
name: this.i18n.__(node.name),
|
||||||
|
type: node.type,
|
||||||
|
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
|
||||||
|
children: accounts,
|
||||||
|
total: this.getTotalAmountMeta(total),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose account schema node to report node.
|
||||||
|
* @param {IBalanceSheetSchemaAccountNode} node
|
||||||
|
* @returns {IBalanceSheetAccountNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaAccountsNodeComposer = (
|
||||||
|
node: IBalanceSheetSchemaAccountNode
|
||||||
|
): IBalanceSheetAccountNode => {
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousYearActive,
|
||||||
|
this.previousYearAggregateNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousPeriodActive,
|
||||||
|
this.previousPeriodAggregateNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isDatePeriodsColumnsType,
|
||||||
|
this.assocAccountsNodeDatePeriods
|
||||||
|
),
|
||||||
|
this.reportSchemaAccountsNodeMapper
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the given report schema node.
|
||||||
|
* @param {IBalanceSheetSchemaNode} node - Schema node.
|
||||||
|
* @return {IBalanceSheetDataNode}
|
||||||
|
*/
|
||||||
|
private reportSchemaNodeMapper = (
|
||||||
|
schemaNode: IBalanceSheetSchemaNode
|
||||||
|
): IBalanceSheetDataNode => {
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
|
||||||
|
this.schemaAggregateNodeCompose
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
||||||
|
this.reportSchemaAccountsNodeComposer
|
||||||
|
)
|
||||||
|
)(schemaNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the report schema nodes.
|
||||||
|
* @param {IBalanceSheetSchemaNode[]} nodes -
|
||||||
|
* @return {IBalanceSheetStructureSection[]}
|
||||||
|
*/
|
||||||
|
private reportSchemaAccountNodesMapper = (
|
||||||
|
schemaNodes: IBalanceSheetSchemaNode[]
|
||||||
|
): IBalanceSheetDataNode[] => {
|
||||||
|
return this.mapNodesDeepReverse(schemaNodes, this.reportSchemaNodeMapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets total amount that calculated from node children.
|
||||||
|
* @param {IBalanceSheetSection} node
|
||||||
|
* @returns {IBalanceSheetDataNode}
|
||||||
|
*/
|
||||||
|
private aggregateNodeTotalMapper = (
|
||||||
|
node: IBalanceSheetDataNode
|
||||||
|
): IBalanceSheetDataNode => {
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousYearActive,
|
||||||
|
this.previousYearAggregateNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isPreviousPeriodActive,
|
||||||
|
this.previousPeriodAggregateNodeComposer
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.query.isDatePeriodsColumnsType,
|
||||||
|
this.assocAggregateNodeDatePeriods
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,7 +299,7 @@ export default class BalanceSheet extends R.compose(
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
this.reportFilterPlugin,
|
this.reportFilterPlugin,
|
||||||
this.reportPercentageCompose,
|
this.reportPercentageCompose,
|
||||||
this.parseSchemaNodes
|
this.reportSchemaAccountNodesMapper
|
||||||
)(balanceSheetSchema);
|
)(balanceSheetSchema);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import { defaultTo, toArray } from 'lodash';
|
|
||||||
import { FinancialSheetStructure } from '../FinancialSheetStructure';
|
|
||||||
import {
|
|
||||||
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
|
||||||
IAccount,
|
|
||||||
IBalanceSheetAccountNode,
|
|
||||||
IBalanceSheetAccountsNode,
|
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetSchemaAccountNode,
|
|
||||||
IBalanceSheetSchemaNode,
|
|
||||||
INumberFormatQuery,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
|
|
||||||
import { BalanceSheetFiltering } from './BalanceSheetFiltering';
|
|
||||||
import { BalanceSheetDatePeriods } from './BalanceSheetDatePeriods';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
|
|
||||||
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
|
||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
|
|
||||||
export const BalanceSheetAccounts = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetNetIncome,
|
|
||||||
BalanceSheetFiltering,
|
|
||||||
BalanceSheetDatePeriods,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
BalanceSheetPercentage,
|
|
||||||
BalanceSheetSchema,
|
|
||||||
BalanceSheetBase,
|
|
||||||
FinancialSheetStructure
|
|
||||||
)(Base) {
|
|
||||||
/**
|
|
||||||
* Balance sheet query.
|
|
||||||
* @param {BalanceSheetQuery}
|
|
||||||
*/
|
|
||||||
readonly query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Balance sheet number format query.
|
|
||||||
* @param {INumberFormatQuery}
|
|
||||||
*/
|
|
||||||
readonly numberFormat: INumberFormatQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base currency of the organization.
|
|
||||||
* @param {string}
|
|
||||||
*/
|
|
||||||
readonly baseCurrency: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Localization.
|
|
||||||
*/
|
|
||||||
readonly i18n: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the accounts node of accounts types.
|
|
||||||
* @param {string} accountsTypes
|
|
||||||
* @returns {IAccount[]}
|
|
||||||
*/
|
|
||||||
private getAccountsByAccountTypes = (
|
|
||||||
accountsTypes: string[]
|
|
||||||
): IAccount[] => {
|
|
||||||
const mapAccountsByTypes = R.map((accountType) =>
|
|
||||||
defaultTo(this.repository.accountsByType.get(accountType), [])
|
|
||||||
);
|
|
||||||
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the account model to report account node.
|
|
||||||
* @param {IAccount} account
|
|
||||||
* @returns {IBalanceSheetAccountNode}
|
|
||||||
*/
|
|
||||||
private reportSchemaAccountNodeMapper = (
|
|
||||||
account: IAccount
|
|
||||||
): IBalanceSheetAccountNode => {
|
|
||||||
const total = this.repository.totalAccountsLedger
|
|
||||||
.whereAccountId(account.id)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: account.id,
|
|
||||||
index: account.index,
|
|
||||||
name: account.name,
|
|
||||||
code: account.code,
|
|
||||||
total: this.getAmountMeta(total),
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the given account model to the balance sheet account node.
|
|
||||||
* @param {IAccount} account
|
|
||||||
* @returns {IBalanceSheetAccountNode}
|
|
||||||
*/
|
|
||||||
private reportSchemaAccountNodeComposer = (
|
|
||||||
account: IAccount
|
|
||||||
): IBalanceSheetAccountNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearActive,
|
|
||||||
this.previousYearAccountNodeComposer
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodActive,
|
|
||||||
this.previousPeriodAccountNodeComposer
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isDatePeriodsColumnsType,
|
|
||||||
this.assocAccountNodeDatePeriods
|
|
||||||
),
|
|
||||||
this.reportSchemaAccountNodeMapper
|
|
||||||
)(account);
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------
|
|
||||||
// - Accounts Node Praser
|
|
||||||
// -----------------------------
|
|
||||||
/**
|
|
||||||
* Retrieve the report accounts node by the given accounts types.
|
|
||||||
* @param {string[]} accountsTypes
|
|
||||||
* @returns {IBalanceSheetAccountNode[]}
|
|
||||||
*/
|
|
||||||
private getAccountsNodesByAccountTypes = (
|
|
||||||
accountsTypes: string[]
|
|
||||||
): IBalanceSheetAccountNode[] => {
|
|
||||||
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
|
||||||
return R.map(this.reportSchemaAccountNodeComposer, accounts);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the accounts schema node type.
|
|
||||||
* @param {IBalanceSheetSchemaNode} node - Schema node.
|
|
||||||
* @returns {IBalanceSheetAccountNode}
|
|
||||||
*/
|
|
||||||
private reportSchemaAccountsNodeMapper = (
|
|
||||||
node: IBalanceSheetSchemaAccountNode
|
|
||||||
): IBalanceSheetAccountsNode => {
|
|
||||||
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
|
|
||||||
const children = toArray(node?.children);
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: node.id,
|
|
||||||
name: this.i18n.__(node.name),
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
|
|
||||||
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
|
|
||||||
children: [...accounts, ...children],
|
|
||||||
total: this.getTotalAmountMeta(0),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the given report schema node.
|
|
||||||
* @param {IBalanceSheetSchemaNode | IBalanceSheetDataNode} node - Schema node.
|
|
||||||
* @return {IBalanceSheetSchemaNode | IBalanceSheetDataNode}
|
|
||||||
*/
|
|
||||||
private reportAccountSchemaParser = (
|
|
||||||
node: IBalanceSheetSchemaNode | IBalanceSheetDataNode
|
|
||||||
): IBalanceSheetSchemaNode | IBalanceSheetDataNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
|
||||||
this.reportSchemaAccountsNodeMapper
|
|
||||||
)
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the report accounts schema nodes.
|
|
||||||
* @param {IBalanceSheetSchemaNode[]} nodes -
|
|
||||||
* @return {IBalanceSheetStructureSection[]}
|
|
||||||
*/
|
|
||||||
public accountsSchemaParser = (
|
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
|
||||||
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
|
||||||
return this.mapNodesDeepReverse(nodes, this.reportAccountSchemaParser);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import { FinancialSheetStructure } from '../FinancialSheetStructure';
|
|
||||||
import {
|
|
||||||
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
|
||||||
IBalanceSheetAggregateNode,
|
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetSchemaAggregateNode,
|
|
||||||
IBalanceSheetSchemaNode,
|
|
||||||
INumberFormatQuery,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetDatePeriods } from './BalanceSheetDatePeriods';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
|
|
||||||
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
|
||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
|
|
||||||
export const BalanceSheetAggregators = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetDatePeriods,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
BalanceSheetPercentage,
|
|
||||||
BalanceSheetSchema,
|
|
||||||
BalanceSheetBase,
|
|
||||||
FinancialSheetStructure
|
|
||||||
)(Base) {
|
|
||||||
/**
|
|
||||||
* Balance sheet query.
|
|
||||||
* @param {BalanceSheetQuery}
|
|
||||||
*/
|
|
||||||
readonly query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Balance sheet number format query.
|
|
||||||
* @param {INumberFormatQuery}
|
|
||||||
*/
|
|
||||||
readonly numberFormat: INumberFormatQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base currency of the organization.
|
|
||||||
* @param {string}
|
|
||||||
*/
|
|
||||||
readonly baseCurrency: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Localization.
|
|
||||||
*/
|
|
||||||
readonly i18n: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets total amount that calculated from node children.
|
|
||||||
* @param {IBalanceSheetSection} node
|
|
||||||
* @returns {IBalanceSheetDataNode}
|
|
||||||
*/
|
|
||||||
private aggregateNodeTotalMapper = (
|
|
||||||
node: IBalanceSheetDataNode
|
|
||||||
): IBalanceSheetDataNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearActive,
|
|
||||||
this.previousYearAggregateNodeComposer
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodActive,
|
|
||||||
this.previousPeriodAggregateNodeComposer
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isDatePeriodsColumnsType,
|
|
||||||
this.assocAggregateNodeDatePeriods
|
|
||||||
)
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the aggregate schema node type.
|
|
||||||
* @param {IBalanceSheetSchemaAggregateNode} node - Schema node.
|
|
||||||
* @return {IBalanceSheetAggregateNode}
|
|
||||||
*/
|
|
||||||
private reportSchemaAggregateNodeMapper = (
|
|
||||||
node: IBalanceSheetSchemaAggregateNode
|
|
||||||
): IBalanceSheetAggregateNode => {
|
|
||||||
const total = this.getTotalOfNodes(node.children);
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: this.i18n.__(node.name),
|
|
||||||
id: node.id,
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
|
|
||||||
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
|
|
||||||
total: this.getTotalAmountMeta(total),
|
|
||||||
children: node.children,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose shema aggregate node of balance sheet schema.
|
|
||||||
* @param {IBalanceSheetSchemaAggregateNode} node
|
|
||||||
* @returns {IBalanceSheetSchemaAggregateNode}
|
|
||||||
*/
|
|
||||||
private schemaAggregateNodeCompose = (
|
|
||||||
node: IBalanceSheetSchemaAggregateNode
|
|
||||||
) => {
|
|
||||||
return R.compose(
|
|
||||||
this.aggregateNodeTotalMapper,
|
|
||||||
this.reportSchemaAggregateNodeMapper
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the given report schema node.
|
|
||||||
* @param {IBalanceSheetSchemaNode} node - Schema node.
|
|
||||||
* @return {IBalanceSheetDataNode}
|
|
||||||
*/
|
|
||||||
private reportAggregateSchemaParser = (
|
|
||||||
node: IBalanceSheetSchemaNode
|
|
||||||
): IBalanceSheetDataNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
|
|
||||||
this.schemaAggregateNodeCompose
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
|
||||||
this.schemaAggregateNodeCompose
|
|
||||||
)
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the report schema nodes.
|
|
||||||
* @param {IBalanceSheetSchemaNode[]} nodes -
|
|
||||||
* @return {IBalanceSheetStructureSection[]}
|
|
||||||
*/
|
|
||||||
public aggregatesSchemaParser = (
|
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
|
||||||
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
|
||||||
return this.mapNodesDeepReverse(nodes, this.reportAggregateSchemaParser);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
IBalanceSheetAggregateNode,
|
IBalanceSheetAggregateNode,
|
||||||
IBalanceSheetTotal,
|
IBalanceSheetTotal,
|
||||||
IBalanceSheetCommonNode,
|
IBalanceSheetCommonNode,
|
||||||
IBalanceSheetComparsions,
|
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
||||||
|
|||||||
@@ -156,14 +156,13 @@ export const BalanceSheetComparsionPreviousYear = (Base: any) =>
|
|||||||
* @param {IBalanceSheetCommonNode} node
|
* @param {IBalanceSheetCommonNode} node
|
||||||
* @returns {IBalanceSheetCommonNode}
|
* @returns {IBalanceSheetCommonNode}
|
||||||
*/
|
*/
|
||||||
public assocPreviousYearAggregateHorizNode = (
|
private assocPreviousYearAggregateHorizNode = (
|
||||||
node: IBalanceSheetCommonNode
|
node: IBalanceSheetCommonNode
|
||||||
): IBalanceSheetCommonNode => {
|
) => {
|
||||||
const horizontalTotals = R.addIndex(R.map)(
|
const horizontalTotals = R.addIndex(R.map)(
|
||||||
this.previousYearAggregateHorizNodeComposer(node),
|
this.previousYearAggregateHorizNodeComposer(node),
|
||||||
node.horizontalTotals
|
node.horizontalTotals
|
||||||
) as IBalanceSheetTotal[];
|
);
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', horizontalTotals, node);
|
return R.assoc('horizontalTotals', horizontalTotals, node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -259,11 +258,12 @@ export const BalanceSheetComparsionPreviousYear = (Base: any) =>
|
|||||||
// ------------------------------
|
// ------------------------------
|
||||||
// # Horizontal Nodes - Aggregate.
|
// # Horizontal Nodes - Aggregate.
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detarmines whether the given node has horizontal totals.
|
* Detarmines whether the given node has horizontal totals.
|
||||||
* @param {IBalanceSheetCommonNode} node
|
* @param {IBalanceSheetCommonNode} node
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
public isNodeHasHorizontalTotals = (node: IBalanceSheetCommonNode) =>
|
private isNodeHasHorizontalTotals = (node: IBalanceSheetCommonNode) =>
|
||||||
!isEmpty(node.horizontalTotals);
|
!isEmpty(node.horizontalTotals);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -107,9 +107,9 @@ export const BalanceSheetDatePeriods = (Base: FinancialSheet) =>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {IBalanceSheetAccountNode} node
|
* @param {IBalanceSheetAccountNode} node
|
||||||
* @param {Date} fromDate
|
* @param {Date} fromDate
|
||||||
* @param {Date} toDate
|
* @param {Date} toDate
|
||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private getAccountNodeDatePeriod = (
|
private getAccountNodeDatePeriod = (
|
||||||
@@ -201,7 +201,7 @@ export const BalanceSheetDatePeriods = (Base: FinancialSheet) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param node
|
* @param node
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import {
|
|
||||||
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
IBalanceSheetSchemaNetIncomeNode,
|
|
||||||
IBalanceSheetSchemaNode,
|
|
||||||
IBalanceSheetTotalPeriod,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
|
||||||
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncome = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetNetIncomePP,
|
|
||||||
BalanceSheetNetIncomePY,
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
private repository: BalanceSheetRepository;
|
|
||||||
private query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing balance of income accounts.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getIncomeTotal = () => {
|
|
||||||
const closeingBalance = this.repository.incomeLedger.getClosingBalance();
|
|
||||||
return closeingBalance;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing balance of expenses accounts.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getExpensesTotal = () => {
|
|
||||||
const closingBalance = this.repository.expensesLedger.getClosingBalance();
|
|
||||||
return closingBalance;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the total net income.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
protected getNetIncomeTotal = () => {
|
|
||||||
const income = this.getIncomeTotal();
|
|
||||||
const expenses = this.getExpensesTotal();
|
|
||||||
|
|
||||||
return income - expenses;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the aggregate schema node type.
|
|
||||||
* @param {IBalanceSheetSchemaNetIncomeNode} node - Schema node.
|
|
||||||
* @return {IBalanceSheetAggregateNode}
|
|
||||||
*/
|
|
||||||
protected schemaNetIncomeNodeMapper = (
|
|
||||||
node: IBalanceSheetSchemaNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const total = this.getNetIncomeTotal();
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: node.id,
|
|
||||||
name: this.i18n.__(node.name),
|
|
||||||
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME,
|
|
||||||
total: this.getTotalAmountMeta(total),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mapps the net income shcema node to report node.
|
|
||||||
* @param {IBalanceSheetSchemaNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
protected schemaNetIncomeNodeCompose = (
|
|
||||||
node: IBalanceSheetSchemaNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearActive,
|
|
||||||
this.previousYearNetIncomeNodeCompose
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodActive,
|
|
||||||
this.previousPeriodNetIncomeNodeCompose
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isDatePeriodsColumnsType,
|
|
||||||
this.assocNetIncomeDatePeriodsNode
|
|
||||||
),
|
|
||||||
this.schemaNetIncomeNodeMapper
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
// --------------------------------
|
|
||||||
// # Date Periods
|
|
||||||
// --------------------------------
|
|
||||||
/**
|
|
||||||
* Retreives total income of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getIncomeDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const periodTotalBetween = this.repository.incomePeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const periodOpening =
|
|
||||||
this.repository.incomePeriodsOpeningAccountsLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return periodOpening + periodTotalBetween;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves total expense of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getExpensesDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const periodTotalBetween = this.repository.expensesPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const periodOpening =
|
|
||||||
this.repository.expensesOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return periodOpening + periodTotalBetween;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the given net income date period total.
|
|
||||||
* @param {number} accountId
|
|
||||||
* @param {Date} toDate
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const income = this.getIncomeDatePeriodTotal(toDate);
|
|
||||||
const expense = this.getExpensesDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the net income date period node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @param {Date} fromDate
|
|
||||||
* @param {Date} toDate
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode,
|
|
||||||
fromDate: Date,
|
|
||||||
toDate: Date
|
|
||||||
): IBalanceSheetTotalPeriod => {
|
|
||||||
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return this.getDatePeriodTotalMeta(periodTotal, fromDate, toDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve total date periods of the given net income node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodsNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetTotalPeriod[] => {
|
|
||||||
return this.getReportNodeDatePeriods(
|
|
||||||
node,
|
|
||||||
this.getNetIncomeDatePeriodNode
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc total date periods to net income node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
public assocNetIncomeDatePeriodsNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', datePeriods, node);
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------
|
|
||||||
// - Net Income Nodes Praser
|
|
||||||
// -----------------------------
|
|
||||||
/**
|
|
||||||
* Mappes the given report schema node.
|
|
||||||
* @param {IBalanceSheetSchemaNode} node - Schema node.
|
|
||||||
* @return {IBalanceSheetDataNode}
|
|
||||||
*/
|
|
||||||
private reportNetIncomeNodeSchemaParser = (
|
|
||||||
schemaNode: IBalanceSheetSchemaNode
|
|
||||||
): IBalanceSheetDataNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME),
|
|
||||||
this.schemaNetIncomeNodeCompose
|
|
||||||
)
|
|
||||||
)(schemaNode);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the report net income schema nodes.
|
|
||||||
* @param {(IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]} nodes -
|
|
||||||
* @return {IBalanceSheetDataNode[]}
|
|
||||||
*/
|
|
||||||
public netIncomeSchemaParser = (
|
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
|
||||||
): IBalanceSheetDataNode[] => {
|
|
||||||
return this.mapNodesDeep(nodes, this.reportNetIncomeNodeSchemaParser);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import {
|
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
IBalanceSheetTotalPeriod,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
|
||||||
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriods = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetNetIncomePP,
|
|
||||||
BalanceSheetNetIncomePY,
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
private repository: BalanceSheetRepository;
|
|
||||||
private query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
// --------------------------------
|
|
||||||
// # Date Periods
|
|
||||||
// --------------------------------
|
|
||||||
/**
|
|
||||||
* Retreives total income of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getIncomeDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const periodTotalBetween = this.repository.incomePeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const periodOpening =
|
|
||||||
this.repository.incomePeriodsOpeningAccountsLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return periodOpening + periodTotalBetween;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves total expense of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getExpensesDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const periodTotalBetween = this.repository.expensesPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const periodOpening =
|
|
||||||
this.repository.expensesOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return periodOpening + periodTotalBetween;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the given net income date period total.
|
|
||||||
* @param {number} accountId
|
|
||||||
* @param {Date} toDate
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodTotal = (toDate: Date): number => {
|
|
||||||
const income = this.getIncomeDatePeriodTotal(toDate);
|
|
||||||
const expense = this.getExpensesDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the net income date period node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @param {Date} fromDate
|
|
||||||
* @param {Date} toDate
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode,
|
|
||||||
fromDate: Date,
|
|
||||||
toDate: Date
|
|
||||||
): IBalanceSheetTotalPeriod => {
|
|
||||||
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return this.getDatePeriodTotalMeta(periodTotal, fromDate, toDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve total date periods of the given net income node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
private getNetIncomeDatePeriodsNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetTotalPeriod[] => {
|
|
||||||
return this.getReportNodeDatePeriods(
|
|
||||||
node,
|
|
||||||
this.getNetIncomeDatePeriodNode
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc total date periods to net income node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
public assocNetIncomeDatePeriodsNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', datePeriods, node);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import { IBalanceSheetNetIncomeNode, IBalanceSheetTotal } from '@/interfaces';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriodsPP = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
query: BalanceSheetQuery;
|
|
||||||
repository: BalanceSheetRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PY total income of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
private getPPIncomeDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const PYPeriodsTotal = this.repository.incomePPPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const PYPeriodsOpeningTotal =
|
|
||||||
this.repository.incomePPPeriodsOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return PYPeriodsOpeningTotal + PYPeriodsTotal;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PY total expense of the given date period.
|
|
||||||
* @param {number} accountId -
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getPPExpenseDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const PYPeriodsTotal = this.repository.expensePPPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const PYPeriodsOpeningTotal =
|
|
||||||
this.repository.expensePPPeriodsOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return PYPeriodsOpeningTotal + PYPeriodsTotal;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the given net income total of the given period.
|
|
||||||
* @param {number} accountId - Account id.
|
|
||||||
* @param {Date} toDate - To date.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getPPNetIncomeDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const income = this.getPPIncomeDatePeriodTotal(toDate);
|
|
||||||
const expense = this.getPPExpenseDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc preivous period to account horizontal total node.
|
|
||||||
* @param {IBalanceSheetAccountNode} node
|
|
||||||
* @returns {}
|
|
||||||
*/
|
|
||||||
private assocPreviousPeriodNetIncomeHorizTotal = R.curry(
|
|
||||||
(node: IBalanceSheetNetIncomeNode, totalNode) => {
|
|
||||||
const total = this.getPPNetIncomeDatePeriodTotal(
|
|
||||||
totalNode.previousPeriodToDate.date
|
|
||||||
);
|
|
||||||
return R.assoc('previousPeriod', this.getAmountMeta(total), totalNode);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose previous period to aggregate horizontal nodes.
|
|
||||||
* @param {IBalanceSheetTotal} node
|
|
||||||
* @returns {IBalanceSheetTotal}
|
|
||||||
*/
|
|
||||||
private previousPeriodNetIncomeHorizNodeComposer = R.curry(
|
|
||||||
(
|
|
||||||
node: IBalanceSheetNetIncomeNode,
|
|
||||||
horiontalTotalNode: IBalanceSheetTotal
|
|
||||||
): IBalanceSheetTotal => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodPercentageActive,
|
|
||||||
this.assocPreviousPeriodTotalPercentageNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodChangeActive,
|
|
||||||
this.assocPreviousPeriodTotalChangeNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodActive,
|
|
||||||
this.assocPreviousPeriodNetIncomeHorizTotal(node)
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodActive,
|
|
||||||
this.assocPreviousPeriodHorizNodeFromToDates(
|
|
||||||
this.query.displayColumnsBy
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)(horiontalTotalNode);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associate the PP to net income horizontal nodes.
|
|
||||||
* @param {IBalanceSheetCommonNode} node
|
|
||||||
* @returns {IBalanceSheetCommonNode}
|
|
||||||
*/
|
|
||||||
public assocPreviousPeriodNetIncomeHorizNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const horizontalTotals = R.addIndex(R.map)(
|
|
||||||
this.previousPeriodNetIncomeHorizNodeComposer(node),
|
|
||||||
node.horizontalTotals
|
|
||||||
) as IBalanceSheetTotal[];
|
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', horizontalTotals, node);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import { IBalanceSheetNetIncomeNode, IBalanceSheetTotal } from '@/interfaces';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriodsPY = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
query: BalanceSheetQuery;
|
|
||||||
repository: BalanceSheetRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PY total income of the given date period.
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
private getPYIncomeDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const PYPeriodsTotal = this.repository.incomePYPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const PYPeriodsOpeningTotal =
|
|
||||||
this.repository.incomePYPeriodsOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return PYPeriodsOpeningTotal + PYPeriodsTotal;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PY total expense of the given date period.
|
|
||||||
* @param {Date} toDate -
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getPYExpenseDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const PYPeriodsTotal = this.repository.expensePYPeriodsAccountsLedger
|
|
||||||
.whereToDate(toDate)
|
|
||||||
.getClosingBalance();
|
|
||||||
|
|
||||||
const PYPeriodsOpeningTotal =
|
|
||||||
this.repository.expensePYPeriodsOpeningAccountLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return PYPeriodsOpeningTotal + PYPeriodsTotal;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the given net income total of the given period.
|
|
||||||
* @param {Date} toDate - To date.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
private getPYNetIncomeDatePeriodTotal = R.curry((toDate: Date) => {
|
|
||||||
const income = this.getPYIncomeDatePeriodTotal(toDate);
|
|
||||||
const expense = this.getPYExpenseDatePeriodTotal(toDate);
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc preivous year to account horizontal total node.
|
|
||||||
* @param {IBalanceSheetAccountNode} node
|
|
||||||
* @returns {}
|
|
||||||
*/
|
|
||||||
private assocPreviousYearNetIncomeHorizTotal = R.curry(
|
|
||||||
(node: IBalanceSheetNetIncomeNode, totalNode) => {
|
|
||||||
const total = this.getPYNetIncomeDatePeriodTotal(
|
|
||||||
totalNode.previousYearToDate.date
|
|
||||||
);
|
|
||||||
return R.assoc('previousYear', this.getAmountMeta(total), totalNode);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose PY to net income horizontal nodes.
|
|
||||||
* @param {IBalanceSheetTotal} node
|
|
||||||
* @returns {IBalanceSheetTotal}
|
|
||||||
*/
|
|
||||||
private previousYearNetIncomeHorizNodeComposer = R.curry(
|
|
||||||
(
|
|
||||||
node: IBalanceSheetNetIncomeNode,
|
|
||||||
horiontalTotalNode: IBalanceSheetTotal
|
|
||||||
): IBalanceSheetTotal => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearPercentageActive,
|
|
||||||
this.assocPreviousYearTotalPercentageNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearChangeActive,
|
|
||||||
this.assocPreviousYearTotalChangeNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearActive,
|
|
||||||
this.assocPreviousYearNetIncomeHorizTotal(node)
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearActive,
|
|
||||||
this.assocPreviousYearHorizNodeFromToDates
|
|
||||||
)
|
|
||||||
)(horiontalTotalNode);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associate the PY to net income horizontal nodes.
|
|
||||||
* @param {IBalanceSheetCommonNode} node
|
|
||||||
* @returns {IBalanceSheetCommonNode}
|
|
||||||
*/
|
|
||||||
public assocPreviousYearNetIncomeHorizNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const horizontalTotals = R.addIndex(R.map)(
|
|
||||||
this.previousYearNetIncomeHorizNodeComposer(node),
|
|
||||||
node.horizontalTotals
|
|
||||||
) as IBalanceSheetTotal[];
|
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', horizontalTotals, node);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import {
|
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import { BalanceSheetNetIncomeDatePeriodsPP } from './BalanceSheetNetIncomeDatePeriodsPP';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncomePP = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetNetIncomeDatePeriodsPP,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
private repository: BalanceSheetRepository;
|
|
||||||
private query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// # Previous Period (PP)
|
|
||||||
// -------------------------------
|
|
||||||
/**
|
|
||||||
* Retrieves the PP net income.
|
|
||||||
* @returns {}
|
|
||||||
*/
|
|
||||||
protected getPreviousPeriodNetIncome = () => {
|
|
||||||
const income = this.repository.incomePPAccountsLedger.getClosingBalance();
|
|
||||||
const expense =
|
|
||||||
this.repository.expensePPAccountsLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associates the previous period to account node.
|
|
||||||
* @param {IBalanceSheetDataNode} node
|
|
||||||
* @returns {IBalanceSheetDataNode}
|
|
||||||
*/
|
|
||||||
protected assocPreviousPeriodNetIncomeNode = (
|
|
||||||
node: IBalanceSheetDataNode
|
|
||||||
): IBalanceSheetDataNode => {
|
|
||||||
const total = this.getPreviousPeriodNetIncome();
|
|
||||||
|
|
||||||
return R.assoc('previousPeriod', this.getAmountMeta(total), node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Previous period account node composer.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {IBalanceSheetNetIncomeNode}
|
|
||||||
*/
|
|
||||||
protected previousPeriodNetIncomeNodeCompose = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.isNodeHasHorizTotals,
|
|
||||||
this.assocPreviousPeriodNetIncomeHorizNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodPercentageActive,
|
|
||||||
this.assocPreviousPeriodPercentageNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousPeriodChangeActive,
|
|
||||||
this.assocPreviousPeriodChangeNode
|
|
||||||
),
|
|
||||||
this.assocPreviousPeriodNetIncomeNode
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import {
|
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
|
||||||
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
|
|
||||||
import { FinancialHorizTotals } from '../FinancialHorizTotals';
|
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import { BalanceSheetNetIncomeDatePeriodsPY } from './BalanceSheetNetIncomeDatePeriodsPY';
|
|
||||||
|
|
||||||
export const BalanceSheetNetIncomePY = (Base: any) =>
|
|
||||||
class extends R.compose(
|
|
||||||
BalanceSheetNetIncomeDatePeriodsPY,
|
|
||||||
BalanceSheetComparsionPreviousYear,
|
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals
|
|
||||||
)(Base) {
|
|
||||||
private repository: BalanceSheetRepository;
|
|
||||||
private query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
// ------------------------------
|
|
||||||
// # Previous Year (PY)
|
|
||||||
// ------------------------------
|
|
||||||
/**
|
|
||||||
* Retrieves the previous year (PY) net income.
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
protected getPreviousYearNetIncome = () => {
|
|
||||||
const income =
|
|
||||||
this.repository.incomePYTotalAccountsLedger.getClosingBalance();
|
|
||||||
const expense =
|
|
||||||
this.repository.expensePYTotalAccountsLedger.getClosingBalance();
|
|
||||||
|
|
||||||
return income - expense;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc previous year on aggregate node.
|
|
||||||
* @param {IBalanceSheetAccountNode} node
|
|
||||||
* @returns {IBalanceSheetAccountNode}
|
|
||||||
*/
|
|
||||||
protected assocPreviousYearNetIncomeNode = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
const total = this.getPreviousYearNetIncome();
|
|
||||||
|
|
||||||
return R.assoc('previousYear', this.getTotalAmountMeta(total), node);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assoc previous year attributes to aggregate node.
|
|
||||||
* @param {IBalanceSheetAccountNode} node
|
|
||||||
* @returns {IBalanceSheetAccountNode}
|
|
||||||
*/
|
|
||||||
protected previousYearNetIncomeNodeCompose = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): IBalanceSheetNetIncomeNode => {
|
|
||||||
return R.compose(
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearPercentageActive,
|
|
||||||
this.assocPreviousYearTotalPercentageNode
|
|
||||||
),
|
|
||||||
R.when(
|
|
||||||
this.query.isPreviousYearChangeActive,
|
|
||||||
this.assocPreviousYearTotalChangeNode
|
|
||||||
),
|
|
||||||
// Associate the PY to date periods horizontal nodes.
|
|
||||||
R.when(
|
|
||||||
this.isNodeHasHorizontalTotals,
|
|
||||||
this.assocPreviousYearNetIncomeHorizNode
|
|
||||||
),
|
|
||||||
this.assocPreviousYearNetIncomeNode
|
|
||||||
)(node);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -12,31 +12,26 @@ export class BalanceSheetQuery extends R.compose(FinancialDateRanges)(
|
|||||||
* @param {IBalanceSheetQuery}
|
* @param {IBalanceSheetQuery}
|
||||||
*/
|
*/
|
||||||
public readonly query: IBalanceSheetQuery;
|
public readonly query: IBalanceSheetQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous year to date.
|
* Previous year to date.
|
||||||
* @param {Date}
|
* @param {Date}
|
||||||
*/
|
*/
|
||||||
public readonly PYToDate: Date;
|
public readonly PYToDate: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous year from date.
|
* Previous year from date.
|
||||||
* @param {Date}
|
* @param {Date}
|
||||||
*/
|
*/
|
||||||
public readonly PYFromDate: Date;
|
public readonly PYFromDate: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous period to date.
|
* Previous period to date.
|
||||||
* @param {Date}
|
* @param {Date}
|
||||||
*/
|
*/
|
||||||
public readonly PPToDate: Date;
|
public readonly PPToDate: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous period from date.
|
* Previous period from date.
|
||||||
* @param {Date}
|
* @param {Date}
|
||||||
*/
|
*/
|
||||||
public readonly PPFromDate: Date;
|
public readonly PPFromDate: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor method
|
* Constructor method
|
||||||
* @param {IBalanceSheetQuery} query
|
* @param {IBalanceSheetQuery} query
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import * as R from 'ramda';
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import {
|
import {
|
||||||
IAccount,
|
|
||||||
IAccountTransactionsGroupBy,
|
IAccountTransactionsGroupBy,
|
||||||
IBalanceSheetQuery,
|
IBalanceSheetQuery,
|
||||||
ILedger,
|
ILedger,
|
||||||
@@ -12,12 +11,9 @@ import { transformToMapBy } from 'utils';
|
|||||||
import Ledger from '@/services/Accounting/Ledger';
|
import Ledger from '@/services/Accounting/Ledger';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { FinancialDatePeriods } from '../FinancialDatePeriods';
|
import { FinancialDatePeriods } from '../FinancialDatePeriods';
|
||||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/data/AccountTypes';
|
|
||||||
import { BalanceSheetRepositoryNetIncome } from './BalanceSheetRepositoryNetIncome';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class BalanceSheetRepository extends R.compose(
|
export default class BalanceSheetRepository extends R.compose(
|
||||||
BalanceSheetRepositoryNetIncome,
|
|
||||||
FinancialDatePeriods
|
FinancialDatePeriods
|
||||||
)(class {}) {
|
)(class {}) {
|
||||||
/**
|
/**
|
||||||
@@ -69,22 +65,8 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public readonly PPFromDate: Date;
|
public readonly PPFromDate: Date;
|
||||||
|
|
||||||
/**
|
|
||||||
* Total closing accounts ledger.
|
|
||||||
* @param {Ledger}
|
|
||||||
*/
|
|
||||||
public totalAccountsLedger: Ledger;
|
public totalAccountsLedger: Ledger;
|
||||||
|
|
||||||
/**
|
|
||||||
* Total income accounts ledger.
|
|
||||||
*/
|
|
||||||
public incomeLedger: Ledger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Total expense accounts ledger.
|
|
||||||
*/
|
|
||||||
public expensesLedger: Ledger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transactions group type.
|
* Transactions group type.
|
||||||
* @param {IAccountTransactionsGroupBy}
|
* @param {IAccountTransactionsGroupBy}
|
||||||
@@ -189,8 +171,6 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
) {
|
) {
|
||||||
await this.initPeriodsPreviousPeriod();
|
await this.initPeriodsPreviousPeriod();
|
||||||
}
|
}
|
||||||
//
|
|
||||||
await this.asyncInitializeNetIncome();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
@@ -201,7 +181,6 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
|
|
||||||
this.accounts = accounts;
|
this.accounts = accounts;
|
||||||
this.accountsByType = transformToMapBy(accounts, 'accountType');
|
this.accountsByType = transformToMapBy(accounts, 'accountType');
|
||||||
this.accountsByParentType = transformToMapBy(accounts, 'accountParentType');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
@@ -330,15 +309,14 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Closing accounts date periods.
|
* Closing accounts date periods.
|
||||||
* @param {Date} fromDate
|
* @param openingDate
|
||||||
* @param {Date} toDate
|
* @param datePeriodsType
|
||||||
* @param {string} datePeriodsType
|
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public accountsDatePeriods = async (
|
public accountsDatePeriods = async (
|
||||||
fromDate: Date,
|
fromDate: Date,
|
||||||
toDate: Date,
|
toDate: Date,
|
||||||
datePeriodsType: string
|
datePeriodsType
|
||||||
) => {
|
) => {
|
||||||
const { AccountTransaction } = this.models;
|
const { AccountTransaction } = this.models;
|
||||||
|
|
||||||
@@ -358,7 +336,6 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the opening balance transactions of the report.
|
* Retrieve the opening balance transactions of the report.
|
||||||
* @param {Date|string} openingDate -
|
|
||||||
*/
|
*/
|
||||||
public closingAccountsTotal = async (openingDate: Date | string) => {
|
public closingAccountsTotal = async (openingDate: Date | string) => {
|
||||||
const { AccountTransaction } = this.models;
|
const { AccountTransaction } = this.models;
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import { IAccount, ILedger } from '@/interfaces';
|
|
||||||
import { FinancialDatePeriods } from '../FinancialDatePeriods';
|
|
||||||
import { ACCOUNT_PARENT_TYPE } from '@/data/AccountTypes';
|
|
||||||
|
|
||||||
export const BalanceSheetRepositoryNetIncome = (Base) =>
|
|
||||||
class extends R.compose(FinancialDatePeriods)(Base) {
|
|
||||||
// -----------------------
|
|
||||||
// # Net Income
|
|
||||||
// -----------------------
|
|
||||||
public incomeAccounts: IAccount[];
|
|
||||||
public incomeAccountsIds: number[];
|
|
||||||
|
|
||||||
public expenseAccounts: IAccount[];
|
|
||||||
public expenseAccountsIds: number[];
|
|
||||||
|
|
||||||
public incomePeriodsAccountsLedger: ILedger;
|
|
||||||
public incomePeriodsOpeningAccountsLedger: ILedger;
|
|
||||||
public expensesPeriodsAccountsLedger: ILedger;
|
|
||||||
public expensesOpeningAccountLedger: ILedger;
|
|
||||||
|
|
||||||
public incomePPAccountsLedger: ILedger;
|
|
||||||
public expensePPAccountsLedger: ILedger;
|
|
||||||
|
|
||||||
public incomePPPeriodsAccountsLedger: ILedger;
|
|
||||||
public incomePPPeriodsOpeningAccountLedger: ILedger;
|
|
||||||
public expensePPPeriodsAccountsLedger: ILedger;
|
|
||||||
public expensePPPeriodsOpeningAccountLedger: ILedger;
|
|
||||||
|
|
||||||
public incomePYTotalAccountsLedger: ILedger;
|
|
||||||
public expensePYTotalAccountsLedger: ILedger;
|
|
||||||
|
|
||||||
public incomePYPeriodsAccountsLedger: ILedger;
|
|
||||||
public incomePYPeriodsOpeningAccountLedger: ILedger;
|
|
||||||
public expensePYPeriodsAccountsLedger: ILedger;
|
|
||||||
public expensePYPeriodsOpeningAccountLedger: ILedger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async initialize.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
public asyncInitializeNetIncome = async () => {
|
|
||||||
await this.initAccounts();
|
|
||||||
await this.initAccountsTotalLedger();
|
|
||||||
|
|
||||||
// Net Income
|
|
||||||
this.initIncomeAccounts();
|
|
||||||
this.initExpenseAccounts();
|
|
||||||
|
|
||||||
this.initIncomeTotalLedger();
|
|
||||||
this.initExpensesTotalLedger();
|
|
||||||
|
|
||||||
// Date periods
|
|
||||||
if (this.query.isDatePeriodsColumnsType()) {
|
|
||||||
this.initNetIncomeDatePeriods();
|
|
||||||
}
|
|
||||||
// Previous Year (PY).
|
|
||||||
if (this.query.isPreviousYearActive()) {
|
|
||||||
this.initNetIncomePreviousYear();
|
|
||||||
}
|
|
||||||
// Previous Period (PP).
|
|
||||||
if (this.query.isPreviousPeriodActive()) {
|
|
||||||
this.initNetIncomePreviousPeriod();
|
|
||||||
}
|
|
||||||
// Previous Year (PY) / Date Periods.
|
|
||||||
if (
|
|
||||||
this.query.isPreviousYearActive() &&
|
|
||||||
this.query.isDatePeriodsColumnsType()
|
|
||||||
) {
|
|
||||||
this.initNetIncomePeriodsPreviewYear();
|
|
||||||
}
|
|
||||||
// Previous Period (PP) / Date Periods.
|
|
||||||
if (
|
|
||||||
this.query.isPreviousPeriodActive() &&
|
|
||||||
this.query.isDatePeriodsColumnsType()
|
|
||||||
) {
|
|
||||||
this.initNetIncomePeriodsPreviousPeriod();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------
|
|
||||||
// # Net Income
|
|
||||||
// ----------------------------
|
|
||||||
/**
|
|
||||||
* Initialize income accounts.
|
|
||||||
*/
|
|
||||||
private initIncomeAccounts = () => {
|
|
||||||
const incomeAccounts = this.accountsByParentType.get(
|
|
||||||
ACCOUNT_PARENT_TYPE.INCOME
|
|
||||||
);
|
|
||||||
const incomeAccountsIds = incomeAccounts.map((a) => a.id);
|
|
||||||
|
|
||||||
this.incomeAccounts = incomeAccounts;
|
|
||||||
this.incomeAccountsIds = incomeAccountsIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize expense accounts.
|
|
||||||
*/
|
|
||||||
private initExpenseAccounts = () => {
|
|
||||||
const expensesAccounts = this.accountsByParentType.get(
|
|
||||||
ACCOUNT_PARENT_TYPE.EXPENSE
|
|
||||||
);
|
|
||||||
const expensesAccountsIds = expensesAccounts.map((a) => a.id);
|
|
||||||
|
|
||||||
this.expenseAccounts = expensesAccounts;
|
|
||||||
this.expenseAccountsIds = expensesAccountsIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the income total ledger.
|
|
||||||
*/
|
|
||||||
private initIncomeTotalLedger = (): void => {
|
|
||||||
// Inject to the repository.
|
|
||||||
this.incomeLedger = this.totalAccountsLedger.whereAccountsIds(
|
|
||||||
this.incomeAccountsIds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the expenses total ledger.
|
|
||||||
*/
|
|
||||||
private initExpensesTotalLedger = (): void => {
|
|
||||||
this.expensesLedger = this.totalAccountsLedger.whereAccountsIds(
|
|
||||||
this.expenseAccountsIds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------
|
|
||||||
// # Net Income - Date Periods
|
|
||||||
// ----------------------------
|
|
||||||
/**
|
|
||||||
* Initialize the net income date periods.
|
|
||||||
*/
|
|
||||||
public initNetIncomeDatePeriods = () => {
|
|
||||||
this.incomePeriodsAccountsLedger =
|
|
||||||
this.periodsAccountsLedger.whereAccountsIds(this.incomeAccountsIds);
|
|
||||||
|
|
||||||
this.incomePeriodsOpeningAccountsLedger =
|
|
||||||
this.periodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.incomeAccountsIds
|
|
||||||
);
|
|
||||||
|
|
||||||
this.expensesPeriodsAccountsLedger =
|
|
||||||
this.periodsAccountsLedger.whereAccountsIds(this.expenseAccountsIds);
|
|
||||||
|
|
||||||
this.expensesOpeningAccountLedger =
|
|
||||||
this.periodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.expenseAccountsIds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------
|
|
||||||
// # Net Income - Previous Period
|
|
||||||
// ----------------------------
|
|
||||||
/**
|
|
||||||
* Initialize the total net income PP.
|
|
||||||
*/
|
|
||||||
public initNetIncomePreviousPeriod = () => {
|
|
||||||
this.incomePPAccountsLedger = this.PPTotalAccountsLedger.whereAccountsIds(
|
|
||||||
this.incomeAccountsIds
|
|
||||||
);
|
|
||||||
this.expensePPAccountsLedger =
|
|
||||||
this.PPTotalAccountsLedger.whereAccountsIds(this.expenseAccountsIds);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the net income periods of previous period.
|
|
||||||
*/
|
|
||||||
public initNetIncomePeriodsPreviousPeriod = () => {
|
|
||||||
this.incomePPPeriodsAccountsLedger =
|
|
||||||
this.PPPeriodsAccountsLedger.whereAccountsIds(this.incomeAccountsIds);
|
|
||||||
|
|
||||||
this.incomePPPeriodsOpeningAccountLedger =
|
|
||||||
this.PPPeriodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.incomeAccountsIds
|
|
||||||
);
|
|
||||||
|
|
||||||
this.expensePPPeriodsAccountsLedger =
|
|
||||||
this.PPPeriodsAccountsLedger.whereAccountsIds(this.expenseAccountsIds);
|
|
||||||
|
|
||||||
this.expensePPPeriodsOpeningAccountLedger =
|
|
||||||
this.PPPeriodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.expenseAccountsIds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------
|
|
||||||
// # Net Income - Previous Year
|
|
||||||
// ----------------------------
|
|
||||||
/**
|
|
||||||
* Initialize the net income PY total.
|
|
||||||
*/
|
|
||||||
public initNetIncomePreviousYear = () => {
|
|
||||||
this.incomePYTotalAccountsLedger =
|
|
||||||
this.PYTotalAccountsLedger.whereAccountsIds(this.incomeAccountsIds);
|
|
||||||
|
|
||||||
this.expensePYTotalAccountsLedger =
|
|
||||||
this.PYTotalAccountsLedger.whereAccountsIds(this.expenseAccountsIds);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the net income PY periods.
|
|
||||||
*/
|
|
||||||
public initNetIncomePeriodsPreviewYear = () => {
|
|
||||||
this.incomePYPeriodsAccountsLedger =
|
|
||||||
this.PYPeriodsAccountsLedger.whereAccountsIds(this.incomeAccountsIds);
|
|
||||||
|
|
||||||
this.incomePYPeriodsOpeningAccountLedger =
|
|
||||||
this.PYPeriodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.incomeAccountsIds
|
|
||||||
);
|
|
||||||
|
|
||||||
this.expensePYPeriodsAccountsLedger =
|
|
||||||
this.PYPeriodsAccountsLedger.whereAccountsIds(this.expenseAccountsIds);
|
|
||||||
|
|
||||||
this.expensePYPeriodsOpeningAccountLedger =
|
|
||||||
this.PYPeriodsOpeningAccountLedger.whereAccountsIds(
|
|
||||||
this.expenseAccountsIds
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -7,11 +7,12 @@ import {
|
|||||||
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
||||||
import { FinancialSchema } from '../FinancialSchema';
|
import { FinancialSchema } from '../FinancialSchema';
|
||||||
|
|
||||||
|
|
||||||
export const BalanceSheetSchema = (Base) =>
|
export const BalanceSheetSchema = (Base) =>
|
||||||
class extends R.compose(FinancialSchema)(Base) {
|
class extends R.compose(FinancialSchema)(Base) {
|
||||||
/**
|
/**
|
||||||
* Retrieves the balance sheet schema.
|
* Retrieves the balance sheet schema.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
getSchema = () => {
|
getSchema = () => {
|
||||||
return getBalanceSheetSchema();
|
return getBalanceSheetSchema();
|
||||||
@@ -114,13 +115,6 @@ export const getBalanceSheetSchema = () => [
|
|||||||
id: BALANCE_SHEET_SCHEMA_NODE_ID.EQUITY,
|
id: BALANCE_SHEET_SCHEMA_NODE_ID.EQUITY,
|
||||||
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
|
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
|
||||||
accountsTypes: [ACCOUNT_TYPE.EQUITY],
|
accountsTypes: [ACCOUNT_TYPE.EQUITY],
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'balance_sheet.net_income',
|
|
||||||
id: BALANCE_SHEET_SCHEMA_NODE_ID.NET_INCOME,
|
|
||||||
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ import {
|
|||||||
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
||||||
IBalanceSheetDataNode,
|
IBalanceSheetDataNode,
|
||||||
IBalanceSheetSchemaNode,
|
IBalanceSheetSchemaNode,
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
IBalanceSheetAccountNode,
|
|
||||||
IBalanceSheetAccountsNode,
|
|
||||||
IBalanceSheetAggregateNode,
|
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import { tableRowMapper } from 'utils';
|
import { tableRowMapper } from 'utils';
|
||||||
import FinancialSheet from '../FinancialSheet';
|
import FinancialSheet from '../FinancialSheet';
|
||||||
@@ -112,13 +108,11 @@ export default class BalanceSheetTable extends R.compose(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the table row from the given report aggregate node.
|
*
|
||||||
* @param {IBalanceSheetAggregateNode} node
|
* @param node
|
||||||
* @returns {ITableRow}
|
* @returns {ITableRow}
|
||||||
*/
|
*/
|
||||||
private aggregateNodeTableRowsMapper = (
|
private aggregateNodeTableRowsMapper = (node): ITableRow => {
|
||||||
node: IBalanceSheetAggregateNode
|
|
||||||
): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
const columns = this.commonColumnsAccessors();
|
||||||
const meta = {
|
const meta = {
|
||||||
rowTypes: [IROW_TYPE.AGGREGATE],
|
rowTypes: [IROW_TYPE.AGGREGATE],
|
||||||
@@ -128,13 +122,11 @@ export default class BalanceSheetTable extends R.compose(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the table row from the given report accounts node.
|
*
|
||||||
* @param {IBalanceSheetAccountsNode} node
|
* @param node
|
||||||
* @returns {ITableRow}
|
* @returns {ITableRow}
|
||||||
*/
|
*/
|
||||||
private accountsNodeTableRowsMapper = (
|
private accountsNodeTableRowsMapper = (node): ITableRow => {
|
||||||
node: IBalanceSheetAccountsNode
|
|
||||||
): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
const columns = this.commonColumnsAccessors();
|
||||||
const meta = {
|
const meta = {
|
||||||
rowTypes: [IROW_TYPE.ACCOUNTS],
|
rowTypes: [IROW_TYPE.ACCOUNTS],
|
||||||
@@ -144,13 +136,11 @@ export default class BalanceSheetTable extends R.compose(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the table row from the given report account node.
|
*
|
||||||
* @param {IBalanceSheetAccountNode} node
|
* @param {} node
|
||||||
* @returns {ITableRow}
|
* @returns {ITableRow}
|
||||||
*/
|
*/
|
||||||
private accountNodeTableRowsMapper = (
|
private accountNodeTableRowsMapper = (node): ITableRow => {
|
||||||
node: IBalanceSheetAccountNode
|
|
||||||
): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
const columns = this.commonColumnsAccessors();
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
@@ -160,22 +150,6 @@ export default class BalanceSheetTable extends R.compose(
|
|||||||
return tableRowMapper(node, columns, meta);
|
return tableRowMapper(node, columns, meta);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the table row from the given report net income node.
|
|
||||||
* @param {IBalanceSheetNetIncomeNode} node
|
|
||||||
* @returns {ITableRow}
|
|
||||||
*/
|
|
||||||
private netIncomeNodeTableRowsMapper = (
|
|
||||||
node: IBalanceSheetNetIncomeNode
|
|
||||||
): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
|
||||||
const meta = {
|
|
||||||
rowTypes: [IROW_TYPE.NET_INCOME],
|
|
||||||
id: node.id,
|
|
||||||
};
|
|
||||||
return tableRowMapper(node, columns, meta);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mappes the given report node to table rows.
|
* Mappes the given report node to table rows.
|
||||||
* @param {IBalanceSheetDataNode} node -
|
* @param {IBalanceSheetDataNode} node -
|
||||||
@@ -195,10 +169,6 @@ export default class BalanceSheetTable extends R.compose(
|
|||||||
this.isNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT),
|
this.isNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT),
|
||||||
this.accountNodeTableRowsMapper,
|
this.accountNodeTableRowsMapper,
|
||||||
],
|
],
|
||||||
[
|
|
||||||
this.isNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME),
|
|
||||||
this.netIncomeNodeTableRowsMapper,
|
|
||||||
],
|
|
||||||
])(node);
|
])(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,5 @@ export enum IROW_TYPE {
|
|||||||
AGGREGATE = 'AGGREGATE',
|
AGGREGATE = 'AGGREGATE',
|
||||||
ACCOUNTS = 'ACCOUNTS',
|
ACCOUNTS = 'ACCOUNTS',
|
||||||
ACCOUNT = 'ACCOUNT',
|
ACCOUNT = 'ACCOUNT',
|
||||||
NET_INCOME = 'NET_INCOME',
|
|
||||||
TOTAL = 'TOTAL',
|
TOTAL = 'TOTAL',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,26 +10,13 @@ import {
|
|||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import FinancialSheet from '../FinancialSheet';
|
import FinancialSheet from '../FinancialSheet';
|
||||||
import { allPassedConditionsPass, flatToNestedArray } from 'utils';
|
import { allPassedConditionsPass, flatToNestedArray } from 'utils';
|
||||||
import { TrialBalanceSheetRepository } from './TrialBalanceSheetRepository';
|
|
||||||
|
|
||||||
export default class TrialBalanceSheet extends FinancialSheet {
|
export default class TrialBalanceSheet extends FinancialSheet {
|
||||||
/**
|
tenantId: number;
|
||||||
* Trial balance sheet query.
|
query: ITrialBalanceSheetQuery;
|
||||||
* @param {ITrialBalanceSheetQuery} query
|
accounts: IAccount & { type: IAccountType }[];
|
||||||
*/
|
journalFinancial: any;
|
||||||
private query: ITrialBalanceSheetQuery;
|
baseCurrency: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Trial balance sheet repository.
|
|
||||||
* @param {TrialBalanceSheetRepository}
|
|
||||||
*/
|
|
||||||
private repository: TrialBalanceSheetRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Organization base currency.
|
|
||||||
* @param {string}
|
|
||||||
*/
|
|
||||||
private baseCurrency: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor method.
|
* Constructor method.
|
||||||
@@ -41,58 +28,20 @@ export default class TrialBalanceSheet extends FinancialSheet {
|
|||||||
constructor(
|
constructor(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
query: ITrialBalanceSheetQuery,
|
query: ITrialBalanceSheetQuery,
|
||||||
repository: TrialBalanceSheetRepository,
|
accounts: IAccount & { type: IAccountType }[],
|
||||||
|
journalFinancial: any,
|
||||||
baseCurrency: string
|
baseCurrency: string
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.repository = repository;
|
this.accounts = accounts;
|
||||||
|
this.journalFinancial = journalFinancial;
|
||||||
this.numberFormat = this.query.numberFormat;
|
this.numberFormat = this.query.numberFormat;
|
||||||
this.baseCurrency = baseCurrency;
|
this.baseCurrency = baseCurrency;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing credit of the given account.
|
|
||||||
* @param {number} accountId
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
public getClosingAccountCredit(accountId: number) {
|
|
||||||
const depsAccountsIds =
|
|
||||||
this.repository.accountsDepGraph.dependenciesOf(accountId);
|
|
||||||
|
|
||||||
return this.repository.totalAccountsLedger
|
|
||||||
.whereAccountsIds([accountId, ...depsAccountsIds])
|
|
||||||
.getClosingCredit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing debit of the given account.
|
|
||||||
* @param {number} accountId
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
public getClosingAccountDebit(accountId: number) {
|
|
||||||
const depsAccountsIds =
|
|
||||||
this.repository.accountsDepGraph.dependenciesOf(accountId);
|
|
||||||
|
|
||||||
return this.repository.totalAccountsLedger
|
|
||||||
.whereAccountsIds([accountId, ...depsAccountsIds])
|
|
||||||
.getClosingDebit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the closing total of the given account.
|
|
||||||
* @param {number} accountId
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
public getClosingAccountTotal(accountId: number) {
|
|
||||||
const credit = this.getClosingAccountCredit(accountId);
|
|
||||||
const debit = this.getClosingAccountDebit(accountId);
|
|
||||||
|
|
||||||
return debit - credit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account mapper.
|
* Account mapper.
|
||||||
* @param {IAccount} account
|
* @param {IAccount} account
|
||||||
@@ -101,28 +50,23 @@ export default class TrialBalanceSheet extends FinancialSheet {
|
|||||||
private accountTransformer = (
|
private accountTransformer = (
|
||||||
account: IAccount & { type: IAccountType }
|
account: IAccount & { type: IAccountType }
|
||||||
): ITrialBalanceAccount => {
|
): ITrialBalanceAccount => {
|
||||||
const debit = this.getClosingAccountDebit(account.id);
|
const trial = this.journalFinancial.getTrialBalanceWithDepands(account.id);
|
||||||
const credit = this.getClosingAccountCredit(account.id);
|
|
||||||
const balance = this.getClosingAccountTotal(account.id);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: account.id,
|
id: account.id,
|
||||||
parentAccountId: account.parentAccountId,
|
parentAccountId: account.parentAccountId,
|
||||||
name: account.name,
|
name: account.name,
|
||||||
formattedName: account.code
|
|
||||||
? `${account.name} - ${account.code}`
|
|
||||||
: `${account.name}`,
|
|
||||||
code: account.code,
|
code: account.code,
|
||||||
accountNormal: account.accountNormal,
|
accountNormal: account.accountNormal,
|
||||||
|
|
||||||
credit,
|
credit: trial.credit,
|
||||||
debit,
|
debit: trial.debit,
|
||||||
balance,
|
balance: trial.balance,
|
||||||
currencyCode: this.baseCurrency,
|
currencyCode: this.baseCurrency,
|
||||||
|
|
||||||
formattedCredit: this.formatNumber(credit),
|
formattedCredit: this.formatNumber(trial.credit),
|
||||||
formattedDebit: this.formatNumber(debit),
|
formattedDebit: this.formatNumber(trial.debit),
|
||||||
formattedBalance: this.formatNumber(balance),
|
formattedBalance: this.formatNumber(trial.balance),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,7 +117,10 @@ export default class TrialBalanceSheet extends FinancialSheet {
|
|||||||
private filterNoneTransactions = (
|
private filterNoneTransactions = (
|
||||||
accountNode: ITrialBalanceAccount
|
accountNode: ITrialBalanceAccount
|
||||||
): boolean => {
|
): boolean => {
|
||||||
return false === this.repository.totalAccountsLedger.isEmpty();
|
const entries = this.journalFinancial.getAccountEntriesWithDepents(
|
||||||
|
accountNode.id
|
||||||
|
);
|
||||||
|
return entries.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,11 +200,11 @@ export default class TrialBalanceSheet extends FinancialSheet {
|
|||||||
*/
|
*/
|
||||||
public reportData(): ITrialBalanceSheetData {
|
public reportData(): ITrialBalanceSheetData {
|
||||||
// Don't return noting if the journal has no transactions.
|
// Don't return noting if the journal has no transactions.
|
||||||
if (this.repository.totalAccountsLedger.isEmpty()) {
|
if (this.journalFinancial.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Retrieve accounts nodes.
|
// Retrieve accounts nodes.
|
||||||
const accounts = this.accountsSection(this.repository.accounts);
|
const accounts = this.accountsSection(this.accounts);
|
||||||
|
|
||||||
// Retrieve account node.
|
// Retrieve account node.
|
||||||
const total = this.tatalSection(accounts);
|
const total = this.tatalSection(accounts);
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
import { ITrialBalanceSheetQuery } from '@/interfaces';
|
|
||||||
import Ledger from '@/services/Accounting/Ledger';
|
|
||||||
import { Knex } from 'knex';
|
|
||||||
import { isEmpty } from 'lodash';
|
|
||||||
import { Service } from 'typedi';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class TrialBalanceSheetRepository {
|
|
||||||
private query: ITrialBalanceSheetQuery;
|
|
||||||
private models: any;
|
|
||||||
public accounts: any;
|
|
||||||
public accountsDepGraph;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Total closing accounts ledger.
|
|
||||||
* @param {Ledger}
|
|
||||||
*/
|
|
||||||
public totalAccountsLedger: Ledger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor method.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {IBalanceSheetQuery} query
|
|
||||||
*/
|
|
||||||
constructor(models: any, repos: any, query: ITrialBalanceSheetQuery) {
|
|
||||||
this.query = query;
|
|
||||||
this.repos = repos;
|
|
||||||
this.models = models;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async initialize.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
public asyncInitialize = async () => {
|
|
||||||
await this.initAccounts();
|
|
||||||
await this.initAccountsClosingTotalLedger();
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------
|
|
||||||
// # Accounts
|
|
||||||
// ----------------------------
|
|
||||||
/**
|
|
||||||
* Initialize accounts.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
public initAccounts = async () => {
|
|
||||||
const accounts = await this.getAccounts();
|
|
||||||
const accountsDepGraph =
|
|
||||||
await this.repos.accountRepository.getDependencyGraph();
|
|
||||||
|
|
||||||
this.accountsDepGraph = accountsDepGraph;
|
|
||||||
this.accounts = accounts;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize all accounts closing total ledger.
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
public initAccountsClosingTotalLedger = async (): Promise<void> => {
|
|
||||||
const totalByAccounts = await this.closingAccountsTotal(this.query.toDate);
|
|
||||||
|
|
||||||
this.totalAccountsLedger = Ledger.fromTransactions(totalByAccounts);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve accounts of the report.
|
|
||||||
* @return {Promise<IAccount[]>}
|
|
||||||
*/
|
|
||||||
private getAccounts = () => {
|
|
||||||
const { Account } = this.models;
|
|
||||||
|
|
||||||
return Account.query();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the opening balance transactions of the report.
|
|
||||||
* @param {Date|string} openingDate -
|
|
||||||
*/
|
|
||||||
public closingAccountsTotal = async (openingDate: Date | string) => {
|
|
||||||
const { AccountTransaction } = this.models;
|
|
||||||
|
|
||||||
return AccountTransaction.query().onBuild((query) => {
|
|
||||||
query.sum('credit as credit');
|
|
||||||
query.sum('debit as debit');
|
|
||||||
query.groupBy('accountId');
|
|
||||||
query.select(['accountId']);
|
|
||||||
|
|
||||||
query.modify('filterDateRange', null, openingDate);
|
|
||||||
query.withGraphFetched('account');
|
|
||||||
|
|
||||||
this.commonFilterBranchesQuery(query);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common branches filter query.
|
|
||||||
* @param {Knex.QueryBuilder} query
|
|
||||||
*/
|
|
||||||
private commonFilterBranchesQuery = (query: Knex.QueryBuilder) => {
|
|
||||||
if (!isEmpty(this.query.branchesIds)) {
|
|
||||||
query.modify('filterByBranches', this.query.branchesIds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -2,18 +2,12 @@ import { Service, Inject } from 'typedi';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import TenancyService from '@/services/Tenancy/TenancyService';
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import Journal from '@/services/Accounting/JournalPoster';
|
import Journal from '@/services/Accounting/JournalPoster';
|
||||||
import {
|
import { ITrialBalanceSheetMeta, ITrialBalanceSheetQuery, ITrialBalanceStatement } from '@/interfaces';
|
||||||
ITrialBalanceSheetMeta,
|
|
||||||
ITrialBalanceSheetQuery,
|
|
||||||
ITrialBalanceStatement,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import TrialBalanceSheet from './TrialBalanceSheet';
|
import TrialBalanceSheet from './TrialBalanceSheet';
|
||||||
import FinancialSheet from '../FinancialSheet';
|
import FinancialSheet from '../FinancialSheet';
|
||||||
import InventoryService from '@/services/Inventory/Inventory';
|
import InventoryService from '@/services/Inventory/Inventory';
|
||||||
import { parseBoolean } from 'utils';
|
import { parseBoolean } from 'utils';
|
||||||
import { Tenant } from '@/system/models';
|
import { Tenant } from '@/system/models';
|
||||||
import { TrialBalanceSheetRepository } from './TrialBalanceSheetRepository';
|
|
||||||
import { TrialBalanceSheetTable } from './TrialBalanceSheetTable';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class TrialBalanceSheetService extends FinancialSheet {
|
export default class TrialBalanceSheetService extends FinancialSheet {
|
||||||
@@ -57,8 +51,9 @@ export default class TrialBalanceSheetService extends FinancialSheet {
|
|||||||
reportMetadata(tenantId: number): ITrialBalanceSheetMeta {
|
reportMetadata(tenantId: number): ITrialBalanceSheetMeta {
|
||||||
const settings = this.tenancy.settings(tenantId);
|
const settings = this.tenancy.settings(tenantId);
|
||||||
|
|
||||||
const isCostComputeRunning =
|
const isCostComputeRunning = this.inventoryService.isItemsCostComputeRunning(
|
||||||
this.inventoryService.isItemsCostComputeRunning(tenantId);
|
tenantId
|
||||||
|
);
|
||||||
const organizationName = settings.get({
|
const organizationName = settings.get({
|
||||||
group: 'organization',
|
group: 'organization',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
@@ -77,8 +72,10 @@ export default class TrialBalanceSheetService extends FinancialSheet {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve trial balance sheet statement.
|
* Retrieve trial balance sheet statement.
|
||||||
|
* -------------
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {IBalanceSheetQuery} query
|
* @param {IBalanceSheetQuery} query
|
||||||
|
*
|
||||||
* @return {IBalanceSheetStatement}
|
* @return {IBalanceSheetStatement}
|
||||||
*/
|
*/
|
||||||
public async trialBalanceSheet(
|
public async trialBalanceSheet(
|
||||||
@@ -89,27 +86,43 @@ export default class TrialBalanceSheetService extends FinancialSheet {
|
|||||||
...this.defaultQuery,
|
...this.defaultQuery,
|
||||||
...query,
|
...query,
|
||||||
};
|
};
|
||||||
|
const {
|
||||||
|
accountRepository,
|
||||||
|
transactionsRepository,
|
||||||
|
} = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
const tenant = await Tenant.query()
|
const tenant = await Tenant.query()
|
||||||
.findById(tenantId)
|
.findById(tenantId)
|
||||||
.withGraphFetched('metadata');
|
.withGraphFetched('metadata');
|
||||||
|
|
||||||
const models = this.tenancy.models(tenantId);
|
this.logger.info('[trial_balance_sheet] trying to calcualte the report.', {
|
||||||
const repos = this.tenancy.repositories(tenantId);
|
tenantId,
|
||||||
|
filter,
|
||||||
|
});
|
||||||
|
// Retrieve all accounts on the storage.
|
||||||
|
const accounts = await accountRepository.all();
|
||||||
|
const accountsGraph = await accountRepository.getDependencyGraph();
|
||||||
|
|
||||||
const trialBalanceSheetRepos = new TrialBalanceSheetRepository(
|
// Retrieve all journal transactions based on the given query.
|
||||||
models,
|
const transactions = await transactionsRepository.journal({
|
||||||
repos,
|
fromDate: query.fromDate,
|
||||||
filter
|
toDate: query.toDate,
|
||||||
|
sumationCreditDebit: true,
|
||||||
|
branchesIds: query.branchesIds
|
||||||
|
});
|
||||||
|
// Transform transactions array to journal collection.
|
||||||
|
const transactionsJournal = Journal.fromTransactions(
|
||||||
|
transactions,
|
||||||
|
tenantId,
|
||||||
|
accountsGraph
|
||||||
);
|
);
|
||||||
await trialBalanceSheetRepos.asyncInitialize();
|
|
||||||
|
|
||||||
// Trial balance report instance.
|
// Trial balance report instance.
|
||||||
const trialBalanceInstance = new TrialBalanceSheet(
|
const trialBalanceInstance = new TrialBalanceSheet(
|
||||||
tenantId,
|
tenantId,
|
||||||
filter,
|
filter,
|
||||||
trialBalanceSheetRepos,
|
accounts,
|
||||||
tenant.metadata.baseCurrency
|
transactionsJournal,
|
||||||
|
tenant.metadata.baseCurrency,
|
||||||
);
|
);
|
||||||
// Trial balance sheet data.
|
// Trial balance sheet data.
|
||||||
const trialBalanceSheetData = trialBalanceInstance.reportData();
|
const trialBalanceSheetData = trialBalanceInstance.reportData();
|
||||||
@@ -120,27 +133,4 @@ export default class TrialBalanceSheetService extends FinancialSheet {
|
|||||||
meta: this.reportMetadata(tenantId),
|
meta: this.reportMetadata(tenantId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the trial balance sheet table.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {ITrialBalanceSheetQuery} query
|
|
||||||
* @returns {Promise<any>}
|
|
||||||
*/
|
|
||||||
public async trialBalanceSheetTable(
|
|
||||||
tenantId: number,
|
|
||||||
query: ITrialBalanceSheetQuery
|
|
||||||
) {
|
|
||||||
const trialBalance = await this.trialBalanceSheet(tenantId, query);
|
|
||||||
const table = new TrialBalanceSheetTable(trialBalance.data, query, {});
|
|
||||||
|
|
||||||
return {
|
|
||||||
table: {
|
|
||||||
columns: table.tableColumns(),
|
|
||||||
rows: table.tableRows(),
|
|
||||||
},
|
|
||||||
meta: trialBalance.meta,
|
|
||||||
query: trialBalance.query,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
import * as R from 'ramda';
|
|
||||||
import FinancialSheet from '../FinancialSheet';
|
|
||||||
import { FinancialTable } from '../FinancialTable';
|
|
||||||
import {
|
|
||||||
IBalanceSheetStatementData,
|
|
||||||
ITableColumn,
|
|
||||||
ITableColumnAccessor,
|
|
||||||
ITableRow,
|
|
||||||
ITrialBalanceAccount,
|
|
||||||
ITrialBalanceSheetData,
|
|
||||||
ITrialBalanceSheetQuery,
|
|
||||||
ITrialBalanceTotal,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { tableRowMapper } from '@/utils';
|
|
||||||
import { IROW_TYPE } from '../BalanceSheet/constants';
|
|
||||||
import { FinancialSheetStructure } from '../FinancialSheetStructure';
|
|
||||||
|
|
||||||
export class TrialBalanceSheetTable extends R.compose(
|
|
||||||
FinancialTable,
|
|
||||||
FinancialSheetStructure
|
|
||||||
)(FinancialSheet) {
|
|
||||||
/**
|
|
||||||
* @param {ITrialBalanceSheetData}
|
|
||||||
*/
|
|
||||||
public data: ITrialBalanceSheetData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Balance sheet query.
|
|
||||||
* @param {ITrialBalanceSheetQuery}
|
|
||||||
*/
|
|
||||||
public query: ITrialBalanceSheetQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor method.
|
|
||||||
* @param {IBalanceSheetStatementData} reportData -
|
|
||||||
* @param {ITrialBalanceSheetQuery} query -
|
|
||||||
*/
|
|
||||||
constructor(
|
|
||||||
data: ITrialBalanceSheetData,
|
|
||||||
query: ITrialBalanceSheetQuery,
|
|
||||||
i18n: any
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.data = data;
|
|
||||||
this.query = query;
|
|
||||||
this.i18n = i18n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the common columns for all report nodes.
|
|
||||||
* @param {ITableColumnAccessor[]}
|
|
||||||
*/
|
|
||||||
private commonColumnsAccessors = (): ITableColumnAccessor[] => {
|
|
||||||
return [
|
|
||||||
{ key: 'account', accessor: 'formattedName' },
|
|
||||||
{ key: 'debit', accessor: 'formattedDebit' },
|
|
||||||
{ key: 'credit', accessor: 'formattedCredit' },
|
|
||||||
{ key: 'total', accessor: 'formattedBalance' },
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps the account node to table row.
|
|
||||||
* @param {ITrialBalanceAccount} node -
|
|
||||||
* @returns {ITableRow}
|
|
||||||
*/
|
|
||||||
private accountNodeTableRowsMapper = (
|
|
||||||
node: ITrialBalanceAccount
|
|
||||||
): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
|
||||||
const meta = {
|
|
||||||
rowTypes: [IROW_TYPE.ACCOUNT],
|
|
||||||
id: node.id,
|
|
||||||
};
|
|
||||||
return tableRowMapper(node, columns, meta);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps the total node to table row.
|
|
||||||
* @param {ITrialBalanceTotal} node -
|
|
||||||
* @returns {ITableRow}
|
|
||||||
*/
|
|
||||||
private totalNodeTableRowsMapper = (node: ITrialBalanceTotal): ITableRow => {
|
|
||||||
const columns = this.commonColumnsAccessors();
|
|
||||||
const meta = {
|
|
||||||
rowTypes: [IROW_TYPE.TOTAL],
|
|
||||||
id: node.id,
|
|
||||||
};
|
|
||||||
return tableRowMapper(node, columns, meta);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mappes the given report sections to table rows.
|
|
||||||
* @param {IBalanceSheetDataNode[]} nodes -
|
|
||||||
* @return {ITableRow}
|
|
||||||
*/
|
|
||||||
private accountsToTableRowsMap = (
|
|
||||||
nodes: ITrialBalanceAccount[]
|
|
||||||
): ITableRow[] => {
|
|
||||||
return this.mapNodesDeep(nodes, this.accountNodeTableRowsMapper);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the accounts table rows of the given report data.
|
|
||||||
* @returns {ITableRow[]}
|
|
||||||
*/
|
|
||||||
private accountsTableRows = (): ITableRow[] => {
|
|
||||||
return this.accountsToTableRowsMap(this.data.accounts);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps the given total node to table row.
|
|
||||||
* @returns {ITableRow}
|
|
||||||
*/
|
|
||||||
private totalTableRow = (): ITableRow => {
|
|
||||||
return this.totalNodeTableRowsMapper(this.data.total);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the table rows.
|
|
||||||
* @returns {ITableRow[]}
|
|
||||||
*/
|
|
||||||
public tableRows = (): ITableRow[] => {
|
|
||||||
return R.compose(
|
|
||||||
R.append(this.totalTableRow()),
|
|
||||||
R.concat(this.accountsTableRows())
|
|
||||||
)([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrrieves the table columns.
|
|
||||||
* @returns {ITableColumn[]}
|
|
||||||
*/
|
|
||||||
public tableColumns = (): ITableColumn[] => {
|
|
||||||
return R.compose(
|
|
||||||
this.tableColumnsCellIndexing,
|
|
||||||
R.concat([
|
|
||||||
{ key: 'account_name', label: 'Account' },
|
|
||||||
{ key: 'debit', label: 'Debit' },
|
|
||||||
{ key: 'credit', label: 'Credit' },
|
|
||||||
{ key: 'total', label: 'Total' },
|
|
||||||
])
|
|
||||||
)([]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
export enum IROW_TYPE {
|
|
||||||
ACCOUNT = 'ACCOUNT',
|
|
||||||
TOTAL = 'TOTAL',
|
|
||||||
}
|
|
||||||
@@ -55,18 +55,6 @@ export class CreateItem {
|
|||||||
itemDTO.inventoryAccountId
|
itemDTO.inventoryAccountId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (itemDTO.purchaseTaxRateId) {
|
|
||||||
await this.validators.validatePurchaseTaxRateExistance(
|
|
||||||
tenantId,
|
|
||||||
itemDTO.purchaseTaxRateId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (itemDTO.sellTaxRateId) {
|
|
||||||
await this.validators.validateSellTaxRateExistance(
|
|
||||||
tenantId,
|
|
||||||
itemDTO.sellTaxRateId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,20 +76,6 @@ export class EditItem {
|
|||||||
itemDTO.inventoryAccountId
|
itemDTO.inventoryAccountId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Validate the purchase tax rate id existance.
|
|
||||||
if (itemDTO.purchaseTaxRateId) {
|
|
||||||
await this.validators.validatePurchaseTaxRateExistance(
|
|
||||||
tenantId,
|
|
||||||
itemDTO.purchaseTaxRateId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Validate the sell tax rate id existance.
|
|
||||||
if (itemDTO.sellTaxRateId) {
|
|
||||||
await this.validators.validateSellTaxRateExistance(
|
|
||||||
tenantId,
|
|
||||||
itemDTO.sellTaxRateId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Validate inventory account should be modified in inventory item
|
// Validate inventory account should be modified in inventory item
|
||||||
// has inventory transactions.
|
// has inventory transactions.
|
||||||
await this.validators.validateItemInvnetoryAccountModified(
|
await this.validators.validateItemInvnetoryAccountModified(
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ export class GetItem {
|
|||||||
.withGraphFetched('category')
|
.withGraphFetched('category')
|
||||||
.withGraphFetched('costAccount')
|
.withGraphFetched('costAccount')
|
||||||
.withGraphFetched('itemWarehouses.warehouse')
|
.withGraphFetched('itemWarehouses.warehouse')
|
||||||
.withGraphFetched('sellTaxRate')
|
|
||||||
.withGraphFetched('purchaseTaxRate')
|
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
return this.transformer.transform(tenantId, item, new ItemTransformer());
|
return this.transformer.transform(tenantId, item, new ItemTransformer());
|
||||||
|
|||||||
@@ -241,40 +241,4 @@ export class ItemsValidators {
|
|||||||
throw new ServiceError(ERRORS.ITEM_CANNOT_CHANGE_INVENTORY_TYPE);
|
throw new ServiceError(ERRORS.ITEM_CANNOT_CHANGE_INVENTORY_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the purchase tax rate id existance.
|
|
||||||
* @param {number} tenantId -
|
|
||||||
* @param {number} taxRateId -
|
|
||||||
*/
|
|
||||||
public async validatePurchaseTaxRateExistance(
|
|
||||||
tenantId: number,
|
|
||||||
taxRateId: number
|
|
||||||
) {
|
|
||||||
const { TaxRate } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
const foundTaxRate = await TaxRate.query().findById(taxRateId);
|
|
||||||
|
|
||||||
if (!foundTaxRate) {
|
|
||||||
throw new ServiceError(ERRORS.PURCHASE_TAX_RATE_NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the sell tax rate id existance.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} taxRateId
|
|
||||||
*/
|
|
||||||
public async validateSellTaxRateExistance(
|
|
||||||
tenantId: number,
|
|
||||||
taxRateId: number
|
|
||||||
) {
|
|
||||||
const { TaxRate } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
const foundTaxRate = await TaxRate.query().findById(taxRateId);
|
|
||||||
|
|
||||||
if (!foundTaxRate) {
|
|
||||||
throw new ServiceError(ERRORS.SELL_TAX_RATE_NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ export const ERRORS = {
|
|||||||
TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS',
|
TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS',
|
||||||
INVENTORY_ACCOUNT_CANNOT_MODIFIED: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED',
|
INVENTORY_ACCOUNT_CANNOT_MODIFIED: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED',
|
||||||
|
|
||||||
ITEM_HAS_ASSOCIATED_TRANSACTIONS: 'ITEM_HAS_ASSOCIATED_TRANSACTIONS',
|
ITEM_HAS_ASSOCIATED_TRANSACTIONS: 'ITEM_HAS_ASSOCIATED_TRANSACTIONS'
|
||||||
|
|
||||||
PURCHASE_TAX_RATE_NOT_FOUND: 'PURCHASE_TAX_RATE_NOT_FOUND',
|
|
||||||
SELL_TAX_RATE_NOT_FOUND: 'SELL_TAX_RATE_NOT_FOUND',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_VIEW_COLUMNS = [];
|
export const DEFAULT_VIEW_COLUMNS = [];
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ export class BillPaymentGLEntries {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the payment GL payable entry.
|
* Retrieves the payment GL payable entry.
|
||||||
* @param {IBillPayment} billPayment
|
* @param {IBillPayment} billPayment
|
||||||
* @param {number} APAccountId
|
* @param {number} APAccountId
|
||||||
* @returns {ILedgerEntry}
|
* @returns {ILedgerEntry}
|
||||||
*/
|
*/
|
||||||
private getPaymentGLPayableEntry = (
|
private getPaymentGLPayableEntry = (
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
import { BranchTransactionDTOTransform } from '@/services/Branches/Integrations/BranchTransactionDTOTransform';
|
import { BranchTransactionDTOTransform } from '@/services/Branches/Integrations/BranchTransactionDTOTransform';
|
||||||
import { WarehouseTransactionDTOTransform } from '@/services/Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
import { WarehouseTransactionDTOTransform } from '@/services/Warehouses/Integrations/WarehouseTransactionDTOTransform';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { ItemEntriesTaxTransactions } from '@/services/TaxRates/ItemEntriesTaxTransactions';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class BillDTOTransformer {
|
export class BillDTOTransformer {
|
||||||
@@ -24,9 +23,6 @@ export class BillDTOTransformer {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private warehouseDTOTransform: WarehouseTransactionDTOTransform;
|
private warehouseDTOTransform: WarehouseTransactionDTOTransform;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private taxDTOTransformer: ItemEntriesTaxTransactions;
|
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
private tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
@@ -77,24 +73,14 @@ export class BillDTOTransformer {
|
|||||||
const billNumber = billDTO.billNumber || oldBill?.billNumber;
|
const billNumber = billDTO.billNumber || oldBill?.billNumber;
|
||||||
|
|
||||||
const initialEntries = billDTO.entries.map((entry) => ({
|
const initialEntries = billDTO.entries.map((entry) => ({
|
||||||
referenceType: 'Bill',
|
reference_type: 'Bill',
|
||||||
isInclusiveTax: billDTO.isInclusiveTax,
|
|
||||||
...omit(entry, ['amount']),
|
...omit(entry, ['amount']),
|
||||||
}));
|
}));
|
||||||
const asyncEntries = await composeAsync(
|
const entries = await composeAsync(
|
||||||
// Associate tax rate from tax id to entries.
|
|
||||||
this.taxDTOTransformer.assocTaxRateFromTaxIdToEntries(tenantId),
|
|
||||||
// Associate tax rate id from tax code to entries.
|
|
||||||
this.taxDTOTransformer.assocTaxRateIdFromCodeToEntries(tenantId),
|
|
||||||
// Sets the default cost account to the bill entries.
|
// Sets the default cost account to the bill entries.
|
||||||
this.setBillEntriesDefaultAccounts(tenantId)
|
this.setBillEntriesDefaultAccounts(tenantId)
|
||||||
)(initialEntries);
|
)(initialEntries);
|
||||||
|
|
||||||
const entries = R.compose(
|
|
||||||
// Remove tax code from entries.
|
|
||||||
R.map(R.omit(['taxCode']))
|
|
||||||
)(asyncEntries);
|
|
||||||
|
|
||||||
const initialDTO = {
|
const initialDTO = {
|
||||||
...formatDateFields(omit(billDTO, ['open', 'entries']), [
|
...formatDateFields(omit(billDTO, ['open', 'entries']), [
|
||||||
'billDate',
|
'billDate',
|
||||||
@@ -114,8 +100,6 @@ export class BillDTOTransformer {
|
|||||||
userId: authorizedUser.id,
|
userId: authorizedUser.id,
|
||||||
};
|
};
|
||||||
return R.compose(
|
return R.compose(
|
||||||
// Associates tax amount withheld to the model.
|
|
||||||
this.taxDTOTransformer.assocTaxAmountWithheldFromEntries,
|
|
||||||
this.branchDTOTransform.transformDTO(tenantId),
|
this.branchDTOTransform.transformDTO(tenantId),
|
||||||
this.warehouseDTOTransform.transformDTO(tenantId)
|
this.warehouseDTOTransform.transformDTO(tenantId)
|
||||||
)(initialDTO);
|
)(initialDTO);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { AccountNormal, IBill, IItemEntry, ILedgerEntry } from '@/interfaces';
|
|||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import Ledger from '@/services/Accounting/Ledger';
|
import Ledger from '@/services/Accounting/Ledger';
|
||||||
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||||
import ItemsEntriesService from '@/services/Items/ItemsEntriesService';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class BillGLEntries {
|
export class BillGLEntries {
|
||||||
@@ -17,9 +16,6 @@ export class BillGLEntries {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private ledgerStorage: LedgerStorageService;
|
private ledgerStorage: LedgerStorageService;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private itemsEntriesService: ItemsEntriesService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates bill GL entries.
|
* Creates bill GL entries.
|
||||||
* @param {number} tenantId -
|
* @param {number} tenantId -
|
||||||
@@ -47,16 +43,8 @@ export class BillGLEntries {
|
|||||||
{},
|
{},
|
||||||
trx
|
trx
|
||||||
);
|
);
|
||||||
// Find or create tax payable account.
|
const billLedger = this.getBillLedger(bill, APAccount.id);
|
||||||
const taxPayableAccount = await accountRepository.findOrCreateTaxPayable(
|
|
||||||
{},
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
const billLedger = this.getBillLedger(
|
|
||||||
bill,
|
|
||||||
APAccount.id,
|
|
||||||
taxPayableAccount.id
|
|
||||||
);
|
|
||||||
// Commit the GL enties on the storage.
|
// Commit the GL enties on the storage.
|
||||||
await this.ledgerStorage.commit(tenantId, billLedger, trx);
|
await this.ledgerStorage.commit(tenantId, billLedger, trx);
|
||||||
};
|
};
|
||||||
@@ -95,7 +83,7 @@ export class BillGLEntries {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the bill common entry.
|
* Retrieves the bill common entry.
|
||||||
* @param {IBill} bill
|
* @param {IBill} bill
|
||||||
* @returns {ILedgerEntry}
|
* @returns {ILedgerEntry}
|
||||||
*/
|
*/
|
||||||
private getBillCommonEntry = (bill: IBill) => {
|
private getBillCommonEntry = (bill: IBill) => {
|
||||||
@@ -131,7 +119,7 @@ export class BillGLEntries {
|
|||||||
(bill: IBill, entry: IItemEntry, index: number): ILedgerEntry => {
|
(bill: IBill, entry: IItemEntry, index: number): ILedgerEntry => {
|
||||||
const commonJournalMeta = this.getBillCommonEntry(bill);
|
const commonJournalMeta = this.getBillCommonEntry(bill);
|
||||||
|
|
||||||
const localAmount = bill.exchangeRate * entry.amountExludingTax;
|
const localAmount = bill.exchangeRate * entry.amount;
|
||||||
const landedCostAmount = sumBy(entry.allocatedCostEntries, 'cost');
|
const landedCostAmount = sumBy(entry.allocatedCostEntries, 'cost');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -185,7 +173,7 @@ export class BillGLEntries {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...commonJournalMeta,
|
...commonJournalMeta,
|
||||||
credit: bill.totalLocal,
|
credit: bill.localAmount,
|
||||||
accountId: payableAccountId,
|
accountId: payableAccountId,
|
||||||
contactId: bill.vendorId,
|
contactId: bill.vendorId,
|
||||||
accountNormal: AccountNormal.CREDIT,
|
accountNormal: AccountNormal.CREDIT,
|
||||||
@@ -194,62 +182,15 @@ export class BillGLEntries {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bill tax GL entry.
|
|
||||||
* @param {IBill} bill -
|
|
||||||
* @param {number} taxPayableAccountId -
|
|
||||||
* @param {IItemEntry} entry -
|
|
||||||
* @param {number} index -
|
|
||||||
* @returns {ILedgerEntry}
|
|
||||||
*/
|
|
||||||
private getBillTaxEntry = R.curry(
|
|
||||||
(
|
|
||||||
bill: IBill,
|
|
||||||
taxPayableAccountId: number,
|
|
||||||
entry: IItemEntry,
|
|
||||||
index: number
|
|
||||||
): ILedgerEntry => {
|
|
||||||
const commonJournalMeta = this.getBillCommonEntry(bill);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...commonJournalMeta,
|
|
||||||
debit: entry.taxAmount,
|
|
||||||
index,
|
|
||||||
indexGroup: 30,
|
|
||||||
accountId: taxPayableAccountId,
|
|
||||||
accountNormal: AccountNormal.CREDIT,
|
|
||||||
taxRateId: entry.taxRateId,
|
|
||||||
taxRate: entry.taxRate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bill tax GL entries.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @param {number} taxPayableAccountId
|
|
||||||
* @returns {ILedgerEntry[]}
|
|
||||||
*/
|
|
||||||
private getBillTaxEntries = (bill: IBill, taxPayableAccountId: number) => {
|
|
||||||
// Retrieves the non-zero tax entries.
|
|
||||||
const nonZeroTaxEntries = this.itemsEntriesService.getNonZeroEntries(
|
|
||||||
bill.entries
|
|
||||||
);
|
|
||||||
const transformTaxEntry = this.getBillTaxEntry(bill, taxPayableAccountId);
|
|
||||||
|
|
||||||
return nonZeroTaxEntries.map(transformTaxEntry);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the given bill GL entries.
|
* Retrieves the given bill GL entries.
|
||||||
* @param {IBill} bill
|
* @param {IBill} bill
|
||||||
* @param {number} payableAccountId
|
* @param {number} payableAccountId
|
||||||
* @returns {ILedgerEntry[]}
|
* @returns {ILedgerEntry[]}
|
||||||
*/
|
*/
|
||||||
private getBillGLEntries = (
|
private getBillGLEntries = (
|
||||||
bill: IBill,
|
bill: IBill,
|
||||||
payableAccountId: number,
|
payableAccountId: number
|
||||||
taxPayableAccountId: number
|
|
||||||
): ILedgerEntry[] => {
|
): ILedgerEntry[] => {
|
||||||
const payableEntry = this.getBillPayableEntry(payableAccountId, bill);
|
const payableEntry = this.getBillPayableEntry(payableAccountId, bill);
|
||||||
|
|
||||||
@@ -260,28 +201,18 @@ export class BillGLEntries {
|
|||||||
const landedCostEntries = bill.locatedLandedCosts.map(
|
const landedCostEntries = bill.locatedLandedCosts.map(
|
||||||
landedCostTransformer
|
landedCostTransformer
|
||||||
);
|
);
|
||||||
const taxEntries = this.getBillTaxEntries(bill, taxPayableAccountId);
|
|
||||||
|
|
||||||
// Allocate cost entries journal entries.
|
// Allocate cost entries journal entries.
|
||||||
return [payableEntry, ...itemsEntries, ...landedCostEntries, ...taxEntries];
|
return [payableEntry, ...itemsEntries, ...landedCostEntries];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the given bill ledger.
|
* Retrieves the given bill ledger.
|
||||||
* @param {IBill} bill
|
* @param {IBill} bill
|
||||||
* @param {number} payableAccountId
|
* @param {number} payableAccountId
|
||||||
* @returns {Ledger}
|
* @returns {Ledger}
|
||||||
*/
|
*/
|
||||||
private getBillLedger = (
|
private getBillLedger = (bill: IBill, payableAccountId: number) => {
|
||||||
bill: IBill,
|
const entries = this.getBillGLEntries(bill, payableAccountId);
|
||||||
payableAccountId: number,
|
|
||||||
taxPayableAccountId: number
|
|
||||||
) => {
|
|
||||||
const entries = this.getBillGLEntries(
|
|
||||||
bill,
|
|
||||||
payableAccountId,
|
|
||||||
taxPayableAccountId
|
|
||||||
);
|
|
||||||
|
|
||||||
return new Ledger(entries);
|
return new Ledger(entries);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ export class GetBill {
|
|||||||
.findById(billId)
|
.findById(billId)
|
||||||
.withGraphFetched('vendor')
|
.withGraphFetched('vendor')
|
||||||
.withGraphFetched('entries.item')
|
.withGraphFetched('entries.item')
|
||||||
.withGraphFetched('branch')
|
.withGraphFetched('branch');
|
||||||
.withGraphFetched('taxes.taxRate');
|
|
||||||
|
|
||||||
// Validates the bill existance.
|
// Validates the bill existance.
|
||||||
this.validators.validateBillExistance(bill);
|
this.validators.validateBillExistance(bill);
|
||||||
|
|||||||
@@ -1,42 +1,27 @@
|
|||||||
import { IBill } from '@/interfaces';
|
import { IBill } from '@/interfaces';
|
||||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||||
import { SaleInvoiceTaxEntryTransformer } from '@/services/Sales/Invoices/SaleInvoiceTaxEntryTransformer';
|
|
||||||
import { formatNumber } from 'utils';
|
import { formatNumber } from 'utils';
|
||||||
|
|
||||||
export class PurchaseInvoiceTransformer extends Transformer {
|
export class PurchaseInvoiceTransformer extends Transformer {
|
||||||
/**
|
/**
|
||||||
* Include these attributes to sale bill object.
|
* Include these attributes to sale invoice object.
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
public includeAttributes = (): string[] => {
|
public includeAttributes = (): string[] => {
|
||||||
return [
|
return [
|
||||||
'formattedBillDate',
|
'formattedBillDate',
|
||||||
'formattedDueDate',
|
'formattedDueDate',
|
||||||
|
'formattedAmount',
|
||||||
'formattedPaymentAmount',
|
'formattedPaymentAmount',
|
||||||
'formattedBalance',
|
'formattedBalance',
|
||||||
'formattedDueAmount',
|
'formattedDueAmount',
|
||||||
'formattedExchangeRate',
|
'formattedExchangeRate',
|
||||||
'subtotalFormatted',
|
|
||||||
'subtotalLocalFormatted',
|
|
||||||
'subtotalExcludingTaxFormatted',
|
|
||||||
'taxAmountWithheldLocalFormatted',
|
|
||||||
'totalFormatted',
|
|
||||||
'totalLocalFormatted',
|
|
||||||
'taxes',
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excluded attributes.
|
* Retrieve formatted invoice date.
|
||||||
* @returns {string[]}
|
* @param {IBill} invoice
|
||||||
*/
|
|
||||||
public excludeAttributes = (): string[] => {
|
|
||||||
return ['amount', 'amountLocal', 'localAmount'];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve formatted bill date.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
protected formattedBillDate = (bill: IBill): string => {
|
protected formattedBillDate = (bill: IBill): string => {
|
||||||
@@ -44,8 +29,8 @@ export class PurchaseInvoiceTransformer extends Transformer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted bill date.
|
* Retrieve formatted invoice date.
|
||||||
* @param {IBill} bill
|
* @param {IBill} invoice
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
protected formattedDueDate = (bill: IBill): string => {
|
protected formattedDueDate = (bill: IBill): string => {
|
||||||
@@ -54,7 +39,7 @@ export class PurchaseInvoiceTransformer extends Transformer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted bill amount.
|
* Retrieve formatted bill amount.
|
||||||
* @param {IBill} bill
|
* @param {IBill} invoice
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
protected formattedAmount = (bill): string => {
|
protected formattedAmount = (bill): string => {
|
||||||
@@ -63,7 +48,7 @@ export class PurchaseInvoiceTransformer extends Transformer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted bill amount.
|
* Retrieve formatted bill amount.
|
||||||
* @param {IBill} bill
|
* @param {IBill} invoice
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
protected formattedPaymentAmount = (bill): string => {
|
protected formattedPaymentAmount = (bill): string => {
|
||||||
@@ -74,7 +59,7 @@ export class PurchaseInvoiceTransformer extends Transformer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve formatted bill amount.
|
* Retrieve formatted bill amount.
|
||||||
* @param {IBill} bill
|
* @param {IBill} invoice
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
protected formattedDueAmount = (bill): string => {
|
protected formattedDueAmount = (bill): string => {
|
||||||
@@ -92,90 +77,10 @@ export class PurchaseInvoiceTransformer extends Transformer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the formatted exchange rate.
|
* Retrieve the formatted exchange rate.
|
||||||
* @param {IBill} bill
|
* @param {ISaleInvoice} invoice
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
protected formattedExchangeRate = (bill): string => {
|
protected formattedExchangeRate = (invoice): string => {
|
||||||
return formatNumber(bill.exchangeRate, {
|
return formatNumber(invoice.exchangeRate, { money: false });
|
||||||
currencyCode: this.context.organization.baseCurrency,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the formatted subtotal.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected subtotalFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.subtotal, {
|
|
||||||
currencyCode: bill.currencyCode,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the local subtotal formatted.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected subtotalLocalFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.subtotalLocal, {
|
|
||||||
currencyCode: this.context.organization.baseCurrency,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the formatted subtotal tax excluded.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected subtotalExcludingTaxFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.subtotalExludingTax, {
|
|
||||||
currencyCode: bill.currencyCode,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the local formatted tax amount withheld
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected taxAmountWithheldLocalFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.taxAmountWithheldLocal, {
|
|
||||||
currencyCode: this.context.organization.baseCurrency,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the total formatted.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected totalFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.total, {
|
|
||||||
currencyCode: bill.currencyCode,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the local total formatted.
|
|
||||||
* @param {IBill} bill
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
protected totalLocalFormatted = (bill): string => {
|
|
||||||
return formatNumber(bill.totalLocal, {
|
|
||||||
currencyCode: this.context.organization.baseCurrency,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the taxes lines of bill.
|
|
||||||
* @param {Bill} bill
|
|
||||||
*/
|
|
||||||
protected taxes = (bill) => {
|
|
||||||
return this.item(bill.taxes, new SaleInvoiceTaxEntryTransformer(), {
|
|
||||||
subtotal: bill.subtotal,
|
|
||||||
isInclusiveTax: bill.isInclusiveTax,
|
|
||||||
currencyCode: bill.currencyCode,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,8 +218,7 @@ export class SaleInvoiceGLEntries {
|
|||||||
...commonEntry,
|
...commonEntry,
|
||||||
credit: entry.taxAmount,
|
credit: entry.taxAmount,
|
||||||
accountId: taxPayableAccountId,
|
accountId: taxPayableAccountId,
|
||||||
index: index + 1,
|
index: index + 3,
|
||||||
indexGroup: 30,
|
|
||||||
accountNormal: AccountNormal.CREDIT,
|
accountNormal: AccountNormal.CREDIT,
|
||||||
taxRateId: entry.taxRateId,
|
taxRateId: entry.taxRateId,
|
||||||
taxRate: entry.taxRate,
|
taxRate: entry.taxRate,
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ export class SaleInvoiceTaxEntryTransformer extends Transformer {
|
|||||||
const taxRate = this.taxRate(taxEntry);
|
const taxRate = this.taxRate(taxEntry);
|
||||||
|
|
||||||
return this.options.isInclusiveTax
|
return this.options.isInclusiveTax
|
||||||
? getInclusiveTaxAmount(this.options.subtotal, taxRate)
|
? getInclusiveTaxAmount(this.options.amount, taxRate)
|
||||||
: getExlusiveTaxAmount(this.options.subtotal, taxRate);
|
: getExlusiveTaxAmount(this.options.amount, taxRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export class SaleInvoiceTransformer extends Transformer {
|
|||||||
*/
|
*/
|
||||||
protected taxes = (invoice) => {
|
protected taxes = (invoice) => {
|
||||||
return this.item(invoice.taxes, new SaleInvoiceTaxEntryTransformer(), {
|
return this.item(invoice.taxes, new SaleInvoiceTaxEntryTransformer(), {
|
||||||
subtotal: invoice.subtotal,
|
amount: invoice.amount,
|
||||||
isInclusiveTax: invoice.isInclusiveTax,
|
isInclusiveTax: invoice.isInclusiveTax,
|
||||||
currencyCode: invoice.currencyCode,
|
currencyCode: invoice.currencyCode,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ export class EditTaxRateService {
|
|||||||
// Triggers `onTaxRateEdited` event.
|
// Triggers `onTaxRateEdited` event.
|
||||||
await this.eventPublisher.emitAsync(events.taxRates.onEdited, {
|
await this.eventPublisher.emitAsync(events.taxRates.onEdited, {
|
||||||
editTaxRateDTO,
|
editTaxRateDTO,
|
||||||
oldTaxRate,
|
|
||||||
taxRate,
|
taxRate,
|
||||||
tenantId,
|
tenantId,
|
||||||
trx,
|
trx,
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
import { Knex } from 'knex';
|
|
||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import HasTenancyService from '../Tenancy/TenancyService';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class SyncItemTaxRateOnEditTaxRate {
|
|
||||||
@Inject()
|
|
||||||
private tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syncs the new tax rate created to item default sell tax rate.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} itemId
|
|
||||||
* @param {number} sellTaxRateId
|
|
||||||
*/
|
|
||||||
public updateItemSellTaxRate = async (
|
|
||||||
tenantId: number,
|
|
||||||
oldSellTaxRateId: number,
|
|
||||||
sellTaxRateId: number,
|
|
||||||
trx?: Knex.Transaction
|
|
||||||
) => {
|
|
||||||
const { Item } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
// Can't continue if the old and new sell tax rate id are equal.
|
|
||||||
if (oldSellTaxRateId === sellTaxRateId) return;
|
|
||||||
|
|
||||||
await Item.query().where('sellTaxRateId', oldSellTaxRateId).update({
|
|
||||||
sellTaxRateId,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syncs the new tax rate created to item default purchase tax rate.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} itemId
|
|
||||||
* @param {number} purchaseTaxRateId
|
|
||||||
*/
|
|
||||||
public updateItemPurchaseTaxRate = async (
|
|
||||||
tenantId: number,
|
|
||||||
oldPurchaseTaxRateId: number,
|
|
||||||
purchaseTaxRateId: number,
|
|
||||||
trx?: Knex.Transaction
|
|
||||||
) => {
|
|
||||||
const { Item } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
// Can't continue if the old and new sell tax rate id are equal.
|
|
||||||
if (oldPurchaseTaxRateId === purchaseTaxRateId) return;
|
|
||||||
|
|
||||||
await Item.query(trx)
|
|
||||||
.where('purchaseTaxRateId', oldPurchaseTaxRateId)
|
|
||||||
.update({
|
|
||||||
purchaseTaxRateId,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { SyncItemTaxRateOnEditTaxRate } from './SyncItemTaxRateOnEditTaxRate';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
import { ITaxRateEditedPayload } from '@/interfaces';
|
|
||||||
import { runAfterTransaction } from '../UnitOfWork/TransactionsHooks';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class SyncItemTaxRateOnEditTaxSubscriber {
|
|
||||||
@Inject()
|
|
||||||
private syncItemRateOnEdit: SyncItemTaxRateOnEditTaxRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches events with handles.
|
|
||||||
*/
|
|
||||||
public attach(bus) {
|
|
||||||
bus.subscribe(
|
|
||||||
events.taxRates.onEdited,
|
|
||||||
this.handleSyncNewTaxRateToItemTaxRate
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syncs the new tax rate created to default item tax rates.
|
|
||||||
* @param {ITaxRateEditedPayload} payload -
|
|
||||||
*/
|
|
||||||
private handleSyncNewTaxRateToItemTaxRate = async ({
|
|
||||||
taxRate,
|
|
||||||
tenantId,
|
|
||||||
oldTaxRate,
|
|
||||||
trx,
|
|
||||||
}: ITaxRateEditedPayload) => {
|
|
||||||
runAfterTransaction(trx, async () => {
|
|
||||||
await this.syncItemRateOnEdit.updateItemPurchaseTaxRate(
|
|
||||||
tenantId,
|
|
||||||
oldTaxRate.id,
|
|
||||||
taxRate.id
|
|
||||||
);
|
|
||||||
await this.syncItemRateOnEdit.updateItemSellTaxRate(
|
|
||||||
tenantId,
|
|
||||||
oldTaxRate.id,
|
|
||||||
taxRate.id
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { IBillCreatingPayload, IBillEditingPayload } from '@/interfaces';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
import { CommandTaxRatesValidators } from '../CommandTaxRatesValidators';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class BillTaxRateValidateSubscriber {
|
|
||||||
@Inject()
|
|
||||||
private taxRateDTOValidator: CommandTaxRatesValidators;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches events with handlers.
|
|
||||||
*/
|
|
||||||
public attach(bus) {
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onCreating,
|
|
||||||
this.validateBillEntriesTaxCodeExistanceOnCreating
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onCreating,
|
|
||||||
this.validateBillEntriesTaxIdExistanceOnCreating
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onEditing,
|
|
||||||
this.validateBillEntriesTaxCodeExistanceOnEditing
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onEditing,
|
|
||||||
this.validateBillEntriesTaxIdExistanceOnEditing
|
|
||||||
);
|
|
||||||
return bus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate bill entries tax rate code existance when creating.
|
|
||||||
* @param {IBillCreatingPayload}
|
|
||||||
*/
|
|
||||||
private validateBillEntriesTaxCodeExistanceOnCreating = async ({
|
|
||||||
billDTO,
|
|
||||||
tenantId,
|
|
||||||
}: IBillCreatingPayload) => {
|
|
||||||
await this.taxRateDTOValidator.validateItemEntriesTaxCode(
|
|
||||||
tenantId,
|
|
||||||
billDTO.entries
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the tax rate id existance when creating.
|
|
||||||
* @param {IBillCreatingPayload}
|
|
||||||
*/
|
|
||||||
private validateBillEntriesTaxIdExistanceOnCreating = async ({
|
|
||||||
billDTO,
|
|
||||||
tenantId,
|
|
||||||
}: IBillCreatingPayload) => {
|
|
||||||
await this.taxRateDTOValidator.validateItemEntriesTaxCodeId(
|
|
||||||
tenantId,
|
|
||||||
billDTO.entries
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate bill entries tax rate code existance when editing.
|
|
||||||
* @param {IBillEditingPayload}
|
|
||||||
*/
|
|
||||||
private validateBillEntriesTaxCodeExistanceOnEditing = async ({
|
|
||||||
tenantId,
|
|
||||||
billDTO,
|
|
||||||
}: IBillEditingPayload) => {
|
|
||||||
await this.taxRateDTOValidator.validateItemEntriesTaxCode(
|
|
||||||
tenantId,
|
|
||||||
billDTO.entries
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the bill entries tax rate id existance when editing.
|
|
||||||
* @param {ISaleInvoiceEditingPayload} payload -
|
|
||||||
*/
|
|
||||||
private validateBillEntriesTaxIdExistanceOnEditing = async ({
|
|
||||||
tenantId,
|
|
||||||
billDTO,
|
|
||||||
}: IBillEditingPayload) => {
|
|
||||||
await this.taxRateDTOValidator.validateItemEntriesTaxCodeId(
|
|
||||||
tenantId,
|
|
||||||
billDTO.entries
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import {
|
|
||||||
IBIllEventDeletedPayload,
|
|
||||||
IBillCreatedPayload,
|
|
||||||
IBillEditedPayload,
|
|
||||||
ISaleInvoiceCreatedPayload,
|
|
||||||
ISaleInvoiceDeletedPayload,
|
|
||||||
ISaleInvoiceEditedPayload,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
import { WriteTaxTransactionsItemEntries } from '../WriteTaxTransactionsItemEntries';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class WriteBillTaxTransactionsSubscriber {
|
|
||||||
@Inject()
|
|
||||||
private writeTaxTransactions: WriteTaxTransactionsItemEntries;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches events with handlers.
|
|
||||||
*/
|
|
||||||
public attach(bus) {
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onCreated,
|
|
||||||
this.writeInvoiceTaxTransactionsOnCreated
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onEdited,
|
|
||||||
this.rewriteInvoiceTaxTransactionsOnEdited
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.bill.onDeleted,
|
|
||||||
this.removeInvoiceTaxTransactionsOnDeleted
|
|
||||||
);
|
|
||||||
return bus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the bill tax transactions on invoice created.
|
|
||||||
* @param {ISaleInvoiceCreatingPaylaod}
|
|
||||||
*/
|
|
||||||
private writeInvoiceTaxTransactionsOnCreated = async ({
|
|
||||||
tenantId,
|
|
||||||
bill,
|
|
||||||
trx,
|
|
||||||
}: IBillCreatedPayload) => {
|
|
||||||
await this.writeTaxTransactions.writeTaxTransactionsFromItemEntries(
|
|
||||||
tenantId,
|
|
||||||
bill.entries,
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rewrites the bill tax transactions on invoice edited.
|
|
||||||
* @param {IBillEditedPayload} payload -
|
|
||||||
*/
|
|
||||||
private rewriteInvoiceTaxTransactionsOnEdited = async ({
|
|
||||||
tenantId,
|
|
||||||
bill,
|
|
||||||
trx,
|
|
||||||
}: IBillEditedPayload) => {
|
|
||||||
await this.writeTaxTransactions.rewriteTaxRateTransactionsFromItemEntries(
|
|
||||||
tenantId,
|
|
||||||
bill.entries,
|
|
||||||
'Bill',
|
|
||||||
bill.id,
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the invoice tax transactions on invoice deleted.
|
|
||||||
* @param {IBIllEventDeletedPayload}
|
|
||||||
*/
|
|
||||||
private removeInvoiceTaxTransactionsOnDeleted = async ({
|
|
||||||
tenantId,
|
|
||||||
oldBill,
|
|
||||||
trx,
|
|
||||||
}: IBIllEventDeletedPayload) => {
|
|
||||||
await this.writeTaxTransactions.removeTaxTransactionsFromItemEntries(
|
|
||||||
tenantId,
|
|
||||||
oldBill.id,
|
|
||||||
'Bill',
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
87
packages/server/src/subscribers/Bills/WriteJournalEntries.ts
Normal file
87
packages/server/src/subscribers/Bills/WriteJournalEntries.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
import events from '@/subscribers/events';
|
||||||
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import BillsService from '@/services/Purchases/Bills';
|
||||||
|
import {
|
||||||
|
IBillCreatedPayload,
|
||||||
|
IBillEditedPayload,
|
||||||
|
IBIllEventDeletedPayload,
|
||||||
|
} from '@/interfaces';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export default class BillWriteGLEntriesSubscriber {
|
||||||
|
@Inject()
|
||||||
|
tenancy: TenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
billsService: BillsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches events with handles.
|
||||||
|
*/
|
||||||
|
public attach(bus) {
|
||||||
|
bus.subscribe(
|
||||||
|
events.bill.onCreated,
|
||||||
|
this.handlerWriteJournalEntriesOnCreate
|
||||||
|
);
|
||||||
|
bus.subscribe(
|
||||||
|
events.bill.onEdited,
|
||||||
|
this.handleOverwriteJournalEntriesOnEdit
|
||||||
|
);
|
||||||
|
bus.subscribe(events.bill.onDeleted, this.handlerDeleteJournalEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles writing journal entries once bill created.
|
||||||
|
* @param {IBillCreatedPayload} payload -
|
||||||
|
*/
|
||||||
|
private handlerWriteJournalEntriesOnCreate = async ({
|
||||||
|
tenantId,
|
||||||
|
billId,
|
||||||
|
bill,
|
||||||
|
trx,
|
||||||
|
}: IBillCreatedPayload) => {
|
||||||
|
// Can't continue if the bill is not opened yet.
|
||||||
|
if (!bill.openedAt) return null;
|
||||||
|
|
||||||
|
await this.billsService.recordJournalTransactions(
|
||||||
|
tenantId,
|
||||||
|
billId,
|
||||||
|
false,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the overwriting journal entries once bill edited.
|
||||||
|
* @param {IBillEditedPayload} payload -
|
||||||
|
*/
|
||||||
|
private handleOverwriteJournalEntriesOnEdit = async ({
|
||||||
|
tenantId,
|
||||||
|
billId,
|
||||||
|
bill,
|
||||||
|
trx,
|
||||||
|
}: IBillEditedPayload) => {
|
||||||
|
// Can't continue if the bill is not opened yet.
|
||||||
|
if (!bill.openedAt) return null;
|
||||||
|
|
||||||
|
await this.billsService.recordJournalTransactions(
|
||||||
|
tenantId,
|
||||||
|
billId,
|
||||||
|
true,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles revert journal entries on bill deleted.
|
||||||
|
* @param {IBIllEventDeletedPayload} payload -
|
||||||
|
*/
|
||||||
|
private handlerDeleteJournalEntries = async ({
|
||||||
|
tenantId,
|
||||||
|
billId,
|
||||||
|
trx,
|
||||||
|
}: IBIllEventDeletedPayload) => {
|
||||||
|
await this.billsService.revertJournalEntries(tenantId, billId, trx);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
exports.up = function (knex) {
|
|
||||||
return knex.schema.table('tenants_metadata', (table) => {
|
|
||||||
table.string('tax_number')
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function (knex) {
|
|
||||||
return knex.schema.table('tenants_metadata', (table) => {
|
|
||||||
table.dropColumn('tax_number');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -41,10 +41,10 @@ const mapValuesDeepReverse = (nodes, callback, config?) => {
|
|||||||
);
|
);
|
||||||
const mappedNode = callback(node, children);
|
const mappedNode = callback(node, children);
|
||||||
|
|
||||||
if (!mappedNode.children && children) {
|
_.set(clonedNodes, pathString, {
|
||||||
mappedNode.children = children;
|
...mappedNode,
|
||||||
}
|
...(!_.isEmpty(children) ? { children } : {}),
|
||||||
_.set(clonedNodes, pathString, mappedNode);
|
});
|
||||||
});
|
});
|
||||||
return clonedNodes;
|
return clonedNodes;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,17 @@
|
|||||||
FROM node:18.16.0-alpine as build
|
FROM node:14.15.0 as build
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy application dependency manifests to the container image.
|
# Install dependencies
|
||||||
COPY ./package*.json ./
|
COPY package*.json ./
|
||||||
COPY ./pnpm-lock.yaml ./pnpm-lock.yaml
|
COPY lerna.json ./
|
||||||
COPY ./pnpm-workspace.yaml ./pnpm-workspace.yaml
|
|
||||||
COPY ./lerna.json ./lerna.json
|
|
||||||
COPY ./packages/webapp/package*.json ./packages/webapp/
|
|
||||||
|
|
||||||
# Install application dependencies
|
COPY ./packages/webapp/package*.json /app/packages/webapp/
|
||||||
RUN apk update
|
|
||||||
RUN apk add python3 build-base chromium
|
|
||||||
|
|
||||||
# Set PYHTON env
|
RUN npm install
|
||||||
ENV PYTHON=/usr/bin/python3
|
RUN npm run bootstrap
|
||||||
|
|
||||||
# Install pnpm packages dependencies
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
RUN pnpm install
|
|
||||||
|
|
||||||
# Build webapp package
|
# Build webapp package
|
||||||
COPY ./packages/webapp /app/packages/webapp
|
COPY ./packages/webapp /app/packages/webapp
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const dotenv = require('dotenv-webpack');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
webpack: {
|
webpack: {
|
||||||
|
plugins: [
|
||||||
|
new dotenv(),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': {
|
||||||
|
MONOREPO_VERSION: JSON.stringify(require('../../lerna.json').version),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, 'src'),
|
'@': path.resolve(__dirname, 'src'),
|
||||||
},
|
},
|
||||||
configure: {
|
|
||||||
resolve: {
|
|
||||||
fallback: { path: require.resolve('path-browserify') },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -117,12 +117,6 @@
|
|||||||
"resolutions": {
|
"resolutions": {
|
||||||
"react-error-overlay": "6.0.9"
|
"react-error-overlay": "6.0.9"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
|
||||||
"extends": [
|
|
||||||
"react-app",
|
|
||||||
"react-app/jest"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.2%",
|
">0.2%",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
import AccountDrawer from '@/containers/Drawers/AccountDrawer';
|
import AccountDrawer from '@/containers/Drawers/AccountDrawer';
|
||||||
import ManualJournalDrawer from '@/containers/Drawers/ManualJournalDrawer';
|
import ManualJournalDrawer from '@/containers/Drawers/ManualJournalDrawer';
|
||||||
import ExpenseDrawer from '@/containers/Drawers/ExpenseDrawer';
|
import ExpenseDrawer from '@/containers/Drawers/ExpenseDrawer';
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ const SelectButton = styled(Button)`
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
|
|
||||||
&.bp4-small{
|
|
||||||
padding-right: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.is-selected):not([class*='bp4-intent-']):not(.bp4-minimal) {
|
&:not(.is-selected):not([class*='bp4-intent-']):not(.bp4-minimal) {
|
||||||
color: #5c7080;
|
color: #5c7080;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import * as R from 'ramda';
|
|
||||||
import intl from 'react-intl-universal';
|
|
||||||
import { FSelect } from '@/components';
|
|
||||||
import { DialogsName } from '@/constants/dialogs';
|
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
|
||||||
|
|
||||||
// Create new account renderer.
|
|
||||||
const createNewItemRenderer = (query, active, handleClick) => {
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
icon="add"
|
|
||||||
text={intl.get('list.create', { value: `"${query}"` })}
|
|
||||||
active={active}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create new item from the given query string.
|
|
||||||
const createNewItemFromQuery = (name) => ({ name });
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tax rates select field binded with Formik form.
|
|
||||||
* @returns {JSX.Element}
|
|
||||||
*/
|
|
||||||
function TaxRatesSelectRoot({
|
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #ownProps
|
|
||||||
allowCreate,
|
|
||||||
|
|
||||||
...restProps
|
|
||||||
}) {
|
|
||||||
// Maybe inject new item props to select component.
|
|
||||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
|
||||||
const maybeCreateNewItemFromQuery = allowCreate
|
|
||||||
? createNewItemFromQuery
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Handles the create item click.
|
|
||||||
const handleCreateItemClick = () => {
|
|
||||||
openDialog(DialogsName.TaxRateForm);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FSelect
|
|
||||||
valueAccessor={'id'}
|
|
||||||
labelAccessor={'code'}
|
|
||||||
textAccessor={'name_formatted'}
|
|
||||||
popoverProps={{ minimal: true, usePortal: true, inline: false }}
|
|
||||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
|
||||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
|
||||||
onCreateItemSelect={handleCreateItemClick}
|
|
||||||
{...restProps}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TaxRatesSelect = R.compose(withDialogActions)(TaxRatesSelectRoot);
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
import { TaxType } from '@/interfaces/TaxRates';
|
|
||||||
|
|
||||||
export const InclusiveTaxOptions = [
|
|
||||||
{ key: TaxType.Inclusive, label: 'Inclusive of Tax' },
|
|
||||||
{ key: TaxType.Exclusive, label: 'Exclusive of Tax' },
|
|
||||||
];
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ export function Sidebar() {
|
|||||||
* @returns {React.JSX}
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
function SidebarFooterVersion() {
|
function SidebarFooterVersion() {
|
||||||
const { REACT_APP_VERSION } = process.env;
|
const { MONOREPO_VERSION } = process.env;
|
||||||
|
|
||||||
if (!REACT_APP_VERSION) {
|
if (!MONOREPO_VERSION) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <div class="sidebar__version">v{REACT_APP_VERSION}</div>;
|
return <div class="sidebar__version">v{MONOREPO_VERSION}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
import { Button, Popover, Menu, Position } from '@blueprintjs/core';
|
import { Button, Popover, Menu, Position } from '@blueprintjs/core';
|
||||||
|
|
||||||
import { Icon } from '@/components';
|
import { Icon } from '@/components';
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default function BillDetailHeader() {
|
|||||||
<CommercialDocTopHeader>
|
<CommercialDocTopHeader>
|
||||||
<DetailsMenu>
|
<DetailsMenu>
|
||||||
<AmountDetailItem label={intl.get('amount')}>
|
<AmountDetailItem label={intl.get('amount')}>
|
||||||
<h3 class="big-number">{bill.total_formatted}</h3>
|
<h3 class="big-number">{bill.formatted_amount}</h3>
|
||||||
</AmountDetailItem>
|
</AmountDetailItem>
|
||||||
<StatusDetailItem>
|
<StatusDetailItem>
|
||||||
<BillDetailsStatus bill={bill} />
|
<BillDetailsStatus bill={bill} />
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
|
FormatNumber,
|
||||||
T,
|
T,
|
||||||
TotalLines,
|
TotalLines,
|
||||||
TotalLine,
|
TotalLine,
|
||||||
@@ -20,20 +23,12 @@ export function BillDetailTableFooter() {
|
|||||||
<BillTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<BillTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'bill.details.subtotal'} />}
|
title={<T id={'bill.details.subtotal'} />}
|
||||||
value={bill.subtotal_formatted}
|
value={<FormatNumber value={bill.amount} />}
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
/>
|
/>
|
||||||
{bill.taxes.map((taxRate) => (
|
|
||||||
<TotalLine
|
|
||||||
key={taxRate.id}
|
|
||||||
title={`${taxRate.name} [${taxRate.tax_rate}%]`}
|
|
||||||
value={taxRate.tax_rate_amount_formatted}
|
|
||||||
textStyle={TotalLineTextStyle.Regular}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'bill.details.total'} />}
|
title={<T id={'bill.details.total'} />}
|
||||||
value={bill.total_formatted}
|
value={bill.formatted_amount}
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
/>
|
/>
|
||||||
@@ -44,7 +39,6 @@ export function BillDetailTableFooter() {
|
|||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'bill.details.due_amount'} />}
|
title={<T id={'bill.details.due_amount'} />}
|
||||||
value={bill.formatted_due_amount}
|
value={bill.formatted_due_amount}
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
|
||||||
/>
|
/>
|
||||||
</BillTotalLines>
|
</BillTotalLines>
|
||||||
</BillDetailsFooterRoot>
|
</BillDetailsFooterRoot>
|
||||||
|
|||||||
@@ -67,14 +67,6 @@ export default function ItemDetailHeader() {
|
|||||||
label={intl.get('cost_account_id')}
|
label={intl.get('cost_account_id')}
|
||||||
children={defaultTo(item.cost_account?.name, '-')}
|
children={defaultTo(item.cost_account?.name, '-')}
|
||||||
/>
|
/>
|
||||||
<DetailItem
|
|
||||||
label={intl.get('item.details.sell_tax_rate')}
|
|
||||||
children={item?.sell_tax_rate?.name}
|
|
||||||
/>
|
|
||||||
<DetailItem
|
|
||||||
label={intl.get('item.details.purchase_tax_rate')}
|
|
||||||
children={item?.purchase_tax_rate?.name}
|
|
||||||
/>
|
|
||||||
<If condition={item.type === 'inventory'}>
|
<If condition={item.type === 'inventory'}>
|
||||||
<DetailItem
|
<DetailItem
|
||||||
label={intl.get('inventory_account')}
|
label={intl.get('inventory_account')}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import { Box } from '@/components';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
export const EntriesActionsBar = styled(Box)`
|
|
||||||
padding-bottom: 12px;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.bp4-form-group {
|
|
||||||
margin-bottom: 0;
|
|
||||||
|
|
||||||
label.bp4-label {
|
|
||||||
opacity: 0.6;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@@ -8,30 +8,20 @@ import { DataTableEditable } from '@/components';
|
|||||||
import { useEditableItemsEntriesColumns } from './components';
|
import { useEditableItemsEntriesColumns } from './components';
|
||||||
import {
|
import {
|
||||||
useFetchItemRow,
|
useFetchItemRow,
|
||||||
|
composeRowsOnNewRow,
|
||||||
useComposeRowsOnEditTableCell,
|
useComposeRowsOnEditTableCell,
|
||||||
useComposeRowsOnRemoveTableRow,
|
useComposeRowsOnRemoveTableRow,
|
||||||
useComposeRowsOnNewRow,
|
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import {
|
import {
|
||||||
ItemEntriesTableProvider,
|
ItemEntriesTableProvider,
|
||||||
useItemEntriesTableContext,
|
useItemEntriesTableContext,
|
||||||
} from './ItemEntriesTableProvider';
|
} from './ItemEntriesTableProvider';
|
||||||
import { useUncontrolled } from '@/hooks/useUncontrolled';
|
import { useUncontrolled } from '@/hooks/useUncontrolled';
|
||||||
import { ItemEntry } from '@/interfaces/ItemEntries';
|
|
||||||
|
|
||||||
interface ItemsEntriesTableProps {
|
|
||||||
initialValue?: ItemEntry;
|
|
||||||
value?: ItemEntry[];
|
|
||||||
onChange?: (entries: ItemEntry[]) => void;
|
|
||||||
taxRates?: any[];
|
|
||||||
minLinesNumber?: number;
|
|
||||||
enableTaxRates?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Items entries table.
|
* Items entries table.
|
||||||
*/
|
*/
|
||||||
function ItemsEntriesTable(props: ItemsEntriesTableProps) {
|
function ItemsEntriesTable(props) {
|
||||||
const { value, initialValue, onChange } = props;
|
const { value, initialValue, onChange } = props;
|
||||||
|
|
||||||
const [localValue, handleChange] = useUncontrolled({
|
const [localValue, handleChange] = useUncontrolled({
|
||||||
@@ -61,7 +51,6 @@ function ItemEntriesTableRoot() {
|
|||||||
currencyCode,
|
currencyCode,
|
||||||
landedCost,
|
landedCost,
|
||||||
taxRates,
|
taxRates,
|
||||||
itemType,
|
|
||||||
} = useItemEntriesTableContext();
|
} = useItemEntriesTableContext();
|
||||||
|
|
||||||
// Editiable items entries columns.
|
// Editiable items entries columns.
|
||||||
@@ -69,12 +58,11 @@ function ItemEntriesTableRoot() {
|
|||||||
|
|
||||||
const composeRowsOnEditCell = useComposeRowsOnEditTableCell();
|
const composeRowsOnEditCell = useComposeRowsOnEditTableCell();
|
||||||
const composeRowsOnDeleteRow = useComposeRowsOnRemoveTableRow();
|
const composeRowsOnDeleteRow = useComposeRowsOnRemoveTableRow();
|
||||||
const composeRowsOnNewRow = useComposeRowsOnNewRow();
|
|
||||||
|
|
||||||
// Handle the fetch item row details.
|
// Handle the fetch item row details.
|
||||||
const { setItemRow, cellsLoading, isItemFetching } = useFetchItemRow({
|
const { setItemRow, cellsLoading, isItemFetching } = useFetchItemRow({
|
||||||
landedCost,
|
landedCost,
|
||||||
itemType,
|
itemType: null,
|
||||||
notifyNewRow: (newRow, rowIndex) => {
|
notifyNewRow: (newRow, rowIndex) => {
|
||||||
// Update the rate, description and quantity data of the row.
|
// Update the rate, description and quantity data of the row.
|
||||||
const newRows = composeRowsOnNewRow(rowIndex, newRow, localValue);
|
const newRows = composeRowsOnNewRow(rowIndex, newRow, localValue);
|
||||||
@@ -131,11 +119,8 @@ ItemsEntriesTable.defaultProps = {
|
|||||||
discount: '',
|
discount: '',
|
||||||
},
|
},
|
||||||
initialEntries: [],
|
initialEntries: [],
|
||||||
taxRates: [],
|
|
||||||
items: [],
|
|
||||||
linesNumber: 1,
|
linesNumber: 1,
|
||||||
minLinesNumber: 1,
|
minLinesNumber: 1,
|
||||||
enableTaxRates: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ItemsEntriesTable;
|
export default ItemsEntriesTable;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ const LandedCostHeaderCell = () => {
|
|||||||
*/
|
*/
|
||||||
export function useEditableItemsEntriesColumns() {
|
export function useEditableItemsEntriesColumns() {
|
||||||
const { featureCan } = useFeatureCan();
|
const { featureCan } = useFeatureCan();
|
||||||
const { landedCost, enableTaxRates } = useItemEntriesTableContext();
|
const { landedCost } = useItemEntriesTableContext();
|
||||||
|
|
||||||
const isProjectsFeatureEnabled = featureCan(Features.Projects);
|
const isProjectsFeatureEnabled = featureCan(Features.Projects);
|
||||||
|
|
||||||
@@ -132,17 +132,13 @@ export function useEditableItemsEntriesColumns() {
|
|||||||
width: 70,
|
width: 70,
|
||||||
align: Align.Right,
|
align: Align.Right,
|
||||||
},
|
},
|
||||||
...(enableTaxRates
|
{
|
||||||
? [
|
Header: 'Tax rate',
|
||||||
{
|
accessor: 'tax_rate_id',
|
||||||
Header: 'Tax rate',
|
Cell: TaxRatesSuggestInputCell,
|
||||||
accessor: 'tax_rate_id',
|
disableSortBy: true,
|
||||||
Cell: TaxRatesSuggestInputCell,
|
width: 110,
|
||||||
disableSortBy: true,
|
},
|
||||||
width: 110,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
{
|
{
|
||||||
Header: intl.get('discount'),
|
Header: intl.get('discount'),
|
||||||
accessor: 'discount',
|
accessor: 'discount',
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { sumBy, isEmpty, last, keyBy, groupBy } from 'lodash';
|
import { sumBy, isEmpty, last, keyBy } from 'lodash';
|
||||||
|
|
||||||
import { useItem } from '@/hooks/query';
|
import { useItem } from '@/hooks/query';
|
||||||
import {
|
import {
|
||||||
toSafeNumber,
|
toSafeNumber,
|
||||||
@@ -11,7 +12,6 @@ import {
|
|||||||
updateAutoAddNewLine,
|
updateAutoAddNewLine,
|
||||||
orderingLinesIndexes,
|
orderingLinesIndexes,
|
||||||
updateTableRow,
|
updateTableRow,
|
||||||
formattedAmount,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { useItemEntriesTableContext } from './ItemEntriesTableProvider';
|
import { useItemEntriesTableContext } from './ItemEntriesTableProvider';
|
||||||
|
|
||||||
@@ -119,24 +119,17 @@ export function useFetchItemRow({ landedCost, itemType, notifyNewRow }) {
|
|||||||
// Detarmines whether the landed cost checkbox should be disabled.
|
// Detarmines whether the landed cost checkbox should be disabled.
|
||||||
const landedCostDisabled = isLandedCostDisabled(item);
|
const landedCostDisabled = isLandedCostDisabled(item);
|
||||||
|
|
||||||
const taxRateId =
|
|
||||||
itemType === ITEM_TYPE.PURCHASABLE
|
|
||||||
? item.purchase_tax_rate_id
|
|
||||||
: item.sell_tax_rate_id;
|
|
||||||
|
|
||||||
// The new row.
|
// The new row.
|
||||||
const newRow = {
|
const newRow = {
|
||||||
rate: price,
|
rate: price,
|
||||||
description,
|
description,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
tax_rate_id: taxRateId,
|
|
||||||
...(landedCost
|
...(landedCost
|
||||||
? {
|
? {
|
||||||
landed_cost: false,
|
landed_cost: false,
|
||||||
landed_cost_disabled: landedCostDisabled,
|
landed_cost_disabled: landedCostDisabled,
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
taxRateId,
|
|
||||||
};
|
};
|
||||||
setItemRow(null);
|
setItemRow(null);
|
||||||
saveInvoke(notifyNewRow, newRow, rowIndex);
|
saveInvoke(notifyNewRow, newRow, rowIndex);
|
||||||
@@ -165,21 +158,13 @@ export const composeRowsOnEditCell = R.curry(
|
|||||||
/**
|
/**
|
||||||
* Compose table rows when insert a new row to table rows.
|
* Compose table rows when insert a new row to table rows.
|
||||||
*/
|
*/
|
||||||
export const useComposeRowsOnNewRow = () => {
|
export const composeRowsOnNewRow = R.curry((rowIndex, newRow, rows) => {
|
||||||
const { taxRates, isInclusiveTax } = useItemEntriesTableContext();
|
return compose(
|
||||||
|
orderingLinesIndexes,
|
||||||
return React.useMemo(() => {
|
updateItemsEntriesTotal,
|
||||||
return R.curry((rowIndex, newRow, rows) => {
|
updateTableRow(rowIndex, newRow),
|
||||||
return compose(
|
)(rows);
|
||||||
assignEntriesTaxAmount(isInclusiveTax),
|
});
|
||||||
assignEntriesTaxRate(taxRates),
|
|
||||||
orderingLinesIndexes,
|
|
||||||
updateItemsEntriesTotal,
|
|
||||||
updateTableRow(rowIndex, newRow),
|
|
||||||
)(rows);
|
|
||||||
});
|
|
||||||
}, [isInclusiveTax, taxRates]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associate tax rate to entries.
|
* Associate tax rate to entries.
|
||||||
@@ -281,29 +266,3 @@ export const useComposeRowsOnRemoveTableRow = () => {
|
|||||||
[minLinesNumber, defaultEntry, localValue],
|
[minLinesNumber, defaultEntry, localValue],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the aggregate tax rates from the given item entries.
|
|
||||||
*/
|
|
||||||
export const aggregateItemEntriesTaxRates = R.curry((taxRates, entries) => {
|
|
||||||
const taxRatesById = keyBy(taxRates, 'id');
|
|
||||||
|
|
||||||
// Calculate the total tax amount of invoice entries.
|
|
||||||
const filteredEntries = entries.filter((e) => e.tax_rate_id);
|
|
||||||
const groupedTaxRates = groupBy(filteredEntries, 'tax_rate_id');
|
|
||||||
|
|
||||||
return Object.keys(groupedTaxRates).map((taxRateId) => {
|
|
||||||
const taxRate = taxRatesById[taxRateId];
|
|
||||||
const taxRates = groupedTaxRates[taxRateId];
|
|
||||||
const totalTaxAmount = sumBy(taxRates, 'tax_amount');
|
|
||||||
const taxAmountFormatted = formattedAmount(totalTaxAmount, 'USD');
|
|
||||||
|
|
||||||
return {
|
|
||||||
taxRateId,
|
|
||||||
taxRate: taxRate.rate,
|
|
||||||
label: `${taxRate.name} [${taxRate.rate}%]`,
|
|
||||||
taxAmount: totalTaxAmount,
|
|
||||||
taxAmountFormatted,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ const BalanceSheetDataTable = styled(ReportDataTable)`
|
|||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
padding-top: 0.32rem;
|
padding-top: 0.32rem;
|
||||||
padding-bottom: 0.32rem;
|
padding-bottom: 0.32rem;
|
||||||
color: #252A31;
|
|
||||||
}
|
}
|
||||||
&.is-expanded {
|
&.is-expanded {
|
||||||
.td:not(.name) .cell-inner {
|
.td:not(.name) .cell-inner {
|
||||||
@@ -73,7 +72,6 @@ const BalanceSheetDataTable = styled(ReportDataTable)`
|
|||||||
.td {
|
.td {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border-top: 1px solid #bbb;
|
border-top: 1px solid #bbb;
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ const CashflowStatementDataTable = styled(DataTable)`
|
|||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
padding-top: 0.32rem;
|
padding-top: 0.32rem;
|
||||||
padding-bottom: 0.32rem;
|
padding-bottom: 0.32rem;
|
||||||
color: #252a31;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// &.row-type--AGGREGATE,
|
||||||
&.row_type--ACCOUNTS {
|
&.row_type--ACCOUNTS {
|
||||||
border-top: 1px solid #bbb;
|
border-top: 1px solid #bbb;
|
||||||
}
|
}
|
||||||
@@ -71,9 +72,6 @@ const CashflowStatementDataTable = styled(DataTable)`
|
|||||||
&.row_type--TOTAL {
|
&.row_type--TOTAL {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
.td {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
&:not(:first-child) .td {
|
&:not(:first-child) .td {
|
||||||
border-top: 1px solid #bbb;
|
border-top: 1px solid #bbb;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ const ProfitLossDataTable = styled(ReportDataTable)`
|
|||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
padding-top: 0.32rem;
|
padding-top: 0.32rem;
|
||||||
padding-bottom: 0.32rem;
|
padding-bottom: 0.32rem;
|
||||||
color: #252A31;
|
|
||||||
}
|
}
|
||||||
&.is-expanded {
|
&.is-expanded {
|
||||||
.td:not(.name) .cell-inner {
|
.td:not(.name) .cell-inner {
|
||||||
@@ -72,7 +71,6 @@ const ProfitLossDataTable = styled(ReportDataTable)`
|
|||||||
.td {
|
.td {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border-top: 1px solid #bbb;
|
border-top: 1px solid #bbb;
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:last-of-type .td {
|
&:last-of-type .td {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from './components';
|
} from './components';
|
||||||
|
|
||||||
import withTrialBalanceActions from './withTrialBalanceActions';
|
import withTrialBalanceActions from './withTrialBalanceActions';
|
||||||
|
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import { tableRowTypesToClassnames } from '@/utils';
|
|||||||
import { ReportDataTable, FinancialSheet } from '@/components';
|
import { ReportDataTable, FinancialSheet } from '@/components';
|
||||||
|
|
||||||
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
|
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
|
||||||
import { useTrialBalanceSheetTableColumns } from './hooks';
|
import { useTrialBalanceTableColumns } from './components';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trial Balance sheet data table.
|
* Trial Balance sheet data table.
|
||||||
@@ -16,12 +17,12 @@ import { useTrialBalanceSheetTableColumns } from './hooks';
|
|||||||
export default function TrialBalanceSheetTable({ companyName }) {
|
export default function TrialBalanceSheetTable({ companyName }) {
|
||||||
// Trial balance sheet context.
|
// Trial balance sheet context.
|
||||||
const {
|
const {
|
||||||
trialBalanceSheet: { table, query },
|
trialBalanceSheet: { tableRows, query },
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useTrialBalanceSheetContext();
|
} = useTrialBalanceSheetContext();
|
||||||
|
|
||||||
// Trial balance sheet table columns.
|
// Trial balance sheet table columns.
|
||||||
const columns = useTrialBalanceSheetTableColumns();
|
const columns = useTrialBalanceTableColumns();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialSheet
|
<FinancialSheet
|
||||||
@@ -35,7 +36,7 @@ export default function TrialBalanceSheetTable({ companyName }) {
|
|||||||
>
|
>
|
||||||
<TrialBalanceDataTable
|
<TrialBalanceDataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={table.rows}
|
data={tableRows}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
expandToggleColumn={1}
|
expandToggleColumn={1}
|
||||||
expandColumnSpace={1}
|
expandColumnSpace={1}
|
||||||
@@ -58,7 +59,7 @@ const TrialBalanceDataTable = styled(ReportDataTable)`
|
|||||||
.balance.td {
|
.balance.td {
|
||||||
border-top-color: #000;
|
border-top-color: #000;
|
||||||
}
|
}
|
||||||
.tr.row_type--TOTAL .td {
|
.tr.row_type--total .td {
|
||||||
border-top: 1px solid #bbb;
|
border-top: 1px solid #bbb;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border-bottom: 3px double #000;
|
border-bottom: 3px double #000;
|
||||||
|
|||||||
@@ -1,10 +1,88 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import intl from 'react-intl-universal';
|
||||||
import { Button } from '@blueprintjs/core';
|
import { Button } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { Align } from '@/constants';
|
||||||
|
import { getColumnWidth } from '@/utils';
|
||||||
|
import { CellTextSpan } from '@/components/Datatable/Cells';
|
||||||
import { If, Icon, FormattedMessage as T } from '@/components';
|
import { If, Icon, FormattedMessage as T } from '@/components';
|
||||||
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
|
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
|
||||||
import { FinancialComputeAlert } from '../FinancialReportPage';
|
import { FinancialComputeAlert } from '../FinancialReportPage';
|
||||||
import FinancialLoadingBar from '../FinancialLoadingBar';
|
import FinancialLoadingBar from '../FinancialLoadingBar';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the credit column.
|
||||||
|
*/
|
||||||
|
const getCreditColumn = (data) => {
|
||||||
|
const width = getColumnWidth(data, `credit`, { minWidth: 140 });
|
||||||
|
|
||||||
|
return {
|
||||||
|
Header: intl.get('credit'),
|
||||||
|
Cell: CellTextSpan,
|
||||||
|
accessor: 'formatted_credit',
|
||||||
|
className: 'credit',
|
||||||
|
width,
|
||||||
|
textOverview: true,
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the debit column.
|
||||||
|
*/
|
||||||
|
const getDebitColumn = (data) => {
|
||||||
|
return {
|
||||||
|
Header: intl.get('debit'),
|
||||||
|
Cell: CellTextSpan,
|
||||||
|
accessor: 'formatted_debit',
|
||||||
|
width: getColumnWidth(data, `debit`, { minWidth: 140 }),
|
||||||
|
textOverview: true,
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the balance column.
|
||||||
|
*/
|
||||||
|
const getBalanceColumn = (data) => {
|
||||||
|
return {
|
||||||
|
Header: intl.get('balance'),
|
||||||
|
Cell: CellTextSpan,
|
||||||
|
accessor: 'formatted_balance',
|
||||||
|
className: 'balance',
|
||||||
|
width: getColumnWidth(data, `balance`, { minWidth: 140 }),
|
||||||
|
textOverview: true,
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve trial balance sheet table columns.
|
||||||
|
*/
|
||||||
|
export const useTrialBalanceTableColumns = () => {
|
||||||
|
// Trial balance sheet context.
|
||||||
|
const {
|
||||||
|
trialBalanceSheet: { tableRows },
|
||||||
|
} = useTrialBalanceSheetContext();
|
||||||
|
|
||||||
|
return React.useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
Header: intl.get('account_name'),
|
||||||
|
accessor: (row) => (row.code ? `${row.name} - ${row.code}` : row.name),
|
||||||
|
className: 'name',
|
||||||
|
width: 350,
|
||||||
|
textOverview: true,
|
||||||
|
},
|
||||||
|
getCreditColumn(tableRows),
|
||||||
|
getDebitColumn(tableRows),
|
||||||
|
getBalanceColumn(tableRows),
|
||||||
|
],
|
||||||
|
[tableRows],
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trial balance sheet progress loading bar.
|
* Trial balance sheet progress loading bar.
|
||||||
*/
|
*/
|
||||||
@@ -23,7 +101,7 @@ export function TrialBalanceSheetLoadingBar() {
|
|||||||
*/
|
*/
|
||||||
export function TrialBalanceSheetAlerts() {
|
export function TrialBalanceSheetAlerts() {
|
||||||
const {
|
const {
|
||||||
trialBalanceSheet,
|
trialBalanceSheet: { meta },
|
||||||
isLoading,
|
isLoading,
|
||||||
refetchSheet,
|
refetchSheet,
|
||||||
} = useTrialBalanceSheetContext();
|
} = useTrialBalanceSheetContext();
|
||||||
@@ -37,7 +115,7 @@ export function TrialBalanceSheetAlerts() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Can't continue if the cost compute job is not running.
|
// Can't continue if the cost compute job is not running.
|
||||||
if (!trialBalanceSheet?.meta.is_cost_compute_running) {
|
if (!meta.is_cost_compute_running) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import * as R from 'ramda';
|
|
||||||
import { Align } from '@/constants';
|
|
||||||
import { getColumnWidth } from '@/utils';
|
|
||||||
|
|
||||||
const ACCOUNT_NAME_COLUMN_WIDTH = 320;
|
|
||||||
const AMOUNT_COLUMNS_MIN_WIDTH = 120;
|
|
||||||
const AMOUNT_COLUMNS_MAGIC_SPACING = 10;
|
|
||||||
|
|
||||||
const getTableCellValueAccessor = (index: number) => `cells[${index}].value`;
|
|
||||||
|
|
||||||
const accountNameAccessor = R.curry((data, column) => {
|
|
||||||
const accessor = getTableCellValueAccessor(column.cell_index);
|
|
||||||
|
|
||||||
return {
|
|
||||||
Header: column.label,
|
|
||||||
id: column.key,
|
|
||||||
accessor,
|
|
||||||
className: column.key,
|
|
||||||
width: ACCOUNT_NAME_COLUMN_WIDTH,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const amountAccessor = R.curry((data, column) => {
|
|
||||||
const accessor = getTableCellValueAccessor(column.cell_index);
|
|
||||||
|
|
||||||
return {
|
|
||||||
Header: column.label,
|
|
||||||
id: column.key,
|
|
||||||
accessor,
|
|
||||||
className: column.key,
|
|
||||||
width: getColumnWidth(data, accessor, {
|
|
||||||
magicSpacing: AMOUNT_COLUMNS_MAGIC_SPACING,
|
|
||||||
minWidth: AMOUNT_COLUMNS_MIN_WIDTH,
|
|
||||||
}),
|
|
||||||
align: Align.Right,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const dynamicColumnMapper = R.curry((data, column) => {
|
|
||||||
const accountNameColumn = accountNameAccessor(data);
|
|
||||||
const creditColumn = amountAccessor(data);
|
|
||||||
const debitColumn = amountAccessor(data);
|
|
||||||
const totalColumn = amountAccessor(data);
|
|
||||||
|
|
||||||
return R.compose(
|
|
||||||
R.when(R.pathEq(['key'], 'account_name'), accountNameColumn),
|
|
||||||
R.when(R.pathEq(['key'], 'credit'), creditColumn),
|
|
||||||
R.when(R.pathEq(['key'], 'debit'), debitColumn),
|
|
||||||
R.when(R.pathEq(['key'], 'total'), totalColumn),
|
|
||||||
)(column);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const trialBalancesheetDynamicColumns = (columns, data) => {
|
|
||||||
return R.map(dynamicColumnMapper(data), columns);
|
|
||||||
};
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react';
|
|
||||||
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
|
|
||||||
import { trialBalancesheetDynamicColumns } from './dynamicColumns';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the trial balance sheet columns.
|
|
||||||
*/
|
|
||||||
export const useTrialBalanceSheetTableColumns = () => {
|
|
||||||
const {
|
|
||||||
trialBalanceSheet: { table },
|
|
||||||
} = useTrialBalanceSheetContext();
|
|
||||||
|
|
||||||
return React.useMemo(
|
|
||||||
() => trialBalancesheetDynamicColumns(table.columns, table.rows),
|
|
||||||
[table],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -29,16 +29,14 @@ import {
|
|||||||
costPriceFieldShouldUpdate,
|
costPriceFieldShouldUpdate,
|
||||||
costAccountFieldShouldUpdate,
|
costAccountFieldShouldUpdate,
|
||||||
purchaseDescFieldShouldUpdate,
|
purchaseDescFieldShouldUpdate,
|
||||||
taxRateFieldShouldUpdate,
|
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { compose, inputIntent } from '@/utils';
|
import { compose, inputIntent } from '@/utils';
|
||||||
import { TaxRatesSelect } from '@/components/TaxRates/TaxRatesSelect';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item form body.
|
* Item form body.
|
||||||
*/
|
*/
|
||||||
function ItemFormBody({ organization: { base_currency } }) {
|
function ItemFormBody({ organization: { base_currency } }) {
|
||||||
const { accounts, taxRates } = useItemFormContext();
|
const { accounts } = useItemFormContext();
|
||||||
const { values } = useFormikContext();
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -113,20 +111,7 @@ function ItemFormBody({ organization: { base_currency } }) {
|
|||||||
filterByParentTypes={[ACCOUNT_PARENT_TYPE.INCOME]}
|
filterByParentTypes={[ACCOUNT_PARENT_TYPE.INCOME]}
|
||||||
fill={true}
|
fill={true}
|
||||||
allowCreate={true}
|
allowCreate={true}
|
||||||
fastField={true}
|
fastField={true}
|
||||||
/>
|
|
||||||
</FFormGroup>
|
|
||||||
|
|
||||||
{/*------------- Sell Tax Rate ------------- */}
|
|
||||||
<FFormGroup
|
|
||||||
name={'sell_tax_rate_id'}
|
|
||||||
label={'Tax Rate'}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<TaxRatesSelect
|
|
||||||
name={'sell_tax_rate_id'}
|
|
||||||
items={taxRates}
|
|
||||||
allowCreate
|
|
||||||
/>
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
@@ -228,24 +213,6 @@ function ItemFormBody({ organization: { base_currency } }) {
|
|||||||
/>
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
{/*------------- Purchase Tax Rate ------------- */}
|
|
||||||
<FFormGroup
|
|
||||||
name={'purchase_tax_rate_id'}
|
|
||||||
label={'Tax Rate'}
|
|
||||||
inline={true}
|
|
||||||
fastField={true}
|
|
||||||
shouldUpdateDeps={{ taxRates }}
|
|
||||||
shouldUpdate={taxRateFieldShouldUpdate}
|
|
||||||
>
|
|
||||||
<TaxRatesSelect
|
|
||||||
name={'purchase_tax_rate_id'}
|
|
||||||
items={taxRates}
|
|
||||||
allowCreate={true}
|
|
||||||
fastField={true}
|
|
||||||
shouldUpdateDeps={{ taxRates }}
|
|
||||||
/>
|
|
||||||
</FFormGroup>
|
|
||||||
|
|
||||||
<FastField
|
<FastField
|
||||||
name={'purchase_description'}
|
name={'purchase_description'}
|
||||||
purchasable={values.purchasable}
|
purchasable={values.purchasable}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
useAccounts,
|
useAccounts,
|
||||||
} from '@/hooks/query';
|
} from '@/hooks/query';
|
||||||
import { useWatchItemError } from './utils';
|
import { useWatchItemError } from './utils';
|
||||||
import { useTaxRates } from '@/hooks/query/taxRates';
|
|
||||||
|
|
||||||
const ItemFormContext = createContext();
|
const ItemFormContext = createContext();
|
||||||
|
|
||||||
@@ -31,8 +30,6 @@ function ItemFormProvider({ itemId, ...props }) {
|
|||||||
data: { itemsCategories },
|
data: { itemsCategories },
|
||||||
} = useItemsCategories();
|
} = useItemsCategories();
|
||||||
|
|
||||||
const { data: taxRates, isLoading: isTaxRatesLoading } = useTaxRates();
|
|
||||||
|
|
||||||
// Fetches the given item details.
|
// Fetches the given item details.
|
||||||
const itemQuery = useItem(itemId || duplicateId, {
|
const itemQuery = useItem(itemId || duplicateId, {
|
||||||
enabled: !!itemId || !!duplicateId,
|
enabled: !!itemId || !!duplicateId,
|
||||||
@@ -72,7 +69,6 @@ function ItemFormProvider({ itemId, ...props }) {
|
|||||||
accounts,
|
accounts,
|
||||||
item,
|
item,
|
||||||
itemsCategories,
|
itemsCategories,
|
||||||
taxRates,
|
|
||||||
submitPayload,
|
submitPayload,
|
||||||
isNewMode,
|
isNewMode,
|
||||||
|
|
||||||
@@ -80,7 +76,6 @@ function ItemFormProvider({ itemId, ...props }) {
|
|||||||
isAccountsLoading,
|
isAccountsLoading,
|
||||||
isItemsCategoriesLoading,
|
isItemsCategoriesLoading,
|
||||||
isItemLoading,
|
isItemLoading,
|
||||||
isTaxRatesLoading,
|
|
||||||
|
|
||||||
createItemMutate,
|
createItemMutate,
|
||||||
editItemMutate,
|
editItemMutate,
|
||||||
|
|||||||
@@ -23,14 +23,12 @@ const defaultInitialValues = {
|
|||||||
sell_price: '',
|
sell_price: '',
|
||||||
cost_account_id: '',
|
cost_account_id: '',
|
||||||
sell_account_id: '',
|
sell_account_id: '',
|
||||||
sell_tax_rate_id: '',
|
|
||||||
inventory_account_id: '',
|
inventory_account_id: '',
|
||||||
category_id: '',
|
category_id: '',
|
||||||
sellable: 1,
|
sellable: 1,
|
||||||
purchasable: true,
|
purchasable: true,
|
||||||
sell_description: '',
|
sell_description: '',
|
||||||
purchase_description: '',
|
purchase_description: '',
|
||||||
purchase_tax_rate_id: '',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,13 +187,6 @@ export const purchaseDescFieldShouldUpdate = (newProps, oldProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const taxRateFieldShouldUpdate = (newProps, oldProps) => {
|
|
||||||
return (
|
|
||||||
newProps.shouldUpdateDeps.taxRates !== oldProps.shouldUpdateDeps.taxRates ||
|
|
||||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function transformItemsTableState(tableState) {
|
export function transformItemsTableState(tableState) {
|
||||||
return {
|
return {
|
||||||
...transformTableStateToQuery(tableState),
|
...transformTableStateToQuery(tableState),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user