diff --git a/.env.example b/.env.example
index 1222e6242..adbec32fc 100644
--- a/.env.example
+++ b/.env.example
@@ -8,7 +8,7 @@ MAIL_FROM_NAME=
MAIL_FROM_ADDRESS=
# Database
-DB_HOST=mysql
+DB_HOST=localhost
DB_USER=bigcapital
DB_PASSWORD=bigcapital
DB_ROOT_PASSWORD=root
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 000000000..9aea12456
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,22 @@
+tasks:
+ - name: Init
+ init: |
+ pnpm install &&
+ cp .env.example .env &&
+ docker-compose up -d &&
+ pnpm run build:server &&
+ node packages/server/build/commands.js system:migrate:latest
+ command: |
+ docker-compose up -d &&
+ pnpm run dev
+
+ports:
+ - port: 4000
+ visibility: public
+ onOpen: open-preview
+ - port: 3000
+ visibility: public
+ onOpen: ignore
+ - port: 3306
+ visibility: public
+ onOpen: ignore
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index aa9093c25..af05add32 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,7 +33,8 @@ Contributions via pull requests are much appreciated. Once the approach is agree
---
## Local Setup Prerequisites
- - The application currently supports **Node.js v14.x**. Please ensure that you are using this version of Node.js when developing. (use [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) to switch between node versions)
+ - The application currently supports **Node.js v18.x**.
+ - `pnpm` packages manager, (from pnpm [guide](https://pnpm.io/installation) pick any installation method).
## Contribute to Backend
@@ -44,11 +45,10 @@ Contributions via pull requests are much appreciated. Once the approach is agree
cp .env.example .env
```
-- Install all npm dependencies of the monorepo, you don't have to change directory to the `backend` package. just hit these command on root directory and it will install dependencies of all packages.
+- Install all npm dependencies of the monorepo, you don't have to change directory to the `backend` package. just hit the command on root directory and it will install dependencies of all packages.
```
-npm install
-npm run bootstrap
+pnpm install
```
- Run all required docker containers in the development, we already configured all containers under `docker-compose.yml`.
@@ -69,7 +69,7 @@ cefa73fe2881 bigcapital-redis "docker-entrypoint.s…" 7 seconds ago Up
- There're some CLI commands we should run before running the server like databaase migration, so we need to build the `server` app first.
```
-npm run build:server
+pnpm run build:server
```
- Run the database migration for system database.
@@ -87,7 +87,7 @@ Batch 1 run: 6 migrations
- Next, start the webapp application.
```
-npm run dev:server
+pnpm run dev:server
```
**[`^top^`](#)**
@@ -105,14 +105,13 @@ git clone https://github.com/bigcapital/bigcapital.git && cd bigcaptial
- Install all npm dependencies of the monorepo, you don't have to change directory to the `frontend` package. just hit that command and will install all packages across all application.
```
-npm install
-npm run bootstrap
+pnpm install
```
- Next, start the webapp application.
```
-npm run dev:webapp
+pnpm run dev:webapp
```
**[`^top^`](#)**
diff --git a/README.md b/README.md
index 9db2572d6..5476c3201 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,31 @@ Bigcapital is a smart and open-source accounting and inventory software, Bigcapi
+# Getting Started
+
+We've got serveral options on dev and prod depending on your need to get started quickly with Bigcapital.
+
+## Self-hosted
+
+Bigcapital is available open-source under AGPL license. You can host it on your own servers using Docker.
+
+### Docker
+
+To get started with self-hosted with Docker and Docker Compose, take a look at the [Docker guide](https://docs.bigcapital.ly/deployment/docker).
+
+## Development
+
+### Local Setup
+
+To get started locally, we have a [guide to help you](https://github.com/bigcapitalhq/bigcapital/blob/develop/CONTRIBUTING.md).
+
+### Gitpod
+
+- Click the Gitpod button below to open this project in development mode.
+- This will open and configure the workspace in your browser with all the necessary dependencies.
+
+[](https://gitpod.io/new/#https://github.com/bigcapitalhq/bigcapital)
+
# Resources
- [Documentation](https://docs.bigcapital.ly/) - Learn how to use.
diff --git a/packages/server/package-lock.json b/packages/server/package-lock.json
index aae0975f4..ddeea17fe 100644
--- a/packages/server/package-lock.json
+++ b/packages/server/package-lock.json
@@ -2658,12 +2658,12 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
},
- "node_modules/abab": {
+ "abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
},
- "node_modules/abbrev": {
+ "abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
@@ -3395,8 +3395,7 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/atob": {
"version": "2.1.2",
@@ -3421,13 +3420,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/axios": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
- "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==",
- "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410",
- "dependencies": {
- "follow-redirects": "^1.10.0"
+ "axios": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
+ "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
+ "requires": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-loader": {
@@ -4526,8 +4526,7 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
- "dependencies": {
+ "requires": {
"delayed-stream": "~1.0.0"
},
"engines": {
@@ -5383,11 +5382,7 @@
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"node_modules/denque": {
"version": "1.5.1",
@@ -7610,8 +7605,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dev": true,
- "dependencies": {
+ "requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
@@ -14926,9 +14920,26 @@
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "engines": {
- "node": ">=0.10.0"
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+ },
+ "source-map-loader": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz",
+ "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==",
+ "requires": {
+ "abab": "^2.0.6",
+ "iconv-lite": "^0.6.3",
+ "source-map-js": "^1.0.2"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ }
+ }
}
},
"node_modules/source-map-loader": {
diff --git a/packages/server/package.json b/packages/server/package.json
index 869ec6aef..d359376de 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -31,7 +31,7 @@
"agendash": "^3.1.0",
"app-root-path": "^3.0.0",
"async": "^3.2.0",
- "axios": "^0.20.0",
+ "axios": "^1.6.0",
"babel-loader": "^9.1.2",
"bcryptjs": "^2.4.3",
"bluebird": "^3.7.2",
@@ -102,7 +102,8 @@
"tsyringe": "^4.3.0",
"typedi": "^0.8.0",
"uniqid": "^5.2.0",
- "winston": "^3.2.1"
+ "winston": "^3.2.1",
+ "xlsx": "^0.18.5"
},
"devDependencies": {
"@types/lodash": "^4.14.158",
diff --git a/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts b/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts
index b0dc28841..5d626896c 100644
--- a/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts
@@ -2,19 +2,20 @@ import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator';
import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
-import APAgingSummaryReportService from '@/services/FinancialStatements/AgingSummary/APAgingSummaryService';
import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { APAgingSummaryApplication } from '@/services/FinancialStatements/AgingSummary/APAgingSummaryApplication';
export default class APAgingSummaryReportController extends BaseFinancialReportController {
@Inject()
- APAgingSummaryService: APAgingSummaryReportService;
+ private APAgingSummaryApp: APAgingSummaryApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -28,8 +29,9 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
/**
* Validation schema.
+ * @returns {ValidationChain[]}
*/
- get validationSchema() {
+ private get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(),
@@ -49,42 +51,58 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
}
/**
- * Retrieve payable aging summary report.
+ * Retrieves payable aging summary report.
+ * @param {Request} req -
+ * @param {Response} res -
+ * @param {NextFunction} next -
*/
- async payableAgingSummary(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
+ private async payableAgingSummary(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
+ const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+ // Retrieves the json table format.
+ if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.APAgingSummaryApp.table(tenantId, filter);
- switch (acceptType) {
- case 'application/json+table':
- const table = await this.APAgingSummaryService.APAgingSummaryTable(
- tenantId,
- filter
- );
- return res.status(200).send({
- table: {
- rows: table.rows,
- columns: table.columns,
- },
- meta: table.meta,
- query: table.query,
- });
- break;
- default:
- const { data, columns, query, meta } =
- await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
+ return res.status(200).send(table);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const csv = await this.APAgingSummaryApp.csv(tenantId, filter);
- return res.status(200).send({
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- meta: this.transfromToResponse(meta),
- });
- break;
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(csv);
+ // Retrieves the xlsx format.
+ } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.APAgingSummaryApp.xlsx(tenantId, filter);
+
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.APAgingSummaryApp.sheet(tenantId, filter);
+
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts b/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts
index 489eb04ae..10e42e900 100644
--- a/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts
@@ -5,16 +5,18 @@ import ARAgingSummaryService from '@/services/FinancialStatements/AgingSummary/A
import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { ARAgingSummaryApplication } from '@/services/FinancialStatements/AgingSummary/ARAgingSummaryApplication';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service()
export default class ARAgingSummaryReportController extends BaseFinancialReportController {
@Inject()
- ARAgingSummaryService: ARAgingSummaryService;
+ ARAgingSummaryApp: ARAgingSummaryApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -30,7 +32,7 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
/**
* AR aging summary validation roles.
*/
- get validationSchema() {
+ private get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
@@ -52,41 +54,53 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
/**
* Retrieve AR aging summary report.
+ * @param {Request} req
+ * @param {Response} res
*/
- async receivableAgingSummary(req: Request, res: Response) {
- const { tenantId, settings } = req;
+ private async receivableAgingSummary(req: Request, res: Response) {
+ const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
- switch (acceptType) {
- case 'application/json+table':
- const table = await this.ARAgingSummaryService.ARAgingSummaryTable(
- tenantId,
- filter
- );
- return res.status(200).send({
- table: {
- rows: table.rows,
- columns: table.columns,
- },
- meta: table.meta,
- query: table.query,
- });
- break;
- default:
- const { data, columns, query, meta } =
- await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+ // Retrieves the xlsx format.
+ if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.ARAgingSummaryApp.xlsx(tenantId, filter);
- return res.status(200).send({
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- meta: this.transfromToResponse(meta),
- });
- break;
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the table format.
+ } else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.ARAgingSummaryApp.table(tenantId, filter);
+
+ return res.status(200).send(table);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const buffer = await this.ARAgingSummaryApp.csv(tenantId, filter);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(buffer);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.ARAgingSummaryApp.sheet(tenantId, filter);
+
+ return res.status(200).send(sheet);
}
} catch (error) {
console.log(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts b/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts
index bc9499889..0af53d723 100644
--- a/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/BalanceSheet.ts
@@ -3,25 +3,21 @@ import { Router, Request, Response, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator';
import { castArray } from 'lodash';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
-import BalanceSheetStatementService from '@/services/FinancialStatements/BalanceSheet/BalanceSheetService';
import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
-import BalanceSheetTable from '@/services/FinancialStatements/BalanceSheet/BalanceSheetTable';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { BalanceSheetApplication } from '@/services/FinancialStatements/BalanceSheet/BalanceSheetApplication';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service()
export default class BalanceSheetStatementController extends BaseFinancialReportController {
@Inject()
- balanceSheetService: BalanceSheetStatementService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private balanceSheetApp: BalanceSheetApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -38,7 +34,7 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
* Balance sheet validation schecma.
* @returns {ValidationChain[]}
*/
- get balanceSheetValidationSchema(): ValidationChain[] {
+ private get balanceSheetValidationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
query('accounting_method').optional().isIn(['cash', 'accrual']),
@@ -84,10 +80,12 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
/**
* Retrieve the balance sheet.
+ * @param {Request} req
+ * @param {Response} res
+ * @param {NextFunction} next
*/
- async balanceSheet(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
- const i18n = this.tenancy.i18n(tenantId);
+ private async balanceSheet(req: Request, res: Response, next: NextFunction) {
+ const { tenantId } = req;
let filter = this.matchedQueryData(req);
@@ -95,29 +93,45 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
...filter,
accountsIds: castArray(filter.accountsIds),
};
-
try {
- const { data, columns, query, meta } =
- await this.balanceSheetService.balanceSheet(tenantId, filter);
-
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
- const table = new BalanceSheetTable(data, query, i18n);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ]);
+ // Retrieves the json table format.
+ if (ACCEPT_TYPE.APPLICATION_JSON_TABLE == acceptType) {
+ const table = await this.balanceSheetApp.table(tenantId, filter);
- switch (acceptType) {
- case 'application/json+table':
- return res.status(200).send({
- table: {
- rows: table.tableRows(),
- columns: table.tableColumns(),
- },
- query,
- meta,
- });
- case 'json':
- default:
- return res.status(200).send({ data, columns, query, meta });
+ return res.status(200).send(table);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const buffer = await this.balanceSheetApp.csv(tenantId, filter);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(buffer);
+ // Retrieves the xlsx format.
+ } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.balanceSheetApp.xlsx(tenantId, filter);
+
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ } else {
+ const sheet = await this.balanceSheetApp.sheet(tenantId, filter);
+
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/CashFlow/CashFlow.ts b/packages/server/src/api/controllers/FinancialStatements/CashFlow/CashFlow.ts
index df2f3f5dd..bab04246d 100644
--- a/packages/server/src/api/controllers/FinancialStatements/CashFlow/CashFlow.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/CashFlow/CashFlow.ts
@@ -8,29 +8,20 @@ import {
ValidationChain,
} from 'express';
import BaseFinancialReportController from '../BaseFinancialReportController';
-import CashFlowStatementService from '@/services/FinancialStatements/CashFlow/CashFlowService';
-import {
- ICashFlowStatementDOO,
- ICashFlowStatement,
- AbilitySubject,
- ReportsAction,
-} from '@/interfaces';
-import CashFlowTable from '@/services/FinancialStatements/CashFlow/CashFlowTable';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { CashflowSheetApplication } from '@/services/FinancialStatements/CashFlow/CashflowSheetApplication';
@Service()
export default class CashFlowController extends BaseFinancialReportController {
@Inject()
- cashFlowService: CashFlowStatementService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private cashflowSheetApp: CashflowSheetApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -47,7 +38,7 @@ export default class CashFlowController extends BaseFinancialReportController {
* Balance sheet validation schecma.
* @returns {ValidationChain[]}
*/
- get cashflowValidationSchema(): ValidationChain[] {
+ private get cashflowValidationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
query('from_date').optional(),
@@ -67,41 +58,6 @@ export default class CashFlowController extends BaseFinancialReportController {
];
}
- /**
- * Retrieve the cashflow statment to json response.
- * @param {ICashFlowStatement} cashFlow -
- */
- private transformJsonResponse(cashFlowDOO: ICashFlowStatementDOO) {
- const { data, query, meta } = cashFlowDOO;
-
- return {
- data: this.transfromToResponse(data),
- query: this.transfromToResponse(query),
- meta: this.transfromToResponse(meta),
- };
- }
-
- /**
- * Transformes the report statement to table rows.
- * @param {ITransactionsByVendorsStatement} statement -
- */
- private transformToTableRows(
- cashFlowDOO: ICashFlowStatementDOO,
- tenantId: number
- ) {
- const i18n = this.tenancy.i18n(tenantId);
- const cashFlowTable = new CashFlowTable(cashFlowDOO, i18n);
-
- return {
- table: {
- data: cashFlowTable.tableRows(),
- columns: cashFlowTable.tableColumns(),
- },
- query: this.transfromToResponse(cashFlowDOO.query),
- meta: this.transfromToResponse(cashFlowDOO.meta),
- };
- }
-
/**
* Retrieve the cash flow statment.
* @param {Request} req
@@ -109,26 +65,52 @@ export default class CashFlowController extends BaseFinancialReportController {
* @param {NextFunction} next
* @returns {Response}
*/
- async cashFlow(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
+ public async cashFlow(req: Request, res: Response, next: NextFunction) {
+ const { tenantId } = req;
const filter = {
...this.matchedQueryData(req),
};
try {
- const cashFlow = await this.cashFlowService.cashFlow(tenantId, filter);
-
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
- switch (acceptType) {
- case 'application/json+table':
- return res
- .status(200)
- .send(this.transformToTableRows(cashFlow, tenantId));
- case 'json':
- default:
- return res.status(200).send(this.transformJsonResponse(cashFlow));
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+ // Retrieves the json table format.
+ if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.cashflowSheetApp.table(tenantId, filter);
+
+ return res.status(200).send(table);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const buffer = await this.cashflowSheetApp.csv(tenantId, filter);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.status(200).send(buffer);
+ // Retrieves the pdf format.
+ } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.cashflowSheetApp.xlsx(tenantId, filter);
+
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the json format.
+ } else {
+ const cashflow = await this.cashflowSheetApp.sheet(tenantId, filter);
+
+ return res.status(200).send(cashflow);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
index eb026e752..6c10543f5 100644
--- a/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
@@ -1,29 +1,21 @@
import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator';
import { Inject } from 'typedi';
-import {
- AbilitySubject,
- ICustomerBalanceSummaryStatement,
- ReportsAction,
-} from '@/interfaces';
+import { AbilitySubject, ReportsAction } from '@/interfaces';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
-import CustomerBalanceSummary from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService';
import BaseFinancialReportController from '../BaseFinancialReportController';
-import CustomerBalanceSummaryTableRows from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows';
import CheckPolicies from '@/api/middleware/CheckPolicies';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { CustomerBalanceSummaryApplication } from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication';
export default class CustomerBalanceSummaryReportController extends BaseFinancialReportController {
@Inject()
- customerBalanceSummaryService: CustomerBalanceSummary;
-
- @Inject()
- tenancy: HasTenancyService;
+ private customerBalanceSummaryApp: CustomerBalanceSummaryApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -42,7 +34,7 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia
/**
* Validation schema.
*/
- get validationSchema() {
+ private get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
@@ -62,75 +54,67 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia
];
}
- /**
- * Transformes the balance summary statement to table rows.
- * @param {ICustomerBalanceSummaryStatement} statement -
- */
- private transformToTableRows(
- tenantId,
- { data, query }: ICustomerBalanceSummaryStatement
- ) {
- const i18n = this.tenancy.i18n(tenantId);
- const tableRows = new CustomerBalanceSummaryTableRows(data, query, i18n);
-
- return {
- table: {
- columns: tableRows.tableColumns(),
- data: tableRows.tableRows(),
- },
- query: this.transfromToResponse(query),
- };
- }
-
- /**
- * Transformes the balance summary statement to raw json.
- * @param {ICustomerBalanceSummaryStatement} customerBalance -
- */
- private transformToJsonResponse({
- data,
- columns,
- query,
- }: ICustomerBalanceSummaryStatement) {
- return {
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- };
- }
-
/**
* Retrieve payable aging summary report.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
- async customerBalanceSummary(
+ private async customerBalanceSummary(
req: Request,
res: Response,
next: NextFunction
) {
- const { tenantId, settings } = req;
+ const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
- const customerBalanceSummary =
- await this.customerBalanceSummaryService.customerBalanceSummary(
+ const accept = this.accepts(req);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+
+ // Retrieves the xlsx format.
+ if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.customerBalanceSummaryApp.xlsx(
tenantId,
filter
);
- const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const buffer = await this.customerBalanceSummaryApp.csv(
+ tenantId,
+ filter
+ );
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
- switch (acceptType) {
- case 'application/json+table':
- return res
- .status(200)
- .send(this.transformToTableRows(tenantId, customerBalanceSummary));
- case 'application/json':
- default:
- return res
- .status(200)
- .send(this.transformToJsonResponse(customerBalanceSummary));
+ return res.send(buffer);
+ // Retrieves the json table format.
+ } else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.customerBalanceSummaryApp.table(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(table);
+ } else {
+ const sheet = await this.customerBalanceSummaryApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts b/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
index 2f8df7722..07f91af4a 100644
--- a/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
@@ -8,24 +8,20 @@ import {
ValidationChain,
} from 'express';
import BaseController from '@/api/controllers/BaseController';
-import InventoryDetailsService from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsService';
-import InventoryDetailsTable from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsTable';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
import { AbilitySubject, ReportsAction } from '@/interfaces';
+import { InventortyDetailsApplication } from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service()
export default class InventoryDetailsController extends BaseController {
@Inject()
- inventoryDetailsService: InventoryDetailsService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private inventoryItemDetailsApp: InventortyDetailsApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -45,7 +41,7 @@ export default class InventoryDetailsController extends BaseController {
* Balance sheet validation schecma.
* @returns {ValidationChain[]}
*/
- get validationSchema(): ValidationChain[] {
+ private get validationSchema(): ValidationChain[] {
return [
query('number_format.precision')
.optional()
@@ -77,69 +73,66 @@ export default class InventoryDetailsController extends BaseController {
}
/**
- * Retrieve the cashflow statment to json response.
- * @param {ICashFlowStatement} cashFlow -
- */
- private transformJsonResponse(inventoryDetails) {
- const { data, query, meta } = inventoryDetails;
-
- return {
- data: this.transfromToResponse(data),
- query: this.transfromToResponse(query),
- meta: this.transfromToResponse(meta),
- };
- }
-
- /**
- * Transformes the report statement to table rows.
- */
- private transformToTableRows(inventoryDetails, tenantId: number) {
- const i18n = this.tenancy.i18n(tenantId);
- const inventoryDetailsTable = new InventoryDetailsTable(
- inventoryDetails,
- i18n
- );
-
- return {
- table: {
- data: inventoryDetailsTable.tableData(),
- columns: inventoryDetailsTable.tableColumns(),
- },
- query: this.transfromToResponse(inventoryDetails.query),
- meta: this.transfromToResponse(inventoryDetails.meta),
- };
- }
-
- /**
- * Retrieve the cash flow statment.
+ * Retrieve the inventory item details sheet.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
* @returns {Response}
*/
- async inventoryDetails(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
+ private async inventoryDetails(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
+ const { tenantId } = req;
const filter = {
...this.matchedQueryData(req),
};
try {
- const inventoryDetails =
- await this.inventoryDetailsService.inventoryDetails(tenantId, filter);
-
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+ // Retrieves the csv format.
+ if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) {
+ const buffer = await this.inventoryItemDetailsApp.csv(tenantId, filter);
- switch (acceptType) {
- case 'application/json+table':
- return res
- .status(200)
- .send(this.transformToTableRows(inventoryDetails, tenantId));
- case 'json':
- default:
- return res
- .status(200)
- .send(this.transformJsonResponse(inventoryDetails));
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(buffer);
+ // Retrieves the xlsx format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) {
+ const buffer = await this.inventoryItemDetailsApp.xlsx(
+ tenantId,
+ filter
+ );
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the json table format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) {
+ const table = await this.inventoryItemDetailsApp.table(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(table);
+ } else {
+ const sheet = await this.inventoryItemDetailsApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts b/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts
index 233654dc0..8c2404335 100644
--- a/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/ProfitLossSheet.ts
@@ -1,24 +1,20 @@
import { Service, Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator';
-import ProfitLossSheetService from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService';
import BaseFinancialReportController from './BaseFinancialReportController';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { AbilitySubject, ReportsAction } from '@/interfaces';
-import { ProfitLossSheetTable } from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { ProfitLossSheetApplication } from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetApplication';
@Service()
export default class ProfitLossSheetController extends BaseFinancialReportController {
@Inject()
- profitLossSheetService: ProfitLossSheetService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private profitLossSheetApp: ProfitLossSheetApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -34,7 +30,7 @@ export default class ProfitLossSheetController extends BaseFinancialReportContro
/**
* Validation schema.
*/
- get validationSchema(): ValidationChain[] {
+ private get validationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
query('basis').optional(),
@@ -85,37 +81,54 @@ export default class ProfitLossSheetController extends BaseFinancialReportContro
* @param {Request} req -
* @param {Response} res -
*/
- async profitLossSheet(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
- const i18n = this.tenancy.i18n(tenantId);
+ private async profitLossSheet(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
+ const { tenantId } = req;
const filter = this.matchedQueryData(req);
+ const accept = this.accepts(req);
+
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
try {
- const { data, query, meta } =
- await this.profitLossSheetService.profitLossSheet(tenantId, filter);
+ // Retrieves the csv format.
+ if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) {
+ const sheet = await this.profitLossSheetApp.csv(tenantId, filter);
- const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
- switch (acceptType) {
- case 'application/json+table':
- const table = new ProfitLossSheetTable(data, query, i18n);
+ return res.send(sheet);
+ // Retrieves the json table format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) {
+ const table = await this.profitLossSheetApp.table(tenantId, filter);
- return res.status(200).send({
- table: {
- rows: table.tableRows(),
- columns: table.tableColumns(),
- },
- query,
- meta,
- });
- case 'json':
- default:
- return res.status(200).send({
- data,
- query,
- meta,
- });
+ return res.status(200).send(table);
+ // Retrieves the xlsx format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) {
+ const sheet = await this.profitLossSheetApp.xlsx(tenantId, filter);
+
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(sheet);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.profitLossSheetApp.sheet(tenantId, filter);
+
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts
index 759165bd1..d31954398 100644
--- a/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/SalesByItems.ts
@@ -16,15 +16,12 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
'/',
- CheckPolicies(
- ReportsAction.READ_SALES_BY_ITEMS,
- AbilitySubject.Report
- ),
+ CheckPolicies(ReportsAction.READ_SALES_BY_ITEMS, AbilitySubject.Report),
this.validationSchema,
this.validationResult,
asyncMiddleware(this.purchasesByItems.bind(this))
@@ -35,7 +32,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
/**
* Validation schema.
*/
- get validationSchema(): ValidationChain[] {
+ private get validationSchema(): ValidationChain[] {
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
@@ -63,7 +60,11 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
* @param {Request} req -
* @param {Response} res -
*/
- async purchasesByItems(req: Request, res: Response, next: NextFunction) {
+ private async purchasesByItems(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
const { tenantId } = req;
const filter = this.matchedQueryData(req);
diff --git a/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts
index 56c837288..933b5c9c4 100644
--- a/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/SalesTaxLiabilitySummary/index.ts
@@ -1,20 +1,21 @@
+import { Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator';
-import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
-import { SalesTaxLiabilitySummaryService } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService';
+import { SalesTaxLiabilitySummaryApplication } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
export default class SalesTaxLiabilitySummary extends BaseFinancialReportController {
@Inject()
- private salesTaxLiabilitySummaryService: SalesTaxLiabilitySummaryService;
+ private salesTaxLiabilitySummaryApp: SalesTaxLiabilitySummaryApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -31,8 +32,9 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
/**
* Validation schema.
+ * @returns {ValidationChain[]}
*/
- get validationSchema() {
+ private get validationSchema() {
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
@@ -45,7 +47,7 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
* @param {Response} res -
* @param {NextFunction} next -
*/
- async salesTaxLiabilitySummary(
+ private async salesTaxLiabilitySummary(
req: Request,
res: Response,
next: NextFunction
@@ -55,33 +57,52 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
try {
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
- switch (acceptType) {
- case 'application/json+table':
- const salesTaxLiabilityTable =
- await this.salesTaxLiabilitySummaryService.salesTaxLiabilitySummaryTable(
- tenantId,
- filter
- );
+ // Retrieves the json table format.
+ if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) {
+ const table = await this.salesTaxLiabilitySummaryApp.table(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(table);
+ // Retrieves the xlsx format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) {
+ const buffer = await this.salesTaxLiabilitySummaryApp.xlsx(
+ tenantId,
+ filter
+ );
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves the csv format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) {
+ const buffer = await this.salesTaxLiabilitySummaryApp.csv(
+ tenantId,
+ filter
+ );
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
- return res.status(200).send({
- table: salesTaxLiabilityTable.table,
- query: salesTaxLiabilityTable.query,
- meta: salesTaxLiabilityTable.meta,
- });
- case 'json':
- default:
- const salesTaxLiability =
- await this.salesTaxLiabilitySummaryService.salesTaxLiability(
- tenantId,
- filter
- );
- return res.status(200).send({
- data: salesTaxLiability.data,
- query: salesTaxLiability.query,
- meta: salesTaxLiability.meta,
- });
+ return res.send(buffer);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.salesTaxLiabilitySummaryApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts b/packages/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
index fa20ea3f3..4bc3b1f44 100644
--- a/packages/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
@@ -1,30 +1,22 @@
import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator';
import { Inject, Service } from 'typedi';
-import {
- AbilitySubject,
- ITransactionsByCustomersStatement,
- ReportsAction,
-} from '@/interfaces';
+import { AbilitySubject, ReportsAction } from '@/interfaces';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController';
-import TransactionsByCustomersService from '@/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService';
-import TransactionsByCustomersTableRows from '@/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableRows';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { TransactionsByCustomerApplication } from '@/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersApplication';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service()
export default class TransactionsByCustomersReportController extends BaseFinancialReportController {
@Inject()
- transactionsByCustomersService: TransactionsByCustomersService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private transactionsByCustomersApp: TransactionsByCustomerApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -58,45 +50,13 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
];
}
- /**
- * Transformes the statement to table rows response.
- * @param {ITransactionsByCustomersStatement} statement -
- */
- private transformToTableResponse(customersTransactions, tenantId) {
- const i18n = this.tenancy.i18n(tenantId);
- const table = new TransactionsByCustomersTableRows(
- customersTransactions,
- i18n
- );
- return {
- table: {
- rows: table.tableRows(),
- },
- };
- }
-
- /**
- * Transformes the statement to json response.
- * @param {ITransactionsByCustomersStatement} statement -
- */
- private transfromToJsonResponse(
- data,
- columns
- ): ITransactionsByCustomersStatement {
- return {
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- };
- }
-
/**
* Retrieve payable aging summary report.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
- async transactionsByCustomers(
+ private async transactionsByCustomers(
req: Request,
res: Response,
next: NextFunction
@@ -104,25 +64,51 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
const { tenantId } = req;
const filter = this.matchedQueryData(req);
+ const accept = this.accepts(req);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
try {
- const report =
- await this.transactionsByCustomersService.transactionsByCustomers(
+ // Retrieves the json table format.
+ if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.transactionsByCustomersApp.table(
tenantId,
filter
);
- const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
+ return res.status(200).send(table);
+ // Retrieve the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const csv = await this.transactionsByCustomersApp.csv(tenantId, filter);
- switch (acceptType) {
- case 'json':
- return res
- .status(200)
- .send(this.transfromToJsonResponse(report.data, report.columns));
- case 'application/json+table':
- default:
- return res
- .status(200)
- .send(this.transformToTableResponse(report.data, tenantId));
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(csv);
+ // Retrieve the xlsx format.
+ } else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.transactionsByCustomersApp.xlsx(
+ tenantId,
+ filter
+ );
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieve the json format.
+ } else {
+ const sheet = await this.transactionsByCustomersApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts b/packages/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
index eaf8e6725..a0c1bf037 100644
--- a/packages/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
@@ -3,27 +3,19 @@ import { query, ValidationChain } from 'express-validator';
import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController';
-import TransactionsByVendorsTableRows from '@/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableRows';
-import TransactionsByVendorsService from '@/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService';
-import {
- AbilitySubject,
- ITransactionsByVendorsStatement,
- ReportsAction,
-} from '@/interfaces';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { TransactionsByVendorApplication } from '@/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorApplication';
export default class TransactionsByVendorsReportController extends BaseFinancialReportController {
@Inject()
- transactionsByVendorsService: TransactionsByVendorsService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private transactionsByVendorsApp: TransactionsByVendorApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -42,7 +34,7 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
/**
* Validation schema.
*/
- get validationSchema(): ValidationChain[] {
+ private get validationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
@@ -58,64 +50,64 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
];
}
- /**
- * Transformes the report statement to table rows.
- * @param {ITransactionsByVendorsStatement} statement -
- */
- private transformToTableRows(tenantId: number, transactions: any[]) {
- const i18n = this.tenancy.i18n(tenantId);
- const table = new TransactionsByVendorsTableRows(transactions, i18n);
-
- return {
- table: {
- data: table.tableRows(),
- },
- };
- }
-
- /**
- * Transformes the report statement to json response.
- * @param {ITransactionsByVendorsStatement} statement -
- */
- private transformToJsonResponse({
- data,
- columns,
- query,
- }: ITransactionsByVendorsStatement) {
- return {
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- };
- }
-
/**
* Retrieve payable aging summary report.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
- async transactionsByVendors(req: Request, res: Response, next: NextFunction) {
+ private async transactionsByVendors(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
- const report =
- await this.transactionsByVendorsService.transactionsByVendors(
+ const accept = this.accepts(req);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+
+ // Retrieves the xlsx format.
+ if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
+ const buffer = await this.transactionsByVendorsApp.xlsx(
tenantId,
filter
);
- const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
-
- switch (acceptType) {
- case 'application/json+table':
- return res
- .status(200)
- .send(this.transformToTableRows(tenantId, report.data));
- case 'json':
- default:
- return res.status(200).send(this.transformToJsonResponse(report));
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=report.xlsx'
+ );
+ return res.send(buffer);
+ // Retrieves the csv format.
+ } else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
+ const buffer = await this.transactionsByVendorsApp.csv(
+ tenantId,
+ filter
+ );
+ res.setHeader('Content-Type', 'text/csv');
+ res.setHeader('Content-Disposition', 'attachment; filename=report.csv');
+ return res.send(buffer);
+ // Retrieves the json table format.
+ } else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
+ const table = await this.transactionsByVendorsApp.table(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(table);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.transactionsByVendorsApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/api/controllers/FinancialStatements/TrialBalanceSheet.ts b/packages/server/src/api/controllers/FinancialStatements/TrialBalanceSheet.ts
index da59287e4..ce23c1071 100644
--- a/packages/server/src/api/controllers/FinancialStatements/TrialBalanceSheet.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/TrialBalanceSheet.ts
@@ -3,15 +3,17 @@ import { Request, Response, Router, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator';
import { castArray } from 'lodash';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
-import TrialBalanceSheetService from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService';
+import TrialBalanceSheetService from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetInjectable';
import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
+import { TrialBalanceSheetApplication } from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service()
export default class TrialBalanceSheetController extends BaseFinancialReportController {
@Inject()
- trialBalanceSheetService: TrialBalanceSheetService;
+ private trialBalanceSheetApp: TrialBalanceSheetApplication;
/**
* Router constructor.
@@ -73,21 +75,46 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
};
try {
const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
- if (acceptType === 'application/json+table') {
- const { table, meta, query } =
- await this.trialBalanceSheetService.trialBalanceSheetTable(
- tenantId,
- filter
- );
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+ // Retrieves in json table format.
+ if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) {
+ const { table, meta, query } = await this.trialBalanceSheetApp.table(
+ tenantId,
+ filter
+ );
return res.status(200).send({ table, meta, query });
+ // Retrieves in xlsx format
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) {
+ const buffer = await this.trialBalanceSheetApp.xlsx(tenantId, filter);
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader(
+ 'Content-Type',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+ );
+ return res.send(buffer);
+ // Retrieves in csv format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) {
+ const buffer = await this.trialBalanceSheetApp.csv(tenantId, filter);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(buffer);
+ // Retrieves in json format.
} else {
- const { data, query, meta } =
- await this.trialBalanceSheetService.trialBalanceSheet(
- tenantId,
- filter
- );
+ const { data, query, meta } = await this.trialBalanceSheetApp.sheet(
+ tenantId,
+ filter
+ );
return res.status(200).send({ data, query, meta });
}
} catch (error) {
diff --git a/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts b/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
index e93891938..ade69cb62 100644
--- a/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
+++ b/packages/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
@@ -3,27 +3,19 @@ import { query } from 'express-validator';
import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController';
-import VendorBalanceSummaryTableRows from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows';
-import VendorBalanceSummaryService from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService';
-import {
- AbilitySubject,
- IVendorBalanceSummaryStatement,
- ReportsAction,
-} from '@/interfaces';
+import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
-import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { ACCEPT_TYPE } from '@/interfaces/Http';
+import { VendorBalanceSummaryApplication } from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication';
export default class VendorBalanceSummaryReportController extends BaseFinancialReportController {
@Inject()
- vendorBalanceSummaryService: VendorBalanceSummaryService;
-
- @Inject()
- tenancy: HasTenancyService;
+ private vendorBalanceSummaryApp: VendorBalanceSummaryApplication;
/**
* Router constructor.
*/
- router() {
+ public router() {
const router = Router();
router.get(
@@ -41,7 +33,7 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR
/**
* Validation schema.
*/
- get validationSchema() {
+ private get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(),
@@ -59,73 +51,62 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR
];
}
- /**
- * Transformes the report statement to table rows.
- * @param {IVendorBalanceSummaryStatement} statement -
- */
- private transformToTableRows(
- tenantId: number,
- { data, query }: IVendorBalanceSummaryStatement
- ) {
- const i18n = this.tenancy.i18n(tenantId);
- const tableData = new VendorBalanceSummaryTableRows(
- data,
- query,
- i18n
- );
- return {
- table: {
- columns: tableData.tableColumns(),
- data: tableData.tableRows(),
- },
- query,
- };
- }
-
- /**
- * Transformes the report statement to raw json.
- * @param {IVendorBalanceSummaryStatement} statement -
- */
- private transformToJsonResponse({
- data,
- columns,
- }: IVendorBalanceSummaryStatement) {
- return {
- data: this.transfromToResponse(data),
- columns: this.transfromToResponse(columns),
- query: this.transfromToResponse(query),
- };
- }
-
/**
* Retrieve vendors balance summary.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
- async vendorBalanceSummary(req: Request, res: Response, next: NextFunction) {
- const { tenantId, settings } = req;
+ public async vendorBalanceSummary(
+ req: Request,
+ res: Response,
+ next: NextFunction
+ ) {
+ const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
- const vendorBalanceSummary =
- await this.vendorBalanceSummaryService.vendorBalanceSummary(
+ const accept = this.accepts(req);
+ const acceptType = accept.types([
+ ACCEPT_TYPE.APPLICATION_JSON,
+ ACCEPT_TYPE.APPLICATION_JSON_TABLE,
+ ACCEPT_TYPE.APPLICATION_CSV,
+ ACCEPT_TYPE.APPLICATION_XLSX,
+ ]);
+
+ // Retrieves the csv format.
+ if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) {
+ const buffer = await this.vendorBalanceSummaryApp.csv(tenantId, filter);
+
+ res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
+ res.setHeader('Content-Type', 'text/csv');
+
+ return res.send(buffer);
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) {
+ const buffer = await this.vendorBalanceSummaryApp.xlsx(
tenantId,
filter
);
- const accept = this.accepts(req);
- const acceptType = accept.types(['json', 'application/json+table']);
-
- switch (acceptType) {
- case 'application/json+table':
- return res
- .status(200)
- .send(this.transformToTableRows(tenantId, vendorBalanceSummary));
- case 'json':
- default:
- return res
- .status(200)
- .send(this.transformToJsonResponse(vendorBalanceSummary));
+ res.setHeader(
+ 'Content-Disposition',
+ 'attachment; filename=output.xlsx'
+ );
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+ return res.send(buffer);
+ // Retrieves the json table format.
+ } else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) {
+ const table = await this.vendorBalanceSummaryApp.table(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(table);
+ // Retrieves the json format.
+ } else {
+ const sheet = await this.vendorBalanceSummaryApp.sheet(
+ tenantId,
+ filter
+ );
+ return res.status(200).send(sheet);
}
} catch (error) {
next(error);
diff --git a/packages/server/src/interfaces/APAgingSummaryReport.ts b/packages/server/src/interfaces/APAgingSummaryReport.ts
index db6626167..6bf7c83bb 100644
--- a/packages/server/src/interfaces/APAgingSummaryReport.ts
+++ b/packages/server/src/interfaces/APAgingSummaryReport.ts
@@ -8,6 +8,7 @@ import {
IAgingSummaryData,
} from './AgingReport';
import { INumberFormatQuery } from './FinancialStatements';
+import { IFinancialTable } from './Table';
export interface IAPAgingSummaryQuery extends IAgingSummaryQuery {
vendorsIds: number[];
@@ -34,3 +35,8 @@ export interface IAPAgingSummaryMeta {
baseCurrency: string;
organizationName: string;
}
+
+export interface IAPAgingSummaryTable extends IFinancialTable {
+ query: IAPAgingSummaryQuery;
+ meta: IAPAgingSummaryMeta;
+}
diff --git a/packages/server/src/interfaces/ARAgingSummaryReport.ts b/packages/server/src/interfaces/ARAgingSummaryReport.ts
index 7d25e2b2c..d42fc8f7f 100644
--- a/packages/server/src/interfaces/ARAgingSummaryReport.ts
+++ b/packages/server/src/interfaces/ARAgingSummaryReport.ts
@@ -5,6 +5,7 @@ import {
IAgingSummaryContact,
IAgingSummaryData,
} from './AgingReport';
+import { IFinancialTable } from './Table';
export interface IARAgingSummaryQuery extends IAgingSummaryQuery {
customersIds: number[];
@@ -26,3 +27,8 @@ export interface IARAgingSummaryMeta {
organizationName: string;
baseCurrency: string;
}
+
+export interface IARAgingSummaryTable extends IFinancialTable {
+ meta: IARAgingSummaryMeta;
+ query: IARAgingSummaryQuery;
+}
diff --git a/packages/server/src/interfaces/BalanceSheet.ts b/packages/server/src/interfaces/BalanceSheet.ts
index 4dad88e55..a74e48ee8 100644
--- a/packages/server/src/interfaces/BalanceSheet.ts
+++ b/packages/server/src/interfaces/BalanceSheet.ts
@@ -3,6 +3,7 @@ import {
IFormatNumberSettings,
IFinancialSheetBranchesQuery,
} from './FinancialStatements';
+import { IFinancialTable } from './Table';
// Balance sheet schema nodes types.
export enum BALANCE_SHEET_SCHEMA_NODE_TYPE {
@@ -215,3 +216,8 @@ export enum IAccountTransactionsGroupBy {
Month = 'month',
Week = 'week',
}
+
+export interface IBalanceSheetTable extends IFinancialTable {
+ meta: IBalanceSheetMeta;
+ query: IBalanceSheetQuery;
+}
diff --git a/packages/server/src/interfaces/CashFlow.ts b/packages/server/src/interfaces/CashFlow.ts
index e9a2dc8cd..1a4a1a6a1 100644
--- a/packages/server/src/interfaces/CashFlow.ts
+++ b/packages/server/src/interfaces/CashFlow.ts
@@ -1,7 +1,7 @@
import { INumberFormatQuery } from './FinancialStatements';
import { IAccount } from './Account';
import { ILedger } from './Ledger';
-import { ITableRow } from './Table';
+import { IFinancialTable, ITableRow } from './Table';
export interface ICashFlowStatementQuery {
fromDate: Date | string;
@@ -101,6 +101,11 @@ export interface ICashFlowStatementDOO {
query: ICashFlowStatementQuery;
}
+export interface ICashFlowStatementTable extends IFinancialTable {
+ meta: ICashFlowStatementMeta;
+ query: ICashFlowStatementQuery;
+}
+
export interface ICashFlowStatementService {
cashFlow(
tenantId: number,
diff --git a/packages/server/src/interfaces/CustomerBalanceSummary.ts b/packages/server/src/interfaces/CustomerBalanceSummary.ts
index cda13f7c9..cf5b5900d 100644
--- a/packages/server/src/interfaces/CustomerBalanceSummary.ts
+++ b/packages/server/src/interfaces/CustomerBalanceSummary.ts
@@ -1,11 +1,10 @@
-import { INumberFormatQuery } from './FinancialStatements';
-
import {
IContactBalanceSummaryQuery,
IContactBalanceSummaryAmount,
IContactBalanceSummaryPercentage,
IContactBalanceSummaryTotal,
} from './ContactBalanceSummary';
+import { IFinancialTable } from './Table';
export interface ICustomerBalanceSummaryQuery
extends IContactBalanceSummaryQuery {
@@ -19,7 +18,7 @@ export interface ICustomerBalanceSummaryPercentage
extends IContactBalanceSummaryPercentage {}
export interface ICustomerBalanceSummaryCustomer {
- id: number,
+ id: number;
customerName: string;
total: ICustomerBalanceSummaryAmount;
percentageOfColumn?: ICustomerBalanceSummaryPercentage;
@@ -47,3 +46,7 @@ export interface ICustomerBalanceSummaryService {
query: ICustomerBalanceSummaryQuery
): Promise;
}
+
+export interface ICustomerBalanceSummaryTable extends IFinancialTable {
+ query: ICustomerBalanceSummaryQuery;
+}
diff --git a/packages/server/src/interfaces/Http.ts b/packages/server/src/interfaces/Http.ts
new file mode 100644
index 000000000..2189cb106
--- /dev/null
+++ b/packages/server/src/interfaces/Http.ts
@@ -0,0 +1,7 @@
+export const ACCEPT_TYPE = {
+ APPLICATION_PDF: 'application/pdf',
+ APPLICATION_JSON: 'application/json',
+ APPLICATION_JSON_TABLE: 'application/json+table',
+ APPLICATION_XLSX: 'application/xlsx',
+ APPLICATION_CSV: 'application/csv',
+};
diff --git a/packages/server/src/interfaces/InventoryDetails.ts b/packages/server/src/interfaces/InventoryDetails.ts
index 733cb588a..033ec269d 100644
--- a/packages/server/src/interfaces/InventoryDetails.ts
+++ b/packages/server/src/interfaces/InventoryDetails.ts
@@ -1,13 +1,12 @@
-import {
- INumberFormatQuery,
-} from './FinancialStatements';
+import { INumberFormatQuery } from './FinancialStatements';
+import { IFinancialTable } from './Table';
export interface IInventoryDetailsQuery {
fromDate: Date | string;
toDate: Date | string;
numberFormat: INumberFormatQuery;
noneTransactions: boolean;
- itemsIds: number[]
+ itemsIds: number[];
warehousesIds?: number[];
branchesIds?: number[];
@@ -66,7 +65,7 @@ export interface IInventoryDetailsItemTransaction {
cost: IInventoryDetailsNumber;
value: IInventoryDetailsNumber;
profitMargin: IInventoryDetailsNumber;
-
+
rate: IInventoryDetailsNumber;
runningQuantity: IInventoryDetailsNumber;
@@ -80,7 +79,6 @@ export type IInventoryDetailsNode =
| IInventoryDetailsItemTransaction;
export type IInventoryDetailsData = IInventoryDetailsItem[];
-
export interface IInventoryItemDetailMeta {
isCostComputeRunning: boolean;
organizationName: string;
@@ -91,4 +89,9 @@ export interface IInvetoryItemDetailDOO {
data: IInventoryDetailsData;
query: IInventoryDetailsQuery;
meta: IInventoryItemDetailMeta;
-}
\ No newline at end of file
+}
+
+export interface IInvetoryItemDetailsTable extends IFinancialTable {
+ query: IInventoryDetailsQuery;
+ meta: IInventoryItemDetailMeta;
+}
diff --git a/packages/server/src/interfaces/ProfitLossSheet.ts b/packages/server/src/interfaces/ProfitLossSheet.ts
index 4f2eec656..944a0a950 100644
--- a/packages/server/src/interfaces/ProfitLossSheet.ts
+++ b/packages/server/src/interfaces/ProfitLossSheet.ts
@@ -2,6 +2,7 @@ import {
IFinancialSheetBranchesQuery,
INumberFormatQuery,
} from './FinancialStatements';
+import { IFinancialTable } from './Table';
export enum ProfitLossAggregateNodeId {
INCOME = 'INCOME',
@@ -177,3 +178,9 @@ export enum ProfitLossSheetRowType {
ACCOUNT = 'ACCOUNT',
TOTAL = 'TOTAL',
}
+
+
+export interface IProfitLossSheetTable extends IFinancialTable{
+ meta: IProfitLossSheetMeta;
+ query: IProfitLossSheetQuery;
+}
\ No newline at end of file
diff --git a/packages/server/src/interfaces/SalesTaxLiabilitySummary.ts b/packages/server/src/interfaces/SalesTaxLiabilitySummary.ts
index 8b04c9719..2fbc9f13d 100644
--- a/packages/server/src/interfaces/SalesTaxLiabilitySummary.ts
+++ b/packages/server/src/interfaces/SalesTaxLiabilitySummary.ts
@@ -1,3 +1,5 @@
+import { IFinancialTable } from "./Table";
+
export interface SalesTaxLiabilitySummaryQuery {
fromDate: Date;
toDate: Date;
@@ -49,3 +51,8 @@ export interface SalesTaxLiabilitySummaryMeta {
organizationName: string;
baseCurrency: string;
}
+
+export interface ISalesTaxLiabilitySummaryTable extends IFinancialTable {
+ query: SalesTaxLiabilitySummaryQuery;
+ meta: SalesTaxLiabilitySummaryMeta;
+}
\ No newline at end of file
diff --git a/packages/server/src/interfaces/Table.ts b/packages/server/src/interfaces/Table.ts
index 28ff72f5c..a567d2d92 100644
--- a/packages/server/src/interfaces/Table.ts
+++ b/packages/server/src/interfaces/Table.ts
@@ -10,7 +10,7 @@ export interface ITableCell {
}
export type ITableRow = {
- rows: ITableCell[];
+ cells: ITableCell[];
};
export interface ITableColumn {
@@ -28,4 +28,13 @@ export interface ITable {
export interface ITableColumnAccessor {
key: string;
accessor: string;
-}
\ No newline at end of file
+}
+
+export interface ITableData {
+ columns: ITableColumn[];
+ rows: ITableRow[];
+}
+
+export interface IFinancialTable {
+ table: ITableData;
+}
diff --git a/packages/server/src/interfaces/TransactionsByCustomers.ts b/packages/server/src/interfaces/TransactionsByCustomers.ts
index fe2fbf5e2..fcfb01ea6 100644
--- a/packages/server/src/interfaces/TransactionsByCustomers.ts
+++ b/packages/server/src/interfaces/TransactionsByCustomers.ts
@@ -1,3 +1,4 @@
+import { IFinancialTable, ITableData } from './Table';
import {
ITransactionsByContactsAmount,
ITransactionsByContactsTransaction,
@@ -26,6 +27,11 @@ export type ITransactionsByCustomersData = ITransactionsByCustomersCustomer[];
export interface ITransactionsByCustomersStatement {
data: ITransactionsByCustomersData;
+ query: ITransactionsByCustomersFilter;
+}
+
+export interface ITransactionsByCustomersTable extends IFinancialTable {
+ query: ITransactionsByCustomersFilter;
}
export interface ITransactionsByCustomersService {
diff --git a/packages/server/src/interfaces/TransactionsByVendors.ts b/packages/server/src/interfaces/TransactionsByVendors.ts
index 107c7662e..ae129bc79 100644
--- a/packages/server/src/interfaces/TransactionsByVendors.ts
+++ b/packages/server/src/interfaces/TransactionsByVendors.ts
@@ -1,3 +1,4 @@
+import { IFinancialTable } from './Table';
import {
ITransactionsByContactsAmount,
ITransactionsByContactsTransaction,
@@ -34,3 +35,7 @@ export interface ITransactionsByVendorsService {
filter: ITransactionsByVendorsFilter
): Promise;
}
+
+export interface ITransactionsByVendorTable extends IFinancialTable {
+ query: ITransactionsByVendorsFilter;
+}
\ No newline at end of file
diff --git a/packages/server/src/interfaces/TrialBalanceSheet.ts b/packages/server/src/interfaces/TrialBalanceSheet.ts
index 56f13e7fa..f423503ae 100644
--- a/packages/server/src/interfaces/TrialBalanceSheet.ts
+++ b/packages/server/src/interfaces/TrialBalanceSheet.ts
@@ -1,4 +1,5 @@
import { INumberFormatQuery } from './FinancialStatements';
+import { IFinancialTable } from './Table';
export interface ITrialBalanceSheetQuery {
fromDate: Date | string;
@@ -48,3 +49,8 @@ export interface ITrialBalanceStatement {
query: ITrialBalanceSheetQuery;
meta: ITrialBalanceSheetMeta;
}
+
+export interface ITrialBalanceSheetTable extends IFinancialTable {
+ meta: ITrialBalanceSheetMeta;
+ query: ITrialBalanceSheetQuery;
+}
diff --git a/packages/server/src/interfaces/VendorBalanceSummary.ts b/packages/server/src/interfaces/VendorBalanceSummary.ts
index af75b2d67..d214202df 100644
--- a/packages/server/src/interfaces/VendorBalanceSummary.ts
+++ b/packages/server/src/interfaces/VendorBalanceSummary.ts
@@ -1,8 +1,9 @@
import { INumberFormatQuery } from './FinancialStatements';
+import { IFinancialTable } from './Table';
export interface IVendorBalanceSummaryQuery {
asDate: Date;
- vendorsIds: number[],
+ vendorsIds: number[];
numberFormat: INumberFormatQuery;
percentageColumn: boolean;
noneTransactions: boolean;
@@ -45,6 +46,10 @@ export interface IVendorBalanceSummaryStatement {
export interface IVendorBalanceSummaryService {
vendorBalanceSummary(
tenantId: number,
- query: IVendorBalanceSummaryQuery,
+ query: IVendorBalanceSummaryQuery
): Promise;
}
+
+export interface IVendorBalanceSummaryTable extends IFinancialTable {
+ query: IVendorBalanceSummaryQuery;
+}
diff --git a/packages/server/src/lib/Xlsx/TableSheet.tsx b/packages/server/src/lib/Xlsx/TableSheet.tsx
new file mode 100644
index 000000000..5bffd1bcf
--- /dev/null
+++ b/packages/server/src/lib/Xlsx/TableSheet.tsx
@@ -0,0 +1,134 @@
+import xlsx, { WorkBook } from 'xlsx';
+import { IFinancialTable, ITableData } from '@/interfaces';
+import { FinancialTableStructure } from '@/services/FinancialStatements/FinancialTableStructure';
+
+interface ITableSheet {
+ convertToXLSX(): WorkBook;
+ convertToCSV(): string;
+ convertToBuffer(workbook: WorkBook, fileType: string): Buffer;
+}
+
+export class TableSheet implements ITableSheet {
+ private table: ITableData;
+
+ constructor(table: ITableData) {
+ this.table = table;
+ }
+
+ /**
+ * Retrieves the columns labels.
+ * @returns {string[]}
+ */
+ private get columns() {
+ return this.table.columns.map((col) => col.label);
+ }
+
+ /**
+ * Retrieves the columns accessors.
+ * @returns {string[]}
+ */
+ private get columnsAccessors() {
+ return this.table.columns.map((col, index) => {
+ return `${index}`;
+ });
+ }
+
+ /**
+ * Retrieves the rows data cellIndex/Value.
+ * @returns {Record}
+ */
+ private get rows() {
+ const computedRows = FinancialTableStructure.flatNestedTree(
+ this.table.rows
+ );
+ return computedRows.map((row) => {
+ const entries = row.cells.map((cell, index) => {
+ return [`${index}`, cell.value];
+ });
+ return Object.fromEntries(entries);
+ });
+ }
+
+ /**
+ * Converts the table to a CSV string.
+ * @returns {string}
+ */
+ public convertToCSV(): string {
+ // Define custom headers
+ const headers = this.columns;
+
+ // Convert data to worksheet with headers
+ const worksheet = xlsx.utils.json_to_sheet(this.rows, {
+ header: this.columnsAccessors,
+ });
+ // Add custom headers to the worksheet
+ xlsx.utils.sheet_add_aoa(worksheet, [headers], { origin: 'A1' });
+
+ // Convert worksheet to CSV format
+ const csvOutput = xlsx.utils.sheet_to_csv(worksheet);
+
+ return csvOutput;
+ }
+
+ /**
+ * Convert the array of objects to an XLSX file with styled headers
+ * @returns {Workbook}
+ */
+ public convertToXLSX(): WorkBook {
+ // Create a new workbook and a worksheet
+ const workbook = xlsx.utils.book_new();
+ const worksheet = xlsx.utils.json_to_sheet(this.rows, {
+ header: this.columnsAccessors,
+ });
+ // Add custom headers to the worksheet
+ xlsx.utils.sheet_add_aoa(worksheet, [this.columns], {
+ origin: 'A1',
+ });
+ // Adjust column width.
+ worksheet['!cols'] = this.computeXlsxColumnsWidths(this.rows);
+
+ // Append the worksheet to the workbook
+ xlsx.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+
+ return workbook;
+ }
+
+ /**
+ * Converts the given workbook to buffer of the given file type
+ * @param {WorkBook} workbook
+ * @param {string} fileType
+ * @returns {Promise}
+ */
+ public convertToBuffer(workbook: WorkBook, fileType: 'xlsx' | 'csv'): Buffer {
+ return xlsx.write(workbook, {
+ type: 'buffer',
+ bookType: fileType,
+ cellStyles: true,
+ });
+ }
+
+ /**
+ * Adjusts and computes the columns width.
+ * @param {} rows
+ * @returns {{wch: number}[]}
+ */
+ private computeXlsxColumnsWidths = (rows): { wch: number }[] => {
+ const cols = [{ wch: 60 }];
+
+ this.columns.map((column) => {
+ cols.push({ wch: column.length });
+ });
+ rows.forEach((row) => {
+ const entries = Object.entries(row);
+
+ entries.forEach(([key, value]) => {
+ if (cols[key]) {
+ cols[key].wch = Math.max(cols[key].wch, String(value).length);
+ } else {
+ cols[key] = { wch: String(value).length };
+ }
+ });
+ });
+ return cols;
+ };
+}
diff --git a/packages/server/src/locales/ar.json b/packages/server/src/locales/ar.json
deleted file mode 100644
index a52b13d51..000000000
--- a/packages/server/src/locales/ar.json
+++ /dev/null
@@ -1,640 +0,0 @@
-{
- "Petty Cash": "العهدة",
- "Cash": "النقدية",
- "Bank": "المصرف",
- "Other Income": "إيرادات اخري",
- "Interest Income": "إيرادات الفوائد",
- "Depreciation Expense": "مصاريف الاهلاك",
- "Interest Expense": "مصروفات الفوائد",
- "Sales of Product Income": "مبيعات دخل المنتجات",
- "Inventory Asset": "المخزون",
- "Cost of Goods Sold (COGS)": "تكلفة البضائع المباعة (COGS)",
- "Cost of Goods Sold": "تكلفة البضاعة المباعة",
- "Accounts Payable": "الذمم الدائنة",
- "Other Expense": "مصاريف أخرى",
- "Payroll Expenses": "مصاريف المرتبات",
- "Fixed Asset": "أصول ثابتة",
- "Credit Card": "بطاقة إئتمان",
- "Non-Current Asset": "أصول غير متداولة",
- "Current Asset": "أصول متداولة",
- "Other Asset": "أصول اخري",
- "Long Term Liability": "التزامات طويلة الاجل",
- "Current Liability": "التزامات قصيرة الاجل",
- "Other Liability": "التزمات اخري",
- "Equity": "حقوق الملكية",
- "Expense": "مصروف",
- "Income": "إيراد",
- "Accounts Receivable (A/R)": "الذمم المدينة",
- "Accounts Receivable": "الذمم المدينة",
- "Accounts Payable (A/P)": "الذمم الدائنة",
- "Inactive": "غير نشط",
- "Other Current Asset": "أصول متداولة اخرى",
- "Tax Payable": "الضريبة المستحقة",
- "Other Current Liability": "التزامات قصيرة الأجر اخرى",
- "Non-Current Liability": "التزامات طويلة الأجر",
- "Assets": "أصول",
- "Liabilities": "الالتزمات",
- "Account name": "أسم الحساب",
- "Account type": "نوع الحساب",
- "Account normal": "حساب عادي",
- "Description": "وصف",
- "Account code": "رمز الحساب",
- "Currency": "عملة",
- "Balance": "توازن",
- "Active": "نشيط",
- "Created at": "أنشئت في",
- "fixed_asset": "أصل ثابت",
- "Journal": "قيد",
- "Reconciliation": "تسوية",
- "Credit": "دائن",
- "Debit": "مدين",
- "Interest": "فائدة",
- "Depreciation": "اهلاك",
- "Payroll": "كشف رواتب",
- "Type": "نوع",
- "Name": "الأسم",
- "Sellable": "قابل للبيع",
- "Purchasable": "قابل للشراء",
- "Sell price": "سعر البيع",
- "Cost price": "سعر الكلفة",
- "User": "المستخدم",
- "Category": "تصنيف",
- "Note": "ملحوظة",
- "Quantity on hand": "كمية في اليد",
- "Purchase description": "وصف الشراء",
- "Sell description": "وصف البيع",
- "Sell account": "حساب البيع",
- "Cost account": "حساب التكلفة",
- "Inventory account": "حساب المخزون",
- "Payment date": "تاريخ الدفع",
- "Payment account": "حساب الدفع",
- "Amount": "كمية",
- "Reference No.": "رقم المرجع.",
- "Published": "نشرت",
- "Journal number": "رقم القيد",
- "Status": "حالة",
- "Journal type": "نوع القيد",
- "Date": "تاريخ",
- "Asset": "أصل",
- "Liability": "التزام",
- "First-in first-out (FIFO)": "الوارد أولاً يصرف أولاً (FIFO)",
- "Last-in first-out (LIFO)": "الوارد أخيرًا يصرف أولاً (LIFO)",
- "Average rate": "المعدل المتوسط",
- "Total": "الإجمالي",
- "Transaction type": "نوع المعاملة",
- "Transaction #": "عملية #",
- "Running Value": "القيمة الجارية",
- "Running quantity": "الكمية الجارية",
- "Profit Margin": "هامش الربح",
- "Value": "القيمة",
- "Rate": "السعر",
- "OPERATING ACTIVITIES": "الأنشطة التشغيلية",
- "FINANCIAL ACTIVITIES": "الأنشطة التمويلية",
- "INVESTMENT ACTIVITIES": "الانشطة الاستثمارية",
- "Net income": "صافي الدخل",
- "Adjustments net income by operating activities.": "تسويات صافي الدخل من الأنشطة التشغيلية.",
- "Net cash provided by operating activities": "صافي التدفقات النقدية من أنشطة التشغيل",
- "Net cash provided by investing activities": "صافي التدفقات النقدية من أنشطة الاستثمار",
- "Net cash provided by financing activities": "صافي التدفقات النقدية من أنشطة التمويلية",
- "Cash at beginning of period": "التدفقات النقدية في بداية الفترة",
- "NET CASH INCREASE FOR PERIOD": "زيادة التدفقات النقدية للفترة",
- "CASH AT END OF PERIOD": "صافي التدفقات النقدية في نهاية الفترة",
- "Expenses": "مصاريف",
- "Services": "خدمات",
- "Inventory": "المخزون",
- "Non Inventory": "غير المخزون",
- "Draft": "مسودة",
- "Delivered": "تم التوصيل",
- "Overdue": "متأخر",
- "Partially paid": "المدفوعة جزئيا",
- "Paid": "مدفوع",
- "Opened": "افتتح",
- "Unpaid": "غير مدفوعة",
- "Approved": "وافق",
- "Rejected": "مرفوض",
- "Invoiced": "مفوترة",
- "Expired": "منتهي الصلاحية",
- "Closed": "مغلق",
- "Manual journal": "قيد اليدوي",
- "Owner contribution": "زيادة رأس المال",
- "Transfer to account": "تحويل إلى الحساب",
- "Transfer from account": "تحويل من الحساب",
- "Other income": "إيراد اخر",
- "Other expense": "مصاريف أخرى",
- "Owner drawing": "سحب رأس المال",
- "Inventory adjustment": "تسوية المخزون",
- "Customer opening balance": "الرصيد الافتتاحي للزبون",
- "Vendor opening balance": "رصيد افتتاحي للمورد",
- "Payment made": "سند الزبون",
- "Bill": "فاتورة الشراء",
- "Payment receive": "استلام الدفع",
- "Sale receipt": "إيصال البيع",
- "Sale invoice": "فاتورة البيع",
- "Quantity": "الكمية",
- "Bank Account": "حساب البنك",
- "Saving Bank Account": "حساب التوفير البنكي",
- "Undeposited Funds": "الأموال غير المودعة",
- "Computer Equipment": "معدات كمبيوتر",
- "Office Equipment": "معدات مكتبية",
- "Uncategorized Income": "الدخل غير مصنف",
- "Sales of Service Income": "دخل مبيعات الخدمات",
- "Bank Fees and Charges": "رسوم المصرفية",
- "Exchange Gain or Loss": "ربح أو خسارة فروقات الصرف",
- "Rent": "إيجار",
- "Office expenses": "مصاريف المكتب",
- "Other Expenses": "مصاريف اخري",
- "Drawings": "السحوبات",
- "Owner's Equity": "حقوق الملكية",
- "Opening Balance Equity": "الارصدة الافتتاحية ",
- "Retained Earnings": "الأرباح المحتجزة",
- "Sales Tax Payable": "ضريبة المبيعات المستحقة",
- "Revenue Received in Advance": "الإيرادات المقبوضة مقدما",
- "Opening Balance Liabilities": "رصيد الالتزامات الافتتاحي",
- "Loan": "اقراض",
- "Owner A Drawings": "مسحوبات المالك",
- "An account that holds valuation of products or goods that available for sale.": "حساب يحمل قيم مخزون البضاعة أو السلع المتاحة للبيع.",
- "Tracks the gain and losses of the exchange differences.": "يسجل مكاسب وخسائر فروق الصرف.",
- "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "يتم تسجيل أي رسوم مصرفية يتم فرضها في حساب الرسوم والمصروفات البنكية. ومن الأمثلة على ذلك رسوم صيانة الحساب المصرفي ورسوم المعاملات ورسوم الدفع المتأخر.",
- "The income activities are not associated to the core business.": "لا ترتبط انشطة الدخل إلى الأعمال الأساسية.",
- "Cash and cash equivalents": "النقد والنقد المكافئ",
- "Inventories": "مخزون البضاعة",
- "Other current assets": "الأصول متداولة الأخرى",
- "Non-Current Assets": "أصول غير المتداولة",
- "Current Liabilties": "التزامات متداولة",
- "Long-Term Liabilities": "التزامات طويلة الاجل",
- "Non-Current Liabilities": "التزامات غير متداولة",
- "Liabilities and Equity": "التزامات وحقوق الملكية",
- "Closing balance": "الرصيد الختامي",
- "Opening balance": "الرصيد الفتاحي",
- "Total {{accountName}}": "إجمالي {{accountName}}",
-
- "invoice.paper.invoice": "فاتورة",
- "invoice.paper.due_amount": "القيمة المستحقة",
- "invoice.paper.billed_to": "فاتورة إلي",
- "invoice.paper.invoice_date": "تاريخ الفاتورة",
- "invoice.paper.invoice_number": "رقم الفاتورة",
- "invoice.paper.due_date": "تاريخ الاستحقاق",
- "invoice.paper.conditions_title": "الشروط والأحكام",
- "invoice.paper.notes_title": "ملاحظات",
- "invoice.paper.total": "المجموع",
- "invoice.paper.balance_due": "مبلغ المستحق",
- "invoice.paper.payment_amount": "مبلغ المدفوع",
- "invoice.paper.invoice_amount": "قيمة الفاتورة",
-
- "item_entry.paper.item_name": "اسم الصنف",
- "item_entry.paper.rate": "السعر",
- "item_entry.paper.quantity": "الكمية",
- "item_entry.paper.total": "إجمالي",
-
- "estimate.paper.estimate": "عرض أسعار",
- "estimate.paper.billed_to": "عرض أسعار إلي",
- "estimate.paper.estimate_date": "تاريخ العرض",
- "estimate.paper.estimate_number": "رقم العرض",
- "estimate.paper.expiration_date": "تاريخ انتهاء الصلاحية",
- "estimate.paper.conditions_title": "الشروط والأحكام",
- "estimate.paper.notes_title": "ملاحظات",
- "estimate.paper.amount": "قيمة العرض",
- "estimate.paper.subtotal": "المجموع",
- "estimate.paper.total": "إجمالي",
- "estimate.paper.estimate_amount": "قيمة العرض",
-
- "receipt.paper.receipt": "إيصال",
- "receipt.paper.billed_to": "الإيصال إلي",
- "receipt.paper.receipt_date": "تاريخ الإيصال",
- "receipt.paper.receipt_number": "رقم الإيصال",
- "receipt.paper.conditions_title": "الشروط والأحكام",
- "receipt.paper.notes_title": "ملاحظات",
- "receipt.paper.receipt_amount": "قيمة الإيصال",
- "receipt.paper.total": "إجمالي",
- "receipt.paper.payment_amount": "مبلغ المدفوع",
- "receipt.paper.balance_due": "مبلغ المستحق",
- "receipt.paper.statement": "البيان",
- "receipt.paper.notes": "ملاحظات",
-
- "payment.paper.payment_receipt": "إيصال قبض",
- "payment.paper.amount_received": "القيمة المستلمه",
- "payment.paper.billed_to": "إيصال إلي",
- "payment.paper.payment_date": "تاريخ الدفع",
- "payment.paper.invoice_number": "رقم الفاتورة",
- "payment.paper.invoice_date": "تاريخ الفاتورة",
- "payment.paper.invoice_amount": "قيمة الفاتورة",
- "payment.paper.payment_amount": "قيمة الدفع",
- "payment.paper.balance_due": "المبلغ المستحق",
- "payment.paper.statement": "البيان",
-
- "credit.paper.credit_note": "اشعار دائن",
- "credit.paper.amount": "قيمة الاشعار",
- "credit.paper.remaining": "رصيد المتبقي",
- "credit.paper.billed_to": "إيصال إلي",
- "credit.paper.credit_date": "تاريخ الاشعار",
- "credit.paper.terms_conditions": "الشروط والاحكام",
- "credit.paper.notes": "ملاحظات",
- "credit.paper.total": "إجمالي",
- "credit.paper.credits_used": "قيمة المستخدمه",
- "credit.paper.credits_remaining": "قيمة المتبقية",
-
- "account.field.name": "إسم الحساب",
- "account.field.description": "الوصف",
- "account.field.slug": "Account slug",
- "account.field.code": "رقم الحساب",
- "account.field.root_type": "جذر الحساب",
- "account.field.normal": "طبيعة الحساب",
- "account.field.normal.credit": "دائن",
- "account.field.normal.debit": "مدين",
- "account.field.type": "نوع الحساب",
- "account.field.active": "Activity",
- "account.field.balance": "الرصيد",
- "account.field.created_at": "أنشئت في",
- "item.field.type": "نوع الصنف",
- "item.field.type.inventory": "مخزون",
- "item.field.type.service": "خدمة",
- "item.field.type.non-inventory": "غير مخزون",
- "item.field.name": "اسم الصنف",
- "item.field.code": "رمز الصنف",
- "item.field.sellable": "قابل للبيع",
- "item.field.purchasable": "قابل للشراء",
- "item.field.cost_price": "سعر التكلفة",
- "item.field.cost_account": "حساب التكلفة",
- "item.field.sell_account": "حساب البيع",
- "item.field.sell_description": "وصف البيع",
- "item.field.inventory_account": "حساب المخزون",
- "item.field.purchase_description": "وصف الشراء",
- "item.field.quantity_on_hand": "الكمية",
- "item.field.note": "ملاحظة",
- "item.field.category": "التصنيف",
- "item.field.active": "Active",
- "item.field.created_at": "أنشئت في",
- "item_category.field.name": "الاسم",
- "item_category.field.description": "الوصف",
- "item_category.field.count": "العدد",
- "item_category.field.created_at": "أنشئت في",
- "invoice.field.customer": "الزبون",
- "invoice.field.invoice_date": "تاريخ الفاتورة",
- "invoice.field.due_date": "تاريخ الاستحقاق",
- "invoice.field.invoice_no": "رقم الفاتورة",
- "invoice.field.reference_no": "رقم الإشاري",
- "invoice.field.invoice_message": "رسالة الفاتورة",
- "invoice.field.terms_conditions": "الشروط والأحكام",
- "invoice.field.amount": "القيمة",
- "invoice.field.payment_amount": "القيمة المدفوعة",
- "invoice.field.due_amount": "القيمة المستحقة",
- "invoice.field.status": "الحالة",
- "invoice.field.status.paid": "مدفوعة",
- "invoice.field.status.partially-paid": "المدفوعة جزئيا",
- "invoice.field.status.overdue": "متأخرة",
- "invoice.field.status.unpaid": "غير مدفوعة",
- "invoice.field.status.delivered": "تم تسليمها",
- "invoice.field.status.draft": "مسودة",
- "invoice.field.created_at": "أنشئت في",
- "estimate.field.amount": "القيمة",
- "estimate.field.estimate_number": "رقم العرض",
- "estimate.field.customer": "الزبون",
- "estimate.field.estimate_date": "تاريخ العرض",
- "estimate.field.expiration_date": "تاريخ انتهاء الصلاحية",
- "estimate.field.reference_no": "رقم الإشاري",
- "estimate.field.note": "ملاحظة",
- "estimate.field.terms_conditions": "الشروط والأحكام",
- "estimate.field.status": "الحالة",
- "estimate.field.status.delivered": "تم تسليمها",
- "estimate.field.status.rejected": "مرفوضة",
- "estimate.field.status.approved": "تم الموافقة",
- "estimate.field.status.draft": "مسودة",
- "estimate.field.created_at": "أنشئت في",
- "payment_receive.field.customer": "الزبون",
- "payment_receive.field.payment_date": "تاريخ الدفع",
- "payment_receive.field.amount": "القيمة",
- "payment_receive.field.reference_no": "رقم الإشاري",
- "payment_receive.field.deposit_account": "حساب الإيداع",
- "payment_receive.field.payment_receive_no": "رقم عملية الدفع",
- "payment_receive.field.statement": "البيان",
- "payment_receive.field.created_at": "أنشئت في",
- "bill_payment.field.vendor": "المورد",
- "bill_payment.field.amount": "القيمة",
- "bill_payment.field.due_amount": "قيمة المستحقة",
- "bill_payment.field.payment_account": "حساب الدفع",
- "bill_payment.field.payment_number": "قيمة الدفع",
- "bill_payment.field.payment_date": "تاريخ الدفع",
- "bill_payment.field.reference_no": "رقم الإشاري",
- "bill_payment.field.description": "الوصف",
- "bill_payment.field.created_at": "أنشئت في",
- "bill.field.vendor": "المورد",
- "bill.field.bill_number": "رقم الفاتورة",
- "bill.field.bill_date": "تاريخ الفاتورة",
- "bill.field.due_date": "تاريخ الاستحقاق",
- "bill.field.reference_no": "رقم الإشاري",
- "bill.field.status": "الحالة",
- "bill.field.status.paid": "مدفوعة",
- "bill.field.status.partially-paid": "مدفوعة جزئيا",
- "bill.field.status.unpaid": "غير مدفوعة",
- "bill.field.status.opened": "مفتوحة",
- "bill.field.status.draft": "مسودة",
- "bill.field.status.overdue": "متأخرة",
- "bill.field.amount": "القيمة",
- "bill.field.payment_amount": "قيم الدفع",
- "bill.field.note": "ملاحظة",
- "bill.field.created_at": "أنشئت في",
- "inventory_adjustment.field.date": "التاريخ",
- "inventory_adjustment.field.type": "النوع",
- "inventory_adjustment.field.type.increment": "زيادة",
- "inventory_adjustment.field.type.decrement": "نقصان",
- "inventory_adjustment.field.adjustment_account": "حساب التسوية",
- "inventory_adjustment.field.reason": "السبب",
- "inventory_adjustment.field.reference_no": "رقم الإشاري",
- "inventory_adjustment.field.description": "الوصف",
- "inventory_adjustment.field.published_at": "نشرت في",
- "inventory_adjustment.field.created_at": "أنشئت في",
- "expense.field.payment_date": "تاريخ الدفع",
- "expense.field.payment_account": "حساب الدفع",
- "expense.field.amount": "القيمة",
- "expense.field.reference_no": "رقم الإشاري",
- "expense.field.description": "الوصف",
- "expense.field.published": "Published",
- "expense.field.status": "الحالة",
- "expense.field.status.draft": "مسودة",
- "expense.field.status.published": "نشرت",
- "expense.field.created_at": "أنشئت في",
- "manual_journal.field.date": "التاريخ",
- "manual_journal.field.journal_number": "رقم القيد",
- "manual_journal.field.reference": "رقم الإشاري",
- "manual_journal.field.journal_type": "نوع القيد",
- "manual_journal.field.amount": "القيمة",
- "manual_journal.field.description": "الوصف",
- "manual_journal.field.status": "الحالة",
- "manual_journal.field.created_at": "أنشئت في",
- "receipt.field.amount": "القيمة",
- "receipt.field.deposit_account": "حساب الإيداع",
- "receipt.field.customer": "الزبون",
- "receipt.field.receipt_date": "تاريخ الإيصال",
- "receipt.field.receipt_number": "رقم الإيصال",
- "receipt.field.reference_no": "رقم الإشاري",
- "receipt.field.receipt_message": "رسالة الإيصال",
- "receipt.field.statement": "البيان",
- "receipt.field.created_at": "أنشئت في",
- "receipt.field.status": "الحالة",
- "receipt.field.status.draft": "مسودة",
- "receipt.field.status.closed": "مغلقة",
- "customer.field.first_name": "الاسم الأول",
- "customer.field.last_name": "الاسم الاخير",
- "customer.field.display_name": "اسم العرض",
- "customer.field.email": "بريد الالكتروني",
- "customer.field.work_phone": "هاتف عمل",
- "customer.field.personal_phone": "هاتف شخصي",
- "customer.field.company_name": "اسم الشركة",
- "customer.field.website": "موقع الكتروني",
- "customer.field.opening_balance_at": "الرصيد الافتتاحي في",
- "customer.field.opening_balance": "الرصيد الافتتاحي",
- "customer.field.created_at": "أنشئت في",
- "customer.field.balance": "الرصيد",
- "customer.field.status": "الحالة",
- "customer.field.currency": "العملة",
- "customer.field.status.active": "مفعل",
- "customer.field.status.inactive": "غير مفعل",
- "customer.field.status.overdue": "متأخر",
- "customer.field.status.unpaid": "غير دافع",
- "vendor.field.first_name": "الاسم الأول",
- "vendor.field.last_name": "الاسم الاخير",
- "vendor.field.display_name": "اسم العرض",
- "vendor.field.email": "بريد الالكتروني",
- "vendor.field.work_phone": "هاتف عمل",
- "vendor.field.personal_phone": "هاتف شخصي",
- "vendor.field.company_name": "اسم الشركة",
- "vendor.field.website": "موقع الكتروني",
- "vendor.field.opening_balance_at": "الرصيد الافتتاحي في",
- "vendor.field.opening_balance": "الرصيد الافتتاحي",
- "vendor.field.created_at": "أنشئت في",
- "vendor.field.balance": "الرصيد",
- "vendor.field.status": "الحالة",
- "vendor.field.currency": "العملة",
- "vendor.field.status.active": "مفعل",
- "vendor.field.status.inactive": "غير مفعل",
- "vendor.field.status.overdue": "متأخر",
- "vendor.field.status.unpaid": "غير دافع",
- "Invoice write-off": "شطب فاتورة",
- "transaction_type.credit_note": "اشعار دائن",
- "transaction_type.refund_credit_note": "استرجاع اموال اشعار دائن",
- "transaction_type.vendor_credit": "اشعار مدين",
- "transaction_type.refund_vendor_credit": "استرجاع اموال اشعار مدين",
- "transaction_type.landed_cost": "تحميل تكلفة",
-
- "sms_notification.invoice_details.label": "تفاصيل فاتورة البيع ",
- "sms_notification.invoice_reminder.label": "تذكير بفاتورة البيع ",
- "sms_notification.receipt_details.label": "تفاصيل إيصال البيع ",
- "sms_notification.sale_estimate_details.label": "تفاصيل فاتورة عرض اسعار ",
- "sms_notification.payment_receive_details.label": "تفاصيل سند الزبون",
- "sms_notification.customer_balance.label": "رصيد الزبون",
-
- "sms_notification.invoice_details.description": "سيتم إرسال إشعار عبر الرسائل القصيرة إلى العميل بمجرد إنشاء الفاتورة ونشرها أو عند إشعار العميل عبر رسالة نصية قصيرة بالفاتورة. ",
- "sms_notification.payment_receive.description": "سيتم إرسال إشعار رسالة شكر للدفع إلى العميل بمجرد إنشاء الدفعة ونشرها أو إشعار العميل بالدفع يدويًا. ",
- "sms_notification.receipt_details.description": "سيتم إرسال إشعار عبر الرسائل القصيرة إلى العميل بمجرد إنشاء ونشر الإيصال أو عند إشعار العميل بالإيصال يدويًا.",
- "sms_notification.customer_balance.description": "إرسال رسالة نصية قصيرة إشعار العملاء برصيدهم الحالي المستحق. ",
- "sms_notification.estimate_details.description": "سيتم إرسال إشعار عبر الرسائل القصيرة إلى عميلك بمجرد نشر العرض أو إشعار العميل بالعرض يدويًا.",
- "sms_notification.invoice_reminder.description": "سيتم ارسال إشعار SMS لتذكير الزبون بالدفع باكراً ، سواء ارسال بشكل تلقائي او يدوي.",
-
- "sms_notification.customer_balance.default_message": "عزيزي {CustomerName} ، هذا تذكير بشأن رصيد الحالي المستحق {Balance} ، يُرجى الدفع في أقرب وقت ممكن. - {CompanyName}",
- "sms_notification.payment_receive.default_message": "مرحبًا {CustomerName} ، تم القبض بقيمة {Amount} للفاتورة - {InvoiceNumber}. نحن نتطلع إلى خدمتك مرة أخرى. شكرا لك. - {CompanyName}",
- "sms_notification.estimate.default_message": "مرحبًا , {CustomerName} ، تم أنشاء فاتورة عرض اسعار - {EstimateNumber} لك. يرجى إلقاء نظرة وقبوله للمضي قدما. بانتظار ردك. - {CompanyName}",
-
- "sms_notification.invoice_details.default_message": "مرحبًا {CustomerName}, لديك مبلغ مستحق قدره {DueAmount} للفاتورة {InvoiceNumber}. - {CompanyName}",
- "sms_notification.receipt_details.default_message": "مرحبًا {CustomerName} ، لقد تم إنشاء إيصال - {ReceiptNumber} من أجلك. نتطلع إلى خدمتك مرة أخرى. شكرًا لك - {CompanyName}",
- "sms_notification.invoice_reminder.default_message": "عزيزي {CustomerName} ، يرجي سداد فاتورة - {InvoiceNumber} المستحقة. يرجى الدفع قبل تاريخ {DueDate}. شكرا لك. - {CompanyName}",
-
- "module.sale_invoices.label": "فواتير البيع",
- "module.sale_receipts.label": "إيصالات البيع",
- "module.sale_estimates.label": "فاتورة عرض اسعار ",
- "module.payment_receives.label": "سندات الزبائن ",
- "module.customers.label": "العملاء",
-
- "sms_notification.invoice.var.invoice_number": "يشير إلى رقم الفاتورة.",
- "sms_notification.invoice.var.reference_number": "يشير إلى رقم إشاري للفاتورة.",
- "sms_notification.invoice.var.customer_name": "يشير إلى اسم العميل الفاتورة",
- "sms_notification.invoice.var.due_amount": "يشير إلى مبلغ الفاتورة المستحق",
- "sms_notification.invoice.var.amount": "يشير إلى مبلغ الفاتورة.",
- "sms_notification.invoice.var.company_name": "يشير إلي اسم الشركة.",
- "sms_notification.invoice.var.due_date": "يشير إلي تاريخ استحقاق الفاتورة.",
-
- "sms_notification.receipt.var.receipt_number": "يشير إلى رقم الإيصال.",
- "sms_notification.receipt.var.reference_number": "يشير إلى رقم الإشاري للإيصال.",
- "sms_notification.receipt.var.customer_name": "يشير إلى اسم العميل الإيصال.",
- "sms_notification.receipt.var.amount": "يشير إلى مبلغ الإيصال. ",
- "sms_notification.receipt.var.company_name": "يشير إلي اسم الشركة.",
-
- "sms_notification.payment.var.payment_number": "يشير إلى رقم معاملة الدفع.",
- "sms_notification.payment.var.reference_number": "يشير إلى رقم الإشاري لعملية الدفع ",
- "sms_notification.payment.var.customer_name": "يشير إلى اسم العميل الدفع",
- "sms_notification.payment.var.amount": "يشير إلى مبلغ معاملة الدفع.",
- "sms_notification.payment.company_name": "يشير إلي اسم الشركة.",
- "sms_notification.payment.var.invoice_number": "يشير إلي رقم فاتورة التي تم دفعها.",
-
- "sms_notification.estimate.var.estimate_number": "يشير إلى رقم فاتورة عرض اسعار.",
- "sms_notification.estimate.var.reference_number": "يشير إلى رقم الإشاري لفاتورة عرض اسعار.",
- "sms_notification.estimate.var.customer_name": "يشير إلى اسم العميل الفاتورة",
- "sms_notification.estimate.var.amount": "يشير إلى قيمة الفاتورة",
- "sms_notification.estimate.var.company_name": "يشير إلي اسم الشركة.",
- "sms_notification.estimate.var.expiration_date": "يشير إلي تاريخ الصلاحية الفاتورة.",
- "sms_notification.estimate.var.estimate_date": "يشير إلي تاريخ الفاتورة.",
-
- "sms_notification.customer.var.customer_name": "يشير إلي اسم الزبون",
- "sms_notification.customer.var.balance": "يشير إلي رصيد زبون المستحق.",
- "sms_notification.customer.var.company_name": "يشير إلي اسم الشركة.",
-
- "ability.accounts": "شجرة الحسابات",
- "ability.manual_journal": "القيود اليدوية",
- "ability.cashflow": "التدفقات النقدية",
- "ability.inventory_adjustment": "تسويات المخزون",
- "ability.customers": "الزبائن",
- "ability.vendors": "الموردين",
- "ability.sale_estimates": "فواتير عرض الاسعار",
- "ability.sale_invoices": "فواتير البيع",
- "ability.sale_receipts": "إيصالات البيع",
- "ability.expenses": "المصاريف",
- "ability.payments_receive": "سندات الزبائن",
- "ability.purchase_invoices": "فواتير الشراء",
- "ability.all_reports": "كل التقارير",
- "ability.payments_made": "سندات الموردين",
- "ability.preferences": "التفضيلات",
- "ability.mutate_system_preferences": "تعديل تفضيلات النظام.",
-
- "ability.items": "الأصناف",
- "ability.view": "عرض",
- "ability.create": "إضافة",
- "ability.edit": "تعديل",
- "ability.delete": "حذف",
- "ability.transactions_locking": "إمكانية اغلاق المعاملات.",
-
- "ability.balance_sheet_report": "ميزانية العمومية",
- "ability.profit_loss_sheet": "قائمة الدخل",
- "ability.journal": "اليومية العامة",
- "ability.general_ledger": "دفتر الأستاذ العام",
- "ability.cashflow_report": "تقرير التدفقات النقدية",
- "ability.AR_aging_summary_report": "ملخص اعمار الديون للذمم المدينة",
- "ability.AP_aging_summary_report": "ملخص اعمار الديون للذمم الدائنة",
- "ability.purchases_by_items": "المشتريات حسب المنتجات",
- "ability.sales_by_items_report": "المبيعات حسب المنتجات",
- "ability.customers_transactions_report": "معاملات الزبائن",
- "ability.vendors_transactions_report": "معاملات الموردين",
- "ability.customers_summary_balance_report": "ملخص أرصدة الزبائن",
- "ability.vendors_summary_balance_report": "ملخص أرصدة الموردين",
- "ability.inventory_valuation_summary": "ملخص تقييم المخزون",
- "ability.inventory_items_details": "تفاصيل منتج المخزون",
-
- "vendor_credit.field.vendor": "المورد",
- "vendor_credit.field.amount": "القيمة",
- "vendor_credit.field.currency_code": "العملة",
- "vendor_credit.field.credit_date": "تاريخ الاشعار",
- "vendor_credit.field.credit_number": "رقم الاشعار",
- "vendor_credit.field.note": "ملاحظة",
- "vendor_credit.field.created_at": "أنشئت في",
- "vendor_credit.field.reference_no": "رقم الإشاري",
-
- "vendor_credit.field.status": "الحالة",
- "vendor_credit.field.status.draft": "مسودة",
- "vendor_credit.field.status.published": "تم نشرها",
- "vendor_credit.field.status.open": "مفتوحة",
- "vendor_credit.field.status.closed": "مغلقة",
-
- "credit_note.field.terms_conditions": "الشروط والاحكام",
- "credit_note.field.note": "ملاحظة",
- "credit_note.field.currency_code": "العملة",
- "credit_note.field.created_at": "أنشئت في",
- "credit_note.field.amount": "القيمة",
- "credit_note.field.credit_note_number": "رقم الاشعار",
- "credit_note.field.credit_note_date": "تاريخ الاشعار",
- "credit_note.field.customer": "الزبون",
- "credit_note.field.reference_no": "رقم الإشاري",
-
- "credit_note.field.status": "الحالة",
- "credit_note.field.status.draft": "مسودة",
- "credit_note.field.status.published": "تم نشرها",
- "credit_note.field.status.open": "مفتوحة",
- "credit_note.field.status.closed": "مغلقة",
-
- "transactions_locking.module.sales.label": "المبيعات",
- "transactions_locking.module.purchases.label": "المشتريات",
- "transactions_locking.module.financial.label": "المالية",
- "transactions_locking.module.all_transactions": "كل المعاملات",
-
- "transactions_locking.module.sales.desc": "فواتير البيع ، والإيصالات ، والإشعارات الدائنة ، واستلام مدفوعات الزبائن ، والأرصدة الافتتاحية للزبائن.",
- "transactions_locking.module.purchases.desc": "فواتير الشراء ومدفوعات الموردين وإشعارات المدينة والأرصدة الافتتاحية للموردين.",
- "transactions_locking.module.financial.desc": "القيود اليدوية والمصروفات وتسويات المخزون.",
-
- "inventory_adjustment.type.increment": "زيادة",
- "inventory_adjustment.type.decrement": "نقصان",
-
- "customer.type.individual": "فرد",
- "customer.type.business": "اعمال",
-
- "credit_note.view.draft": "مسودة",
- "credit_note.view.closed": "مغلقة",
- "credit_note.view.open": "مفتوحة",
- "credit_note.view.published": "نشرت",
-
- "vendor_credit.view.draft": "مسودة",
- "vendor_credit.view.closed": "مغلقة",
- "vendor_credit.view.open": "مفتوحة",
- "vendor_credit.view.published": "نشرت",
-
- "allocation_method.value.label": "القيمة",
- "allocation_method.quantity.label": "الكمية",
-
- "balance_sheet.assets": "الأصول",
- "balance_sheet.current_asset": "الأصول المتداولة",
- "balance_sheet.cash_and_cash_equivalents": "النقدية وما يعادلها",
- "balance_sheet.accounts_receivable": "الذمم المدينة",
- "balance_sheet.inventory": "المخزون",
- "balance_sheet.other_current_assets": "اصول متداولة اخرى",
- "balance_sheet.fixed_asset": "الأصول الثابتة",
- "balance_sheet.non_current_assets": "الاصول غير المتداولة",
- "balance_sheet.liabilities_and_equity": "الالتزامات وحقوق الملكية",
- "balance_sheet.liabilities": "الإلتزامات",
- "balance_sheet.current_liabilties": "الالتزامات المتداولة",
- "balance_sheet.long_term_liabilities": "الالتزامات طويلة الاجل",
- "balance_sheet.non_current_liabilities": "الالتزامات غير المتداولة",
- "balance_sheet.equity": "حقوق الملكية",
-
- "balance_sheet.account_name": "اسم الحساب",
- "balance_sheet.total": "إجمالي",
- "balance_sheet.percentage_of_column": "٪ التغير العمودي",
- "balance_sheet.percentage_of_row": "٪ التغير الأفقي",
-
- "financial_sheet.previoud_period_date": "(ف.س) {{date}}",
- "fianncial_sheet.previous_period_change": "التغيرات (ف.س)",
- "financial_sheet.previous_period_percentage": "٪ التغير (ف.س)",
-
- "financial_sheet.previous_year_date": "(س.س) {{date}}",
- "financial_sheet.previous_year_change": "التغيرات (س.س)",
- "financial_sheet.previous_year_percentage": "٪ التغير (س.س)",
- "financial_sheet.total_row": "إجمالي {{value}}",
-
- "profit_loss_sheet.income": "الإيرادات",
- "profit_loss_sheet.cost_of_sales": "تكلفة المبيعات",
- "profit_loss_sheet.gross_profit": "إجمالي الدخل",
- "profit_loss_sheet.expenses": "المصروفات",
- "profit_loss_sheet.net_operating_income": "صافي الدخل التشغيلي",
- "profit_loss_sheet.other_income": "إيرادات اخري",
- "profit_loss_sheet.other_expenses": "مصاريف اخري",
- "profit_loss_sheet.net_income": "صافي الدخل",
-
- "profit_loss_sheet.account_name": "اسم الحساب",
- "profit_loss_sheet.total": "إجمالي",
-
- "profit_loss_sheet.percentage_of_income": "٪ التغير في الإيرادات",
- "profit_loss_sheet.percentage_of_expenses": "٪ التغير في المصاريف",
- "profit_loss_sheet.percentage_of_column": "٪ التغير العمودي",
- "profit_loss_sheet.percentage_of_row": "٪ التغير الأفقي",
-
- "warehouses.primary_warehouse": "المستودع الرئيسي",
- "branches.head_branch": "الفرع الرئيسي",
-
- "account.accounts_payable.currency": "الذمم الدائنة - {{currency}}",
- "account.accounts_receivable.currency": "الذمم المدينة - {{currency}}",
-
- "role.admin.name": "الادارة",
- "role.admin.desc": "وصول غير مقيد لجميع الوحدات.",
-
- "role.staff.name": "العاملين",
- "role.staff.desc": "الوصول إلى جميع الوحدات باستثناء التقارير والإعدادات والمحاسبة.",
-
- "warehouse_transfer.view.draft.name": "مسودة",
- "warehouse_transfer.view.in_transit.name": "في النقل",
- "warehouse_transfer.view.transferred.name": "تم النقل"
-}
\ No newline at end of file
diff --git a/packages/server/src/locales/en.json b/packages/server/src/locales/en.json
deleted file mode 100644
index 293186e9e..000000000
--- a/packages/server/src/locales/en.json
+++ /dev/null
@@ -1,642 +0,0 @@
-{
- "Petty Cash": "Petty Cash",
- "Cash": "Cash",
- "Bank": "Bank",
- "Other Income": "Other Income",
- "Interest Income": "Interest Income",
- "Depreciation Expense": "Depreciation Expense",
- "Interest Expense": "Interest Expense",
- "Sales of Product Income": "Sales of Product Income",
- "Inventory Asset": "Inventory Asset",
- "Cost of Goods Sold (COGS)": "Cost of Goods Sold (COGS)",
- "Cost of Goods Sold": "Cost of Goods Sold",
- "Accounts Payable": "Accounts Payable",
- "Other Expense": "Other Expense",
- "Payroll Expenses": "Payroll Expenses",
- "Fixed Asset": "Fixed Asset",
- "Credit Card": "Credit Card",
- "Non-Current Asset": "Non-Current Asset",
- "Current Asset": "Current Asset",
- "Other Asset": "Other Asset",
- "Long Term Liability": "Long Term Liability",
- "Current Liability": "Current Liability",
- "Other Liability": "Other Liability",
- "Equity": "Equity",
- "Expense": "Expense",
- "Income": "Income",
- "Accounts Receivable (A/R)": "Accounts Receivable (A/R)",
- "Accounts Receivable": "Accounts Receivable",
- "Accounts Payable (A/P)": "Accounts Payable (A/P)",
- "Inactive": "Inactive",
- "Other Current Asset": "Other Current Asset",
- "Tax Payable": "Tax Payable",
- "Other Current Liability": "Other Current Liability",
- "Non-Current Liability": "Non-Current Liability",
- "Assets": "Assets",
- "Liabilities": "Liabilities",
- "Account name": "Account name",
- "Account type": "Account type",
- "Account normal": "Account normal",
- "Description": "Description",
- "Account code": "Account code",
- "Currency": "Currency",
- "Balance": "Balance",
- "Active": "Active",
- "Created at": "Created at",
- "fixed_asset": "Fixed asset",
- "Journal": "Journal",
- "Reconciliation": "Reconciliation",
- "Credit": "Credit",
- "Debit": "Debit",
- "Interest": "Interest",
- "Depreciation": "Depreciation",
- "Payroll": "Payroll",
- "Type": "Type",
- "Name": "Name",
- "Sellable": "Sellable",
- "Purchasable": "Purchasable",
- "Sell price": "Sell price",
- "Cost price": "Cost price",
- "User": "User",
- "Category": "Category",
- "Note": "Note",
- "Quantity on hand": "Quantity on hand",
- "Quantity": "Quantity",
- "Purchase description": "Purchase description",
- "Sell description": "Sell description",
- "Sell account": "Sell account",
- "Cost account": "Cost account",
- "Inventory account": "Inventory account",
- "Payment date": "Payment date",
- "Payment account": "Payment account",
- "Amount": "Amount",
- "Reference No.": "Reference No.",
- "Journal number": "Journal number",
- "Status": "Status",
- "Journal type": "Journal type",
- "Date": "Date",
- "Asset": "Asset",
- "Liability": "Liability",
- "First-in first-out (FIFO)": "First-in first-out (FIFO)",
- "Last-in first-out (LIFO)": "Last-in first-out (LIFO)",
- "Average rate": "Average rate",
- "Total": "Total",
- "Transaction type": "Transaction type",
- "Transaction #": "Transaction #",
- "Running Value": "Running Value",
- "Running quantity": "Running quantity",
- "Profit Margin": "Profit Margin",
- "Value": "Value",
- "Rate": "Rate",
- "OPERATING ACTIVITIES": "OPERATING ACTIVITIES",
- "FINANCIAL ACTIVITIES": "FINANCIAL ACTIVITIES",
- "Net income": "Net income",
- "Adjustments net income by operating activities.": "Adjustments net income by operating activities.",
- "Net cash provided by operating activities": "Net cash provided by operating activities",
- "Net cash provided by investing activities": "Net cash provided by investing activities",
- "Net cash provided by financing activities": "Net cash provided by financing activities",
- "Cash at beginning of period": "Cash at beginning of period",
- "NET CASH INCREASE FOR PERIOD": "NET CASH INCREASE FOR PERIOD",
- "CASH AT END OF PERIOD": "CASH AT END OF PERIOD",
- "Expenses": "Expenses",
- "Services": "Services",
- "Inventory": "Inventory",
- "Non Inventory": "Non Inventory",
- "Draft": "Draft",
- "Published": "Published",
- "Delivered": "Delivered",
- "Overdue": "Overdue",
- "Partially paid": "Partially paid",
- "Paid": "Paid",
- "Opened": "Opened",
- "Unpaid": "Unpaid",
- "Approved": "Approved",
- "Rejected": "Rejected",
- "Invoiced": "Invoiced",
- "Expired": "Expired",
- "Closed": "Closed",
- "Manual journal": "Manual journal",
- "Owner contribution": "Owner contribution",
- "Transfer to account": "Transfer to account",
- "Transfer from account": "Transfer from account",
- "Other income": "Other income",
- "Other expense": "Other expense",
- "Owner drawing": "Owner drawing",
- "Inventory adjustment": "Inventory adjustment",
- "Customer opening balance": "Customer opening balance",
- "Vendor opening balance": "Vendor opening balance",
- "Payment made": "Payment made",
- "Bill": "Bill",
- "Payment receive": "Payment receive",
- "Sale receipt": "Sale receipt",
- "Sale invoice": "Sale invoice",
- "Bank Account": "Bank Account",
- "Saving Bank Account": "Saving Bank Account",
- "Undeposited Funds": "Undeposited Funds",
- "Computer Equipment": "Computer Equipment",
- "Office Equipment": "Office Equipment",
- "Uncategorized Income": "Uncategorized Income",
- "Sales of Service Income": "Sales of Service Income",
- "Bank Fees and Charges": "Bank Fees and Charges",
- "Exchange Gain or Loss": "Exchange Gain or Loss",
- "Rent": "Rent",
- "Office expenses": "Office expenses",
- "Other Expenses": "Other Expenses",
- "Drawings": "Drawings",
- "Owner's Equity": "Owner's Equity",
- "Opening Balance Equity": "Opening Balance Equity",
- "Retained Earnings": "Retained Earnings",
- "Sales Tax Payable": "Sales Tax Payable",
- "Revenue Received in Advance": "Revenue Received in Advance",
- "Opening Balance Liabilities": "Opening Balance Liabilities",
- "Loan": "Loan",
- "Owner A Drawings": "Owner A Drawings",
- "An account that holds valuation of products or goods that available for sale.": "An account that holds valuation of products or goods that available for sale.",
- "Tracks the gain and losses of the exchange differences.": "Tracks the gain and losses of the exchange differences.",
- "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.",
- "The income activities are not associated to the core business.": "The income activities are not associated to the core business.",
- "Cash and cash equivalents": "Cash and cash equivalents",
- "Inventories": "Inventories",
- "Other current assets": "Other current assets",
- "Non-Current Assets": "Non-Current Assets",
- "Current Liabilties": "Current Liabilties",
- "Long-Term Liabilities": "Long-Term Liabilities",
- "Non-Current Liabilities": "Non-Current Liabilities",
- "Liabilities and Equity": "Liabilities and Equity",
- "Closing balance": "Closing balance",
- "Opening Balance": "Opening balance",
- "Total {{accountName}}": "Total {{accountName}}",
- "invoice.paper.invoice": "Invoice",
- "invoice.paper.invoice_amount": "Invoice amount",
- "invoice.paper.due_amount": "Due amount",
- "invoice.paper.billed_to": "Billed to",
- "invoice.paper.invoice_date": "Invoice date",
- "invoice.paper.invoice_number": "Invoice No.",
- "invoice.paper.due_date": "Due date",
- "invoice.paper.conditions_title": "Conditions & terms",
- "invoice.paper.notes_title": "Notes",
- "invoice.paper.total": "Total",
- "invoice.paper.payment_amount": "Payment Amount",
- "invoice.paper.balance_due": "Balance Due",
-
- "item_entry.paper.item_name": "Item name",
- "item_entry.paper.rate": "Rate",
- "item_entry.paper.quantity": "Quantity",
- "item_entry.paper.total": "Total",
-
- "estimate.paper.estimate": "Estimate",
- "estimate.paper.estimate_amount": "Estimate amount",
- "estimate.paper.billed_to": "Billed to",
- "estimate.paper.estimate_date": "Estimate date",
- "estimate.paper.estimate_number": "Estimate number",
- "estimate.paper.expiration_date": "Expiration date",
- "estimate.paper.conditions_title": "Conditions & terms",
- "estimate.paper.notes_title": "Notes",
- "estimate.paper.amount": "Estimate amount",
- "estimate.paper.subtotal": "Subtotal",
- "estimate.paper.total": "Total",
-
- "receipt.paper.receipt": "Receipt",
- "receipt.paper.billed_to": "Billed to",
- "receipt.paper.receipt_date": "Receipt date",
- "receipt.paper.receipt_number": "Receipt number",
- "receipt.paper.expiration_date": "Expiration date",
- "receipt.paper.conditions_title": "Conditions & terms",
- "receipt.paper.notes": "Notes",
- "receipt.paper.statement": "Statement",
- "receipt.paper.receipt_amount": "Receipt amount",
- "receipt.paper.total": "Total",
- "receipt.paper.balance_due": "Balance Due",
- "receipt.paper.payment_amount": "Payment Amount",
-
- "credit.paper.credit_note": "Credit Note",
- "credit.paper.remaining": "Credit remaining",
- "credit.paper.amount": "Credit amount",
- "credit.paper.billed_to": "Bill to",
- "credit.paper.credit_date": "Credit date",
- "credit.paper.total": "Total",
- "credit.paper.credits_used": "Credits used",
- "credit.paper.credits_remaining": "Credits remaining",
- "credit.paper.conditions_title": "Conditions & terms",
- "credit.paper.notes": "Notes",
-
- "payment.paper.payment_receipt": "Payment Receipt",
- "payment.paper.amount_received": "Amount received",
- "payment.paper.billed_to": "Billed to",
- "payment.paper.payment_date": "Payment date",
- "payment.paper.invoice_number": "Invoice number",
- "payment.paper.invoice_date": "Invoice date",
- "payment.paper.invoice_amount": "Invoice amount",
- "payment.paper.payment_amount": "Payment amount",
- "payment.paper.balance_due": "Balance Due",
- "payment.paper.statement": "Statement",
-
- "account.field.name": "Account name",
- "account.field.description": "Description",
- "account.field.slug": "Account slug",
- "account.field.code": "Account code",
- "account.field.root_type": "Root type",
- "account.field.normal": "Account normal",
- "account.field.normal.credit": "Credit",
- "account.field.normal.debit": "Debit",
- "account.field.type": "Type",
- "account.field.active": "Activity",
- "account.field.balance": "Balance",
- "account.field.created_at": "Created at",
- "item.field.type": "Item type",
- "item.field.type.inventory": "Inventory",
- "item.field.type.service": "Service",
- "item.field.type.non-inventory": "Non inventory",
- "item.field.name": "Name",
- "item.field.code": "Code",
- "item.field.sellable": "Sellable",
- "item.field.purchasable": "Purchasable",
- "item.field.cost_price": "Cost price",
- "item.field.cost_account": "Cost account",
- "item.field.sell_account": "Sell account",
- "item.field.sell_description": "Sell description",
- "item.field.inventory_account": "Inventory account",
- "item.field.purchase_description": "Purchase description",
- "item.field.quantity_on_hand": "Quantity on hand",
- "item.field.note": "Note",
- "item.field.category": "Category",
- "item.field.active": "Active",
- "item.field.created_at": "Created at",
- "item_category.field.name": "Name",
- "item_category.field.description": "Description",
- "item_category.field.count": "Count",
- "item_category.field.created_at": "Created at",
- "invoice.field.customer": "Customer",
- "invoice.field.invoice_date": "Invoice date",
- "invoice.field.due_date": "Due date",
- "invoice.field.invoice_no": "Invoice No.",
- "invoice.field.reference_no": "Reference No.",
- "invoice.field.invoice_message": "Invoice message",
- "invoice.field.terms_conditions": "Terms & conditions",
- "invoice.field.amount": "Amount",
- "invoice.field.payment_amount": "Payment amount",
- "invoice.field.due_amount": "Due amount",
- "invoice.field.status": "Status",
- "invoice.field.status.paid": "Paid",
- "invoice.field.status.partially-paid": "Partially paid",
- "invoice.field.status.overdue": "Overdue",
- "invoice.field.status.unpaid": "Unpaid",
- "invoice.field.status.delivered": "Delivered",
- "invoice.field.status.draft": "Draft",
- "invoice.field.created_at": "Created at",
- "estimate.field.amount": "Amount",
- "estimate.field.estimate_number": "Estimate number",
- "estimate.field.customer": "Customer",
- "estimate.field.estimate_date": "Estimate date",
- "estimate.field.expiration_date": "Expiration date",
- "estimate.field.reference_no": "Reference No.",
- "estimate.field.note": "Note",
- "estimate.field.terms_conditions": "Terms & conditions",
- "estimate.field.status": "Status",
- "estimate.field.status.delivered": "Delivered",
- "estimate.field.status.rejected": "Rejected",
- "estimate.field.status.approved": "Approved",
- "estimate.field.status.draft": "Draft",
- "estimate.field.created_at": "Created at",
- "payment_receive.field.customer": "Customer",
- "payment_receive.field.payment_date": "Payment date",
- "payment_receive.field.amount": "Amount",
- "payment_receive.field.reference_no": "Reference No.",
- "payment_receive.field.deposit_account": "Deposit account",
- "payment_receive.field.payment_receive_no": "Payment receive No.",
- "payment_receive.field.statement": "Statement",
- "payment_receive.field.created_at": "Created at",
- "bill_payment.field.vendor": "Vendor",
- "bill_payment.field.amount": "Amount",
- "bill_payment.field.due_amount": "Due amount",
- "bill_payment.field.payment_account": "Payment account",
- "bill_payment.field.payment_number": "Payment number",
- "bill_payment.field.payment_date": "Payment date",
- "bill_payment.field.reference_no": "Reference No.",
- "bill_payment.field.description": "Description",
- "bill_payment.field.created_at": "Created at",
- "bill.field.vendor": "Vendor",
- "bill.field.bill_number": "Bill number",
- "bill.field.bill_date": "Bill date",
- "bill.field.due_date": "Due date",
- "bill.field.reference_no": "Reference No.",
- "bill.field.status": "Status",
- "bill.field.status.paid": "Paid",
- "bill.field.status.partially-paid": "Partially paid",
- "bill.field.status.unpaid": "Unpaid",
- "bill.field.status.opened": "Opened",
- "bill.field.status.draft": "Draft",
- "bill.field.status.overdue": "overdue",
- "bill.field.amount": "Amount",
- "bill.field.payment_amount": "Payment amount",
- "bill.field.note": "Note",
- "bill.field.created_at": "Created at",
- "inventory_adjustment.field.date": "Date",
- "inventory_adjustment.field.type": "Type",
- "inventory_adjustment.field.type.increment": "Increment",
- "inventory_adjustment.field.type.decrement": "Decrement",
- "inventory_adjustment.field.adjustment_account": "Adjustment account",
- "inventory_adjustment.field.reason": "Reason",
- "inventory_adjustment.field.reference_no": "Reference No.",
- "inventory_adjustment.field.description": "Description",
- "inventory_adjustment.field.published_at": "Published at",
- "inventory_adjustment.field.created_at": "Created at",
- "expense.field.payment_date": "Payment date",
- "expense.field.payment_account": "Payment account",
- "expense.field.amount": "Amount",
- "expense.field.reference_no": "Reference No.",
- "expense.field.description": "Description",
- "expense.field.published": "Published",
- "expense.field.status": "Status",
- "expense.field.status.draft": "Draft",
- "expense.field.status.published": "Published",
- "expense.field.created_at": "Created at",
- "manual_journal.field.date": "Date",
- "manual_journal.field.journal_number": "Journal number",
- "manual_journal.field.reference": "Reference No.",
- "manual_journal.field.journal_type": "Journal type",
- "manual_journal.field.amount": "Amount",
- "manual_journal.field.description": "Description",
- "manual_journal.field.status": "Status",
- "manual_journal.field.created_at": "Created at",
- "receipt.field.amount": "Amount",
- "receipt.field.deposit_account": "Deposit account",
- "receipt.field.customer": "Customer",
- "receipt.field.receipt_date": "Receipt date",
- "receipt.field.receipt_number": "Receipt number",
- "receipt.field.reference_no": "Reference No.",
- "receipt.field.receipt_message": "Receipt message",
- "receipt.field.statement": "Statement",
- "receipt.field.created_at": "Created at",
- "receipt.field.status": "Status",
- "receipt.field.status.draft": "Draft",
- "receipt.field.status.closed": "Closed",
- "customer.field.first_name": "First name",
- "customer.field.last_name": "Last name",
- "customer.field.display_name": "Display name",
- "customer.field.email": "Email",
- "customer.field.work_phone": "Work phone",
- "customer.field.personal_phone": "Personal phone",
- "customer.field.company_name": "Company name",
- "customer.field.website": "Website",
- "customer.field.opening_balance_at": "Opening balance at",
- "customer.field.opening_balance": "Opening balance",
- "customer.field.created_at": "Created at",
- "customer.field.balance": "Balance",
- "customer.field.status": "Status",
- "customer.field.currency": "Curreny",
- "customer.field.status.active": "Active",
- "customer.field.status.inactive": "Inactive",
- "customer.field.status.overdue": "Overdue",
- "customer.field.status.unpaid": "Unpaid",
- "vendor.field.first_name": "First name",
- "vendor.field.last_name": "Last name",
- "vendor.field.display_name": "Display name",
- "vendor.field.email": "Email",
- "vendor.field.work_phone": "Work phone",
- "vendor.field.personal_phone": "Personal phone",
- "vendor.field.company_name": "Company name",
- "vendor.field.website": "Website",
- "vendor.field.opening_balance_at": "Opening balance at",
- "vendor.field.opening_balance": "Opening balance",
- "vendor.field.created_at": "Created at",
- "vendor.field.balance": "Balance",
- "vendor.field.status": "Status",
- "vendor.field.currency": "Curreny",
- "vendor.field.status.active": "Active",
- "vendor.field.status.inactive": "Inactive",
- "vendor.field.status.overdue": "Overdue",
- "vendor.field.status.unpaid": "Unpaid",
- "Invoice write-off": "Invoice write-off",
-
- "transaction_type.credit_note": "Credit note",
- "transaction_type.refund_credit_note": "Refund credit note",
- "transaction_type.vendor_credit": "Vendor credit",
- "transaction_type.refund_vendor_credit": "Refund vendor credit",
- "transaction_type.landed_cost": "Landed cost",
-
- "sms_notification.invoice_details.label": "Sale invoice details",
- "sms_notification.invoice_reminder.label": "Sale invoice reminder",
- "sms_notification.receipt_details.label": "Sale receipt details",
- "sms_notification.sale_estimate_details.label": "Sale estimate details",
- "sms_notification.payment_receive_details.label": "Payment receive details",
- "sms_notification.customer_balance.label": "Customer balance",
-
- "sms_notification.invoice_details.description": "SMS notification will be sent to your customer once invoice created and published or when notify customer via SMS about the invoice.",
- "sms_notification.payment_receive.description": "Payment thank you message notification will be sent to customer once the payment created and published or notify customer about payment manually.",
- "sms_notification.receipt_details.description": "SMS notification will be sent to your cusotmer once receipt created and published or when notify customer about the receipt manually.",
- "sms_notification.customer_balance.description": "Send SMS to notify customers about their current outstanding balance.",
- "sms_notification.estimate_details.description": "SMS notification will be sent to your customer once estimate publish or notify customer about estimate manually.",
- "sms_notification.invoice_reminder.description": "SMS notification will be sent to remind the customer to pay earliest, either automatically or manually.",
-
- "sms_notification.customer_balance.default_message": "Dear {CustomerName}, This is reminder about your current outstanding balance of {Balance}, Please pay at the earliest. - {CompanyName}",
- "sms_notification.payment_receive.default_message": "'Hi, {CustomerName}, We have received your payment for the invoice - {InvoiceNumber}. We look forward to serving you again. Thank you. - {CompanyName}'",
- "sms_notification.estimate.default_message": "Hi, {CustomerName}, We have created an estimate - {EstimateNumber} for you. Please take a look and accept it to proceed further. Looking forward to hearing from you. - {CompanyName}",
-
- "sms_notification.invoice_details.default_message": "Hi, {CustomerName}, You have an outstanding amount of {DueAmount} for the invoice {InvoiceNumber}. - {CompanyName}",
- "sms_notification.receipt_details.default_message": "Hi, {CustomerName}, We have created receipt - {ReceiptNumber} for you. we look forward to serveing you again. Thank your - {CompanyName}",
- "sms_notification.invoice_reminder.default_message": "Dear {CustomerName}, The payment towards the invoice - {InvoiceNumber} is due. Please pay before {DueDate}. Thank you. - {CompanyName}",
-
- "module.sale_invoices.label": "Sale invoices",
- "module.sale_receipts.label": "Sale receipts",
- "module.sale_estimates.label": "Sale estimates",
- "module.payment_receives.label": "Payment receive",
- "module.customers.label": "Customers",
-
- "sms_notification.invoice.var.invoice_number": "References to invoice number.",
- "sms_notification.invoice.var.reference_number": "References to invoice reference number.",
- "sms_notification.invoice.var.customer_name": "References to invoice customer name.",
- "sms_notification.invoice.var.due_amount": "References to invoice due amount.",
- "sms_notification.invoice.var.amount": "References to invoice amount.",
- "sms_notification.invoice.var.company_name": "References to company name.",
- "sms_notification.invoice.var.due_date": "References to invoice due date.",
-
- "sms_notification.receipt.var.receipt_number": "References to receipt number.",
- "sms_notification.receipt.var.reference_number": "References to receipt reference number.",
- "sms_notification.receipt.var.customer_name": "References to receipt customer name.",
- "sms_notification.receipt.var.amount": "References to receipt amount.",
- "sms_notification.receipt.var.company_name": "References to company name.",
-
- "sms_notification.payment.var.payment_number": "References to payment transaction number.",
- "sms_notification.payment.var.reference_number": "References to payment reference number",
- "sms_notification.payment.var.customer_name": "References to payment customer name.",
- "sms_notification.payment.var.amount": "References to payment transaction amount.",
- "sms_notification.payment.company_name": "References to company name",
- "sms_notification.payment.var.invoice_number": "Reference to payment invoice number.",
-
- "sms_notification.estimate.var.estimate_number": "References to estimate number.",
- "sms_notification.estimate.var.reference_number": "References to estimate reference number.",
- "sms_notification.estimate.var.customer_name": "References to estimate customer name.",
- "sms_notification.estimate.var.amount": "References to estimate amount.",
- "sms_notification.estimate.var.company_name": "References to company name.",
- "sms_notification.estimate.var.expiration_date": "References to estimate expirtaion date.",
- "sms_notification.estimate.var.estimate_date": "References to estimate date.",
-
- "sms_notification.customer.var.customer_name": "References to customer name.",
- "sms_notification.customer.var.balance": "References to customer outstanding balance.",
- "sms_notification.customer.var.company_name": "References to company name.",
-
- "ability.accounts": "Chart of accounts",
- "ability.manual_journal": "Manual journals",
- "ability.cashflow": "Cash flow",
- "ability.inventory_adjustment": "Inventory adjustments",
- "ability.customers": "Customers",
- "ability.vendors": "vendors",
- "ability.sale_estimates": "Sale estimates",
- "ability.sale_invoices": "Sale invoices",
- "ability.sale_receipts": "Sale receipts",
- "ability.expenses": "Expenses",
- "ability.payments_receive": "Payments receive",
- "ability.purchase_invoices": "Purchase invoices",
- "ability.all_reports": "All reports",
- "ability.payments_made": "Payments made",
- "ability.preferences": "Preferences",
- "ability.mutate_system_preferences": "Mutate the system preferences.",
-
- "ability.items": "Items",
- "ability.view": "View",
- "ability.create": "Create",
- "ability.edit": "Edit",
- "ability.delete": "Delete",
- "ability.transactions_locking": "Ability to transactions locking.",
-
- "ability.balance_sheet_report": "Balance sheet.",
- "ability.profit_loss_sheet": "Profit/loss sheet",
- "ability.journal": "Journal",
- "ability.general_ledger": "General ledger",
- "ability.cashflow_report": "Cashflow",
- "ability.AR_aging_summary_report": "A/R aging summary",
- "ability.AP_aging_summary_report": "A/P aging summary",
- "ability.purchases_by_items": "Purchases by items",
- "ability.sales_by_items_report": "Sales by items",
- "ability.customers_transactions_report": "Customers transactions",
- "ability.vendors_transactions_report": "Vendors transactions",
- "ability.customers_summary_balance_report": "Customers summary balance",
- "ability.vendors_summary_balance_report": "Vendors summary balance",
- "ability.inventory_valuation_summary": "Inventory valuation summary",
- "ability.inventory_items_details": "Inventory items details",
-
- "vendor_credit.field.vendor": "Vendor name",
- "vendor_credit.field.amount": "Amount",
- "vendor_credit.field.currency_code": "Currency code",
- "vendor_credit.field.credit_date": "Credit date",
- "vendor_credit.field.credit_number": "Credit number",
- "vendor_credit.field.note": "Note",
- "vendor_credit.field.created_at": "Created at",
- "vendor_credit.field.reference_no": "Reference No.",
-
- "credit_note.field.terms_conditions": "Terms and conditions",
- "credit_note.field.note": "Note",
- "credit_note.field.currency_code": "Currency code",
- "credit_note.field.created_at": "Created at",
- "credit_note.field.amount": "Amount",
- "credit_note.field.credit_note_number": "Credit note number",
- "credit_note.field.credit_note_date": "Credit date",
- "credit_note.field.customer": "Customer",
- "credit_note.field.reference_no": "Reference No.",
-
- "Credit note": "Credit note",
- "Vendor credit": "Vendor credit",
- "Refund credit note": "Refund credit note",
- "Refund vendor credit": "Refund vendor credit",
- "credit_note.field.status": "Status",
- "credit_note.field.status.draft": "Draft",
- "credit_note.field.status.published": "Published",
- "credit_note.field.status.open": "Open",
- "credit_note.field.status.closed": "Closed",
-
- "transactions_locking.module.sales.label": "Sales",
- "transactions_locking.module.purchases.label": "Purchases",
- "transactions_locking.module.financial.label": "Financial",
- "transactions_locking.module.all_transactions": "All transactions",
-
- "transactions_locking.module.sales.desc": "Sale invoices, Receipts, credit notes, customers payment receive and customers opening balances.",
- "transactions_locking.module.purchases.desc": "Purchase invoices, vendors payments, vendor credit notes and vendors opening balances.",
- "transactions_locking.module.financial.desc": "Manual journal, expenses and inventory adjustments.",
-
- "inventory_adjustment.type.increment": "Increment",
- "inventory_adjustment.type.decrement": "Decrement",
-
- "customer.type.individual": "Individual",
- "customer.type.business": "Business",
-
- "credit_note.view.draft": "Draft",
- "credit_note.view.closed": "Closed",
- "credit_note.view.open": "Open",
- "credit_note.view.published": "Published",
-
- "vendor_credit.view.draft": "Draft",
- "vendor_credit.view.closed": "Closed",
- "vendor_credit.view.open": "Open",
- "vendor_credit.view.published": "Published",
-
- "allocation_method.value.label": "Value",
- "allocation_method.quantity.label": "Quantity",
-
- "balance_sheet.assets": "Assets",
- "balance_sheet.current_asset": "Current Asset",
- "balance_sheet.cash_and_cash_equivalents": "Cash and cash equivalents",
- "balance_sheet.accounts_receivable": "Accounts Receivable",
- "balance_sheet.inventory": "Inventory",
- "balance_sheet.other_current_assets": "Other current assets",
- "balance_sheet.fixed_asset": "Fixed Asset",
- "balance_sheet.non_current_assets": "Non-Current Assets",
- "balance_sheet.liabilities_and_equity": "Liabilities and Equity",
- "balance_sheet.liabilities": "Liabilities",
- "balance_sheet.current_liabilties": "Current Liabilties",
- "balance_sheet.long_term_liabilities": "Long-Term Liabilities",
- "balance_sheet.non_current_liabilities": "Non-Current Liabilities",
- "balance_sheet.equity": "Equity",
- "balance_sheet.net_income": "Net Income",
-
- "balance_sheet.account_name": "Account name",
- "balance_sheet.total": "Total",
- "balance_sheet.percentage_of_column": "% of Column",
- "balance_sheet.percentage_of_row": "% of Row",
-
- "financial_sheet.previoud_period_date": "{{date}} (PP)",
- "fianncial_sheet.previous_period_change": "Change (PP)",
- "financial_sheet.previous_period_percentage": "% Change (PP)",
-
- "financial_sheet.previous_year_date": "{{date}} (PY)",
- "financial_sheet.previous_year_change": "Change (PY)",
- "financial_sheet.previous_year_percentage": "% Change (PY)",
- "financial_sheet.total_row": "Total {{value}}",
-
- "profit_loss_sheet.income": "Income",
- "profit_loss_sheet.cost_of_sales": "Cost of sales",
- "profit_loss_sheet.gross_profit": "GROSS PROFIT",
- "profit_loss_sheet.expenses": "Expenses",
- "profit_loss_sheet.net_operating_income": "NET OPERATING INCOME",
- "profit_loss_sheet.other_income": "Other income",
- "profit_loss_sheet.other_expenses": "Other expenses",
- "profit_loss_sheet.net_income": "NET INCOME",
-
- "profit_loss_sheet.account_name": "Account name",
- "profit_loss_sheet.total": "Total",
-
- "profit_loss_sheet.percentage_of_income": "% of Income",
- "profit_loss_sheet.percentage_of_expenses": "% of Expenses",
- "profit_loss_sheet.percentage_of_column": "% of Column",
- "profit_loss_sheet.percentage_of_row": "% of Row",
-
- "contact_summary_balance.account_name": "Account name",
- "contact_summary_balance.total": "Total",
- "contact_summary_balance.percentage_column": "% of Column",
-
- "warehouses.primary_warehouse": "Primary warehouse",
- "branches.head_branch": "Head Branch",
-
- "account.accounts_payable.currency": "Accounts Payable (A/P) - {{currency}}",
- "account.accounts_receivable.currency": "Accounts Receivable (A/R) - {{currency}}",
-
- "role.admin.name": "Admin",
- "role.admin.desc": "Unrestricted access to all modules.",
-
- "role.staff.name": "Staff",
- "role.staff.desc": "Access to all modules except reports, settings and accountant.",
-
- "warehouse_transfer.view.draft.name": "Draft",
- "warehouse_transfer.view.in_transit.name": "In Transit",
- "warehouse_transfer.view.transferred.name": "Transferred"
-}
\ No newline at end of file
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryApplication.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryApplication.ts
new file mode 100644
index 000000000..73c08b2d8
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryApplication.ts
@@ -0,0 +1,53 @@
+import { Inject, Service } from 'typedi';
+import { APAgingSummaryExportInjectable } from './APAgingSummaryExportInjectable';
+import { APAgingSummaryTableInjectable } from './APAgingSummaryTableInjectable';
+import { IAPAgingSummaryQuery } from '@/interfaces';
+import { APAgingSummaryService } from './APAgingSummaryService';
+
+@Service()
+export class APAgingSummaryApplication {
+ @Inject()
+ private APAgingSummaryTable: APAgingSummaryTableInjectable;
+
+ @Inject()
+ private APAgingSummaryExport: APAgingSummaryExportInjectable;
+
+ @Inject()
+ private APAgingSummarySheet: APAgingSummaryService;
+
+ /**
+ * Retrieve the A/P aging summary in sheet format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public sheet(tenantId: number, query: IAPAgingSummaryQuery) {
+ return this.APAgingSummarySheet.APAgingSummary(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/P aging summary in table format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public table(tenantId: number, query: IAPAgingSummaryQuery) {
+ return this.APAgingSummaryTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/P aging summary in CSV format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public csv(tenantId: number, query: IAPAgingSummaryQuery) {
+ return this.APAgingSummaryExport.csv(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/P aging summary in XLSX format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public xlsx(tenantId: number, query: IAPAgingSummaryQuery) {
+ return this.APAgingSummaryExport.xlsx(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryExportInjectable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryExportInjectable.ts
new file mode 100644
index 000000000..4561687e7
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { APAgingSummaryTableInjectable } from './APAgingSummaryTableInjectable';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { IAPAgingSummaryQuery } from '@/interfaces';
+
+@Service()
+export class APAgingSummaryExportInjectable {
+ @Inject()
+ private APAgingSummaryTable: APAgingSummaryTableInjectable;
+
+ /**
+ * Retrieves the A/P aging summary sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: IAPAgingSummaryQuery) {
+ const table = await this.APAgingSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the A/P aging summary sheet in CSV format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IAPAgingSummaryQuery
+ ): Promise {
+ const table = await this.APAgingSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts
index 73860c9a5..fa3e6a2b3 100644
--- a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts
@@ -1,14 +1,13 @@
import moment from 'moment';
import { Inject, Service } from 'typedi';
+import { isEmpty } from 'lodash';
import { IAPAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService';
import APAgingSummarySheet from './APAgingSummarySheet';
import { Tenant } from '@/system/models';
-import { isEmpty } from 'lodash';
-import APAgingSummaryTable from './APAgingSummaryTable';
@Service()
-export default class PayableAgingSummaryService {
+export class APAgingSummaryService {
@Inject()
tenancy: TenancyService;
@@ -18,7 +17,7 @@ export default class PayableAgingSummaryService {
/**
* Default report query.
*/
- get defaultQuery(): IAPAgingSummaryQuery {
+ private get defaultQuery(): IAPAgingSummaryQuery {
return {
asDate: moment().format('YYYY-MM-DD'),
agingDaysBefore: 30,
@@ -119,21 +118,4 @@ export default class PayableAgingSummaryService {
meta: this.reportMetadata(tenantId),
};
}
-
- /**
- * Retrieves A/P aging summary in table format.
- * @param {number} tenantId
- * @param {IAPAgingSummaryQuery} query
- */
- async APAgingSummaryTable(tenantId: number, query: IAPAgingSummaryQuery) {
- const report = await this.APAgingSummary(tenantId, query);
- const table = new APAgingSummaryTable(report.data, query, {});
-
- return {
- columns: table.tableColumns(),
- rows: table.tableRows(),
- meta: report.meta,
- query: report.query,
- };
- }
}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTableInjectable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTableInjectable.ts
new file mode 100644
index 000000000..f9eda1613
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTableInjectable.ts
@@ -0,0 +1,36 @@
+import { Inject, Service } from 'typedi';
+import { IAPAgingSummaryQuery, IAPAgingSummaryTable } from '@/interfaces';
+import { APAgingSummaryService } from './APAgingSummaryService';
+import APAgingSummaryTable from './APAgingSummaryTable';
+
+@Service()
+export class APAgingSummaryTableInjectable {
+ @Inject()
+ private APAgingSummarySheet: APAgingSummaryService;
+
+ /**
+ * Retrieves A/P aging summary in table format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: IAPAgingSummaryQuery
+ ): Promise {
+ const report = await this.APAgingSummarySheet.APAgingSummary(
+ tenantId,
+ query
+ );
+ const table = new APAgingSummaryTable(report.data, query, {});
+
+ return {
+ table: {
+ columns: table.tableColumns(),
+ rows: table.tableRows(),
+ },
+ meta: report.meta,
+ query: report.query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryApplication.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryApplication.ts
new file mode 100644
index 000000000..d3282ca4b
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryApplication.ts
@@ -0,0 +1,53 @@
+import { Inject, Service } from 'typedi';
+import { IARAgingSummaryQuery } from '@/interfaces';
+import { ARAgingSummaryTableInjectable } from './ARAgingSummaryTableInjectable';
+import { ARAgingSummaryExportInjectable } from './ARAgingSummaryExportInjectable';
+import ARAgingSummaryService from './ARAgingSummaryService';
+
+@Service()
+export class ARAgingSummaryApplication {
+ @Inject()
+ private ARAgingSummaryTable: ARAgingSummaryTableInjectable;
+
+ @Inject()
+ private ARAgingSummaryExport: ARAgingSummaryExportInjectable;
+
+ @Inject()
+ private ARAgingSummarySheet: ARAgingSummaryService;
+
+ /**
+ * Retrieve the A/R aging summary sheet.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public sheet(tenantId: number, query: IARAgingSummaryQuery) {
+ return this.ARAgingSummarySheet.ARAgingSummary(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/R aging summary in table format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public table(tenantId: number, query: IARAgingSummaryQuery) {
+ return this.ARAgingSummaryTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/R aging summary in XLSX format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public xlsx(tenantId: number, query: IARAgingSummaryQuery) {
+ return this.ARAgingSummaryExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieve the A/R aging summary in CSV format.
+ * @param {number} tenantId
+ * @param {IAPAgingSummaryQuery} query
+ */
+ public csv(tenantId: number, query: IARAgingSummaryQuery) {
+ return this.ARAgingSummaryExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryExportInjectable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryExportInjectable.ts
new file mode 100644
index 000000000..25c3dd064
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryExportInjectable.ts
@@ -0,0 +1,46 @@
+import { Inject, Service } from 'typedi';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { ARAgingSummaryTableInjectable } from './ARAgingSummaryTableInjectable';
+import { IARAgingSummaryQuery } from '@/interfaces';
+
+@Service()
+export class ARAgingSummaryExportInjectable {
+ @Inject()
+ private ARAgingSummaryTable: ARAgingSummaryTableInjectable;
+
+ /**
+ * Retrieves the A/R aging summary sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IARAgingSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(
+ tenantId: number,
+ query: IARAgingSummaryQuery
+ ): Promise {
+ const table = await this.ARAgingSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the A/R aging summary sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IARAgingSummaryQuery
+ ): Promise {
+ const table = await this.ARAgingSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
index 60bdb8675..e13dfc276 100644
--- a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
@@ -5,7 +5,6 @@ import { IARAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService';
import ARAgingSummarySheet from './ARAgingSummarySheet';
import { Tenant } from '@/system/models';
-import ARAgingSummaryTable from './ARAgingSummaryTable';
@Service()
export default class ARAgingSummaryService {
@@ -118,21 +117,4 @@ export default class ARAgingSummaryService {
meta: this.reportMetadata(tenantId),
};
}
-
- /**
- * Retrieves A/R aging summary in table format.
- * @param {number} tenantId
- * @param {IARAgingSummaryQuery} query
- */
- async ARAgingSummaryTable(tenantId: number, query: IARAgingSummaryQuery) {
- const report = await this.ARAgingSummary(tenantId, query);
- const table = new ARAgingSummaryTable(report.data, query, {});
-
- return {
- columns: table.tableColumns(),
- rows: table.tableRows(),
- meta: report.meta,
- query,
- };
- }
}
diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTableInjectable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTableInjectable.ts
new file mode 100644
index 000000000..10ac9ee8c
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTableInjectable.ts
@@ -0,0 +1,36 @@
+import { IARAgingSummaryQuery, IARAgingSummaryTable } from '@/interfaces';
+import { Inject, Service } from 'typedi';
+import ARAgingSummaryTable from './ARAgingSummaryTable';
+import ARAgingSummaryService from './ARAgingSummaryService';
+
+@Service()
+export class ARAgingSummaryTableInjectable {
+ @Inject()
+ private ARAgingSummarySheet: ARAgingSummaryService;
+
+ /**
+ * Retrieves A/R aging summary in table format.
+ * @param {number} tenantId
+ * @param {IARAgingSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: IARAgingSummaryQuery
+ ): Promise {
+ const report = await this.ARAgingSummarySheet.ARAgingSummary(
+ tenantId,
+ query
+ );
+ const table = new ARAgingSummaryTable(report.data, query, {});
+
+ return {
+ table: {
+ columns: table.tableColumns(),
+ rows: table.tableRows(),
+ },
+ meta: report.meta,
+ query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetApplication.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetApplication.ts
new file mode 100644
index 000000000..01ab77bfe
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetApplication.ts
@@ -0,0 +1,57 @@
+import { Inject, Service } from 'typedi';
+import { IBalanceSheetQuery } from '@/interfaces';
+import { BalanceSheetExportInjectable } from './BalanceSheetExportInjectable';
+import { BalanceSheetTableInjectable } from './BalanceSheetTableInjectable';
+import BalanceSheetStatementService from './BalanceSheetInjectable';
+
+@Service()
+export class BalanceSheetApplication {
+ @Inject()
+ public balanceSheetExport: BalanceSheetExportInjectable;
+
+ @Inject()
+ public balanceSheetTable: BalanceSheetTableInjectable;
+
+ @Inject()
+ public balanceSheet: BalanceSheetStatementService;
+
+ /**
+ * Retrieves the balnace sheet in json format.
+ * @param {numnber} tenantId
+ * @param {IBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public sheet(tenantId: number, query: IBalanceSheetQuery) {
+ return this.balanceSheet.balanceSheet(tenantId, query);
+ }
+
+ /**
+ * Retrieves the balance sheet in table format.
+ * @param {number} tenantId
+ * @param {IBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public table(tenantId: number, query: IBalanceSheetQuery) {
+ return this.balanceSheetTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(tenantId: number, query: IBalanceSheetQuery) {
+ return this.balanceSheetExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {IBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public csv(tenantId: number, query: IBalanceSheetQuery): Promise {
+ return this.balanceSheetExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetExportInjectable.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetExportInjectable.ts
new file mode 100644
index 000000000..2c43d5f80
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { BalanceSheetTableInjectable } from './BalanceSheetTableInjectable';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { IBalanceSheetQuery } from '@/interfaces';
+
+@Service()
+export class BalanceSheetExportInjectable {
+ @Inject()
+ private balanceSheetTable: BalanceSheetTableInjectable;
+
+ /**
+ * Retrieves the trial balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: IBalanceSheetQuery) {
+ const table = await this.balanceSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the trial balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IBalanceSheetQuery
+ ): Promise {
+ const table = await this.balanceSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetInjectable.ts
similarity index 96%
rename from packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts
rename to packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetInjectable.ts
index b0470c745..02e136ca1 100644
--- a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts
+++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetInjectable.ts
@@ -19,13 +19,10 @@ export default class BalanceSheetStatementService
implements IBalanceSheetStatementService
{
@Inject()
- tenancy: TenancyService;
-
- @Inject('logger')
- logger: any;
+ private tenancy: TenancyService;
@Inject()
- inventoryService: InventoryService;
+ private inventoryService: InventoryService;
/**
* Defaults balance sheet filter query.
@@ -94,10 +91,8 @@ export default class BalanceSheetStatementService
/**
* Retrieve balance sheet statement.
- * -------------
* @param {number} tenantId
* @param {IBalanceSheetQuery} query
- *
* @return {IBalanceSheetStatement}
*/
public async balanceSheet(
diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetTableInjectable.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetTableInjectable.ts
new file mode 100644
index 000000000..3eb769350
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetTableInjectable.ts
@@ -0,0 +1,42 @@
+import { Inject, Service } from 'typedi';
+import BalanceSheetStatementService from './BalanceSheetInjectable';
+import BalanceSheetTable from './BalanceSheetTable';
+import { IBalanceSheetQuery, IBalanceSheetTable } from '@/interfaces';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+
+@Service()
+export class BalanceSheetTableInjectable {
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ @Inject()
+ private balanceSheetService: BalanceSheetStatementService;
+
+ /**
+ * Retrieves the balance sheet in table format.
+ * @param {number} tenantId
+ * @param {number} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ filter: IBalanceSheetQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const { data, query, meta } = await this.balanceSheetService.balanceSheet(
+ tenantId,
+ filter
+ );
+ const table = new BalanceSheetTable(data, query, i18n);
+
+ return {
+ table: {
+ columns: table.tableColumns(),
+ rows: table.tableRows(),
+ },
+ query,
+ meta,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashflowExportInjectable.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashflowExportInjectable.ts
new file mode 100644
index 000000000..8562cfbf5
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CashFlow/CashflowExportInjectable.ts
@@ -0,0 +1,46 @@
+import { Inject, Service } from 'typedi';
+import { ICashFlowStatementQuery } from '@/interfaces';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { CashflowTableInjectable } from './CashflowTableInjectable';
+
+@Service()
+export class CashflowExportInjectable {
+ @Inject()
+ private cashflowSheetTable: CashflowTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(
+ tenantId: number,
+ query: ICashFlowStatementQuery
+ ): Promise {
+ const table = await this.cashflowSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ICashFlowStatementQuery
+ ): Promise {
+ const table = await this.cashflowSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashflowSheetApplication.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashflowSheetApplication.ts
new file mode 100644
index 000000000..0fd8b7357
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CashFlow/CashflowSheetApplication.ts
@@ -0,0 +1,58 @@
+import { Inject, Service } from 'typedi';
+import { CashflowExportInjectable } from './CashflowExportInjectable';
+import { ICashFlowStatementQuery } from '@/interfaces';
+import CashFlowStatementService from './CashFlowService';
+import { CashflowTableInjectable } from './CashflowTableInjectable';
+
+@Service()
+export class CashflowSheetApplication {
+ @Inject()
+ private cashflowExport: CashflowExportInjectable;
+
+ @Inject()
+ private cashflowSheet: CashFlowStatementService;
+
+ @Inject()
+ private cashflowTable: CashflowTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ */
+ public async sheet(tenantId: number, query: ICashFlowStatementQuery) {
+ return this.cashflowSheet.cashFlow(tenantId, query);
+ }
+
+ /**
+ * Retrieves the cashflow sheet in table format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ */
+ public async table(tenantId: number, query: ICashFlowStatementQuery) {
+ return this.cashflowTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: ICashFlowStatementQuery) {
+ return this.cashflowExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ICashFlowStatementQuery
+ ): Promise {
+ return this.cashflowExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts
new file mode 100644
index 000000000..0a54071f2
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CashFlow/CashflowTableInjectable.ts
@@ -0,0 +1,37 @@
+import { Inject, Service } from "typedi";
+import { ICashFlowStatementQuery, ICashFlowStatementTable } from "@/interfaces";
+import HasTenancyService from "@/services/Tenancy/TenancyService";
+import CashFlowTable from "./CashFlowTable";
+import CashFlowStatementService from "./CashFlowService";
+
+@Service()
+export class CashflowTableInjectable {
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ @Inject()
+ private cashflowSheet: CashFlowStatementService;
+
+ /**
+ * Retrieves the cash flow table.
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: ICashFlowStatementQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const cashflowDOO = await this.cashflowSheet.cashFlow(tenantId, query);
+ const cashflowTable = new CashFlowTable(cashflowDOO, i18n);
+
+ return {
+ table: {
+ columns: cashflowTable.tableColumns(),
+ rows: cashflowTable.tableRows(),
+ },
+ query: cashflowDOO.query,
+ meta: cashflowDOO.meta,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication.ts b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication.ts
new file mode 100644
index 000000000..964cd91a9
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication.ts
@@ -0,0 +1,60 @@
+import { Inject, Service } from 'typedi';
+import { CustomerBalanceSummaryExportInjectable } from './CustomerBalanceSummaryExportInjectable';
+import { CustomerBalanceSummaryTableInjectable } from './CustomerBalanceSummaryTableInjectable';
+import { ICustomerBalanceSummaryQuery } from '@/interfaces';
+import { CustomerBalanceSummaryService } from './CustomerBalanceSummaryService';
+
+@Service()
+export class CustomerBalanceSummaryApplication {
+ @Inject()
+ private customerBalanceSummaryTable: CustomerBalanceSummaryTableInjectable;
+
+ @Inject()
+ private customerBalanceSummaryExport: CustomerBalanceSummaryExportInjectable;
+
+ @Inject()
+ private customerBalanceSummarySheet: CustomerBalanceSummaryService;
+
+ /**
+ * Retrieves the customer balance sheet in json format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public sheet(tenantId: number, query: ICustomerBalanceSummaryQuery) {
+ return this.customerBalanceSummarySheet.customerBalanceSummary(
+ tenantId,
+ query
+ );
+ }
+
+ /**
+ * Retrieves the customer balance sheet in json format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public table(tenantId: number, query: ICustomerBalanceSummaryQuery) {
+ return this.customerBalanceSummaryTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the customer balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(tenantId: number, query: ICustomerBalanceSummaryQuery) {
+ return this.customerBalanceSummaryExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the customer balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public csv(tenantId: number, query: ICustomerBalanceSummaryQuery) {
+ return this.customerBalanceSummaryExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryExportInjectable.ts b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryExportInjectable.ts
new file mode 100644
index 000000000..97fec14d8
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { ICustomerBalanceSummaryQuery } from '@/interfaces';
+import { CustomerBalanceSummaryTableInjectable } from './CustomerBalanceSummaryTableInjectable';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+
+@Service()
+export class CustomerBalanceSummaryExportInjectable {
+ @Inject()
+ private customerBalanceSummaryTable: CustomerBalanceSummaryTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: ICustomerBalanceSummaryQuery) {
+ const table = await this.customerBalanceSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ICustomerBalanceSummaryQuery
+ ): Promise {
+ const table = await this.customerBalanceSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService.ts b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService.ts
index 01ec0e050..78afc3bb2 100644
--- a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService.ts
+++ b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService.ts
@@ -1,7 +1,5 @@
import { Inject } from 'typedi';
import moment from 'moment';
-import { isEmpty, map } from 'lodash';
-import TenancyService from '@/services/Tenancy/TenancyService';
import * as R from 'ramda';
import {
ICustomerBalanceSummaryService,
@@ -11,28 +9,21 @@ import {
ILedgerEntry,
} from '@/interfaces';
import { CustomerBalanceSummaryReport } from './CustomerBalanceSummary';
-
import Ledger from '@/services/Accounting/Ledger';
import CustomerBalanceSummaryRepository from './CustomerBalanceSummaryRepository';
import { Tenant } from '@/system/models';
-export default class CustomerBalanceSummaryService
+export class CustomerBalanceSummaryService
implements ICustomerBalanceSummaryService
{
@Inject()
- tenancy: TenancyService;
-
- @Inject('logger')
- logger: any;
-
- @Inject()
- reportRepository: CustomerBalanceSummaryRepository;
+ private reportRepository: CustomerBalanceSummaryRepository;
/**
* Defaults balance sheet filter query.
* @return {ICustomerBalanceSummaryQuery}
*/
- get defaultQuery(): ICustomerBalanceSummaryQuery {
+ private get defaultQuery(): ICustomerBalanceSummaryQuery {
return {
asDate: moment().format('YYYY-MM-DD'),
numberFormat: {
@@ -43,13 +34,12 @@ export default class CustomerBalanceSummaryService
negativeFormat: 'mines',
},
percentageColumn: false,
-
+
noneZero: false,
noneTransactions: true,
};
}
-
/**
* Retrieve the customers ledger entries mapped from accounts transactions.
* @param {number} tenantId
@@ -75,7 +65,7 @@ export default class CustomerBalanceSummaryService
* @param {ICustomerBalanceSummaryQuery} query
* @return {Promise}
*/
- async customerBalanceSummary(
+ public async customerBalanceSummary(
tenantId: number,
query: ICustomerBalanceSummaryQuery
): Promise {
@@ -86,13 +76,6 @@ export default class CustomerBalanceSummaryService
// Merges the default query and request query.
const filter = { ...this.defaultQuery, ...query };
- this.logger.info(
- '[customer_balance_summary] trying to calculate the report.',
- {
- filter,
- tenantId,
- }
- );
// Retrieve the customers list ordered by the display name.
const customers = await this.reportRepository.getCustomers(
tenantId,
@@ -111,7 +94,7 @@ export default class CustomerBalanceSummaryService
ledger,
customers,
filter,
- tenant.metadata.baseCurrency,
+ tenant.metadata.baseCurrency
);
return {
diff --git a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableInjectable.ts b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableInjectable.ts
new file mode 100644
index 000000000..56450d4ca
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableInjectable.ts
@@ -0,0 +1,44 @@
+import { Inject, Service } from 'typedi';
+import { CustomerBalanceSummaryService } from './CustomerBalanceSummaryService';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+import {
+ ICustomerBalanceSummaryQuery,
+ ICustomerBalanceSummaryTable,
+} from '@/interfaces';
+import { CustomerBalanceSummaryTable } from './CustomerBalanceSummaryTableRows';
+
+@Service()
+export class CustomerBalanceSummaryTableInjectable {
+ @Inject()
+ private customerBalanceSummaryService: CustomerBalanceSummaryService;
+
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ /**
+ * Retrieves the customer balance sheet in table format.
+ * @param {number} tenantId
+ * @param {ICustomerBalanceSummaryQuery} filter
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ filter: ICustomerBalanceSummaryQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+ const { data, query } =
+ await this.customerBalanceSummaryService.customerBalanceSummary(
+ tenantId,
+ filter
+ );
+ const tableRows = new CustomerBalanceSummaryTable(data, filter, i18n);
+
+ return {
+ table: {
+ columns: tableRows.tableColumns(),
+ rows: tableRows.tableRows(),
+ },
+ query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows.ts b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows.ts
index b55a12613..e6cdc6415 100644
--- a/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows.ts
+++ b/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows.ts
@@ -15,7 +15,7 @@ enum TABLE_ROWS_TYPES {
TOTAL = 'TOTAL',
}
-export default class CustomerBalanceSummaryTable {
+export class CustomerBalanceSummaryTable {
report: ICustomerBalanceSummaryData;
query: ICustomerBalanceSummaryQuery;
i18n: any;
diff --git a/packages/server/src/services/FinancialStatements/FinancialTableStructure.ts b/packages/server/src/services/FinancialStatements/FinancialTableStructure.ts
new file mode 100644
index 000000000..6b3bb38b7
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/FinancialTableStructure.ts
@@ -0,0 +1,48 @@
+import { ITableRow } from '@/interfaces';
+import { flatNestedTree } from '@/utils/deepdash';
+import { repeat } from 'lodash';
+
+interface FlatNestTreeOpts {
+ nestedPrefix?: string;
+ nestedPrefixIndex?: number;
+}
+
+export class FinancialTableStructure {
+ /**
+ * Converts the given table object with nested rows in flat rows.
+ * @param {ITableRow[]}
+ * @param {FlatNestTreeOpts}
+ * @returns {ITableRow[]}
+ */
+ public static flatNestedTree = (
+ obj: ITableRow[],
+ options?: FlatNestTreeOpts
+ ): ITableRow[] => {
+ const parsedOptions = {
+ nestedPrefix: ' ',
+ nestedPrefixIndex: 0,
+ ...options,
+ };
+ const { nestedPrefixIndex, nestedPrefix } = parsedOptions;
+
+ return flatNestedTree(
+ obj,
+ (item, key, context) => {
+ const cells = item.cells.map((cell, index) => {
+ return {
+ ...cell,
+ value:
+ (context.depth > 1 && nestedPrefixIndex === index
+ ? repeat(nestedPrefix, context.depth)
+ : '') + cell.value,
+ };
+ });
+ return {
+ ...item,
+ cells,
+ };
+ },
+ parsedOptions
+ );
+ };
+}
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts
index d09cf19cd..489acff3e 100644
--- a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts
@@ -29,7 +29,7 @@ enum INodeTypes {
CLOSING_ENTRY = 'CLOSING_ENTRY',
}
-export default class InventoryDetails extends FinancialSheet {
+export class InventoryDetails extends FinancialSheet {
readonly inventoryTransactionsByItemId: Map;
readonly openingBalanceTransactions: Map;
readonly query: IInventoryDetailsQuery;
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication.ts
new file mode 100644
index 000000000..a2639094e
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication.ts
@@ -0,0 +1,66 @@
+import {
+ IInventoryDetailsQuery,
+ IInvetoryItemDetailsTable,
+} from '@/interfaces';
+import { Inject, Service } from 'typedi';
+import { InventoryDetailsExportInjectable } from './InventoryDetailsExportInjectable';
+import { InventoryDetailsTableInjectable } from './InventoryDetailsTableInjectable';
+import { InventoryDetailsService } from './InventoryDetailsService';
+
+@Service()
+export class InventortyDetailsApplication {
+ @Inject()
+ private inventoryDetailsExport: InventoryDetailsExportInjectable;
+
+ @Inject()
+ private inventoryDetailsTable: InventoryDetailsTableInjectable;
+
+ @Inject()
+ private inventoryDetails: InventoryDetailsService;
+
+ /**
+ * Retrieves the inventory details report in sheet format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public sheet(tenantId: number, query: IInventoryDetailsQuery) {
+ return this.inventoryDetails.inventoryDetails(tenantId, query);
+ }
+
+ /**
+ * Retrieve the inventory details report in table format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns
+ */
+ public table(
+ tenantId: number,
+ query: IInventoryDetailsQuery
+ ): Promise {
+ return this.inventoryDetailsTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the inventory details report in XLSX format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(
+ tenantId: number,
+ query: IInventoryDetailsQuery
+ ): Promise {
+ return this.inventoryDetailsExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the inventory details report in CSV format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public csv(tenantId: number, query: IInventoryDetailsQuery): Promise {
+ return this.inventoryDetailsExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsExportInjectable.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsExportInjectable.ts
new file mode 100644
index 000000000..bede24eb4
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { IInventoryDetailsQuery } from '@/interfaces';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { InventoryDetailsTableInjectable } from './InventoryDetailsTableInjectable';
+
+@Service()
+export class InventoryDetailsExportInjectable {
+ @Inject()
+ private inventoryDetailsTable: InventoryDetailsTableInjectable;
+
+ /**
+ * Retrieves the trial balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: IInventoryDetailsQuery) {
+ const table = await this.inventoryDetailsTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the trial balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IInventoryDetailsQuery
+ ): Promise {
+ const table = await this.inventoryDetailsTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
index cdeca4f39..d74137753 100644
--- a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
@@ -6,7 +6,7 @@ import {
IInventoryItemDetailMeta,
} from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService';
-import InventoryDetails from './InventoryDetails';
+import { InventoryDetails } from './InventoryDetails';
import FinancialSheet from '../FinancialSheet';
import InventoryDetailsRepository from './InventoryDetailsRepository';
import InventoryService from '@/services/Inventory/Inventory';
@@ -14,7 +14,7 @@ import { parseBoolean } from 'utils';
import { Tenant } from '@/system/models';
@Service()
-export default class InventoryDetailsService extends FinancialSheet {
+export class InventoryDetailsService extends FinancialSheet {
@Inject()
private tenancy: TenancyService;
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTable.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTable.ts
index 98d5522f2..1fa6d602d 100644
--- a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTable.ts
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTable.ts
@@ -20,13 +20,13 @@ enum IROW_TYPE {
const MAP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
-export default class InventoryDetailsTable {
+export class InventoryDetailsTable {
i18n: any;
report: any;
/**
* Constructor method.
- * @param {ICashFlowStatement} reportStatement - Report statement.
+ * @param {ICashFlowStatement} report - Report statement.
*/
constructor(reportStatement, i18n) {
this.report = reportStatement;
@@ -172,7 +172,7 @@ export default class InventoryDetailsTable {
* Retrieve the table rows of the inventory item details.
* @returns {ITableRow[]}
*/
- public tableData = (): ITableRow[] => {
+ public tableRows = (): ITableRow[] => {
return this.itemsMapper(this.report.data);
};
diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTableInjectable.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTableInjectable.ts
new file mode 100644
index 000000000..7cf803b46
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsTableInjectable.ts
@@ -0,0 +1,45 @@
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { Inject, Service } from 'typedi';
+import { InventoryDetailsTable } from './InventoryDetailsTable';
+import {
+ IInventoryDetailsQuery,
+ IInvetoryItemDetailsTable,
+} from '@/interfaces';
+import { InventoryDetailsService } from './InventoryDetailsService';
+
+@Service()
+export class InventoryDetailsTableInjectable {
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ @Inject()
+ private inventoryDetails: InventoryDetailsService;
+
+ /**
+ * Retrieves the inventory item details in table format.
+ * @param {number} tenantId
+ * @param {IInventoryDetailsQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: IInventoryDetailsQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const inventoryDetails = await this.inventoryDetails.inventoryDetails(
+ tenantId,
+ query
+ );
+ const table = new InventoryDetailsTable(inventoryDetails, i18n);
+
+ return {
+ table: {
+ rows: table.tableRows(),
+ columns: table.tableColumns(),
+ },
+ query: inventoryDetails.query,
+ meta: inventoryDetails.meta,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetApplication.ts b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetApplication.ts
new file mode 100644
index 000000000..eee89e73a
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetApplication.ts
@@ -0,0 +1,60 @@
+import { Inject, Service } from 'typedi';
+import { ProfitLossSheetExportInjectable } from './ProfitLossSheetExportInjectable';
+import { ProfitLossSheetTableInjectable } from './ProfitLossSheetTableInjectable';
+import { IProfitLossSheetQuery, IProfitLossSheetTable } from '@/interfaces';
+import ProfitLossSheetService from './ProfitLossSheetService';
+
+@Service()
+export class ProfitLossSheetApplication {
+ @Inject()
+ private profitLossTable: ProfitLossSheetTableInjectable;
+
+ @Inject()
+ private profitLossExport: ProfitLossSheetExportInjectable;
+
+ @Inject()
+ private profitLossSheet: ProfitLossSheetService;
+
+ /**
+ * Retreives the profit/loss sheet.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {}
+ */
+ public sheet(tenantId: number, query: IProfitLossSheetQuery) {
+ return this.profitLossSheet.profitLossSheet(tenantId, query);
+ }
+
+ /**
+ * Retrieves the profit/loss sheet table format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {Promise}
+ */
+ public table(
+ tenantId: number,
+ query: IProfitLossSheetQuery
+ ): Promise {
+ return this.profitLossTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the profit/loss sheet in csv format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {Promise}
+ */
+ public csv(tenantId: number, query: IProfitLossSheetQuery): Promise {
+ return this.profitLossExport.csv(tenantId, query);
+ }
+
+ /**
+ * Retrieves the profit/loss sheet in xlsx format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(tenantId: number, query: IProfitLossSheetQuery): Promise {
+ return this.profitLossExport.xlsx(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetExportInjectable.ts b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetExportInjectable.ts
new file mode 100644
index 000000000..ba2371797
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { IProfitLossSheetQuery } from '@/interfaces';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { ProfitLossSheetTableInjectable } from './ProfitLossSheetTableInjectable';
+
+@Service()
+export class ProfitLossSheetExportInjectable {
+ @Inject()
+ private profitLossSheetTable: ProfitLossSheetTableInjectable;
+
+ /**
+ * Retrieves the profit/loss sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: IProfitLossSheetQuery) {
+ const table = await this.profitLossSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the profit/loss sheet in CSV format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IProfitLossSheetQuery
+ ): Promise {
+ const table = await this.profitLossSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService.ts b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService.ts
index 14d17fc5a..20cf9a170 100644
--- a/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService.ts
+++ b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService.ts
@@ -16,39 +16,10 @@ import { ProfitLossSheetRepository } from './ProfitLossSheetRepository';
@Service()
export default class ProfitLossSheetService {
@Inject()
- tenancy: TenancyService;
-
- @Inject('logger')
- logger: any;
+ private tenancy: TenancyService;
@Inject()
- inventoryService: InventoryService;
-
- /**
- * Retrieve the trial balance sheet meta.
- * @param {number} tenantId - Tenant id.
- * @returns {ITrialBalanceSheetMeta}
- */
- reportMetadata(tenantId: number): IProfitLossSheetMeta {
- const settings = this.tenancy.settings(tenantId);
-
- const isCostComputeRunning =
- this.inventoryService.isItemsCostComputeRunning(tenantId);
- const organizationName = settings.get({
- group: 'organization',
- key: 'name',
- });
- const baseCurrency = settings.get({
- group: 'organization',
- key: 'base_currency',
- });
-
- return {
- isCostComputeRunning: parseBoolean(isCostComputeRunning, false),
- organizationName,
- baseCurrency,
- };
- }
+ private inventoryService: InventoryService;
/**
* Retrieve profit/loss sheet statement.
@@ -56,7 +27,7 @@ export default class ProfitLossSheetService {
* @param {IProfitLossSheetQuery} query
* @return { }
*/
- profitLossSheet = async (
+ public profitLossSheet = async (
tenantId: number,
query: IProfitLossSheetQuery
): Promise<{
@@ -70,13 +41,6 @@ export default class ProfitLossSheetService {
// Merges the given query with default filter query.
const filter = mergeQueryWithDefaults(query);
- // Get the given accounts or throw not found service error.
- // if (filter.accountsIds.length > 0) {
- // await this.accountsService.getAccountsOrThrowError(
- // tenantId,
- // filter.accountsIds
- // );
- // }
const tenant = await Tenant.query()
.findById(tenantId)
.withGraphFetched('metadata');
@@ -101,4 +65,30 @@ export default class ProfitLossSheetService {
meta: this.reportMetadata(tenantId),
};
};
+
+ /**
+ * Retrieve the trial balance sheet meta.
+ * @param {number} tenantId - Tenant id.
+ * @returns {ITrialBalanceSheetMeta}
+ */
+ private reportMetadata(tenantId: number): IProfitLossSheetMeta {
+ const settings = this.tenancy.settings(tenantId);
+
+ const isCostComputeRunning =
+ this.inventoryService.isItemsCostComputeRunning(tenantId);
+ const organizationName = settings.get({
+ group: 'organization',
+ key: 'name',
+ });
+ const baseCurrency = settings.get({
+ group: 'organization',
+ key: 'base_currency',
+ });
+
+ return {
+ isCostComputeRunning: parseBoolean(isCostComputeRunning, false),
+ organizationName,
+ baseCurrency,
+ };
+ }
}
diff --git a/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetTableInjectable.ts b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetTableInjectable.ts
new file mode 100644
index 000000000..326e7aaef
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetTableInjectable.ts
@@ -0,0 +1,42 @@
+import { Inject, Service } from 'typedi';
+import ProfitLossSheetService from './ProfitLossSheetService';
+import { ProfitLossSheetTable } from './ProfitLossSheetTable';
+import { IProfitLossSheetQuery, IProfitLossSheetTable } from '@/interfaces';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+
+@Service()
+export class ProfitLossSheetTableInjectable {
+ @Inject()
+ private profitLossSheet: ProfitLossSheetService;
+
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ /**
+ * Retrieves the profit/loss sheet in table format.
+ * @param {number} tenantId
+ * @param {IProfitLossSheetQuery} filter
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ filter: IProfitLossSheetQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const { data, query, meta } = await this.profitLossSheet.profitLossSheet(
+ tenantId,
+ filter
+ );
+ const table = new ProfitLossSheetTable(data, query, i18n);
+
+ return {
+ table: {
+ rows: table.tableRows(),
+ columns: table.tableColumns(),
+ },
+ query,
+ meta,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
index 7570ef572..6f81e1489 100644
--- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
+++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
@@ -87,10 +87,6 @@ export default class SalesByItemsReportService {
...this.defaultQuery,
...query,
};
- this.logger.info('[sales_by_items] trying to calculate the report.', {
- filter,
- tenantId,
- });
// Inventory items for sales report.
const inventoryItems = await Item.query().onBuild((q) => {
q.where('type', 'inventory');
diff --git a/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication.ts b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication.ts
new file mode 100644
index 000000000..f0e5a5248
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication.ts
@@ -0,0 +1,63 @@
+import { Inject, Service } from 'typedi';
+import { SalesTaxLiabilitySummaryQuery } from '@/interfaces/SalesTaxLiabilitySummary';
+import { SalesTaxLiabilitySummaryTableInjectable } from './SalesTaxLiabilitySummaryTableInjectable';
+import { SalesTaxLiabilitySummaryExportInjectable } from './SalesTaxLiabilitySummaryExportInjectable';
+import { SalesTaxLiabilitySummaryService } from './SalesTaxLiabilitySummaryService';
+
+@Service()
+export class SalesTaxLiabilitySummaryApplication {
+ @Inject()
+ private salesTaxLiabilitySheet: SalesTaxLiabilitySummaryService;
+
+ @Inject()
+ private salesTaxLiabilityExport: SalesTaxLiabilitySummaryExportInjectable;
+
+ @Inject()
+ private salesTaxLiabilityTable: SalesTaxLiabilitySummaryTableInjectable;
+
+ /**
+ * Retrieves the sales tax liability summary in json format.
+ * @param {number} tenantId
+ * @param {SalesTaxLiabilitySummaryQuery} query
+ * @returns {Promise}
+ */
+ public sheet(tenantId: number, query: SalesTaxLiabilitySummaryQuery) {
+ return this.salesTaxLiabilitySheet.salesTaxLiability(tenantId, query);
+ }
+
+ /**
+ * Retrieves the sales tax liability summary in table format.
+ * @param {number} tenantId
+ * @param {SalesTaxLiabilitySummaryQuery} query
+ * @return {Promise}
+ */
+ public table(tenantId: number, query: SalesTaxLiabilitySummaryQuery) {
+ return this.salesTaxLiabilityTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the sales tax liability summary in XLSX format.
+ * @param {number} tenantId
+ * @param {SalesTaxLiabilitySummaryQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(
+ tenantId: number,
+ query: SalesTaxLiabilitySummaryQuery
+ ): Promise {
+ return this.salesTaxLiabilityExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the sales tax liability summary in CSV format.
+ * @param {number} tenantId
+ * @param {SalesTaxLiabilitySummaryQuery} query
+ * @returns {Promise}
+ */
+ public csv(
+ tenantId: number,
+ query: SalesTaxLiabilitySummaryQuery
+ ): Promise {
+ return this.salesTaxLiabilityExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryExportInjectable.ts b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryExportInjectable.ts
new file mode 100644
index 000000000..932743679
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryExportInjectable.ts
@@ -0,0 +1,46 @@
+import { SalesTaxLiabilitySummaryQuery } from '@/interfaces/SalesTaxLiabilitySummary';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { Inject, Service } from 'typedi';
+import { SalesTaxLiabilitySummaryTableInjectable } from './SalesTaxLiabilitySummaryTableInjectable';
+
+@Service()
+export class SalesTaxLiabilitySummaryExportInjectable {
+ @Inject()
+ private salesTaxLiabilityTable: SalesTaxLiabilitySummaryTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(
+ tenantId: number,
+ query: SalesTaxLiabilitySummaryQuery
+ ): Promise {
+ const table = await this.salesTaxLiabilityTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: SalesTaxLiabilitySummaryQuery
+ ): Promise {
+ const table = await this.salesTaxLiabilityTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService.ts b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService.ts
index 09fa9283b..a1ec7a771 100644
--- a/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService.ts
+++ b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService.ts
@@ -5,7 +5,6 @@ import {
SalesTaxLiabilitySummaryQuery,
} from '@/interfaces/SalesTaxLiabilitySummary';
import { SalesTaxLiabilitySummary } from './SalesTaxLiabilitySummary';
-import { SalesTaxLiabilitySummaryTable } from './SalesTaxLiabilitySummaryTable';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service()
@@ -47,32 +46,6 @@ export class SalesTaxLiabilitySummaryService {
};
}
- /**
- * Retrieve sales tax liability summary table.
- * @param {number} tenantId
- * @param {SalesTaxLiabilitySummaryQuery} query
- * @returns
- */
- public async salesTaxLiabilitySummaryTable(
- tenantId: number,
- query: SalesTaxLiabilitySummaryQuery
- ) {
- const report = await this.salesTaxLiability(tenantId, query);
-
- // Creates the sales tax liability summary table.
- const table = new SalesTaxLiabilitySummaryTable(report.data, query);
-
- return {
- table: {
- rows: table.tableRows(),
- columns: table.tableColumns(),
- },
- data: report.data,
- query: report.query,
- meta: report.meta,
- };
- }
-
/**
* Retrieve the report meta.
* @param {number} tenantId -
diff --git a/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryTableInjectable.ts b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryTableInjectable.ts
new file mode 100644
index 000000000..907cab2ad
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryTableInjectable.ts
@@ -0,0 +1,40 @@
+import { Inject, Service } from 'typedi';
+import {
+ ISalesTaxLiabilitySummaryTable,
+ SalesTaxLiabilitySummaryQuery,
+} from '@/interfaces/SalesTaxLiabilitySummary';
+import { SalesTaxLiabilitySummaryTable } from './SalesTaxLiabilitySummaryTable';
+import { SalesTaxLiabilitySummaryService } from './SalesTaxLiabilitySummaryService';
+
+@Service()
+export class SalesTaxLiabilitySummaryTableInjectable {
+ @Inject()
+ private salesTaxLiability: SalesTaxLiabilitySummaryService;
+
+ /**
+ * Retrieve sales tax liability summary table.
+ * @param {number} tenantId
+ * @param {SalesTaxLiabilitySummaryQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: SalesTaxLiabilitySummaryQuery
+ ): Promise {
+ const report = await this.salesTaxLiability.salesTaxLiability(
+ tenantId,
+ query
+ );
+ // Creates the sales tax liability summary table.
+ const table = new SalesTaxLiabilitySummaryTable(report.data, query);
+
+ return {
+ table: {
+ rows: table.tableRows(),
+ columns: table.tableColumns(),
+ },
+ query: report.query,
+ meta: report.meta,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomers.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomers.ts
index 3ab624830..e35692bd5 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomers.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomers.ts
@@ -139,11 +139,4 @@ export default class TransactionsByCustomers extends TransactionsByContact {
public reportData(): ITransactionsByCustomersData {
return this.customersMapper(this.customers);
}
-
- /**
- * Retrieve the report columns.
- */
- public reportColumns() {
- return [];
- }
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersApplication.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersApplication.ts
new file mode 100644
index 000000000..b729c219a
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersApplication.ts
@@ -0,0 +1,72 @@
+import { Inject, Service } from 'typedi';
+import {
+ ITransactionsByCustomersFilter,
+ ITransactionsByCustomersStatement,
+} from '@/interfaces';
+import { TransactionsByCustomersTableInjectable } from './TransactionsByCustomersTableInjectable';
+import { TransactionsByCustomersExportInjectable } from './TransactionsByCustomersExportInjectable';
+import { TransactionsByCustomersSheet } from './TransactionsByCustomersService';
+
+@Service()
+export class TransactionsByCustomerApplication {
+ @Inject()
+ private transactionsByCustomersTable: TransactionsByCustomersTableInjectable;
+
+ @Inject()
+ private transactionsByCustomersExport: TransactionsByCustomersExportInjectable;
+
+ @Inject()
+ private transactionsByCustomersSheet: TransactionsByCustomersSheet;
+
+ /**
+ * Retrieves the transactions by customers sheet in json format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public sheet(
+ tenantId: number,
+ query: ITransactionsByCustomersFilter
+ ): Promise {
+ return this.transactionsByCustomersSheet.transactionsByCustomers(
+ tenantId,
+ query
+ );
+ }
+
+ /**
+ * Retrieves the transactions by vendors sheet in table format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public table(tenantId: number, query: ITransactionsByCustomersFilter) {
+ return this.transactionsByCustomersTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the transactions by vendors sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public csv(
+ tenantId: number,
+ query: ITransactionsByCustomersFilter
+ ): Promise {
+ return this.transactionsByCustomersExport.csv(tenantId, query);
+ }
+
+ /**
+ * Retrieves the transactions by vendors sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public xlsx(
+ tenantId: number,
+ query: ITransactionsByCustomersFilter
+ ): Promise {
+ return this.transactionsByCustomersExport.xlsx(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersExportInjectable.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersExportInjectable.ts
new file mode 100644
index 000000000..d5dbffcff
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersExportInjectable.ts
@@ -0,0 +1,46 @@
+import { Inject, Service } from 'typedi';
+import { ITransactionsByCustomersFilter } from '@/interfaces';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { TransactionsByCustomersTableInjectable } from './TransactionsByCustomersTableInjectable';
+
+@Service()
+export class TransactionsByCustomersExportInjectable {
+ @Inject()
+ private transactionsByCustomerTable: TransactionsByCustomersTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public async xlsx(
+ tenantId: number,
+ query: ITransactionsByCustomersFilter
+ ): Promise {
+ const table = await this.transactionsByCustomerTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ITransactionsByCustomersFilter
+ ): Promise {
+ const table = await this.transactionsByCustomerTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
index fd66d8f1e..09579e2b2 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
@@ -1,16 +1,16 @@
+import { Inject } from 'typedi';
import { isEmpty, map } from 'lodash';
import { IAccount, IAccountTransaction } from '@/interfaces';
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
import HasTenancyService from '@/services/Tenancy/TenancyService';
-import { Inject } from 'typedi';
export default class TransactionsByCustomersRepository {
@Inject()
- tenancy: HasTenancyService;
+ private tenancy: HasTenancyService;
/**
* Retrieve the report customers.
- * @param {number} tenantId
+ * @param {number} tenantId
* @returns {Promise}
*/
public async getCustomers(tenantId: number, customersIds?: number[]) {
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
index a6f56d9fe..3fbf8cf06 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
@@ -13,23 +13,20 @@ import Ledger from '@/services/Accounting/Ledger';
import TransactionsByCustomersRepository from './TransactionsByCustomersRepository';
import { Tenant } from '@/system/models';
-export default class TransactionsByCustomersService
+export class TransactionsByCustomersSheet
implements ITransactionsByCustomersService
{
@Inject()
- tenancy: TenancyService;
-
- @Inject('logger')
- logger: any;
+ private tenancy: TenancyService;
@Inject()
- reportRepository: TransactionsByCustomersRepository;
+ private reportRepository: TransactionsByCustomersRepository;
/**
* Defaults balance sheet filter query.
* @return {ICustomerBalanceSummaryQuery}
*/
- get defaultQuery(): ITransactionsByCustomersFilter {
+ private get defaultQuery(): ITransactionsByCustomersFilter {
return {
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
@@ -165,7 +162,6 @@ export default class TransactionsByCustomersService
return {
data: reportInstance.reportData(),
- columns: reportInstance.reportColumns(),
query: filter,
};
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableRows.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTable.ts
similarity index 81%
rename from packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableRows.ts
rename to packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTable.ts
index 5c4e1ceb3..7016cf853 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableRows.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTable.ts
@@ -1,6 +1,6 @@
import * as R from 'ramda';
-import { tableRowMapper, tableMapper } from 'utils';
-import { ITransactionsByCustomersCustomer, ITableRow } from '@/interfaces';
+import { tableRowMapper } from 'utils';
+import { ITransactionsByCustomersCustomer, ITableRow, ITableColumn } from '@/interfaces';
import TransactionsByContactsTableRows from '../TransactionsByContact/TransactionsByContactTableRows';
enum ROW_TYPE {
@@ -10,17 +10,14 @@ enum ROW_TYPE {
CUSTOMER = 'CUSTOMER',
}
-export default class TransactionsByCustomersTableRows extends TransactionsByContactsTableRows {
+export class TransactionsByCustomersTable extends TransactionsByContactsTableRows {
private customersTransactions: ITransactionsByCustomersCustomer[];
/**
* Constructor method.
* @param {ITransactionsByCustomersCustomer[]} customersTransactions - Customers transactions.
*/
- constructor(
- customersTransactions: ITransactionsByCustomersCustomer[],
- i18n
- ) {
+ constructor(customersTransactions: ITransactionsByCustomersCustomer[], i18n) {
super();
this.customersTransactions = customersTransactions;
this.i18n = i18n;
@@ -75,4 +72,12 @@ export default class TransactionsByCustomersTableRows extends TransactionsByCont
this.customersTransactions
);
};
+
+ /**
+ * Retrieve the table columns of transactions by customers report.
+ * @returns {ITableColumn[]}
+ */
+ public tableColumns = (): ITableColumn[] => {
+ return [];
+ }
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableInjectable.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableInjectable.ts
new file mode 100644
index 000000000..fb1c61311
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersTableInjectable.ts
@@ -0,0 +1,44 @@
+import { Inject, Service } from 'typedi';
+import { ITransactionsByCustomersFilter, ITransactionsByCustomersTable } from '@/interfaces';
+import { TransactionsByCustomersSheet } from './TransactionsByCustomersService';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { TransactionsByCustomersTable } from './TransactionsByCustomersTable';
+
+@Service()
+export class TransactionsByCustomersTableInjectable {
+ @Inject()
+ private transactionsByCustomerService: TransactionsByCustomersSheet;
+
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ /**
+ * Retrieves the transactions by customers sheet in table format.
+ * @param {number} tenantId
+ * @param {ITransactionsByCustomersFilter} filter
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ filter: ITransactionsByCustomersFilter
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const customersTransactions =
+ await this.transactionsByCustomerService.transactionsByCustomers(
+ tenantId,
+ filter
+ );
+ const table = new TransactionsByCustomersTable(
+ customersTransactions.data,
+ i18n
+ );
+ return {
+ table: {
+ rows: table.tableRows(),
+ columns: table.tableColumns(),
+ },
+ query: customersTransactions.query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendor.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendor.ts
index 5bc9276c0..500e548f7 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendor.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendor.ts
@@ -137,11 +137,4 @@ export default class TransactionsByVendors extends TransactionsByContact {
public reportData(): ITransactionsByVendorsData {
return this.vendorsMapper(this.contacts);
}
-
- /**
- * Retrieve the report columns.
- */
- public reportColumns() {
- return [];
- }
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorApplication.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorApplication.ts
new file mode 100644
index 000000000..d8d424a30
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorApplication.ts
@@ -0,0 +1,75 @@
+import { Inject, Service } from 'typedi';
+import {
+ ITransactionsByVendorTable,
+ ITransactionsByVendorsFilter,
+ ITransactionsByVendorsStatement,
+} from '@/interfaces';
+import { TransactionsByVendorExportInjectable } from './TransactionsByVendorExportInjectable';
+import { TransactionsByVendorTableInjectable } from './TransactionsByVendorTableInjectable';
+import { TransactionsByVendorsInjectable } from './TransactionsByVendorInjectable';
+
+@Service()
+export class TransactionsByVendorApplication {
+ @Inject()
+ private transactionsByVendorTable: TransactionsByVendorTableInjectable;
+
+ @Inject()
+ private transactionsByVendorExport: TransactionsByVendorExportInjectable;
+
+ @Inject()
+ private transactionsByVendorSheet: TransactionsByVendorsInjectable;
+
+ /**
+ * Retrieves the transactions by vendor in sheet format.
+ * @param {number} tenantId
+ * @param {ITransactionsByVendorsFilter} query
+ * @returns {Promise}
+ */
+ public sheet(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ return this.transactionsByVendorSheet.transactionsByVendors(
+ tenantId,
+ query
+ );
+ }
+
+ /**
+ * Retrieves the transactions by vendor in table format.
+ * @param {number} tenantId
+ * @param {ITransactionsByVendorsFilter} query
+ * @returns {Promise}
+ */
+ public table(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ return this.transactionsByVendorTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the transactions by vendor in CSV format.
+ * @param {number} tenantId
+ * @param {ITransactionsByVendorsFilter} query
+ * @returns {Promise}
+ */
+ public csv(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ return this.transactionsByVendorExport.csv(tenantId, query);
+ }
+
+ /**
+ * Retrieves the transactions by vendor in XLSX format.
+ * @param {number} tenantId
+ * @param {ITransactionsByVendorsFilter} query
+ */
+ public xlsx(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ return this.transactionsByVendorExport.xlsx(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorExportInjectable.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorExportInjectable.ts
new file mode 100644
index 000000000..1d547e752
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorExportInjectable.ts
@@ -0,0 +1,46 @@
+import { Inject, Service } from 'typedi';
+import { ITransactionsByVendorsFilter } from '@/interfaces';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { TransactionsByVendorTableInjectable } from './TransactionsByVendorTableInjectable';
+
+@Service()
+export class TransactionsByVendorExportInjectable {
+ @Inject()
+ private transactionsByVendorTable: TransactionsByVendorTableInjectable;
+
+ /**
+ * Retrieves the cashflow sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITransactionsByVendorsFilter} query
+ * @returns {Promise}
+ */
+ public async xlsx(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ const table = await this.transactionsByVendorTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the cashflow sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ICashFlowStatementQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ const table = await this.transactionsByVendorTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorInjectable.ts
similarity index 94%
rename from packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts
rename to packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorInjectable.ts
index c112a059a..a24041929 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorInjectable.ts
@@ -1,7 +1,6 @@
import { Inject } from 'typedi';
import moment from 'moment';
import * as R from 'ramda';
-import { map } from 'lodash';
import TenancyService from '@/services/Tenancy/TenancyService';
import {
ITransactionsByVendorsService,
@@ -14,17 +13,14 @@ import Ledger from '@/services/Accounting/Ledger';
import TransactionsByVendorRepository from './TransactionsByVendorRepository';
import { Tenant } from '@/system/models';
-export default class TransactionsByVendorsService
+export class TransactionsByVendorsInjectable
implements ITransactionsByVendorsService
{
@Inject()
- tenancy: TenancyService;
-
- @Inject('logger')
- logger: any;
+ private tenancy: TenancyService;
@Inject()
- reportRepository: TransactionsByVendorRepository;
+ private reportRepository: TransactionsByVendorRepository;
/**
* Defaults balance sheet filter query.
@@ -136,7 +132,7 @@ export default class TransactionsByVendorsService
const { accountRepository } = this.tenancy.repositories(tenantId);
const i18n = this.tenancy.i18n(tenantId);
-
+
const tenant = await Tenant.query()
.findById(tenantId)
.withGraphFetched('metadata');
@@ -171,7 +167,6 @@ export default class TransactionsByVendorsService
);
return {
data: reportInstance.reportData(),
- columns: reportInstance.reportColumns(),
query: filter,
};
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableRows.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTable.ts
similarity index 76%
rename from packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableRows.ts
rename to packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTable.ts
index e37eeb8fe..14ad3c1b4 100644
--- a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableRows.ts
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTable.ts
@@ -1,6 +1,10 @@
import * as R from 'ramda';
import { tableRowMapper } from 'utils';
-import { ITransactionsByVendorsVendor, ITableRow } from '@/interfaces';
+import {
+ ITransactionsByVendorsVendor,
+ ITableRow,
+ ITableColumn,
+} from '@/interfaces';
import TransactionsByContactsTableRows from '../TransactionsByContact/TransactionsByContactTableRows';
enum ROW_TYPE {
@@ -10,16 +14,15 @@ enum ROW_TYPE {
VENDOR = 'VENDOR',
}
-export default class TransactionsByVendorsTableRows extends TransactionsByContactsTableRows {
- vendorsTransactions: ITransactionsByVendorsVendor[];
+export class TransactionsByVendorsTable extends TransactionsByContactsTableRows {
+ private vendorsTransactions: ITransactionsByVendorsVendor[];
/**
* Constructor method.
+ * @param {ITransactionsByVendorsVendor[]} vendorsTransactions -
+ * @param {any} i18n
*/
- constructor(
- vendorsTransactions: ITransactionsByVendorsVendor[],
- i18n
- ) {
+ constructor(vendorsTransactions: ITransactionsByVendorsVendor[], i18n) {
super();
this.vendorsTransactions = vendorsTransactions;
@@ -73,4 +76,12 @@ export default class TransactionsByVendorsTableRows extends TransactionsByContac
public tableRows = (): ITableRow[] => {
return R.map(this.vendorRowsMapper)(this.vendorsTransactions);
};
+
+ /**
+ * Retrieve the table columns of transactions by vendors report.
+ * @returns {ITableColumn[]}
+ */
+ public tableColumns = (): ITableColumn[] => {
+ return [];
+ };
}
diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableInjectable.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableInjectable.ts
new file mode 100644
index 000000000..5b42b88e7
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorTableInjectable.ts
@@ -0,0 +1,44 @@
+import { Inject, Service } from 'typedi';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { TransactionsByVendorsTable } from './TransactionsByVendorTable';
+import {
+ ITransactionsByVendorTable,
+ ITransactionsByVendorsFilter,
+} from '@/interfaces';
+import { TransactionsByVendorsInjectable } from './TransactionsByVendorInjectable';
+
+@Service()
+export class TransactionsByVendorTableInjectable {
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ @Inject()
+ private transactionsByVendor: TransactionsByVendorsInjectable;
+
+ /**
+ * Retrieves the transactions by vendor in table format.
+ * @param {number} tenantId
+ * @param {ITransactionsByReferenceQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: ITransactionsByVendorsFilter
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const sheet = await this.transactionsByVendor.transactionsByVendors(
+ tenantId,
+ query
+ );
+ const table = new TransactionsByVendorsTable(sheet.data, i18n);
+
+ return {
+ table: {
+ rows: table.tableRows(),
+ columns: table.tableColumns(),
+ },
+ query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceExportInjectable.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceExportInjectable.ts
new file mode 100644
index 000000000..a515f1beb
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceExportInjectable.ts
@@ -0,0 +1,43 @@
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+import { ITrialBalanceSheetQuery } from '@/interfaces';
+import { Inject, Service } from 'typedi';
+import { TrialBalanceSheetTableInjectable } from './TrialBalanceSheetTableInjectable';
+
+@Service()
+export class TrialBalanceExportInjectable {
+ @Inject()
+ private trialBalanceSheetTable: TrialBalanceSheetTableInjectable;
+
+ /**
+ * Retrieves the trial balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: ITrialBalanceSheetQuery) {
+ const table = await this.trialBalanceSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the trial balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: ITrialBalanceSheetQuery
+ ): Promise {
+ const table = await this.trialBalanceSheetTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts
new file mode 100644
index 000000000..a771c8f15
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication.ts
@@ -0,0 +1,60 @@
+import { Inject, Service } from 'typedi';
+import { TrialBalanceSheetTableInjectable } from './TrialBalanceSheetTableInjectable';
+import { TrialBalanceExportInjectable } from './TrialBalanceExportInjectable';
+import { ITrialBalanceSheetQuery, ITrialBalanceStatement } from '@/interfaces';
+import TrialBalanceSheetService from './TrialBalanceSheetInjectable';
+
+@Service()
+export class TrialBalanceSheetApplication {
+ @Inject()
+ private sheetService: TrialBalanceSheetService;
+
+ @Inject()
+ private tablable: TrialBalanceSheetTableInjectable;
+
+ @Inject()
+ private exportable: TrialBalanceExportInjectable;
+
+ /**
+ * Retrieves the trial balance sheet.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public sheet(
+ tenantId: number,
+ query: ITrialBalanceSheetQuery
+ ): Promise {
+ return this.sheetService.trialBalanceSheet(tenantId, query);
+ }
+
+ /**
+ * Retrieves the trial balance sheet in table format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public table(tenantId: number, query: ITrialBalanceSheetQuery) {
+ return this.tablable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieve the trial balance sheet in CSV format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public csv(tenantId: number, query: ITrialBalanceSheetQuery) {
+ return this.exportable.csv(tenantId, query);
+ }
+
+ /**
+ * Retrieve the trial balance sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: ITrialBalanceSheetQuery) {
+ return this.exportable.xlsx(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetInjectable.ts
similarity index 78%
rename from packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts
rename to packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetInjectable.ts
index 150f160b0..bc880ec99 100644
--- a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts
+++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetInjectable.ts
@@ -1,7 +1,6 @@
import { Service, Inject } from 'typedi';
import moment from 'moment';
import TenancyService from '@/services/Tenancy/TenancyService';
-import Journal from '@/services/Accounting/JournalPoster';
import {
ITrialBalanceSheetMeta,
ITrialBalanceSheetQuery,
@@ -13,7 +12,6 @@ import InventoryService from '@/services/Inventory/Inventory';
import { parseBoolean } from 'utils';
import { Tenant } from '@/system/models';
import { TrialBalanceSheetRepository } from './TrialBalanceSheetRepository';
-import { TrialBalanceSheetTable } from './TrialBalanceSheetTable';
@Service()
export default class TrialBalanceSheetService extends FinancialSheet {
@@ -30,7 +28,7 @@ export default class TrialBalanceSheetService extends FinancialSheet {
* Defaults trial balance sheet filter query.
* @return {IBalanceSheetQuery}
*/
- get defaultQuery(): ITrialBalanceSheetQuery {
+ private get defaultQuery(): ITrialBalanceSheetQuery {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
@@ -54,7 +52,7 @@ export default class TrialBalanceSheetService extends FinancialSheet {
* @param {number} tenantId - Tenant id.
* @returns {ITrialBalanceSheetMeta}
*/
- reportMetadata(tenantId: number): ITrialBalanceSheetMeta {
+ private reportMetadata(tenantId: number): ITrialBalanceSheetMeta {
const settings = this.tenancy.settings(tenantId);
const isCostComputeRunning =
@@ -89,7 +87,6 @@ export default class TrialBalanceSheetService extends FinancialSheet {
...this.defaultQuery,
...query,
};
-
const tenant = await Tenant.query()
.findById(tenantId)
.withGraphFetched('metadata');
@@ -120,27 +117,4 @@ export default class TrialBalanceSheetService extends FinancialSheet {
meta: this.reportMetadata(tenantId),
};
}
-
- /**
- * Retrieves the trial balance sheet table.
- * @param {number} tenantId
- * @param {ITrialBalanceSheetQuery} query
- * @returns {Promise}
- */
- 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,
- };
- }
}
diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetTableInjectable.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetTableInjectable.ts
new file mode 100644
index 000000000..e62a1dde2
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetTableInjectable.ts
@@ -0,0 +1,33 @@
+import { Inject, Service } from 'typedi';
+import { ITrialBalanceSheetQuery, ITrialBalanceSheetTable } from '@/interfaces';
+import { TrialBalanceSheetTable } from './TrialBalanceSheetTable';
+import TrialBalanceSheetService from './TrialBalanceSheetInjectable';
+
+@Service()
+export class TrialBalanceSheetTableInjectable {
+ @Inject()
+ private sheet: TrialBalanceSheetService;
+
+ /**
+ * Retrieves the trial balance sheet table.
+ * @param {number} tenantId
+ * @param {ITrialBalanceSheetQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: ITrialBalanceSheetQuery
+ ): Promise {
+ const trialBalance = await this.sheet.trialBalanceSheet(tenantId, query);
+ const table = new TrialBalanceSheetTable(trialBalance.data, query, {});
+
+ return {
+ table: {
+ columns: table.tableColumns(),
+ rows: table.tableRows(),
+ },
+ meta: trialBalance.meta,
+ query: trialBalance.query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummary.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummary.ts
index 1d84d593f..2e5e09aa4 100644
--- a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummary.ts
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummary.ts
@@ -101,8 +101,4 @@ export class VendorBalanceSummaryReport extends ContactBalanceSummaryReport {
return { vendors, total };
}
-
- reportColumns() {
- return [];
- }
}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication.ts
new file mode 100644
index 000000000..5fe4bc74d
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication.ts
@@ -0,0 +1,62 @@
+import { Inject, Service } from 'typedi';
+import { IVendorBalanceSummaryQuery } from '@/interfaces';
+import { VendorBalanceSummaryTableInjectable } from './VendorBalanceSummaryTableInjectable';
+import { VendorBalanceSummaryExportInjectable } from './VendorBalanceSummaryExportInjectable';
+import { VendorBalanceSummaryService } from './VendorBalanceSummaryService';
+
+@Service()
+export class VendorBalanceSummaryApplication {
+ @Inject()
+ private vendorBalanceSummaryTable: VendorBalanceSummaryTableInjectable;
+
+ @Inject()
+ private vendorBalanceSummarySheet: VendorBalanceSummaryService;
+
+ @Inject()
+ private vendorBalanceSummaryExport: VendorBalanceSummaryExportInjectable;
+
+ /**
+ * Retrieves the vendor balance summary sheet in sheet format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ */
+ public sheet(tenantId: number, query: IVendorBalanceSummaryQuery) {
+ return this.vendorBalanceSummarySheet.vendorBalanceSummary(tenantId, query);
+ }
+
+ /**
+ * Retrieves the vendor balance summary sheet in table format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {}
+ */
+ public table(tenantId: number, query: IVendorBalanceSummaryQuery) {
+ return this.vendorBalanceSummaryTable.table(tenantId, query);
+ }
+
+ /**
+ * Retrieves the vendor balance summary sheet in xlsx format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public xlsx(
+ tenantId: number,
+ query: IVendorBalanceSummaryQuery
+ ): Promise {
+ return this.vendorBalanceSummaryExport.xlsx(tenantId, query);
+ }
+
+ /**
+ * Retrieves the vendor balance summary sheet in csv format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public csv(
+ tenantId: number,
+ query: IVendorBalanceSummaryQuery
+ ): Promise {
+ return this.vendorBalanceSummaryExport.csv(tenantId, query);
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryExportInjectable.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryExportInjectable.ts
new file mode 100644
index 000000000..ba278f88d
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryExportInjectable.ts
@@ -0,0 +1,43 @@
+import { Inject, Service } from 'typedi';
+import { IVendorBalanceSummaryQuery } from '@/interfaces';
+import { VendorBalanceSummaryTableInjectable } from './VendorBalanceSummaryTableInjectable';
+import { TableSheet } from '@/lib/Xlsx/TableSheet';
+
+@Service()
+export class VendorBalanceSummaryExportInjectable {
+ @Inject()
+ private customerBalanceSummaryTable: VendorBalanceSummaryTableInjectable;
+
+ /**
+ * Retrieves the vendor balance summary sheet in XLSX format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async xlsx(tenantId: number, query: IVendorBalanceSummaryQuery) {
+ const table = await this.customerBalanceSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToXLSX();
+
+ return tableSheet.convertToBuffer(tableCsv, 'xlsx');
+ }
+
+ /**
+ * Retrieves the vendor balance summary sheet in CSV format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async csv(
+ tenantId: number,
+ query: IVendorBalanceSummaryQuery
+ ): Promise {
+ const table = await this.customerBalanceSummaryTable.table(tenantId, query);
+
+ const tableSheet = new TableSheet(table.table);
+ const tableCsv = tableSheet.convertToCSV();
+
+ return tableCsv;
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryRepository.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryRepository.ts
index a8d67089d..721291b7d 100644
--- a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryRepository.ts
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryRepository.ts
@@ -7,7 +7,7 @@ import { ACCOUNT_TYPE } from '@/data/AccountTypes';
@Service()
export default class VendorBalanceSummaryRepository {
@Inject()
- tenancy: HasTenancyService;
+ private tenancy: HasTenancyService;
/**
* Retrieve the report vendors.
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService.ts
index 82dc0475d..b1a361b87 100644
--- a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService.ts
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService.ts
@@ -1,10 +1,8 @@
import { Inject } from 'typedi';
import moment from 'moment';
-import { map } from 'lodash';
import * as R from 'ramda';
import TenancyService from '@/services/Tenancy/TenancyService';
import {
- IVendor,
IVendorBalanceSummaryService,
IVendorBalanceSummaryQuery,
IVendorBalanceSummaryStatement,
@@ -15,15 +13,12 @@ import Ledger from '@/services/Accounting/Ledger';
import VendorBalanceSummaryRepository from './VendorBalanceSummaryRepository';
import { Tenant } from '@/system/models';
-export default class VendorBalanceSummaryService
+export class VendorBalanceSummaryService
implements IVendorBalanceSummaryService
{
@Inject()
tenancy: TenancyService;
- @Inject('logger')
- logger: any;
-
@Inject()
reportRepo: VendorBalanceSummaryRepository;
@@ -31,7 +26,7 @@ export default class VendorBalanceSummaryService
* Defaults balance sheet filter query.
* @return {IVendorBalanceSummaryQuery}
*/
- get defaultQuery(): IVendorBalanceSummaryQuery {
+ private get defaultQuery(): IVendorBalanceSummaryQuery {
return {
asDate: moment().format('YYYY-MM-DD'),
numberFormat: {
@@ -72,7 +67,7 @@ export default class VendorBalanceSummaryService
* @param {IVendorBalanceSummaryQuery} query -
* @return {Promise}
*/
- async vendorBalanceSummary(
+ public async vendorBalanceSummary(
tenantId: number,
query: IVendorBalanceSummaryQuery
): Promise {
@@ -81,13 +76,7 @@ export default class VendorBalanceSummaryService
.withGraphFetched('metadata');
const filter = { ...this.defaultQuery, ...query };
- this.logger.info(
- '[customer_balance_summary] trying to calculate the report.',
- {
- filter,
- tenantId,
- }
- );
+
// Retrieve the vendors transactions.
const vendorsEntries = await this.getReportVendorsEntries(
tenantId,
@@ -111,7 +100,6 @@ export default class VendorBalanceSummaryService
return {
data: reportInstance.reportData(),
- columns: reportInstance.reportColumns(),
query: filter,
};
}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableInjectable.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableInjectable.ts
new file mode 100644
index 000000000..aec97e6f1
--- /dev/null
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableInjectable.ts
@@ -0,0 +1,44 @@
+import {
+ IVendorBalanceSummaryQuery,
+ IVendorBalanceSummaryTable,
+} from '@/interfaces';
+import HasTenancyService from '@/services/Tenancy/TenancyService';
+import { Inject, Service } from 'typedi';
+import { VendorBalanceSummaryTable } from './VendorBalanceSummaryTableRows';
+import { VendorBalanceSummaryService } from './VendorBalanceSummaryService';
+
+@Service()
+export class VendorBalanceSummaryTableInjectable {
+ @Inject()
+ private tenancy: HasTenancyService;
+
+ @Inject()
+ private vendorBalanceSummarySheet: VendorBalanceSummaryService;
+
+ /**
+ * Retrieves the vendor balance summary sheet in table format.
+ * @param {number} tenantId
+ * @param {IVendorBalanceSummaryQuery} query
+ * @returns {Promise}
+ */
+ public async table(
+ tenantId: number,
+ query: IVendorBalanceSummaryQuery
+ ): Promise {
+ const i18n = this.tenancy.i18n(tenantId);
+
+ const { data } = await this.vendorBalanceSummarySheet.vendorBalanceSummary(
+ tenantId,
+ query
+ );
+ const table = new VendorBalanceSummaryTable(data, query, i18n);
+
+ return {
+ table: {
+ columns: table.tableColumns(),
+ rows: table.tableRows(),
+ },
+ query,
+ };
+ }
+}
diff --git a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows.ts b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows.ts
index d65ced56e..2095ea087 100644
--- a/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows.ts
+++ b/packages/server/src/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows.ts
@@ -15,7 +15,7 @@ enum TABLE_ROWS_TYPES {
TOTAL = 'TOTAL',
}
-export default class VendorBalanceSummaryTable {
+export class VendorBalanceSummaryTable {
i18n: any;
report: IVendorBalanceSummaryData;
query: IVendorBalanceSummaryQuery;
diff --git a/packages/server/src/utils/deepdash.ts b/packages/server/src/utils/deepdash.ts
index 6a97209e0..0ce65216a 100644
--- a/packages/server/src/utils/deepdash.ts
+++ b/packages/server/src/utils/deepdash.ts
@@ -78,6 +78,27 @@ const filterNodesDeep = (predicate, nodes) => {
);
};
+const flatNestedTree = (obj, mapper, options) => {
+ return reduceDeep(
+ obj,
+ (accumulator, value, key, parentValue, context) => {
+ const computedValue = _.omit(value, ['children']);
+ const mappedValue = mapper
+ ? mapper(computedValue, key, context)
+ : computedValue;
+
+ accumulator.push(mappedValue);
+ return accumulator;
+ },
+ [],
+ {
+ childrenPath: 'children',
+ pathFormat: 'array',
+ ...options,
+ }
+ );
+};
+
export {
iteratee,
condense,
@@ -103,4 +124,5 @@ export {
someDeep,
mapValuesDeepReverse,
filterNodesDeep,
+ flatNestedTree,
};
diff --git a/packages/server/src/utils/table.ts b/packages/server/src/utils/table.ts
index a6d39be94..74f5c3170 100644
--- a/packages/server/src/utils/table.ts
+++ b/packages/server/src/utils/table.ts
@@ -22,7 +22,9 @@ export function tableRowMapper(
): ITableRow {
const cells = columns.map((column) => ({
key: column.key,
- value: column.value ? column.value : getAccessor(object, column.accessor),
+ value: column.value
+ ? column.value
+ : getAccessor(object, column.accessor) || '',
}));
return {
diff --git a/packages/webapp/craco.config.js b/packages/webapp/craco.config.js
index c86d33ebc..4d444d065 100644
--- a/packages/webapp/craco.config.js
+++ b/packages/webapp/craco.config.js
@@ -11,4 +11,7 @@ module.exports = {
},
},
},
+ devServer: {
+ allowedHosts: process.env.GITPOD_HOST ? 'all' : 'auto'
+ },
};
diff --git a/packages/webapp/package.json b/packages/webapp/package.json
index 1d6481add..d4e1c65d1 100644
--- a/packages/webapp/package.json
+++ b/packages/webapp/package.json
@@ -37,7 +37,7 @@
"@typescript-eslint/parser": "^2.10.0",
"@welldone-software/why-did-you-render": "^6.0.0-rc.1",
"accounting": "^0.4.1",
- "axios": "^0.21.2",
+ "axios": "^1.6.0",
"basscss": "^8.0.2",
"camelcase": "^5.3.1",
"classnames": "^2.3.2",
diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.tsx
index de806ab2f..f0473ab58 100644
--- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.tsx
@@ -15,6 +15,7 @@ import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
+import { APAgingSummaryExportMenu } from './components';
import withAPAgingSummary from './withAPAgingSummary';
import withAPAgingSummaryActions from './withAPAgingSummaryActions';
@@ -106,11 +107,18 @@ function APAgingSummaryActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.tsx
index 367140711..28611a13d 100644
--- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.tsx
@@ -27,6 +27,7 @@ function APAgingSummaryProvider({ filter, ...props }) {
isAPAgingLoading,
isAPAgingFetching,
refetch,
+ query,
};
return (
diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx
index f6af9931a..b313bab50 100644
--- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx
@@ -1,10 +1,23 @@
// @ts-nocheck
-import React, { useMemo } from 'react';
+import { useRef } from 'react';
+import classNames from 'classnames';
-import { If } from '@/components';
+import { AppToaster, If, Stack } from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
+import {
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import {
+ useAPAgingSheetCsvExport,
+ useAPAgingSheetXlsxExport,
+} from '@/hooks/query';
/**
* Retrieve AP aging summary columns.
@@ -29,3 +42,87 @@ export function APAgingSummarySheetLoadingBar() {
);
}
+
+/**
+ * A/P aging summary export menu.
+ * @returns {JSX.Element}
+ */
+export function APAgingSummaryExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useAPAgingSummaryContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useAPAgingSheetXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useAPAgingSheetCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.tsx
index bccef0742..4b34f94aa 100644
--- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.tsx
@@ -19,6 +19,7 @@ import withARAgingSummaryActions from './withARAgingSummaryActions';
import withARAgingSummary from './withARAgingSummary';
import { compose, safeInvoke } from '@/utils';
+import { ARAgingSummaryExportMenu } from './components';
/**
* A/R Aging summary sheet - Actions bar.
@@ -107,11 +108,18 @@ function ARAgingSummaryActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx
index e2e89a8db..19166c101 100644
--- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx
@@ -1,10 +1,23 @@
// @ts-nocheck
-import React from 'react';
+import React, { useRef } from 'react';
+import classNames from 'classnames';
+import {
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
-import { If, FormattedMessage as T } from '@/components';
+import { AppToaster, If, Stack, FormattedMessage as T } from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
+import {
+ useARAgingSheetCsvExport,
+ useARAgingSheetXlsxExport,
+} from '@/hooks/query';
/**
* Retrieve AR aging summary columns.
@@ -29,3 +42,88 @@ export function ARAgingSummarySheetLoadingBar() {
);
}
+
+/**
+ * A/R aging summary export menu.
+ * @returns {JSX.Element}
+ */
+export function ARAgingSummaryExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useARAgingSummaryContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useARAgingSheetXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useARAgingSheetCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.tsx
index dd50cd541..0421ea2ae 100644
--- a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.tsx
@@ -1,5 +1,4 @@
// @ts-nocheck
-import React from 'react';
import {
NavbarGroup,
Button,
@@ -13,11 +12,12 @@ import classNames from 'classnames';
import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
+import { BalanceSheetExportMenu } from './components';
-import { compose, saveInvoke } from '@/utils';
import { useBalanceSheetContext } from './BalanceSheetProvider';
import withBalanceSheet from './withBalanceSheet';
import withBalanceSheetActions from './withBalanceSheetActions';
+import { compose, saveInvoke } from '@/utils';
/**
* Balance sheet - actions bar.
@@ -114,11 +114,18 @@ function BalanceSheetActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/components.tsx b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/components.tsx
index 08f946f75..7a27c33c4 100644
--- a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/components.tsx
@@ -1,13 +1,32 @@
// @ts-nocheck
-import React from 'react';
-import { Button } from '@blueprintjs/core';
+import React, { useRef } from 'react';
+import {
+ Button,
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import classNames from 'classnames';
-import { FormattedMessage as T, Icon, If } from '@/components';
+import {
+ FormattedMessage as T,
+ Icon,
+ If,
+ Stack,
+ AppToaster,
+} from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useBalanceSheetContext } from './BalanceSheetProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import { dynamicColumns } from './dynamicColumns';
+import {
+ useBalanceSheetCsvExport,
+ useBalanceSheetXlsxExport,
+} from '@/hooks/query';
/**
* Balance sheet alerts.
@@ -66,3 +85,88 @@ export const useBalanceSheetColumns = () => {
[table],
);
};
+
+/**
+ * Retrieves the balance sheet export menu.
+ * @returns {JSX.Element}
+ */
+export const BalanceSheetExportMenu = () => {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useBalanceSheetContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useBalanceSheetXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useBalanceSheetCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport().then(() => {});
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport().then(() => {});
+ };
+
+ return (
+
+
+
+
+ );
+};
diff --git a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/CashFlowStatementActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/CashFlowStatementActionsBar.tsx
index 559f86053..957b7e733 100644
--- a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/CashFlowStatementActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/CashFlowStatementActionsBar.tsx
@@ -19,6 +19,7 @@ import withCashFlowStatement from './withCashFlowStatement';
import withCashFlowStatementActions from './withCashFlowStatementActions';
import { compose, saveInvoke } from '@/utils';
+import { CashflowSheetExportMenu } from './components';
/**
* Cash flow statement actions bar.
@@ -115,11 +116,18 @@ function CashFlowStatementActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/components.tsx b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/components.tsx
index 1d1af31f5..ee86944f6 100644
--- a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/components.tsx
@@ -1,8 +1,27 @@
// @ts-nocheck
-import React from 'react';
-import { Button } from '@blueprintjs/core';
+import React, { useRef } from 'react';
+import {
+ Button,
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import classNames from 'classnames';
-import { Icon, If, FormattedMessage as T } from '@/components';
+import {
+ AppToaster,
+ Icon,
+ If,
+ Stack,
+ FormattedMessage as T,
+} from '@/components';
+import {
+ useCashFlowStatementCsvExport,
+ useCashFlowStatementXlsxExport,
+} from '@/hooks/query';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { dynamicColumns } from './dynamicColumns';
@@ -65,3 +84,88 @@ export function CashFlowStatementAlerts() {
);
}
+
+/**
+ * Cashflow sheet export menu.
+ * @returns {JSX.Element}
+ */
+export function CashflowSheetExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useCashFlowStatementContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useCashFlowStatementXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useCashFlowStatementCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.tsx
index 81d8a7848..f22fea1e6 100644
--- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.tsx
@@ -17,6 +17,7 @@ import withCustomersBalanceSummary from './withCustomersBalanceSummary';
import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions';
import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
import { compose, saveInvoke } from '@/utils';
+import { CustomerBalanceSummaryExportMenu } from './components';
/**
* customer balance summary action bar.
@@ -35,7 +36,7 @@ function CustomersBalanceSummaryActionsBar({
const { refetch, isCustomersBalanceLoading } =
useCustomersBalanceSummaryContext();
- // handle filter toggle click.
+ // Handle filter toggle click.
const handleFilterToggleClick = () => {
toggleCustomerBalanceFilterDrawer();
};
@@ -112,11 +113,18 @@ function CustomersBalanceSummaryActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.tsx
index 63f26ca2e..c9d40b22b 100644
--- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.tsx
@@ -31,6 +31,7 @@ function CustomersBalanceSummaryProvider({ filter, ...props }) {
isCustomersBalanceLoading,
refetch,
+ query
};
return (
diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx
index c03ca5cde..69fb340c7 100644
--- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx
@@ -32,7 +32,7 @@ export default function CustomersBalanceSummaryTable({
>
);
}
+
+/**
+ * Customer balance summary export menu.
+ */
+export function CustomerBalanceSummaryExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useCustomersBalanceSummaryContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useCustomerBalanceSummaryXlsxExport(
+ query,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useCustomerBalanceSummaryCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsActionsBar.tsx
index 3b80a051a..044bf9e9d 100644
--- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsActionsBar.tsx
@@ -9,9 +9,10 @@ import {
PopoverInteractionKind,
Position,
} from '@blueprintjs/core';
-import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import classNames from 'classnames';
+import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
+import { CustomersTransactionsExportMenu } from './components';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
import { useCustomersTransactionsContext } from './CustomersTransactionsProvider';
@@ -114,11 +115,18 @@ function CustomersTransactionsActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/components.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/components.tsx
index b1137e130..5bf73e1c1 100644
--- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/components.tsx
@@ -1,12 +1,24 @@
// @ts-nocheck
-import React from 'react';
+import React, { useRef } from 'react';
import intl from 'react-intl-universal';
-import { If } from '@/components';
+import { AppToaster, If, Stack } from '@/components';
import { Align } from '@/constants';
import { getColumnWidth } from '@/utils';
import { useCustomersTransactionsContext } from './CustomersTransactionsProvider';
import FinancialLoadingBar from '../FinancialLoadingBar';
-
+import {
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import {
+ useCustomersTransactionsCsvExport,
+ useCustomersTransactionsXlsxExport,
+} from '@/hooks/query';
+import classNames from 'classnames';
/**
* Retrieve customers transactions columns.
@@ -92,3 +104,91 @@ export function CustomersTransactionsLoadingBar() {
);
}
+
+/**
+ * Customers transactions export menu.
+ * @returns {JSX.Element}
+ */
+export function CustomersTransactionsExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useCustomersTransactionsContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useCustomersTransactionsXlsxExport(
+ query,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useCustomersTransactionsCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsActionsBar.tsx
index 94dea9531..da4d6c4df 100644
--- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsActionsBar.tsx
@@ -13,6 +13,7 @@ import { DashboardActionsBar, Icon, FormattedMessage as T } from '@/components';
import classNames from 'classnames';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
+import { InventoryItemDetailsExportMenu } from './components';
import { useInventoryItemDetailsContext } from './InventoryItemDetailsProvider';
import withInventoryItemDetails from './withInventoryItemDetails';
@@ -112,11 +113,18 @@ function InventoryItemDetailsActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/components.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/components.tsx
index b56f91a23..f5842d032 100644
--- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/components.tsx
@@ -1,12 +1,32 @@
// @ts-nocheck
-import React from 'react';
-import { Button } from '@blueprintjs/core';
-import { Icon, If, FormattedMessage as T } from '@/components';
+import React, { useRef } from 'react';
+import {
+ Button,
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import classNames from 'classnames';
+import {
+ AppToaster,
+ Icon,
+ If,
+ Stack,
+ FormattedMessage as T,
+} from '@/components';
import { dynamicColumns } from './utils';
import FinancialLoadingBar from '../FinancialLoadingBar';
+import {
+ useInventoryItemDetailsCsvExport,
+ useInventoryItemDetailsXlsxExport,
+} from '@/hooks/query';
import { useInventoryItemDetailsContext } from './InventoryItemDetailsProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
+import { useInventoryValuationHttpQuery } from './utils2';
/**
* Retrieve inventory item details columns.
@@ -70,3 +90,94 @@ export function InventoryItemDetailsAlerts() {
);
}
+
+/**
+ * Inventory item details export menu.
+ * @returns {JSX.Element}
+ */
+export function InventoryItemDetailsExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const httpQuery = useInventoryValuationHttpQuery();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useInventoryItemDetailsXlsxExport(
+ httpQuery,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useInventoryItemDetailsCsvExport(
+ httpQuery,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx
index 4293cf610..d786403be 100644
--- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx
@@ -7,6 +7,7 @@ import intl from 'react-intl-universal';
import { useAppQueryString } from '@/hooks';
import { transformToForm } from '@/utils';
+import { transformFilterFormToQuery } from '../common';
/**
* Retrieves inventory item details default query.
@@ -73,3 +74,13 @@ export const useInventoryValuationQuery = () => {
setLocationQuery,
};
};
+
+/**
+ * Retrieves the inventory valuation http query.
+ * @returns {Object}
+ */
+export const useInventoryValuationHttpQuery = () => {
+ const { query } = useInventoryValuationQuery();
+
+ return React.useMemo(() => transformFilterFormToQuery(query), [query]);
+};
diff --git a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossActionsBar.tsx
index 34545766a..3988ff7f2 100644
--- a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossActionsBar.tsx
@@ -19,6 +19,7 @@ import withProfitLoss from './withProfitLoss';
import { compose, saveInvoke } from '@/utils';
import { useProfitLossSheetContext } from './ProfitLossProvider';
+import { ProfitLossSheetExportMenu } from './components';
/**
* Profit/Loss sheet actions bar.
@@ -110,11 +111,18 @@ function ProfitLossActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.tsx b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.tsx
index b422013b6..0ea7bbe93 100644
--- a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.tsx
@@ -1,5 +1,5 @@
// @ts-nocheck
-import React, { createContext, useContext } from 'react';
+import React, { createContext, useContext, useMemo } from 'react';
import FinancialReportPage from '../FinancialReportPage';
import { useProfitLossSheet } from '@/hooks/query';
import { transformFilterFormToQuery } from '../common';
@@ -11,15 +11,18 @@ const ProfitLossSheetContext = createContext();
* @returns {React.JSX}
*/
function ProfitLossSheetProvider({ query, ...props }) {
+
+ const innerQuery = useMemo(() => {
+ return transformFilterFormToQuery(query);
+ }, [query]);
+
const {
data: profitLossSheet,
isFetching,
isLoading,
refetch,
} = useProfitLossSheet(
- {
- ...transformFilterFormToQuery(query),
- },
+ innerQuery,
{ keepPreviousData: true },
);
@@ -28,6 +31,7 @@ function ProfitLossSheetProvider({ query, ...props }) {
isLoading,
isFetching,
sheetRefetch: refetch,
+ query: innerQuery
};
return (
diff --git a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/components.tsx b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/components.tsx
index e64255953..97a4fa860 100644
--- a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/components.tsx
@@ -1,11 +1,29 @@
// @ts-nocheck
-import React from 'react';
-import { Button } from '@blueprintjs/core';
-import { Icon, If, FormattedMessage as T } from '@/components';
-
+import React, { useRef } from 'react';
+import {
+ Button,
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import {
+ AppToaster,
+ Icon,
+ If,
+ Stack,
+ FormattedMessage as T,
+} from '@/components';
import { useProfitLossSheetContext } from './ProfitLossProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import FinancialLoadingBar from '../FinancialLoadingBar';
+import {
+ useProfitLossSheetCsvExport,
+ useProfitLossSheetXlsxExport,
+} from '@/hooks/query';
+import classNames from 'classnames';
/**
* Profit/loss sheet loading bar.
@@ -50,3 +68,87 @@ export function ProfitLossSheetAlerts() {
);
}
+
+/**
+ * Profit/loss sheet export menu.
+ */
+export const ProfitLossSheetExportMenu = () => {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useProfitLossSheetContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useProfitLossSheetXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useProfitLossSheetCsvExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+};
diff --git a/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryActionsBar.tsx
index 9c551ff24..d4d0de97e 100644
--- a/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryActionsBar.tsx
@@ -18,6 +18,7 @@ import { compose, saveInvoke } from '@/utils';
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
import withSalesTaxLiabilitySummary from './withSalesTaxLiabilitySummary';
import withSalesTaxLiabilitySummaryActions from './withSalesTaxLiabilitySummaryActions';
+import { SalesTaxLiabilityExportMenu } from './components';
/**
* Sales tax liability summary - actions bar.
@@ -113,11 +114,18 @@ function SalesTaxLiabilitySummaryActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/components.tsx b/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/components.tsx
index 6e4221b60..10fed35b6 100644
--- a/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/SalesTaxLiabilitySummary/components.tsx
@@ -1,8 +1,22 @@
// @ts-nocheck
-import React from 'react';
-
+import { useRef } from 'react';
+import classNames from 'classnames';
+import {
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
import FinancialLoadingBar from '../FinancialLoadingBar';
+import { AppToaster, Stack } from '@/components';
+import {
+ useSalesTaxLiabilitySummaryCsvExport,
+ useSalesTaxLiabilitySummaryXlsxExport,
+} from '@/hooks/query';
+import { useSalesByItemsContext } from '../SalesByItems/SalesByItemProvider';
/**
* Sales tax liability summary loading bar.
@@ -15,3 +29,94 @@ export function SalesTaxLiabilitySummaryLoadingBar() {
}
return ;
}
+
+/**
+ *
+ * @returns {JSX.Element}
+ */
+export function SalesTaxLiabilityExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useSalesTaxLiabilitySummaryContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useSalesTaxLiabilitySummaryXlsxExport(
+ query,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useSalesTaxLiabilitySummaryCsvExport(
+ query,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceActionsBar.tsx
index b409a44cd..198a5761f 100644
--- a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceActionsBar.tsx
@@ -18,6 +18,7 @@ import withTrialBalance from './withTrialBalance';
import withTrialBalanceActions from './withTrialBalanceActions';
import { compose, saveInvoke } from '@/utils';
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
+import { TrialBalanceSheetExportMenu } from './components';
function TrialBalanceActionsBar({
// #withTrialBalance
@@ -109,11 +110,18 @@ function TrialBalanceActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/components.tsx b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/components.tsx
index c2d40f8a0..db9aa183b 100644
--- a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/components.tsx
@@ -1,9 +1,30 @@
// @ts-nocheck
-import { Button } from '@blueprintjs/core';
-import { If, Icon, FormattedMessage as T } from '@/components';
+import { useRef } from 'react';
+import {
+ Button,
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import classNames from 'classnames';
+import {
+ If,
+ Icon,
+ FormattedMessage as T,
+ Stack,
+ AppToaster,
+} from '@/components';
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import FinancialLoadingBar from '../FinancialLoadingBar';
+import {
+ useTrialBalanceSheetCsvExport,
+ useTrialBalanceSheetXlsxExport,
+} from '@/hooks/query';
+import { useTrialBalanceSheetHttpQuery } from './utils';
/**
* Trial balance sheet progress loading bar.
@@ -22,11 +43,8 @@ export function TrialBalanceSheetLoadingBar() {
* Trial balance sheet alerts.
*/
export function TrialBalanceSheetAlerts() {
- const {
- trialBalanceSheet,
- isLoading,
- refetchSheet,
- } = useTrialBalanceSheetContext();
+ const { trialBalanceSheet, isLoading, refetchSheet } =
+ useTrialBalanceSheetContext();
// Handle refetch the sheet.
const handleRecalcReport = () => {
@@ -52,3 +70,89 @@ export function TrialBalanceSheetAlerts() {
);
}
+
+/**
+ * Trial balance sheet export menu.
+ */
+export const TrialBalanceSheetExportMenu = () => {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const httpQuery = useTrialBalanceSheetHttpQuery();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useTrialBalanceSheetXlsxExport(
+ httpQuery,
+ {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ },
+ );
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useTrialBalanceSheetCsvExport(httpQuery, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+};
diff --git a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx
index 62be9afa8..f28dac8bf 100644
--- a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx
@@ -5,6 +5,7 @@ import { castArray } from 'lodash';
import { useAppQueryString } from '@/hooks';
import { transformToForm } from '@/utils';
+import { transformFilterFormToQuery } from '../common';
/**
* Retrieves the default trial balance query.
@@ -56,3 +57,13 @@ export const useTrialBalanceSheetQuery = () => {
setLocationQuery,
};
};
+
+/**
+ * Retrieves the trial balance sheet http query.
+ * @returns {object}
+ */
+export const useTrialBalanceSheetHttpQuery = () => {
+ const { query } = useTrialBalanceSheetQuery();
+
+ return React.useMemo(() => transformFilterFormToQuery(query), [query]);
+};
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.tsx
index c89d21f20..7e37ba792 100644
--- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.tsx
@@ -19,6 +19,7 @@ import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions
import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
import { saveInvoke, compose } from '@/utils';
+import { VendorSummarySheetExportMenu } from './components';
/**
* Vendors balance summary action bar.
@@ -106,11 +107,18 @@ function VendorsBalanceSummaryActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx
index a3bbfa122..dc2ac5561 100644
--- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx
@@ -31,7 +31,7 @@ export default function VendorsBalanceSummaryTable({
>
);
}
+
+/**
+ * Vendor summary sheet export menu.
+ * @returns {JSX.Element}
+ */
+export function VendorSummarySheetExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useVendorBalanceSummaryXlsxExport({
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useVendorBalanceSummaryCsvExport({
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport().then(() => {});
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport().then(() => {});
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsActionsBar.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsActionsBar.tsx
index 52595565f..8b5fbc600 100644
--- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsActionsBar.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsActionsBar.tsx
@@ -19,6 +19,7 @@ import withVendorsTransaction from './withVendorsTransaction';
import withVendorsTransactionsActions from './withVendorsTransactionsActions';
import { compose, saveInvoke } from '@/utils';
+import { VendorTransactionsExportMenu } from './components';
/**
* vendors transactions actions bar.
@@ -114,11 +115,18 @@ function VendorsTransactionsActionsBar({
icon={ }
text={ }
/>
- }
- text={ }
- />
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ placement="bottom-start"
+ minimal
+ >
+ }
+ text={ }
+ />
+
);
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/components.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/components.tsx
index ee078f215..120a321bb 100644
--- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/components.tsx
+++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/components.tsx
@@ -1,11 +1,24 @@
// @ts-nocheck
-import React from 'react';
+import React, { useRef } from 'react';
import intl from 'react-intl-universal';
+import {
+ Classes,
+ Intent,
+ Menu,
+ MenuItem,
+ ProgressBar,
+ Text,
+} from '@blueprintjs/core';
+import classNames from 'classnames';
-import { If } from '@/components';
+import { AppToaster, If, Stack } from '@/components';
import { useVendorsTransactionsContext } from './VendorsTransactionsProvider';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { getColumnWidth } from '@/utils';
+import {
+ useVendorsTransactionsCsvExport,
+ useVendorsTransactionsXlsxExport,
+} from '@/hooks/query';
/**
* Retrieve vendors transactions columns.
@@ -77,7 +90,7 @@ export const useVendorsTransactionsColumns = () => {
};
/**
- * vendors transactions loading bar.
+ * Vendors transactions loading bar.
*/
export function VendorsTransactionsLoadingBar() {
const { isVendorsTransactionFetching } = useVendorsTransactionsContext();
@@ -88,3 +101,86 @@ export function VendorsTransactionsLoadingBar() {
);
}
+
+/**
+ * Vendor transactions export menu.
+ */
+export function VendorTransactionsExportMenu() {
+ const toastKey = useRef(null);
+ const commonToastConfig = {
+ isCloseButtonShown: true,
+ timeout: 2000,
+ };
+ const { query } = useVendorsTransactionsContext();
+
+ const openProgressToast = (amount: number) => {
+ return (
+
+ The report has been exported successfully.
+ = 100,
+ })}
+ intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
+ value={amount / 100}
+ />
+
+ );
+ };
+ // Export the report to xlsx.
+ const { mutateAsync: xlsxExport } = useVendorsTransactionsXlsxExport(query, {
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Export the report to csv.
+ const { mutateAsync: csvExport } = useVendorsTransactionsCsvExport({
+ onDownloadProgress: (xlsxExportProgress: number) => {
+ if (!toastKey.current) {
+ toastKey.current = AppToaster.show({
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ });
+ } else {
+ AppToaster.show(
+ {
+ message: openProgressToast(xlsxExportProgress),
+ ...commonToastConfig,
+ },
+ toastKey.current,
+ );
+ }
+ },
+ });
+ // Handle csv export button click.
+ const handleCsvExportBtnClick = () => {
+ csvExport();
+ };
+ // Handle xlsx export button click.
+ const handleXlsxExportBtnClick = () => {
+ xlsxExport();
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/webapp/src/hooks/query/financialReports.tsx b/packages/webapp/src/hooks/query/financialReports.tsx
index 3645a6293..e9531ddec 100644
--- a/packages/webapp/src/hooks/query/financialReports.tsx
+++ b/packages/webapp/src/hooks/query/financialReports.tsx
@@ -1,16 +1,14 @@
// @ts-nocheck
import { useRequestQuery } from '../useQueryRequest';
import {
- trialBalanceSheetReducer,
generalLedgerTableRowsReducer,
journalTableRowsReducer,
- ARAgingSummaryTableRowsMapper,
- APAgingSummaryTableRowsMapper,
inventoryValuationReducer,
purchasesByItemsReducer,
salesByItemsReducer,
} from '@/containers/FinancialStatements/reducers';
import t from './types';
+import { useDownloadFile } from '../useDownloadFile';
/**
* Retrieve balance sheet.
@@ -33,6 +31,34 @@ export function useBalanceSheet(query, props) {
);
}
+export const useBalanceSheetXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/balance_sheet',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'balance_sheet.xlsx',
+ ...args,
+ });
+};
+
+export const useBalanceSheetCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/balance_sheet',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'balance_sheet.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve trial balance sheet.
*/
@@ -54,6 +80,34 @@ export function useTrialBalanceSheet(query, props) {
);
}
+export const useTrialBalanceSheetXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/trial_balance_sheet',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'trial_balance_sheet.xlsx',
+ ...args,
+ });
+};
+
+export const useTrialBalanceSheetCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/trial_balance_sheet',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'trial_balance_sheet.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve profit/loss (P&L) sheet.
*/
@@ -75,6 +129,34 @@ export function useProfitLossSheet(query, props) {
);
}
+export const useProfitLossSheetXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/profit_loss_sheet',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'profit_loss_sheet.xlsx',
+ ...args,
+ });
+};
+
+export const useProfitLossSheetCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/profit_loss_sheet',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'profit_loss_sheet.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve general ledger (GL) sheet.
*/
@@ -144,6 +226,34 @@ export function useARAgingSummaryReport(query, props) {
);
}
+export const useARAgingSheetXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/receivable_aging_summary',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'receivable_aging_summary.xlsx',
+ ...args,
+ });
+};
+
+export const useARAgingSheetCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/receivable_aging_summary',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'receivable_aging_summary.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve A/P aging summary report.
*/
@@ -165,6 +275,34 @@ export function useAPAgingSummaryReport(query, props) {
);
}
+export const useAPAgingSheetXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/payable_aging_summary',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'payable_aging_summary.xlsx',
+ ...args,
+ });
+};
+
+export const useAPAgingSheetCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/payable_aging_summary',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'payable_aging_summary.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve inventory valuation.
*/
@@ -270,6 +408,34 @@ export function useCustomerBalanceSummaryReport(query, props) {
);
}
+export const useCustomerBalanceSummaryXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/customer-balance-summary',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'customer_balance_summary.xlsx',
+ ...args,
+ });
+};
+
+export const useCustomerBalanceSummaryCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/customer-balance-summary',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'customer_balance_summary.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve vendors balance summary report.
*/
@@ -299,6 +465,36 @@ export function useVendorsBalanceSummaryReport(query, props) {
);
}
+export const useVendorBalanceSummaryXlsxExport = (args) => {
+ const url = '/financial_statements/vendor-balance-summary';
+ const config = {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ };
+ const filename = 'vendor_balance_summary.xlsx';
+
+ return useDownloadFile({
+ url,
+ config,
+ filename,
+ ...args,
+ });
+};
+
+export const useVendorBalanceSummaryCsvExport = (args) => {
+ return useDownloadFile({
+ url: '/financial_statements/vendor-balance-summary',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ },
+ filename: 'vendor_balance_summary.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve customers transactions report.
*/
@@ -327,6 +523,38 @@ export function useCustomersTransactionsReport(query, props) {
);
}
+export const useCustomersTransactionsXlsxExport = (query, args) => {
+ const url = '/financial_statements/transactions-by-customers';
+ const config = {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ };
+ const filename = 'customers_transactions.xlsx';
+
+ return useDownloadFile({
+ url,
+ config,
+ filename,
+ ...args,
+ });
+};
+
+export const useCustomersTransactionsCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/transactions-by-customers',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'customers_transactions.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve vendors transactions report.
*/
@@ -344,7 +572,7 @@ export function useVendorsTransactionsReport(query, props) {
{
select: (res) => ({
data: res.data.table,
- tableRows: res.data.table.data,
+ tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -355,6 +583,38 @@ export function useVendorsTransactionsReport(query, props) {
);
}
+export const useVendorsTransactionsXlsxExport = (query, args) => {
+ const url = '/financial_statements/transactions-by-vendors';
+ const config = {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ };
+ const filename = 'transactions_by_vendor.xlsx';
+
+ return useDownloadFile({
+ url,
+ config,
+ filename,
+ ...args,
+ });
+};
+
+export const useVendorsTransactionsCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/transactions-by-vendors',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'transactions_by_vendor.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve cash flow statement report.
*/
@@ -374,7 +634,7 @@ export function useCashFlowStatementReport(query, props) {
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
- tableRows: res.data.table.data,
+ tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -387,6 +647,42 @@ export function useCashFlowStatementReport(query, props) {
);
}
+export const useCashFlowStatementXlsxExport = (query, args) => {
+ const url = '/financial_statements/cash-flow';
+ const config = {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ };
+ const filename = 'cashflow_statement.xlsx';
+
+ return useDownloadFile({
+ url,
+ config,
+ filename,
+ ...args,
+ });
+};
+
+export const useCashFlowStatementCsvExport = (query, args) => {
+ const url = '/financial_statements/cash-flow';
+ const config = {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ };
+ const filename = 'cashflow_statement.csv';
+
+ return useDownloadFile({
+ url,
+ config,
+ filename,
+ ...args,
+ });
+};
+
/**
* Retrieve inventory item detail report.
*/
@@ -406,7 +702,7 @@ export function useInventoryItemDetailsReport(query, props) {
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
- tableRows: res.data.table.data,
+ tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -419,6 +715,34 @@ export function useInventoryItemDetailsReport(query, props) {
);
}
+export const useInventoryItemDetailsXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/inventory-item-details',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'inventory_item_details.xlsx',
+ ...args,
+ });
+};
+
+export const useInventoryItemDetailsCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/inventory-item-details',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'inventory_item_details.csv',
+ ...args,
+ });
+};
+
/**
* Retrieve transactions by reference report.
*/
@@ -460,3 +784,31 @@ export function useSalesTaxLiabilitySummary(query, props) {
},
);
}
+
+export const useSalesTaxLiabilitySummaryXlsxExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/sales-tax-liability-summary',
+ config: {
+ headers: {
+ accept: 'application/xlsx',
+ },
+ params: query,
+ },
+ filename: 'sales_tax_liability_summary.xlsx',
+ ...args,
+ });
+};
+
+export const useSalesTaxLiabilitySummaryCsvExport = (query, args) => {
+ return useDownloadFile({
+ url: '/financial_statements/sales-tax-liability-summary',
+ config: {
+ headers: {
+ accept: 'application/csv',
+ },
+ params: query,
+ },
+ filename: 'sales_tax_liability_summary.csv',
+ ...args,
+ });
+};
diff --git a/packages/webapp/src/hooks/useDownloadFile.ts b/packages/webapp/src/hooks/useDownloadFile.ts
new file mode 100644
index 000000000..3237f2a79
--- /dev/null
+++ b/packages/webapp/src/hooks/useDownloadFile.ts
@@ -0,0 +1,72 @@
+// @ts-nocheck
+import axios, { AxiosError, AxiosRequestConfig } from 'axios';
+import { useState } from 'react';
+import { useMutation } from 'react-query';
+import useApiRequest from './useRequest';
+
+interface IArgs {
+ url: string;
+ filename: string;
+ mime?: string;
+ config?: AxiosRequestConfig;
+ onDownloadProgress?: (progress: number) => void;
+}
+
+export const useDownloadFile = (args: IArgs) => {
+ const apiRequest = useApiRequest();
+
+ const mutation = useMutation(() =>
+ apiRequest
+ .get(args.url, {
+ responseType: 'blob',
+ onDownloadProgress: (ev) => {
+ args.onDownloadProgress &&
+ args.onDownloadProgress(Math.round((ev.loaded * 100) / ev.total));
+ },
+ ...args.config,
+ })
+ .then((res) => {
+ downloadFile(res.data, args.filename, args.mime);
+ return res;
+ }),
+ );
+ return { ...mutation };
+};
+
+export function downloadFile(data, filename, mime, bom) {
+ var blobData = typeof bom !== 'undefined' ? [bom, data] : [data];
+ var blob = new Blob(blobData, { type: mime || 'application/octet-stream' });
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ // IE workaround for "HTML7007: One or more blob URLs were
+ // revoked by closing the blob for which they were created.
+ // These URLs will no longer resolve as the data backing
+ // the URL has been freed."
+ window.navigator.msSaveBlob(blob, filename);
+ } else {
+ var blobURL =
+ window.URL && window.URL.createObjectURL
+ ? window.URL.createObjectURL(blob)
+ : window.webkitURL.createObjectURL(blob);
+ var tempLink = document.createElement('a');
+ tempLink.style.display = 'none';
+ tempLink.href = blobURL;
+ tempLink.setAttribute('download', filename);
+
+ // Safari thinks _blank anchor are pop ups. We only want to set _blank
+ // target if the browser does not support the HTML5 download attribute.
+ // This allows you to download files in desktop safari if pop up blocking
+ // is enabled.
+ if (typeof tempLink.download === 'undefined') {
+ tempLink.setAttribute('target', '_blank');
+ }
+
+ document.body.appendChild(tempLink);
+ tempLink.click();
+
+ // Fixes "webkit blob resource error 1"
+ setTimeout(function () {
+ document.body.removeChild(tempLink);
+ window.URL.revokeObjectURL(blobURL);
+ }, 200);
+ }
+}
diff --git a/packages/webapp/src/lang/ar/index.json b/packages/webapp/src/lang/ar/index.json
index b2325c53f..976b049d6 100644
--- a/packages/webapp/src/lang/ar/index.json
+++ b/packages/webapp/src/lang/ar/index.json
@@ -407,7 +407,6 @@
"display_name": "اسم العرض",
"the_customer_has_been_created_successfully": "تم إنشاء زبون جديد بنجاح.",
"select_contact": "حدد جهة اتصال",
- "contact": "جهة اتصال",
"contacts": "جهات الاتصال",
"close_sidebar": "إغلاق الشريط الجانبي.",
"open_sidebar": "فتح الشريط الجانبي.",
@@ -804,7 +803,6 @@
"all_customers": "كل الزبائن",
"all_vendors": "كل الموردين",
"selected_customers": "{عدد} العملاء المحددين",
- "transaction_number": " العملية",
"running_balance": "الرصيد التحليلي",
"view_all": "مشاهدة الكل",
"payment_via_voucher": "الدفع عن طريق القسيمة",
@@ -871,7 +869,6 @@
"inventory_valuation": "تقييم المخزون",
"payable_accounts_should_assign_with_vendors": "يجب تعيين حسابات الدفع مع البائعين.",
"account_paper": "ورقة الحساب",
- "transaction_date": "تاريخ العملة",
"account_normal": "طبيعة الحساب",
"published_at": "نشرت في",
"customers_balance_summary": "ملخص رصيد الزبائن",
@@ -922,7 +919,6 @@
"drag_drop_files_here_or_click_here": "قم بسحب/إسقاط الملفات هنا أو انقر هنا.",
"enter_an_item": "أدخل منتج ...",
"due_amount": "القيمة المستحقة",
- "invoice_details": "تفاصيل الفاتورة",
"setting_your_auto_generated_estimate_number": "عيين رقم العرض الذي تم إنشاؤه تلقائيًا",
"setting_your_auto_generated_journal_number": "عيين رقم قيد اليدوي الذي تم إنشاؤه تلقائيًا",
"setting_your_auto_generated_invoice_number": "عيين رقم الفاتورة الذي تم إنشاؤه تلقائيًا",
@@ -934,7 +930,6 @@
"receive_full_amount": "استلام المبلغ كاملاً",
"manage_the_organization_s_services_and_products": "إدارة الخدمات والمنتجات للمنشأة.",
"here_a_list_of_your_organization_products_and_services": "هنا قائمة بمنتجات وخدمات عملك ، لاستخدامها عند إنشاء فواتير أو فواتير لموردين أو البائعين.",
- "receipt_details": "تفاصيل الإيصال",
"bill_details": "تفاصيل الفاتورة",
"new_bill_payment": "سند مورد جديد",
"new_sale_invoice": "فاتورة بيع جديدة",
@@ -1148,7 +1143,6 @@
"conditions_and_terms": "Conditions and terms",
"allocate_landed_coast": "تحميل تكلفة اضافية",
"transaction_date": "تاريخ المعاملة",
- "transaction_type": "نوع المعاملة",
"transaction_id": "رقم المعاملة",
"transaction_number": "رقم المعاملة",
"transaction_line": "سطر المعاملة",
@@ -1177,7 +1171,6 @@
"contact": "جهة الاتصال",
"invoice_details": "تفاصيل الفاتورة",
"receipt_details": "تفاصيل الإيصال",
- "payment_receive_details": "تفاصيل سند الزبون",
"payment_made_details": "تفاصيل سند المورد",
"New item category": "اضافة تصنيف صنف جديد",
"New service": "اضافة خدمة جديدة",
diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json
index 4dd764c3f..4a78b4e76 100644
--- a/packages/webapp/src/lang/en/index.json
+++ b/packages/webapp/src/lang/en/index.json
@@ -408,7 +408,6 @@
"display_name": "Display Name",
"the_customer_has_been_created_successfully": "The customer has been created successfully.",
"select_contact": "Select contact",
- "contact": "Contact",
"contacts": "Contacts",
"close_sidebar": "Close sidebar.",
"open_sidebar": "Open sidebar.",
@@ -796,7 +795,6 @@
"all_customers": "All Customers",
"all_vendors": "All Vendors",
"selected_customers": "{count} Selected Customers",
- "transaction_number": "Transaction #",
"running_balance": "Running balance",
"view_all": "View all",
"payment_via_voucher": "Payment via voucher",
@@ -867,8 +865,6 @@
"inventory_valuation": "Inventory valuation",
"payable_accounts_should_assign_with_vendors": "Payable accounts should assign with vendors.",
"account_paper": "Account Paper",
- "transaction_date": "Transaction date",
- "transaction_type": "Transaction type",
"account_normal": "Account normal",
"published_at": "Published at",
"customers_balance_summary": "Customers Balance Summary",
@@ -1130,7 +1126,6 @@
"transaction_date": "Transaction date",
"transaction_type": "Transaction type",
"transaction_id": "Transaction #",
- "transaction_number": "Transaction number",
"transaction_line": "Transaction line",
"allocation_method": "Allocation method",
"other_income_account": "Other income account",
@@ -1157,9 +1152,6 @@
"journal_entries": "Journal Entries",
"contact": "Contact",
"invoice_details": "Invoice details",
- "receipt_details": "Receipt details",
- "payment_receive_details": "Payment receive details",
- "payment_made_details": "Payment made details",
"New item category": "New item category",
"New service": "New service",
"New inventory item": "New inventory item",
@@ -2078,7 +2070,7 @@
"project_task.dialog.edit_success_message": "The task has been edited successfully.",
"project_task.action.edit_task": "Edit Task",
"project_task.action.delete_task": "Delete Task",
- "project_task.rate": "{rate} / hour",
+"project_task.rate": "{rate} / hour",
"project_task.fixed_price": "Fixed price",
"project_task.non_chargable": "Non-chargeable",
"project_task.estimate_hours": "• {estimate_hours}h 0m estimated",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e5fb689ed..9482a23bf 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -66,8 +66,8 @@ importers:
specifier: ^3.2.0
version: 3.2.4
axios:
- specifier: ^0.20.0
- version: 0.20.0
+ specifier: ^1.6.0
+ version: 1.6.0
babel-loader:
specifier: ^9.1.2
version: 9.1.2(@babel/core@7.20.12)(webpack@5.76.0)
@@ -281,6 +281,9 @@ importers:
winston:
specifier: ^3.2.1
version: 3.8.2
+ xlsx:
+ specifier: ^0.18.5
+ version: 0.18.5
devDependencies:
'@types/lodash':
specifier: ^4.14.158
@@ -520,8 +523,8 @@ importers:
specifier: ^0.4.1
version: 0.4.1
axios:
- specifier: ^0.21.2
- version: 0.21.4
+ specifier: ^1.6.0
+ version: 1.6.0
basscss:
specifier: ^8.0.2
version: 8.1.0
@@ -7220,6 +7223,11 @@ packages:
regex-parser: 2.2.11
dev: false
+ /adler-32@1.3.1:
+ resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
+ engines: {node: '>=0.8'}
+ dev: false
+
/agenda@4.4.0:
resolution: {integrity: sha512-7fIO4indmmrtkDmj2woOBJnhHIM7jPtkdGR4VOApB46eeBrPGUnO28RFrmjHebc3PMDnKJI0PWFyu9L9VotgJg==}
engines: {node: '>=12.9.0'}
@@ -7825,32 +7833,14 @@ packages:
engines: {node: '>=4'}
dev: false
- /axios@0.20.0:
- resolution: {integrity: sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==}
- deprecated: Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410
- dependencies:
- follow-redirects: 1.15.2
- transitivePeerDependencies:
- - debug
- dev: false
-
- /axios@0.21.4:
- resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
- dependencies:
- follow-redirects: 1.15.2
- transitivePeerDependencies:
- - debug
- dev: false
-
- /axios@1.3.2:
- resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==}
+ /axios@1.6.0:
+ resolution: {integrity: sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==}
dependencies:
follow-redirects: 1.15.2
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
- dev: true
/axobject-query@3.2.1:
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
@@ -8858,6 +8848,14 @@ packages:
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
dev: false
+ /cfb@1.2.2:
+ resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ adler-32: 1.3.1
+ crc-32: 1.2.2
+ dev: false
+
/chai-http@4.3.0:
resolution: {integrity: sha512-zFTxlN7HLMv+7+SPXZdkd5wUlK+KxH6Q7bIEMiEx0FK3zuuMqL7cwICAQ0V1+yYRozBburYuxN1qZstgHpFZQg==}
engines: {node: '>=4'}
@@ -9198,6 +9196,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
+ /codepage@1.15.0:
+ resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
+ engines: {node: '>=0.8'}
+ dev: false
+
/collect-v8-coverage@1.0.2:
resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
dev: false
@@ -9733,6 +9736,12 @@ packages:
- supports-color
dev: false
+ /crc-32@1.2.2:
+ resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
+ engines: {node: '>=0.8'}
+ hasBin: true
+ dev: false
+
/create-ecdh@4.0.4:
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
dependencies:
@@ -12511,6 +12520,11 @@ packages:
engines: {node: '>= 0.6'}
dev: false
+ /frac@1.1.2:
+ resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
+ engines: {node: '>=0.8'}
+ dev: false
+
/fraction.js@4.2.0:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
dev: false
@@ -17861,7 +17875,7 @@ packages:
'@yarnpkg/lockfile': 1.1.0
'@yarnpkg/parsers': 3.0.0-rc.38
'@zkochan/js-yaml': 0.0.6
- axios: 1.3.2
+ axios: 1.6.0
chalk: 4.1.2
cli-cursor: 3.1.0
cli-spinners: 2.6.1
@@ -22290,6 +22304,13 @@ packages:
engines: {node: '>= 0.6'}
dev: false
+ /ssf@0.11.2:
+ resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ frac: 1.1.2
+ dev: false
+
/sshpk@1.17.0:
resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==}
engines: {node: '>=0.10.0'}
@@ -24576,10 +24597,20 @@ packages:
babel-walk: 3.0.0-canary-5
dev: false
+ /wmf@1.0.2:
+ resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
+ engines: {node: '>=0.8'}
+ dev: false
+
/word-wrap@1.2.4:
resolution: {integrity: sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==}
engines: {node: '>=0.10.0'}
+ /word@0.3.0:
+ resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
+ engines: {node: '>=0.8'}
+ dev: false
+
/wordwrap@1.0.0:
resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
dev: true
@@ -24909,6 +24940,20 @@ packages:
engines: {node: '>=4'}
dev: false
+ /xlsx@0.18.5:
+ resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
+ engines: {node: '>=0.8'}
+ hasBin: true
+ dependencies:
+ adler-32: 1.3.1
+ cfb: 1.2.2
+ codepage: 1.15.0
+ crc-32: 1.2.2
+ ssf: 0.11.2
+ wmf: 1.0.2
+ word: 0.3.0
+ dev: false
+
/xml-name-validator@3.0.0:
resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==}
dev: false