Compare commits

..

1 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
dbd2f77d12 chore: update mysql docker container restart policy 2023-07-23 20:03:57 +02:00
689 changed files with 31087 additions and 41349 deletions

View File

@@ -42,24 +42,6 @@
"contributions": [ "contributions": [
"bug" "bug"
] ]
},
{
"login": "suhaibaffan",
"name": "Suhaib Affan",
"avatar_url": "https://avatars.githubusercontent.com/u/18115937?v=4",
"profile": "https://github.com/suhaibaffan",
"contributions": [
"code"
]
},
{
"login": "KalliopiPliogka",
"name": "Kalliopi Pliogka",
"avatar_url": "https://avatars.githubusercontent.com/u/81677549?v=4",
"profile": "https://github.com/KalliopiPliogka",
"contributions": [
"bug"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -47,6 +47,3 @@ AGENDASH_AUTH_PASSWORD=123123
SIGNUP_DISABLED=false SIGNUP_DISABLED=false
SIGNUP_ALLOWED_DOMAINS= SIGNUP_ALLOWED_DOMAINS=
SIGNUP_ALLOWED_EMAILS= SIGNUP_ALLOWED_EMAILS=
# API rate limit (points,duration,block duration).
API_RATE_LIMIT=120,60,600

13
.github/FUNDING.yml vendored
View File

@@ -1,13 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: Bigcapital # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

7
.gitignore vendored
View File

@@ -1,9 +1,4 @@
node_modules/ node_modules/
data
# Docker volumes data directory
/data
# Production env file
.env .env
test-results/ test-results/

View File

@@ -2,45 +2,6 @@
All notable changes to Bigcapital server-side will be in this file. All notable changes to Bigcapital server-side will be in this file.
# [0.10.1] - 25-09-2023
* Fix: Running tenants migration on Docker migration container by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/242
# [0.10.0] - 24-09-2023
* Added: Tax rates service by @abouolia @elforjani13 in https://github.com/bigcapitalhq/bigcapital/pull/204
* Added: Sales Tax Liability Summary report by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/204
* Added: Tax rates tracking with sale invoices by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/204
* fix(webapp): Table headers sticky for all reports. by @elforjani13 in https://github.com/bigcapitalhq/bigcapital/pull/240
* chore(deps): bump word-wrap from 1.2.3 to 1.2.4 by @dependabot in https://github.com/bigcapitalhq/bigcapital/pull/200
* chore(deps): bump word-wrap from 1.2.3 to 1.2.4 in /packages/webapp by @dependabot in https://github.com/bigcapitalhq/bigcapital/pull/199
* chore(deps): bump mongoose from 5.13.15 to 5.13.20 by @dependabot in https://github.com/bigcapitalhq/bigcapital/pull/197
# [0.9.12] - 29-08-2023
* Refactor: split the services to multiple service classes. (by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/202)
* Fix: create quick customer/vendor by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/206
* Fix: typo in bill success message without bill number by @KalliopiPliogka in https://github.com/bigcapitalhq/bigcapital/pull/219
* Fix: AP/AR aging summary issue by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/229
* Fix: shouldn't write GL entries when save transaction as draft. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/221
* Fix: Transaction type of credit note and vendor credit are not defined on account transactions by @abouolia in
* Fix: date format of filtering transactions by date range by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/231
* Fix: change the default from/date date value of reports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/230
* Fix: typos in words start with `A` letter by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/227
* Fix: filter by customers, vendors and items in reports do not work by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/224
https://github.com/bigcapitalhq/bigcapital/pull/225
# [0.9.11] - 23-07-2023
* added: Restart policy to docker compose files. by @suhaibaffan in https://github.com/bigcapitalhq/bigcapital/pull/198
* fix: Expose and expand the rate limit to the env variables by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/195
# [0.9.10] - 18-07-2023
* feat(e2e): E2E onboarding process by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/176
* fix(webapp): Show loading message of cost computing job on financial reports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/196
* fix(webapp): Change the currency code of sales and purchases transactions with foreign contacts.
# [0.9.9] - 28-06-2023 # [0.9.9] - 28-06-2023
* refactor: Customer and vendor select component by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/171 * refactor: Customer and vendor select component by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/171
@@ -125,7 +86,7 @@ https://github.com/bigcapitalhq/bigcapital/pull/225
- fix: delete invoice transaction issue. - fix: delete invoice transaction issue.
`@bigcapital/webapp` `@bigcapital/webapp`
- fix: general, accountant and items preferences. - fix: general, accoutant and items preferences.
- fix: auto-increment sale invoices, estiamtes, credit notes, payments and manual journals. - fix: auto-increment sale invoices, estiamtes, credit notes, payments and manual journals.
- refactor: the setup organization form to use binded Formik components. - refactor: the setup organization form to use binded Formik components.

View File

@@ -7,7 +7,6 @@ Please read through this document before submitting any issues or pull requests
## Sections ## Sections
- [General Instructions](#general-instructions) - [General Instructions](#general-instructions)
- [Local Setup Prerequisites](#local-setup-prerequisites)
- [Contribute to Backend](#contribute-to-backend) - [Contribute to Backend](#contribute-to-backend)
- [Contribute to Frontend](#contribute-to-frontend) - [Contribute to Frontend](#contribute-to-frontend)
- [Other Ways to Contribute](#other-ways-to-contribute) - [Other Ways to Contribute](#other-ways-to-contribute)
@@ -32,18 +31,9 @@ Contributions via pull requests are much appreciated. Once the approach is agree
--- ---
## Local Setup Prerequisites
- The application currently supports **Node.js v14.x**. Please ensure that you are using this version of Node.js when developing. (use [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) to switch between node versions)
## Contribute to Backend ## Contribute to Backend
- Clone the `bigcapital` repository and `cd` into `bigcapital` directory. - Clone the `bigcapital` repository and `cd` into `bigcapital` directory.
- Create `.env` file by copying `.env.example` file to `.env`. (The ``.env.example`` file has all the necessary values of variables to start development directly).
```
cp .env.example .env
```
- Install all npm dependencies of the monorepo, you don't have to change directory to the `backend` package. just hit these command on root directory and it will install dependencies of all packages. - Install all npm dependencies of the monorepo, you don't have to change directory to the `backend` package. just hit these command on root directory and it will install dependencies of all packages.
``` ```

View File

@@ -48,12 +48,6 @@ Bigcapital is a smart and open-source accounting and inventory software, Bigcapi
Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently. Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently.
# Contact us
Meet our sales team for any commercial inquiries.
<a target="_blank" href="https://cal.com/ahmed-bouhuolia-ekk3ph/30min"><img src="https://cal.com/book-with-cal-dark.svg" alt="Book us with Cal.com"></a>
# Recognition # Recognition
<a href="https://news.ycombinator.com/item?id=36118990"> <a href="https://news.ycombinator.com/item?id=36118990">
@@ -75,11 +69,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<tbody> <tbody>
<tr> <tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/abouolia"><img src="https://avatars.githubusercontent.com/u/2197422?v=4?s=100" width="100px;" alt="Ahmed Bouhuolia"/><br /><sub><b>Ahmed Bouhuolia</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=abouolia" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/abouolia"><img src="https://avatars.githubusercontent.com/u/2197422?v=4?s=100" width="100px;" alt="Ahmed Bouhuolia"/><br /><sub><b>Ahmed Bouhuolia</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=abouolia" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://ameir.net"><img src="https://avatars.githubusercontent.com/u/374330?v=4?s=100" width="100px;" alt="Ameir Abdeldayem"/><br /><sub><b>Ameir Abdeldayem</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Aameir" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/elforjani13"><img src="https://avatars.githubusercontent.com/u/39470382?v=4?s=100" width="100px;" alt="ElforJani13"/><br /><sub><b>ElforJani13</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=elforjani13" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/elforjani13"><img src="https://avatars.githubusercontent.com/u/39470382?v=4?s=100" width="100px;" alt="ElforJani13"/><br /><sub><b>ElforJani13</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=elforjani13" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://ameir.net"><img src="https://avatars.githubusercontent.com/u/374330?v=4?s=100" width="100px;" alt="Ameir Abdeldayem"/><br /><sub><b>Ameir Abdeldayem</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Aameir" 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://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/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>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -15,8 +15,8 @@ services:
- ./data/logs/nginx/:/var/log/nginx - ./data/logs/nginx/:/var/log/nginx
- ./docker/certbot/certs/:/var/certs - ./docker/certbot/certs/:/var/certs
ports: ports:
- '${PUBLIC_PROXY_PORT:-80}:80' - "${PUBLIC_PROXY_PORT:-80}:80"
- '${PUBLIC_PROXY_SSL_PORT:-443}:443' - "${PUBLIC_PROXY_SSL_PORT:-443}:443"
tty: true tty: true
depends_on: depends_on:
- server - server
@@ -71,7 +71,7 @@ services:
# Authentication # Authentication
- JWT_SECRET=${JWT_SECRET} - JWT_SECRET=${JWT_SECRET}
# MongoDB # MongoDB
- MONGODB_DATABASE_URL=mongodb://mongo/bigcapital - MONGODB_DATABASE_URL=mongodb://mongo/bigcapital
# Application # Application
@@ -92,14 +92,11 @@ services:
context: ./ context: ./
dockerfile: docker/migration/Dockerfile dockerfile: docker/migration/Dockerfile
environment: environment:
# Database
- DB_HOST=mysql - DB_HOST=mysql
- DB_USER=${DB_USER} - DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD} - DB_PASSWORD=${DB_PASSWORD}
- DB_CHARSET=${DB_CHARSET} - DB_CHARSET=${DB_CHARSET}
- SYSTEM_DB_NAME=${SYSTEM_DB_NAME} - SYSTEM_DB_NAME=${SYSTEM_DB_NAME}
# Tenants databases
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
depends_on: depends_on:
- mysql - mysql
@@ -139,7 +136,7 @@ services:
build: build:
context: ./docker/redis context: ./docker/redis
expose: expose:
- '6379' - "6379"
volumes: volumes:
- redis:/data - redis:/data

View File

@@ -34,7 +34,5 @@ WORKDIR /app/packages/server
RUN git clone https://github.com/vishnubob/wait-for-it.git RUN git clone https://github.com/vishnubob/wait-for-it.git
ADD docker/migration/start.sh / # Once we listen the mysql port run the migration task.
RUN chmod +x /start.sh CMD ["./wait-for-it/wait-for-it.sh", "mysql:3306", "--", "node", "./build/commands.js", "system:migrate:latest"]
CMD ["/start.sh"]

View File

@@ -1,5 +0,0 @@
# Migrate the master system database.
./wait-for-it/wait-for-it.sh mysql:3306 -- node ./build/commands.js system:migrate:latest
# Migrate all tenants.
./wait-for-it/wait-for-it.sh mysql:3306 -- node ./build/commands.js tenants:migrate:latest

View File

@@ -1,7 +0,0 @@
import { test, expect, Page } from '@playwright/test';
test.describe('item', () => {
test('should validate all required fields.', () => {});
test('should save the item successfully.', () => {});
test('should item code be unqiue.', () => {});
});

View File

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

5730
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "bigcapital-monorepo", "name": "bigcapital-monorepo",
"private": true, "private": true,
"scripts": { "scripts": {
"bootstrap": "lerna exec pnpm install", "bootstrap": "lerna exec npm 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\"",
@@ -13,6 +13,10 @@
"test:e2e": "playwright test", "test:e2e": "playwright test",
"prepare": "husky install" "prepare": "husky install"
}, },
"workspaces": [
"packages/*",
"shared/*"
],
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.4.2", "@commitlint/cli": "^17.4.2",
"@commitlint/config-conventional": "^17.4.2", "@commitlint/config-conventional": "^17.4.2",

View File

@@ -1,6 +1,7 @@
/node_modules/ /node_modules/
/.env /.env
/storage /storage
package-lock.json
stdout.log stdout.log
/dist /dist
/build /build

View File

@@ -1,6 +1,6 @@
{ {
"name": "@bigcapital/server", "name": "@bigcapital/server",
"version": "0.10.1", "version": "0.9.5",
"description": "", "description": "",
"main": "src/server.ts", "main": "src/server.ts",
"scripts": { "scripts": {
@@ -35,7 +35,6 @@
"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",
"body-parser": "^1.20.2",
"compression": "^1.7.4", "compression": "^1.7.4",
"country-codes-list": "^1.6.8", "country-codes-list": "^1.6.8",
"cpy": "^8.1.2", "cpy": "^8.1.2",
@@ -73,8 +72,6 @@
"memory-cache": "^0.2.0", "memory-cache": "^0.2.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"moment-range": "^4.0.2", "moment-range": "^4.0.2",
"moment-timezone": "^0.5.43",
"mongodb": "^6.1.0",
"mongoose": "^5.10.0", "mongoose": "^5.10.0",
"mustache": "^3.0.3", "mustache": "^3.0.3",
"mysql": "^2.17.1", "mysql": "^2.17.1",
@@ -134,7 +131,7 @@
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rtlcss": "^3.3.0", "rtlcss": "^3.3.0",
"run-script-webpack-plugin": "^0.1.1", "run-script-webpack-plugin": "^0.1.1",
"sass": "^1.58.0", "sass": "^1.37.5",
"sinon": "^7.4.2", "sinon": "^7.4.2",
"start-server-webpack-plugin": "^2.2.5", "start-server-webpack-plugin": "^2.2.5",
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",

View File

@@ -152,7 +152,7 @@
"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 availiable 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.": "لا ترتبط انشطة الدخل إلى الأعمال الأساسية.",

View File

@@ -151,7 +151,7 @@
"Opening Balance Liabilities": "Opening Balance Liabilities", "Opening Balance Liabilities": "Opening Balance Liabilities",
"Loan": "Loan", "Loan": "Loan",
"Owner A Drawings": "Owner A Drawings", "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.", "An account that holds valuation of products or goods that availiable for sale.": "An account that holds valuation of products or goods that availiable for sale.",
"Tracks the gain and losses of the exchange differences.": "Tracks the gain and losses of the exchange differences.", "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.", "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.", "The income activities are not associated to the core business.": "The income activities are not associated to the core business.",

View File

@@ -20,7 +20,6 @@ import InventoryDetailsController from './FinancialStatements/InventoryDetails';
import TransactionsByReferenceController from './FinancialStatements/TransactionsByReference'; import TransactionsByReferenceController from './FinancialStatements/TransactionsByReference';
import CashflowAccountTransactions from './FinancialStatements/CashflowAccountTransactions'; import CashflowAccountTransactions from './FinancialStatements/CashflowAccountTransactions';
import ProjectProfitabilityController from './FinancialStatements/ProjectProfitabilitySummary'; import ProjectProfitabilityController from './FinancialStatements/ProjectProfitabilitySummary';
import SalesTaxLiabilitySummary from './FinancialStatements/SalesTaxLiabilitySummary';
@Service() @Service()
export default class FinancialStatementsService { export default class FinancialStatementsService {
@@ -69,44 +68,40 @@ export default class FinancialStatementsService {
); );
router.use( router.use(
'/customer-balance-summary', '/customer-balance-summary',
Container.get(CustomerBalanceSummaryController).router() Container.get(CustomerBalanceSummaryController).router(),
); );
router.use( router.use(
'/vendor-balance-summary', '/vendor-balance-summary',
Container.get(VendorBalanceSummaryController).router() Container.get(VendorBalanceSummaryController).router(),
); );
router.use( router.use(
'/transactions-by-customers', '/transactions-by-customers',
Container.get(TransactionsByCustomers).router() Container.get(TransactionsByCustomers).router(),
); );
router.use( router.use(
'/transactions-by-vendors', '/transactions-by-vendors',
Container.get(TransactionsByVendors).router() Container.get(TransactionsByVendors).router(),
); );
router.use( router.use(
'/cash-flow', '/cash-flow',
Container.get(CashFlowStatementController).router() Container.get(CashFlowStatementController).router(),
); );
router.use( router.use(
'/inventory-item-details', '/inventory-item-details',
Container.get(InventoryDetailsController).router() Container.get(InventoryDetailsController).router(),
); );
router.use( router.use(
'/transactions-by-reference', '/transactions-by-reference',
Container.get(TransactionsByReferenceController).router() Container.get(TransactionsByReferenceController).router(),
); );
router.use( router.use(
'/cashflow-account-transactions', '/cashflow-account-transactions',
Container.get(CashflowAccountTransactions).router() Container.get(CashflowAccountTransactions).router(),
); );
router.use( router.use(
'/project-profitability-summary', '/project-profitability-summary',
Container.get(ProjectProfitabilityController).router() Container.get(ProjectProfitabilityController).router(),
); )
router.use(
'/sales-tax-liability-summary',
Container.get(SalesTaxLiabilitySummary).router()
);
return router; return router;
} }
} }

View File

@@ -33,13 +33,10 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
return [ return [
...this.sheetNumberFormatValidationSchema, ...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(), query('as_date').optional().isISO8601(),
query('aging_days_before').optional().isNumeric().toInt(),
query('aging_days_before').default(30).isInt({ max: 500 }).toInt(), query('aging_periods').optional().isNumeric().toInt(),
query('aging_periods').default(3).isInt({ max: 12 }).toInt(),
query('vendors_ids').optional().isArray({ min: 1 }), query('vendors_ids').optional().isArray({ min: 1 }),
query('vendors_ids.*').isInt({ min: 1 }).toInt(), query('vendors_ids.*').isInt({ min: 1 }).toInt(),
query('none_zero').default(true).isBoolean().toBoolean(), query('none_zero').default(true).isBoolean().toBoolean(),
// Filtering by branches. // Filtering by branches.
@@ -56,36 +53,15 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const accept = this.accepts(req); const { data, columns, query, meta } =
const acceptType = accept.types(['json', 'application/json+table']); await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
switch (acceptType) { return res.status(200).send({
case 'application/json+table': data: this.transfromToResponse(data),
const table = await this.APAgingSummaryService.APAgingSummaryTable( columns: this.transfromToResponse(columns),
tenantId, query: this.transfromToResponse(query),
filter meta: this.transfromToResponse(meta),
); });
return res.status(200).send({
table: {
rows: table.rows,
columns: table.columns,
},
meta: table.meta,
query: table.query,
});
break;
default:
const { data, columns, query, meta } =
await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
break;
}
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@@ -36,8 +36,8 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
query('as_date').optional().isISO8601(), query('as_date').optional().isISO8601(),
query('aging_days_before').default(30).isInt({ max: 500 }).toInt(), query('aging_days_before').optional().isInt({ max: 500 }).toInt(),
query('aging_periods').default(3).isInt({ max: 12 }).toInt(), query('aging_periods').optional().isInt({ max: 12 }).toInt(),
query('customers_ids').optional().isArray({ min: 1 }), query('customers_ids').optional().isArray({ min: 1 }),
query('customers_ids.*').isInt({ min: 1 }).toInt(), query('customers_ids.*').isInt({ min: 1 }).toInt(),
@@ -58,36 +58,15 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
const filter = this.matchedQueryData(req); const filter = this.matchedQueryData(req);
try { try {
const accept = this.accepts(req); const { data, columns, query, meta } =
const acceptType = accept.types(['json', 'application/json+table']); await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
switch (acceptType) { return res.status(200).send({
case 'application/json+table': data: this.transfromToResponse(data),
const table = await this.ARAgingSummaryService.ARAgingSummaryTable( columns: this.transfromToResponse(columns),
tenantId, query: this.transfromToResponse(query),
filter meta: this.transfromToResponse(meta),
); });
return res.status(200).send({
table: {
rows: table.rows,
columns: table.columns,
},
meta: table.meta,
query: table.query,
});
break;
default:
const { data, columns, query, meta } =
await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
break;
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@@ -1,90 +0,0 @@
import { Router, Request, Response, NextFunction } from 'express';
import { query } from 'express-validator';
import { Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseFinancialReportController from '../BaseFinancialReportController';
import { AbilitySubject, ReportsAction } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { SalesTaxLiabilitySummaryService } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService';
export default class SalesTaxLiabilitySummary extends BaseFinancialReportController {
@Inject()
private salesTaxLiabilitySummaryService: SalesTaxLiabilitySummaryService;
/**
* Router constructor.
*/
router() {
const router = Router();
router.get(
'/',
CheckPolicies(
ReportsAction.READ_SALES_TAX_LIABILITY_SUMMARY,
AbilitySubject.Report
),
this.validationSchema,
asyncMiddleware(this.salesTaxLiabilitySummary.bind(this))
);
return router;
}
/**
* Validation schema.
*/
get validationSchema() {
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
];
}
/*
* Retrieves the sales tax liability summary.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
async salesTaxLiabilitySummary(
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req;
const filter = this.matchedQueryData(req);
try {
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
switch (acceptType) {
case 'application/json+table':
const salesTaxLiabilityTable =
await this.salesTaxLiabilitySummaryService.salesTaxLiabilitySummaryTable(
tenantId,
filter
);
return res.status(200).send({
table: salesTaxLiabilityTable.table,
query: salesTaxLiabilityTable.query,
meta: salesTaxLiabilityTable.meta,
});
case 'json':
default:
const salesTaxLiability =
await this.salesTaxLiabilitySummaryService.salesTaxLiability(
tenantId,
filter
);
return res.status(200).send({
data: salesTaxLiability.data,
query: salesTaxLiability.query,
meta: salesTaxLiability.meta,
});
}
} catch (error) {
next(error);
}
}
}

View File

@@ -387,7 +387,7 @@ export default class ManualJournalsController extends BaseController {
errors: [{ type: 'CREDIT.DEBIT.NOT.EQUALS', code: 300 }], errors: [{ type: 'CREDIT.DEBIT.NOT.EQUALS', code: 300 }],
}); });
} }
if (error.errorType === 'accounts_ids_not_found') { if (error.errorType === 'acccounts_ids_not_found') {
return res.boom.badRequest( return res.boom.badRequest(
'Journal entries some of accounts ids not exists.', 'Journal entries some of accounts ids not exists.',
{ errors: [{ type: 'ACCOUNTS.IDS.NOT.FOUND', code: 400 }] } { errors: [{ type: 'ACCOUNTS.IDS.NOT.FOUND', code: 400 }] }

View File

@@ -1,27 +1,26 @@
import { Service, Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator'; import { check, param, query } from 'express-validator';
import { import { Service, Inject } from 'typedi';
AbilitySubject, import { AbilitySubject, BillAction, IBillDTO, IBillEditDTO } from '@/interfaces';
BillAction,
IBillDTO,
IBillEditDTO,
} from '@/interfaces';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BillsService from '@/services/Purchases/Bills';
import BaseController from '@/api/controllers/BaseController'; import BaseController from '@/api/controllers/BaseController';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { BillsApplication } from '@/services/Purchases/Bills/BillsApplication'; import BillPaymentsService from '@/services/Purchases/BillPaymentsService';
@Service() @Service()
export default class BillsController extends BaseController { export default class BillsController extends BaseController {
@Inject() @Inject()
private billsApplication: BillsApplication; private billsService: BillsService;
@Inject() @Inject()
private dynamicListService: DynamicListingService; private dynamicListService: DynamicListingService;
@Inject()
private billPayments: BillPaymentsService;
/** /**
* Router constructor. * Router constructor.
*/ */
@@ -98,7 +97,7 @@ export default class BillsController extends BaseController {
/** /**
* Common validation schema. * Common validation schema.
*/ */
private get billValidationSchema() { get billValidationSchema() {
return [ return [
check('bill_number').exists().trim().escape(), check('bill_number').exists().trim().escape(),
check('reference_no').optional().trim().escape(), check('reference_no').optional().trim().escape(),
@@ -143,7 +142,7 @@ export default class BillsController extends BaseController {
/** /**
* Common validation schema. * Common validation schema.
*/ */
private get billEditValidationSchema() { get billEditValidationSchema() {
return [ return [
check('bill_number').optional().trim().escape(), check('bill_number').optional().trim().escape(),
check('reference_no').optional().trim().escape(), check('reference_no').optional().trim().escape(),
@@ -185,14 +184,14 @@ export default class BillsController extends BaseController {
/** /**
* Bill validation schema. * Bill validation schema.
*/ */
private get specificBillValidationSchema() { get specificBillValidationSchema() {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
/** /**
* Bills list validation schema. * Bills list validation schema.
*/ */
private get billsListingValidationSchema() { get billsListingValidationSchema() {
return [ return [
query('view_slug').optional().isString().trim(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -204,7 +203,7 @@ export default class BillsController extends BaseController {
]; ];
} }
private get dueBillsListingValidationSchema() { get dueBillsListingValidationSchema() {
return [ return [
query('vendor_id').optional().trim().escape(), query('vendor_id').optional().trim().escape(),
query('payment_made_id').optional().trim().escape(), query('payment_made_id').optional().trim().escape(),
@@ -217,16 +216,17 @@ export default class BillsController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {Function} next * @param {Function} next
*/ */
private async newBill(req: Request, res: Response, next: NextFunction) { async newBill(req: Request, res: Response, next: NextFunction) {
const { tenantId, user } = req; const { tenantId, user } = req;
const billDTO: IBillDTO = this.matchedBodyData(req); const billDTO: IBillDTO = this.matchedBodyData(req);
try { try {
const storedBill = await this.billsApplication.createBill( const storedBill = await this.billsService.createBill(
tenantId, tenantId,
billDTO, billDTO,
user user
); );
return res.status(200).send({ return res.status(200).send({
id: storedBill.id, id: storedBill.id,
message: 'The bill has been created successfully.', message: 'The bill has been created successfully.',
@@ -241,13 +241,13 @@ export default class BillsController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async editBill(req: Request, res: Response, next: NextFunction) { async editBill(req: Request, res: Response, next: NextFunction) {
const { id: billId } = req.params; const { id: billId } = req.params;
const { tenantId, user } = req; const { tenantId, user } = req;
const billDTO: IBillEditDTO = this.matchedBodyData(req); const billDTO: IBillEditDTO = this.matchedBodyData(req);
try { try {
await this.billsApplication.editBill(tenantId, billId, billDTO, user); await this.billsService.editBill(tenantId, billId, billDTO, user);
return res.status(200).send({ return res.status(200).send({
id: billId, id: billId,
@@ -263,12 +263,12 @@ export default class BillsController extends BaseController {
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async openBill(req: Request, res: Response, next: NextFunction) { async openBill(req: Request, res: Response, next: NextFunction) {
const { id: billId } = req.params; const { id: billId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.billsApplication.openBill(tenantId, billId); await this.billsService.openBill(tenantId, billId);
return res.status(200).send({ return res.status(200).send({
id: billId, id: billId,
@@ -285,12 +285,12 @@ export default class BillsController extends BaseController {
* @param {Response} res * @param {Response} res
* @return {Response} * @return {Response}
*/ */
private async getBill(req: Request, res: Response, next: NextFunction) { async getBill(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId } = req;
const { id: billId } = req.params; const { id: billId } = req.params;
try { try {
const bill = await this.billsApplication.getBill(tenantId, billId); const bill = await this.billsService.getBill(tenantId, billId);
return res.status(200).send(this.transfromToResponse({ bill })); return res.status(200).send(this.transfromToResponse({ bill }));
} catch (error) { } catch (error) {
@@ -304,12 +304,12 @@ export default class BillsController extends BaseController {
* @param {Response} res - * @param {Response} res -
* @return {Response} * @return {Response}
*/ */
private async deleteBill(req: Request, res: Response, next: NextFunction) { async deleteBill(req: Request, res: Response, next: NextFunction) {
const billId = req.params.id; const billId = req.params.id;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.billsApplication.deleteBill(tenantId, billId); await this.billsService.deleteBill(tenantId, billId);
return res.status(200).send({ return res.status(200).send({
id: billId, id: billId,
@@ -326,7 +326,7 @@ export default class BillsController extends BaseController {
* @param {Response} res - * @param {Response} res -
* @return {Response} * @return {Response}
*/ */
private async billsList(req: Request, res: Response, next: NextFunction) { public async billsList(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId } = req;
const filter = { const filter = {
page: 1, page: 1,
@@ -338,7 +338,7 @@ export default class BillsController extends BaseController {
try { try {
const { bills, pagination, filterMeta } = const { bills, pagination, filterMeta } =
await this.billsApplication.getBills(tenantId, filter); await this.billsService.getBills(tenantId, filter);
return res.status(200).send({ return res.status(200).send({
bills: this.transfromToResponse(bills), bills: this.transfromToResponse(bills),
@@ -356,13 +356,12 @@ export default class BillsController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async getDueBills(req: Request, res: Response, next: NextFunction) { public async getDueBills(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId } = req;
const { vendorId } = this.matchedQueryData(req); const { vendorId } = this.matchedQueryData(req);
try { try {
const bills = await this.billsApplication.getDueBills(tenantId, vendorId); const bills = await this.billsService.getDueBills(tenantId, vendorId);
return res.status(200).send({ bills }); return res.status(200).send({ bills });
} catch (error) { } catch (error) {
next(error); next(error);
@@ -375,7 +374,7 @@ export default class BillsController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private getBillPaymentsTransactions = async ( public getBillPaymentsTransactions = async (
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -384,7 +383,7 @@ export default class BillsController extends BaseController {
const { id: billId } = req.params; const { id: billId } = req.params;
try { try {
const billPayments = await this.billsApplication.getBillPayments( const billPayments = await this.billPayments.getBillPayments(
tenantId, tenantId,
billId billId
); );

View File

@@ -4,7 +4,7 @@ import { check, param, query, ValidationChain } from 'express-validator';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import BaseController from '@/api/controllers/BaseController'; import BaseController from '@/api/controllers/BaseController';
import { BillPaymentsApplication } from '@/services/Purchases/BillPayments/BillPaymentsApplication'; import BillPaymentsService from '@/services/Purchases/BillPayments/BillPayments';
import BillPaymentsPages from '@/services/Purchases/BillPayments/BillPaymentsPages'; import BillPaymentsPages from '@/services/Purchases/BillPayments/BillPaymentsPages';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
@@ -17,18 +17,18 @@ import { AbilitySubject, IPaymentMadeAction } from '@/interfaces';
@Service() @Service()
export default class BillsPayments extends BaseController { export default class BillsPayments extends BaseController {
@Inject() @Inject()
private billPaymentsApplication: BillPaymentsApplication; billPaymentService: BillPaymentsService;
@Inject() @Inject()
private dynamicListService: DynamicListingService; dynamicListService: DynamicListingService;
@Inject() @Inject()
private billPaymentsPages: BillPaymentsPages; billPaymentsPages: BillPaymentsPages;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.post( router.post(
@@ -106,7 +106,7 @@ export default class BillsPayments extends BaseController {
* Bill payments schema validation. * Bill payments schema validation.
* @return {ValidationChain[]} * @return {ValidationChain[]}
*/ */
private get billPaymentSchemaValidation(): ValidationChain[] { get billPaymentSchemaValidation(): ValidationChain[] {
return [ return [
check('vendor_id').exists().isNumeric().toInt(), check('vendor_id').exists().isNumeric().toInt(),
check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(), check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(),
@@ -129,7 +129,7 @@ export default class BillsPayments extends BaseController {
* Specific bill payment schema validation. * Specific bill payment schema validation.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get specificBillPaymentValidateSchema(): ValidationChain[] { get specificBillPaymentValidateSchema(): ValidationChain[] {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
@@ -137,7 +137,7 @@ export default class BillsPayments extends BaseController {
* Bills payment list validation schema. * Bills payment list validation schema.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get listingValidationSchema(): ValidationChain[] { get listingValidationSchema(): ValidationChain[] {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('custom_view_id').optional().isNumeric().toInt(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -154,7 +154,7 @@ export default class BillsPayments extends BaseController {
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async getBillPaymentNewPageEntries(req: Request, res: Response) { async getBillPaymentNewPageEntries(req: Request, res: Response) {
const { tenantId } = req; const { tenantId } = req;
const { vendorId } = this.matchedQueryData(req); const { vendorId } = this.matchedQueryData(req);
@@ -174,7 +174,7 @@ export default class BillsPayments extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async getBillPaymentEditPage( async getBillPaymentEditPage(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -205,19 +205,16 @@ export default class BillsPayments extends BaseController {
* @param {Response} res * @param {Response} res
* @param {Response} res * @param {Response} res
*/ */
private async createBillPayment( async createBillPayment(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const billPaymentDTO = this.matchedBodyData(req); const billPaymentDTO = this.matchedBodyData(req);
try { try {
const billPayment = await this.billPaymentsApplication.createBillPayment( const billPayment = await this.billPaymentService.createBillPayment(
tenantId, tenantId,
billPaymentDTO billPaymentDTO
); );
return res.status(200).send({ return res.status(200).send({
id: billPayment.id, id: billPayment.id,
message: 'Payment made has been created successfully.', message: 'Payment made has been created successfully.',
@@ -232,17 +229,13 @@ export default class BillsPayments extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async editBillPayment( async editBillPayment(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const billPaymentDTO = this.matchedBodyData(req); const billPaymentDTO = this.matchedBodyData(req);
const { id: billPaymentId } = req.params; const { id: billPaymentId } = req.params;
try { try {
const paymentMade = await this.billPaymentsApplication.editBillPayment( const paymentMade = await this.billPaymentService.editBillPayment(
tenantId, tenantId,
billPaymentId, billPaymentId,
billPaymentDTO billPaymentDTO
@@ -263,19 +256,12 @@ export default class BillsPayments extends BaseController {
* @param {Response} res - * @param {Response} res -
* @return {Response} res - * @return {Response} res -
*/ */
private async deleteBillPayment( async deleteBillPayment(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: billPaymentId } = req.params; const { id: billPaymentId } = req.params;
try { try {
await this.billPaymentsApplication.deleteBillPayment( await this.billPaymentService.deleteBillPayment(tenantId, billPaymentId);
tenantId,
billPaymentId
);
return res.status(200).send({ return res.status(200).send({
id: billPaymentId, id: billPaymentId,
@@ -291,19 +277,16 @@ export default class BillsPayments extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async getBillPayment( async getBillPayment(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: billPaymentId } = req.params; const { id: billPaymentId } = req.params;
try { try {
const billPayment = await this.billPaymentsApplication.getBillPayment( const billPayment = await this.billPaymentService.getBillPayment(
tenantId, tenantId,
billPaymentId billPaymentId
); );
return res.status(200).send({ return res.status(200).send({
bill_payment: this.transfromToResponse(billPayment), bill_payment: this.transfromToResponse(billPayment),
}); });
@@ -318,16 +301,12 @@ export default class BillsPayments extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async getPaymentBills( async getPaymentBills(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: billPaymentId } = req.params; const { id: billPaymentId } = req.params;
try { try {
const bills = await this.billPaymentsApplication.getPaymentBills( const bills = await this.billPaymentService.getPaymentBills(
tenantId, tenantId,
billPaymentId billPaymentId
); );
@@ -343,11 +322,7 @@ export default class BillsPayments extends BaseController {
* @param {Response} res - * @param {Response} res -
* @return {Response} * @return {Response}
*/ */
private async getBillsPayments( async getBillsPayments(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const billPaymentsFilter = { const billPaymentsFilter = {
page: 1, page: 1,
@@ -360,7 +335,7 @@ export default class BillsPayments extends BaseController {
try { try {
const { billPayments, pagination, filterMeta } = const { billPayments, pagination, filterMeta } =
await this.billPaymentsApplication.getBillPayments( await this.billPaymentService.listBillPayments(
tenantId, tenantId,
billPaymentsFilter billPaymentsFilter
); );
@@ -382,7 +357,7 @@ export default class BillsPayments extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private handleServiceError( handleServiceError(
error: Error, error: Error,
req: Request, req: Request,
res: Response, res: Response,

View File

@@ -1,29 +1,42 @@
import { Inject, Service } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query, ValidationChain } from 'express-validator'; import { check, param, query, ValidationChain } from 'express-validator';
import { Inject, Service } from 'typedi';
import { import {
AbilitySubject, AbilitySubject,
IPaymentReceiveDTO, IPaymentReceiveDTO,
PaymentReceiveAction, PaymentReceiveAction,
SaleInvoiceAction,
} from '@/interfaces'; } from '@/interfaces';
import BaseController from '@/api/controllers/BaseController'; import BaseController from '@/api/controllers/BaseController';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import PaymentReceiveService from '@/services/Sales/PaymentReceives/PaymentsReceives';
import PaymentReceivesPages from '@/services/Sales/PaymentReceives/PaymentReceivesPages'; import PaymentReceivesPages from '@/services/Sales/PaymentReceives/PaymentReceivesPages';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import { PaymentReceivesApplication } from '@/services/Sales/PaymentReceives/PaymentReceivesApplication';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import PaymentReceiveNotifyBySms from '@/services/Sales/PaymentReceives/PaymentReceiveSmsNotify';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import GetPaymentReceivePdf from '@/services/Sales/PaymentReceives/GetPaymentReeceivePdf';
/**
* Payments receives controller.
* @service
*/
@Service() @Service()
export default class PaymentReceivesController extends BaseController { export default class PaymentReceivesController extends BaseController {
@Inject() @Inject()
private paymentReceiveApplication: PaymentReceivesApplication; paymentReceiveService: PaymentReceiveService;
@Inject() @Inject()
private PaymentReceivesPages: PaymentReceivesPages; PaymentReceivesPages: PaymentReceivesPages;
@Inject() @Inject()
private dynamicListService: DynamicListingService; dynamicListService: DynamicListingService;
@Inject()
paymentReceiveSmsNotify: PaymentReceiveNotifyBySms;
@Inject()
paymentReceivePdf: GetPaymentReceivePdf;
/** /**
* Router constructor. * Router constructor.
@@ -124,7 +137,7 @@ export default class PaymentReceivesController extends BaseController {
* Payment receive schema. * Payment receive schema.
* @return {Array} * @return {Array}
*/ */
private get paymentReceiveSchema(): ValidationChain[] { get paymentReceiveSchema(): ValidationChain[] {
return [ return [
check('customer_id').exists().isNumeric().toInt(), check('customer_id').exists().isNumeric().toInt(),
check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(), check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(),
@@ -149,7 +162,7 @@ export default class PaymentReceivesController extends BaseController {
/** /**
* Payment receive list validation schema. * Payment receive list validation schema.
*/ */
private get validatePaymentReceiveList(): ValidationChain[] { get validatePaymentReceiveList(): ValidationChain[] {
return [ return [
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -168,7 +181,7 @@ export default class PaymentReceivesController extends BaseController {
/** /**
* Validate payment receive parameters. * Validate payment receive parameters.
*/ */
private get paymentReceiveValidation() { get paymentReceiveValidation() {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
@@ -176,14 +189,14 @@ export default class PaymentReceivesController extends BaseController {
* New payment receive validation schema. * New payment receive validation schema.
* @return {Array} * @return {Array}
*/ */
private get newPaymentReceiveValidation() { get newPaymentReceiveValidation() {
return [...this.paymentReceiveSchema]; return [...this.paymentReceiveSchema];
} }
/** /**
* Edit payment receive validation. * Edit payment receive validation.
*/ */
private get editPaymentReceiveValidation() { get editPaymentReceiveValidation() {
return [ return [
param('id').exists().isNumeric().toInt(), param('id').exists().isNumeric().toInt(),
...this.paymentReceiveSchema, ...this.paymentReceiveSchema,
@@ -196,17 +209,13 @@ export default class PaymentReceivesController extends BaseController {
* @param {Response} res * @param {Response} res
* @return {Response} * @return {Response}
*/ */
private async newPaymentReceive( async newPaymentReceive(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const paymentReceive: IPaymentReceiveDTO = this.matchedBodyData(req); const paymentReceive: IPaymentReceiveDTO = this.matchedBodyData(req);
try { try {
const storedPaymentReceive = const storedPaymentReceive =
await this.paymentReceiveApplication.createPaymentReceive( await this.paymentReceiveService.createPaymentReceive(
tenantId, tenantId,
paymentReceive, paymentReceive,
user user
@@ -226,18 +235,14 @@ export default class PaymentReceivesController extends BaseController {
* @param {Response} res * @param {Response} res
* @return {Response} * @return {Response}
*/ */
private async editPaymentReceive( async editPaymentReceive(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
const paymentReceive: IPaymentReceiveDTO = this.matchedBodyData(req); const paymentReceive: IPaymentReceiveDTO = this.matchedBodyData(req);
try { try {
await this.paymentReceiveApplication.editPaymentReceive( await this.paymentReceiveService.editPaymentReceive(
tenantId, tenantId,
paymentReceiveId, paymentReceiveId,
paymentReceive, paymentReceive,
@@ -257,20 +262,17 @@ export default class PaymentReceivesController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async deletePaymentReceive( async deletePaymentReceive(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { try {
await this.paymentReceiveApplication.deletePaymentReceive( await this.paymentReceiveService.deletePaymentReceive(
tenantId, tenantId,
paymentReceiveId, paymentReceiveId,
user user
); );
return res.status(200).send({ return res.status(200).send({
id: paymentReceiveId, id: paymentReceiveId,
message: 'The payment receive has been deleted successfully', message: 'The payment receive has been deleted successfully',
@@ -286,7 +288,7 @@ export default class PaymentReceivesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async getPaymentReceiveInvoices( async getPaymentReceiveInvoices(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -296,7 +298,7 @@ export default class PaymentReceivesController extends BaseController {
try { try {
const saleInvoices = const saleInvoices =
await this.paymentReceiveApplication.getPaymentReceiveInvoices( await this.paymentReceiveService.getPaymentReceiveInvoices(
tenantId, tenantId,
paymentReceiveId paymentReceiveId
); );
@@ -313,11 +315,7 @@ export default class PaymentReceivesController extends BaseController {
* @param {Response} res * @param {Response} res
* @return {Response} * @return {Response}
*/ */
private async getPaymentReceiveList( async getPaymentReceiveList(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const filter = { const filter = {
sortOrder: 'desc', sortOrder: 'desc',
@@ -329,10 +327,7 @@ export default class PaymentReceivesController extends BaseController {
try { try {
const { paymentReceives, pagination, filterMeta } = const { paymentReceives, pagination, filterMeta } =
await this.paymentReceiveApplication.getPaymentReceives( await this.paymentReceiveService.listPaymentReceives(tenantId, filter);
tenantId,
filter
);
return res.status(200).send({ return res.status(200).send({
payment_receives: this.transfromToResponse(paymentReceives), payment_receives: this.transfromToResponse(paymentReceives),
@@ -349,7 +344,7 @@ export default class PaymentReceivesController extends BaseController {
* @param {Request} req - Request. * @param {Request} req - Request.
* @param {Response} res - Response. * @param {Response} res - Response.
*/ */
private async getPaymentReceiveNewPageEntries( async getPaymentReceiveNewPageEntries(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -372,11 +367,11 @@ export default class PaymentReceivesController extends BaseController {
/** /**
* Retrieve the given payment receive details. * Retrieve the given payment receive details.
* @async * @asycn
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async getPaymentReceiveEditPage( async getPaymentReceiveEditPage(
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -407,20 +402,15 @@ export default class PaymentReceivesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async getPaymentReceive( async getPaymentReceive(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { try {
const paymentReceive = const paymentReceive = await this.paymentReceiveService.getPaymentReceive(
await this.paymentReceiveApplication.getPaymentReceive( tenantId,
tenantId, paymentReceiveId
paymentReceiveId );
);
const ACCEPT_TYPE = { const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf', APPLICATION_PDF: 'application/pdf',
@@ -433,11 +423,10 @@ export default class PaymentReceivesController extends BaseController {
}); });
}, },
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { [ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = const pdfContent = await this.paymentReceivePdf.getPaymentReceivePdf(
await this.paymentReceiveApplication.getPaymentReceivePdf( tenantId,
tenantId, paymentReceive
paymentReceive );
);
res.set({ res.set({
'Content-Type': 'application/pdf', 'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length, 'Content-Length': pdfContent.length,
@@ -465,11 +454,10 @@ export default class PaymentReceivesController extends BaseController {
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { try {
const paymentReceive = const paymentReceive = await this.paymentReceiveSmsNotify.notifyBySms(
await this.paymentReceiveApplication.notifyPaymentBySms( tenantId,
tenantId, paymentReceiveId
paymentReceiveId );
);
return res.status(200).send({ return res.status(200).send({
id: paymentReceive.id, id: paymentReceive.id,
message: 'The payment notification has been sent successfully.', message: 'The payment notification has been sent successfully.',
@@ -494,11 +482,10 @@ export default class PaymentReceivesController extends BaseController {
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { try {
const smsDetails = const smsDetails = await this.paymentReceiveSmsNotify.smsDetails(
await this.paymentReceiveApplication.getPaymentSmsDetails( tenantId,
tenantId, paymentReceiveId
paymentReceiveId );
);
return res.status(200).send({ return res.status(200).send({
data: smsDetails, data: smsDetails,
}); });

View File

@@ -1,17 +1,20 @@
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator'; import { check, param, query, matchedData } from 'express-validator';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import { import {
AbilitySubject, AbilitySubject,
ISaleEstimateDTO, ISaleEstimateDTO,
SaleEstimateAction, SaleEstimateAction,
SaleInvoiceAction,
} from '@/interfaces'; } from '@/interfaces';
import BaseController from '@/api/controllers/BaseController'; import BaseController from '@/api/controllers/BaseController';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import SaleEstimateService from '@/services/Sales/SalesEstimate';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import SaleEstimatesPdfService from '@/services/Sales/Estimates/SaleEstimatesPdf';
import SaleEstimateNotifyBySms from '@/services/Sales/Estimates/SaleEstimateSmsNotify';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { SaleEstimatesApplication } from '@/services/Sales/Estimates/SaleEstimatesApplication';
const ACCEPT_TYPE = { const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf', APPLICATION_PDF: 'application/pdf',
@@ -20,15 +23,21 @@ const ACCEPT_TYPE = {
@Service() @Service()
export default class SalesEstimatesController extends BaseController { export default class SalesEstimatesController extends BaseController {
@Inject() @Inject()
private saleEstimatesApplication: SaleEstimatesApplication; saleEstimateService: SaleEstimateService;
@Inject() @Inject()
private dynamicListService: DynamicListingService; dynamicListService: DynamicListingService;
@Inject()
saleEstimatesPdf: SaleEstimatesPdfService;
@Inject()
saleEstimateNotifySms: SaleEstimateNotifyBySms;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.post( router.post(
@@ -127,7 +136,7 @@ export default class SalesEstimatesController extends BaseController {
/** /**
* Estimate validation schema. * Estimate validation schema.
*/ */
private get estimateValidationSchema() { get estimateValidationSchema() {
return [ return [
check('customer_id').exists().isNumeric().toInt(), check('customer_id').exists().isNumeric().toInt(),
check('estimate_date').exists().isISO8601().toDate(), check('estimate_date').exists().isISO8601().toDate(),
@@ -168,14 +177,14 @@ export default class SalesEstimatesController extends BaseController {
/** /**
* Specific sale estimate validation schema. * Specific sale estimate validation schema.
*/ */
private get validateSpecificEstimateSchema() { get validateSpecificEstimateSchema() {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
/** /**
* Sales estimates list validation schema. * Sales estimates list validation schema.
*/ */
private get validateEstimateListSchema() { get validateEstimateListSchema() {
return [ return [
query('view_slug').optional().isString().trim(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -193,16 +202,15 @@ export default class SalesEstimatesController extends BaseController {
* @param {Response} res - * @param {Response} res -
* @return {Response} res - * @return {Response} res -
*/ */
private async newEstimate(req: Request, res: Response, next: NextFunction) { async newEstimate(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId } = req;
const estimateDTO: ISaleEstimateDTO = this.matchedBodyData(req); const estimateDTO: ISaleEstimateDTO = this.matchedBodyData(req);
try { try {
const storedEstimate = const storedEstimate = await this.saleEstimateService.createEstimate(
await this.saleEstimatesApplication.createSaleEstimate( tenantId,
tenantId, estimateDTO
estimateDTO );
);
return res.status(200).send({ return res.status(200).send({
id: storedEstimate.id, id: storedEstimate.id,
@@ -218,18 +226,19 @@ export default class SalesEstimatesController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async editEstimate(req: Request, res: Response, next: NextFunction) { async editEstimate(req: Request, res: Response, next: NextFunction) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
const estimateDTO: ISaleEstimateDTO = this.matchedBodyData(req); const estimateDTO: ISaleEstimateDTO = this.matchedBodyData(req);
try { try {
// Update estimate with associated estimate entries. // Update estimate with associated estimate entries.
await this.saleEstimatesApplication.editSaleEstimate( await this.saleEstimateService.editEstimate(
tenantId, tenantId,
estimateId, estimateId,
estimateDTO estimateDTO
); );
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
message: 'The sale estimate has been created successfully.', message: 'The sale estimate has been created successfully.',
@@ -244,19 +253,13 @@ export default class SalesEstimatesController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async deleteEstimate( async deleteEstimate(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.saleEstimatesApplication.deleteSaleEstimate( await this.saleEstimateService.deleteEstimate(tenantId, estimateId);
tenantId,
estimateId
);
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
message: 'The sale estimate has been deleted successfully.', message: 'The sale estimate has been deleted successfully.',
@@ -271,19 +274,13 @@ export default class SalesEstimatesController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async deliverSaleEstimate( async deliverSaleEstimate(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.saleEstimatesApplication.deliverSaleEstimate( await this.saleEstimateService.deliverSaleEstimate(tenantId, estimateId);
tenantId,
estimateId
);
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
message: 'The sale estimate has been delivered successfully.', message: 'The sale estimate has been delivered successfully.',
@@ -299,19 +296,12 @@ export default class SalesEstimatesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async approveSaleEstimate( async approveSaleEstimate(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.saleEstimatesApplication.approveSaleEstimate( await this.saleEstimateService.approveSaleEstimate(tenantId, estimateId);
tenantId,
estimateId
);
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
@@ -328,19 +318,12 @@ export default class SalesEstimatesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async rejectSaleEstimate( async rejectSaleEstimate(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
await this.saleEstimatesApplication.rejectSaleEstimate( await this.saleEstimateService.rejectSaleEstimate(tenantId, estimateId);
tenantId,
estimateId
);
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
@@ -357,12 +340,12 @@ export default class SalesEstimatesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async getEstimate(req: Request, res: Response, next: NextFunction) { async getEstimate(req: Request, res: Response, next: NextFunction) {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { try {
const estimate = await this.saleEstimatesApplication.getSaleEstimate( const estimate = await this.saleEstimateService.getEstimate(
tenantId, tenantId,
estimateId estimateId
); );
@@ -374,11 +357,10 @@ export default class SalesEstimatesController extends BaseController {
}, },
// PDF content type. // PDF content type.
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { [ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = const pdfContent = await this.saleEstimatesPdf.saleEstimatePdf(
await this.saleEstimatesApplication.getSaleEstimatePdf( tenantId,
tenantId, estimate
estimate );
);
res.set({ res.set({
'Content-Type': 'application/pdf', 'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length, 'Content-Length': pdfContent.length,
@@ -396,7 +378,7 @@ export default class SalesEstimatesController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async getEstimates(req: Request, res: Response, next: NextFunction) { async getEstimates(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req; const { tenantId } = req;
const filter = { const filter = {
sortOrder: 'desc', sortOrder: 'desc',
@@ -408,7 +390,7 @@ export default class SalesEstimatesController extends BaseController {
try { try {
const { salesEstimates, pagination, filterMeta } = const { salesEstimates, pagination, filterMeta } =
await this.saleEstimatesApplication.getSaleEstimates(tenantId, filter); await this.saleEstimateService.estimatesList(tenantId, filter);
res.format({ res.format({
[ACCEPT_TYPE.APPLICATION_JSON]: () => { [ACCEPT_TYPE.APPLICATION_JSON]: () => {
@@ -426,7 +408,7 @@ export default class SalesEstimatesController extends BaseController {
} }
} }
private saleEstimateNotifyBySms = async ( public saleEstimateNotifyBySms = async (
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -435,11 +417,10 @@ export default class SalesEstimatesController extends BaseController {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
try { try {
const saleEstimate = const saleEstimate = await this.saleEstimateNotifySms.notifyBySms(
await this.saleEstimatesApplication.notifySaleEstimateBySms( tenantId,
tenantId, estimateId
estimateId );
);
return res.status(200).send({ return res.status(200).send({
id: saleEstimate.id, id: saleEstimate.id,
message: message:
@@ -456,7 +437,7 @@ export default class SalesEstimatesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private saleEstimateSmsDetails = async ( public saleEstimateSmsDetails = async (
req: Request, req: Request,
res: Response, res: Response,
next: NextFunction next: NextFunction
@@ -465,11 +446,10 @@ export default class SalesEstimatesController extends BaseController {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
try { try {
const estimateSmsDetails = const estimateSmsDetails = await this.saleEstimateNotifySms.smsDetails(
await this.saleEstimatesApplication.getSaleEstimateSmsDetails( tenantId,
tenantId, estimateId
estimateId );
);
return res.status(200).send({ return res.status(200).send({
data: estimateSmsDetails, data: estimateSmsDetails,
}); });

View File

@@ -3,6 +3,7 @@ import { check, param, query } from 'express-validator';
import { Service, Inject } from 'typedi'; import { Service, Inject } from 'typedi';
import BaseController from '../BaseController'; import BaseController from '../BaseController';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import SaleInvoiceService from '@/services/Sales/SalesInvoices';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import { import {
@@ -11,8 +12,11 @@ import {
SaleInvoiceAction, SaleInvoiceAction,
AbilitySubject, AbilitySubject,
} from '@/interfaces'; } from '@/interfaces';
import SaleInvoicePdf from '@/services/Sales/SaleInvoicePdf';
import SaleInvoiceWriteoff from '@/services/Sales/SaleInvoiceWriteoff';
import SaleInvoiceNotifyBySms from '@/services/Sales/SaleInvoiceNotifyBySms';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { SaleInvoiceApplication } from '@/services/Sales/Invoices/SaleInvoicesApplication'; import InvoicePaymentsService from '@/services/Sales/Invoices/InvoicePaymentsService';
const ACCEPT_TYPE = { const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf', APPLICATION_PDF: 'application/pdf',
@@ -21,15 +25,27 @@ const ACCEPT_TYPE = {
@Service() @Service()
export default class SaleInvoicesController extends BaseController { export default class SaleInvoicesController extends BaseController {
@Inject() @Inject()
private saleInvoiceApplication: SaleInvoiceApplication; saleInvoiceService: SaleInvoiceService;
@Inject() @Inject()
private dynamicListService: DynamicListingService; dynamicListService: DynamicListingService;
@Inject()
saleInvoicePdf: SaleInvoicePdf;
@Inject()
saleInvoiceWriteoff: SaleInvoiceWriteoff;
@Inject()
saleInvoiceSmsNotify: SaleInvoiceNotifyBySms;
@Inject()
invoicePaymentsSerivce: InvoicePaymentsService;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.post( router.post(
@@ -151,7 +167,7 @@ export default class SaleInvoicesController extends BaseController {
/** /**
* Sale invoice validation schema. * Sale invoice validation schema.
*/ */
private get saleInvoiceValidationSchema() { get saleInvoiceValidationSchema() {
return [ return [
check('customer_id').exists().isNumeric().toInt(), check('customer_id').exists().isNumeric().toInt(),
check('invoice_date').exists().isISO8601().toDate(), check('invoice_date').exists().isISO8601().toDate(),
@@ -169,9 +185,8 @@ export default class SaleInvoicesController extends BaseController {
check('branch_id').optional({ nullable: true }).isNumeric().toInt(), check('branch_id').optional({ nullable: true }).isNumeric().toInt(),
check('project_id').optional({ nullable: true }).isNumeric().toInt(), check('project_id').optional({ nullable: true }).isNumeric().toInt(),
check('is_inclusive_tax').optional().isBoolean().toBoolean(),
check('entries').exists().isArray({ min: 1 }), check('entries').exists().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(),
@@ -184,15 +199,6 @@ export default class SaleInvoicesController extends BaseController {
.optional({ nullable: true }) .optional({ nullable: true })
.trim() .trim()
.escape(), .escape(),
check('entries.*.tax_code')
.optional({ nullable: true })
.trim()
.escape()
.isString(),
check('entries.*.tax_rate_id')
.optional({ nullable: true })
.isNumeric()
.toInt(),
check('entries.*.warehouse_id') check('entries.*.warehouse_id')
.optional({ nullable: true }) .optional({ nullable: true })
.isNumeric() .isNumeric()
@@ -221,14 +227,14 @@ export default class SaleInvoicesController extends BaseController {
/** /**
* Specific sale invoice validation schema. * Specific sale invoice validation schema.
*/ */
private get specificSaleInvoiceValidation() { get specificSaleInvoiceValidation() {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
/** /**
* Sales invoices list validation schema. * Sales invoices list validation schema.
*/ */
private get saleInvoiceListValidationSchema() { get saleInvoiceListValidationSchema() {
return [ return [
query('view_slug').optional({ nullable: true }).isString().trim(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -243,7 +249,7 @@ export default class SaleInvoicesController extends BaseController {
/** /**
* Due sale invoice list validation schema. * Due sale invoice list validation schema.
*/ */
private get dueSalesInvoicesListValidationSchema() { get dueSalesInvoicesListValidationSchema() {
return [query('customer_id').optional().isNumeric().toInt()]; return [query('customer_id').optional().isNumeric().toInt()];
} }
@@ -253,22 +259,17 @@ export default class SaleInvoicesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {Function} next * @param {Function} next
*/ */
private async newSaleInvoice( async newSaleInvoice(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const saleInvoiceDTO: ISaleInvoiceCreateDTO = this.matchedBodyData(req); const saleInvoiceDTO: ISaleInvoiceCreateDTO = this.matchedBodyData(req);
try { try {
// Creates a new sale invoice with associated entries. // Creates a new sale invoice with associated entries.
const storedSaleInvoice = const storedSaleInvoice = await this.saleInvoiceService.createSaleInvoice(
await this.saleInvoiceApplication.createSaleInvoice( tenantId,
tenantId, saleInvoiceDTO,
saleInvoiceDTO, user
user );
);
return res.status(200).send({ return res.status(200).send({
id: storedSaleInvoice.id, id: storedSaleInvoice.id,
message: 'The sale invoice has been created successfully.', message: 'The sale invoice has been created successfully.',
@@ -284,18 +285,14 @@ export default class SaleInvoicesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {Function} next * @param {Function} next
*/ */
private async editSaleInvoice( async editSaleInvoice(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const { id: saleInvoiceId } = req.params; const { id: saleInvoiceId } = req.params;
const saleInvoiceOTD: ISaleInvoiceDTO = this.matchedBodyData(req); const saleInvoiceOTD: ISaleInvoiceDTO = this.matchedBodyData(req);
try { try {
// Update the given sale invoice details. // Update the given sale invoice details.
await this.saleInvoiceApplication.editSaleInvoice( await this.saleInvoiceService.editSaleInvoice(
tenantId, tenantId,
saleInvoiceId, saleInvoiceId,
saleInvoiceOTD, saleInvoiceOTD,
@@ -316,16 +313,12 @@ export default class SaleInvoicesController extends BaseController {
* @param {Response} res - * @param {Response} res -
* @param {NextFunction} next - * @param {NextFunction} next -
*/ */
private async deliverSaleInvoice( async deliverSaleInvoice(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, user } = req; const { tenantId, user } = req;
const { id: saleInvoiceId } = req.params; const { id: saleInvoiceId } = req.params;
try { try {
await this.saleInvoiceApplication.deliverSaleInvoice( await this.saleInvoiceService.deliverSaleInvoice(
tenantId, tenantId,
saleInvoiceId, saleInvoiceId,
user user
@@ -345,17 +338,13 @@ export default class SaleInvoicesController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {Function} next * @param {Function} next
*/ */
private async deleteSaleInvoice( async deleteSaleInvoice(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: saleInvoiceId } = req.params; const { id: saleInvoiceId } = req.params;
const { tenantId, user } = req; const { tenantId, user } = req;
try { try {
// Deletes the sale invoice with associated entries and journal transaction. // Deletes the sale invoice with associated entries and journal transaction.
await this.saleInvoiceApplication.deleteSaleInvoice( await this.saleInvoiceService.deleteSaleInvoice(
tenantId, tenantId,
saleInvoiceId, saleInvoiceId,
user user
@@ -375,16 +364,12 @@ export default class SaleInvoicesController extends BaseController {
* @param {Request} req - Request object. * @param {Request} req - Request object.
* @param {Response} res - Response object. * @param {Response} res - Response object.
*/ */
private async getSaleInvoice( async getSaleInvoice(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { id: saleInvoiceId } = req.params; const { id: saleInvoiceId } = req.params;
const { tenantId, user } = req; const { tenantId, user } = req;
try { try {
const saleInvoice = await this.saleInvoiceApplication.getSaleInvoice( const saleInvoice = await this.saleInvoiceService.getSaleInvoice(
tenantId, tenantId,
saleInvoiceId, saleInvoiceId,
user user
@@ -399,7 +384,7 @@ export default class SaleInvoicesController extends BaseController {
}, },
// PDF content type. // PDF content type.
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { [ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = await this.saleInvoiceApplication.saleInvoicePdf( const pdfContent = await this.saleInvoicePdf.saleInvoicePdf(
tenantId, tenantId,
saleInvoice saleInvoice
); );
@@ -435,7 +420,7 @@ export default class SaleInvoicesController extends BaseController {
}; };
try { try {
const { salesInvoices, filterMeta, pagination } = const { salesInvoices, filterMeta, pagination } =
await this.saleInvoiceApplication.getSaleInvoices(tenantId, filter); await this.saleInvoiceService.salesInvoicesList(tenantId, filter);
return res.status(200).send({ return res.status(200).send({
sales_invoices: this.transfromToResponse(salesInvoices), sales_invoices: this.transfromToResponse(salesInvoices),
@@ -463,11 +448,10 @@ export default class SaleInvoicesController extends BaseController {
const { customerId } = this.matchedQueryData(req); const { customerId } = this.matchedQueryData(req);
try { try {
const salesInvoices = const salesInvoices = await this.saleInvoiceService.getPayableInvoices(
await this.saleInvoiceApplication.getReceivableSaleInvoices( tenantId,
tenantId, customerId
customerId );
);
return res.status(200).send({ return res.status(200).send({
sales_invoices: this.transfromToResponse(salesInvoices), sales_invoices: this.transfromToResponse(salesInvoices),
}); });
@@ -493,7 +477,7 @@ export default class SaleInvoicesController extends BaseController {
const writeoffDTO = this.matchedBodyData(req); const writeoffDTO = this.matchedBodyData(req);
try { try {
const saleInvoice = await this.saleInvoiceApplication.writeOff( const saleInvoice = await this.saleInvoiceWriteoff.writeOff(
tenantId, tenantId,
invoiceId, invoiceId,
writeoffDTO writeoffDTO
@@ -501,7 +485,7 @@ export default class SaleInvoicesController extends BaseController {
return res.status(200).send({ return res.status(200).send({
id: saleInvoice.id, id: saleInvoice.id,
message: 'The given sale invoice has been written-off successfully.', message: 'The given sale invoice has been writte-off successfully.',
}); });
} catch (error) { } catch (error) {
next(error); next(error);
@@ -523,7 +507,7 @@ export default class SaleInvoicesController extends BaseController {
const { id: invoiceId } = req.params; const { id: invoiceId } = req.params;
try { try {
const saleInvoice = await this.saleInvoiceApplication.cancelWrittenoff( const saleInvoice = await this.saleInvoiceWriteoff.cancelWrittenoff(
tenantId, tenantId,
invoiceId invoiceId
); );
@@ -554,12 +538,11 @@ export default class SaleInvoicesController extends BaseController {
const invoiceNotifySmsDTO = this.matchedBodyData(req); const invoiceNotifySmsDTO = this.matchedBodyData(req);
try { try {
const saleInvoice = const saleInvoice = await this.saleInvoiceSmsNotify.notifyBySms(
await this.saleInvoiceApplication.notifySaleInvoiceBySms( tenantId,
tenantId, invoiceId,
invoiceId, invoiceNotifySmsDTO.notificationKey
invoiceNotifySmsDTO.notificationKey );
);
return res.status(200).send({ return res.status(200).send({
id: saleInvoice.id, id: saleInvoice.id,
message: message:
@@ -586,12 +569,11 @@ export default class SaleInvoicesController extends BaseController {
const smsDetailsDTO = this.matchedQueryData(req); const smsDetailsDTO = this.matchedQueryData(req);
try { try {
const invoiceSmsDetails = const invoiceSmsDetails = await this.saleInvoiceSmsNotify.smsDetails(
await this.saleInvoiceApplication.getSaleInvoiceSmsDetails( tenantId,
tenantId, invoiceId,
invoiceId, smsDetailsDTO
smsDetailsDTO );
);
return res.status(200).send({ return res.status(200).send({
data: invoiceSmsDetails, data: invoiceSmsDetails,
}); });
@@ -617,7 +599,7 @@ export default class SaleInvoicesController extends BaseController {
try { try {
const invoicePayments = const invoicePayments =
await this.saleInvoiceApplication.getInvoicePayments( await this.invoicePaymentsSerivce.getInvoicePayments(
tenantId, tenantId,
invoiceId invoiceId
); );
@@ -766,16 +748,6 @@ export default class SaleInvoicesController 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: 5000 }],
});
}
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: 5100 }],
});
}
} }
next(error); next(error);
} }

View File

@@ -2,26 +2,34 @@ import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator'; import { check, param, query } from 'express-validator';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import SaleReceiptService from '@/services/Sales/SalesReceipts';
import SaleReceiptsPdfService from '@/services/Sales/Receipts/SaleReceiptsPdfService';
import BaseController from '../BaseController'; import BaseController from '../BaseController';
import { ISaleReceiptDTO } from '@/interfaces/SaleReceipt'; import { ISaleReceiptDTO } from '@/interfaces/SaleReceipt';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import SaleReceiptNotifyBySms from '@/services/Sales/SaleReceiptNotifyBySms';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { AbilitySubject, SaleReceiptAction } from '@/interfaces'; import { AbilitySubject, SaleReceiptAction } from '@/interfaces';
import { SaleReceiptApplication } from '@/services/Sales/Receipts/SaleReceiptApplication';
@Service() @Service()
export default class SalesReceiptsController extends BaseController { export default class SalesReceiptsController extends BaseController {
@Inject() @Inject()
private saleReceiptsApplication: SaleReceiptApplication; saleReceiptService: SaleReceiptService;
@Inject() @Inject()
private dynamicListService: DynamicListingService; saleReceiptsPdf: SaleReceiptsPdfService;
@Inject()
dynamicListService: DynamicListingService;
@Inject()
saleReceiptSmsNotify: SaleReceiptNotifyBySms;
/** /**
* Router constructor. * Router constructor.
*/ */
public router() { router() {
const router = Router(); const router = Router();
router.post( router.post(
@@ -97,7 +105,7 @@ export default class SalesReceiptsController extends BaseController {
* Sales receipt validation schema. * Sales receipt validation schema.
* @return {Array} * @return {Array}
*/ */
private get salesReceiptsValidationSchema() { get salesReceiptsValidationSchema() {
return [ return [
check('customer_id').exists().isNumeric().toInt(), check('customer_id').exists().isNumeric().toInt(),
check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(), check('exchange_rate').optional().isFloat({ gt: 0 }).toFloat(),
@@ -138,14 +146,14 @@ export default class SalesReceiptsController extends BaseController {
/** /**
* Specific sale receipt validation schema. * Specific sale receipt validation schema.
*/ */
private get specificReceiptValidationSchema() { get specificReceiptValidationSchema() {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
/** /**
* List sales receipts validation schema. * List sales receipts validation schema.
*/ */
private get listSalesReceiptsValidationSchema() { get listSalesReceiptsValidationSchema() {
return [ return [
query('view_slug').optional().isString().trim(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
@@ -162,21 +170,16 @@ export default class SalesReceiptsController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async newSaleReceipt( async newSaleReceipt(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const saleReceiptDTO: ISaleReceiptDTO = this.matchedBodyData(req); const saleReceiptDTO: ISaleReceiptDTO = this.matchedBodyData(req);
try { try {
// Store the given sale receipt details with associated entries. // Store the given sale receipt details with associated entries.
const storedSaleReceipt = const storedSaleReceipt = await this.saleReceiptService.createSaleReceipt(
await this.saleReceiptsApplication.createSaleReceipt( tenantId,
tenantId, saleReceiptDTO
saleReceiptDTO );
);
return res.status(200).send({ return res.status(200).send({
id: storedSaleReceipt.id, id: storedSaleReceipt.id,
message: 'Sale receipt has been created successfully.', message: 'Sale receipt has been created successfully.',
@@ -191,20 +194,13 @@ export default class SalesReceiptsController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async deleteSaleReceipt( async deleteSaleReceipt(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: saleReceiptId } = req.params; const { id: saleReceiptId } = req.params;
try { try {
// Deletes the sale receipt. // Deletes the sale receipt.
await this.saleReceiptsApplication.deleteSaleReceipt( await this.saleReceiptService.deleteSaleReceipt(tenantId, saleReceiptId);
tenantId,
saleReceiptId
);
return res.status(200).send({ return res.status(200).send({
id: saleReceiptId, id: saleReceiptId,
@@ -221,18 +217,14 @@ export default class SalesReceiptsController extends BaseController {
* @param {Request} req - * @param {Request} req -
* @param {Response} res - * @param {Response} res -
*/ */
private async editSaleReceipt( async editSaleReceipt(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: saleReceiptId } = req.params; const { id: saleReceiptId } = req.params;
const saleReceipt = this.matchedBodyData(req); const saleReceipt = this.matchedBodyData(req);
try { try {
// Update the given sale receipt details. // Update the given sale receipt details.
await this.saleReceiptsApplication.editSaleReceipt( await this.saleReceiptService.editSaleReceipt(
tenantId, tenantId,
saleReceiptId, saleReceiptId,
saleReceipt saleReceipt
@@ -252,20 +244,13 @@ export default class SalesReceiptsController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
private async closeSaleReceipt( async closeSaleReceipt(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const { id: saleReceiptId } = req.params; const { id: saleReceiptId } = req.params;
try { try {
// Update the given sale receipt details. // Update the given sale receipt details.
await this.saleReceiptsApplication.closeSaleReceipt( await this.saleReceiptService.closeSaleReceipt(tenantId, saleReceiptId);
tenantId,
saleReceiptId
);
return res.status(200).send({ return res.status(200).send({
id: saleReceiptId, id: saleReceiptId,
message: 'Sale receipt has been closed successfully.', message: 'Sale receipt has been closed successfully.',
@@ -280,11 +265,7 @@ export default class SalesReceiptsController extends BaseController {
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
private async getSalesReceipts( async getSalesReceipts(req: Request, res: Response, next: NextFunction) {
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId } = req; const { tenantId } = req;
const filter = { const filter = {
sortOrder: 'desc', sortOrder: 'desc',
@@ -293,9 +274,10 @@ export default class SalesReceiptsController extends BaseController {
pageSize: 12, pageSize: 12,
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const { data, pagination, filterMeta } = const { data, pagination, filterMeta } =
await this.saleReceiptsApplication.getSaleReceipts(tenantId, filter); await this.saleReceiptService.salesReceiptsList(tenantId, filter);
const response = this.transfromToResponse({ const response = this.transfromToResponse({
data, data,
@@ -319,10 +301,11 @@ export default class SalesReceiptsController extends BaseController {
const { tenantId } = req; const { tenantId } = req;
try { try {
const saleReceipt = await this.saleReceiptsApplication.getSaleReceipt( const saleReceipt = await this.saleReceiptService.getSaleReceipt(
tenantId, tenantId,
saleReceiptId saleReceiptId
); );
res.format({ res.format({
'application/json': () => { 'application/json': () => {
return res return res
@@ -330,11 +313,10 @@ export default class SalesReceiptsController extends BaseController {
.send(this.transfromToResponse({ saleReceipt })); .send(this.transfromToResponse({ saleReceipt }));
}, },
'application/pdf': async () => { 'application/pdf': async () => {
const pdfContent = const pdfContent = await this.saleReceiptsPdf.saleReceiptPdf(
await this.saleReceiptsApplication.getSaleReceiptPdf( tenantId,
tenantId, saleReceipt
saleReceipt );
);
res.set({ res.set({
'Content-Type': 'application/pdf', 'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length, 'Content-Length': pdfContent.length,
@@ -362,11 +344,10 @@ export default class SalesReceiptsController extends BaseController {
const { id: receiptId } = req.params; const { id: receiptId } = req.params;
try { try {
const saleReceipt = const saleReceipt = await this.saleReceiptSmsNotify.notifyBySms(
await this.saleReceiptsApplication.saleReceiptNotifyBySms( tenantId,
tenantId, receiptId
receiptId );
);
return res.status(200).send({ return res.status(200).send({
id: saleReceipt.id, id: saleReceipt.id,
message: message:
@@ -392,11 +373,10 @@ export default class SalesReceiptsController extends BaseController {
const { id: receiptId } = req.params; const { id: receiptId } = req.params;
try { try {
const smsDetails = const smsDetails = await this.saleReceiptSmsNotify.smsDetails(
await this.saleReceiptsApplication.getSaleReceiptSmsDetails( tenantId,
tenantId, receiptId
receiptId );
);
return res.status(200).send({ return res.status(200).send({
data: smsDetails, data: smsDetails,
}); });

View File

@@ -1,10 +1,10 @@
import { Router } from 'express'; import { Router } from 'express';
import { Container, Service } from 'typedi'; import { Container, Service } from 'typedi';
import SalesInvoices from './SalesInvoices'
import SalesEstimates from './SalesEstimates'; import SalesEstimates from './SalesEstimates';
import SalesReceipts from './SalesReceipts'; import SalesReceipts from './SalesReceipts';
import CreditNotes from './CreditNotes'; import SalesInvoices from './SalesInvoices'
import PaymentReceives from './PaymentReceives'; import PaymentReceives from './PaymentReceives';
import CreditNotes from './CreditNotes';
@Service() @Service()
export default class SalesController { export default class SalesController {
/** /**

View File

@@ -1,278 +0,0 @@
import { Inject, Service } from 'typedi';
import { Router, Request, Response } from 'express';
import { body, param } from 'express-validator';
import BaseController from '@/api/controllers/BaseController';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import { TaxRatesApplication } from '@/services/TaxRates/TaxRatesApplication';
import CheckAbilities from '@/api/middleware/CheckPolicies';
import { ServiceError } from '@/exceptions';
import { ERRORS } from '@/services/TaxRates/constants';
import { AbilitySubject, TaxRateAction } from '@/interfaces';
@Service()
export class TaxRatesController extends BaseController {
@Inject()
private taxRatesApplication: TaxRatesApplication;
/**
* Router constructor.
*/
public router() {
const router = Router();
router.post(
'/',
CheckAbilities(TaxRateAction.CREATE, AbilitySubject.TaxRate),
this.taxRateValidationSchema,
this.validationResult,
asyncMiddleware(this.createTaxRate.bind(this)),
this.handleServiceErrors
);
router.post(
'/:id',
CheckAbilities(TaxRateAction.EDIT, AbilitySubject.TaxRate),
[param('id').exists().toInt(), ...this.taxRateValidationSchema],
this.validationResult,
asyncMiddleware(this.editTaxRate.bind(this)),
this.handleServiceErrors
);
router.post(
'/:id/active',
CheckAbilities(TaxRateAction.EDIT, AbilitySubject.TaxRate),
[param('id').exists().toInt()],
this.validationResult,
asyncMiddleware(this.activateTaxRate.bind(this)),
this.handleServiceErrors
);
router.post(
'/:id/inactive',
CheckAbilities(TaxRateAction.EDIT, AbilitySubject.TaxRate),
[param('id').exists().toInt()],
this.validationResult,
asyncMiddleware(this.inactivateTaxRate.bind(this)),
this.handleServiceErrors
);
router.delete(
'/:id',
CheckAbilities(TaxRateAction.DELETE, AbilitySubject.TaxRate),
[param('id').exists().toInt()],
this.validationResult,
asyncMiddleware(this.deleteTaxRate.bind(this)),
this.handleServiceErrors
);
router.get(
'/:id',
CheckAbilities(TaxRateAction.VIEW, AbilitySubject.TaxRate),
[param('id').exists().toInt()],
this.validationResult,
asyncMiddleware(this.getTaxRate.bind(this)),
this.handleServiceErrors
);
router.get(
'/',
CheckAbilities(TaxRateAction.VIEW, AbilitySubject.TaxRate),
this.validationResult,
asyncMiddleware(this.getTaxRates.bind(this)),
this.handleServiceErrors
);
return router;
}
/**
* Tax rate validation schema.
*/
private get taxRateValidationSchema() {
return [
body('name').exists(),
body('code').exists().isString(),
body('rate').exists().isNumeric().toFloat(),
body('description').optional().trim().isString(),
body('is_non_recoverable').optional().isBoolean().default(false),
body('is_compound').optional().isBoolean().default(false),
body('active').optional().isBoolean().default(false),
];
}
/**
* Creates a new tax rate.
* @param {Request} req -
* @param {Response} res -
*/
public async createTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const createTaxRateDTO = this.matchedBodyData(req);
try {
const taxRate = await this.taxRatesApplication.createTaxRate(
tenantId,
createTaxRateDTO
);
return res.status(200).send({
data: taxRate,
});
} catch (error) {
next(error);
}
}
/**
* Edits the given tax rate.
* @param {Request} req -
* @param {Response} res -
*/
public async editTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const editTaxRateDTO = this.matchedBodyData(req);
const { id: taxRateId } = req.params;
try {
const taxRate = await this.taxRatesApplication.editTaxRate(
tenantId,
taxRateId,
editTaxRateDTO
);
return res.status(200).send({
data: taxRate,
});
} catch (error) {
next(error);
}
}
/**
* Deletes the given tax rate.
* @param {Request} req -
* @param {Response} res -
*/
public async deleteTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const { id: taxRateId } = req.params;
try {
await this.taxRatesApplication.deleteTaxRate(tenantId, taxRateId);
return res.status(200).send({
code: 200,
message: 'The tax rate has been deleted successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Retrieves the given tax rate.
* @param {Request} req -
* @param {Response} res -
*/
public async getTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const { id: taxRateId } = req.params;
try {
const taxRate = await this.taxRatesApplication.getTaxRate(
tenantId,
taxRateId
);
return res.status(200).send({ data: taxRate });
} catch (error) {
next(error);
}
}
/**
* Retrieves the tax rates list.
* @param {Request} req -
* @param {Response} res -
*/
public async getTaxRates(req: Request, res: Response, next) {
const { tenantId } = req;
try {
const taxRates = await this.taxRatesApplication.getTaxRates(tenantId);
return res.status(200).send({ data: taxRates });
} catch (error) {
next(error);
}
}
/**
* Inactivates the given tax rate.
* @param req
* @param res
* @param next
* @returns
*/
public async inactivateTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const { id: taxRateId } = req.params;
try {
await this.taxRatesApplication.inactivateTaxRate(tenantId, taxRateId);
return res.status(200).send({
id: taxRateId,
message: 'The given tax rate has been inactivated successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Inactivates the given tax rate.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
* @returns
*/
public async activateTaxRate(req: Request, res: Response, next) {
const { tenantId } = req;
const { id: taxRateId } = req.params;
try {
await this.taxRatesApplication.activateTaxRate(tenantId, taxRateId);
return res.status(200).send({
id: taxRateId,
message: 'The given tax rate has been activated successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Handles service errors.
* @param {Error} error
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
private handleServiceErrors(error: Error, req: Request, res: Response, next) {
if (error instanceof ServiceError) {
if (error.errorType === ERRORS.TAX_CODE_NOT_UNIQUE) {
return res.boom.badRequest(null, {
errors: [{ type: ERRORS.TAX_CODE_NOT_UNIQUE, code: 100 }],
});
}
if (error.errorType === ERRORS.TAX_RATE_NOT_FOUND) {
return res.boom.badRequest(null, {
errors: [{ type: ERRORS.TAX_RATE_NOT_FOUND, code: 200 }],
});
}
if (error.errorType === ERRORS.TAX_RATE_ALREADY_INACTIVE) {
return res.boom.badRequest(null, {
errors: [{ type: ERRORS.TAX_RATE_ALREADY_INACTIVE, code: 300 }],
});
}
if (error.errorType === ERRORS.TAX_RATE_ALREADY_ACTIVE) {
return res.boom.badRequest(null, {
errors: [{ type: ERRORS.TAX_RATE_ALREADY_ACTIVE, code: 400 }],
});
}
}
next(error);
}
}

View File

@@ -55,7 +55,6 @@ import { InventoryItemsCostController } from './controllers/Inventory/Inventorty
import { ProjectsController } from './controllers/Projects/Projects'; import { ProjectsController } from './controllers/Projects/Projects';
import { ProjectTasksController } from './controllers/Projects/Tasks'; import { ProjectTasksController } from './controllers/Projects/Tasks';
import { ProjectTimesController } from './controllers/Projects/Times'; import { ProjectTimesController } from './controllers/Projects/Times';
import { TaxRatesController } from './controllers/TaxRates/TaxRates';
export default () => { export default () => {
const app = Router(); const app = Router();
@@ -130,7 +129,6 @@ export default () => {
); );
dashboard.use('/warehouses', Container.get(WarehousesController).router()); dashboard.use('/warehouses', Container.get(WarehousesController).router());
dashboard.use('/projects', Container.get(ProjectsController).router()); dashboard.use('/projects', Container.get(ProjectsController).router());
dashboard.use('/tax-rates', Container.get(TaxRatesController).router());
dashboard.use('/', Container.get(ProjectTasksController).router()); dashboard.use('/', Container.get(ProjectTasksController).router());
dashboard.use('/', Container.get(ProjectTimesController).router()); dashboard.use('/', Container.get(ProjectTimesController).router());

View File

@@ -1,12 +1,9 @@
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import path from 'path'; import path from 'path';
import { toInteger } from 'lodash';
import { castCommaListEnvVarToArray, parseBoolean } from '@/utils'; import { castCommaListEnvVarToArray, parseBoolean } from '@/utils';
dotenv.config(); dotenv.config();
const API_RATE_LIMIT = process.env.API_RATE_LIMIT?.split(',') || [];
module.exports = { module.exports = {
/** /**
* Your favorite port * Your favorite port
@@ -100,7 +97,7 @@ module.exports = {
jwtSecret: process.env.JWT_SECRET, jwtSecret: process.env.JWT_SECRET,
/** /**
* *
*/ */
resetPasswordSeconds: 600, resetPasswordSeconds: 600,
@@ -133,9 +130,9 @@ module.exports = {
blockDuration: 60 * 15, blockDuration: 60 * 15,
}, },
requests: { requests: {
points: API_RATE_LIMIT[0] ? toInteger(API_RATE_LIMIT[0]) : 120, points: 60,
duration: API_RATE_LIMIT[1] ? toInteger(API_RATE_LIMIT[1]) : 60, duration: 60,
blockDuration: API_RATE_LIMIT[2] ? toInteger(API_RATE_LIMIT[2]) : 60 * 10, blockDuration: 60 * 10,
}, },
}, },

View File

@@ -1,28 +0,0 @@
export const TransactionTypes = {
SaleInvoice: 'Sale invoice',
SaleReceipt: 'Sale receipt',
PaymentReceive: 'Payment receive',
Bill: 'Bill',
BillPayment: 'Payment made',
VendorOpeningBalance: 'Vendor opening balance',
CustomerOpeningBalance: 'Customer opening balance',
InventoryAdjustment: 'Inventory adjustment',
ManualJournal: 'Manual journal',
Journal: 'Manual journal',
Expense: 'Expense',
OwnerContribution: 'Owner contribution',
TransferToAccount: 'Transfer to account',
TransferFromAccount: 'Transfer from account',
OtherIncome: 'Other income',
OtherExpense: 'Other expense',
OwnerDrawing: 'Owner drawing',
InvoiceWriteOff: 'Invoice write-off',
CreditNote: 'transaction_type.credit_note',
VendorCredit: 'transaction_type.vendor_credit',
RefundCreditNote: 'transaction_type.refund_credit_note',
RefundVendorCredit: 'transaction_type.refund_vendor_credit',
LandedCost: 'transaction_type.landed_cost',
};

View File

@@ -1,52 +0,0 @@
exports.up = (knex) => {
return knex.schema
.createTable('tax_rates', (table) => {
table.increments();
table.string('name');
table.string('code');
table.decimal('rate');
table.string('description');
table.boolean('is_non_recoverable').defaultTo(false);
table.boolean('is_compound').defaultTo(false);
table.boolean('active').defaultTo(false);
table.date('deleted_at');
table.timestamps();
})
.table('items_entries', (table) => {
table.boolean('is_inclusive_tax').defaultTo(false);
table
.integer('tax_rate_id')
.unsigned()
.references('id')
.inTable('tax_rates');
table.decimal('tax_rate').unsigned();
})
.table('sales_invoices', (table) => {
table.boolean('is_inclusive_tax').defaultTo(false);
table.decimal('tax_amount_withheld');
})
.createTable('tax_rate_transactions', (table) => {
table.increments('id');
table
.integer('tax_rate_id')
.unsigned()
.references('id')
.inTable('tax_rates');
table.string('reference_type');
table.integer('reference_id');
table.decimal('rate').unsigned();
table.integer('tax_account_id').unsigned();
})
.table('accounts_transactions', (table) => {
table
.integer('tax_rate_id')
.unsigned()
.references('id')
.inTable('tax_rates');
table.decimal('tax_rate').unsigned();
});
};
exports.down = (knex) => {
return knex.schema.dropTableIfExists('tax_rates');
};

View File

@@ -1,14 +0,0 @@
import { TenantSeeder } from '@/lib/Seeder/TenantSeeder';
import { InitialTaxRates } from '../data/TaxRates';
export default class SeedTaxRates extends TenantSeeder {
/**
* Seeds initial tax rates to the organization.
*/
up(knex) {
return knex('tax_rates').then(async () => {
// Inserts seed entries.
return knex('tax_rates').insert(InitialTaxRates);
});
}
}

View File

@@ -1,16 +0,0 @@
import { TenantSeeder } from '@/lib/Seeder/TenantSeeder';
import { InitialTaxRates } from '../data/TaxRates';
export default class UpdateTaxPayableAccount extends TenantSeeder {
/**
* Seeds initial tax rates to the organization.
*/
up(knex) {
return knex('accounts').then(async () => {
// Inserts seed entries.
return knex('accounts').where('slug', 'tax-payable').update({
account_type: 'tax-payable',
});
});
}
}

View File

@@ -1,30 +0,0 @@
export const InitialTaxRates = [
{
name: 'Tax Exempt',
code: 'TAX-EXEMPT',
description: 'Exempts goods or services from taxes.',
rate: 0,
active: 1,
},
{
name: 'Tax on Purchases',
code: 'TAX-PURCHASES',
description: 'Fee added to the cost when you buy items.',
rate: 0,
active: 1,
},
{
name: 'Tax on Sales',
code: 'TAX-SALES',
description: 'Fee added to the cost when you sell items.',
rate: 0,
active: 1,
},
{
name: 'Sales Tax on Imports',
code: 'TAX-IMPORTS',
description: 'Fee added to the cost when you sale to another country.',
rate: 0,
active: 1,
},
];

View File

@@ -1,17 +1,7 @@
export const TaxPayableAccount = {
name: 'Tax Payable',
slug: 'tax-payable',
account_type: 'tax-payable',
code: '20006',
description: '',
active: 1,
index: 1,
predefined: 1,
};
export default [ export default [
{ {
name: 'Bank Account', name:'Bank Account',
slug: 'bank-account', slug: 'bank-account',
account_type: 'bank', account_type: 'bank',
code: '10001', code: '10001',
@@ -21,7 +11,7 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Saving Bank Account', name:'Saving Bank Account',
slug: 'saving-bank-account', slug: 'saving-bank-account',
account_type: 'bank', account_type: 'bank',
code: '10002', code: '10002',
@@ -31,7 +21,7 @@ export default [
predefined: 0, predefined: 0,
}, },
{ {
name: 'Undeposited Funds', name:'Undeposited Funds',
slug: 'undeposited-funds', slug: 'undeposited-funds',
account_type: 'cash', account_type: 'cash',
code: '10003', code: '10003',
@@ -41,7 +31,7 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Petty Cash', name:'Petty Cash',
slug: 'petty-cash', slug: 'petty-cash',
account_type: 'cash', account_type: 'cash',
code: '10004', code: '10004',
@@ -51,7 +41,7 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Computer Equipment', name:'Computer Equipment',
slug: 'computer-equipment', slug: 'computer-equipment',
code: '10005', code: '10005',
account_type: 'fixed-asset', account_type: 'fixed-asset',
@@ -62,7 +52,7 @@ export default [
description: '', description: '',
}, },
{ {
name: 'Office Equipment', name:'Office Equipment',
slug: 'office-equipment', slug: 'office-equipment',
code: '10006', code: '10006',
account_type: 'fixed-asset', account_type: 'fixed-asset',
@@ -73,7 +63,7 @@ export default [
description: '', description: '',
}, },
{ {
name: 'Accounts Receivable (A/R)', name:'Accounts Receivable (A/R)',
slug: 'accounts-receivable', slug: 'accounts-receivable',
account_type: 'accounts-receivable', account_type: 'accounts-receivable',
code: '10007', code: '10007',
@@ -83,7 +73,7 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Inventory Asset', name:'Inventory Asset',
slug: 'inventory-asset', slug: 'inventory-asset',
code: '10008', code: '10008',
account_type: 'inventory', account_type: 'inventory',
@@ -91,13 +81,12 @@ export default [
parent_account_id: null, parent_account_id: null,
index: 1, index: 1,
active: 1, active: 1,
description: description:'An account that holds valuation of products or goods that availiable for sale.',
'An account that holds valuation of products or goods that available for sale.',
}, },
// Libilities // Libilities
{ {
name: 'Accounts Payable (A/P)', name:'Accounts Payable (A/P)',
slug: 'accounts-payable', slug: 'accounts-payable',
account_type: 'accounts-payable', account_type: 'accounts-payable',
parent_account_id: null, parent_account_id: null,
@@ -108,39 +97,38 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Owner A Drawings', name:'Owner A Drawings',
slug: 'owner-drawings', slug: 'owner-drawings',
account_type: 'other-current-liability', account_type: 'other-current-liability',
parent_account_id: null, parent_account_id: null,
code: '20002', code: '20002',
description: 'Withdrawals by the owners.', description:'Withdrawals by the owners.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 0, predefined: 0,
}, },
{ {
name: 'Loan', name:'Loan',
slug: 'owner-drawings', slug: 'owner-drawings',
account_type: 'other-current-liability', account_type: 'other-current-liability',
code: '20003', code: '20003',
description: 'Money that has been borrowed from a creditor.', description:'Money that has been borrowed from a creditor.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 0, predefined: 0,
}, },
{ {
name: 'Opening Balance Liabilities', name:'Opening Balance Liabilities',
slug: 'opening-balance-liabilities', slug: 'opening-balance-liabilities',
account_type: 'other-current-liability', account_type: 'other-current-liability',
code: '20004', code: '20004',
description: description:'This account will hold the difference in the debits and credits entered during the opening balance..',
'This account will hold the difference in the debits and credits entered during the opening balance..',
active: 1, active: 1,
index: 1, index: 1,
predefined: 0, predefined: 0,
}, },
{ {
name: 'Revenue Received in Advance', name:'Revenue Received in Advance',
slug: 'revenue-received-in-advance', slug: 'revenue-received-in-advance',
account_type: 'other-current-liability', account_type: 'other-current-liability',
parent_account_id: null, parent_account_id: null,
@@ -150,27 +138,34 @@ export default [
index: 1, index: 1,
predefined: 0, predefined: 0,
}, },
TaxPayableAccount, {
name:'Sales Tax Payable',
slug: 'owner-drawings',
account_type: 'other-current-liability',
code: '20006',
description: '',
active: 1,
index: 1,
predefined: 1,
},
// Equity // Equity
{ {
name: 'Retained Earnings', name:'Retained Earnings',
slug: 'retained-earnings', slug: 'retained-earnings',
account_type: 'equity', account_type: 'equity',
code: '30001', code: '30001',
description: description:'Retained earnings tracks net income from previous fiscal years.',
'Retained earnings tracks net income from previous fiscal years.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 1, predefined: 1,
}, },
{ {
name: 'Opening Balance Equity', name:'Opening Balance Equity',
slug: 'opening-balance-equity', slug: 'opening-balance-equity',
account_type: 'equity', account_type: 'equity',
code: '30002', code: '30002',
description: description:'When you enter opening balances to the accounts, the amounts enter in Opening balance equity. This ensures that you have a correct trial balance sheet for your company, without even specific the second credit or debit entry.',
'When you enter opening balances to the accounts, the amounts enter in Opening balance equity. This ensures that you have a correct trial balance sheet for your company, without even specific the second credit or debit entry.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 1, predefined: 1,
@@ -186,12 +181,11 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: `Drawings`, name:`Drawings`,
slug: 'drawings', slug: 'drawings',
account_type: 'equity', account_type: 'equity',
code: '30003', code: '30003',
description: description:'Goods purchased with the intention of selling these to customers',
'Goods purchased with the intention of selling these to customers',
active: 1, active: 1,
index: 1, index: 1,
predefined: 1, predefined: 1,
@@ -199,7 +193,7 @@ export default [
// Expenses // Expenses
{ {
name: 'Other Expenses', name:'Other Expenses',
slug: 'other-expenses', slug: 'other-expenses',
account_type: 'other-expense', account_type: 'other-expense',
parent_account_id: null, parent_account_id: null,
@@ -210,18 +204,18 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Cost of Goods Sold', name:'Cost of Goods Sold',
slug: 'cost-of-goods-sold', slug: 'cost-of-goods-sold',
account_type: 'cost-of-goods-sold', account_type: 'cost-of-goods-sold',
parent_account_id: null, parent_account_id: null,
code: '40002', code: '40002',
description: 'Tracks the direct cost of the goods sold.', description:'Tracks the direct cost of the goods sold.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 1, predefined: 1,
}, },
{ {
name: 'Office expenses', name:'Office expenses',
slug: 'office-expenses', slug: 'office-expenses',
account_type: 'expense', account_type: 'expense',
parent_account_id: null, parent_account_id: null,
@@ -232,7 +226,7 @@ export default [
predefined: 0, predefined: 0,
}, },
{ {
name: 'Rent', name:'Rent',
slug: 'rent', slug: 'rent',
account_type: 'expense', account_type: 'expense',
parent_account_id: null, parent_account_id: null,
@@ -243,30 +237,29 @@ export default [
predefined: 0, predefined: 0,
}, },
{ {
name: 'Exchange Gain or Loss', name:'Exchange Gain or Loss',
slug: 'exchange-grain-loss', slug: 'exchange-grain-loss',
account_type: 'other-expense', account_type: 'other-expense',
parent_account_id: null, parent_account_id: null,
code: '40005', code: '40005',
description: 'Tracks the gain and losses of the exchange differences.', description:'Tracks the gain and losses of the exchange differences.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 1, predefined: 1,
}, },
{ {
name: 'Bank Fees and Charges', name:'Bank Fees and Charges',
slug: 'bank-fees-and-charges', slug: 'bank-fees-and-charges',
account_type: 'expense', account_type: 'expense',
parent_account_id: null, parent_account_id: null,
code: '40006', code: '40006',
description: description: '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.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 0, predefined: 0,
}, },
{ {
name: 'Depreciation Expense', name:'Depreciation Expense',
slug: 'depreciation-expense', slug: 'depreciation-expense',
account_type: 'expense', account_type: 'expense',
parent_account_id: null, parent_account_id: null,
@@ -279,7 +272,7 @@ export default [
// Income // Income
{ {
name: 'Sales of Product Income', name:'Sales of Product Income',
slug: 'sales-of-product-income', slug: 'sales-of-product-income',
account_type: 'income', account_type: 'income',
predefined: 1, predefined: 1,
@@ -290,7 +283,7 @@ export default [
description: '', description: '',
}, },
{ {
name: 'Sales of Service Income', name:'Sales of Service Income',
slug: 'sales-of-service-income', slug: 'sales-of-service-income',
account_type: 'income', account_type: 'income',
predefined: 0, predefined: 0,
@@ -301,7 +294,7 @@ export default [
description: '', description: '',
}, },
{ {
name: 'Uncategorized Income', name:'Uncategorized Income',
slug: 'uncategorized-income', slug: 'uncategorized-income',
account_type: 'income', account_type: 'income',
parent_account_id: null, parent_account_id: null,
@@ -312,15 +305,14 @@ export default [
predefined: 1, predefined: 1,
}, },
{ {
name: 'Other Income', name:'Other Income',
slug: 'other-income', slug: 'other-income',
account_type: 'other-income', account_type: 'other-income',
parent_account_id: null, parent_account_id: null,
code: '50004', code: '50004',
description: description:'The income activities are not associated to the core business.',
'The income activities are not associated to the core business.',
active: 1, active: 1,
index: 1, index: 1,
predefined: 0, predefined: 0,
}, }
]; ];

View File

@@ -1,36 +1,51 @@
import { import {
IAgingPeriod, IAgingPeriod,
IAgingPeriodTotal, IAgingPeriodTotal,
IAgingAmount, IAgingAmount
IAgingSummaryQuery,
IAgingSummaryTotal,
IAgingSummaryContact,
IAgingSummaryData,
} from './AgingReport'; } from './AgingReport';
import { INumberFormatQuery } from './FinancialStatements'; import {
INumberFormatQuery
} from './FinancialStatements';
export interface IAPAgingSummaryQuery extends IAgingSummaryQuery { export interface IAPAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
vendorsIds: number[]; vendorsIds: number[];
noneZero: boolean;
branchesIds?: number[]
} }
export interface IAPAgingSummaryVendor extends IAgingSummaryContact { export interface IAPAgingSummaryVendor {
vendorName: string; vendorName: string,
} current: IAgingAmount,
aging: IAgingPeriodTotal[],
total: IAgingAmount,
};
export interface IAPAgingSummaryTotal extends IAgingSummaryTotal {} export interface IAPAgingSummaryTotal {
current: IAgingAmount,
aging: IAgingPeriodTotal[],
total: IAgingAmount,
};
export interface IAPAgingSummaryData extends IAgingSummaryData { export interface IAPAgingSummaryData {
vendors: IAPAgingSummaryVendor[]; vendors: IAPAgingSummaryVendor[],
} total: IAPAgingSummaryTotal,
};
export type IAPAgingSummaryColumns = IAgingPeriod[]; export type IAPAgingSummaryColumns = IAgingPeriod[];
export interface IARAgingSummaryMeta { export interface IARAgingSummaryMeta {
baseCurrency: string; baseCurrency: string,
organizationName: string; organizationName: string,
} }
export interface IAPAgingSummaryMeta { export interface IAPAgingSummaryMeta {
baseCurrency: string; baseCurrency: string,
organizationName: string; organizationName: string,
} }

View File

@@ -1,28 +1,37 @@
import { import { IAgingPeriod, IAgingPeriodTotal, IAgingAmount } from './AgingReport';
IAgingPeriod, import { INumberFormatQuery } from './FinancialStatements';
IAgingSummaryQuery,
IAgingSummaryTotal,
IAgingSummaryContact,
IAgingSummaryData,
} from './AgingReport';
export interface IARAgingSummaryQuery extends IAgingSummaryQuery { export interface IARAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
customersIds: number[]; customersIds: number[];
branchesIds: number[];
noneZero: boolean;
} }
export interface IARAgingSummaryCustomer extends IAgingSummaryContact { export interface IARAgingSummaryCustomer {
customerName: string; customerName: string;
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
} }
export interface IARAgingSummaryTotal extends IAgingSummaryTotal {} export interface IARAgingSummaryTotal {
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IARAgingSummaryData extends IAgingSummaryData { export interface IARAgingSummaryData {
customers: IARAgingSummaryCustomer[]; customers: IARAgingSummaryCustomer[];
total: IARAgingSummaryTotal;
} }
export type IARAgingSummaryColumns = IAgingPeriod[]; export type IARAgingSummaryColumns = IAgingPeriod[];
export interface IARAgingSummaryMeta { export interface IARAgingSummaryMeta {
organizationName: string; organizationName: string,
baseCurrency: string; baseCurrency: string,
} }

View File

@@ -58,7 +58,6 @@ export interface IAccountTransaction {
date: string | Date; date: string | Date;
referenceType: string; referenceType: string;
referenceTypeFormatted: string;
referenceId: number; referenceId: number;
referenceNumber?: string; referenceNumber?: string;
@@ -77,9 +76,6 @@ export interface IAccountTransaction {
projectId?: number; projectId?: number;
account?: IAccount; account?: IAccount;
taxRateId?: number;
taxRate?: number;
} }
export interface IAccountResponse extends IAccount {} export interface IAccountResponse extends IAccount {}
@@ -153,11 +149,3 @@ export enum AccountAction {
VIEW = 'View', VIEW = 'View',
TransactionsLocking = 'TransactionsLocking', TransactionsLocking = 'TransactionsLocking',
} }
export enum TaxRateAction {
CREATE = 'Create',
EDIT = 'Edit',
DELETE = 'Delete',
VIEW = 'View',
}

View File

@@ -1,9 +1,6 @@
import { INumberFormatQuery } from './FinancialStatements';
export interface IAgingPeriodTotal extends IAgingPeriod { export interface IAgingPeriodTotal extends IAgingPeriod {
total: IAgingAmount; total: IAgingAmount;
} };
export interface IAgingAmount { export interface IAgingAmount {
amount: number; amount: number;
@@ -23,22 +20,3 @@ export interface IAgingSummaryContact {
aging: IAgingPeriodTotal[]; aging: IAgingPeriodTotal[];
total: IAgingAmount; total: IAgingAmount;
} }
export interface IAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
branchesIds: number[];
noneZero: boolean;
}
export interface IAgingSummaryTotal {
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IAgingSummaryData {
total: IAgingSummaryTotal;
}

View File

@@ -1,7 +1,7 @@
import { Knex } from 'knex'; 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;
@@ -99,17 +99,17 @@ export interface IBillCreatedPayload {
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillCreatingPayload { export interface IBillCreatingPayload{
tenantId: number; tenantId: number;
billDTO: IBillDTO; billDTO: IBillDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillEditingPayload { export interface IBillEditingPayload {
tenantId: number; tenantId: number;
oldBill: IBill; oldBill: IBill;
billDTO: IBillEditDTO; billDTO: IBillEditDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillEditedPayload { export interface IBillEditedPayload {
tenantId: number; tenantId: number;
@@ -129,7 +129,7 @@ export interface IBIllEventDeletedPayload {
export interface IBillEventDeletingPayload { export interface IBillEventDeletingPayload {
tenantId: number; tenantId: number;
oldBill: IBill; oldBill: IBill;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export enum BillAction { export enum BillAction {
Create = 'Create', Create = 'Create',
@@ -138,16 +138,3 @@ export enum BillAction {
View = 'View', View = 'View',
NotifyBySms = 'NotifyBySms', NotifyBySms = 'NotifyBySms',
} }
export interface IBillOpeningPayload {
trx: Knex.Transaction;
tenantId: number;
oldBill: IBill;
}
export interface IBillOpenedPayload {
trx: Knex.Transaction;
bill: IBill;
oldBill: IBill;
tenantId: number;
}

View File

@@ -41,7 +41,7 @@ export interface ICashFlowStatementAccountMeta {
code: string; code: string;
total: ICashFlowStatementTotal; total: ICashFlowStatementTotal;
accountType: string; accountType: string;
adjustmentType: string; adjusmentType: string;
sectionType: ICashFlowStatementSectionType.ACCOUNT; sectionType: ICashFlowStatementSectionType.ACCOUNT;
} }

View File

@@ -37,7 +37,6 @@ export enum ReportsAction {
READ_INVENTORY_ITEM_DETAILS = 'read-inventory-item-details', READ_INVENTORY_ITEM_DETAILS = 'read-inventory-item-details',
READ_CASHFLOW_ACCOUNT_TRANSACTION = 'read-cashflow-account-transactions', READ_CASHFLOW_ACCOUNT_TRANSACTION = 'read-cashflow-account-transactions',
READ_PROJECT_PROFITABILITY_SUMMARY = 'read-project-profitability-summary', READ_PROJECT_PROFITABILITY_SUMMARY = 'read-project-profitability-summary',
READ_SALES_TAX_LIABILITY_SUMMARY = 'read-sales-tax-liability-summary',
} }
export interface IFinancialSheetBranchesQuery { export interface IFinancialSheetBranchesQuery {

View File

@@ -18,11 +18,6 @@ export interface IItemEntry {
rate: number; rate: number;
amount: number; amount: number;
total: number;
amountInclusingTax: number;
amountExludingTax: number;
discountAmount: number;
landedCost: number; landedCost: number;
allocatedCostAmount: number; allocatedCostAmount: number;
unallocatedCostAmount: number; unallocatedCostAmount: number;
@@ -37,10 +32,6 @@ export interface IItemEntry {
projectRefType?: ProjectLinkRefType; projectRefType?: ProjectLinkRefType;
projectRefInvoicedAmount?: number; projectRefInvoicedAmount?: number;
taxRateId: number | null;
taxRate: number;
taxAmount: number;
item?: IItem; item?: IItem;
allocatedCostEntries?: IBillLandedCostEntry[]; allocatedCostEntries?: IBillLandedCostEntry[];
@@ -55,9 +46,6 @@ export interface IItemEntryDTO {
projectRefId?: number; projectRefId?: number;
projectRefType?: ProjectLinkRefType; projectRefType?: ProjectLinkRefType;
projectRefInvoicedAmount?: number; projectRefInvoicedAmount?: number;
taxRateId?: number;
taxCode?: string;
} }
export enum ProjectLinkRefType { export enum ProjectLinkRefType {

View File

@@ -48,9 +48,6 @@ export interface ILedgerEntry {
branchId?: number; branchId?: number;
projectId?: number; projectId?: number;
taxRateId?: number;
taxRate?: number;
entryId?: number; entryId?: number;
createdAt?: Date; createdAt?: Date;

View File

@@ -1,5 +1,6 @@
import { Knex } from 'knex';
import { ISystemUser } from '@/interfaces'; import { ISystemUser } from '@/interfaces';
import { Knex } from 'knex';
import { pick } from 'lodash';
import { ILedgerEntry } from './Ledger'; import { ILedgerEntry } from './Ledger';
import { ISaleInvoice } from './SaleInvoice'; import { ISaleInvoice } from './SaleInvoice';

View File

@@ -1,5 +1,5 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { IItemEntry, IItemEntryDTO } from './ItemEntry'; import { IItemEntry } from './ItemEntry';
import { IDynamicListFilterDTO } from '@/interfaces/DynamicFilter'; import { IDynamicListFilterDTO } from '@/interfaces/DynamicFilter';
export interface ISaleEstimate { export interface ISaleEstimate {
@@ -29,7 +29,7 @@ export interface ISaleEstimateDTO {
estimateDate?: Date; estimateDate?: Date;
reference?: string; reference?: string;
estimateNumber?: string; estimateNumber?: string;
entries: IItemEntryDTO[]; entries: IItemEntry[];
note: string; note: string;
termsConditions: string; termsConditions: string;
sendToEmail: string; sendToEmail: string;

View File

@@ -1,12 +1,11 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { ISystemUser, IAccount, ITaxTransaction } from '@/interfaces'; import { ISystemUser, IAccount } from '@/interfaces';
import { IDynamicListFilter } from '@/interfaces/DynamicFilter'; import { IDynamicListFilter } from '@/interfaces/DynamicFilter';
import { IItemEntry, IItemEntryDTO } from './ItemEntry'; import { IItemEntry, IItemEntryDTO } from './ItemEntry';
export interface ISaleInvoice { export interface ISaleInvoice {
id: number; id: number;
amount: number; balance: number;
amountLocal?: number;
paymentAmount: number; paymentAmount: number;
currencyCode: string; currencyCode: string;
exchangeRate?: number; exchangeRate?: number;
@@ -28,21 +27,12 @@ export interface ISaleInvoice {
branchId?: number; branchId?: number;
projectId?: number; projectId?: number;
writtenoffAmount?: number; localAmount?: number;
writtenoffAmountLocal?: number;
localWrittenoffAmount?: number;
writtenoffExpenseAccountId?: number; writtenoffExpenseAccountId?: number;
writtenoffExpenseAccount?: IAccount; writtenoffExpenseAccount?: IAccount;
taxAmountWithheld: number;
taxAmountWithheldLocal: number;
taxes: ITaxTransaction[];
total: number;
totalLocal: number;
subtotal: number;
subtotalLocal: number;
subtotalExludingTax: number;
} }
export interface ISaleInvoiceDTO { export interface ISaleInvoiceDTO {
@@ -54,15 +44,12 @@ export interface ISaleInvoiceDTO {
exchangeRate?: number; exchangeRate?: number;
invoiceMessage: string; invoiceMessage: string;
termsConditions: string; termsConditions: string;
isTaxExclusive: boolean;
entries: IItemEntryDTO[]; entries: IItemEntryDTO[];
delivered: boolean; delivered: boolean;
warehouseId?: number | null; warehouseId?: number | null;
projectId?: number; projectId?: number;
branchId?: number | null; branchId?: number | null;
isInclusiveTax?: boolean;
} }
export interface ISaleInvoiceCreateDTO extends ISaleInvoiceDTO { export interface ISaleInvoiceCreateDTO extends ISaleInvoiceDTO {
@@ -169,7 +156,6 @@ export interface ISaleInvoiceEventDeliveredPayload {
tenantId: number; tenantId: number;
saleInvoiceId: number; saleInvoiceId: number;
saleInvoice: ISaleInvoice; saleInvoice: ISaleInvoice;
trx: Knex.Transaction;
} }
export interface ISaleInvoiceDeliveringPayload { export interface ISaleInvoiceDeliveringPayload {

View File

@@ -1,51 +0,0 @@
export interface SalesTaxLiabilitySummaryQuery {
fromDate: Date;
toDate: Date;
basis: 'cash' | 'accrual';
}
export interface SalesTaxLiabilitySummaryAmount {
amount: number;
formattedAmount: string;
currencyCode: string;
}
export interface SalesTaxLiabilitySummaryTotal {
taxableAmount: SalesTaxLiabilitySummaryAmount;
taxAmount: SalesTaxLiabilitySummaryAmount;
collectedTaxAmount: SalesTaxLiabilitySummaryAmount;
}
export interface SalesTaxLiabilitySummaryRate {
id: number;
taxName: string;
taxableAmount: SalesTaxLiabilitySummaryAmount;
taxAmount: SalesTaxLiabilitySummaryAmount;
taxPercentage: any;
collectedTaxAmount: SalesTaxLiabilitySummaryAmount;
}
export enum SalesTaxLiabilitySummaryTableRowType {
TaxRate = 'TaxRate',
Total = 'Total',
}
export interface SalesTaxLiabilitySummaryReportData {
taxRates: SalesTaxLiabilitySummaryRate[];
total: SalesTaxLiabilitySummaryTotal;
}
export type SalesTaxLiabilitySummaryPayableById = Record<
string,
{ taxRateId: number; credit: number; debit: number }
>;
export type SalesTaxLiabilitySummarySalesById = Record<
string,
{ taxRateId: number; credit: number; debit: number }
>;
export interface SalesTaxLiabilitySummaryMeta {
organizationName: string;
baseCurrency: string;
}

View File

@@ -1,88 +0,0 @@
import { Knex } from 'knex';
export interface ITaxRate {
id?: number;
name: string;
code: string;
rate: number;
description: string;
IsNonRecoverable: boolean;
IsCompound: boolean;
active: boolean;
}
export interface ICommonTaxRateDTO {
name: string;
code: string;
rate: number;
description: string;
IsNonRecoverable: boolean;
IsCompound: boolean;
active: boolean;
}
export interface ICreateTaxRateDTO extends ICommonTaxRateDTO {}
export interface IEditTaxRateDTO extends ICommonTaxRateDTO {}
export interface ITaxRateCreatingPayload {
createTaxRateDTO: ICreateTaxRateDTO;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateCreatedPayload {
createTaxRateDTO: ICreateTaxRateDTO;
taxRate: ITaxRate;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateEditingPayload {
editTaxRateDTO: IEditTaxRateDTO;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateEditedPayload {
editTaxRateDTO: IEditTaxRateDTO;
oldTaxRate: ITaxRate;
taxRate: ITaxRate;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateDeletingPayload {
oldTaxRate: ITaxRate;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateActivatingPayload {
taxRateId: number;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateActivatedPayload {
taxRateId: number;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxRateDeletedPayload {
oldTaxRate: ITaxRate;
tenantId: number;
trx: Knex.Transaction;
}
export interface ITaxTransaction {
id?: number;
taxRateId: number;
referenceType: string;
referenceId: number;
rate: number;
taxAccountId: number;
}
export enum TaxRateAction {
CREATE = 'Create',
EDIT = 'Edit',
DELETE = 'Delete',
VIEW = 'View',
}

View File

@@ -73,7 +73,6 @@ export * from './Project';
export * from './Tasks'; export * from './Tasks';
export * from './Times'; export * from './Times';
export * from './ProjectProfitabilitySummary'; export * from './ProjectProfitabilitySummary';
export * from './TaxRate';
export interface I18nService { export interface I18nService {
__: (input: string) => string; __: (input: string) => string;

View File

@@ -1,7 +1,7 @@
import { Container } from 'typedi'; import { Container } from 'typedi';
import events from '@/subscribers/events'; import events from '@/subscribers/events';
import SalesInvoicesCost from '@/services/Sales/SalesInvoicesCost';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import { SaleInvoicesCost } from '@/services/Sales/Invoices/SalesInvoicesCost';
export default class WriteInvoicesJournalEntries { export default class WriteInvoicesJournalEntries {
eventPublisher: EventPublisher; eventPublisher: EventPublisher;
@@ -26,7 +26,7 @@ export default class WriteInvoicesJournalEntries {
*/ */
public async handler(job, done: Function): Promise<void> { public async handler(job, done: Function): Promise<void> {
const { startingDate, tenantId } = job.attrs.data; const { startingDate, tenantId } = job.attrs.data;
const salesInvoicesCost = Container.get(SaleInvoicesCost); const salesInvoicesCost = Container.get(SalesInvoicesCost);
try { try {
await salesInvoicesCost.writeCostLotsGLEntries(tenantId, startingDate); await salesInvoicesCost.writeCostLotsGLEntries(tenantId, startingDate);

View File

@@ -1,8 +1,8 @@
import { forEach, uniqBy } from 'lodash'; import { forEach, uniqBy } from 'lodash';
import DynamicFilterAbstractor from './DynamicFilterAbstractor'; import DynamicFilterAbstructor from './DynamicFilterAbstructor';
import { IDynamicFilter, IFilterRole, IModel } from '@/interfaces'; import { IDynamicFilter, IFilterRole, IModel } from '@/interfaces';
export default class DynamicFilter extends DynamicFilterAbstractor{ export default class DynamicFilter extends DynamicFilterAbstructor{
private model: IModel; private model: IModel;
private tableName: string; private tableName: string;
private dynamicFilters: IDynamicFilter[]; private dynamicFilters: IDynamicFilter[];

View File

@@ -1,5 +1,5 @@
export default class DynamicFilterAbstractor { export default class DynamicFilterAbstructor {
/** /**
* Extract relation table name from relation. * Extract relation table name from relation.
* @param {String} column - * @param {String} column -

View File

@@ -1,7 +1,7 @@
import DynamicFilterRoleAbstractor from './DynamicFilterRoleAbstractor'; import DynamicFilterRoleAbstructor from './DynamicFilterRoleAbstructor';
import { IFilterRole } from '@/interfaces'; import { IFilterRole } from '@/interfaces';
export default class FilterRoles extends DynamicFilterRoleAbstractor { export default class FilterRoles extends DynamicFilterRoleAbstructor {
private filterRoles: IFilterRole[]; private filterRoles: IFilterRole[];
/** /**

View File

@@ -6,7 +6,7 @@ import DynamicFilterQueryParser from './DynamicFilterQueryParser';
import { Lexer } from '../LogicEvaluation/Lexer'; import { Lexer } from '../LogicEvaluation/Lexer';
import { COMPARATOR_TYPE, FIELD_TYPE } from './constants'; import { COMPARATOR_TYPE, FIELD_TYPE } from './constants';
export default abstract class DynamicFilterAbstractor export default abstract class DynamicFilterAbstructor
implements IDynamicFilter implements IDynamicFilter
{ {
protected filterRoles: IFilterRole[] = []; protected filterRoles: IFilterRole[] = [];

View File

@@ -1,4 +1,4 @@
import DynamicFilterRoleAbstractor from '@/lib/DynamicFilter/DynamicFilterRoleAbstractor'; import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import { FIELD_TYPE } from './constants'; import { FIELD_TYPE } from './constants';
interface ISortRole { interface ISortRole {
@@ -6,7 +6,7 @@ interface ISortRole {
order: string; order: string;
} }
export default class DynamicFilterSortBy extends DynamicFilterRoleAbstractor { export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
private sortRole: ISortRole = {}; private sortRole: ISortRole = {};
/** /**

View File

@@ -1,8 +1,8 @@
import { omit } from 'lodash'; import { omit } from 'lodash';
import { IView, IViewRole } from '@/interfaces'; import { IView, IViewRole } from '@/interfaces';
import DynamicFilterRoleAbstractor from './DynamicFilterRoleAbstractor'; import DynamicFilterRoleAbstructor from './DynamicFilterRoleAbstructor';
export default class DynamicFilterViews extends DynamicFilterRoleAbstractor { export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
private viewSlug: string; private viewSlug: string;
private logicExpression: string; private logicExpression: string;
private filterRoles: IViewRole[]; private filterRoles: IViewRole[];

View File

@@ -1,7 +1,8 @@
import moment from 'moment'; import moment from 'moment';
import * as R from 'ramda'; import * as R from 'ramda';
import { includes, isFunction, isObject, isUndefined, omit } from 'lodash'; import { includes, isFunction, isObject, isUndefined, omit } from 'lodash';
import { formatNumber, sortObjectKeysAlphabetically } from 'utils'; import { formatNumber } from 'utils';
import { isArrayLikeObject } from 'lodash/fp';
export class Transformer { export class Transformer {
public context: any; public context: any;
@@ -81,7 +82,6 @@ export class Transformer {
const normlizedItem = this.normalizeModelItem(item); const normlizedItem = this.normalizeModelItem(item);
return R.compose( return R.compose(
sortObjectKeysAlphabetically,
this.transform, this.transform,
R.when(this.hasExcludeAttributes, this.excludeAttributesTransformed), R.when(this.hasExcludeAttributes, this.excludeAttributesTransformed),
this.includeAttributesTransformed this.includeAttributesTransformed

View File

@@ -1,10 +1,10 @@
import DynamicFilterRoleAbstractor from '@/lib/DynamicFilter/DynamicFilterRoleAbstractor'; import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
import { import {
validateViewRoles, validateViewRoles,
buildFilterQuery, buildFilterQuery,
} from '@/lib/ViewRolesBuilder'; } from '@/lib/ViewRolesBuilder';
export default class ViewRolesDynamicFilter extends DynamicFilterRoleAbstractor { export default class ViewRolesDynamicFilter extends DynamicFilterRoleAbstructor {
/** /**
* Constructor method. * Constructor method.
* @param {*} filterRoles - * @param {*} filterRoles -

View File

@@ -1,16 +1,17 @@
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import ItemSubscriber from '@/subscribers/Items/ItemSubscriber';
import InventoryAdjustmentsSubscriber from '@/subscribers/Inventory/InventoryAdjustment'; import InventoryAdjustmentsSubscriber from '@/subscribers/Inventory/InventoryAdjustment';
import BillWriteInventoryTransactionsSubscriber from '@/subscribers/Bills/WriteInventoryTransactions'; import BillWriteInventoryTransactionsSubscriber from '@/subscribers/Bills/WriteInventoryTransactions';
import PaymentSyncBillBalance from '@/subscribers/PaymentMades/PaymentSyncBillBalance'; import PaymentSyncBillBalance from '@/subscribers/PaymentMades/PaymentSyncBillBalance';
import SaleReceiptInventoryTransactionsSubscriber from '@/subscribers/SaleReceipt/WriteInventoryTransactions'; import SaleReceiptInventoryTransactionsSubscriber from '@/subscribers/SaleReceipt/WriteInventoryTransactions';
import SaleInvoiceWriteInventoryTransactions from '@/subscribers/SaleInvoices/WriteInventoryTransactions'; import SaleInvoiceWriteInventoryTransactions from '@/subscribers/SaleInvoices/WriteInventoryTransactions';
import SaleInvoiceWriteGLEntriesSubscriber from '@/subscribers/SaleInvoices/WriteJournalEntries'; import SaleInvoiceWriteGLEntriesSubscriber from '@/subscribers/SaleInvoices/WriteJournalEntries';
import SaleReceiptWriteGLEntriesSubscriber from '@/subscribers/SaleReceipt/WriteJournalEntries';
import PaymentReceiveSyncInvoices from '@/subscribers/PaymentReceive/PaymentReceiveSyncInvoices'; import PaymentReceiveSyncInvoices from '@/subscribers/PaymentReceive/PaymentReceiveSyncInvoices';
import CashflowTransactionSubscriber from '@/services/Cashflow/CashflowTransactionSubscriber'; import CashflowTransactionSubscriber from '@/services/Cashflow/CashflowTransactionSubscriber';
import PaymentReceivesWriteGLEntriesSubscriber from '@/subscribers/PaymentReceive/WriteGLEntries'; import PaymentReceivesWriteGLEntriesSubscriber from '@/subscribers/PaymentReceive/WriteGLEntries';
import InventorySubscriber from '@/subscribers/Inventory/Inventory'; import InventorySubscriber from '@/subscribers/Inventory/Inventory';
import SaleReceiptWriteGLEntriesSubscriber from '@/subscribers/SaleReceipt/WriteJournalEntries';
import { CustomerWriteGLOpeningBalanceSubscriber } from '@/services/Contacts/Customers/Subscribers/CustomerGLEntriesSubscriber'; import { CustomerWriteGLOpeningBalanceSubscriber } from '@/services/Contacts/Customers/Subscribers/CustomerGLEntriesSubscriber';
import { VendorsWriteGLOpeningSubscriber } from '@/services/Contacts/Vendors/Subscribers/VendorGLEntriesSubscriber'; import { VendorsWriteGLOpeningSubscriber } from '@/services/Contacts/Vendors/Subscribers/VendorGLEntriesSubscriber';
import SaleEstimateAutoSerialSubscriber from '@/subscribers/SaleEstimate/AutoIncrementSerial'; import SaleEstimateAutoSerialSubscriber from '@/subscribers/SaleEstimate/AutoIncrementSerial';
@@ -34,7 +35,7 @@ import PurgeAuthorizedUserOnceRoleMutate from '@/services/Roles/PurgeAuthorizedU
import SendSmsNotificationToCustomer from '@/subscribers/SaleInvoices/SendSmsNotificationToCustomer'; import SendSmsNotificationToCustomer from '@/subscribers/SaleInvoices/SendSmsNotificationToCustomer';
import SendSmsNotificationSaleReceipt from '@/subscribers/SaleReceipt/SendSmsNotificationToCustomer'; import SendSmsNotificationSaleReceipt from '@/subscribers/SaleReceipt/SendSmsNotificationToCustomer';
import SendSmsNotificationPaymentReceive from '@/subscribers/PaymentReceive/SendSmsNotificationToCustomer'; import SendSmsNotificationPaymentReceive from '@/subscribers/PaymentReceive/SendSmsNotificationToCustomer';
import SaleInvoiceWriteoffSubscriber from '@/services/Sales/Invoices/SaleInvoiceWriteoffSubscriber'; import SaleInvoiceWriteoffSubscriber from '@/services/Sales/SaleInvoiceWriteoffSubscriber';
import LandedCostSyncCostTransactionsSubscriber from '@/services/Purchases/LandedCost/LandedCostSyncCostTransactionsSubscriber'; import LandedCostSyncCostTransactionsSubscriber from '@/services/Purchases/LandedCost/LandedCostSyncCostTransactionsSubscriber';
import LandedCostInventoryTransactionsSubscriber from '@/services/Purchases/LandedCost/LandedCostInventoryTransactionsSubscriber'; import LandedCostInventoryTransactionsSubscriber from '@/services/Purchases/LandedCost/LandedCostInventoryTransactionsSubscriber';
import CreditNoteGLEntriesSubscriber from '@/services/CreditNotes/CreditNoteGLEntriesSubscriber'; import CreditNoteGLEntriesSubscriber from '@/services/CreditNotes/CreditNoteGLEntriesSubscriber';
@@ -65,6 +66,7 @@ import { ActivateWarehousesSubscriber } from '@/services/Warehouses/ActivateWare
import { ManualJournalWriteGLSubscriber } from '@/services/ManualJournals/ManualJournalGLEntriesSubscriber'; import { ManualJournalWriteGLSubscriber } from '@/services/ManualJournals/ManualJournalGLEntriesSubscriber';
import { BillGLEntriesSubscriber } from '@/services/Purchases/Bills/BillGLEntriesSubscriber'; import { BillGLEntriesSubscriber } from '@/services/Purchases/Bills/BillGLEntriesSubscriber';
import { PaymentWriteGLEntriesSubscriber } from '@/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber'; import { PaymentWriteGLEntriesSubscriber } from '@/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber';
import BranchesIntegrationsSubscribers from '@/services/Branches/EventsProvider'; import BranchesIntegrationsSubscribers from '@/services/Branches/EventsProvider';
import WarehousesIntegrationsSubscribers from '@/services/Warehouses/EventsProvider'; import WarehousesIntegrationsSubscribers from '@/services/Warehouses/EventsProvider';
import { WarehouseTransferAutoIncrementSubscriber } from '@/services/Warehouses/WarehousesTransfers/WarehouseTransferAutoIncrementSubscriber'; import { WarehouseTransferAutoIncrementSubscriber } from '@/services/Warehouses/WarehousesTransfers/WarehouseTransferAutoIncrementSubscriber';
@@ -79,8 +81,6 @@ import { ProjectBillableTasksSubscriber } from '@/services/Projects/Projects/Pro
import { ProjectBillableExpensesSubscriber } from '@/services/Projects/Projects/ProjectBillableExpenseSubscriber'; import { ProjectBillableExpensesSubscriber } from '@/services/Projects/Projects/ProjectBillableExpenseSubscriber';
import { ProjectBillableBillSubscriber } from '@/services/Projects/Projects/ProjectBillableBillSubscriber'; import { ProjectBillableBillSubscriber } from '@/services/Projects/Projects/ProjectBillableBillSubscriber';
import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber'; import { SyncActualTimeTaskSubscriber } from '@/services/Projects/Times/SyncActualTimeTaskSubscriber';
import { SaleInvoiceTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/SaleInvoiceTaxRateValidateSubscriber';
import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteInvoiceTaxTransactionsSubscriber';
export default () => { export default () => {
return new EventPublisher(); return new EventPublisher();
@@ -88,6 +88,7 @@ export default () => {
export const susbcribers = () => { export const susbcribers = () => {
return [ return [
ItemSubscriber,
InventoryAdjustmentsSubscriber, InventoryAdjustmentsSubscriber,
BillWriteInventoryTransactionsSubscriber, BillWriteInventoryTransactionsSubscriber,
PaymentSyncBillBalance, PaymentSyncBillBalance,
@@ -187,9 +188,5 @@ export const susbcribers = () => {
ProjectBillableTasksSubscriber, ProjectBillableTasksSubscriber,
ProjectBillableExpensesSubscriber, ProjectBillableExpensesSubscriber,
ProjectBillableBillSubscriber, ProjectBillableBillSubscriber,
// Tax Rates
SaleInvoiceTaxRateValidateSubscriber,
WriteInvoiceTaxTransactionsSubscriber,
]; ];
}; };

View File

@@ -58,8 +58,6 @@ import ItemWarehouseQuantity from 'models/ItemWarehouseQuantity';
import Project from 'models/Project'; import Project from 'models/Project';
import Time from 'models/Time'; import Time from 'models/Time';
import Task from 'models/Task'; import Task from 'models/Task';
import TaxRate from 'models/TaxRate';
import TaxRateTransaction from 'models/TaxRateTransaction';
export default (knex) => { export default (knex) => {
const models = { const models = {
@@ -121,8 +119,6 @@ export default (knex) => {
Project, Project,
Time, Time,
Task, Task,
TaxRate,
TaxRateTransaction,
}; };
return mapValues(models, (model) => model.bindKnex(knex)); return mapValues(models, (model) => model.bindKnex(knex));
}; };

View File

@@ -152,7 +152,7 @@
"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 availiable 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.": "لا ترتبط انشطة الدخل إلى الأعمال الأساسية.",

View File

@@ -151,7 +151,7 @@
"Opening Balance Liabilities": "Opening Balance Liabilities", "Opening Balance Liabilities": "Opening Balance Liabilities",
"Loan": "Loan", "Loan": "Loan",
"Owner A Drawings": "Owner A Drawings", "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.", "An account that holds valuation of products or goods that availiable for sale.": "An account that holds valuation of products or goods that availiable for sale.",
"Tracks the gain and losses of the exchange differences.": "Tracks the gain and losses of the exchange differences.", "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.", "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.", "The income activities are not associated to the core business.": "The income activities are not associated to the core business.",

View File

@@ -127,7 +127,7 @@ export default class Account extends mixin(TenantModel, [
}, },
filterAccountTypes(query, typesIds) { filterAccountTypes(query, typesIds) {
if (typesIds.length > 0) { if (typesIds.length > 0) {
query.whereIn('account_types.account_type_id', typesIds); query.whereIn('account_types.accoun_type_id', typesIds);
} }
}, },
viewRolesBuilder(query, conditionals, expression) { viewRolesBuilder(query, conditionals, expression) {

View File

@@ -2,15 +2,8 @@ import { Model, raw } from 'objection';
import moment from 'moment'; import moment from 'moment';
import { isEmpty, castArray } from 'lodash'; import { isEmpty, castArray } from 'lodash';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import { getTransactionTypeLabel } from '@/utils/transactions-types';
export default class AccountTransaction extends TenantModel { export default class AccountTransaction extends TenantModel {
referenceType: string;
credit: number;
debit: number;
exchangeRate: number;
taxRate: number;
/** /**
* Table name * Table name
*/ */
@@ -29,23 +22,7 @@ export default class AccountTransaction extends TenantModel {
* Virtual attributes. * Virtual attributes.
*/ */
static get virtualAttributes() { static get virtualAttributes() {
return ['referenceTypeFormatted', 'creditLocal', 'debitLocal']; return ['referenceTypeFormatted'];
}
/**
* Retrieves the credit amount in base currency.
* @return {number}
*/
get creditLocal() {
return this.credit * this.exchangeRate;
}
/**
* Retrieves the debit amount in base currency.
* @return {number}
*/
get debitLocal() {
return this.debit * this.exchangeRate;
} }
/** /**
@@ -53,7 +30,40 @@ export default class AccountTransaction extends TenantModel {
* @return {string} * @return {string}
*/ */
get referenceTypeFormatted() { get referenceTypeFormatted() {
return getTransactionTypeLabel(this.referenceType); return AccountTransaction.getReferenceTypeFormatted(this.referenceType);
}
/**
* Reference type formatted.
*/
static getReferenceTypeFormatted(referenceType) {
const mapped = {
SaleInvoice: 'Sale invoice',
SaleReceipt: 'Sale receipt',
PaymentReceive: 'Payment receive',
Bill: 'Bill',
BillPayment: 'Payment made',
VendorOpeningBalance: 'Vendor opening balance',
CustomerOpeningBalance: 'Customer opening balance',
InventoryAdjustment: 'Inventory adjustment',
ManualJournal: 'Manual journal',
Journal: 'Manual journal',
Expense: 'Expense',
OwnerContribution: 'Owner contribution',
TransferToAccount: 'Transfer to account',
TransferFromAccount: 'Transfer from account',
OtherIncome: 'Other income',
OtherExpense: 'Other expense',
OwnerDrawing: 'Owner drawing',
InvoiceWriteOff: 'Invoice write-off',
CreditNote: 'transaction_type.credit_note',
VendorCredit: 'transaction_type.vendor_credit',
RefundCreditNote: 'transaction_type.refund_credit_note',
RefundVendorCredit: 'transaction_type.refund_vendor_credit',
};
return mapped[referenceType] || '';
} }
/** /**
@@ -79,9 +89,15 @@ export default class AccountTransaction extends TenantModel {
} }
}, },
filterDateRange(query, startDate, endDate, type = 'day') { filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const fromDate = moment(startDate).startOf(type).format(dateFormat); const fromDate = moment(startDate)
const toDate = moment(endDate).endOf(type).format(dateFormat); .utcOffset(0)
.startOf(type)
.format(dateFormat);
const toDate = moment(endDate)
.utcOffset(0)
.endOf(type)
.format(dateFormat);
if (startDate) { if (startDate) {
query.where('date', '>=', fromDate); query.where('date', '>=', fromDate);
@@ -125,6 +141,7 @@ export default class AccountTransaction extends TenantModel {
query.modify('filterDateRange', null, toDate); query.modify('filterDateRange', null, toDate);
query.modify('sumationCreditDebit'); query.modify('sumationCreditDebit');
}, },
contactsOpeningBalance( contactsOpeningBalance(
query, query,
openingDate, openingDate,

View File

@@ -5,7 +5,7 @@ import TenantModel from 'models/TenantModel';
import BillSettings from './Bill.Settings'; import BillSettings from './Bill.Settings';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import CustomViewBaseModel from './CustomViewBaseModel'; import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from '@/services/Purchases/Bills/constants'; import { DEFAULT_VIEWS } from '@/services/Purchases/constants';
import ModelSearchable from './ModelSearchable'; import ModelSearchable from './ModelSearchable';
export default class Bill extends mixin(TenantModel, [ export default class Bill extends mixin(TenantModel, [

View File

@@ -97,7 +97,7 @@ export default class Branch extends TenantModel {
}, },
/** /**
* Branch may belongs to associated bills. * Branch may belongs to assocaited bills.
*/ */
bills: { bills: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,

View File

@@ -121,7 +121,7 @@ export default class CashflowTransaction extends TenantModel {
}, },
/** /**
* Cashflow transaction may has associated cashflow account. * Cashflow transaction may has assocaited cashflow account.
*/ */
cashflowAccount: { cashflowAccount: {
relation: Model.BelongsToOneRelation, relation: Model.BelongsToOneRelation,

View File

@@ -33,7 +33,7 @@ export default class InventoryCostLotTracker extends TenantModel {
query.groupBy('item_id'); query.groupBy('item_id');
}, },
filterDateRange(query, startDate, endDate, type = 'day') { filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const fromDate = moment(startDate).startOf(type).format(dateFormat); const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat);

View File

@@ -1,13 +1,9 @@
import { Model, raw } from 'objection'; import { Model, raw } from 'objection';
import { castArray } from 'lodash'; import { castArray, isEmpty } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import { getTransactionTypeLabel } from '@/utils/transactions-types';
export default class InventoryTransaction extends TenantModel { export default class InventoryTransaction extends TenantModel {
transactionId: number;
transactionType: string;
/** /**
* Table name * Table name
*/ */
@@ -27,7 +23,27 @@ export default class InventoryTransaction extends TenantModel {
* @return {string} * @return {string}
*/ */
get transcationTypeFormatted() { get transcationTypeFormatted() {
return getTransactionTypeLabel(this.transactionType); return InventoryTransaction.getReferenceTypeFormatted(this.transactionType);
}
/**
* Reference type formatted.
*/
static getReferenceTypeFormatted(referenceType) {
const mapped = {
SaleInvoice: 'Sale invoice',
SaleReceipt: 'Sale receipt',
PaymentReceive: 'Payment receive',
Bill: 'Bill',
BillPayment: 'Payment made',
VendorOpeningBalance: 'Vendor opening balance',
CustomerOpeningBalance: 'Customer opening balance',
InventoryAdjustment: 'Inventory adjustment',
ManualJournal: 'Manual journal',
Journal: 'Manual journal',
LandedCost: 'transaction_type.landed_cost',
};
return mapped[referenceType] || '';
} }
/** /**
@@ -36,7 +52,7 @@ export default class InventoryTransaction extends TenantModel {
static get modifiers() { static get modifiers() {
return { return {
filterDateRange(query, startDate, endDate, type = 'day') { filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const fromDate = moment(startDate).startOf(type).format(dateFormat); const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat);

View File

@@ -1,17 +1,9 @@
import { Model } from 'objection'; import { Model } from 'objection';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import { getExlusiveTaxAmount, getInclusiveTaxAmount } from '@/utils/taxRate';
export default class ItemEntry extends TenantModel { export default class ItemEntry extends TenantModel {
public taxRate: number;
public discount: number;
public quantity: number;
public rate: number;
public isInclusiveTax: number;
/** /**
* Table name. * Table name.
* @returns {string}
*/ */
static get tableName() { static get tableName() {
return 'items_entries'; return 'items_entries';
@@ -19,89 +11,26 @@ export default class ItemEntry extends TenantModel {
/** /**
* Timestamps columns. * Timestamps columns.
* @returns {string[]}
*/ */
get timestamps() { get timestamps() {
return ['created_at', 'updated_at']; return ['created_at', 'updated_at'];
} }
/**
* Virtual attributes.
* @returns {string[]}
*/
static get virtualAttributes() { static get virtualAttributes() {
return [ return ['amount'];
'amount',
'taxAmount',
'amountExludingTax',
'amountInclusingTax',
'total',
];
} }
/**
* Item entry total.
* Amount of item entry includes tax and subtracted discount amount.
* @returns {number}
*/
get total() {
return this.amountInclusingTax;
}
/**
* Item entry amount.
* Amount of item entry that may include or exclude tax.
* @returns {number}
*/
get amount() { get amount() {
return this.quantity * this.rate; return ItemEntry.calcAmount(this);
} }
/** static calcAmount(itemEntry) {
* Item entry amount including tax. const { discount, quantity, rate } = itemEntry;
* @returns {number} const total = quantity * rate;
*/
get amountInclusingTax() { return discount ? total - total * discount * 0.01 : total;
return this.isInclusiveTax ? this.amount : this.amount + this.taxAmount;
} }
/**
* Item entry amount excluding tax.
* @returns {number}
*/
get amountExludingTax() {
return this.isInclusiveTax ? this.amount - this.taxAmount : this.amount;
}
/**
* Discount amount.
* @returns {number}
*/
get discountAmount() {
return this.amount * (this.discount / 100);
}
/**
* Tag rate fraction.
* @returns {number}
*/
get tagRateFraction() {
return this.taxRate / 100;
}
/**
* Tax amount withheld.
* @returns {number}
*/
get taxAmount() {
return this.isInclusiveTax
? getInclusiveTaxAmount(this.amount, this.taxRate)
: getExlusiveTaxAmount(this.amount, this.taxRate);
}
/**
* Item entry relations.
*/
static get relationMappings() { static get relationMappings() {
const Item = require('models/Item'); const Item = require('models/Item');
const BillLandedCostEntry = require('models/BillLandedCostEntry'); const BillLandedCostEntry = require('models/BillLandedCostEntry');
@@ -111,7 +40,6 @@ export default class ItemEntry extends TenantModel {
const SaleEstimate = require('models/SaleEstimate'); const SaleEstimate = require('models/SaleEstimate');
const ProjectTask = require('models/Task'); const ProjectTask = require('models/Task');
const Expense = require('models/Expense'); const Expense = require('models/Expense');
const TaxRate = require('models/TaxRate');
return { return {
item: { item: {
@@ -158,9 +86,6 @@ export default class ItemEntry extends TenantModel {
}, },
}, },
/**
* Sale receipt reference.
*/
receipt: { receipt: {
relation: Model.BelongsToOneRelation, relation: Model.BelongsToOneRelation,
modelClass: SaleReceipt.default, modelClass: SaleReceipt.default,
@@ -171,7 +96,7 @@ export default class ItemEntry extends TenantModel {
}, },
/** /**
* Project task reference. *
*/ */
projectTaskRef: { projectTaskRef: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,
@@ -183,7 +108,7 @@ export default class ItemEntry extends TenantModel {
}, },
/** /**
* Project expense reference. *
*/ */
projectExpenseRef: { projectExpenseRef: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,
@@ -195,7 +120,7 @@ export default class ItemEntry extends TenantModel {
}, },
/** /**
* Project bill reference. *
*/ */
projectBillRef: { projectBillRef: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,
@@ -205,18 +130,6 @@ export default class ItemEntry extends TenantModel {
to: 'bills.id', to: 'bills.id',
}, },
}, },
/**
* Tax rate reference.
*/
tax: {
relation: Model.HasOneRelation,
modelClass: TaxRate.default,
join: {
from: 'items_entries.taxRateId',
to: 'tax_rates.id',
},
},
}; };
} }
} }

View File

@@ -1,11 +1,11 @@
import { mixin, Model, raw } from 'objection'; import { mixin, Model, raw } from 'objection';
import { castArray, takeWhile } from 'lodash'; import { castArray } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import SaleInvoiceMeta from './SaleInvoice.Settings'; import SaleInvoiceMeta from './SaleInvoice.Settings';
import CustomViewBaseModel from './CustomViewBaseModel'; import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from '@/services/Sales/Invoices/constants'; import { DEFAULT_VIEWS } from '@/services/Sales/constants';
import ModelSearchable from './ModelSearchable'; import ModelSearchable from './ModelSearchable';
export default class SaleInvoice extends mixin(TenantModel, [ export default class SaleInvoice extends mixin(TenantModel, [
@@ -13,17 +13,6 @@ export default class SaleInvoice extends mixin(TenantModel, [
CustomViewBaseModel, CustomViewBaseModel,
ModelSearchable, ModelSearchable,
]) { ]) {
public taxAmountWithheld: number;
public balance: number;
public paymentAmount: number;
public exchangeRate: number;
public writtenoffAmount: number;
public creditedAmount: number;
public isInclusiveTax: boolean;
public writtenoffAt: Date;
public dueDate: Date;
public deliveredAt: Date;
/** /**
* Table name * Table name
*/ */
@@ -38,9 +27,6 @@ export default class SaleInvoice extends mixin(TenantModel, [
return ['created_at', 'updated_at']; return ['created_at', 'updated_at'];
} }
/**
*
*/
get pluralName() { get pluralName() {
return 'asdfsdf'; return 'asdfsdf';
} }
@@ -50,97 +36,35 @@ export default class SaleInvoice extends mixin(TenantModel, [
*/ */
static get virtualAttributes() { static get virtualAttributes() {
return [ return [
'localAmount',
'dueAmount',
'balanceAmount',
'isDelivered', 'isDelivered',
'isOverdue', 'isOverdue',
'isPartiallyPaid', 'isPartiallyPaid',
'isFullyPaid', 'isFullyPaid',
'isWrittenoff',
'isPaid', 'isPaid',
'isWrittenoff',
'dueAmount',
'balanceAmount',
'remainingDays', 'remainingDays',
'overdueDays', 'overdueDays',
'filterByBranches',
'subtotal',
'subtotalLocal',
'subtotalExludingTax',
'taxAmountWithheldLocal',
'total',
'totalLocal',
'writtenoffAmountLocal',
]; ];
} }
/** /**
* Invoice amount. * Invoice amount in local currency.
* @todo Sugger attribute to balance, we need to rename the balance to amount.
* @returns {number} * @returns {number}
*/ */
get amount() { get localAmount() {
return this.balance; return this.balance * this.exchangeRate;
} }
/** /**
* Invoice amount in base currency. * Invoice local written-off amount.
* @returns {number} * @returns {number}
*/ */
get amountLocal() { get localWrittenoffAmount() {
return this.amount * this.exchangeRate; return this.writtenoffAmount * 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 subtotalExludingTax() {
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;
} }
/** /**
@@ -173,7 +97,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
* @return {boolean} * @return {boolean}
*/ */
get dueAmount() { get dueAmount() {
return Math.max(this.total - this.balanceAmount, 0); return Math.max(this.balance - this.balanceAmount, 0);
} }
/** /**
@@ -181,7 +105,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
* @return {boolean} * @return {boolean}
*/ */
get isPartiallyPaid() { get isPartiallyPaid() {
return this.dueAmount !== this.total && this.dueAmount > 0; return this.dueAmount !== this.balance && this.dueAmount > 0;
} }
/** /**
@@ -252,7 +176,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
* Filters the invoices between the given date range. * Filters the invoices between the given date range.
*/ */
filterDateRange(query, startDate, endDate, type = 'day') { filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const fromDate = moment(startDate).startOf(type).format(dateFormat); const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat);
@@ -409,7 +333,6 @@ export default class SaleInvoice extends mixin(TenantModel, [
const PaymentReceiveEntry = require('models/PaymentReceiveEntry'); const PaymentReceiveEntry = require('models/PaymentReceiveEntry');
const Branch = require('models/Branch'); const Branch = require('models/Branch');
const Account = require('models/Account'); const Account = require('models/Account');
const TaxRateTransaction = require('models/TaxRateTransaction');
return { return {
/** /**
@@ -459,7 +382,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
}, },
/** /**
* Invoice may has associated cost transactions. *
*/ */
costTransactions: { costTransactions: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,
@@ -474,7 +397,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
}, },
/** /**
* Invoice may has associated payment entries. *
*/ */
paymentEntries: { paymentEntries: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,
@@ -497,9 +420,6 @@ export default class SaleInvoice extends mixin(TenantModel, [
}, },
}, },
/**
* Invoice may has associated written-off expense account.
*/
writtenoffExpenseAccount: { writtenoffExpenseAccount: {
relation: Model.BelongsToOneRelation, relation: Model.BelongsToOneRelation,
modelClass: Account.default, modelClass: Account.default,
@@ -508,21 +428,6 @@ export default class SaleInvoice extends mixin(TenantModel, [
to: 'accounts.id', to: 'accounts.id',
}, },
}, },
/**
* Invoice may has associated tax rate transactions.
*/
taxes: {
relation: Model.HasManyRelation,
modelClass: TaxRateTransaction.default,
join: {
from: 'sales_invoices.id',
to: 'tax_rate_transactions.referenceId',
},
filter(builder) {
builder.where('reference_type', 'SaleInvoice');
},
},
}; };
} }

View File

@@ -1,48 +0,0 @@
import { mixin, Model, raw } from 'objection';
import TenantModel from 'models/TenantModel';
import ModelSearchable from './ModelSearchable';
import SoftDeleteQueryBuilder from '@/collection/SoftDeleteQueryBuilder';
export default class TaxRate extends mixin(TenantModel, [ModelSearchable]) {
/**
* Table name
*/
static get tableName() {
return 'tax_rates';
}
/**
* Soft delete query builder.
*/
static get QueryBuilder() {
return SoftDeleteQueryBuilder;
}
/**
* Timestamps columns.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/**
* Virtual attributes.
*/
static get virtualAttributes() {
return [];
}
/**
* Model modifiers.
*/
static get modifiers() {
return {};
}
/**
* Relationship mapping.
*/
static get relationMappings() {
return {};
}
}

View File

@@ -1,56 +0,0 @@
import { mixin, Model, raw } from 'objection';
import TenantModel from 'models/TenantModel';
import ModelSearchable from './ModelSearchable';
export default class TaxRateTransaction extends mixin(TenantModel, [
ModelSearchable,
]) {
/**
* Table name
*/
static get tableName() {
return 'tax_rate_transactions';
}
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/**
* Virtual attributes.
*/
static get virtualAttributes() {
return [];
}
/**
* Model modifiers.
*/
static get modifiers() {
return {};
}
/**
* Relationship mapping.
*/
static get relationMappings() {
const TaxRate = require('models/TaxRate');
return {
/**
* Belongs to the tax rate.
*/
taxRate: {
relation: Model.BelongsToOneRelation,
modelClass: TaxRate.default,
join: {
from: 'tax_rate_transactions.taxRateId',
to: 'tax_rates.id',
},
},
};
}
}

View File

@@ -84,7 +84,7 @@ export default class Warehouse extends TenantModel {
}, },
/** /**
* Warehouse may belongs to associated bills. * Warehouse may belongs to assocaited bills.
*/ */
bills: { bills: {
relation: Model.HasManyRelation, relation: Model.HasManyRelation,

View File

@@ -2,7 +2,6 @@ import { Account } from 'models';
import TenantRepository from '@/repositories/TenantRepository'; import TenantRepository from '@/repositories/TenantRepository';
import { IAccount } from '@/interfaces'; import { IAccount } from '@/interfaces';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { TaxPayableAccount } from '@/database/seeds/data/accounts';
export default class AccountRepository extends TenantRepository { export default class AccountRepository extends TenantRepository {
/** /**
@@ -117,7 +116,7 @@ export default class AccountRepository extends TenantRepository {
if (!result) { if (!result) {
result = await this.model.query(trx).insertAndFetch({ result = await this.model.query(trx).insertAndFetch({
name: this.i18n.__('account.accounts_receivable.currency', { name: this.i18n.__('account.accounts_receivable.currency', {
currency: currencyCode, currency: currencyCode
}), }),
accountType: 'accounts-receivable', accountType: 'accounts-receivable',
currencyCode, currencyCode,
@@ -128,29 +127,6 @@ export default class AccountRepository extends TenantRepository {
return result; return result;
}; };
/**
* Find or create tax payable account.
* @param {Record<string, string>}extraAttrs
* @param {Knex.Transaction} trx
* @returns
*/
async findOrCreateTaxPayable(
extraAttrs: Record<string, string> = {},
trx?: Knex.Transaction
) {
let result = await this.model
.query(trx)
.findOne({ slug: TaxPayableAccount.slug, ...extraAttrs });
if (!result) {
result = await this.model.query(trx).insertAndFetch({
...TaxPayableAccount,
...extraAttrs,
});
}
return result;
}
findOrCreateAccountsPayable = async ( findOrCreateAccountsPayable = async (
currencyCode: string = '', currencyCode: string = '',
extraAttrs = {}, extraAttrs = {},

View File

@@ -1,6 +1,6 @@
import { Service, Inject } from 'typedi'; import { Service, Inject } from 'typedi';
import events from '@/subscribers/events'; import events from '@/subscribers/events';
import { InventoryTransactionsWarehouses } from './AccountsTransactionsWarehouses'; import { InventoryTransactionsWarehouses } from './AcountsTransactionsWarehouses';
import { IBranchesActivatedPayload } from '@/interfaces'; import { IBranchesActivatedPayload } from '@/interfaces';
@Service() @Service()

View File

@@ -1,6 +1,10 @@
import { castArray } from 'lodash'; import moment from 'moment';
import { castArray, sumBy, toArray } from 'lodash';
import { IBill, ISystemUser, IAccount } from '@/interfaces';
import JournalPoster from './JournalPoster'; import JournalPoster from './JournalPoster';
import JournalEntry from './JournalEntry';
import { IExpense, IExpenseCategory } from '@/interfaces';
import { increment } from 'utils';
export default class JournalCommands { export default class JournalCommands {
journal: JournalPoster; journal: JournalPoster;
models: any; models: any;
@@ -12,6 +16,7 @@ export default class JournalCommands {
*/ */
constructor(journal: JournalPoster) { constructor(journal: JournalPoster) {
this.journal = journal; this.journal = journal;
this.repositories = this.journal.repositories; this.repositories = this.journal.repositories;
this.models = this.journal.models; this.models = this.journal.models;
} }

View File

@@ -79,7 +79,7 @@ export default class JournalPoster implements IJournalPoster {
} }
/** /**
* Async initialize accounts dependency graph. * Async initialize acccounts dependency graph.
* @private * @private
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */

View File

@@ -234,9 +234,6 @@ export default class Ledger implements ILedger {
entryId: entry.id, entryId: entry.id,
branchId: entry.branchId, branchId: entry.branchId,
projectId: entry.projectId, projectId: entry.projectId,
taxRateId: entry.taxRateId,
taxRate: entry.taxRate,
}; };
} }

View File

@@ -66,14 +66,14 @@ export class LedgerContactsBalanceStorage {
): Promise<(entry: ILedgerEntry) => boolean> => { ): Promise<(entry: ILedgerEntry) => boolean> => {
const { Account } = this.tenancy.models(tenantId); const { Account } = this.tenancy.models(tenantId);
const ARAPAccounts = await Account.query(trx).whereIn('accountType', [ const ARAPAcounts = await Account.query(trx).whereIn('accountType', [
ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE, ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE,
ACCOUNT_TYPE.ACCOUNTS_PAYABLE, ACCOUNT_TYPE.ACCOUNTS_PAYABLE,
]); ]);
const ARAPAccountsIds = ARAPAccounts.map((a) => a.id); const ARAPAcountsIds = ARAPAcounts.map((a) => a.id);
return (entry: ILedgerEntry) => { return (entry: ILedgerEntry) => {
return ARAPAccountsIds.indexOf(entry.accountId) !== -1; return ARAPAcountsIds.indexOf(entry.accountId) !== -1;
}; };
}; };

View File

@@ -35,7 +35,7 @@ export default class LedgerStorageService {
// Saves the ledger entries. // Saves the ledger entries.
this.ledgerEntriesService.saveEntries(tenantId, ledger, trx), this.ledgerEntriesService.saveEntries(tenantId, ledger, trx),
// Mutates the associated accounts balances. // Mutates the assocaited accounts balances.
this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx), this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx),
// Mutates the associated contacts balances. // Mutates the associated contacts balances.
@@ -60,7 +60,7 @@ export default class LedgerStorageService {
// Deletes the ledger entries. // Deletes the ledger entries.
this.ledgerEntriesService.deleteEntries(tenantId, ledger, trx), this.ledgerEntriesService.deleteEntries(tenantId, ledger, trx),
// Mutates the associated accounts balances. // Mutates the assocaited accounts balances.
this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx), this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx),
// Mutates the associated contacts balances. // Mutates the associated contacts balances.

View File

@@ -108,7 +108,7 @@ export class LedegrAccountsStorage {
const { Account } = this.tenancy.models(tenantId); const { Account } = this.tenancy.models(tenantId);
const account = await Account.query(trx).findById(accountId); const account = await Account.query(trx).findById(accountId);
// Filters the ledger entries by the current account. // Filters the ledger entries by the current acount.
const accountLedger = ledger.whereAccountId(accountId); const accountLedger = ledger.whereAccountId(accountId);
// Retrieves the given tenant metadata. // Retrieves the given tenant metadata.

View File

@@ -32,8 +32,5 @@ export const transformLedgerEntryToTransaction = (
projectId: entry.projectId, projectId: entry.projectId,
costable: entry.costable, costable: entry.costable,
taxRateId: entry.taxRateId,
taxRate: entry.taxRate,
}; };
}; };

View File

@@ -46,7 +46,7 @@ export default class AccountTransactionTransformer extends Transformer {
* @returns {string} * @returns {string}
*/ */
public transactionTypeFormatted(transaction: IAccountTransaction) { public transactionTypeFormatted(transaction: IAccountTransaction) {
return this.context.i18n.__(transaction.referenceTypeFormatted); return transaction.referenceTypeFormatted;
} }
/** /**

View File

@@ -77,7 +77,7 @@ export class DeleteAccount {
// Authorize before delete account. // Authorize before delete account.
await this.authorize(tenantId, accountId, oldAccount); await this.authorize(tenantId, accountId, oldAccount);
// Deletes the account and associated transactions under UOW envirement. // Deletes the account and assocaited transactions under UOW envirement.
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
// Triggers `onAccountDelete` event. // Triggers `onAccountDelete` event.
await this.eventPublisher.emitAsync(events.accounts.onDelete, { await this.eventPublisher.emitAsync(events.accounts.onDelete, {

View File

@@ -23,6 +23,15 @@ export class GetAccounts {
@Inject() @Inject()
private transformer: TransformerInjectable; private transformer: TransformerInjectable;
/**
* Parsees accounts list filter DTO.
* @param filterDTO
* @returns
*/
private parseListFilterDTO(filterDTO) {
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
}
/** /**
* Retrieve accounts datatable list. * Retrieve accounts datatable list.
* @param {number} tenantId * @param {number} tenantId
@@ -66,13 +75,4 @@ export class GetAccounts {
filterMeta: dynamicList.getResponseMeta(), filterMeta: dynamicList.getResponseMeta(),
}; };
}; };
/**
* Parsees accounts list filter DTO.
* @param filterDTO
* @returns
*/
private parseListFilterDTO(filterDTO) {
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
}
} }

View File

@@ -0,0 +1,9 @@
export class AccountsReceivableRepository {
findOrCreateAccount = (currencyCode?: string) => {
};
}

View File

@@ -8,7 +8,6 @@ import { IBranchDeletedPayload, IBranchDeletePayload } from '@/interfaces';
import { CURDBranch } from './CRUDBranch'; import { CURDBranch } from './CRUDBranch';
import { BranchValidator } from './BranchValidate'; import { BranchValidator } from './BranchValidate';
import { ERRORS } from './constants'; import { ERRORS } from './constants';
@Service() @Service()
export class DeleteBranch extends CURDBranch { export class DeleteBranch extends CURDBranch {
@Inject() @Inject()

View File

@@ -14,8 +14,8 @@ export class ValidateBranchExistance {
/** /**
* Validate transaction branch id when the feature is active. * Validate transaction branch id when the feature is active.
* @param {number} tenantId * @param {number} tenantId
* @param {number} branchId * @param {number} branchId
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public validateTransactionBranchWhenActive = async ( public validateTransactionBranchWhenActive = async (
@@ -32,16 +32,18 @@ export class ValidateBranchExistance {
/** /**
* Validate transaction branch id existance. * Validate transaction branch id existance.
* @param {number} tenantId * @param {number} tenantId
* @param {number} branchId * @param {number} branchId
* @return {Promise<void>} * @return {Promise<void>}
*/ */
public validateTransactionBranch = async ( public validateTransactionBranch = async (
tenantId: number, tenantId: number,
branchId: number | null branchId: number | null
) => { ) => {
//
this.validateBranchIdExistance(branchId); this.validateBranchIdExistance(branchId);
//
await this.validateBranchExistance(tenantId, branchId); await this.validateBranchExistance(tenantId, branchId);
}; };
@@ -60,10 +62,7 @@ export class ValidateBranchExistance {
* @param tenantId * @param tenantId
* @param branchId * @param branchId
*/ */
public validateBranchExistance = async ( public validateBranchExistance = async (tenantId: number, branchId: number) => {
tenantId: number,
branchId: number
) => {
const { Branch } = this.tenancy.models(tenantId); const { Branch } = this.tenancy.models(tenantId);
const branch = await Branch.query().findById(branchId); const branch = await Branch.query().findById(branchId);

View File

@@ -1,4 +1,4 @@
export * from './CashflowBranchesActivateSubscriber'; export * from './CashflowBranchesActviateSubscriber';
export * from './CreditNoteBranchesActivateSubscriber'; export * from './CreditNoteBranchesActivateSubscriber';
export * from './PaymentMadeBranchesActivateSubscriber'; export * from './PaymentMadeBranchesActivateSubscriber';
export * from './PaymentReceiveBranchesActivateSubscriber'; export * from './PaymentReceiveBranchesActivateSubscriber';

View File

@@ -1,12 +1,17 @@
import { Service } from 'typedi'; import { Service, Inject } from 'typedi';
import { includes, camelCase, upperFirst } from 'lodash'; import { includes, difference, camelCase, upperFirst } from 'lodash';
import { IAccount } from '@/interfaces'; import { ACCOUNT_TYPE } from '@/data/AccountTypes';
import { IAccount, ICashflowTransactionLine } from '@/interfaces';
import { getCashflowTransactionType } from './utils'; import { getCashflowTransactionType } from './utils';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants'; import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service() @Service()
export class CommandCashflowValidator { export class CommandCashflowValidator {
@Inject()
private tenancy: HasTenancyService;
/** /**
* Validates the lines accounts type should be cash or bank account. * Validates the lines accounts type should be cash or bank account.
* @param {IAccount} accounts - * @param {IAccount} accounts -

View File

@@ -0,0 +1,14 @@
import { difference, includes } from 'lodash';
import { ICashflowTransactionLine } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import { Inject, Service } from 'typedi';
import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants';
import { IAccount } from '@/interfaces';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service()
export default class CommandCashflowTransaction {
@Inject()
private tenancy: HasTenancyService;
}

View File

@@ -6,7 +6,7 @@ import {
} from './constants'; } from './constants';
/** /**
* Ensures the given transaction type to transformed to appropriate format. * Ensures the given transaction type to transformed to properiate format.
* @param {string} type * @param {string} type
* @returns {string} * @returns {string}
*/ */

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