Compare commits

..

6 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
04b16a7d2f Publish
- @bigcapital/server@0.10.1
 - @bigcapital/webapp@0.10.2
2023-10-03 22:07:42 +02:00
Ahmed Bouhuolia
fd27136274 tst 2023-10-03 22:06:33 +02:00
Ahmed Bouhuolia
951e360405 chore(webapp): add missing packages 2023-10-03 22:05:57 +02:00
Ahmed Bouhuolia
d2242b7744 WIP 2023-10-03 12:11:55 +02:00
Ahmed Bouhuolia
4e9b0ae24f fix: migrate from npm to pnpm 2023-09-29 15:54:47 +02:00
Ahmed Bouhuolia
e5ffb5661a feat: migrate to pnpm 2023-09-27 22:44:54 +02:00
326 changed files with 3243 additions and 26763 deletions

View File

@@ -60,15 +60,6 @@
"contributions": [ "contributions": [
"bug" "bug"
] ]
},
{
"login": "kochie",
"name": "Robert Koch",
"avatar_url": "https://avatars.githubusercontent.com/u/10809884?v=4",
"profile": "https://me.kochie.io",
"contributions": [
"code"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -8,7 +8,7 @@ MAIL_FROM_NAME=
MAIL_FROM_ADDRESS= MAIL_FROM_ADDRESS=
# Database # Database
DB_HOST=localhost DB_HOST=mysql
DB_USER=bigcapital DB_USER=bigcapital
DB_PASSWORD=bigcapital DB_PASSWORD=bigcapital
DB_ROOT_PASSWORD=root DB_ROOT_PASSWORD=root
@@ -49,12 +49,4 @@ SIGNUP_ALLOWED_DOMAINS=
SIGNUP_ALLOWED_EMAILS= SIGNUP_ALLOWED_EMAILS=
# API rate limit (points,duration,block duration). # API rate limit (points,duration,block duration).
API_RATE_LIMIT=120,60,600 API_RATE_LIMIT=120,60,600
# Gotenberg API for PDF printing - (production).
GOTENBERG_URL=http://gotenberg:3000
GOTENBERG_DOCS_URL=http://server:3000/public/
# Gotenberg API - (development)
# GOTENBERG_URL=http://gotenberg:3000
# GOTENBERG_DOCS_URL=http://server:3000/public/

View File

@@ -1,22 +0,0 @@
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

View File

@@ -33,8 +33,7 @@ Contributions via pull requests are much appreciated. Once the approach is agree
--- ---
## Local Setup Prerequisites ## Local Setup Prerequisites
- The application currently supports **Node.js v18.x**. - 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)
- `pnpm` packages manager, (from pnpm [guide](https://pnpm.io/installation) pick any installation method).
## Contribute to Backend ## Contribute to Backend
@@ -45,10 +44,11 @@ Contributions via pull requests are much appreciated. Once the approach is agree
cp .env.example .env cp .env.example .env
``` ```
- 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. - 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.
``` ```
pnpm install npm install
npm run bootstrap
``` ```
- Run all required docker containers in the development, we already configured all containers under `docker-compose.yml`. - 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. - There're some CLI commands we should run before running the server like databaase migration, so we need to build the `server` app first.
``` ```
pnpm run build:server npm run build:server
``` ```
- Run the database migration for system database. - Run the database migration for system database.
@@ -87,7 +87,7 @@ Batch 1 run: 6 migrations
- Next, start the webapp application. - Next, start the webapp application.
``` ```
pnpm run dev:server npm run dev:server
``` ```
**[`^top^`](#)** **[`^top^`](#)**
@@ -105,13 +105,14 @@ 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. - 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.
``` ```
pnpm install npm install
npm run bootstrap
``` ```
- Next, start the webapp application. - Next, start the webapp application.
``` ```
pnpm run dev:webapp npm run dev:webapp
``` ```
**[`^top^`](#)** **[`^top^`](#)**

View File

@@ -37,31 +37,6 @@ Bigcapital is a smart and open-source accounting and inventory software, Bigcapi
<img src="https://raw.githubusercontent.com/abouolia/blog/main/public/screenshot-3.png" width="270"> <img src="https://raw.githubusercontent.com/abouolia/blog/main/public/screenshot-3.png" width="270">
</p> </p>
# 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.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/new/#https://github.com/bigcapitalhq/bigcapital)
# Resources # Resources
- [Documentation](https://docs.bigcapital.ly/) - Learn how to use. - [Documentation](https://docs.bigcapital.ly/) - Learn how to use.
@@ -105,7 +80,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://scheibling.se"><img src="https://avatars.githubusercontent.com/u/24367830?v=4?s=100" width="100px;" alt="Lars Scheibling"/><br /><sub><b>Lars Scheibling</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Ascheibling" title="Bug reports">🐛</a></td> <td align="center" valign="top" width="14.28%"><a href="https://scheibling.se"><img src="https://avatars.githubusercontent.com/u/24367830?v=4?s=100" width="100px;" alt="Lars Scheibling"/><br /><sub><b>Lars Scheibling</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Ascheibling" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/suhaibaffan"><img src="https://avatars.githubusercontent.com/u/18115937?v=4?s=100" width="100px;" alt="Suhaib Affan"/><br /><sub><b>Suhaib Affan</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=suhaibaffan" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/suhaibaffan"><img src="https://avatars.githubusercontent.com/u/18115937?v=4?s=100" width="100px;" alt="Suhaib Affan"/><br /><sub><b>Suhaib Affan</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=suhaibaffan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KalliopiPliogka"><img src="https://avatars.githubusercontent.com/u/81677549?v=4?s=100" width="100px;" alt="Kalliopi Pliogka"/><br /><sub><b>Kalliopi Pliogka</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3AKalliopiPliogka" title="Bug reports">🐛</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/KalliopiPliogka"><img src="https://avatars.githubusercontent.com/u/81677549?v=4?s=100" width="100px;" alt="Kalliopi Pliogka"/><br /><sub><b>Kalliopi Pliogka</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3AKalliopiPliogka" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://me.kochie.io"><img src="https://avatars.githubusercontent.com/u/10809884?v=4?s=100" width="100px;" alt="Robert Koch"/><br /><sub><b>Robert Koch</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=kochie" title="Code">💻</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -35,8 +35,6 @@ services:
server: server:
container_name: bigcapital-server container_name: bigcapital-server
image: ghcr.io/bigcapitalhq/server:latest image: ghcr.io/bigcapitalhq/server:latest
expose:
- '3000'
links: links:
- mysql - mysql
- mongo - mongo
@@ -88,10 +86,6 @@ services:
- SIGNUP_ALLOWED_DOMAINS=${SIGNUP_ALLOWED_DOMAINS} - SIGNUP_ALLOWED_DOMAINS=${SIGNUP_ALLOWED_DOMAINS}
- SIGNUP_ALLOWED_EMAILS=${SIGNUP_ALLOWED_EMAILS} - SIGNUP_ALLOWED_EMAILS=${SIGNUP_ALLOWED_EMAILS}
# Gotenberg (Pdf generator)
- GOTENBERG_URL=${GOTENBERG_URL}
- GOTENBERG_DOCS_URL=${GOTENBERG_DOCS_URL}
database_migration: database_migration:
container_name: bigcapital-database-migration container_name: bigcapital-database-migration
build: build:
@@ -149,11 +143,6 @@ services:
volumes: volumes:
- redis:/data - redis:/data
gotenberg:
image: gotenberg/gotenberg:7
expose:
- '9000'
# Volumes # Volumes
volumes: volumes:
mysql: mysql:

View File

@@ -47,11 +47,6 @@ services:
restart_policy: restart_policy:
condition: unless-stopped condition: unless-stopped
gotenberg:
image: gotenberg/gotenberg:7
ports:
- "9000:3000"
# Volumes # Volumes
volumes: volumes:
mysql: mysql:

View File

@@ -2,6 +2,5 @@
"$schema": "node_modules/lerna/schemas/lerna-schema.json", "$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "independent", "version": "independent",
"npmClient": "pnpm", "npmClient": "pnpm",
"useWorkspaces": true,
"packages": ["packages/*"] "packages": ["packages/*"]
} }

View File

@@ -2,6 +2,7 @@
"name": "bigcapital-monorepo", "name": "bigcapital-monorepo",
"private": true, "private": true,
"scripts": { "scripts": {
"bootstrap": "lerna exec pnpm install",
"dev": "lerna run dev", "dev": "lerna run dev",
"build": "lerna run build", "build": "lerna run build",
"dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"", "dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"",
@@ -22,7 +23,7 @@
"lerna": "^6.4.1" "lerna": "^6.4.1"
}, },
"engines": { "engines": {
"node": "16.x || 17.x || 18.x" "node": "14.x"
}, },
"husky": { "husky": {
"hooks": { "hooks": {

View File

@@ -1,5 +1,6 @@
/node_modules/ /node_modules/
/.env /.env
/storage
stdout.log stdout.log
/dist /dist
/build /build

View File

@@ -1,4 +1,4 @@
FROM node:18.16.0-alpine as build FROM node:14.20-alpine as build
USER root USER root
@@ -83,25 +83,15 @@ WORKDIR /app
RUN chown node:node / RUN chown node:node /
# Install pnpm
RUN npm install -g pnpm
# Copy application dependency manifests to the container image. # Copy application dependency manifests to the container image.
COPY ./package*.json ./ COPY ./package*.json ./
COPY ./pnpm-lock.yaml ./pnpm-lock.yaml
COPY ./pnpm-workspace.yaml ./pnpm-workspace.yaml
COPY ./lerna.json ./lerna.json
COPY ./packages/server/package*.json ./packages/server/ COPY ./packages/server/package*.json ./packages/server/
# Install application dependencies COPY ./lerna.json ./lerna.json
RUN apk update
RUN apk add python3 build-base chromium
# Set PYHTON env # Install app dependencies for production.
ENV PYTHON=/usr/bin/python3 RUN npm install
RUN npm run bootstrap
# Install packages dependencies for production.
RUN pnpm install
COPY --chown=node:node ./packages/server ./packages/server COPY --chown=node:node ./packages/server ./packages/server

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "@bigcapital/server", "name": "@bigcapital/server",
"version": "0.10.2", "version": "0.10.1",
"description": "", "description": "",
"main": "src/server.ts", "main": "src/server.ts",
"scripts": { "scripts": {
@@ -31,7 +31,7 @@
"agendash": "^3.1.0", "agendash": "^3.1.0",
"app-root-path": "^3.0.0", "app-root-path": "^3.0.0",
"async": "^3.2.0", "async": "^3.2.0",
"axios": "^1.6.0", "axios": "^0.20.0",
"babel-loader": "^9.1.2", "babel-loader": "^9.1.2",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
@@ -43,7 +43,7 @@
"crypto-random-string": "^3.2.0", "crypto-random-string": "^3.2.0",
"csurf": "^1.10.0", "csurf": "^1.10.0",
"deep-map": "^2.0.0", "deep-map": "^2.0.0",
"deepdash": "^5.3.9", "deepdash": "^5.3.7",
"dotenv": "^8.1.0", "dotenv": "^8.1.0",
"errorhandler": "^1.5.1", "errorhandler": "^1.5.1",
"es6-weak-map": "^2.0.3", "es6-weak-map": "^2.0.3",
@@ -56,7 +56,6 @@
"express-fileupload": "^1.1.7-alpha.3", "express-fileupload": "^1.1.7-alpha.3",
"express-oauth-server": "^2.0.0", "express-oauth-server": "^2.0.0",
"express-validator": "^6.12.2", "express-validator": "^6.12.2",
"form-data": "^4.0.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-sass": "^5.0.0", "gulp-sass": "^5.0.0",
"helmet": "^3.21.0", "helmet": "^3.21.0",
@@ -96,14 +95,11 @@
"rate-limiter-flexible": "^2.1.14", "rate-limiter-flexible": "^2.1.14",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rtl-detect": "^1.0.4", "rtl-detect": "^1.0.4",
"source-map-loader": "^4.0.1",
"tmp-promise": "^3.0.3",
"ts-transformer-keys": "^0.4.2", "ts-transformer-keys": "^0.4.2",
"tsyringe": "^4.3.0", "tsyringe": "^4.3.0",
"typedi": "^0.8.0", "typedi": "^0.8.0",
"uniqid": "^5.2.0", "uniqid": "^5.2.0",
"winston": "^3.2.1", "winston": "^3.2.1"
"xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash": "^4.14.158", "@types/lodash": "^4.14.158",

View File

@@ -176,7 +176,6 @@
"invoice.paper.conditions_title": "Conditions & terms", "invoice.paper.conditions_title": "Conditions & terms",
"invoice.paper.notes_title": "Notes", "invoice.paper.notes_title": "Notes",
"invoice.paper.total": "Total", "invoice.paper.total": "Total",
"invoice.paper.subtotal": "Subtotal",
"invoice.paper.payment_amount": "Payment Amount", "invoice.paper.payment_amount": "Payment Amount",
"invoice.paper.balance_due": "Balance Due", "invoice.paper.balance_due": "Balance Due",
@@ -588,7 +587,6 @@
"balance_sheet.long_term_liabilities": "Long-Term Liabilities", "balance_sheet.long_term_liabilities": "Long-Term Liabilities",
"balance_sheet.non_current_liabilities": "Non-Current Liabilities", "balance_sheet.non_current_liabilities": "Non-Current Liabilities",
"balance_sheet.equity": "Equity", "balance_sheet.equity": "Equity",
"balance_sheet.net_income": "Net Income",
"balance_sheet.account_name": "Account name", "balance_sheet.account_name": "Account name",
"balance_sheet.total": "Total", "balance_sheet.total": "Total",

View File

@@ -137,14 +137,10 @@
tbody tr.payment-amount td:last-child { tbody tr.payment-amount td:last-child {
color: red color: red
} }
tbody tr.blanace-due td{ tbody tr.blanace-due td {
border-top: 3px double #666; border-top: 3px double #666;
font-weight: bold; font-weight: bold;
} }
tbody tr.total td {
border-top: 1px solid #666;
font-weight: bold;
}
} }
} }

View File

@@ -22,12 +22,12 @@ block content
div.invoice__due-amount div.invoice__due-amount
div.label #{__('invoice.paper.invoice_amount')} div.label #{__('invoice.paper.invoice_amount')}
div.amount #{saleInvoice.totalFormatted} div.amount #{saleInvoice.formattedAmount}
div.invoice__meta div.invoice__meta
div.invoice__meta-item.invoice__meta-item--amount div.invoice__meta-item.invoice__meta-item--amount
span.label #{__('invoice.paper.due_amount')} span.label #{__('invoice.paper.due_amount')}
span.value #{saleInvoice.dueAmountFormatted} span.value #{saleInvoice.formattedDueAmount}
div.invoice__meta-item.invoice__meta-item--billed-to div.invoice__meta-item.invoice__meta-item--billed-to
span.label #{__("invoice.paper.billed_to")} span.label #{__("invoice.paper.billed_to")}
@@ -35,11 +35,11 @@ block content
div.invoice__meta-item.invoice__meta-item--invoice-date div.invoice__meta-item.invoice__meta-item--invoice-date
span.label #{__("invoice.paper.invoice_date")} span.label #{__("invoice.paper.invoice_date")}
span.value #{saleInvoice.invoiceDateFormatted} span.value #{saleInvoice.formattedInvoiceDate}
div.invoice__meta-item.invoice__meta-item--due-date div.invoice__meta-item.invoice__meta-item--due-date
span.label #{__("invoice.paper.due_date")} span.label #{__("invoice.paper.due_date")}
span.value #{saleInvoice.dueDateFormatted} span.value #{saleInvoice.formattedDueDate}
div.invoice__table div.invoice__table
table table
@@ -63,22 +63,15 @@ block content
div.invoice__table-total div.invoice__table-total
table table
tbody tbody
tr.subtotal
td #{__('invoice.paper.subtotal')}
td #{saleInvoice.subtotalFormatted}
each tax in saleInvoice.taxes
tr.tax_line
td #{tax.name} [#{tax.taxRate}%]
td #{tax.taxRateAmountFormatted}
tr.total tr.total
td #{__('invoice.paper.total')} td #{__('invoice.paper.total')}
td #{saleInvoice.totalFormatted} td #{saleInvoice.formattedAmount}
tr.payment-amount tr.payment-amount
td #{__('invoice.paper.payment_amount')} td #{__('invoice.paper.payment_amount')}
td #{saleInvoice.paymentAmountFormatted} td #{saleInvoice.formattedPaymentAmount}
tr.blanace-due tr.blanace-due
td #{__('invoice.paper.balance_due')} td #{__('invoice.paper.balance_due')}
td #{saleInvoice.dueAmountFormatted} td #{saleInvoice.formattedDueAmount}
div.invoice__footer div.invoice__footer
if saleInvoice.termsConditions if saleInvoice.termsConditions

View File

@@ -45,9 +45,9 @@ block content
each entry in paymentReceive.entries each entry in paymentReceive.entries
tr tr
td.item=entry.invoice.invoiceNo td.item=entry.invoice.invoiceNo
td.date=entry.invoice.invoiceDateFormatted td.date=entry.invoice.formattedInvoiceDate
td.invoiceAmount=entry.invoice.totalFormatted td.invoiceAmount=entry.invoice.formattedAmount
td.paymentAmount=entry.invoice.paymentAmountFormatted td.paymentAmount=entry.invoice.formattedPaymentAmount
div.payment__table-after div.payment__table-after
div.payment__table-total div.payment__table-total

View File

@@ -2,20 +2,19 @@ import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator'; import { query } from 'express-validator';
import { Inject } from 'typedi'; import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import APAgingSummaryReportService from '@/services/FinancialStatements/AgingSummary/APAgingSummaryService';
import BaseFinancialReportController from './BaseFinancialReportController'; import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; 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 { export default class APAgingSummaryReportController extends BaseFinancialReportController {
@Inject() @Inject()
private APAgingSummaryApp: APAgingSummaryApplication; APAgingSummaryService: APAgingSummaryReportService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -29,9 +28,8 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
/** /**
* Validation schema. * Validation schema.
* @returns {ValidationChain[]}
*/ */
private get validationSchema() { get validationSchema() {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(), query('as_date').optional().isISO8601(),
@@ -51,58 +49,42 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
} }
/** /**
* Retrieves payable aging summary report. * Retrieve payable aging summary report.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/ */
private async payableAgingSummary( async payableAgingSummary(req: Request, res: Response, next: NextFunction) {
req: Request, const { tenantId, settings } = req;
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
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);
return res.status(200).send(table); switch (acceptType) {
// Retrieves the csv format. case 'application/json+table':
} else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { const table = await this.APAgingSummaryService.APAgingSummaryTable(
const csv = await this.APAgingSummaryApp.csv(tenantId, filter); 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);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); return res.status(200).send({
res.setHeader('Content-Type', 'text/csv'); data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
return res.send(csv); query: this.transfromToResponse(query),
// Retrieves the xlsx format. meta: this.transfromToResponse(meta),
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { });
const buffer = await this.APAgingSummaryApp.xlsx(tenantId, filter); 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 json format.
} else {
const sheet = await this.APAgingSummaryApp.sheet(tenantId, filter);
return res.status(200).send(sheet);
} }
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -5,18 +5,16 @@ import ARAgingSummaryService from '@/services/FinancialStatements/AgingSummary/A
import BaseFinancialReportController from './BaseFinancialReportController'; import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ARAgingSummaryApplication } from '@/services/FinancialStatements/AgingSummary/ARAgingSummaryApplication';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class ARAgingSummaryReportController extends BaseFinancialReportController { export default class ARAgingSummaryReportController extends BaseFinancialReportController {
@Inject() @Inject()
ARAgingSummaryApp: ARAgingSummaryApplication; ARAgingSummaryService: ARAgingSummaryService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -32,7 +30,7 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
/** /**
* AR aging summary validation roles. * AR aging summary validation roles.
*/ */
private get validationSchema() { get validationSchema() {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
@@ -54,53 +52,41 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
/** /**
* Retrieve AR aging summary report. * Retrieve AR aging summary report.
* @param {Request} req
* @param {Response} res
*/ */
private async receivableAgingSummary(req: Request, res: Response) { async receivableAgingSummary(req: Request, res: Response) {
const { tenantId } = req; const { tenantId, settings } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
const acceptType = accept.types([ switch (acceptType) {
ACCEPT_TYPE.APPLICATION_JSON, case 'application/json+table':
ACCEPT_TYPE.APPLICATION_JSON_TABLE, const table = await this.ARAgingSummaryService.ARAgingSummaryTable(
ACCEPT_TYPE.APPLICATION_CSV, tenantId,
ACCEPT_TYPE.APPLICATION_XLSX, filter
]); );
// Retrieves the xlsx format. return res.status(200).send({
if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { table: {
const buffer = await this.ARAgingSummaryApp.xlsx(tenantId, filter); 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);
res.setHeader( return res.status(200).send({
'Content-Disposition', data: this.transfromToResponse(data),
'attachment; filename=output.xlsx' columns: this.transfromToResponse(columns),
); query: this.transfromToResponse(query),
res.setHeader( meta: this.transfromToResponse(meta),
'Content-Type', });
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' break;
);
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) { } catch (error) {
console.log(error); console.log(error);

View File

@@ -3,21 +3,25 @@ import { Router, Request, Response, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator'; import { query, ValidationChain } from 'express-validator';
import { castArray } from 'lodash'; import { castArray } from 'lodash';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BalanceSheetStatementService from '@/services/FinancialStatements/BalanceSheet/BalanceSheetService';
import BaseFinancialReportController from './BaseFinancialReportController'; import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { BalanceSheetApplication } from '@/services/FinancialStatements/BalanceSheet/BalanceSheetApplication'; import BalanceSheetTable from '@/services/FinancialStatements/BalanceSheet/BalanceSheetTable';
import { ACCEPT_TYPE } from '@/interfaces/Http'; import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service() @Service()
export default class BalanceSheetStatementController extends BaseFinancialReportController { export default class BalanceSheetStatementController extends BaseFinancialReportController {
@Inject() @Inject()
private balanceSheetApp: BalanceSheetApplication; balanceSheetService: BalanceSheetStatementService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -34,7 +38,7 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
* Balance sheet validation schecma. * Balance sheet validation schecma.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get balanceSheetValidationSchema(): ValidationChain[] { get balanceSheetValidationSchema(): ValidationChain[] {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('accounting_method').optional().isIn(['cash', 'accrual']), query('accounting_method').optional().isIn(['cash', 'accrual']),
@@ -80,12 +84,10 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
/** /**
* Retrieve the balance sheet. * Retrieve the balance sheet.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/ */
private async balanceSheet(req: Request, res: Response, next: NextFunction) { async balanceSheet(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId, settings } = req;
const i18n = this.tenancy.i18n(tenantId);
let filter = this.matchedQueryData(req); let filter = this.matchedQueryData(req);
@@ -93,45 +95,29 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
...filter, ...filter,
accountsIds: castArray(filter.accountsIds), accountsIds: castArray(filter.accountsIds),
}; };
try { try {
const { data, columns, query, meta } =
await this.balanceSheetService.balanceSheet(tenantId, filter);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
const acceptType = accept.types([ const table = new BalanceSheetTable(data, query, i18n);
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);
return res.status(200).send(table); switch (acceptType) {
// Retrieves the csv format. case 'application/json+table':
} else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) { return res.status(200).send({
const buffer = await this.balanceSheetApp.csv(tenantId, filter); table: {
rows: table.tableRows(),
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); columns: table.tableColumns(),
res.setHeader('Content-Type', 'text/csv'); },
query,
return res.send(buffer); meta,
// Retrieves the xlsx format. });
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { case 'json':
const buffer = await this.balanceSheetApp.xlsx(tenantId, filter); default:
return res.status(200).send({ data, columns, query, meta });
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) { } catch (error) {
next(error); next(error);

View File

@@ -8,20 +8,29 @@ import {
ValidationChain, ValidationChain,
} from 'express'; } from 'express';
import BaseFinancialReportController from '../BaseFinancialReportController'; import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; 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 CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ACCEPT_TYPE } from '@/interfaces/Http';
import { CashflowSheetApplication } from '@/services/FinancialStatements/CashFlow/CashflowSheetApplication';
@Service() @Service()
export default class CashFlowController extends BaseFinancialReportController { export default class CashFlowController extends BaseFinancialReportController {
@Inject() @Inject()
private cashflowSheetApp: CashflowSheetApplication; cashFlowService: CashFlowStatementService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -38,7 +47,7 @@ export default class CashFlowController extends BaseFinancialReportController {
* Balance sheet validation schecma. * Balance sheet validation schecma.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get cashflowValidationSchema(): ValidationChain[] { get cashflowValidationSchema(): ValidationChain[] {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('from_date').optional(), query('from_date').optional(),
@@ -58,6 +67,41 @@ 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. * Retrieve the cash flow statment.
* @param {Request} req * @param {Request} req
@@ -65,52 +109,26 @@ export default class CashFlowController extends BaseFinancialReportController {
* @param {NextFunction} next * @param {NextFunction} next
* @returns {Response} * @returns {Response}
*/ */
public async cashFlow(req: Request, res: Response, next: NextFunction) { async cashFlow(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId, settings } = req;
const filter = { const filter = {
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const cashFlow = await this.cashFlowService.cashFlow(tenantId, filter);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
const acceptType = accept.types([ switch (acceptType) {
ACCEPT_TYPE.APPLICATION_JSON, case 'application/json+table':
ACCEPT_TYPE.APPLICATION_JSON_TABLE, return res
ACCEPT_TYPE.APPLICATION_CSV, .status(200)
ACCEPT_TYPE.APPLICATION_XLSX, .send(this.transformToTableRows(cashFlow, tenantId));
]); case 'json':
// Retrieves the json table format. default:
if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) { return res.status(200).send(this.transformJsonResponse(cashFlow));
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) { } catch (error) {
next(error); next(error);

View File

@@ -1,21 +1,29 @@
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator'; import { query } from 'express-validator';
import { Inject } from 'typedi'; import { Inject } from 'typedi';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import {
AbilitySubject,
ICustomerBalanceSummaryStatement,
ReportsAction,
} from '@/interfaces';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import CustomerBalanceSummary from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService';
import BaseFinancialReportController from '../BaseFinancialReportController'; import BaseFinancialReportController from '../BaseFinancialReportController';
import CustomerBalanceSummaryTableRows from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryTableRows';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ACCEPT_TYPE } from '@/interfaces/Http'; import HasTenancyService from '@/services/Tenancy/TenancyService';
import { CustomerBalanceSummaryApplication } from '@/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryApplication';
export default class CustomerBalanceSummaryReportController extends BaseFinancialReportController { export default class CustomerBalanceSummaryReportController extends BaseFinancialReportController {
@Inject() @Inject()
private customerBalanceSummaryApp: CustomerBalanceSummaryApplication; customerBalanceSummaryService: CustomerBalanceSummary;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -34,7 +42,7 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia
/** /**
* Validation schema. * Validation schema.
*/ */
private get validationSchema() { get validationSchema() {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
@@ -54,67 +62,75 @@ 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. * Retrieve payable aging summary report.
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
private async customerBalanceSummary( async customerBalanceSummary(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
) { ) {
const { tenantId } = req; const { tenantId, settings } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const customerBalanceSummary =
await this.customerBalanceSummaryService.customerBalanceSummary(
tenantId,
filter
);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_JSON_TABLE,
ACCEPT_TYPE.APPLICATION_CSV,
ACCEPT_TYPE.APPLICATION_XLSX,
]);
// Retrieves the xlsx format. switch (acceptType) {
if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { case 'application/json+table':
const buffer = await this.customerBalanceSummaryApp.xlsx( return res
tenantId, .status(200)
filter .send(this.transformToTableRows(tenantId, customerBalanceSummary));
); case 'application/json':
res.setHeader( default:
'Content-Disposition', return res
'attachment; filename=output.xlsx' .status(200)
); .send(this.transformToJsonResponse(customerBalanceSummary));
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');
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) { } catch (error) {
next(error); next(error);

View File

@@ -8,20 +8,24 @@ import {
ValidationChain, ValidationChain,
} from 'express'; } from 'express';
import BaseController from '@/api/controllers/BaseController'; 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 { AbilitySubject, ReportsAction } from '@/interfaces';
import { InventortyDetailsApplication } from '@/services/FinancialStatements/InventoryDetails/InventoryDetailsApplication';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class InventoryDetailsController extends BaseController { export default class InventoryDetailsController extends BaseController {
@Inject() @Inject()
private inventoryItemDetailsApp: InventortyDetailsApplication; inventoryDetailsService: InventoryDetailsService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -41,7 +45,7 @@ export default class InventoryDetailsController extends BaseController {
* Balance sheet validation schecma. * Balance sheet validation schecma.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get validationSchema(): ValidationChain[] { get validationSchema(): ValidationChain[] {
return [ return [
query('number_format.precision') query('number_format.precision')
.optional() .optional()
@@ -73,66 +77,69 @@ export default class InventoryDetailsController extends BaseController {
} }
/** /**
* Retrieve the inventory item details sheet. * 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.
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
* @returns {Response} * @returns {Response}
*/ */
private async inventoryDetails( async inventoryDetails(req: Request, res: Response, next: NextFunction) {
req: Request, const { tenantId, settings } = req;
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const filter = { const filter = {
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const inventoryDetails =
await this.inventoryDetailsService.inventoryDetails(tenantId, filter);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
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);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); switch (acceptType) {
res.setHeader('Content-Type', 'text/csv'); case 'application/json+table':
return res
return res.send(buffer); .status(200)
// Retrieves the xlsx format. .send(this.transformToTableRows(inventoryDetails, tenantId));
} else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { case 'json':
const buffer = await this.inventoryItemDetailsApp.xlsx( default:
tenantId, return res
filter .status(200)
); .send(this.transformJsonResponse(inventoryDetails));
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) { } catch (error) {
next(error); next(error);

View File

@@ -1,20 +1,24 @@
import { Service, Inject } from 'typedi'; import { Service, Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator'; import { query, ValidationChain } from 'express-validator';
import ProfitLossSheetService from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetService';
import BaseFinancialReportController from './BaseFinancialReportController'; import BaseFinancialReportController from './BaseFinancialReportController';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import { ACCEPT_TYPE } from '@/interfaces/Http'; import { ProfitLossSheetTable } from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable';
import { ProfitLossSheetApplication } from '@/services/FinancialStatements/ProfitLossSheet/ProfitLossSheetApplication'; import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service() @Service()
export default class ProfitLossSheetController extends BaseFinancialReportController { export default class ProfitLossSheetController extends BaseFinancialReportController {
@Inject() @Inject()
private profitLossSheetApp: ProfitLossSheetApplication; profitLossSheetService: ProfitLossSheetService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -30,7 +34,7 @@ export default class ProfitLossSheetController extends BaseFinancialReportContro
/** /**
* Validation schema. * Validation schema.
*/ */
private get validationSchema(): ValidationChain[] { get validationSchema(): ValidationChain[] {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('basis').optional(), query('basis').optional(),
@@ -81,54 +85,37 @@ export default class ProfitLossSheetController extends BaseFinancialReportContro
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async profitLossSheet( async profitLossSheet(req: Request, res: Response, next: NextFunction) {
req: Request, const { tenantId, settings } = req;
res: Response, const i18n = this.tenancy.i18n(tenantId);
next: NextFunction
) {
const { tenantId } = req;
const filter = this.matchedQueryData(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 { try {
// Retrieves the csv format. const { data, query, meta } =
if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { await this.profitLossSheetService.profitLossSheet(tenantId, filter);
const sheet = await this.profitLossSheetApp.csv(tenantId, filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); const accept = this.accepts(req);
res.setHeader('Content-Type', 'text/csv'); const acceptType = accept.types(['json', 'application/json+table']);
return res.send(sheet); switch (acceptType) {
// Retrieves the json table format. case 'application/json+table':
} else if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { const table = new ProfitLossSheetTable(data, query, i18n);
const table = await this.profitLossSheetApp.table(tenantId, filter);
return res.status(200).send(table); return res.status(200).send({
// Retrieves the xlsx format. table: {
} else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { rows: table.tableRows(),
const sheet = await this.profitLossSheetApp.xlsx(tenantId, filter); columns: table.tableColumns(),
},
res.setHeader( query,
'Content-Disposition', meta,
'attachment; filename=output.xlsx' });
); case 'json':
res.setHeader( default:
'Content-Type', return res.status(200).send({
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' data,
); query,
return res.send(sheet); meta,
// Retrieves the json format. });
} else {
const sheet = await this.profitLossSheetApp.sheet(tenantId, filter);
return res.status(200).send(sheet);
} }
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -16,12 +16,15 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
'/', '/',
CheckPolicies(ReportsAction.READ_SALES_BY_ITEMS, AbilitySubject.Report), CheckPolicies(
ReportsAction.READ_SALES_BY_ITEMS,
AbilitySubject.Report
),
this.validationSchema, this.validationSchema,
this.validationResult, this.validationResult,
asyncMiddleware(this.purchasesByItems.bind(this)) asyncMiddleware(this.purchasesByItems.bind(this))
@@ -32,7 +35,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
/** /**
* Validation schema. * Validation schema.
*/ */
private get validationSchema(): ValidationChain[] { get validationSchema(): ValidationChain[] {
return [ return [
query('from_date').optional().isISO8601(), query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(), query('to_date').optional().isISO8601(),
@@ -60,11 +63,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async purchasesByItems( async purchasesByItems(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);

View File

@@ -1,21 +1,20 @@
import { Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator'; import { query } from 'express-validator';
import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController'; import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { SalesTaxLiabilitySummaryApplication } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryApplication'; import { SalesTaxLiabilitySummaryService } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService';
import { ACCEPT_TYPE } from '@/interfaces/Http';
export default class SalesTaxLiabilitySummary extends BaseFinancialReportController { export default class SalesTaxLiabilitySummary extends BaseFinancialReportController {
@Inject() @Inject()
private salesTaxLiabilitySummaryApp: SalesTaxLiabilitySummaryApplication; private salesTaxLiabilitySummaryService: SalesTaxLiabilitySummaryService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -32,9 +31,8 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
/** /**
* Validation schema. * Validation schema.
* @returns {ValidationChain[]}
*/ */
private get validationSchema() { get validationSchema() {
return [ return [
query('from_date').optional().isISO8601(), query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(), query('to_date').optional().isISO8601(),
@@ -47,7 +45,7 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
private async salesTaxLiabilitySummary( async salesTaxLiabilitySummary(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -57,52 +55,33 @@ export default class SalesTaxLiabilitySummary extends BaseFinancialReportControl
try { try {
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_JSON_TABLE,
ACCEPT_TYPE.APPLICATION_CSV,
ACCEPT_TYPE.APPLICATION_XLSX,
]);
// Retrieves the json table format. switch (acceptType) {
if (acceptType === ACCEPT_TYPE.APPLICATION_JSON_TABLE) { case 'application/json+table':
const table = await this.salesTaxLiabilitySummaryApp.table( const salesTaxLiabilityTable =
tenantId, await this.salesTaxLiabilitySummaryService.salesTaxLiabilitySummaryTable(
filter 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.send(buffer); return res.status(200).send({
// Retrieves the json format. table: salesTaxLiabilityTable.table,
} else { query: salesTaxLiabilityTable.query,
const sheet = await this.salesTaxLiabilitySummaryApp.sheet( meta: salesTaxLiabilityTable.meta,
tenantId, });
filter case 'json':
); default:
return res.status(200).send(sheet); const salesTaxLiability =
await this.salesTaxLiabilitySummaryService.salesTaxLiability(
tenantId,
filter
);
return res.status(200).send({
data: salesTaxLiability.data,
query: salesTaxLiability.query,
meta: salesTaxLiability.meta,
});
} }
} catch (error) { } catch (error) {
next(error); next(error);

View File

@@ -1,22 +1,30 @@
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator'; import { query } from 'express-validator';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import {
AbilitySubject,
ITransactionsByCustomersStatement,
ReportsAction,
} from '@/interfaces';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController'; 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 CheckPolicies from '@/api/middleware/CheckPolicies';
import { TransactionsByCustomerApplication } from '@/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersApplication';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class TransactionsByCustomersReportController extends BaseFinancialReportController { export default class TransactionsByCustomersReportController extends BaseFinancialReportController {
@Inject() @Inject()
private transactionsByCustomersApp: TransactionsByCustomerApplication; transactionsByCustomersService: TransactionsByCustomersService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -50,13 +58,45 @@ 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. * Retrieve payable aging summary report.
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
private async transactionsByCustomers( async transactionsByCustomers(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -64,51 +104,25 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
const { tenantId } = req; const { tenantId } = req;
const filter = this.matchedQueryData(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 { try {
// Retrieves the json table format. const report =
if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) { await this.transactionsByCustomersService.transactionsByCustomers(
const table = await this.transactionsByCustomersApp.table(
tenantId, tenantId,
filter filter
); );
return res.status(200).send(table); const accept = this.accepts(req);
// Retrieve the csv format. const acceptType = accept.types(['json', 'application/json+table']);
} else if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
const csv = await this.transactionsByCustomersApp.csv(tenantId, filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); switch (acceptType) {
res.setHeader('Content-Type', 'text/csv'); case 'json':
return res
return res.send(csv); .status(200)
// Retrieve the xlsx format. .send(this.transfromToJsonResponse(report.data, report.columns));
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { case 'application/json+table':
const buffer = await this.transactionsByCustomersApp.xlsx( default:
tenantId, return res
filter .status(200)
); .send(this.transformToTableResponse(report.data, tenantId));
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) { } catch (error) {
next(error); next(error);

View File

@@ -3,19 +3,27 @@ import { query, ValidationChain } from 'express-validator';
import { Inject } from 'typedi'; import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController'; import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; 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 CheckPolicies from '@/api/middleware/CheckPolicies'; 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 { export default class TransactionsByVendorsReportController extends BaseFinancialReportController {
@Inject() @Inject()
private transactionsByVendorsApp: TransactionsByVendorApplication; transactionsByVendorsService: TransactionsByVendorsService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -34,7 +42,7 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
/** /**
* Validation schema. * Validation schema.
*/ */
private get validationSchema(): ValidationChain[] { get validationSchema(): ValidationChain[] {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
@@ -50,64 +58,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. * Retrieve payable aging summary report.
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
private async transactionsByVendors( async transactionsByVendors(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const report =
await this.transactionsByVendorsService.transactionsByVendors(
tenantId,
filter
);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_JSON_TABLE,
ACCEPT_TYPE.APPLICATION_CSV,
ACCEPT_TYPE.APPLICATION_XLSX,
]);
// Retrieves the xlsx format. switch (acceptType) {
if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) { case 'application/json+table':
const buffer = await this.transactionsByVendorsApp.xlsx( return res
tenantId, .status(200)
filter .send(this.transformToTableRows(tenantId, report.data));
); case 'json':
res.setHeader('Content-Type', 'application/vnd.openxmlformats'); default:
res.setHeader( return res.status(200).send(this.transformToJsonResponse(report));
'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) { } catch (error) {
next(error); next(error);

View File

@@ -3,22 +3,20 @@ import { Request, Response, Router, NextFunction } from 'express';
import { query, ValidationChain } from 'express-validator'; import { query, ValidationChain } from 'express-validator';
import { castArray } from 'lodash'; import { castArray } from 'lodash';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import TrialBalanceSheetService from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetInjectable'; import TrialBalanceSheetService from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService';
import BaseFinancialReportController from './BaseFinancialReportController'; import BaseFinancialReportController from './BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { TrialBalanceSheetApplication } from '@/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetApplication';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class TrialBalanceSheetController extends BaseFinancialReportController { export default class TrialBalanceSheetController extends BaseFinancialReportController {
@Inject() @Inject()
private trialBalanceSheetApp: TrialBalanceSheetApplication; trialBalanceSheetService: TrialBalanceSheetService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -38,7 +36,7 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
* Validation schema. * Validation schema.
* @return {ValidationChain[]} * @return {ValidationChain[]}
*/ */
private get trialBalanceSheetValidationSchema(): ValidationChain[] { get trialBalanceSheetValidationSchema(): ValidationChain[] {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('basis').optional(), query('basis').optional(),
@@ -61,62 +59,28 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
/** /**
* Retrieve the trial balance sheet. * Retrieve the trial balance sheet.
*/ */
private async trialBalanceSheet( public async trialBalanceSheet(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
) { ) {
const { tenantId } = req; const { tenantId, settings } = req;
let filter = this.matchedQueryData(req); let filter = this.matchedQueryData(req);
filter = { filter = {
...filter, ...filter,
accountsIds: castArray(filter.accountsIds), accountsIds: castArray(filter.accountsIds),
}; };
try { try {
const accept = this.accepts(req); const { data, query, meta } =
await this.trialBalanceSheetService.trialBalanceSheet(tenantId, filter);
const acceptType = accept.types([ return res.status(200).send({
ACCEPT_TYPE.APPLICATION_JSON, data: this.transfromToResponse(data),
ACCEPT_TYPE.APPLICATION_JSON_TABLE, query: this.transfromToResponse(query),
ACCEPT_TYPE.APPLICATION_CSV, meta: this.transfromToResponse(meta),
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.trialBalanceSheetApp.sheet(
tenantId,
filter
);
return res.status(200).send({ data, query, meta });
}
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@@ -3,19 +3,27 @@ import { query } from 'express-validator';
import { Inject } from 'typedi'; import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController'; import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces'; import VendorBalanceSummaryTableRows from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryTableRows';
import VendorBalanceSummaryService from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryService';
import {
AbilitySubject,
IVendorBalanceSummaryStatement,
ReportsAction,
} from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ACCEPT_TYPE } from '@/interfaces/Http'; import HasTenancyService from '@/services/Tenancy/TenancyService';
import { VendorBalanceSummaryApplication } from '@/services/FinancialStatements/VendorBalanceSummary/VendorBalanceSummaryApplication';
export default class VendorBalanceSummaryReportController extends BaseFinancialReportController { export default class VendorBalanceSummaryReportController extends BaseFinancialReportController {
@Inject() @Inject()
private vendorBalanceSummaryApp: VendorBalanceSummaryApplication; vendorBalanceSummaryService: VendorBalanceSummaryService;
@Inject()
tenancy: HasTenancyService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.get( router.get(
@@ -33,7 +41,7 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR
/** /**
* Validation schema. * Validation schema.
*/ */
private get validationSchema() { get validationSchema() {
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(), query('as_date').optional().isISO8601(),
@@ -51,62 +59,73 @@ 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. * Retrieve vendors balance summary.
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
public async vendorBalanceSummary( async vendorBalanceSummary(req: Request, res: Response, next: NextFunction) {
req: Request, const { tenantId, settings } = req;
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const vendorBalanceSummary =
await this.vendorBalanceSummaryService.vendorBalanceSummary(
tenantId,
filter
);
const accept = this.accepts(req); const accept = this.accepts(req);
const acceptType = accept.types([ const acceptType = accept.types(['json', 'application/json+table']);
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_JSON_TABLE,
ACCEPT_TYPE.APPLICATION_CSV,
ACCEPT_TYPE.APPLICATION_XLSX,
]);
// Retrieves the csv format. switch (acceptType) {
if (acceptType === ACCEPT_TYPE.APPLICATION_CSV) { case 'application/json+table':
const buffer = await this.vendorBalanceSummaryApp.csv(tenantId, filter); return res
.status(200)
res.setHeader('Content-Disposition', 'attachment; filename=output.csv'); .send(this.transformToTableRows(tenantId, vendorBalanceSummary));
res.setHeader('Content-Type', 'text/csv'); case 'json':
default:
return res.send(buffer); return res
} else if (acceptType === ACCEPT_TYPE.APPLICATION_XLSX) { .status(200)
const buffer = await this.vendorBalanceSummaryApp.xlsx( .send(this.transformToJsonResponse(vendorBalanceSummary));
tenantId,
filter
);
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) { } catch (error) {
next(error); next(error);

View File

@@ -149,11 +149,6 @@ export default class ItemsController extends BaseController {
.trim() .trim()
.escape() .escape()
.isLength({ max: DATATYPES_LENGTH.TEXT }), .isLength({ max: DATATYPES_LENGTH.TEXT }),
check('sell_tax_rate_id').optional({ nullable: true }).isInt().toInt(),
check('purchase_tax_rate_id')
.optional({ nullable: true })
.isInt()
.toInt(),
check('category_id') check('category_id')
.optional({ nullable: true }) .optional({ nullable: true })
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 }) .isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
@@ -513,28 +508,6 @@ export default class ItemsController extends BaseController {
], ],
}); });
} }
if (error.errorType === 'PURCHASE_TAX_RATE_NOT_FOUND') {
return res.status(400).send({
errors: [
{
type: 'PURCHASE_TAX_RATE_NOT_FOUND',
message: 'Purchase tax rate has not found.',
code: 410,
},
],
});
}
if (error.errorType === 'SELL_TAX_RATE_NOT_FOUND') {
return res.status(400).send({
errors: [
{
type: 'SELL_TAX_RATE_NOT_FOUND',
message: 'Sell tax rate is not found.',
code: 420,
},
],
});
}
} }
next(error); next(error);
} }

View File

@@ -31,14 +31,14 @@ export default class OrganizationController extends BaseController {
router.post( router.post(
'/build', '/build',
this.buildOrganizationValidationSchema, this.organizationValidationSchema,
this.validationResult, this.validationResult,
asyncMiddleware(this.build.bind(this)), asyncMiddleware(this.build.bind(this)),
this.handleServiceErrors.bind(this) this.handleServiceErrors.bind(this)
); );
router.put( router.put(
'/', '/',
this.updateOrganizationValidationSchema, this.organizationValidationSchema,
this.validationResult, this.validationResult,
this.asyncMiddleware(this.updateOrganization.bind(this)), this.asyncMiddleware(this.updateOrganization.bind(this)),
this.handleServiceErrors.bind(this) this.handleServiceErrors.bind(this)
@@ -55,7 +55,7 @@ export default class OrganizationController extends BaseController {
* Organization setup schema. * Organization setup schema.
* @return {ValidationChain[]} * @return {ValidationChain[]}
*/ */
private get commonOrganizationValidationSchema(): ValidationChain[] { private get organizationValidationSchema(): ValidationChain[] {
return [ return [
check('name').exists().trim(), check('name').exists().trim(),
check('industry').optional({ nullable: true }).isString().trim().escape(), check('industry').optional({ nullable: true }).isString().trim().escape(),
@@ -68,29 +68,6 @@ export default class OrganizationController extends BaseController {
]; ];
} }
/**
* Build organization validation schema.
* @returns {ValidationChain[]}
*/
private get buildOrganizationValidationSchema(): ValidationChain[] {
return [...this.commonOrganizationValidationSchema];
}
/**
* Update organization validation schema.
* @returns {ValidationChain[]}
*/
private get updateOrganizationValidationSchema(): ValidationChain[] {
return [
...this.commonOrganizationValidationSchema,
check('tax_number')
.optional({ nullable: true })
.isString()
.trim()
.escape(),
];
}
/** /**
* Builds tenant database and migrate database schema. * Builds tenant database and migrate database schema.
* @param {Request} req - Express request. * @param {Request} req - Express request.

View File

@@ -115,14 +115,12 @@ export default class BillsController extends BaseController {
check('note').optional().trim().escape(), check('note').optional().trim().escape(),
check('open').default(false).isBoolean().toBoolean(), check('open').default(false).isBoolean().toBoolean(),
check('is_inclusive_tax').default(false).isBoolean().toBoolean(),
check('entries').isArray({ min: 1 }), check('entries').isArray({ min: 1 }),
check('entries.*.index').exists().isNumeric().toInt(), check('entries.*.index').exists().isNumeric().toInt(),
check('entries.*.item_id').exists().isNumeric().toInt(), check('entries.*.item_id').exists().isNumeric().toInt(),
check('entries.*.rate').exists().isNumeric().toFloat(), check('entries.*.rate').exists().isNumeric().toFloat(),
check('entries.*.quantity').exists().isNumeric().toInt(), check('entries.*.quantity').exists().isNumeric().toFloat(),
check('entries.*.discount') check('entries.*.discount')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()
@@ -139,15 +137,6 @@ export default class BillsController extends BaseController {
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()
.toInt(), .toInt(),
check('entries.*.tax_code')
.optional({ nullable: true })
.trim()
.escape()
.isString(),
check('entries.*.tax_rate_id')
.optional({ nullable: true })
.isNumeric()
.toInt(),
]; ];
} }
@@ -553,16 +542,6 @@ export default class BillsController extends BaseController {
], ],
}); });
} }
if (error.errorType === 'ITEM_ENTRY_TAX_RATE_CODE_NOT_FOUND') {
return res.boom.badRequest(null, {
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_CODE_NOT_FOUND', code: 1800 }],
});
}
if (error.errorType === 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND') {
return res.boom.badRequest(null, {
errors: [{ type: 'ITEM_ENTRY_TAX_RATE_ID_NOT_FOUND', code: 1900 }],
});
}
} }
next(error); next(error);
} }

View File

@@ -121,7 +121,7 @@ export default class BillsPayments extends BaseController {
check('entries').exists().isArray({ min: 1 }), check('entries').exists().isArray({ min: 1 }),
check('entries.*.index').optional().isNumeric().toInt(), check('entries.*.index').optional().isNumeric().toInt(),
check('entries.*.bill_id').exists().isNumeric().toInt(), check('entries.*.bill_id').exists().isNumeric().toInt(),
check('entries.*.payment_amount').exists().isNumeric().toFloat(), check('entries.*.payment_amount').exists().isNumeric().toInt(),
]; ];
} }

View File

@@ -173,7 +173,7 @@ export default class VendorCreditController extends BaseController {
check('entries.*.index').exists().isNumeric().toInt(), check('entries.*.index').exists().isNumeric().toInt(),
check('entries.*.item_id').exists().isNumeric().toInt(), check('entries.*.item_id').exists().isNumeric().toInt(),
check('entries.*.rate').exists().isNumeric().toFloat(), check('entries.*.rate').exists().isNumeric().toFloat(),
check('entries.*.quantity').exists().isNumeric().toInt(), check('entries.*.quantity').exists().isNumeric().toFloat(),
check('entries.*.discount') check('entries.*.discount')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()
@@ -211,11 +211,12 @@ export default class VendorCreditController extends BaseController {
check('branch_id').optional({ nullable: true }).isNumeric().toInt(), check('branch_id').optional({ nullable: true }).isNumeric().toInt(),
check('entries').isArray({ min: 1 }), check('entries').isArray({ min: 1 }),
check('entries.*.id').optional().isNumeric().toInt(), check('entries.*.id').optional().isNumeric().toInt(),
check('entries.*.index').exists().isNumeric().toInt(), check('entries.*.index').exists().isNumeric().toInt(),
check('entries.*.item_id').exists().isNumeric().toInt(), check('entries.*.item_id').exists().isNumeric().toInt(),
check('entries.*.rate').exists().isNumeric().toFloat(), check('entries.*.rate').exists().isNumeric().toFloat(),
check('entries.*.quantity').exists().isNumeric().toInt(), check('entries.*.quantity').exists().isNumeric().toFloat(),
check('entries.*.discount') check('entries.*.discount')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()

View File

@@ -222,7 +222,7 @@ export default class PaymentReceivesController extends BaseController {
check('entries.*.index').exists().isNumeric().toInt(), check('entries.*.index').exists().isNumeric().toInt(),
check('entries.*.item_id').exists().isNumeric().toInt(), check('entries.*.item_id').exists().isNumeric().toInt(),
check('entries.*.rate').exists().isNumeric().toFloat(), check('entries.*.rate').exists().isNumeric().toFloat(),
check('entries.*.quantity').exists().isNumeric().toInt(), check('entries.*.quantity').exists().isNumeric().toFloat(),
check('entries.*.discount') check('entries.*.discount')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()

View File

@@ -142,7 +142,7 @@ export default class PaymentReceivesController extends BaseController {
check('entries.*.id').optional({ nullable: true }).isNumeric().toInt(), check('entries.*.id').optional({ nullable: true }).isNumeric().toInt(),
check('entries.*.index').optional().isNumeric().toInt(), check('entries.*.index').optional().isNumeric().toInt(),
check('entries.*.invoice_id').exists().isNumeric().toInt(), check('entries.*.invoice_id').exists().isNumeric().toInt(),
check('entries.*.payment_amount').exists().isNumeric().toFloat(), check('entries.*.payment_amount').exists().isNumeric().toInt(),
]; ];
} }

View File

@@ -117,7 +117,7 @@ export default class SalesReceiptsController extends BaseController {
check('entries.*.index').exists().isNumeric().toInt(), check('entries.*.index').exists().isNumeric().toInt(),
check('entries.*.item_id').exists().isNumeric().toInt(), check('entries.*.item_id').exists().isNumeric().toInt(),
check('entries.*.quantity').exists().isNumeric().toInt(), check('entries.*.quantity').exists().isNumeric().toInt(),
check('entries.*.rate').exists().isNumeric().toFloat(), check('entries.*.rate').exists().isNumeric().toInt(),
check('entries.*.discount') check('entries.*.discount')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()

View File

@@ -5,7 +5,6 @@ global.__root_dir = path.join(__dirname, '..');
global.__resources_dir = path.join(global.__root_dir, 'resources'); global.__resources_dir = path.join(global.__root_dir, 'resources');
global.__locales_dir = path.join(global.__resources_dir, 'locales'); global.__locales_dir = path.join(global.__resources_dir, 'locales');
global.__views_dir = path.join(global.__root_dir, 'views'); global.__views_dir = path.join(global.__root_dir, 'views');
global.__storage_dir = path.join(global.__root_dir, 'storage');
moment.prototype.toMySqlDateTime = function () { moment.prototype.toMySqlDateTime = function () {
return this.format('YYYY-MM-DD HH:mm:ss'); return this.format('YYYY-MM-DD HH:mm:ss');

View File

@@ -1,10 +0,0 @@
exports.up = (knex) => {
return knex.schema.table('bills', (table) => {
table.boolean('is_inclusive_tax').defaultTo(false);
table.decimal('tax_amount_withheld');
});
};
exports.down = (knex) => {
return knex.schema.table('bills', () => {});
};

View File

@@ -1,18 +0,0 @@
exports.up = (knex) => {
return knex.schema.table('items', (table) => {
table
.integer('sell_tax_rate_id')
.unsigned()
.references('id')
.inTable('tax_rates');
table
.integer('purchase_tax_rate_id')
.unsigned()
.references('id')
.inTable('tax_rates');
});
};
exports.down = (knex) => {
return knex.schema.dropTableIfExists('tax_rates');
};

View File

@@ -1,14 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('storage', (table) => {
table.increments('id').primary();
table.string('key').notNullable();
table.string('path').notNullable();
table.string('extension').notNullable();
table.integer('expire_in');
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('storage');
};

View File

@@ -1,9 +0,0 @@
exports.up = function (knex) {
return knex.schema.alterTable('items_entries', (table) => {
table.decimal('rate', 15, 5).alter();
});
};
exports.down = function (knex) {
return knex.table('items_entries', (table) => {});
};

View File

@@ -8,7 +8,6 @@ import {
IAgingSummaryData, IAgingSummaryData,
} from './AgingReport'; } from './AgingReport';
import { INumberFormatQuery } from './FinancialStatements'; import { INumberFormatQuery } from './FinancialStatements';
import { IFinancialTable } from './Table';
export interface IAPAgingSummaryQuery extends IAgingSummaryQuery { export interface IAPAgingSummaryQuery extends IAgingSummaryQuery {
vendorsIds: number[]; vendorsIds: number[];
@@ -35,8 +34,3 @@ export interface IAPAgingSummaryMeta {
baseCurrency: string; baseCurrency: string;
organizationName: string; organizationName: string;
} }
export interface IAPAgingSummaryTable extends IFinancialTable {
query: IAPAgingSummaryQuery;
meta: IAPAgingSummaryMeta;
}

View File

@@ -5,7 +5,6 @@ import {
IAgingSummaryContact, IAgingSummaryContact,
IAgingSummaryData, IAgingSummaryData,
} from './AgingReport'; } from './AgingReport';
import { IFinancialTable } from './Table';
export interface IARAgingSummaryQuery extends IAgingSummaryQuery { export interface IARAgingSummaryQuery extends IAgingSummaryQuery {
customersIds: number[]; customersIds: number[];
@@ -27,8 +26,3 @@ export interface IARAgingSummaryMeta {
organizationName: string; organizationName: string;
baseCurrency: string; baseCurrency: string;
} }
export interface IARAgingSummaryTable extends IFinancialTable {
meta: IARAgingSummaryMeta;
query: IARAgingSummaryQuery;
}

View File

@@ -3,14 +3,12 @@ import {
IFormatNumberSettings, IFormatNumberSettings,
IFinancialSheetBranchesQuery, IFinancialSheetBranchesQuery,
} from './FinancialStatements'; } from './FinancialStatements';
import { IFinancialTable } from './Table';
// Balance sheet schema nodes types. // Balance sheet schema nodes types.
export enum BALANCE_SHEET_SCHEMA_NODE_TYPE { export enum BALANCE_SHEET_SCHEMA_NODE_TYPE {
AGGREGATE = 'AGGREGATE', AGGREGATE = 'AGGREGATE',
ACCOUNTS = 'ACCOUNTS', ACCOUNTS = 'ACCOUNTS',
ACCOUNT = 'ACCOUNT', ACCOUNT = 'ACCOUNT',
NET_INCOME = 'NET_INCOME',
} }
export enum BALANCE_SHEET_NODE_TYPE { export enum BALANCE_SHEET_NODE_TYPE {
@@ -35,7 +33,6 @@ export enum BALANCE_SHEET_SCHEMA_NODE_ID {
LOGN_TERM_LIABILITY = 'LOGN_TERM_LIABILITY', LOGN_TERM_LIABILITY = 'LOGN_TERM_LIABILITY',
NON_CURRENT_LIABILITY = 'NON_CURRENT_LIABILITY', NON_CURRENT_LIABILITY = 'NON_CURRENT_LIABILITY',
EQUITY = 'EQUITY', EQUITY = 'EQUITY',
NET_INCOME = 'NET_INCOME',
} }
// Balance sheet query. // Balance sheet query.
@@ -90,6 +87,7 @@ export interface IBalanceSheetDOO {
meta: IBalanceSheetMeta; meta: IBalanceSheetMeta;
} }
export interface IBalanceSheetCommonNode { export interface IBalanceSheetCommonNode {
total: IBalanceSheetTotal; total: IBalanceSheetTotal;
horizontalTotals?: IBalanceSheetTotal[]; horizontalTotals?: IBalanceSheetTotal[];
@@ -110,7 +108,7 @@ export interface IBalanceSheetAggregateNode extends IBalanceSheetCommonNode {
id: string; id: string;
name: string; name: string;
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE; nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE;
children?: IBalanceSheetDataNode[]; children?: (IBalanceSheetAggregateNode | IBalanceSheetAccountNode)[];
} }
export interface IBalanceSheetTotal { export interface IBalanceSheetTotal {
@@ -120,13 +118,6 @@ export interface IBalanceSheetTotal {
date?: string | Date; date?: string | Date;
} }
export interface IBalanceSheetAccountsNode extends IBalanceSheetCommonNode {
id: number | string;
name: string;
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS;
children: IBalanceSheetAccountNode[];
}
export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode { export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
id: number; id: number;
index: number; index: number;
@@ -137,17 +128,7 @@ export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
children?: IBalanceSheetAccountNode[]; children?: IBalanceSheetAccountNode[];
} }
export interface IBalanceSheetNetIncomeNode extends IBalanceSheetCommonNode { export type IBalanceSheetDataNode = IBalanceSheetAggregateNode;
id: number;
name: string;
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME;
}
export type IBalanceSheetDataNode =
| IBalanceSheetAggregateNode
| IBalanceSheetAccountNode
| IBalanceSheetAccountsNode
| IBalanceSheetNetIncomeNode;
export interface IBalanceSheetPercentageAmount { export interface IBalanceSheetPercentageAmount {
amount: number; amount: number;
@@ -169,16 +150,9 @@ export interface IBalanceSheetSchemaAccountNode {
accountsTypes: string[]; accountsTypes: string[];
} }
export interface IBalanceSheetSchemaNetIncomeNode {
id: string;
name: string;
type: BALANCE_SHEET_SCHEMA_NODE_TYPE;
}
export type IBalanceSheetSchemaNode = export type IBalanceSheetSchemaNode =
| IBalanceSheetSchemaAccountNode | IBalanceSheetSchemaAccountNode
| IBalanceSheetSchemaAggregateNode | IBalanceSheetSchemaAggregateNode;
| IBalanceSheetSchemaNetIncomeNode;
export interface IBalanceSheetDatePeriods { export interface IBalanceSheetDatePeriods {
assocAccountNodeDatePeriods(node): any; assocAccountNodeDatePeriods(node): any;
@@ -216,8 +190,3 @@ export enum IAccountTransactionsGroupBy {
Month = 'month', Month = 'month',
Week = 'week', Week = 'week',
} }
export interface IBalanceSheetTable extends IFinancialTable {
meta: IBalanceSheetMeta;
query: IBalanceSheetQuery;
}

View File

@@ -2,7 +2,6 @@ import { Knex } from 'knex';
import { IDynamicListFilterDTO } from './DynamicFilter'; import { IDynamicListFilterDTO } from './DynamicFilter';
import { IItemEntry, IItemEntryDTO } from './ItemEntry'; import { IItemEntry, IItemEntryDTO } from './ItemEntry';
import { IBillLandedCost } from './LandedCost'; import { IBillLandedCost } from './LandedCost';
export interface IBillDTO { export interface IBillDTO {
vendorId: number; vendorId: number;
billNumber: string; billNumber: string;
@@ -16,10 +15,10 @@ export interface IBillDTO {
exchangeRate?: number; exchangeRate?: number;
open: boolean; open: boolean;
entries: IItemEntryDTO[]; entries: IItemEntryDTO[];
branchId?: number; branchId?: number;
warehouseId?: number; warehouseId?: number;
projectId?: number; projectId?: number;
isInclusiveTax?: boolean;
} }
export interface IBillEditDTO { export interface IBillEditDTO {
@@ -81,15 +80,6 @@ export interface IBill {
localAmount?: number; localAmount?: number;
locatedLandedCosts?: IBillLandedCost[]; locatedLandedCosts?: IBillLandedCost[];
amountLocal: number;
subtotal: number;
subtotalLocal: number;
subtotalExcludingTax: number;
taxAmountWithheld: number;
taxAmountWithheldLocal: number;
total: number;
totalLocal: number;
} }
export interface IBillsFilter extends IDynamicListFilterDTO { export interface IBillsFilter extends IDynamicListFilterDTO {

View File

@@ -1,7 +1,7 @@
import { INumberFormatQuery } from './FinancialStatements'; import { INumberFormatQuery } from './FinancialStatements';
import { IAccount } from './Account'; import { IAccount } from './Account';
import { ILedger } from './Ledger'; import { ILedger } from './Ledger';
import { IFinancialTable, ITableRow } from './Table'; import { ITableRow } from './Table';
export interface ICashFlowStatementQuery { export interface ICashFlowStatementQuery {
fromDate: Date | string; fromDate: Date | string;
@@ -101,11 +101,6 @@ export interface ICashFlowStatementDOO {
query: ICashFlowStatementQuery; query: ICashFlowStatementQuery;
} }
export interface ICashFlowStatementTable extends IFinancialTable {
meta: ICashFlowStatementMeta;
query: ICashFlowStatementQuery;
}
export interface ICashFlowStatementService { export interface ICashFlowStatementService {
cashFlow( cashFlow(
tenantId: number, tenantId: number,

View File

@@ -1,10 +1,11 @@
import { INumberFormatQuery } from './FinancialStatements';
import { import {
IContactBalanceSummaryQuery, IContactBalanceSummaryQuery,
IContactBalanceSummaryAmount, IContactBalanceSummaryAmount,
IContactBalanceSummaryPercentage, IContactBalanceSummaryPercentage,
IContactBalanceSummaryTotal, IContactBalanceSummaryTotal,
} from './ContactBalanceSummary'; } from './ContactBalanceSummary';
import { IFinancialTable } from './Table';
export interface ICustomerBalanceSummaryQuery export interface ICustomerBalanceSummaryQuery
extends IContactBalanceSummaryQuery { extends IContactBalanceSummaryQuery {
@@ -18,7 +19,7 @@ export interface ICustomerBalanceSummaryPercentage
extends IContactBalanceSummaryPercentage {} extends IContactBalanceSummaryPercentage {}
export interface ICustomerBalanceSummaryCustomer { export interface ICustomerBalanceSummaryCustomer {
id: number; id: number,
customerName: string; customerName: string;
total: ICustomerBalanceSummaryAmount; total: ICustomerBalanceSummaryAmount;
percentageOfColumn?: ICustomerBalanceSummaryPercentage; percentageOfColumn?: ICustomerBalanceSummaryPercentage;
@@ -46,7 +47,3 @@ export interface ICustomerBalanceSummaryService {
query: ICustomerBalanceSummaryQuery query: ICustomerBalanceSummaryQuery
): Promise<ICustomerBalanceSummaryStatement>; ): Promise<ICustomerBalanceSummaryStatement>;
} }
export interface ICustomerBalanceSummaryTable extends IFinancialTable {
query: ICustomerBalanceSummaryQuery;
}

View File

@@ -1,7 +0,0 @@
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',
};

View File

@@ -1,12 +1,13 @@
import { INumberFormatQuery } from './FinancialStatements'; import {
import { IFinancialTable } from './Table'; INumberFormatQuery,
} from './FinancialStatements';
export interface IInventoryDetailsQuery { export interface IInventoryDetailsQuery {
fromDate: Date | string; fromDate: Date | string;
toDate: Date | string; toDate: Date | string;
numberFormat: INumberFormatQuery; numberFormat: INumberFormatQuery;
noneTransactions: boolean; noneTransactions: boolean;
itemsIds: number[]; itemsIds: number[]
warehousesIds?: number[]; warehousesIds?: number[];
branchesIds?: number[]; branchesIds?: number[];
@@ -65,7 +66,7 @@ export interface IInventoryDetailsItemTransaction {
cost: IInventoryDetailsNumber; cost: IInventoryDetailsNumber;
value: IInventoryDetailsNumber; value: IInventoryDetailsNumber;
profitMargin: IInventoryDetailsNumber; profitMargin: IInventoryDetailsNumber;
rate: IInventoryDetailsNumber; rate: IInventoryDetailsNumber;
runningQuantity: IInventoryDetailsNumber; runningQuantity: IInventoryDetailsNumber;
@@ -79,6 +80,7 @@ export type IInventoryDetailsNode =
| IInventoryDetailsItemTransaction; | IInventoryDetailsItemTransaction;
export type IInventoryDetailsData = IInventoryDetailsItem[]; export type IInventoryDetailsData = IInventoryDetailsItem[];
export interface IInventoryItemDetailMeta { export interface IInventoryItemDetailMeta {
isCostComputeRunning: boolean; isCostComputeRunning: boolean;
organizationName: string; organizationName: string;
@@ -89,9 +91,4 @@ export interface IInvetoryItemDetailDOO {
data: IInventoryDetailsData; data: IInventoryDetailsData;
query: IInventoryDetailsQuery; query: IInventoryDetailsQuery;
meta: IInventoryItemDetailMeta; meta: IInventoryItemDetailMeta;
} }
export interface IInvetoryItemDetailsTable extends IFinancialTable {
query: IInventoryDetailsQuery;
meta: IInventoryItemDetailMeta;
}

View File

@@ -22,9 +22,6 @@ export interface IItem {
sellDescription: string; sellDescription: string;
purchaseDescription: string; purchaseDescription: string;
sellTaxRateId: number;
purchaseTaxRateId: number;
quantityOnHand: number; quantityOnHand: number;
note: string; note: string;
@@ -57,9 +54,6 @@ export interface IItemDTO {
sellDescription: string; sellDescription: string;
purchaseDescription: string; purchaseDescription: string;
sellTaxRateId: number;
purchaseTaxRateId: number;
quantityOnHand: number; quantityOnHand: number;
note: string; note: string;

View File

@@ -7,25 +7,18 @@ export interface ILedger {
filter(cb: (entry: ILedgerEntry) => boolean): ILedger; filter(cb: (entry: ILedgerEntry) => boolean): ILedger;
whereAccountId(accountId: number): ILedger; whereAccountId(accountId: number): ILedger;
whereAccountsIds(accountsIds: number[]): ILedger;
whereContactId(contactId: number): ILedger; whereContactId(contactId: number): ILedger;
whereFromDate(fromDate: Date | string): ILedger; whereFromDate(fromDate: Date | string): ILedger;
whereToDate(toDate: Date | string): ILedger; whereToDate(toDate: Date | string): ILedger;
whereCurrencyCode(currencyCode: string): ILedger; whereCurrencyCode(currencyCode: string): ILedger;
whereBranch(branchId: number): ILedger; whereBranch(branchId: number): ILedger;
whereItem(itemId: number): ILedger; whereItem(itemId: number): ILedger;
whereProject(projectId: number): ILedger;
getClosingBalance(): number; getClosingBalance(): number;
getForeignClosingBalance(): number; getForeignClosingBalance(): number;
getClosingDebit(): number;
getClosingCredit(): number;
getContactsIds(): number[]; getContactsIds(): number[];
getAccountsIds(): number[]; getAccountsIds(): number[];
reverse(): ILedger;
isEmpty(): boolean;
} }
export interface ILedgerEntry { export interface ILedgerEntry {

View File

@@ -2,7 +2,6 @@ import {
IFinancialSheetBranchesQuery, IFinancialSheetBranchesQuery,
INumberFormatQuery, INumberFormatQuery,
} from './FinancialStatements'; } from './FinancialStatements';
import { IFinancialTable } from './Table';
export enum ProfitLossAggregateNodeId { export enum ProfitLossAggregateNodeId {
INCOME = 'INCOME', INCOME = 'INCOME',
@@ -178,9 +177,3 @@ export enum ProfitLossSheetRowType {
ACCOUNT = 'ACCOUNT', ACCOUNT = 'ACCOUNT',
TOTAL = 'TOTAL', TOTAL = 'TOTAL',
} }
export interface IProfitLossSheetTable extends IFinancialTable{
meta: IProfitLossSheetMeta;
query: IProfitLossSheetQuery;
}

View File

@@ -1,5 +1,5 @@
import { Knex } from 'knex';
import { Ability, RawRuleOf, ForcedSubject } from '@casl/ability'; import { Ability, RawRuleOf, ForcedSubject } from '@casl/ability';
import Knex from 'knex';
export const actions = [ export const actions = [
'manage', 'manage',
@@ -96,8 +96,7 @@ export enum AbilitySubject {
Preferences = 'Preferences', Preferences = 'Preferences',
CreditNote = 'CreditNode', CreditNote = 'CreditNode',
VendorCredit = 'VendorCredit', VendorCredit = 'VendorCredit',
Project = 'Project', Project = 'Project'
TaxRate = 'TaxRate'
} }
export interface IRoleCreatedPayload { export interface IRoleCreatedPayload {

View File

@@ -1,5 +1,3 @@
import { IFinancialTable } from "./Table";
export interface SalesTaxLiabilitySummaryQuery { export interface SalesTaxLiabilitySummaryQuery {
fromDate: Date; fromDate: Date;
toDate: Date; toDate: Date;
@@ -51,8 +49,3 @@ export interface SalesTaxLiabilitySummaryMeta {
organizationName: string; organizationName: string;
baseCurrency: string; baseCurrency: string;
} }
export interface ISalesTaxLiabilitySummaryTable extends IFinancialTable {
query: SalesTaxLiabilitySummaryQuery;
meta: SalesTaxLiabilitySummaryMeta;
}

View File

@@ -25,7 +25,6 @@ export interface IOrganizationUpdateDTO {
timezone: string; timezone: string;
fiscalYear: string; fiscalYear: string;
industry: string; industry: string;
taxNumber: string;
} }
export interface IOrganizationBuildEventPayload { export interface IOrganizationBuildEventPayload {

View File

@@ -10,7 +10,7 @@ export interface ITableCell {
} }
export type ITableRow = { export type ITableRow = {
cells: ITableCell[]; rows: ITableCell[];
}; };
export interface ITableColumn { export interface ITableColumn {
@@ -28,13 +28,4 @@ export interface ITable {
export interface ITableColumnAccessor { export interface ITableColumnAccessor {
key: string; key: string;
accessor: string; accessor: string;
} }
export interface ITableData {
columns: ITableColumn[];
rows: ITableRow[];
}
export interface IFinancialTable {
table: ITableData;
}

View File

@@ -36,7 +36,6 @@ export interface ITaxRateCreatedPayload {
} }
export interface ITaxRateEditingPayload { export interface ITaxRateEditingPayload {
oldTaxRate: ITaxRate;
editTaxRateDTO: IEditTaxRateDTO; editTaxRateDTO: IEditTaxRateDTO;
tenantId: number; tenantId: number;
trx: Knex.Transaction; trx: Knex.Transaction;

View File

@@ -1,4 +1,3 @@
import { IFinancialTable, ITableData } from './Table';
import { import {
ITransactionsByContactsAmount, ITransactionsByContactsAmount,
ITransactionsByContactsTransaction, ITransactionsByContactsTransaction,
@@ -27,11 +26,6 @@ export type ITransactionsByCustomersData = ITransactionsByCustomersCustomer[];
export interface ITransactionsByCustomersStatement { export interface ITransactionsByCustomersStatement {
data: ITransactionsByCustomersData; data: ITransactionsByCustomersData;
query: ITransactionsByCustomersFilter;
}
export interface ITransactionsByCustomersTable extends IFinancialTable {
query: ITransactionsByCustomersFilter;
} }
export interface ITransactionsByCustomersService { export interface ITransactionsByCustomersService {

View File

@@ -1,4 +1,3 @@
import { IFinancialTable } from './Table';
import { import {
ITransactionsByContactsAmount, ITransactionsByContactsAmount,
ITransactionsByContactsTransaction, ITransactionsByContactsTransaction,
@@ -35,7 +34,3 @@ export interface ITransactionsByVendorsService {
filter: ITransactionsByVendorsFilter filter: ITransactionsByVendorsFilter
): Promise<ITransactionsByVendorsStatement>; ): Promise<ITransactionsByVendorsStatement>;
} }
export interface ITransactionsByVendorTable extends IFinancialTable {
query: ITransactionsByVendorsFilter;
}

View File

@@ -1,5 +1,4 @@
import { INumberFormatQuery } from './FinancialStatements'; import { INumberFormatQuery } from './FinancialStatements';
import { IFinancialTable } from './Table';
export interface ITrialBalanceSheetQuery { export interface ITrialBalanceSheetQuery {
fromDate: Date | string; fromDate: Date | string;
@@ -34,7 +33,6 @@ export interface ITrialBalanceAccount extends ITrialBalanceTotal {
id: number; id: number;
parentAccountId: number; parentAccountId: number;
name: string; name: string;
formattedName: string;
code: string; code: string;
accountNormal: string; accountNormal: string;
} }
@@ -49,8 +47,3 @@ export interface ITrialBalanceStatement {
query: ITrialBalanceSheetQuery; query: ITrialBalanceSheetQuery;
meta: ITrialBalanceSheetMeta; meta: ITrialBalanceSheetMeta;
} }
export interface ITrialBalanceSheetTable extends IFinancialTable {
meta: ITrialBalanceSheetMeta;
query: ITrialBalanceSheetQuery;
}

View File

@@ -1,9 +1,8 @@
import { INumberFormatQuery } from './FinancialStatements'; import { INumberFormatQuery } from './FinancialStatements';
import { IFinancialTable } from './Table';
export interface IVendorBalanceSummaryQuery { export interface IVendorBalanceSummaryQuery {
asDate: Date; asDate: Date;
vendorsIds: number[]; vendorsIds: number[],
numberFormat: INumberFormatQuery; numberFormat: INumberFormatQuery;
percentageColumn: boolean; percentageColumn: boolean;
noneTransactions: boolean; noneTransactions: boolean;
@@ -46,10 +45,6 @@ export interface IVendorBalanceSummaryStatement {
export interface IVendorBalanceSummaryService { export interface IVendorBalanceSummaryService {
vendorBalanceSummary( vendorBalanceSummary(
tenantId: number, tenantId: number,
query: IVendorBalanceSummaryQuery query: IVendorBalanceSummaryQuery,
): Promise<IVendorBalanceSummaryStatement>; ): Promise<IVendorBalanceSummaryStatement>;
} }
export interface IVendorBalanceSummaryTable extends IFinancialTable {
query: IVendorBalanceSummaryQuery;
}

View File

@@ -1,26 +0,0 @@
import { ChromiumRoute, LibreOfficeRoute, PdfEngineRoute } from './_types';
export class Chromiumly {
public static readonly GOTENBERG_ENDPOINT = process.env.GOTENBERG_URL || '';
public static readonly CHROMIUM_PATH = 'forms/chromium/convert';
public static readonly PDF_ENGINES_PATH = 'forms/pdfengines';
public static readonly LIBRE_OFFICE_PATH = 'forms/libreoffice';
public static readonly GOTENBERG_DOCS_ENDPOINT =
process.env.GOTENBERG_DOCS_URL || '';
public static readonly CHROMIUM_ROUTES = {
url: ChromiumRoute.URL,
html: ChromiumRoute.HTML,
markdown: ChromiumRoute.MARKDOWN,
};
public static readonly PDF_ENGINE_ROUTES = {
merge: PdfEngineRoute.MERGE,
};
public static readonly LIBRE_OFFICE_ROUTES = {
convert: LibreOfficeRoute.CONVERT,
};
}

View File

@@ -1,66 +0,0 @@
import FormData from 'form-data';
import { GotenbergUtils } from './GotenbergUtils';
import { PageProperties } from './_types';
export class ConverterUtils {
public static injectPageProperties(
data: FormData,
pageProperties: PageProperties
): void {
if (pageProperties.size) {
GotenbergUtils.assert(
pageProperties.size.width >= 1.0 && pageProperties.size.height >= 1.5,
'size is smaller than the minimum printing requirements (i.e. 1.0 x 1.5 in)'
);
data.append('paperWidth', pageProperties.size.width);
data.append('paperHeight', pageProperties.size.height);
}
if (pageProperties.margins) {
GotenbergUtils.assert(
pageProperties.margins.top >= 0 &&
pageProperties.margins.bottom >= 0 &&
pageProperties.margins.left >= 0 &&
pageProperties.margins.left >= 0,
'negative margins are not allowed'
);
data.append('marginTop', pageProperties.margins.top);
data.append('marginBottom', pageProperties.margins.bottom);
data.append('marginLeft', pageProperties.margins.left);
data.append('marginRight', pageProperties.margins.right);
}
if (pageProperties.preferCssPageSize) {
data.append(
'preferCssPageSize',
String(pageProperties.preferCssPageSize)
);
}
if (pageProperties.printBackground) {
data.append('printBackground', String(pageProperties.printBackground));
}
if (pageProperties.landscape) {
data.append('landscape', String(pageProperties.landscape));
}
if (pageProperties.scale) {
GotenbergUtils.assert(
pageProperties.scale >= 0.1 && pageProperties.scale <= 2.0,
'scale is outside of [0.1 - 2] range'
);
data.append('scale', pageProperties.scale);
}
if (pageProperties.nativePageRanges) {
GotenbergUtils.assert(
pageProperties.nativePageRanges.from > 0 &&
pageProperties.nativePageRanges.to > 0 &&
pageProperties.nativePageRanges.to >=
pageProperties.nativePageRanges.from,
'page ranges syntax error'
);
data.append(
'nativePageRanges',
`${pageProperties.nativePageRanges.from}-${pageProperties.nativePageRanges.to}`
);
}
}
}

View File

@@ -1,10 +0,0 @@
import { Chromiumly } from './Chromiumly';
import { ChromiumRoute } from './_types';
export abstract class Converter {
readonly endpoint: string;
constructor(route: ChromiumRoute) {
this.endpoint = `${Chromiumly.GOTENBERG_ENDPOINT}/${Chromiumly.CHROMIUM_PATH}/${Chromiumly.CHROMIUM_ROUTES[route]}`;
}
}

View File

@@ -1,24 +0,0 @@
import FormData from 'form-data';
import Axios from 'axios';
export class GotenbergUtils {
public static assert(condition: boolean, message: string): asserts condition {
if (!condition) {
throw new Error(message);
}
}
public static async fetch(endpoint: string, data: FormData): Promise<Buffer> {
try {
const response = await Axios.post(endpoint, data, {
headers: {
...data.getHeaders(),
},
responseType: 'arraybuffer', // This ensures you get a Buffer bac
});
return response.data;
} catch (error) {
console.error(error);
}
}
}

View File

@@ -1,38 +0,0 @@
import { constants, createReadStream, PathLike, promises } from 'fs';
import FormData from 'form-data';
import { GotenbergUtils } from './GotenbergUtils';
import { IConverter, PageProperties } from './_types';
import { PdfFormat, ChromiumRoute } from './_types';
import { ConverterUtils } from './ConvertUtils';
import { Converter } from './Converter';
export class HtmlConverter extends Converter implements IConverter {
constructor() {
super(ChromiumRoute.HTML);
}
async convert({
html,
properties,
pdfFormat,
}: {
html: PathLike;
properties?: PageProperties;
pdfFormat?: PdfFormat;
}): Promise<Buffer> {
try {
await promises.access(html, constants.R_OK);
const data = new FormData();
if (pdfFormat) {
data.append('pdfFormat', pdfFormat);
}
data.append('index.html', createReadStream(html));
if (properties) {
ConverterUtils.injectPageProperties(data, properties);
}
return GotenbergUtils.fetch(this.endpoint, data);
} catch (error) {
throw error;
}
}
}

View File

@@ -1,38 +0,0 @@
import FormData from 'form-data';
import { IConverter, PageProperties, PdfFormat, ChromiumRoute } from './_types';
import { ConverterUtils } from './ConvertUtils';
import { Converter } from './Converter';
import { GotenbergUtils } from './GotenbergUtils';
export class UrlConverter extends Converter implements IConverter {
constructor() {
super(ChromiumRoute.URL);
}
async convert({
url,
properties,
pdfFormat,
}: {
url: string;
properties?: PageProperties;
pdfFormat?: PdfFormat;
}): Promise<Buffer> {
try {
const _url = new URL(url);
const data = new FormData();
if (pdfFormat) {
data.append('pdfFormat', pdfFormat);
}
data.append('url', _url.href);
if (properties) {
ConverterUtils.injectPageProperties(data, properties);
}
return GotenbergUtils.fetch(this.endpoint, data);
} catch (error) {
throw error;
}
}
}

View File

@@ -1,51 +0,0 @@
import { PathLike } from 'fs';
export type PageSize = {
width: number; // Paper width, in inches (default 8.5)
height: number; //Paper height, in inches (default 11)
};
export type PageMargins = {
top: number; // Top margin, in inches (default 0.39)
bottom: number; // Bottom margin, in inches (default 0.39)
left: number; // Left margin, in inches (default 0.39)
right: number; // Right margin, in inches (default 0.39)
};
export type PageProperties = {
size?: PageSize;
margins?: PageMargins;
preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
printBackground?: boolean; // Print the background graphics (default false)
landscape?: boolean; // Set the paper orientation to landscape (default false)
scale?: number; // The scale of the page rendering (default 1.0)
nativePageRanges?: { from: number; to: number }; // Page ranges to print
};
export interface IConverter {
convert({
...args
}: {
[x: string]: string | PathLike | PageProperties | PdfFormat;
}): Promise<Buffer>;
}
export enum PdfFormat {
A_1a = 'PDF/A-1a',
A_2b = 'PDF/A-2b',
A_3b = 'PDF/A-3b',
}
export enum ChromiumRoute {
URL = 'url',
HTML = 'html',
MARKDOWN = 'markdown',
}
export enum PdfEngineRoute {
MERGE = 'merge',
}
export enum LibreOfficeRoute {
CONVERT = 'convert',
}

View File

@@ -1,134 +0,0 @@
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<string, string>}
*/
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<Buffer>}
*/
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;
};
}

View File

@@ -81,9 +81,6 @@ import { ProjectBillableBillSubscriber } from '@/services/Projects/Projects/Proj
import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber'; import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber';
import { SaleInvoiceTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/SaleInvoiceTaxRateValidateSubscriber'; import { SaleInvoiceTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/SaleInvoiceTaxRateValidateSubscriber';
import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteInvoiceTaxTransactionsSubscriber'; import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteInvoiceTaxTransactionsSubscriber';
import { BillTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/BillTaxRateValidateSubscriber';
import { WriteBillTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteBillTaxTransactionsSubscriber';
import { SyncItemTaxRateOnEditTaxSubscriber } from '@/services/TaxRates/SyncItemTaxRateOnEditTaxSubscriber';
export default () => { export default () => {
return new EventPublisher(); return new EventPublisher();
@@ -191,14 +188,8 @@ export const susbcribers = () => {
ProjectBillableExpensesSubscriber, ProjectBillableExpensesSubscriber,
ProjectBillableBillSubscriber, ProjectBillableBillSubscriber,
// Tax Rates - Sale Invoice // Tax Rates
SaleInvoiceTaxRateValidateSubscriber, SaleInvoiceTaxRateValidateSubscriber,
WriteInvoiceTaxTransactionsSubscriber, WriteInvoiceTaxTransactionsSubscriber,
// Tax Rates - Bills
BillTaxRateValidateSubscriber,
WriteBillTaxTransactionsSubscriber,
SyncItemTaxRateOnEditTaxSubscriber
]; ];
}; };

View File

@@ -1,5 +1,4 @@
import { json, Request, Response, NextFunction } from 'express'; import { json, Request, Response, NextFunction } from 'express';
import express from 'express';
import helmet from 'helmet'; import helmet from 'helmet';
import boom from 'express-boom'; import boom from 'express-boom';
import errorHandler from 'errorhandler'; import errorHandler from 'errorhandler';
@@ -43,8 +42,6 @@ export default ({ app }) => {
// Middleware for intercepting and transforming json responses. // Middleware for intercepting and transforming json responses.
app.use(JSONResponseTransformer(snakecaseResponseTransformer)); app.use(JSONResponseTransformer(snakecaseResponseTransformer));
app.use('/public', express.static(path.join(global.__storage_dir)));
// Handle multi-media requests. // Handle multi-media requests.
app.use( app.use(
fileUpload({ fileUpload({

View File

@@ -60,7 +60,6 @@ import Time from 'models/Time';
import Task from 'models/Task'; import Task from 'models/Task';
import TaxRate from 'models/TaxRate'; import TaxRate from 'models/TaxRate';
import TaxRateTransaction from 'models/TaxRateTransaction'; import TaxRateTransaction from 'models/TaxRateTransaction';
import Attachment from 'models/Attachment';
export default (knex) => { export default (knex) => {
const models = { const models = {
@@ -124,7 +123,6 @@ export default (knex) => {
Task, Task,
TaxRate, TaxRate,
TaxRateTransaction, TaxRateTransaction,
Attachment
}; };
return mapValues(models, (model) => model.bindKnex(knex)); return mapValues(models, (model) => model.bindKnex(knex));
}; };

View File

@@ -0,0 +1,640 @@
{
"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": "تم النقل"
}

View File

@@ -0,0 +1,641 @@
{
"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.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"
}

View File

@@ -1,23 +0,0 @@
import { mixin } from 'objection';
import TenantModel from 'models/TenantModel';
import ModelSetting from './ModelSetting';
import ModelSearchable from './ModelSearchable';
export default class Attachment extends mixin(TenantModel, [
ModelSetting,
ModelSearchable,
]) {
/**
* Table name
*/
static get tableName() {
return 'storage';
}
/**
* Model timestamps.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
}

View File

@@ -13,109 +13,6 @@ export default class Bill extends mixin(TenantModel, [
CustomViewBaseModel, CustomViewBaseModel,
ModelSearchable, ModelSearchable,
]) { ]) {
public amount: number;
public paymentAmount: number;
public landedCostAmount: number;
public allocatedCostAmount: number;
public isInclusiveTax: boolean;
public taxAmountWithheld: number;
public exchangeRate: number;
/**
* Timestamps columns.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/**
* Virtual attributes.
*/
static get virtualAttributes() {
return [
'balance',
'dueAmount',
'isOpen',
'isPartiallyPaid',
'isFullyPaid',
'isPaid',
'remainingDays',
'overdueDays',
'isOverdue',
'unallocatedCostAmount',
'localAmount',
'localAllocatedCostAmount',
'billableAmount',
'amountLocal',
'subtotal',
'subtotalLocal',
'subtotalExludingTax',
'taxAmountWithheldLocal',
'total',
'totalLocal',
];
}
/**
* Invoice amount in base currency.
* @returns {number}
*/
get amountLocal() {
return this.amount * this.exchangeRate;
}
/**
* Subtotal. (Tax inclusive) if the tax inclusive is enabled.
* @returns {number}
*/
get subtotal() {
return this.amount;
}
/**
* Subtotal in base currency. (Tax inclusive) if the tax inclusive is enabled.
* @returns {number}
*/
get subtotalLocal() {
return this.amountLocal;
}
/**
* Sale invoice amount excluding tax.
* @returns {number}
*/
get subtotalExcludingTax() {
return this.isInclusiveTax
? this.subtotal - this.taxAmountWithheld
: this.subtotal;
}
/**
* Tax amount withheld in base currency.
* @returns {number}
*/
get taxAmountWithheldLocal() {
return this.taxAmountWithheld * this.exchangeRate;
}
/**
* Invoice total. (Tax included)
* @returns {number}
*/
get total() {
return this.isInclusiveTax
? this.subtotal
: this.subtotal + this.taxAmountWithheld;
}
/**
* Invoice total in local currency. (Tax included)
* @returns {number}
*/
get totalLocal() {
return this.total * this.exchangeRate;
}
/** /**
* Table name * Table name
*/ */
@@ -261,13 +158,40 @@ export default class Bill extends mixin(TenantModel, [
}; };
} }
/**
* Timestamps columns.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/**
* Virtual attributes.
*/
static get virtualAttributes() {
return [
'balance',
'dueAmount',
'isOpen',
'isPartiallyPaid',
'isFullyPaid',
'isPaid',
'remainingDays',
'overdueDays',
'isOverdue',
'unallocatedCostAmount',
'localAmount',
'localAllocatedCostAmount',
'billableAmount',
];
}
/** /**
* Invoice amount in organization base currency. * Invoice amount in organization base currency.
* @deprecated
* @returns {number} * @returns {number}
*/ */
get localAmount() { get localAmount() {
return this.amountLocal; return this.amount * this.exchangeRate;
} }
/** /**
@@ -307,7 +231,7 @@ export default class Bill extends mixin(TenantModel, [
* @return {number} * @return {number}
*/ */
get dueAmount() { get dueAmount() {
return Math.max(this.total - this.balance, 0); return Math.max(this.amount - this.balance, 0);
} }
/** /**
@@ -323,7 +247,7 @@ export default class Bill extends mixin(TenantModel, [
* @return {boolean} * @return {boolean}
*/ */
get isPartiallyPaid() { get isPartiallyPaid() {
return this.dueAmount !== this.total && this.dueAmount > 0; return this.dueAmount !== this.amount && this.dueAmount > 0;
} }
/** /**
@@ -384,7 +308,7 @@ export default class Bill extends mixin(TenantModel, [
* Retrieves the calculated amount which have not been invoiced. * Retrieves the calculated amount which have not been invoiced.
*/ */
get billableAmount() { get billableAmount() {
return Math.max(this.total - this.invoicedAmount, 0); return Math.max(this.amount - this.invoicedAmount, 0);
} }
/** /**
@@ -402,7 +326,6 @@ export default class Bill extends mixin(TenantModel, [
const ItemEntry = require('models/ItemEntry'); const ItemEntry = require('models/ItemEntry');
const BillLandedCost = require('models/BillLandedCost'); const BillLandedCost = require('models/BillLandedCost');
const Branch = require('models/Branch'); const Branch = require('models/Branch');
const TaxRateTransaction = require('models/TaxRateTransaction');
return { return {
vendor: { vendor: {
@@ -450,21 +373,6 @@ export default class Bill extends mixin(TenantModel, [
to: 'branches.id', to: 'branches.id',
}, },
}, },
/**
* Bill may has associated tax rate transactions.
*/
taxes: {
relation: Model.HasManyRelation,
modelClass: TaxRateTransaction.default,
join: {
from: 'bills.id',
to: 'tax_rate_transactions.referenceId',
},
filter(builder) {
builder.where('reference_type', 'Bill');
},
},
}; };
} }

View File

@@ -65,7 +65,6 @@ export default class Item extends mixin(TenantModel, [
const ItemEntry = require('models/ItemEntry'); const ItemEntry = require('models/ItemEntry');
const WarehouseTransferEntry = require('models/WarehouseTransferEntry'); const WarehouseTransferEntry = require('models/WarehouseTransferEntry');
const InventoryAdjustmentEntry = require('models/InventoryAdjustmentEntry'); const InventoryAdjustmentEntry = require('models/InventoryAdjustmentEntry');
const TaxRate = require('models/TaxRate');
return { return {
/** /**
@@ -179,35 +178,11 @@ export default class Item extends mixin(TenantModel, [
to: 'media.id', to: 'media.id',
}, },
}, },
/**
* Item may has sell tax rate.
*/
sellTaxRate: {
relation: Model.BelongsToOneRelation,
modelClass: TaxRate.default,
join: {
from: 'items.sellTaxRateId',
to: 'tax_rates.id',
},
},
/**
* Item may has purchase tax rate.
*/
purchaseTaxRate: {
relation: Model.BelongsToOneRelation,
modelClass: TaxRate.default,
join: {
from: 'items.purchaseTaxRateId',
to: 'tax_rates.id',
},
},
}; };
} }
/** /**
* *
*/ */
static get secureDeleteRelations() { static get secureDeleteRelations() {
return [ return [

View File

@@ -99,13 +99,6 @@ export default class ItemEntry extends TenantModel {
: getExlusiveTaxAmount(this.amount, this.taxRate); : getExlusiveTaxAmount(this.amount, this.taxRate);
} }
static calcAmount(itemEntry) {
const { discount, quantity, rate } = itemEntry;
const total = quantity * rate;
return discount ? total - total * discount * 0.01 : total;
}
/** /**
* Item entry relations. * Item entry relations.
*/ */

View File

@@ -1,5 +1,5 @@
import moment from 'moment'; import moment from 'moment';
import { defaultTo, sumBy, uniqBy } from 'lodash'; import { defaultTo, uniqBy } from 'lodash';
import { IAccountTransaction, ILedger, ILedgerEntry } from '@/interfaces'; import { IAccountTransaction, ILedger, ILedgerEntry } from '@/interfaces';
export default class Ledger implements ILedger { export default class Ledger implements ILedger {
@@ -49,15 +49,6 @@ export default class Ledger implements ILedger {
return this.filter((entry) => entry.accountId === accountId); return this.filter((entry) => entry.accountId === accountId);
} }
/**
* Filters entries by the given accounts ids then returns a new ledger.
* @param {number[]} accountIds
* @returns {ILedger}
*/
public whereAccountsIds(accountIds: number[]): ILedger {
return this.filter((entry) => accountIds.indexOf(entry.accountId) !== -1);
}
/** /**
* Filters entries that before or same the given date and returns a new ledger. * Filters entries that before or same the given date and returns a new ledger.
* @param {Date|string} fromDate * @param {Date|string} fromDate
@@ -139,22 +130,6 @@ export default class Ledger implements ILedger {
return closingBalance; return closingBalance;
} }
/**
* Retrieves the closing credit of the entries.
* @returns {number}
*/
public getClosingCredit(): number {
return sumBy(this.entries, 'credit');
}
/**
* Retrieves the closing debit of the entries.
* @returns {number}
*/
public getClosingDebit(): number {
return sumBy(this.entries, 'debit');
}
/** /**
* Retrieve the closing balance of the entries. * Retrieve the closing balance of the entries.
* @returns {number} * @returns {number}

View File

@@ -1,75 +0,0 @@
import { Inject, Service } from 'typedi';
import path from 'path';
import { promises as fs } from 'fs';
import { PageProperties, PdfFormat } from '@/lib/Chromiumly/_types';
import { UrlConverter } from '@/lib/Chromiumly/UrlConvert';
import HasTenancyService from '../Tenancy/TenancyService';
import { Chromiumly } from '@/lib/Chromiumly/Chromiumly';
import { PDF_FILE_EXPIRE_IN, getPdfFilesStorageDir } from './utils';
@Service()
export class ChromiumlyHtmlConvert {
@Inject()
private tenancy: HasTenancyService;
/**
* Write HTML content to temporary file.
* @param {number} tenantId - Tenant id.
* @param {string} content - HTML content.
* @returns {Promise<[string, () => Promise<void>]>}
*/
async writeTempHtmlFile(
tenantId: number,
content: string
): Promise<[string, () => Promise<void>]> {
const { Attachment } = this.tenancy.models(tenantId);
const filename = `document-${Date.now()}.html`;
const storageDir = getPdfFilesStorageDir(filename);
const filePath = path.join(global.__storage_dir, storageDir);
await fs.writeFile(filePath, content);
await Attachment.query().insert({
key: filename,
path: storageDir,
expire_in: PDF_FILE_EXPIRE_IN, // ms
extension: 'html',
});
const cleanup = async () => {
await fs.unlink(filePath);
await Attachment.query().where('key', filename).delete();
};
return [filename, cleanup];
}
/**
* Converts the given HTML content to PDF.
* @param {string} html
* @param {PageProperties} properties
* @param {PdfFormat} pdfFormat
* @returns {Array<Buffer>}
*/
async convert(
tenantId: number,
html: string,
properties?: PageProperties,
pdfFormat?: PdfFormat
): Promise<Buffer> {
const [filename, cleanupTempFile] = await this.writeTempHtmlFile(
tenantId,
html
);
const fileDir = getPdfFilesStorageDir(filename);
const url = path.join(Chromiumly.GOTENBERG_DOCS_ENDPOINT, fileDir);
const urlConverter = new UrlConverter();
const buffer = await urlConverter.convert({
url,
properties,
pdfFormat,
});
await cleanupTempFile();
return buffer;
}
}

View File

@@ -1,25 +0,0 @@
import { Inject, Service } from 'typedi';
import { PageProperties, PdfFormat } from '@/lib/Chromiumly/_types';
import { ChromiumlyHtmlConvert } from './ChromiumlyHtmlConvert';
@Service()
export class ChromiumlyTenancy {
@Inject()
private htmlConvert: ChromiumlyHtmlConvert;
/**
* Converts the given HTML content to PDF.
* @param {string} content
* @param {PageProperties} properties
* @param {PdfFormat} pdfFormat
* @returns {Promise<Buffer>}
*/
public convertHtmlContent(
tenantId: number,
content: string,
properties?: PageProperties,
pdfFormat?: PdfFormat
) {
return this.htmlConvert.convert(tenantId, content, properties, pdfFormat);
}
}

View File

@@ -1,8 +0,0 @@
import path from 'path';
export const PDF_FILE_SUB_DIR = '/pdf';
export const PDF_FILE_EXPIRE_IN = 40; // ms
export const getPdfFilesStorageDir = (filename: string) => {
return path.join(PDF_FILE_SUB_DIR, filename);
}

View File

@@ -1,7 +1,5 @@
import { Transformer } from '@/lib/Transformer/Transformer'; import { Transformer } from '@/lib/Transformer/Transformer';
import { formatNumber } from 'utils'; import { formatNumber } from 'utils';
import { ItemEntryTransformer } from '../Sales/Invoices/ItemEntryTransformer';
import { ICreditNote } from '@/interfaces';
export class CreditNoteTransformer extends Transformer { export class CreditNoteTransformer extends Transformer {
/** /**
@@ -13,8 +11,7 @@ export class CreditNoteTransformer extends Transformer {
'formattedCreditsRemaining', 'formattedCreditsRemaining',
'formattedCreditNoteDate', 'formattedCreditNoteDate',
'formattedAmount', 'formattedAmount',
'formattedCreditsUsed', 'formattedCreditsUsed'
'entries',
]; ];
}; };
@@ -54,20 +51,9 @@ export class CreditNoteTransformer extends Transformer {
* @param {ICreditNote} credit * @param {ICreditNote} credit
* @returns {string} * @returns {string}
*/ */
protected formattedCreditsUsed = (credit) => { protected formattedCreditsUsed = (credit) => {
return formatNumber(credit.creditsUsed, { return formatNumber(credit.creditsUsed, {
currencyCode: credit.currencyCode, currencyCode: credit.currencyCode,
}); });
}; };
/**
* Retrieves the entries of the credit note.
* @param {ICreditNote} credit
* @returns {}
*/
protected entries = (credit) => {
return this.item(credit.entries, new ItemEntryTransformer(), {
currencyCode: credit.currencyCode,
});
};
} }

View File

@@ -1,29 +1,37 @@
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import { ChromiumlyTenancy } from '../ChromiumlyTenancy/ChromiumlyTenancy'; import PdfService from '@/services/PDF/PdfService';
import { TemplateInjectable } from '../TemplateInjectable/TemplateInjectable'; import { templateRender } from 'utils';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { Tenant } from '@/system/models';
@Service() @Service()
export default class GetCreditNotePdf { export default class GetCreditNotePdf {
@Inject() @Inject()
private chromiumlyTenancy: ChromiumlyTenancy; pdfService: PdfService;
@Inject() @Inject()
private templateInjectable: TemplateInjectable; tenancy: HasTenancyService;
/** /**
* Retrieve sale invoice pdf content. * Retrieve sale invoice pdf content.
* @param {} saleInvoice - * @param {} saleInvoice -
*/ */
public async getCreditNotePdf(tenantId: number, creditNote) { async getCreditNotePdf(tenantId: number, creditNote) {
const htmlContent = await this.templateInjectable.render( const i18n = this.tenancy.i18n(tenantId);
tenantId,
'modules/credit-note-standard', const organization = await Tenant.query()
{ .findById(tenantId)
creditNote, .withGraphFetched('metadata');
}
); const htmlContent = templateRender('modules/credit-note-standard', {
return this.chromiumlyTenancy.convertHtmlContent(tenantId, htmlContent, { organization,
margins: { top: 0, bottom: 0, left: 0, right: 0 }, organizationName: organization.metadata.name,
organizationEmail: organization.metadata.email,
creditNote,
...i18n,
}); });
const pdfContent = await this.pdfService.pdfDocument(htmlContent);
return pdfContent;
} }
} }

View File

@@ -1,53 +0,0 @@
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);
}
}

View File

@@ -1,43 +0,0 @@
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<Buffer>}
*/
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<Buffer>}
*/
public async csv(
tenantId: number,
query: IAPAgingSummaryQuery
): Promise<string> {
const table = await this.APAgingSummaryTable.table(tenantId, query);
const tableSheet = new TableSheet(table.table);
const tableCsv = tableSheet.convertToCSV();
return tableCsv;
}
}

View File

@@ -1,13 +1,14 @@
import moment from 'moment'; import moment from 'moment';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import { isEmpty } from 'lodash';
import { IAPAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces'; import { IAPAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService'; import TenancyService from '@/services/Tenancy/TenancyService';
import APAgingSummarySheet from './APAgingSummarySheet'; import APAgingSummarySheet from './APAgingSummarySheet';
import { Tenant } from '@/system/models'; import { Tenant } from '@/system/models';
import { isEmpty } from 'lodash';
import APAgingSummaryTable from './APAgingSummaryTable';
@Service() @Service()
export class APAgingSummaryService { export default class PayableAgingSummaryService {
@Inject() @Inject()
tenancy: TenancyService; tenancy: TenancyService;
@@ -17,7 +18,7 @@ export class APAgingSummaryService {
/** /**
* Default report query. * Default report query.
*/ */
private get defaultQuery(): IAPAgingSummaryQuery { get defaultQuery(): IAPAgingSummaryQuery {
return { return {
asDate: moment().format('YYYY-MM-DD'), asDate: moment().format('YYYY-MM-DD'),
agingDaysBefore: 30, agingDaysBefore: 30,
@@ -118,4 +119,21 @@ export class APAgingSummaryService {
meta: this.reportMetadata(tenantId), 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,
};
}
} }

View File

@@ -1,36 +0,0 @@
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<IAPAgingSummaryTable>}
*/
public async table(
tenantId: number,
query: IAPAgingSummaryQuery
): Promise<IAPAgingSummaryTable> {
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,
};
}
}

View File

@@ -1,53 +0,0 @@
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);
}
}

View File

@@ -1,46 +0,0 @@
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<Buffer>}
*/
public async xlsx(
tenantId: number,
query: IARAgingSummaryQuery
): Promise<Buffer> {
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<string>}
*/
public async csv(
tenantId: number,
query: IARAgingSummaryQuery
): Promise<string> {
const table = await this.ARAgingSummaryTable.table(tenantId, query);
const tableSheet = new TableSheet(table.table);
const tableCsv = tableSheet.convertToCSV();
return tableCsv;
}
}

View File

@@ -5,6 +5,7 @@ import { IARAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService'; import TenancyService from '@/services/Tenancy/TenancyService';
import ARAgingSummarySheet from './ARAgingSummarySheet'; import ARAgingSummarySheet from './ARAgingSummarySheet';
import { Tenant } from '@/system/models'; import { Tenant } from '@/system/models';
import ARAgingSummaryTable from './ARAgingSummaryTable';
@Service() @Service()
export default class ARAgingSummaryService { export default class ARAgingSummaryService {
@@ -117,4 +118,21 @@ export default class ARAgingSummaryService {
meta: this.reportMetadata(tenantId), 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,
};
}
} }

View File

@@ -1,36 +0,0 @@
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<IARAgingSummaryTable>}
*/
public async table(
tenantId: number,
query: IARAgingSummaryQuery
): Promise<IARAgingSummaryTable> {
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,
};
}
}

View File

@@ -1,10 +1,18 @@
import * as R from 'ramda'; import * as R from 'ramda';
import { defaultTo, isEmpty, sumBy } from 'lodash';
import FinancialSheet from '../FinancialSheet'; import FinancialSheet from '../FinancialSheet';
import { import {
IBalanceSheetAggregateNode,
IBalanceSheetAccountNode,
BALANCE_SHEET_SCHEMA_NODE_TYPE,
IBalanceSheetQuery, IBalanceSheetQuery,
INumberFormatQuery, INumberFormatQuery,
IAccount,
IBalanceSheetSchemaNode, IBalanceSheetSchemaNode,
IBalanceSheetSchemaAggregateNode,
IBalanceSheetDataNode, IBalanceSheetDataNode,
IBalanceSheetSchemaAccountNode,
IBalanceSheetCommonNode,
} from '../../../interfaces'; } from '../../../interfaces';
import { BalanceSheetSchema } from './BalanceSheetSchema'; import { BalanceSheetSchema } from './BalanceSheetSchema';
import { BalanceSheetPercentage } from './BalanceSheetPercentage'; import { BalanceSheetPercentage } from './BalanceSheetPercentage';
@@ -16,14 +24,8 @@ import { FinancialSheetStructure } from '../FinancialSheetStructure';
import BalanceSheetRepository from './BalanceSheetRepository'; import BalanceSheetRepository from './BalanceSheetRepository';
import { BalanceSheetQuery } from './BalanceSheetQuery'; import { BalanceSheetQuery } from './BalanceSheetQuery';
import { BalanceSheetFiltering } from './BalanceSheetFiltering'; import { BalanceSheetFiltering } from './BalanceSheetFiltering';
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
import { BalanceSheetAggregators } from './BalanceSheetAggregators';
import { BalanceSheetAccounts } from './BalanceSheetAccounts';
export default class BalanceSheet extends R.compose( export default class BalanceSheet extends R.compose(
BalanceSheetAggregators,
BalanceSheetAccounts,
BalanceSheetNetIncome,
BalanceSheetFiltering, BalanceSheetFiltering,
BalanceSheetDatePeriods, BalanceSheetDatePeriods,
BalanceSheetComparsionPreviousPeriod, BalanceSheetComparsionPreviousPeriod,
@@ -51,9 +53,6 @@ export default class BalanceSheet extends R.compose(
*/ */
readonly baseCurrency: string; readonly baseCurrency: string;
/**
* Localization.
*/
readonly i18n: any; readonly i18n: any;
/** /**
@@ -78,18 +77,216 @@ export default class BalanceSheet extends R.compose(
} }
/** /**
* Parses report schema nodes. * Retrieve the accounts node of accounts types.
* @param {IBalanceSheetSchemaNode[]} schema * @param {string} accountsTypes
* @returns {IBalanceSheetDataNode[]} * @returns {IAccount[]}
*/ */
public parseSchemaNodes = ( private getAccountsByAccountTypes = (accountsTypes: string[]): IAccount[] => {
schema: IBalanceSheetSchemaNode[] const mapAccountsByTypes = R.map((accountType) =>
): IBalanceSheetDataNode[] => { defaultTo(this.repository.accountsByType.get(accountType), [])
);
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
};
/**
* Mappes the aggregate schema node type.
* @param {IBalanceSheetSchemaAggregateNode} node - Schema node.
* @return {IBalanceSheetAggregateNode}
*/
private reportSchemaAggregateNodeMapper = (
node: IBalanceSheetSchemaAggregateNode
): IBalanceSheetAggregateNode => {
const total = this.getTotalOfNodes(node.children);
return {
name: this.i18n.__(node.name),
id: node.id,
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
total: this.getTotalAmountMeta(total),
children: node.children,
};
};
/**
* Compose shema aggregate node of balance sheet schema.
* @param {IBalanceSheetSchemaAggregateNode} node
* @returns {IBalanceSheetSchemaAggregateNode}
*/
private schemaAggregateNodeCompose = (
node: IBalanceSheetSchemaAggregateNode
) => {
return R.compose( return R.compose(
this.aggregatesSchemaParser, this.aggregateNodeTotalMapper,
this.netIncomeSchemaParser, this.reportSchemaAggregateNodeMapper
this.accountsSchemaParser )(node);
)(schema) as IBalanceSheetDataNode[]; };
/**
* Mappes the account model to report account node.
* @param {IAccount} account
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountNodeMapper = (
account: IAccount
): IBalanceSheetAccountNode => {
const total = this.repository.totalAccountsLedger
.whereAccountId(account.id)
.getClosingBalance();
return {
id: account.id,
index: account.index,
name: account.name,
code: account.code,
total: this.getAmountMeta(total),
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT,
};
};
/**
*
* @param {IAccount} account
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountNodeComposer = (
account: IAccount
): IBalanceSheetAccountNode => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearAccountNodeComposer
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodAccountNodeComposer
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocAccountNodeDatePeriods
),
this.reportSchemaAccountNodeMapper
)(account);
};
/**
* Retrieve the total of the given nodes.
* @param {IBalanceSheetCommonNode[]} nodes
* @returns {number}
*/
private getTotalOfNodes = (nodes: IBalanceSheetCommonNode[]) => {
return sumBy(nodes, 'total.amount');
};
/**
* Retrieve the report accounts node by the given accounts types.
* @param {string[]} accountsTypes
* @returns {}
*/
private getAccountsNodesByAccountTypes = (accountsTypes: string[]) => {
const accounts = this.getAccountsByAccountTypes(accountsTypes);
return R.compose(R.map(this.reportSchemaAccountNodeComposer))(accounts);
};
/**
* Mappes the accounts schema node type.
* @param {IBalanceSheetSchemaNode} node - Schema node.
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountsNodeMapper = (
node: IBalanceSheetSchemaAccountNode
): IBalanceSheetAccountNode => {
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
const total = this.getTotalOfNodes(accounts);
return {
id: node.id,
name: this.i18n.__(node.name),
type: node.type,
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
children: accounts,
total: this.getTotalAmountMeta(total),
};
};
/**
* Compose account schema node to report node.
* @param {IBalanceSheetSchemaAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountsNodeComposer = (
node: IBalanceSheetSchemaAccountNode
): IBalanceSheetAccountNode => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearAggregateNodeComposer
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodAggregateNodeComposer
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocAccountsNodeDatePeriods
),
this.reportSchemaAccountsNodeMapper
)(node);
};
/**
* Mappes the given report schema node.
* @param {IBalanceSheetSchemaNode} node - Schema node.
* @return {IBalanceSheetDataNode}
*/
private reportSchemaNodeMapper = (
schemaNode: IBalanceSheetSchemaNode
): IBalanceSheetDataNode => {
return R.compose(
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
this.schemaAggregateNodeCompose
),
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
this.reportSchemaAccountsNodeComposer
)
)(schemaNode);
};
/**
* Mappes the report schema nodes.
* @param {IBalanceSheetSchemaNode[]} nodes -
* @return {IBalanceSheetStructureSection[]}
*/
private reportSchemaAccountNodesMapper = (
schemaNodes: IBalanceSheetSchemaNode[]
): IBalanceSheetDataNode[] => {
return this.mapNodesDeepReverse(schemaNodes, this.reportSchemaNodeMapper);
};
/**
* Sets total amount that calculated from node children.
* @param {IBalanceSheetSection} node
* @returns {IBalanceSheetDataNode}
*/
private aggregateNodeTotalMapper = (
node: IBalanceSheetDataNode
): IBalanceSheetDataNode => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearAggregateNodeComposer
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodAggregateNodeComposer
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocAggregateNodeDatePeriods
)
)(node);
}; };
/** /**
@@ -102,7 +299,7 @@ export default class BalanceSheet extends R.compose(
return R.compose( return R.compose(
this.reportFilterPlugin, this.reportFilterPlugin,
this.reportPercentageCompose, this.reportPercentageCompose,
this.parseSchemaNodes this.reportSchemaAccountNodesMapper
)(balanceSheetSchema); )(balanceSheetSchema);
}; };
} }

View File

@@ -1,182 +0,0 @@
import * as R from 'ramda';
import { defaultTo, toArray } from 'lodash';
import { FinancialSheetStructure } from '../FinancialSheetStructure';
import {
BALANCE_SHEET_SCHEMA_NODE_TYPE,
IAccount,
IBalanceSheetAccountNode,
IBalanceSheetAccountsNode,
IBalanceSheetDataNode,
IBalanceSheetSchemaAccountNode,
IBalanceSheetSchemaNode,
INumberFormatQuery,
} from '@/interfaces';
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
import { BalanceSheetFiltering } from './BalanceSheetFiltering';
import { BalanceSheetDatePeriods } from './BalanceSheetDatePeriods';
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
import { BalanceSheetSchema } from './BalanceSheetSchema';
import { BalanceSheetBase } from './BalanceSheetBase';
import { BalanceSheetQuery } from './BalanceSheetQuery';
export const BalanceSheetAccounts = (Base: any) =>
class extends R.compose(
BalanceSheetNetIncome,
BalanceSheetFiltering,
BalanceSheetDatePeriods,
BalanceSheetComparsionPreviousPeriod,
BalanceSheetComparsionPreviousYear,
BalanceSheetPercentage,
BalanceSheetSchema,
BalanceSheetBase,
FinancialSheetStructure
)(Base) {
/**
* Balance sheet query.
* @param {BalanceSheetQuery}
*/
readonly query: BalanceSheetQuery;
/**
* Balance sheet number format query.
* @param {INumberFormatQuery}
*/
readonly numberFormat: INumberFormatQuery;
/**
* Base currency of the organization.
* @param {string}
*/
readonly baseCurrency: string;
/**
* Localization.
*/
readonly i18n: any;
/**
* Retrieve the accounts node of accounts types.
* @param {string} accountsTypes
* @returns {IAccount[]}
*/
private getAccountsByAccountTypes = (
accountsTypes: string[]
): IAccount[] => {
const mapAccountsByTypes = R.map((accountType) =>
defaultTo(this.repository.accountsByType.get(accountType), [])
);
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
};
/**
* Mappes the account model to report account node.
* @param {IAccount} account
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountNodeMapper = (
account: IAccount
): IBalanceSheetAccountNode => {
const total = this.repository.totalAccountsLedger
.whereAccountId(account.id)
.getClosingBalance();
return {
id: account.id,
index: account.index,
name: account.name,
code: account.code,
total: this.getAmountMeta(total),
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNT,
};
};
/**
* Mappes the given account model to the balance sheet account node.
* @param {IAccount} account
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountNodeComposer = (
account: IAccount
): IBalanceSheetAccountNode => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearAccountNodeComposer
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodAccountNodeComposer
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocAccountNodeDatePeriods
),
this.reportSchemaAccountNodeMapper
)(account);
};
// -----------------------------
// - Accounts Node Praser
// -----------------------------
/**
* Retrieve the report accounts node by the given accounts types.
* @param {string[]} accountsTypes
* @returns {IBalanceSheetAccountNode[]}
*/
private getAccountsNodesByAccountTypes = (
accountsTypes: string[]
): IBalanceSheetAccountNode[] => {
const accounts = this.getAccountsByAccountTypes(accountsTypes);
return R.map(this.reportSchemaAccountNodeComposer, accounts);
};
/**
* Mappes the accounts schema node type.
* @param {IBalanceSheetSchemaNode} node - Schema node.
* @returns {IBalanceSheetAccountNode}
*/
private reportSchemaAccountsNodeMapper = (
node: IBalanceSheetSchemaAccountNode
): IBalanceSheetAccountsNode => {
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
const children = toArray(node?.children);
return {
id: node.id,
name: this.i18n.__(node.name),
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS,
children: [...accounts, ...children],
total: this.getTotalAmountMeta(0),
};
};
/**
* Mappes the given report schema node.
* @param {IBalanceSheetSchemaNode | IBalanceSheetDataNode} node - Schema node.
* @return {IBalanceSheetSchemaNode | IBalanceSheetDataNode}
*/
private reportAccountSchemaParser = (
node: IBalanceSheetSchemaNode | IBalanceSheetDataNode
): IBalanceSheetSchemaNode | IBalanceSheetDataNode => {
return R.compose(
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
this.reportSchemaAccountsNodeMapper
)
)(node);
};
/**
* Parses the report accounts schema nodes.
* @param {IBalanceSheetSchemaNode[]} nodes -
* @return {IBalanceSheetStructureSection[]}
*/
public accountsSchemaParser = (
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
return this.mapNodesDeepReverse(nodes, this.reportAccountSchemaParser);
};
};

View File

@@ -1,142 +0,0 @@
import * as R from 'ramda';
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
import { FinancialHorizTotals } from '../FinancialHorizTotals';
import { FinancialSheetStructure } from '../FinancialSheetStructure';
import {
BALANCE_SHEET_SCHEMA_NODE_TYPE,
IBalanceSheetAggregateNode,
IBalanceSheetDataNode,
IBalanceSheetSchemaAggregateNode,
IBalanceSheetSchemaNode,
INumberFormatQuery,
} from '@/interfaces';
import { BalanceSheetDatePeriods } from './BalanceSheetDatePeriods';
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
import { BalanceSheetPercentage } from './BalanceSheetPercentage';
import { BalanceSheetSchema } from './BalanceSheetSchema';
import { BalanceSheetBase } from './BalanceSheetBase';
import { BalanceSheetQuery } from './BalanceSheetQuery';
export const BalanceSheetAggregators = (Base: any) =>
class extends R.compose(
BalanceSheetDatePeriods,
BalanceSheetComparsionPreviousPeriod,
BalanceSheetComparsionPreviousYear,
BalanceSheetPercentage,
BalanceSheetSchema,
BalanceSheetBase,
FinancialSheetStructure
)(Base) {
/**
* Balance sheet query.
* @param {BalanceSheetQuery}
*/
readonly query: BalanceSheetQuery;
/**
* Balance sheet number format query.
* @param {INumberFormatQuery}
*/
readonly numberFormat: INumberFormatQuery;
/**
* Base currency of the organization.
* @param {string}
*/
readonly baseCurrency: string;
/**
* Localization.
*/
readonly i18n: any;
/**
* Sets total amount that calculated from node children.
* @param {IBalanceSheetSection} node
* @returns {IBalanceSheetDataNode}
*/
private aggregateNodeTotalMapper = (
node: IBalanceSheetDataNode
): IBalanceSheetDataNode => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearAggregateNodeComposer
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodAggregateNodeComposer
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocAggregateNodeDatePeriods
)
)(node);
};
/**
* Mappes the aggregate schema node type.
* @param {IBalanceSheetSchemaAggregateNode} node - Schema node.
* @return {IBalanceSheetAggregateNode}
*/
private reportSchemaAggregateNodeMapper = (
node: IBalanceSheetSchemaAggregateNode
): IBalanceSheetAggregateNode => {
const total = this.getTotalOfNodes(node.children);
return {
name: this.i18n.__(node.name),
id: node.id,
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
type: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE,
total: this.getTotalAmountMeta(total),
children: node.children,
};
};
/**
* Compose shema aggregate node of balance sheet schema.
* @param {IBalanceSheetSchemaAggregateNode} node
* @returns {IBalanceSheetSchemaAggregateNode}
*/
private schemaAggregateNodeCompose = (
node: IBalanceSheetSchemaAggregateNode
) => {
return R.compose(
this.aggregateNodeTotalMapper,
this.reportSchemaAggregateNodeMapper
)(node);
};
/**
* Mappes the given report schema node.
* @param {IBalanceSheetSchemaNode} node - Schema node.
* @return {IBalanceSheetDataNode}
*/
private reportAggregateSchemaParser = (
node: IBalanceSheetSchemaNode
): IBalanceSheetDataNode => {
return R.compose(
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
this.schemaAggregateNodeCompose
),
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
this.schemaAggregateNodeCompose
)
)(node);
};
/**
* Mappes the report schema nodes.
* @param {IBalanceSheetSchemaNode[]} nodes -
* @return {IBalanceSheetStructureSection[]}
*/
public aggregatesSchemaParser = (
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
return this.mapNodesDeepReverse(nodes, this.reportAggregateSchemaParser);
};
};

View File

@@ -1,57 +0,0 @@
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<IBalanceSheetStatement>}
*/
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<IBalanceSheetTable>}
*/
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<Buffer>}
*/
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<Buffer>}
*/
public csv(tenantId: number, query: IBalanceSheetQuery): Promise<string> {
return this.balanceSheetExport.csv(tenantId, query);
}
}

View File

@@ -6,7 +6,6 @@ import {
IBalanceSheetAggregateNode, IBalanceSheetAggregateNode,
IBalanceSheetTotal, IBalanceSheetTotal,
IBalanceSheetCommonNode, IBalanceSheetCommonNode,
IBalanceSheetComparsions,
} from '@/interfaces'; } from '@/interfaces';
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod'; import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
import { FinancialHorizTotals } from '../FinancialHorizTotals'; import { FinancialHorizTotals } from '../FinancialHorizTotals';

View File

@@ -156,14 +156,13 @@ export const BalanceSheetComparsionPreviousYear = (Base: any) =>
* @param {IBalanceSheetCommonNode} node * @param {IBalanceSheetCommonNode} node
* @returns {IBalanceSheetCommonNode} * @returns {IBalanceSheetCommonNode}
*/ */
public assocPreviousYearAggregateHorizNode = ( private assocPreviousYearAggregateHorizNode = (
node: IBalanceSheetCommonNode node: IBalanceSheetCommonNode
): IBalanceSheetCommonNode => { ) => {
const horizontalTotals = R.addIndex(R.map)( const horizontalTotals = R.addIndex(R.map)(
this.previousYearAggregateHorizNodeComposer(node), this.previousYearAggregateHorizNodeComposer(node),
node.horizontalTotals node.horizontalTotals
) as IBalanceSheetTotal[]; );
return R.assoc('horizontalTotals', horizontalTotals, node); return R.assoc('horizontalTotals', horizontalTotals, node);
}; };
@@ -259,11 +258,12 @@ export const BalanceSheetComparsionPreviousYear = (Base: any) =>
// ------------------------------ // ------------------------------
// # Horizontal Nodes - Aggregate. // # Horizontal Nodes - Aggregate.
// ------------------------------ // ------------------------------
/** /**
* Detarmines whether the given node has horizontal totals. * Detarmines whether the given node has horizontal totals.
* @param {IBalanceSheetCommonNode} node * @param {IBalanceSheetCommonNode} node
* @returns {boolean} * @returns {boolean}
*/ */
public isNodeHasHorizontalTotals = (node: IBalanceSheetCommonNode) => private isNodeHasHorizontalTotals = (node: IBalanceSheetCommonNode) =>
!isEmpty(node.horizontalTotals); !isEmpty(node.horizontalTotals);
}; };

Some files were not shown because too many files have changed in this diff Show More