mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
Compare commits
102 Commits
old-arch
...
reports-ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f068218a16 | ||
|
|
842a862b87 | ||
|
|
1ed77dd5ed | ||
|
|
e47ca98171 | ||
|
|
503d0016ea | ||
|
|
0a2ac4ee56 | ||
|
|
8eb23d3a6f | ||
|
|
18017d25d5 | ||
|
|
f11b09cd87 | ||
|
|
ed81d4c1e0 | ||
|
|
88f66f1c1c | ||
|
|
ab717b96ac | ||
|
|
caff6ce47c | ||
|
|
682be715ae | ||
|
|
85946d3161 | ||
|
|
173610d0fa | ||
|
|
f20f07a42f | ||
|
|
6251831741 | ||
|
|
1cfddf2b4d | ||
|
|
6461a2318f | ||
|
|
92d98ce1d3 | ||
|
|
ef22b9ddaf | ||
|
|
4c42515613 | ||
|
|
2eb56e5850 | ||
|
|
136cc907bb | ||
|
|
fd65ee9428 | ||
|
|
08de50e2b1 | ||
|
|
197d173db9 | ||
|
|
cf496909a5 | ||
|
|
67ae7ad037 | ||
|
|
40b7daa2e3 | ||
|
|
b7d0b6c24a | ||
|
|
95bb4fc8e3 | ||
|
|
5c0bb52b59 | ||
|
|
36851d3209 | ||
|
|
9eee0b384d | ||
|
|
9539003cac | ||
|
|
2017539032 | ||
|
|
c4692d1716 | ||
|
|
7b81d0c8e5 | ||
|
|
9a5110aa38 | ||
|
|
2e1c57438c | ||
|
|
b46f2a91c3 | ||
|
|
8e36aab529 | ||
|
|
9eec60ea22 | ||
|
|
6550e88af3 | ||
|
|
dfc5674088 | ||
|
|
6dd854178d | ||
|
|
520d053b36 | ||
|
|
108d286f62 | ||
|
|
271c46ea3b | ||
|
|
7bcd578c11 | ||
|
|
936800600b | ||
|
|
e7e7a95aa1 | ||
|
|
081fdebee0 | ||
|
|
4ab20ac76a | ||
|
|
72818759a5 | ||
|
|
270b421a6c | ||
|
|
ddaea20d16 | ||
|
|
7e82080cb7 | ||
|
|
3bf5f4be86 | ||
|
|
6f870ea1e1 | ||
|
|
ee284196eb | ||
|
|
52362a43ab | ||
|
|
fdfb766587 | ||
|
|
1773df1858 | ||
|
|
abf92ac83f | ||
|
|
385d84d654 | ||
|
|
2bf58d9cb4 | ||
|
|
ba176394c8 | ||
|
|
1869ba216f | ||
|
|
b72f85b394 | ||
|
|
8bacf3a001 | ||
|
|
505c4b28a5 | ||
|
|
3ad34ba56f | ||
|
|
a819d6c1ba | ||
|
|
1b15261adb | ||
|
|
4938db704e | ||
|
|
3191076762 | ||
|
|
b046edf337 | ||
|
|
515a984714 | ||
|
|
77bbf6828d | ||
|
|
caf235e2b5 | ||
|
|
9f9b75cd31 | ||
|
|
736cedd63d | ||
|
|
cd84872a61 | ||
|
|
a6932d76f3 | ||
|
|
336171081e | ||
|
|
8a12caf48d | ||
|
|
cb8fd68d46 | ||
|
|
dc52f784b6 | ||
|
|
330192c042 | ||
|
|
1f32a7c59a | ||
|
|
83dfaa00fd | ||
|
|
93bf6d9d3d | ||
|
|
bfff56c470 | ||
|
|
87e9cd64e8 | ||
|
|
0a112c5655 | ||
|
|
70211980aa | ||
|
|
2ba31148ca | ||
|
|
05f4b49b58 | ||
|
|
19080a67ab |
@@ -1,3 +1,6 @@
|
|||||||
|
# App
|
||||||
|
APP_JWT_SECRET=123123
|
||||||
|
|
||||||
# Mail
|
# Mail
|
||||||
MAIL_HOST=
|
MAIL_HOST=
|
||||||
MAIL_USERNAME=
|
MAIL_USERNAME=
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,4 +6,5 @@ node_modules/
|
|||||||
# Production env file
|
# Production env file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
test-results/
|
test-results/
|
||||||
|
.qodo
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ services:
|
|||||||
context: ./docker/redis
|
context: ./docker/redis
|
||||||
expose:
|
expose:
|
||||||
- "6379"
|
- "6379"
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
volumes:
|
volumes:
|
||||||
- redis:/data
|
- redis:/data
|
||||||
deploy:
|
deploy:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM redis:4.0
|
FROM redis:6.2.0
|
||||||
|
|
||||||
COPY redis.conf /usr/local/etc/redis/redis.conf
|
COPY redis.conf /usr/local/etc/redis/redis.conf
|
||||||
|
|
||||||
|
|||||||
24
launch.json
Normal file
24
launch.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug Nest Framework",
|
||||||
|
"runtimeExecutable": "npm",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"run",
|
||||||
|
"start:debug",
|
||||||
|
"--",
|
||||||
|
"--inspect-brk"
|
||||||
|
],
|
||||||
|
"autoAttachChildProcesses": true,
|
||||||
|
"restart": true,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"stopOnEntry": false,
|
||||||
|
"console": "integratedTerminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,10 @@
|
|||||||
"dev:server": "lerna run dev --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
|
"dev:server": "lerna run dev --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
|
||||||
"build:server": "lerna run build --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
|
"build:server": "lerna run build --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
|
||||||
"serve:server": "lerna run serve --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\"",
|
"serve:server": "lerna run serve --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\"",
|
||||||
"test:e2e": "playwright test",
|
"server2:start": "lerna run start:dev --scope \"@bigcapital/server2\"",
|
||||||
|
"test:watch": "lerna run test:watch",
|
||||||
|
"test:e2e": "lerna run test:e2e",
|
||||||
|
"start:debug": "lerna run start:debug",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
105
packages/server-nest/.env.example
Normal file
105
packages/server-nest/.env.example
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# App
|
||||||
|
APP_JWT_SECRET=123123
|
||||||
|
|
||||||
|
# Mail
|
||||||
|
MAIL_HOST=
|
||||||
|
MAIL_USERNAME=
|
||||||
|
MAIL_PASSWORD=
|
||||||
|
MAIL_PORT=
|
||||||
|
MAIL_SECURE=
|
||||||
|
MAIL_FROM_NAME=
|
||||||
|
MAIL_FROM_ADDRESS=
|
||||||
|
|
||||||
|
# Database
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_USER=bigcapital
|
||||||
|
DB_PASSWORD=bigcapital
|
||||||
|
DB_ROOT_PASSWORD=root
|
||||||
|
DB_CHARSET=utf8
|
||||||
|
|
||||||
|
# System database
|
||||||
|
SYSTEM_DB_NAME=bigcapital_system
|
||||||
|
# SYSTEM_DB_USER=
|
||||||
|
# SYSTEM_DB_PASSWORD=
|
||||||
|
# SYSTEM_DB_NAME=
|
||||||
|
# SYSTEM_DB_CHARSET=
|
||||||
|
|
||||||
|
# Tenant databases
|
||||||
|
TENANT_DB_NAME_PERFIX=bigcapital_tenant_
|
||||||
|
# TENANT_DB_HOST=
|
||||||
|
# TENANT_DB_USER=
|
||||||
|
# TENANT_DB_PASSWORD=
|
||||||
|
# TENANT_DB_CHARSET=
|
||||||
|
|
||||||
|
# Application
|
||||||
|
BASE_URL=http://example.com
|
||||||
|
JWT_SECRET=b0JDZW56RnV6aEthb0RGPXVEcUI
|
||||||
|
|
||||||
|
# Jobs MongoDB
|
||||||
|
MONGODB_DATABASE_URL=mongodb://localhost/bigcapital
|
||||||
|
|
||||||
|
# App proxy
|
||||||
|
PUBLIC_PROXY_PORT=80
|
||||||
|
PUBLIC_PROXY_SSL_PORT=443
|
||||||
|
|
||||||
|
# Agendash
|
||||||
|
AGENDASH_AUTH_USER=agendash
|
||||||
|
AGENDASH_AUTH_PASSWORD=123123
|
||||||
|
|
||||||
|
# Sign-up restrictions
|
||||||
|
SIGNUP_DISABLED=false
|
||||||
|
SIGNUP_ALLOWED_DOMAINS=
|
||||||
|
SIGNUP_ALLOWED_EMAILS=
|
||||||
|
|
||||||
|
# Sign-up Email Confirmation
|
||||||
|
SIGNUP_EMAIL_CONFIRMATION=false
|
||||||
|
|
||||||
|
# API rate limit (points,duration,block duration).
|
||||||
|
API_RATE_LIMIT=120,60,600
|
||||||
|
|
||||||
|
# Gotenberg API for PDF printing - (production).
|
||||||
|
GOTENBERG_URL=http://gotenberg:3000
|
||||||
|
GOTENBERG_DOCS_URL=http://server:3000/public/
|
||||||
|
|
||||||
|
# Gotenberg API - (development)
|
||||||
|
# GOTENBERG_URL=http://localhost:9000
|
||||||
|
# GOTENBERG_DOCS_URL=http://host.docker.internal:3000/public/
|
||||||
|
|
||||||
|
# Exchange Rate Service
|
||||||
|
EXCHANGE_RATE_SERVICE=open-exchange-rate
|
||||||
|
|
||||||
|
# Open Exchange Rate
|
||||||
|
OPEN_EXCHANGE_RATE_APP_ID=
|
||||||
|
|
||||||
|
# The Plaid environment to use ('sandbox' or 'development').
|
||||||
|
# https://plaid.com/docs/#api-host
|
||||||
|
PLAID_ENV=sandbox
|
||||||
|
|
||||||
|
# Your Plaid keys, which can be found in the Plaid Dashboard.
|
||||||
|
# https://dashboard.plaid.com/account/keys
|
||||||
|
PLAID_CLIENT_ID=
|
||||||
|
PLAID_SECRET=
|
||||||
|
PLAID_LINK_WEBHOOK=
|
||||||
|
|
||||||
|
# https://docs.lemonsqueezy.com/guides/developer-guide/getting-started#create-an-api-key
|
||||||
|
LEMONSQUEEZY_API_KEY=
|
||||||
|
LEMONSQUEEZY_STORE_ID=
|
||||||
|
LEMONSQUEEZY_WEBHOOK_SECRET=
|
||||||
|
|
||||||
|
# S3 documents and attachments
|
||||||
|
S3_REGION=US
|
||||||
|
S3_ACCESS_KEY_ID=
|
||||||
|
S3_SECRET_ACCESS_KEY=
|
||||||
|
S3_ENDPOINT=
|
||||||
|
S3_BUCKET=
|
||||||
|
|
||||||
|
# PostHog
|
||||||
|
POSTHOG_API_KEY=
|
||||||
|
POSTHOG_HOST=
|
||||||
|
|
||||||
|
# Stripe Payment
|
||||||
|
STRIPE_PAYMENT_SECRET_KEY=
|
||||||
|
STRIPE_PAYMENT_PUBLISHABLE_KEY=
|
||||||
|
STRIPE_PAYMENT_CLIENT_ID=
|
||||||
|
STRIPE_PAYMENT_WEBHOOKS_SECRET=
|
||||||
|
STRIPE_PAYMENT_REDIRECT_URL=
|
||||||
25
packages/server-nest/.eslintrc.js
Normal file
25
packages/server-nest/.eslintrc.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: 'tsconfig.json',
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
ignorePatterns: ['.eslintrc.js'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
},
|
||||||
|
};
|
||||||
56
packages/server-nest/.gitignore
vendored
Normal file
56
packages/server-nest/.gitignore
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/node_modules
|
||||||
|
/build
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
/coverage
|
||||||
|
/.nyc_output
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# temp directory
|
||||||
|
.temp
|
||||||
|
.tmp
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
4
packages/server-nest/.prettierrc
Normal file
4
packages/server-nest/.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
||||||
1
packages/server-nest/.todo
Normal file
1
packages/server-nest/.todo
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- Build authentication services.
|
||||||
1
packages/server-nest/README.md
Normal file
1
packages/server-nest/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
## @bigcapitalhq/server
|
||||||
11
packages/server-nest/nest-cli.json
Normal file
11
packages/server-nest/nest-cli.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/nest-cli",
|
||||||
|
"collection": "@nestjs/schematics",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"compilerOptions": {
|
||||||
|
"deleteOutDir": true,
|
||||||
|
"assets": [
|
||||||
|
{ "include": "i18n/**/*", "watchAssets": true }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
151
packages/server-nest/package.json
Normal file
151
packages/server-nest/package.json
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
{
|
||||||
|
"name": "@bigcapital/server2",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"author": "",
|
||||||
|
"private": true,
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nest build",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
|
"start": "nest start",
|
||||||
|
"start:dev": "nest start --watch",
|
||||||
|
"start:debug": "nest start --debug --watch",
|
||||||
|
"start:prod": "node dist/main",
|
||||||
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:cov": "jest --coverage",
|
||||||
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
|
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-s3": "^3.576.0",
|
||||||
|
"@aws-sdk/s3-request-presigner": "^3.583.0",
|
||||||
|
"@bigcapital/email-components": "*",
|
||||||
|
"@bigcapital/pdf-templates": "*",
|
||||||
|
"@bigcapital/utils": "*",
|
||||||
|
"@casl/ability": "^5.4.3",
|
||||||
|
"@lemonsqueezy/lemonsqueezy.js": "^2.2.0",
|
||||||
|
"@liaoliaots/nestjs-redis": "^10.0.0",
|
||||||
|
"@types/multer": "^1.4.11",
|
||||||
|
"@nestjs/bull": "^10.2.1",
|
||||||
|
"@nestjs/bullmq": "^10.2.2",
|
||||||
|
"@nestjs/cache-manager": "^2.2.2",
|
||||||
|
"@nestjs/common": "^10.0.0",
|
||||||
|
"@nestjs/config": "^3.2.3",
|
||||||
|
"@nestjs/core": "^10.0.0",
|
||||||
|
"@nestjs/event-emitter": "^2.0.4",
|
||||||
|
"@nestjs/jwt": "^10.2.0",
|
||||||
|
"@nestjs/passport": "^11.0.5",
|
||||||
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
|
"@nestjs/swagger": "^7.4.2",
|
||||||
|
"@nestjs/throttler": "^6.2.1",
|
||||||
|
"@supercharge/promise-pool": "^3.2.0",
|
||||||
|
"@types/nodemailer": "^6.4.17",
|
||||||
|
"@types/passport-local": "^1.0.38",
|
||||||
|
"@types/ramda": "^0.30.2",
|
||||||
|
"accounting": "^0.4.1",
|
||||||
|
"async": "^3.2.0",
|
||||||
|
"async-mutex": "^0.5.0",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"bluebird": "^3.7.2",
|
||||||
|
"bull": "^4.16.3",
|
||||||
|
"bullmq": "^5.25.6",
|
||||||
|
"cache-manager": "^6.1.1",
|
||||||
|
"cache-manager-redis-store": "^3.0.1",
|
||||||
|
"class-transformer": "^0.5.1",
|
||||||
|
"class-validator": "^0.14.1",
|
||||||
|
"deepdash": "^5.3.9",
|
||||||
|
"express-validator": "^7.2.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"fp-ts": "^2.16.9",
|
||||||
|
"ioredis": "^5.6.0",
|
||||||
|
"is-my-json-valid": "^2.20.5",
|
||||||
|
"js-money": "^0.6.3",
|
||||||
|
"knex": "^3.1.0",
|
||||||
|
"lamda": "^0.4.1",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"mathjs": "^9.4.0",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
|
"moment": "^2.30.1",
|
||||||
|
"moment-range": "^4.0.2",
|
||||||
|
"moment-timezone": "^0.5.43",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"mysql2": "^3.11.3",
|
||||||
|
"multer": "1.4.5-lts.1",
|
||||||
|
"multer-s3": "^3.0.1",
|
||||||
|
"nestjs-cls": "^5.2.0",
|
||||||
|
"nestjs-i18n": "^10.4.9",
|
||||||
|
"nestjs-redis": "^1.3.3",
|
||||||
|
"nodemailer": "^6.3.0",
|
||||||
|
"object-hash": "^2.0.3",
|
||||||
|
"objection": "^3.1.5",
|
||||||
|
"passport": "^0.7.0",
|
||||||
|
"passport-jwt": "^4.0.1",
|
||||||
|
"passport-local": "^1.0.0",
|
||||||
|
"plaid": "^10.3.0",
|
||||||
|
"pluralize": "^8.0.0",
|
||||||
|
"posthog-node": "^4.3.2",
|
||||||
|
"pug": "^3.0.2",
|
||||||
|
"ramda": "^0.30.1",
|
||||||
|
"redis": "^4.7.0",
|
||||||
|
"reflect-metadata": "^0.2.0",
|
||||||
|
"remeda": "^2.19.2",
|
||||||
|
"rxjs": "^7.8.1",
|
||||||
|
"serialize-interceptor": "^1.1.7",
|
||||||
|
"strategy": "^1.1.1",
|
||||||
|
"stripe": "^16.10.0",
|
||||||
|
"uniqid": "^5.2.0",
|
||||||
|
"uuid": "^10.0.0",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
|
"yup": "^0.28.1",
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nestjs/cli": "^10.0.0",
|
||||||
|
"@nestjs/schematics": "^10.0.0",
|
||||||
|
"@nestjs/testing": "^10.0.0",
|
||||||
|
"@types/express": "^5.0.0",
|
||||||
|
"@types/jest": "^29.5.2",
|
||||||
|
"@types/mathjs": "^6.0.12",
|
||||||
|
"@types/node": "^20.3.1",
|
||||||
|
"@types/supertest": "^6.0.0",
|
||||||
|
"@types/yup": "^0.29.13",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||||
|
"@typescript-eslint/parser": "^8.0.0",
|
||||||
|
"eslint": "^9.0.0",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
|
"jest": "^29.5.0",
|
||||||
|
"mustache": "^3.0.3",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"source-map-support": "^0.5.21",
|
||||||
|
"supertest": "^7.0.0",
|
||||||
|
"ts-jest": "^29.1.0",
|
||||||
|
"ts-loader": "^9.4.3",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"tsconfig-paths": "^4.2.0",
|
||||||
|
"typescript": "^5.1.3"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"rootDir": "src",
|
||||||
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
},
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
|
"coverageDirectory": "../coverage",
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
packages/server-nest/src/common/config/gotenberg.ts
Normal file
6
packages/server-nest/src/common/config/gotenberg.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('gotenberg', () => ({
|
||||||
|
url: process.env.GOTENBERG_URL,
|
||||||
|
docsUrl: process.env.GOTENBERG_DOCS_URL,
|
||||||
|
}));
|
||||||
33
packages/server-nest/src/common/config/index.ts
Normal file
33
packages/server-nest/src/common/config/index.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import systemDatabase from './system-database';
|
||||||
|
import tenantDatabase from './tenant-database';
|
||||||
|
import signup from './signup';
|
||||||
|
import gotenberg from './gotenberg';
|
||||||
|
import plaid from './plaid';
|
||||||
|
import lemonsqueezy from './lemonsqueezy';
|
||||||
|
import s3 from './s3';
|
||||||
|
import openExchange from './open-exchange';
|
||||||
|
import posthog from './posthog';
|
||||||
|
import stripePayment from './stripe-payment';
|
||||||
|
import signupConfirmation from './signup-confirmation';
|
||||||
|
import signupRestrictions from './signup-restrictions';
|
||||||
|
import jwt from './jwt';
|
||||||
|
import mail from './mail';
|
||||||
|
import loops from './loops';
|
||||||
|
|
||||||
|
export const config = [
|
||||||
|
systemDatabase,
|
||||||
|
tenantDatabase,
|
||||||
|
signup,
|
||||||
|
gotenberg,
|
||||||
|
plaid,
|
||||||
|
lemonsqueezy,
|
||||||
|
s3,
|
||||||
|
openExchange,
|
||||||
|
posthog,
|
||||||
|
stripePayment,
|
||||||
|
signupConfirmation,
|
||||||
|
signupRestrictions,
|
||||||
|
jwt,
|
||||||
|
mail,
|
||||||
|
loops
|
||||||
|
];
|
||||||
5
packages/server-nest/src/common/config/inventory.ts
Normal file
5
packages/server-nest/src/common/config/inventory.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { registerAs } from "@nestjs/config";
|
||||||
|
|
||||||
|
export default registerAs('inventory', () => ({
|
||||||
|
scheduleComputeItemCost: process.env.INVENTORY_SCHEDULE_COMPUTE_ITEM_COST,
|
||||||
|
}));
|
||||||
5
packages/server-nest/src/common/config/jwt.ts
Normal file
5
packages/server-nest/src/common/config/jwt.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('jwt', () => ({
|
||||||
|
secret: process.env.APP_JWT_SECRET || '123123',
|
||||||
|
}));
|
||||||
7
packages/server-nest/src/common/config/lemonsqueezy.ts
Normal file
7
packages/server-nest/src/common/config/lemonsqueezy.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('lemonsqueezy', () => ({
|
||||||
|
apiKey: process.env.LEMONSQUEEZY_API_KEY,
|
||||||
|
storeId: process.env.LEMONSQUEEZY_STORE_ID,
|
||||||
|
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
|
||||||
|
}));
|
||||||
6
packages/server-nest/src/common/config/loops.ts
Normal file
6
packages/server-nest/src/common/config/loops.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('loops', () => ({
|
||||||
|
apiKey: process.env.LOOPS_API_KEY,
|
||||||
|
}));
|
||||||
13
packages/server-nest/src/common/config/mail.ts
Normal file
13
packages/server-nest/src/common/config/mail.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('mail', () => ({
|
||||||
|
host: process.env.MAIL_HOST,
|
||||||
|
username: process.env.MAIL_USERNAME,
|
||||||
|
password: process.env.MAIL_PASSWORD,
|
||||||
|
port: parseInt(process.env.MAIL_PORT, 10),
|
||||||
|
secure: process.env.MAIL_SECURE === 'true',
|
||||||
|
from: {
|
||||||
|
name: process.env.MAIL_FROM_NAME,
|
||||||
|
address: process.env.MAIL_FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
}));
|
||||||
5
packages/server-nest/src/common/config/open-exchange.ts
Normal file
5
packages/server-nest/src/common/config/open-exchange.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('openExchange', () => ({
|
||||||
|
appId: process.env.OPEN_EXCHANGE_RATE_APP_ID,
|
||||||
|
}));
|
||||||
8
packages/server-nest/src/common/config/plaid.ts
Normal file
8
packages/server-nest/src/common/config/plaid.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('plaid', () => ({
|
||||||
|
env: process.env.PLAID_ENV || 'sandbox',
|
||||||
|
clientId: process.env.PLAID_CLIENT_ID,
|
||||||
|
secret: process.env.PLAID_SECRET,
|
||||||
|
linkWebhook: process.env.PLAID_LINK_WEBHOOK,
|
||||||
|
}));
|
||||||
6
packages/server-nest/src/common/config/posthog.ts
Normal file
6
packages/server-nest/src/common/config/posthog.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('posthog', () => ({
|
||||||
|
apiKey: process.env.POSTHOG_API_KEY,
|
||||||
|
host: process.env.POSTHOG_HOST || 'https://us.i.posthog.com',
|
||||||
|
}));
|
||||||
8
packages/server-nest/src/common/config/redis.ts
Normal file
8
packages/server-nest/src/common/config/redis.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('redis', () => ({
|
||||||
|
host: process.env.REDIS_HOST || 'localhost',
|
||||||
|
port: parseInt(process.env.REDIS_PORT, 10) || 6379,
|
||||||
|
password: process.env.REDIS_PASSWORD || undefined,
|
||||||
|
db: parseInt(process.env.REDIS_DB, 10) || 0,
|
||||||
|
}));
|
||||||
9
packages/server-nest/src/common/config/s3.ts
Normal file
9
packages/server-nest/src/common/config/s3.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('s3', () => ({
|
||||||
|
region: process.env.S3_REGION || 'US',
|
||||||
|
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
||||||
|
endpoint: process.env.S3_ENDPOINT,
|
||||||
|
bucket: process.env.S3_BUCKET,
|
||||||
|
}));
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { parseBoolean } from '@/utils/parse-boolean';
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('signupConfirmation', () => ({
|
||||||
|
enabled: parseBoolean<boolean>(process.env.SIGNUP_EMAIL_CONFIRMATION, false),
|
||||||
|
}));
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { castCommaListEnvVarToArray } from '@/utils/cast-comma-list-envvar-Array';
|
||||||
|
import { parseBoolean } from '@/utils/parse-boolean';
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('signupRestrictions', () => ({
|
||||||
|
disabled: parseBoolean<boolean>(process.env.SIGNUP_DISABLED, false),
|
||||||
|
allowedDomains: castCommaListEnvVarToArray(
|
||||||
|
process.env.SIGNUP_ALLOWED_DOMAINS,
|
||||||
|
),
|
||||||
|
allowedEmails: castCommaListEnvVarToArray(process.env.SIGNUP_ALLOWED_EMAILS),
|
||||||
|
}));
|
||||||
12
packages/server-nest/src/common/config/signup.ts
Normal file
12
packages/server-nest/src/common/config/signup.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('signup', () => ({
|
||||||
|
disabled: process.env.SIGNUP_DISABLED === 'true',
|
||||||
|
allowedDomains: process.env.SIGNUP_ALLOWED_DOMAINS
|
||||||
|
? process.env.SIGNUP_ALLOWED_DOMAINS.split(',')
|
||||||
|
: [],
|
||||||
|
allowedEmails: process.env.SIGNUP_ALLOWED_EMAILS
|
||||||
|
? process.env.SIGNUP_ALLOWED_EMAILS.split(',')
|
||||||
|
: [],
|
||||||
|
emailConfirmation: process.env.SIGNUP_EMAIL_CONFIRMATION === 'true',
|
||||||
|
}));
|
||||||
9
packages/server-nest/src/common/config/stripe-payment.ts
Normal file
9
packages/server-nest/src/common/config/stripe-payment.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('stripePayment', () => ({
|
||||||
|
secretKey: process.env.STRIPE_PAYMENT_SECRET_KEY,
|
||||||
|
publishableKey: process.env.STRIPE_PAYMENT_PUBLISHABLE_KEY,
|
||||||
|
clientId: process.env.STRIPE_PAYMENT_CLIENT_ID,
|
||||||
|
webhooksSecret: process.env.STRIPE_PAYMENT_WEBHOOKS_SECRET,
|
||||||
|
redirectUrl: process.env.STRIPE_PAYMENT_REDIRECT_URL,
|
||||||
|
}));
|
||||||
10
packages/server-nest/src/common/config/system-database.ts
Normal file
10
packages/server-nest/src/common/config/system-database.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('systemDatabase', () => ({
|
||||||
|
client: 'mysql',
|
||||||
|
host: process.env.SYSTEM_DB_HOST || process.env.DB_HOST,
|
||||||
|
port: process.env.SYSTEM_DB_PORT || process.env.DB_PORT || 5432,
|
||||||
|
user: process.env.SYSTEM_DB_USER || process.env.DB_USER,
|
||||||
|
password: process.env.SYSTEM_DB_PASSWORD || process.env.DB_PASSWORD,
|
||||||
|
databaseName: process.env.SYSTEM_DB_NAME || process.env.DB_NAME,
|
||||||
|
}));
|
||||||
13
packages/server-nest/src/common/config/tenant-database.ts
Normal file
13
packages/server-nest/src/common/config/tenant-database.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('tenantDatabase', () => ({
|
||||||
|
client: 'mysql',
|
||||||
|
host: process.env.TENANT_DB_HOST || process.env.DB_HOST,
|
||||||
|
port: process.env.TENANT_DB_PORT || process.env.DB_PORT || 5432,
|
||||||
|
user: process.env.TENANT_DB_USER || process.env.DB_USER,
|
||||||
|
password: process.env.TENANT_DB_PASSWORD || process.env.DB_PASSWORD,
|
||||||
|
dbNamePrefix: process.env.TENANT_DB_NAME_PERFIX || 'bigcapital_tenant_',
|
||||||
|
migrationsDir: path.join(__dirname, '../../database/migrations'),
|
||||||
|
seedsDir: path.join(__dirname, '../../database/seeds/core'),
|
||||||
|
}));
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MULTER_MODULE_OPTIONS = 'MULTER_MODULE_OPTIONS';
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import type { Multer } from 'multer';
|
||||||
|
import * as multerS3 from 'multer-s3';
|
||||||
|
|
||||||
|
export const multerExceptions = {
|
||||||
|
// from https://github.com/expressjs/multer/blob/master/lib/multer-error.js
|
||||||
|
LIMIT_PART_COUNT: 'Too many parts',
|
||||||
|
LIMIT_FILE_SIZE: 'File too large',
|
||||||
|
LIMIT_FILE_COUNT: 'Too many files',
|
||||||
|
LIMIT_FIELD_KEY: 'Field name too long',
|
||||||
|
LIMIT_FIELD_VALUE: 'Field value too long',
|
||||||
|
LIMIT_FIELD_COUNT: 'Too many fields',
|
||||||
|
LIMIT_UNEXPECTED_FILE: 'Unexpected field',
|
||||||
|
MISSING_FIELD_NAME: 'Field name missing',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const busboyExceptions = {
|
||||||
|
// from https://github.com/mscdex/busboy/blob/master/lib/types/multipart.js
|
||||||
|
MULTIPART_BOUNDARY_NOT_FOUND: 'Multipart: Boundary not found',
|
||||||
|
MULTIPART_MALFORMED_PART_HEADER: 'Malformed part header',
|
||||||
|
MULTIPART_UNEXPECTED_END_OF_FORM: 'Unexpected end of form',
|
||||||
|
MULTIPART_UNEXPECTED_END_OF_FILE: 'Unexpected end of file',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
38
packages/server-nest/src/common/constants/multer.utils.ts
Normal file
38
packages/server-nest/src/common/constants/multer.utils.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
HttpException,
|
||||||
|
PayloadTooLargeException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { multerExceptions, busboyExceptions } from './multer.constants';
|
||||||
|
|
||||||
|
// Multer may add in a 'field' property to the error
|
||||||
|
// https://github.com/expressjs/multer/blob/aa42bea6ac7d0cb8fcb279b15a7278cda805dc63/lib/multer-error.js#L19
|
||||||
|
export function transformException(
|
||||||
|
error: (Error & { field?: string }) | undefined,
|
||||||
|
) {
|
||||||
|
if (!error || error instanceof HttpException) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
switch (error.message) {
|
||||||
|
case multerExceptions.LIMIT_FILE_SIZE:
|
||||||
|
return new PayloadTooLargeException(error.message);
|
||||||
|
case multerExceptions.LIMIT_FILE_COUNT:
|
||||||
|
case multerExceptions.LIMIT_FIELD_KEY:
|
||||||
|
case multerExceptions.LIMIT_FIELD_VALUE:
|
||||||
|
case multerExceptions.LIMIT_FIELD_COUNT:
|
||||||
|
case multerExceptions.LIMIT_UNEXPECTED_FILE:
|
||||||
|
case multerExceptions.LIMIT_PART_COUNT:
|
||||||
|
case multerExceptions.MISSING_FIELD_NAME:
|
||||||
|
if (error.field) {
|
||||||
|
return new BadRequestException(`${error.message} - ${error.field}`);
|
||||||
|
}
|
||||||
|
return new BadRequestException(error.message);
|
||||||
|
case busboyExceptions.MULTIPART_BOUNDARY_NOT_FOUND:
|
||||||
|
return new BadRequestException(error.message);
|
||||||
|
case busboyExceptions.MULTIPART_MALFORMED_PART_HEADER:
|
||||||
|
case busboyExceptions.MULTIPART_UNEXPECTED_END_OF_FORM:
|
||||||
|
case busboyExceptions.MULTIPART_UNEXPECTED_END_OF_FILE:
|
||||||
|
return new BadRequestException(`Multipart: ${error.message}`);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
775
packages/server-nest/src/common/events/events.ts
Normal file
775
packages/server-nest/src/common/events/events.ts
Normal file
@@ -0,0 +1,775 @@
|
|||||||
|
export const events = {
|
||||||
|
/**
|
||||||
|
* Authentication service.
|
||||||
|
*/
|
||||||
|
auth: {
|
||||||
|
signIn: 'onSignIn',
|
||||||
|
signingIn: 'onSigningIn',
|
||||||
|
|
||||||
|
signUp: 'onSignUp',
|
||||||
|
signingUp: 'onSigningUp',
|
||||||
|
|
||||||
|
signUpConfirming: 'signUpConfirming',
|
||||||
|
signUpConfirmed: 'signUpConfirmed',
|
||||||
|
|
||||||
|
sendingResetPassword: 'onSendingResetPassword',
|
||||||
|
sendResetPassword: 'onSendResetPassword',
|
||||||
|
|
||||||
|
resetPassword: 'onResetPassword',
|
||||||
|
resetingPassword: 'onResetingPassword',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invite users service.
|
||||||
|
*/
|
||||||
|
inviteUser: {
|
||||||
|
acceptInvite: 'onUserAcceptInvite',
|
||||||
|
sendInvite: 'onUserSendInvite',
|
||||||
|
resendInvite: 'onUserInviteResend',
|
||||||
|
checkInvite: 'onUserCheckInvite',
|
||||||
|
sendInviteTenantSynced: 'onUserSendInviteTenantSynced',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Organization managment service.
|
||||||
|
*/
|
||||||
|
organization: {
|
||||||
|
build: 'onOrganizationBuild',
|
||||||
|
built: 'onOrganizationBuilt',
|
||||||
|
|
||||||
|
seeded: 'onOrganizationSeeded',
|
||||||
|
|
||||||
|
baseCurrencyUpdated: 'onOrganizationBaseCurrencyUpdated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Organization subscription.
|
||||||
|
*/
|
||||||
|
subscription: {
|
||||||
|
onSubscriptionCancel: 'onSubscriptionCancel',
|
||||||
|
onSubscriptionCancelled: 'onSubscriptionCancelled',
|
||||||
|
|
||||||
|
onSubscriptionResume: 'onSubscriptionResume',
|
||||||
|
onSubscriptionResumed: 'onSubscriptionResumed',
|
||||||
|
|
||||||
|
onSubscriptionPlanChange: 'onSubscriptionPlanChange',
|
||||||
|
onSubscriptionPlanChanged: 'onSubscriptionPlanChanged',
|
||||||
|
|
||||||
|
onSubscriptionSubscribed: 'onSubscriptionSubscribed',
|
||||||
|
|
||||||
|
onSubscriptionPaymentSucceed: 'onSubscriptionPaymentSucceed',
|
||||||
|
onSubscriptionPaymentFailed: 'onSubscriptionPaymentFailed',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tenants managment service.
|
||||||
|
*/
|
||||||
|
tenantManager: {
|
||||||
|
databaseCreated: 'onDatabaseCreated',
|
||||||
|
tenantMigrated: 'onTenantMigrated',
|
||||||
|
tenantSeeded: 'onTenantSeeded',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accounts service.
|
||||||
|
*/
|
||||||
|
accounts: {
|
||||||
|
onViewed: 'onAccountViewed',
|
||||||
|
onListViewed: 'onAccountsListViewed',
|
||||||
|
|
||||||
|
onCreating: 'onAccountCreating',
|
||||||
|
onCreated: 'onAccountCreated',
|
||||||
|
|
||||||
|
onEditing: 'onAccountEditing',
|
||||||
|
onEdited: 'onAccountEdited',
|
||||||
|
|
||||||
|
onDelete: 'onAccountDelete',
|
||||||
|
onDeleted: 'onAccountDeleted',
|
||||||
|
|
||||||
|
onBulkDeleted: 'onBulkDeleted',
|
||||||
|
onBulkActivated: 'onAccountBulkActivated',
|
||||||
|
|
||||||
|
onActivated: 'onAccountActivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual journals service.
|
||||||
|
*/
|
||||||
|
manualJournals: {
|
||||||
|
onCreating: 'onManualJournalCreating',
|
||||||
|
onCreated: 'onManualJournalCreated',
|
||||||
|
|
||||||
|
onEditing: 'onManualJournalEditing',
|
||||||
|
onEdited: 'onManualJournalEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onManualJournalDeleting',
|
||||||
|
onDeleted: 'onManualJournalDeleted',
|
||||||
|
|
||||||
|
onPublished: 'onManualJournalPublished',
|
||||||
|
onPublishing: 'onManualJournalPublishing',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expenses service.
|
||||||
|
*/
|
||||||
|
expenses: {
|
||||||
|
onCreating: 'onExpenseCreating',
|
||||||
|
onCreated: 'onExpenseCreated',
|
||||||
|
|
||||||
|
onEditing: 'onExpenseEditing',
|
||||||
|
onEdited: 'onExpenseEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onExpenseDeleting',
|
||||||
|
onDeleted: 'onExpenseDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onExpensePublishing',
|
||||||
|
onPublished: 'onExpensePublished',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales invoices service.
|
||||||
|
*/
|
||||||
|
saleInvoice: {
|
||||||
|
onViewed: 'onSaleInvoiceItemViewed',
|
||||||
|
onListViewed: 'onSaleInvoiceListViewed',
|
||||||
|
|
||||||
|
onPdfViewed: 'onSaleInvoicePdfViewed',
|
||||||
|
|
||||||
|
onCreate: 'onSaleInvoiceCreate',
|
||||||
|
onCreating: 'onSaleInvoiceCreating',
|
||||||
|
onCreated: 'onSaleInvoiceCreated',
|
||||||
|
|
||||||
|
onEdit: 'onSaleInvoiceEdit',
|
||||||
|
onEditing: 'onSaleInvoiceEditing',
|
||||||
|
onEdited: 'onSaleInvoiceEdited',
|
||||||
|
|
||||||
|
onDelete: 'onSaleInvoiceDelete',
|
||||||
|
onDeleting: 'onSaleInvoiceDeleting',
|
||||||
|
onDeleted: 'onSaleInvoiceDeleted',
|
||||||
|
|
||||||
|
onDelivering: 'onSaleInvoiceDelivering',
|
||||||
|
onDeliver: 'onSaleInvoiceDeliver',
|
||||||
|
onDelivered: 'onSaleInvoiceDelivered',
|
||||||
|
|
||||||
|
onPublish: 'onSaleInvoicePublish',
|
||||||
|
onPublished: 'onSaleInvoicePublished',
|
||||||
|
|
||||||
|
onWriteoff: 'onSaleInvoiceWriteoff',
|
||||||
|
onWrittenoff: 'onSaleInvoiceWrittenoff',
|
||||||
|
onWrittenoffCancel: 'onSaleInvoiceWrittenoffCancel',
|
||||||
|
onWrittenoffCanceled: 'onSaleInvoiceWrittenoffCanceled',
|
||||||
|
|
||||||
|
onNotifySms: 'onSaleInvoiceNotifySms',
|
||||||
|
onNotifiedSms: 'onSaleInvoiceNotifiedSms',
|
||||||
|
|
||||||
|
onNotifyMail: 'onSaleInvoiceNotifyMail',
|
||||||
|
onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail',
|
||||||
|
|
||||||
|
onPreMailSend: 'onSaleInvoicePreMailSend',
|
||||||
|
onMailSend: 'onSaleInvoiceMailSend',
|
||||||
|
onMailSent: 'onSaleInvoiceMailSent',
|
||||||
|
|
||||||
|
onMailReminderSend: 'onSaleInvoiceMailReminderSend',
|
||||||
|
onMailReminderSent: 'onSaleInvoiceMailReminderSent',
|
||||||
|
|
||||||
|
onPublicLinkGenerating: 'onPublicSharableLinkGenerating',
|
||||||
|
onPublicLinkGenerated: 'onPublicSharableLinkGenerated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales estimates service.
|
||||||
|
*/
|
||||||
|
saleEstimate: {
|
||||||
|
onViewed: 'onSaleEstimateViewed',
|
||||||
|
onPdfViewed: 'onSaleEstimatePdfViewed',
|
||||||
|
|
||||||
|
onCreating: 'onSaleEstimateCreating',
|
||||||
|
onCreated: 'onSaleEstimateCreated',
|
||||||
|
|
||||||
|
onEditing: 'onSaleEstimateEditing',
|
||||||
|
onEdited: 'onSaleEstimateEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onSaleEstimatedDeleting',
|
||||||
|
onDeleted: 'onSaleEstimatedDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onSaleEstimatedPublishing',
|
||||||
|
onPublished: 'onSaleEstimatedPublished',
|
||||||
|
|
||||||
|
onNotifySms: 'onSaleEstimateNotifySms',
|
||||||
|
onNotifiedSms: 'onSaleEstimateNotifiedSms',
|
||||||
|
|
||||||
|
onDelivering: 'onSaleEstimateDelivering',
|
||||||
|
onDelivered: 'onSaleEstimateDelivered',
|
||||||
|
|
||||||
|
onConvertedToInvoice: 'onSaleEstimateConvertedToInvoice',
|
||||||
|
|
||||||
|
onApproving: 'onSaleEstimateApproving',
|
||||||
|
onApproved: 'onSaleEstimateApproved',
|
||||||
|
|
||||||
|
onRejecting: 'onSaleEstimateRejecting',
|
||||||
|
onRejected: 'onSaleEstimateRejected',
|
||||||
|
|
||||||
|
onNotifyMail: 'onSaleEstimateNotifyMail',
|
||||||
|
|
||||||
|
onPreMailSend: 'onSaleEstimatePreMailSend',
|
||||||
|
onMailSend: 'onSaleEstimateMailSend',
|
||||||
|
onMailSent: 'onSaleEstimateMailSent',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales receipts service.
|
||||||
|
*/
|
||||||
|
saleReceipt: {
|
||||||
|
onPdfViewed: 'onSaleReceiptPdfViewed',
|
||||||
|
|
||||||
|
onCreating: 'onSaleReceiptsCreating',
|
||||||
|
onCreated: 'onSaleReceiptsCreated',
|
||||||
|
|
||||||
|
onEditing: 'onSaleReceiptsEditing',
|
||||||
|
onEdited: 'onSaleReceiptsEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onSaleReceiptsDeleting',
|
||||||
|
onDeleted: 'onSaleReceiptsDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onSaleReceiptPublishing',
|
||||||
|
onPublished: 'onSaleReceiptPublished',
|
||||||
|
|
||||||
|
onClosed: 'onSaleReceiptClosed',
|
||||||
|
onClosing: 'onSaleReceiptClosing',
|
||||||
|
|
||||||
|
onNotifySms: 'onSaleReceiptNotifySms',
|
||||||
|
onNotifiedSms: 'onSaleReceiptNotifiedSms',
|
||||||
|
|
||||||
|
onPreMailSend: 'onSaleReceiptPreMailSend',
|
||||||
|
onMailSend: 'onSaleReceiptMailSend',
|
||||||
|
onMailSent: 'onSaleReceiptMailSent',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment receipts service.
|
||||||
|
*/
|
||||||
|
paymentReceive: {
|
||||||
|
onPdfViewed: 'onPaymentReceivedPdfViewed',
|
||||||
|
|
||||||
|
onCreated: 'onPaymentReceiveCreated',
|
||||||
|
onCreating: 'onPaymentReceiveCreating',
|
||||||
|
|
||||||
|
onEditing: 'onPaymentReceiveEditing',
|
||||||
|
onEdited: 'onPaymentReceiveEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onPaymentReceiveDeleting',
|
||||||
|
onDeleted: 'onPaymentReceiveDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onPaymentReceivePublishing',
|
||||||
|
onPublished: 'onPaymentReceivePublished',
|
||||||
|
|
||||||
|
onNotifySms: 'onPaymentReceiveNotifySms',
|
||||||
|
onNotifiedSms: 'onPaymentReceiveNotifiedSms',
|
||||||
|
|
||||||
|
onPreMailSend: 'onPaymentReceivePreMailSend',
|
||||||
|
onMailSend: 'onPaymentReceiveMailSend',
|
||||||
|
onMailSent: 'onPaymentReceiveMailSent',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bills service.
|
||||||
|
*/
|
||||||
|
bill: {
|
||||||
|
onCreating: 'onBillCreating',
|
||||||
|
onCreated: 'onBillCreated',
|
||||||
|
|
||||||
|
onEditing: 'onBillEditing',
|
||||||
|
onEdited: 'onBillEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onBillDeleting',
|
||||||
|
onDeleted: 'onBillDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onBillPublishing',
|
||||||
|
onPublished: 'onBillPublished',
|
||||||
|
|
||||||
|
onOpening: 'onBillOpening',
|
||||||
|
onOpened: 'onBillOpened',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill payments service.
|
||||||
|
*/
|
||||||
|
billPayment: {
|
||||||
|
onCreating: 'onBillPaymentCreating',
|
||||||
|
onCreated: 'onBillPaymentCreated',
|
||||||
|
|
||||||
|
onEditing: 'onBillPaymentEditing',
|
||||||
|
onEdited: 'onBillPaymentEdited',
|
||||||
|
|
||||||
|
onDeleted: 'onBillPaymentDeleted',
|
||||||
|
onDeleting: 'onBillPaymentDeleting',
|
||||||
|
|
||||||
|
onPublishing: 'onBillPaymentPublishing',
|
||||||
|
onPublished: 'onBillPaymentPublished',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customers services.
|
||||||
|
*/
|
||||||
|
customers: {
|
||||||
|
onCreating: 'onCustomerCreating',
|
||||||
|
onCreated: 'onCustomerCreated',
|
||||||
|
|
||||||
|
onEdited: 'onCustomerEdited',
|
||||||
|
onEditing: 'onCustomerEditing',
|
||||||
|
|
||||||
|
onDeleted: 'onCustomerDeleted',
|
||||||
|
onDeleting: 'onCustomerDeleting',
|
||||||
|
onBulkDeleted: 'onBulkDeleted',
|
||||||
|
|
||||||
|
onOpeningBalanceChanging: 'onCustomerOpeningBalanceChanging',
|
||||||
|
onOpeningBalanceChanged: 'onCustomerOpeingBalanceChanged',
|
||||||
|
|
||||||
|
onActivating: 'onCustomerActivating',
|
||||||
|
onActivated: 'onCustomerActivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vendors services.
|
||||||
|
*/
|
||||||
|
vendors: {
|
||||||
|
onCreated: 'onVendorCreated',
|
||||||
|
onCreating: 'onVendorCreating',
|
||||||
|
|
||||||
|
onEdited: 'onVendorEdited',
|
||||||
|
onEditing: 'onVendorEditing',
|
||||||
|
|
||||||
|
onDeleted: 'onVendorDeleted',
|
||||||
|
onDeleting: 'onVendorDeleting',
|
||||||
|
|
||||||
|
onOpeningBalanceChanging: 'onVendorOpeingBalanceChanging',
|
||||||
|
onOpeningBalanceChanged: 'onVendorOpeingBalanceChanged',
|
||||||
|
|
||||||
|
onActivating: 'onVendorActivating',
|
||||||
|
onActivated: 'onVendorActivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Items service.
|
||||||
|
*/
|
||||||
|
item: {
|
||||||
|
onViewed: 'onItemViewed',
|
||||||
|
|
||||||
|
onCreated: 'onItemCreated',
|
||||||
|
onCreating: 'onItemCreating',
|
||||||
|
|
||||||
|
onEditing: 'onItemEditing',
|
||||||
|
onEdited: 'onItemEdited',
|
||||||
|
|
||||||
|
onDeleted: 'onItemDeleted',
|
||||||
|
onDeleting: 'onItemDeleting',
|
||||||
|
|
||||||
|
onActivating: 'onItemActivating',
|
||||||
|
onActivated: 'onItemActivated',
|
||||||
|
|
||||||
|
onInactivating: 'onInactivating',
|
||||||
|
onInactivated: 'onItemInactivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item category service.
|
||||||
|
*/
|
||||||
|
itemCategory: {
|
||||||
|
onCreated: 'onItemCategoryCreated',
|
||||||
|
onEdited: 'onItemCategoryEdited',
|
||||||
|
onDeleted: 'onItemCategoryDeleted',
|
||||||
|
onBulkDeleted: 'onItemCategoryBulkDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inventory service.
|
||||||
|
*/
|
||||||
|
inventory: {
|
||||||
|
onInventoryTransactionsCreated: 'onInventoryTransactionsCreated',
|
||||||
|
onInventoryTransactionsDeleted: 'onInventoryTransactionsDeleted',
|
||||||
|
|
||||||
|
onComputeItemCostJobScheduled: 'onComputeItemCostJobScheduled',
|
||||||
|
onComputeItemCostJobStarted: 'onComputeItemCostJobStarted',
|
||||||
|
onComputeItemCostJobCompleted: 'onComputeItemCostJobCompleted',
|
||||||
|
|
||||||
|
onInventoryCostEntriesWritten: 'onInventoryCostEntriesWritten',
|
||||||
|
|
||||||
|
onCostLotsGLEntriesBeforeWrite: 'onInventoryCostLotsGLEntriesBeforeWrite',
|
||||||
|
onCostLotsGLEntriesWrite: 'onInventoryCostLotsGLEntriesWrite',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inventory adjustment service.
|
||||||
|
*/
|
||||||
|
inventoryAdjustment: {
|
||||||
|
onQuickCreating: 'onInventoryAdjustmentCreating',
|
||||||
|
onQuickCreated: 'onInventoryAdjustmentQuickCreated',
|
||||||
|
|
||||||
|
onCreated: 'onInventoryAdjustmentCreated',
|
||||||
|
|
||||||
|
onDeleting: 'onInventoryAdjustmentDeleting',
|
||||||
|
onDeleted: 'onInventoryAdjustmentDeleted',
|
||||||
|
|
||||||
|
onPublishing: 'onInventoryAdjustmentPublishing',
|
||||||
|
onPublished: 'onInventoryAdjustmentPublished',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill landed cost.
|
||||||
|
*/
|
||||||
|
billLandedCost: {
|
||||||
|
onCreate: 'onBillLandedCostCreate',
|
||||||
|
onCreated: 'onBillLandedCostCreated',
|
||||||
|
onDelete: 'onBillLandedCostDelete',
|
||||||
|
onDeleted: 'onBillLandedCostDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
cashflow: {
|
||||||
|
onOwnerContributionCreate: 'onCashflowOwnerContributionCreate',
|
||||||
|
onOwnerContributionCreated: 'onCashflowOwnerContributionCreated',
|
||||||
|
|
||||||
|
onOtherIncomeCreate: 'onCashflowOtherIncomeCreate',
|
||||||
|
onOtherIncomeCreated: 'onCashflowOtherIncomeCreated',
|
||||||
|
|
||||||
|
onTransactionCreating: 'onCashflowTransactionCreating',
|
||||||
|
onTransactionCreated: 'onCashflowTransactionCreated',
|
||||||
|
|
||||||
|
onTransactionDeleting: 'onCashflowTransactionDeleting',
|
||||||
|
onTransactionDeleted: 'onCashflowTransactionDeleted',
|
||||||
|
|
||||||
|
onTransactionCategorizing: 'onTransactionCategorizing',
|
||||||
|
onTransactionCategorized: 'onCashflowTransactionCategorized',
|
||||||
|
|
||||||
|
onTransactionUncategorizedCreating: 'onTransactionUncategorizedCreating',
|
||||||
|
onTransactionUncategorizedCreated: 'onTransactionUncategorizedCreated',
|
||||||
|
|
||||||
|
onTransactionUncategorizing: 'onTransactionUncategorizing',
|
||||||
|
onTransactionUncategorized: 'onTransactionUncategorized',
|
||||||
|
|
||||||
|
onTransactionCategorizingAsExpense: 'onTransactionCategorizingAsExpense',
|
||||||
|
onTransactionCategorizedAsExpense: 'onTransactionCategorizedAsExpense',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Roles service events.
|
||||||
|
*/
|
||||||
|
roles: {
|
||||||
|
onCreate: 'onRoleCreate',
|
||||||
|
onCreated: 'onRoleCreated',
|
||||||
|
onEdit: 'onRoleEdit',
|
||||||
|
onEdited: 'onRoleEdited',
|
||||||
|
onDelete: 'onRoleDelete',
|
||||||
|
onDeleted: 'onRoleDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
tenantUser: {
|
||||||
|
onEdited: 'onTenantUserEdited',
|
||||||
|
onDeleted: 'onTenantUserDeleted',
|
||||||
|
onActivated: 'onTenantUserActivated',
|
||||||
|
onInactivated: 'onTenantUserInactivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credit note service.
|
||||||
|
*/
|
||||||
|
creditNote: {
|
||||||
|
onPdfViewed: 'onCreditNotePdfViewed',
|
||||||
|
|
||||||
|
onCreate: 'onCreditNoteCreate',
|
||||||
|
onCreating: 'onCreditNoteCreating',
|
||||||
|
onCreated: 'onCreditNoteCreated',
|
||||||
|
|
||||||
|
onEditing: 'onCreditNoteEditing',
|
||||||
|
onEdit: 'onCreditNoteEdit',
|
||||||
|
onEdited: 'onCreditNoteEdited',
|
||||||
|
|
||||||
|
onDelete: 'onCreditNoteDelete',
|
||||||
|
onDeleting: 'onCreditNoteDeleting',
|
||||||
|
onDeleted: 'onCreditNoteDeleted',
|
||||||
|
|
||||||
|
onOpen: 'onCreditNoteOpen',
|
||||||
|
onOpening: 'onCreditNoteOpening',
|
||||||
|
onOpened: 'onCreditNoteOpened',
|
||||||
|
|
||||||
|
onRefundCreate: 'onCreditNoteRefundCreate',
|
||||||
|
onRefundCreating: 'onCreditNoteRefundCreating',
|
||||||
|
onRefundCreated: 'onCreditNoteRefundCreated',
|
||||||
|
|
||||||
|
onRefundDelete: 'onCreditNoteRefundDelete',
|
||||||
|
onRefundDeleting: 'onCreditNoteRefundDeleting',
|
||||||
|
onRefundDeleted: 'onCreditNoteRefundDeleted',
|
||||||
|
|
||||||
|
onApplyToInvoicesCreated: 'onCreditNoteApplyToInvoiceCreated',
|
||||||
|
onApplyToInvoicesCreate: 'onCreditNoteApplyToInvoiceCreate',
|
||||||
|
onApplyToInvoicesDeleted: 'onCreditNoteApplyToInvoiceDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vendor credit service.
|
||||||
|
*/
|
||||||
|
vendorCredit: {
|
||||||
|
onCreate: 'onVendorCreditCreate',
|
||||||
|
onCreating: 'onVendorCreditCreating',
|
||||||
|
onCreated: 'onVendorCreditCreated',
|
||||||
|
|
||||||
|
onEdit: 'onVendorCreditEdit',
|
||||||
|
onEditing: 'onVendorCreditEditing',
|
||||||
|
onEdited: 'onVendorCreditEdited',
|
||||||
|
|
||||||
|
onDelete: 'onVendorCreditDelete',
|
||||||
|
onDeleting: 'onVendorCreditDeleting',
|
||||||
|
onDeleted: 'onVendorCreditDeleted',
|
||||||
|
|
||||||
|
onOpen: 'onVendorCreditOpen',
|
||||||
|
onOpened: 'onVendorCreditOpened',
|
||||||
|
|
||||||
|
onRefundCreating: 'onVendorCreditRefundCreating',
|
||||||
|
onRefundCreate: 'onVendorCreditRefundCreate',
|
||||||
|
onRefundCreated: 'onVendorCreditRefundCreated',
|
||||||
|
|
||||||
|
onRefundDelete: 'onVendorCreditRefundDelete',
|
||||||
|
onRefundDeleting: 'onVendorCreditRefundDeleting',
|
||||||
|
onRefundDeleted: 'onVendorCreditRefundDeleted',
|
||||||
|
|
||||||
|
onApplyToInvoicesCreated: 'onVendorCreditApplyToInvoiceCreated',
|
||||||
|
onApplyToInvoicesCreate: 'onVendorCreditApplyToInvoiceCreate',
|
||||||
|
onApplyToInvoicesDeleted: 'onVendorCreditApplyToInvoiceDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
transactionsLocking: {
|
||||||
|
locked: 'onTransactionLockingLocked',
|
||||||
|
lockCanceled: 'onTransactionLockingLockCanceled',
|
||||||
|
partialUnlocked: 'onTransactionLockingPartialUnlocked',
|
||||||
|
partialUnlockCanceled: 'onTransactionLockingPartialUnlockCanceled',
|
||||||
|
},
|
||||||
|
|
||||||
|
warehouse: {
|
||||||
|
onCreate: 'onWarehouseCreate',
|
||||||
|
onCreated: 'onWarehouseCreated',
|
||||||
|
|
||||||
|
onEdit: 'onWarehouseEdit',
|
||||||
|
onEdited: 'onWarehouseEdited',
|
||||||
|
|
||||||
|
onDelete: 'onWarehouseDelete',
|
||||||
|
onDeleted: 'onWarehouseDeleted',
|
||||||
|
|
||||||
|
onActivate: 'onWarehouseActivate',
|
||||||
|
onActivated: 'onWarehouseActivated',
|
||||||
|
|
||||||
|
onMarkPrimary: 'onWarehouseMarkPrimary',
|
||||||
|
onMarkedPrimary: 'onWarehouseMarkedPrimary',
|
||||||
|
},
|
||||||
|
|
||||||
|
warehouseTransfer: {
|
||||||
|
onCreate: 'onWarehouseTransferCreate',
|
||||||
|
onCreated: 'onWarehouseTransferCreated',
|
||||||
|
|
||||||
|
onEdit: 'onWarehouseTransferEdit',
|
||||||
|
onEdited: 'onWarehouseTransferEdited',
|
||||||
|
|
||||||
|
onDelete: 'onWarehouseTransferDelete',
|
||||||
|
onDeleted: 'onWarehouseTransferDeleted',
|
||||||
|
|
||||||
|
onInitiate: 'onWarehouseTransferInitiate',
|
||||||
|
onInitiated: 'onWarehouseTransferInitated',
|
||||||
|
|
||||||
|
onTransfer: 'onWarehouseTransferInitiate',
|
||||||
|
onTransferred: 'onWarehouseTransferTransferred',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Branches.
|
||||||
|
*/
|
||||||
|
branch: {
|
||||||
|
onActivate: 'onBranchActivate',
|
||||||
|
onActivated: 'onBranchActivated',
|
||||||
|
|
||||||
|
onMarkPrimary: 'onBranchMarkPrimary',
|
||||||
|
onMarkedPrimary: 'onBranchMarkedPrimary',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Projects.
|
||||||
|
*/
|
||||||
|
project: {
|
||||||
|
onCreate: 'onProjectCreate',
|
||||||
|
onCreating: 'onProjectCreating',
|
||||||
|
onCreated: 'onProjectCreated',
|
||||||
|
|
||||||
|
onEdit: 'onEditProject',
|
||||||
|
onEditing: 'onEditingProject',
|
||||||
|
onEdited: 'onEditedProject',
|
||||||
|
|
||||||
|
onEditStatus: 'onEditStatusProject',
|
||||||
|
onEditingStatus: 'onEditingStatusProject',
|
||||||
|
onEditedStatus: 'onEditedStatusProject',
|
||||||
|
|
||||||
|
onDelete: 'onDeleteProject',
|
||||||
|
onDeleting: 'onDeletingProject',
|
||||||
|
onDeleted: 'onDeletedProject',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project Tasks.
|
||||||
|
*/
|
||||||
|
projectTask: {
|
||||||
|
onCreate: 'onProjectTaskCreate',
|
||||||
|
onCreating: 'onProjectTaskCreating',
|
||||||
|
onCreated: 'onProjectTaskCreated',
|
||||||
|
|
||||||
|
onEdit: 'onProjectTaskEdit',
|
||||||
|
onEditing: 'onProjectTaskEditing',
|
||||||
|
onEdited: 'onProjectTaskEdited',
|
||||||
|
|
||||||
|
onDelete: 'onProjectTaskDelete',
|
||||||
|
onDeleting: 'onProjectTaskDeleting',
|
||||||
|
onDeleted: 'onProjectTaskDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project Times.
|
||||||
|
*/
|
||||||
|
projectTime: {
|
||||||
|
onCreate: 'onProjectTimeCreate',
|
||||||
|
onCreating: 'onProjectTimeCreating',
|
||||||
|
onCreated: 'onProjectTimeCreated',
|
||||||
|
|
||||||
|
onEdit: 'onProjectTimeEdit',
|
||||||
|
onEditing: 'onProjectTimeEditing',
|
||||||
|
onEdited: 'onProjectTimeEdited',
|
||||||
|
|
||||||
|
onDelete: 'onProjectTimeDelete',
|
||||||
|
onDeleting: 'onProjectTimeDeleting',
|
||||||
|
onDeleted: 'onProjectTimeDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
taxRates: {
|
||||||
|
onCreating: 'onTaxRateCreating',
|
||||||
|
onCreated: 'onTaxRateCreated',
|
||||||
|
|
||||||
|
onEditing: 'onTaxRateEditing',
|
||||||
|
onEdited: 'onTaxRateEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onTaxRateDeleting',
|
||||||
|
onDeleted: 'onTaxRateDeleted',
|
||||||
|
|
||||||
|
onActivating: 'onTaxRateActivating',
|
||||||
|
onActivated: 'onTaxRateActivated',
|
||||||
|
|
||||||
|
onInactivating: 'onTaxRateInactivating',
|
||||||
|
onInactivated: 'onTaxRateInactivated',
|
||||||
|
},
|
||||||
|
|
||||||
|
plaid: {
|
||||||
|
onItemCreated: 'onPlaidItemCreated',
|
||||||
|
onTransactionsSynced: 'onPlaidTransactionsSynced',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bank rules.
|
||||||
|
bankRules: {
|
||||||
|
onCreating: 'onBankRuleCreating',
|
||||||
|
onCreated: 'onBankRuleCreated',
|
||||||
|
|
||||||
|
onEditing: 'onBankRuleEditing',
|
||||||
|
onEdited: 'onBankRuleEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onBankRuleDeleting',
|
||||||
|
onDeleted: 'onBankRuleDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bank matching.
|
||||||
|
bankMatch: {
|
||||||
|
onMatching: 'onBankTransactionMatching',
|
||||||
|
onMatched: 'onBankTransactionMatched',
|
||||||
|
|
||||||
|
onUnmatching: 'onBankTransactionUnmathcing',
|
||||||
|
onUnmatched: 'onBankTransactionUnmathced',
|
||||||
|
},
|
||||||
|
|
||||||
|
bankTransactions: {
|
||||||
|
onExcluding: 'onBankTransactionExclude',
|
||||||
|
onExcluded: 'onBankTransactionExcluded',
|
||||||
|
|
||||||
|
onUnexcluding: 'onBankTransactionUnexcluding',
|
||||||
|
onUnexcluded: 'onBankTransactionUnexcluded',
|
||||||
|
|
||||||
|
onPendingRemoving: 'onBankTransactionPendingRemoving',
|
||||||
|
onPendingRemoved: 'onBankTransactionPendingRemoved',
|
||||||
|
},
|
||||||
|
|
||||||
|
bankAccount: {
|
||||||
|
onDisconnecting: 'onBankAccountDisconnecting',
|
||||||
|
onDisconnected: 'onBankAccountDisconnected',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Import files.
|
||||||
|
import: {
|
||||||
|
onImportCommitted: 'onImportFileCommitted',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Branding templates
|
||||||
|
pdfTemplate: {
|
||||||
|
onCreating: 'onPdfTemplateCreating',
|
||||||
|
onCreated: 'onPdfTemplateCreated',
|
||||||
|
|
||||||
|
onEditing: 'onPdfTemplateEditing',
|
||||||
|
onEdited: 'onPdfTemplatedEdited',
|
||||||
|
|
||||||
|
onDeleting: 'onPdfTemplateDeleting',
|
||||||
|
onDeleted: 'onPdfTemplateDeleted',
|
||||||
|
|
||||||
|
onAssignedDefault: 'onPdfTemplateAssignedDefault',
|
||||||
|
onAssigningDefault: 'onPdfTemplateAssigningDefault',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Payment method.
|
||||||
|
paymentMethod: {
|
||||||
|
onEditing: 'onPaymentMethodEditing',
|
||||||
|
onEdited: 'onPaymentMethodEdited',
|
||||||
|
|
||||||
|
onDeleted: 'onPaymentMethodDeleted',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Payment methods integrations
|
||||||
|
paymentIntegrationLink: {
|
||||||
|
onPaymentIntegrationLink: 'onPaymentIntegrationLink',
|
||||||
|
onPaymentIntegrationDeleteLink: 'onPaymentIntegrationDeleteLink',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Stripe Payment Integration
|
||||||
|
stripeIntegration: {
|
||||||
|
onAccountCreated: 'onStripeIntegrationAccountCreated',
|
||||||
|
onAccountDeleted: 'onStripeIntegrationAccountDeleted',
|
||||||
|
|
||||||
|
onPaymentLinkCreated: 'onStripePaymentLinkCreated',
|
||||||
|
onPaymentLinkInactivated: 'onStripePaymentLinkInactivated',
|
||||||
|
|
||||||
|
onOAuthCodeGranted: 'onStripeOAuthCodeGranted',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Stripe Payment Webhooks
|
||||||
|
stripeWebhooks: {
|
||||||
|
onCheckoutSessionCompleted: 'onStripeCheckoutSessionCompleted',
|
||||||
|
onAccountUpdated: 'onStripeAccountUpdated',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Reports
|
||||||
|
reports: {
|
||||||
|
onBalanceSheetViewed: 'onBalanceSheetViewed',
|
||||||
|
onTrialBalanceSheetView: 'onTrialBalanceSheetViewed',
|
||||||
|
onProfitLossSheetViewed: 'onProfitLossSheetViewed',
|
||||||
|
onCashflowStatementViewed: 'onCashflowStatementViewed',
|
||||||
|
onGeneralLedgerViewed: 'onGeneralLedgerViewed',
|
||||||
|
onJournalViewed: 'onJounralViewed',
|
||||||
|
onReceivableAgingViewed: 'onReceivableAgingViewed',
|
||||||
|
onPayableAgingViewed: 'onPayableAgingViewed',
|
||||||
|
onCustomerBalanceSummaryViewed: 'onInventoryValuationViewed',
|
||||||
|
onVendorBalanceSummaryViewed: 'onVendorBalanceSummaryViewed',
|
||||||
|
onInventoryValuationViewed: 'onCustomerBalanceSummaryViewed',
|
||||||
|
onCustomerTransactionsViewed: 'onCustomerTransactionsViewed',
|
||||||
|
onVendorTransactionsViewed: 'onVendorTransactionsViewed',
|
||||||
|
onSalesByItemViewed: 'onSalesByItemViewed',
|
||||||
|
onPurchasesByItemViewed: 'onPurchasesByItemViewed',
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export class ModelEntityNotFound extends Error {
|
||||||
|
constructor(entityId, message?) {
|
||||||
|
message = message || `Entity with id ${entityId} does not exist`;
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
ExceptionFilter,
|
||||||
|
Catch,
|
||||||
|
ArgumentsHost,
|
||||||
|
HttpStatus,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Response } from 'express';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
|
||||||
|
@Catch(ServiceError)
|
||||||
|
export class ServiceErrorFilter implements ExceptionFilter {
|
||||||
|
catch(exception: ServiceError, host: ArgumentsHost) {
|
||||||
|
const ctx = host.switchToHttp();
|
||||||
|
const response = ctx.getResponse<Response>();
|
||||||
|
const status = exception.getStatus();
|
||||||
|
|
||||||
|
response.status(status).json({
|
||||||
|
statusCode: status,
|
||||||
|
errorType: exception.errorType,
|
||||||
|
message: exception.message,
|
||||||
|
payload: exception.payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
CallHandler,
|
||||||
|
ExecutionContext,
|
||||||
|
Inject,
|
||||||
|
mixin,
|
||||||
|
NestInterceptor,
|
||||||
|
Optional,
|
||||||
|
Type,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import * as multer from 'multer';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { MULTER_MODULE_OPTIONS } from '../constants/files.constants';
|
||||||
|
import { transformException } from '../constants/multer.utils';
|
||||||
|
import { MulterModuleOptions } from '@nestjs/platform-express';
|
||||||
|
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
|
||||||
|
|
||||||
|
type MulterInstance = any;
|
||||||
|
/**
|
||||||
|
* @param {string} fieldName
|
||||||
|
* @param {Function|MulterOptions} localOptions - Function that receives controller instance or MulterOptions object
|
||||||
|
*/
|
||||||
|
export function FileInterceptor(
|
||||||
|
fieldName: string,
|
||||||
|
localOptions?: ((instance: any) => MulterOptions) | MulterOptions,
|
||||||
|
): Type<NestInterceptor> {
|
||||||
|
class MixinInterceptor implements NestInterceptor {
|
||||||
|
protected multer: MulterInstance;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Optional()
|
||||||
|
@Inject(MULTER_MODULE_OPTIONS)
|
||||||
|
options: (() => MulterModuleOptions | MulterModuleOptions) = () => ({}),
|
||||||
|
) {
|
||||||
|
const resolvedOptions = typeof localOptions === 'function'
|
||||||
|
? localOptions(this)
|
||||||
|
: localOptions;
|
||||||
|
|
||||||
|
this.multer = (multer as any)({
|
||||||
|
...(typeof options === 'function' ? options() : options),
|
||||||
|
...resolvedOptions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async intercept(
|
||||||
|
context: ExecutionContext,
|
||||||
|
next: CallHandler,
|
||||||
|
): Promise<Observable<any>> {
|
||||||
|
const ctx = context.switchToHttp();
|
||||||
|
|
||||||
|
await new Promise<void>((resolve, reject) =>
|
||||||
|
this.multer.single(fieldName)(
|
||||||
|
ctx.getRequest(),
|
||||||
|
ctx.getResponse(),
|
||||||
|
(err: any) => {
|
||||||
|
if (err) {
|
||||||
|
const error = transformException(err);
|
||||||
|
return reject(error);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return next.handle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Interceptor = mixin(MixinInterceptor);
|
||||||
|
|
||||||
|
return Interceptor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
type ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
type NestInterceptor,
|
||||||
|
type CallHandler,
|
||||||
|
Optional,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { type Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
export function camelToSnake<T = any>(value: T) {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(camelToSnake);
|
||||||
|
}
|
||||||
|
if (typeof value === 'object' && !(value instanceof Date)) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(value).map(([key, value]) => [
|
||||||
|
key
|
||||||
|
.split(/(?=[A-Z])/)
|
||||||
|
.join('_')
|
||||||
|
.toLowerCase(),
|
||||||
|
camelToSnake(value),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function snakeToCamel<T = any>(value: T) {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(snakeToCamel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const impl = (str: string) => {
|
||||||
|
const converted = str.replace(/([-_]\w)/g, (group) =>
|
||||||
|
group[1].toUpperCase(),
|
||||||
|
);
|
||||||
|
return converted[0].toLowerCase() + converted.slice(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof value === 'object' && !(value instanceof Date)) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(value).map(([key, value]) => [
|
||||||
|
impl(key),
|
||||||
|
snakeToCamel(value),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_STRATEGY = {
|
||||||
|
in: snakeToCamel,
|
||||||
|
out: camelToSnake,
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SerializeInterceptor implements NestInterceptor<any, any> {
|
||||||
|
constructor(@Optional() readonly strategy = DEFAULT_STRATEGY) {}
|
||||||
|
|
||||||
|
intercept(
|
||||||
|
context: ExecutionContext,
|
||||||
|
next: CallHandler<any>,
|
||||||
|
): Observable<any> {
|
||||||
|
const request = context.switchToHttp().getRequest();
|
||||||
|
request.body = this.strategy.in(request.body);
|
||||||
|
|
||||||
|
// handle returns stream..
|
||||||
|
return next.handle().pipe(map(this.strategy.out));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import {
|
||||||
|
PipeTransform,
|
||||||
|
Injectable,
|
||||||
|
ArgumentMetadata,
|
||||||
|
BadRequestException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { validate } from 'class-validator';
|
||||||
|
import { plainToInstance } from 'class-transformer';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ValidationPipe implements PipeTransform<any> {
|
||||||
|
async transform(value: any, { metatype }: ArgumentMetadata) {
|
||||||
|
if (!metatype || !this.toValidate(metatype)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const object = plainToInstance(metatype, value);
|
||||||
|
const errors = await validate(object);
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
throw new BadRequestException(errors);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private toValidate(metatype: Function): boolean {
|
||||||
|
const types: Function[] = [String, Boolean, Number, Array, Object];
|
||||||
|
return !types.includes(metatype);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
packages/server-nest/src/common/pipes/ZodValidation.pipe.ts
Normal file
20
packages/server-nest/src/common/pipes/ZodValidation.pipe.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
PipeTransform,
|
||||||
|
ArgumentMetadata,
|
||||||
|
BadRequestException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ZodSchema } from 'zod';
|
||||||
|
|
||||||
|
export class ZodValidationPipe implements PipeTransform {
|
||||||
|
constructor(private schema: ZodSchema) {}
|
||||||
|
|
||||||
|
transform(value: unknown, metadata: ArgumentMetadata) {
|
||||||
|
try {
|
||||||
|
const parsedValue = this.schema.parse(value);
|
||||||
|
return parsedValue;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
throw new BadRequestException(error.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
260
packages/server-nest/src/common/repository/CachableRepository.ts
Normal file
260
packages/server-nest/src/common/repository/CachableRepository.ts
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
// import hashObject from 'object-hash';
|
||||||
|
// import { EntityRepository } from './EntityRepository';
|
||||||
|
|
||||||
|
// export class CachableRepository extends EntityRepository {
|
||||||
|
// repositoryName: string;
|
||||||
|
// cache: any;
|
||||||
|
// i18n: any;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Constructor method.
|
||||||
|
// * @param {Knex} knex
|
||||||
|
// * @param {Cache} cache
|
||||||
|
// */
|
||||||
|
// constructor(knex, cache, i18n) {
|
||||||
|
// super(knex);
|
||||||
|
|
||||||
|
// this.cache = cache;
|
||||||
|
// this.i18n = i18n;
|
||||||
|
// this.repositoryName = this.constructor.name;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// getByCache(key, callback) {
|
||||||
|
// return callback();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Retrieve the cache key of the method name and arguments.
|
||||||
|
// * @param {string} method
|
||||||
|
// * @param {...any} args
|
||||||
|
// * @return {string}
|
||||||
|
// */
|
||||||
|
// getCacheKey(method, ...args) {
|
||||||
|
// const hashArgs = hashObject({ ...args });
|
||||||
|
// const repositoryName = this.repositoryName;
|
||||||
|
|
||||||
|
// return `${repositoryName}-${method}-${hashArgs}`;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Retrieve all entries with specified relations.
|
||||||
|
// * @param withRelations
|
||||||
|
// */
|
||||||
|
// all(withRelations?, trx?) {
|
||||||
|
// const cacheKey = this.getCacheKey('all', withRelations);
|
||||||
|
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.all(withRelations, trx);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Finds list of entities with specified attributes
|
||||||
|
// * @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
|
||||||
|
// * @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
// */
|
||||||
|
// find(attributeValues = {}, withRelations?) {
|
||||||
|
// const cacheKey = this.getCacheKey('find', attributeValues, withRelations);
|
||||||
|
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.find(attributeValues, withRelations);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Finds list of entities with attribute values that are different from specified ones
|
||||||
|
// * @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
// * @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
// */
|
||||||
|
// findWhereNot(attributeValues = {}, withRelations?) {
|
||||||
|
// const cacheKey = this.getCacheKey(
|
||||||
|
// 'findWhereNot',
|
||||||
|
// attributeValues,
|
||||||
|
// withRelations
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.findWhereNot(attributeValues, withRelations);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Finds list of entities with specified attributes (any of multiple specified values)
|
||||||
|
// * Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
|
||||||
|
// *
|
||||||
|
// * @param {string|Object} searchParam - attribute name or search criteria object
|
||||||
|
// * @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
|
||||||
|
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
// * @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
// */
|
||||||
|
// findWhereIn(searchParam, attributeValues, withRelations?) {
|
||||||
|
// const cacheKey = this.getCacheKey(
|
||||||
|
// 'findWhereIn',
|
||||||
|
// attributeValues,
|
||||||
|
// withRelations
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.findWhereIn(searchParam, attributeValues, withRelations);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Finds first entity by given parameters
|
||||||
|
// *
|
||||||
|
// * @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
// * @returns {Promise<Object>}
|
||||||
|
// */
|
||||||
|
// findOne(attributeValues = {}, withRelations?) {
|
||||||
|
// const cacheKey = this.getCacheKey(
|
||||||
|
// 'findOne',
|
||||||
|
// attributeValues,
|
||||||
|
// withRelations
|
||||||
|
// );
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.findOne(attributeValues, withRelations);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Finds first entity by given parameters
|
||||||
|
// *
|
||||||
|
// * @param {string || number} id - value of id column of the entity
|
||||||
|
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
// * @returns {Promise<Object>}
|
||||||
|
// */
|
||||||
|
// findOneById(id, withRelations?) {
|
||||||
|
// const cacheKey = this.getCacheKey('findOneById', id, withRelations);
|
||||||
|
|
||||||
|
// return this.getByCache(cacheKey, () => {
|
||||||
|
// return super.findOneById(id, withRelations);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Persists new entity or an array of entities.
|
||||||
|
// * This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
|
||||||
|
// * Batch insert only works on PostgreSQL
|
||||||
|
// * @param {Object} entity - model instance or parameters for a new entity
|
||||||
|
// * @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
// */
|
||||||
|
// async create(entity, trx?) {
|
||||||
|
// const result = await super.create(entity, trx);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after insert operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
|
||||||
|
// *
|
||||||
|
// * @param {Object} entity - single entity instance
|
||||||
|
// * @param {Object} [trx] - knex transaction instance. If not specified, new implicit transaction will be used.
|
||||||
|
// * @returns {Promise<integer>} number of affected rows
|
||||||
|
// */
|
||||||
|
// async update(entity, whereAttributes?, trx?) {
|
||||||
|
// const result = await super.update(entity, whereAttributes, trx);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after update operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @param {Object} attributeValues - values to filter deleted entities by
|
||||||
|
// * @param {Object} [trx]
|
||||||
|
// * @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||||
|
// */
|
||||||
|
// async deleteBy(attributeValues, trx?) {
|
||||||
|
// const result = await super.deleteBy(attributeValues, trx);
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @param {string || number} id - value of id column of the entity
|
||||||
|
// * @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||||
|
// */
|
||||||
|
// deleteById(id: number | string, trx?) {
|
||||||
|
// const result = super.deleteById(id, trx);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after insert operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {string|number[]} values -
|
||||||
|
// */
|
||||||
|
// async deleteWhereIn(field: string, values: string | number[]) {
|
||||||
|
// const result = await super.deleteWhereIn(field, values);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after delete operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {string|number[]} values
|
||||||
|
// */
|
||||||
|
// async deleteWhereIdIn(values: string | number[], trx?) {
|
||||||
|
// const result = await super.deleteWhereIdIn(values, trx);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after delete operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param graph
|
||||||
|
// * @param options
|
||||||
|
// */
|
||||||
|
// async upsertGraph(graph, options) {
|
||||||
|
// const result = await super.upsertGraph(graph, options);
|
||||||
|
|
||||||
|
// // Flushes the repository cache after insert operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {} whereAttributes
|
||||||
|
// * @param {string} field
|
||||||
|
// * @param {number} amount
|
||||||
|
// */
|
||||||
|
// async changeNumber(whereAttributes, field: string, amount: number, trx?) {
|
||||||
|
// const result = await super.changeNumber(
|
||||||
|
// whereAttributes,
|
||||||
|
// field,
|
||||||
|
// amount,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Flushes the repository cache after update operation.
|
||||||
|
// this.flushCache();
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Flush repository cache.
|
||||||
|
// */
|
||||||
|
// flushCache(): void {
|
||||||
|
// this.cache.delStartWith(this.repositoryName);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
232
packages/server-nest/src/common/repository/EntityRepository.ts
Normal file
232
packages/server-nest/src/common/repository/EntityRepository.ts
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
import { cloneDeep, forOwn, isString } from 'lodash';
|
||||||
|
import { ModelEntityNotFound } from '../exceptions/ModelEntityNotFound';
|
||||||
|
import { Model } from 'objection';
|
||||||
|
|
||||||
|
function applyGraphFetched(withRelations, builder) {
|
||||||
|
const relations = Array.isArray(withRelations)
|
||||||
|
? withRelations
|
||||||
|
: typeof withRelations === 'string'
|
||||||
|
? withRelations.split(',').map((relation) => relation.trim())
|
||||||
|
: [];
|
||||||
|
|
||||||
|
relations.forEach((relation) => {
|
||||||
|
builder.withGraphFetched(relation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EntityRepository {
|
||||||
|
idColumn: string = 'id';
|
||||||
|
knex: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the repository model binded it to knex instance.
|
||||||
|
*/
|
||||||
|
get model(): typeof Model {
|
||||||
|
throw new Error("The repository's model is not defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all entries with specified relations.
|
||||||
|
* @param withRelations
|
||||||
|
*/
|
||||||
|
all(withRelations?, trx?) {
|
||||||
|
const builder = this.model.query(trx);
|
||||||
|
applyGraphFetched(withRelations, builder);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds list of entities with specified attributes
|
||||||
|
*
|
||||||
|
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
|
||||||
|
* @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
*/
|
||||||
|
find(attributeValues = {}, withRelations?) {
|
||||||
|
const builder = this.model.query().where(attributeValues);
|
||||||
|
|
||||||
|
applyGraphFetched(withRelations, builder);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds list of entities with attribute values that are different from specified ones
|
||||||
|
*
|
||||||
|
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
*/
|
||||||
|
findWhereNot(attributeValues = {}, withRelations?) {
|
||||||
|
const builder = this.model.query().whereNot(attributeValues);
|
||||||
|
|
||||||
|
applyGraphFetched(withRelations, builder);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds list of entities with specified attributes (any of multiple specified values)
|
||||||
|
* Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
|
||||||
|
*
|
||||||
|
* @param {string|Object} searchParam - attribute name or search criteria object
|
||||||
|
* @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
|
||||||
|
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
*/
|
||||||
|
findWhereIn(searchParam, attributeValues, withRelations?) {
|
||||||
|
const commonBuilder = (builder) => {
|
||||||
|
applyGraphFetched(withRelations, builder);
|
||||||
|
};
|
||||||
|
if (isString(searchParam)) {
|
||||||
|
return this.model
|
||||||
|
.query()
|
||||||
|
.whereIn(searchParam, attributeValues)
|
||||||
|
.onBuild(commonBuilder);
|
||||||
|
} else {
|
||||||
|
const builder = this.model.query(this.knex).onBuild(commonBuilder);
|
||||||
|
|
||||||
|
forOwn(searchParam, (value, key) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
builder.whereIn(key, value);
|
||||||
|
} else {
|
||||||
|
builder.where(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds first entity by given parameters
|
||||||
|
*
|
||||||
|
* @param {Object} attributeValues - values to filter retrieved entities by
|
||||||
|
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
* @returns {Promise<Object>}
|
||||||
|
*/
|
||||||
|
async findOne(attributeValues = {}, withRelations?) {
|
||||||
|
const results = await this.find(attributeValues, withRelations);
|
||||||
|
return results[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds first entity by given parameters
|
||||||
|
*
|
||||||
|
* @param {string || number} id - value of id column of the entity
|
||||||
|
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
|
||||||
|
* @returns {Promise<Object>}
|
||||||
|
*/
|
||||||
|
findOneById(id, withRelations?) {
|
||||||
|
return this.findOne({ [this.idColumn]: id }, withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists new entity or an array of entities.
|
||||||
|
* This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
|
||||||
|
* Batch insert only works on PostgreSQL
|
||||||
|
*
|
||||||
|
* @param {Object} entity - model instance or parameters for a new entity
|
||||||
|
* @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
|
||||||
|
*/
|
||||||
|
create(entity, trx?) {
|
||||||
|
// Keep the input parameter immutable
|
||||||
|
const instanceDTO = cloneDeep(entity);
|
||||||
|
|
||||||
|
return this.model.query(trx).insert(instanceDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
|
||||||
|
*
|
||||||
|
* @param {Object} entity - single entity instance
|
||||||
|
* @returns {Promise<integer>} number of affected rows
|
||||||
|
*/
|
||||||
|
async update(entity, whereAttributes?, trx?) {
|
||||||
|
const entityDto = cloneDeep(entity);
|
||||||
|
const identityClause = {};
|
||||||
|
|
||||||
|
if (Array.isArray(this.idColumn)) {
|
||||||
|
this.idColumn.forEach(
|
||||||
|
(idColumn) => (identityClause[idColumn] = entityDto[idColumn]),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
identityClause[this.idColumn] = entityDto[this.idColumn];
|
||||||
|
}
|
||||||
|
const whereConditions = whereAttributes || identityClause;
|
||||||
|
const modifiedEntitiesCount = await this.model
|
||||||
|
.query(trx)
|
||||||
|
.where(whereConditions)
|
||||||
|
.update(entityDto);
|
||||||
|
|
||||||
|
if (modifiedEntitiesCount === 0) {
|
||||||
|
throw new ModelEntityNotFound(entityDto[this.idColumn]);
|
||||||
|
}
|
||||||
|
return modifiedEntitiesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} attributeValues - values to filter deleted entities by
|
||||||
|
* @param {Object} [trx]
|
||||||
|
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||||
|
*/
|
||||||
|
deleteBy(attributeValues, trx?) {
|
||||||
|
return this.model.query(trx).delete().where(attributeValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string || number} id - value of id column of the entity
|
||||||
|
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
|
||||||
|
*/
|
||||||
|
deleteById(id: number | string, trx?) {
|
||||||
|
return this.deleteBy(
|
||||||
|
{
|
||||||
|
[this.idColumn]: id,
|
||||||
|
},
|
||||||
|
trx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given entries in the array on the specific field.
|
||||||
|
* @param {string} field -
|
||||||
|
* @param {number|string} values -
|
||||||
|
*/
|
||||||
|
deleteWhereIn(field: string, values: (string | number)[], trx) {
|
||||||
|
return this.model.query(trx).whereIn(field, values).delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string|number[]} values
|
||||||
|
*/
|
||||||
|
deleteWhereIdIn(values: (string | number)[], trx?) {
|
||||||
|
return this.deleteWhereIn(this.idColumn, values, trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary relation graphs can be upserted (insert + update + delete)
|
||||||
|
* using the upsertGraph method.
|
||||||
|
* @param graph
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
upsertGraph(graph, options) {
|
||||||
|
// Keep the input grpah immutable
|
||||||
|
const graphCloned = cloneDeep(graph);
|
||||||
|
return this.model.query().upsertGraph(graphCloned, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} whereAttributes
|
||||||
|
* @param {string} field
|
||||||
|
* @param amount
|
||||||
|
*/
|
||||||
|
changeNumber(whereAttributes, field: string, amount: number, trx) {
|
||||||
|
const changeMethod = amount > 0 ? 'increment' : 'decrement';
|
||||||
|
|
||||||
|
return this.model
|
||||||
|
.query(trx)
|
||||||
|
.where(whereAttributes)
|
||||||
|
[changeMethod](field, Math.abs(amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// import { CachableRepository } from './CachableRepository';
|
||||||
|
import { EntityRepository } from './EntityRepository';
|
||||||
|
|
||||||
|
export class TenantRepository extends EntityRepository {
|
||||||
|
|
||||||
|
}
|
||||||
2
packages/server-nest/src/common/types/Constructor.ts
Normal file
2
packages/server-nest/src/common/types/Constructor.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export type Constructor = new (...args: any[]) => {};
|
||||||
|
export type GConstructor<T> = new (...args: any[]) => T;
|
||||||
3
packages/server-nest/src/common/types/Date.ts
Normal file
3
packages/server-nest/src/common/types/Date.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
|
export type DateInput = moment.MomentInput;
|
||||||
4
packages/server-nest/src/common/types/Discount.ts
Normal file
4
packages/server-nest/src/common/types/Discount.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum DiscountType {
|
||||||
|
Percentage = 'percentage',
|
||||||
|
Amount = 'amount',
|
||||||
|
}
|
||||||
16
packages/server-nest/src/common/types/Features.ts
Normal file
16
packages/server-nest/src/common/types/Features.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export enum Features {
|
||||||
|
WAREHOUSES = 'warehouses',
|
||||||
|
BRANCHES = 'branches',
|
||||||
|
BankSyncing = 'BankSyncing',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFeatureAllItem {
|
||||||
|
name: string;
|
||||||
|
isAccessible: boolean;
|
||||||
|
defaultAccessible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFeatureConfiugration {
|
||||||
|
name: string;
|
||||||
|
defaultValue?: boolean;
|
||||||
|
}
|
||||||
8
packages/server-nest/src/constants/accept-type.ts
Normal file
8
packages/server-nest/src/constants/accept-type.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const AcceptType = {
|
||||||
|
ApplicationPdf: 'application/pdf',
|
||||||
|
ApplicationJson: 'application/json',
|
||||||
|
ApplicationJsonTable: 'application/json+table',
|
||||||
|
ApplicationXlsx: 'application/xlsx',
|
||||||
|
ApplicationCsv: 'application/csv',
|
||||||
|
ApplicationTextHtml: 'application/json+html',
|
||||||
|
};
|
||||||
230
packages/server-nest/src/constants/accounts.ts
Normal file
230
packages/server-nest/src/constants/accounts.ts
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
export const ACCOUNT_TYPE = {
|
||||||
|
CASH: 'cash',
|
||||||
|
BANK: 'bank',
|
||||||
|
ACCOUNTS_RECEIVABLE: 'accounts-receivable',
|
||||||
|
INVENTORY: 'inventory',
|
||||||
|
OTHER_CURRENT_ASSET: 'other-current-asset',
|
||||||
|
FIXED_ASSET: 'fixed-asset',
|
||||||
|
NON_CURRENT_ASSET: 'none-current-asset',
|
||||||
|
|
||||||
|
ACCOUNTS_PAYABLE: 'accounts-payable',
|
||||||
|
CREDIT_CARD: 'credit-card',
|
||||||
|
TAX_PAYABLE: 'tax-payable',
|
||||||
|
OTHER_CURRENT_LIABILITY: 'other-current-liability',
|
||||||
|
LOGN_TERM_LIABILITY: 'long-term-liability',
|
||||||
|
NON_CURRENT_LIABILITY: 'non-current-liability',
|
||||||
|
|
||||||
|
EQUITY: 'equity',
|
||||||
|
INCOME: 'income',
|
||||||
|
OTHER_INCOME: 'other-income',
|
||||||
|
COST_OF_GOODS_SOLD: 'cost-of-goods-sold',
|
||||||
|
EXPENSE: 'expense',
|
||||||
|
OTHER_EXPENSE: 'other-expense',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ACCOUNT_PARENT_TYPE = {
|
||||||
|
CURRENT_ASSET: 'current-asset',
|
||||||
|
FIXED_ASSET: 'fixed-asset',
|
||||||
|
NON_CURRENT_ASSET: 'non-current-asset',
|
||||||
|
|
||||||
|
CURRENT_LIABILITY: 'current-liability',
|
||||||
|
LOGN_TERM_LIABILITY: 'long-term-liability',
|
||||||
|
NON_CURRENT_LIABILITY: 'non-current-liability',
|
||||||
|
|
||||||
|
EQUITY: 'equity',
|
||||||
|
EXPENSE: 'expense',
|
||||||
|
INCOME: 'income',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ACCOUNT_ROOT_TYPE = {
|
||||||
|
ASSET: 'asset',
|
||||||
|
LIABILITY: 'liability',
|
||||||
|
EQUITY: 'equity',
|
||||||
|
EXPENSE: 'expense',
|
||||||
|
INCOME: 'income',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ACCOUNT_NORMAL = {
|
||||||
|
CREDIT: 'credit',
|
||||||
|
DEBIT: 'debit',
|
||||||
|
};
|
||||||
|
export const ACCOUNT_TYPES = [
|
||||||
|
{
|
||||||
|
label: 'Cash',
|
||||||
|
key: ACCOUNT_TYPE.CASH,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
multiCurrency: true,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Bank',
|
||||||
|
key: ACCOUNT_TYPE.BANK,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
multiCurrency: true,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Accounts Receivable',
|
||||||
|
key: ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Inventory',
|
||||||
|
key: ACCOUNT_TYPE.INVENTORY,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Other Current Asset',
|
||||||
|
key: ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Fixed Asset',
|
||||||
|
key: ACCOUNT_TYPE.FIXED_ASSET,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.FIXED_ASSET,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Non-Current Asset',
|
||||||
|
key: ACCOUNT_TYPE.NON_CURRENT_ASSET,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.ASSET,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.FIXED_ASSET,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Accounts Payable',
|
||||||
|
key: ACCOUNT_TYPE.ACCOUNTS_PAYABLE,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Credit Card',
|
||||||
|
key: ACCOUNT_TYPE.CREDIT_CARD,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
|
||||||
|
multiCurrency: true,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Tax Payable',
|
||||||
|
key: ACCOUNT_TYPE.TAX_PAYABLE,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Other Current Liability',
|
||||||
|
key: ACCOUNT_TYPE.OTHER_CURRENT_LIABILITY,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Long Term Liability',
|
||||||
|
key: ACCOUNT_TYPE.LOGN_TERM_LIABILITY,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.LOGN_TERM_LIABILITY,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Non-Current Liability',
|
||||||
|
key: ACCOUNT_TYPE.NON_CURRENT_LIABILITY,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.NON_CURRENT_LIABILITY,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Equity',
|
||||||
|
key: ACCOUNT_TYPE.EQUITY,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.EQUITY,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.EQUITY,
|
||||||
|
balanceSheet: true,
|
||||||
|
incomeSheet: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Income',
|
||||||
|
key: ACCOUNT_TYPE.INCOME,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.INCOME,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.INCOME,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Other Income',
|
||||||
|
key: ACCOUNT_TYPE.OTHER_INCOME,
|
||||||
|
normal: ACCOUNT_NORMAL.CREDIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.INCOME,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.INCOME,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cost of Goods Sold',
|
||||||
|
key: ACCOUNT_TYPE.COST_OF_GOODS_SOLD,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Expense',
|
||||||
|
key: ACCOUNT_TYPE.EXPENSE,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Other Expense',
|
||||||
|
key: ACCOUNT_TYPE.OTHER_EXPENSE,
|
||||||
|
normal: ACCOUNT_NORMAL.DEBIT,
|
||||||
|
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
|
||||||
|
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
|
||||||
|
balanceSheet: false,
|
||||||
|
incomeSheet: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getAccountsSupportsMultiCurrency = () => {
|
||||||
|
return ACCOUNT_TYPES.filter((account) => account.multiCurrency);
|
||||||
|
};
|
||||||
7
packages/server-nest/src/constants/data-types.ts
Normal file
7
packages/server-nest/src/constants/data-types.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const DATATYPES_LENGTH = {
|
||||||
|
STRING: 255,
|
||||||
|
TEXT: 65535,
|
||||||
|
INT_10: 4294967295,
|
||||||
|
DECIMAL_13_3: 9999999999.999,
|
||||||
|
DECIMAL_15_5: 999999999999.999,
|
||||||
|
};
|
||||||
241
packages/server-nest/src/constants/metable-options.ts
Normal file
241
packages/server-nest/src/constants/metable-options.ts
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
// import { getTransactionsLockingSettingsSchema } from '@/api/controllers/TransactionsLocking/utils';
|
||||||
|
|
||||||
|
export const SettingsOptions = {
|
||||||
|
organization: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
base_currency: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
industry: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
fiscal_year: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
financial_date_start: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
time_zone: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
date_format: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
accounting_basis: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
manual_journals: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bill_payments: {
|
||||||
|
withdrawal_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_estimates: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_receipts: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
preferred_deposit_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
receipt_message: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_invoices: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payment_receives: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
preferred_deposit_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_advance_deposit: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
preferred_sell_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_cost_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_inventory_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expenses: {
|
||||||
|
preferred_payment_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
cost_compute_running: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accounts: {
|
||||||
|
account_code_required: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
account_code_unique: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cashflow: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
credit_note: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
vendor_credit: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warehouse_transfers: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'sms-notification': {
|
||||||
|
'sms-notification-enable.sale-invoice-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-invoice-reminder': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-estimate-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-receipt-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.payment-receive-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.customer-balance': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'transactions-locking': {
|
||||||
|
'locking-type': {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
// ...getTransactionsLockingSettingsSchema([
|
||||||
|
// 'all',
|
||||||
|
// 'sales',
|
||||||
|
// 'purchases',
|
||||||
|
// 'financial',
|
||||||
|
// ]),
|
||||||
|
},
|
||||||
|
features: {
|
||||||
|
'multi-warehouses': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'multi-branches': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('accounts', (table) => {
|
||||||
|
table.increments('id').comment('Auto-generated id');
|
||||||
|
table.string('name').index();
|
||||||
|
table.string('slug');
|
||||||
|
table.string('account_type').index();
|
||||||
|
table.integer('parent_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.string('code', 10).index();
|
||||||
|
table.text('description');
|
||||||
|
table.boolean('active').defaultTo(true).index();
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table.boolean('predefined').defaultTo(false).index();
|
||||||
|
table.decimal('amount', 15, 5);
|
||||||
|
table.string('currency_code', 3).index();
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `ACCOUNTS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('accounts');
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('items_categories', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('name').index();
|
||||||
|
|
||||||
|
table.text('description');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
|
||||||
|
table.integer('cost_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.integer('sell_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
|
||||||
|
table.string('cost_method');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('items_categories');
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('items', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('name').index();
|
||||||
|
table.string('type').index();
|
||||||
|
table.string('code');
|
||||||
|
table.boolean('sellable').index();
|
||||||
|
table.boolean('purchasable').index();
|
||||||
|
table.decimal('sell_price', 13, 3).unsigned();
|
||||||
|
table.decimal('cost_price', 13, 3).unsigned();
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.string('picture_uri');
|
||||||
|
table.integer('cost_account_id').nullable().unsigned().references('id').inTable('accounts');
|
||||||
|
table.integer('sell_account_id').nullable().unsigned().references('id').inTable('accounts');
|
||||||
|
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.text('sell_description').nullable();
|
||||||
|
table.text('purchase_description').nullable();
|
||||||
|
table.integer('quantity_on_hand');
|
||||||
|
table.boolean('landed_cost').nullable();
|
||||||
|
|
||||||
|
table.text('note').nullable();
|
||||||
|
table.boolean('active');
|
||||||
|
table.integer('category_id').unsigned().index().references('id').inTable('items_categories');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `ITEMS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('items');
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('views', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('name').index();
|
||||||
|
table.string('slug').index();
|
||||||
|
table.boolean('predefined');
|
||||||
|
table.string('resource_model').index();
|
||||||
|
table.boolean('favourite');
|
||||||
|
table.string('roles_logic_expression');
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `VIEWS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('views');
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('settings', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.string('group').index();
|
||||||
|
table.string('type');
|
||||||
|
table.string('key').index();
|
||||||
|
table.string('value');
|
||||||
|
}).raw('ALTER TABLE `SETTINGS` AUTO_INCREMENT = 2000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('settings');
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('view_has_columns', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('view_id').unsigned().index().references('id').inTable('views');
|
||||||
|
table.string('field_key');
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
}).raw('ALTER TABLE `ITEMS_CATEGORIES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('view_has_columns');
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('view_roles', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('index');
|
||||||
|
table.string('field_key').index();
|
||||||
|
table.string('comparator');
|
||||||
|
table.string('value');
|
||||||
|
table
|
||||||
|
.integer('view_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('views');
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `VIEW_ROLES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => knex.schema.dropTableIfExists('view_roles');
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('contacts', table => {
|
||||||
|
table.increments();
|
||||||
|
|
||||||
|
table.string('contact_service');
|
||||||
|
table.string('contact_type');
|
||||||
|
|
||||||
|
table.decimal('balance', 13, 3).defaultTo(0);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
|
||||||
|
table.decimal('opening_balance', 13, 3).defaultTo(0);
|
||||||
|
table.date('opening_balance_at');
|
||||||
|
|
||||||
|
table.string('salutation').nullable();
|
||||||
|
table.string('first_name').nullable();
|
||||||
|
table.string('last_name').nullable();
|
||||||
|
table.string('company_name').nullable();
|
||||||
|
|
||||||
|
table.string('display_name');
|
||||||
|
|
||||||
|
table.string('email').nullable();
|
||||||
|
table.string('work_phone').nullable();
|
||||||
|
table.string('personal_phone').nullable();
|
||||||
|
table.string('website').nullable();
|
||||||
|
|
||||||
|
table.string('billing_address_1').nullable();
|
||||||
|
table.string('billing_address_2').nullable();
|
||||||
|
table.string('billing_address_city').nullable();
|
||||||
|
table.string('billing_address_country').nullable();
|
||||||
|
table.string('billing_address_email').nullable();
|
||||||
|
table.string('billing_address_postcode').nullable();
|
||||||
|
table.string('billing_address_phone').nullable();
|
||||||
|
table.string('billing_address_state').nullable(),
|
||||||
|
|
||||||
|
table.string('shipping_address_1').nullable();
|
||||||
|
table.string('shipping_address_2').nullable();
|
||||||
|
table.string('shipping_address_city').nullable();
|
||||||
|
table.string('shipping_address_country').nullable();
|
||||||
|
table.string('shipping_address_email').nullable();
|
||||||
|
table.string('shipping_address_postcode').nullable();
|
||||||
|
table.string('shipping_address_phone').nullable();
|
||||||
|
table.string('shipping_address_state').nullable();
|
||||||
|
|
||||||
|
table.text('note');
|
||||||
|
table.boolean('active').defaultTo(true);
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('contacts');
|
||||||
|
};
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('accounts_transactions', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('credit', 13, 3);
|
||||||
|
table.decimal('debit', 13, 3);
|
||||||
|
table.string('transaction_type').index();
|
||||||
|
table.string('reference_type').index();
|
||||||
|
table.integer('reference_id').index();
|
||||||
|
table
|
||||||
|
.integer('account_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.string('contact_type').nullable().index();
|
||||||
|
table.integer('contact_id').unsigned().nullable().index();
|
||||||
|
table.string('transaction_number').nullable().index();
|
||||||
|
table.string('reference_number').nullable().index();
|
||||||
|
table.integer('item_id').unsigned().nullable().index();
|
||||||
|
table.integer('item_quantity').unsigned().nullable().index(),
|
||||||
|
table.string('note');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
|
||||||
|
table.integer('index_group').unsigned().index();
|
||||||
|
table.integer('index').unsigned().index();
|
||||||
|
|
||||||
|
table.date('date').index();
|
||||||
|
table.datetime('created_at').index();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `ACCOUNTS_TRANSACTIONS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('accounts_transactions');
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('expenses_transactions', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.text('description');
|
||||||
|
table
|
||||||
|
.integer('payment_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.integer('payee_id').unsigned().references('id').inTable('contacts');
|
||||||
|
table.string('reference_no');
|
||||||
|
|
||||||
|
table.decimal('total_amount', 13, 3);
|
||||||
|
table.decimal('landed_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
|
||||||
|
table.date('published_at').index();
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.date('payment_date').index();
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `EXPENSES_TRANSACTIONS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('expenses');
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('manual_journals', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('journal_number').index();
|
||||||
|
table.string('reference').index();
|
||||||
|
table.string('journal_type').index();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.date('date').index();
|
||||||
|
table.string('description');
|
||||||
|
table.date('published_at').index();
|
||||||
|
table.string('attachment_file');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `MANUAL_JOURNALS` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('manual_journals');
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('manual_journals_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('credit', 13, 3);
|
||||||
|
table.decimal('debit', 13, 3);
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table.integer('account_id').unsigned().index().references('id').inTable('accounts');
|
||||||
|
table.integer('contact_id').unsigned().nullable().index();
|
||||||
|
table.string('note');
|
||||||
|
table.integer('manual_journal_id').unsigned().index().references('id').inTable('manual_journals');
|
||||||
|
}).raw('ALTER TABLE `MANUAL_JOURNALS_ENTRIES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('manual_journals_entries');
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('currencies', table => {
|
||||||
|
table.increments();
|
||||||
|
table.string('currency_name').index();
|
||||||
|
table.string('currency_code', 4).index();
|
||||||
|
table.string('currency_sign').index();
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `CURRENCIES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('currencies');
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('exchange_rates', table => {
|
||||||
|
table.increments();
|
||||||
|
table.string('currency_code', 4).index();
|
||||||
|
table.decimal('exchange_rate');
|
||||||
|
table.date('date').index();
|
||||||
|
table.timestamps();
|
||||||
|
}).raw('ALTER TABLE `EXCHANGE_RATES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('exchange_rates');
|
||||||
|
};
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('media', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('attachment_file');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('media');
|
||||||
|
};
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('media_links', table => {
|
||||||
|
table.increments();
|
||||||
|
table.string('model_name').index();
|
||||||
|
table.integer('media_id').unsigned().references('id').inTable('media');
|
||||||
|
table.integer('model_id').unsigned().index();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('media_links');
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('expense_transaction_categories', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('expense_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table.text('description');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
table.boolean('landed_cost').defaultTo(false);
|
||||||
|
table
|
||||||
|
.integer('expense_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('expenses_transactions');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.raw('ALTER TABLE `EXPENSE_TRANSACTION_CATEGORIES` AUTO_INCREMENT = 1000');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('expense_transaction_categories');
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('sales_estimates', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table
|
||||||
|
.integer('customer_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
|
table.date('estimate_date').index();
|
||||||
|
table.date('expiration_date').index();
|
||||||
|
table.string('reference');
|
||||||
|
table.string('estimate_number').index();
|
||||||
|
table.text('note');
|
||||||
|
table.text('terms_conditions');
|
||||||
|
table.text('send_to_email');
|
||||||
|
|
||||||
|
table.date('delivered_at').index();
|
||||||
|
table.date('approved_at').index();
|
||||||
|
table.date('rejected_at').index();
|
||||||
|
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
|
||||||
|
table.integer('converted_to_invoice_id').unsigned();
|
||||||
|
table.date('converted_to_invoice_at');
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('sales_estimates');
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('sales_receipts', table => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.integer('deposit_account_id').unsigned().index().references('id').inTable('accounts');
|
||||||
|
table.integer('customer_id').unsigned().index().references('id').inTable('contacts');
|
||||||
|
table.date('receipt_date').index();
|
||||||
|
table.string('receipt_number').index();
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table.string('send_to_email');
|
||||||
|
table.text('receipt_message');
|
||||||
|
table.text('statement');
|
||||||
|
table.date('closed_at').index();
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('sales_receipts');
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('sales_invoices', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('customer_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
|
|
||||||
|
table.date('invoice_date').index();
|
||||||
|
table.date('due_date');
|
||||||
|
table.string('invoice_no').index();
|
||||||
|
table.string('reference_no');
|
||||||
|
|
||||||
|
table.text('invoice_message');
|
||||||
|
table.text('terms_conditions');
|
||||||
|
|
||||||
|
table.decimal('balance', 13, 3);
|
||||||
|
table.decimal('payment_amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.decimal('credited_amount', 13, 3).defaultTo(0);
|
||||||
|
|
||||||
|
table.string('inv_lot_number').index();
|
||||||
|
|
||||||
|
table.date('delivered_at').index();
|
||||||
|
table.integer('user_id').unsigned();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('sales_invoices');
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
const { knexSnakeCaseMappers } = require('objection');
|
||||||
|
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('payment_receives', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('customer_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
|
table.date('payment_date').index();
|
||||||
|
table.decimal('amount', 13, 3).defaultTo(0);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table
|
||||||
|
.integer('deposit_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.string('payment_receive_no').nullable();
|
||||||
|
table.text('statement');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('payment_receives');
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('payment_receives_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('payment_receive_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('payment_receives');
|
||||||
|
table
|
||||||
|
.integer('invoice_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('sales_invoices');
|
||||||
|
table.decimal('payment_amount', 13, 3).unsigned();
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('payment_receives_entries');
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('bills', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('vendor_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
|
table.string('bill_number');
|
||||||
|
table.date('bill_date').index();
|
||||||
|
table.date('due_date').index();
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table.string('status').index();
|
||||||
|
table.text('note');
|
||||||
|
table.decimal('amount', 13, 3).defaultTo(0);
|
||||||
|
table.string('currency_code');
|
||||||
|
table.decimal('payment_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('landed_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('credited_amount', 13, 3).defaultTo(0);
|
||||||
|
table.string('inv_lot_number').index();
|
||||||
|
table.date('opened_at').index();
|
||||||
|
table.integer('user_id').unsigned();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('bills');
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('bills_payments', table => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('vendor_id').unsigned().index().references('id').inTable('contacts');
|
||||||
|
table.decimal('amount', 13, 3).defaultTo(0);
|
||||||
|
table.string('currency_code');
|
||||||
|
table.integer('payment_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.string('payment_number').nullable().index();
|
||||||
|
table.date('payment_date').index();
|
||||||
|
table.string('payment_method');
|
||||||
|
table.string('reference');
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.text('statement');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('inventory_transactions', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.date('date').index();
|
||||||
|
table.string('direction').index();
|
||||||
|
table
|
||||||
|
.integer('item_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('items');
|
||||||
|
table.integer('quantity').unsigned();
|
||||||
|
table.decimal('rate', 13, 3).unsigned();
|
||||||
|
|
||||||
|
table.string('transaction_type').index();
|
||||||
|
table.integer('transaction_id').unsigned().index();
|
||||||
|
|
||||||
|
table.integer('entry_id').unsigned().index();
|
||||||
|
table.integer('cost_account_id').unsigned();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('bill_located_costs', (table) => {
|
||||||
|
table.increments();
|
||||||
|
|
||||||
|
table.decimal('amount', 13, 3).unsigned();
|
||||||
|
|
||||||
|
table.integer('fromTransactionId').unsigned();
|
||||||
|
table.string('fromTransactionType');
|
||||||
|
table.integer('fromTransactionEntryId').unsigned();
|
||||||
|
|
||||||
|
table.string('allocationMethod');
|
||||||
|
table.integer('costAccountId').unsigned();
|
||||||
|
table.text('description');
|
||||||
|
|
||||||
|
table.integer('billId').unsigned();
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('bill_located_cost_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
|
||||||
|
table.decimal('cost', 13, 3).unsigned();
|
||||||
|
table.integer('entry_id').unsigned();
|
||||||
|
table.integer('bill_located_cost_id').unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('inventory_transaction_meta', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.string('transaction_number');
|
||||||
|
table.text('description');
|
||||||
|
table.integer('inventory_transaction_id').unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('items_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('reference_type').index();
|
||||||
|
table.string('reference_id').index();
|
||||||
|
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table
|
||||||
|
.integer('item_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('items');
|
||||||
|
table.text('description');
|
||||||
|
table.integer('discount').unsigned();
|
||||||
|
table.integer('quantity').unsigned();
|
||||||
|
table.integer('rate').unsigned();
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('sell_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('cost_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
|
||||||
|
table.boolean('landed_cost').defaultTo(false);
|
||||||
|
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('items_entries');
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('bills_payments_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('bill_payment_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('bills_payments');
|
||||||
|
table
|
||||||
|
.integer('bill_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('bills');
|
||||||
|
table.decimal('payment_amount', 13, 3).unsigned();
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('bills_payments_entries');
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('inventory_cost_lot_tracker', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date').index();
|
||||||
|
table.string('direction').index();
|
||||||
|
|
||||||
|
table.integer('item_id').unsigned().index();
|
||||||
|
table.integer('quantity').unsigned().index();
|
||||||
|
table.decimal('rate', 13, 3);
|
||||||
|
table.integer('remaining');
|
||||||
|
table.decimal('cost', 13, 3);
|
||||||
|
|
||||||
|
table.string('transaction_type').index();
|
||||||
|
table.integer('transaction_id').unsigned().index();
|
||||||
|
|
||||||
|
table.integer('entry_id').unsigned().index();
|
||||||
|
table.integer('cost_account_id').unsigned();
|
||||||
|
table.integer('inventory_transaction_id').unsigned().index();
|
||||||
|
|
||||||
|
table.datetime('created_at').index();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('inventory_cost_lot_tracker');
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
exports.up = function(knex) {
|
||||||
|
return knex.schema.createTable('inventory_adjustments', table => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date').index();
|
||||||
|
table.string('type').index();
|
||||||
|
table.integer('adjustment_account_id').unsigned().references('id').inTable('accounts');
|
||||||
|
table.string('reason');
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table.string('description');
|
||||||
|
table.integer('user_id').unsigned();
|
||||||
|
table.date('published_at');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function(knex) {
|
||||||
|
return knex.schema.dropTableIfExists('inventory_adjustments');
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('inventory_adjustments_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('adjustment_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('inventory_adjustments');
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table
|
||||||
|
.integer('item_id')
|
||||||
|
.unsigned()
|
||||||
|
.index()
|
||||||
|
.references('id')
|
||||||
|
.inTable('items');
|
||||||
|
table.integer('quantity');
|
||||||
|
table.decimal('cost', 13, 3).unsigned();
|
||||||
|
table.decimal('value', 13, 3).unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('inventory_adjustments_entries');
|
||||||
|
};
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('cashflow_transactions', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date').index();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table.string('transaction_type').index();
|
||||||
|
table.string('transaction_number').index();
|
||||||
|
table.string('description');
|
||||||
|
table.date('published_at').index();
|
||||||
|
table.integer('user_id').unsigned().index();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('cashflow_transactions');
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('cashflow_transaction_lines', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('cashflow_transaction_id').unsigned();
|
||||||
|
table
|
||||||
|
.integer('cashflow_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('credit_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.integer('index').unsigned();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('cashflow_transaction_lines');
|
||||||
|
};
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('sales_invoices', (table) => {
|
||||||
|
table.decimal('writtenoff_amount', 13, 3);
|
||||||
|
table.date('writtenoff_at').index();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('sales_invoices', (table) => {
|
||||||
|
table.dropColumn('writtenoff_amount');
|
||||||
|
table.dropColumn('writtenoff_at');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('accounts_transactions', (table) => {
|
||||||
|
table.boolean('costable');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('accounts_transactions', (table) => {
|
||||||
|
table.dropColumn('costable');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('roles', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.string('name', 255).notNullable();
|
||||||
|
table.string('slug');
|
||||||
|
table.text('description');
|
||||||
|
table.boolean('predefined');
|
||||||
|
})
|
||||||
|
.createTable('role_permissions', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.integer('role_id').unsigned().references('id').inTable('roles');
|
||||||
|
table.string('subject');
|
||||||
|
table.string('ability');
|
||||||
|
table.boolean('value');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTable('roles').dropTable('role_permissions');
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('users', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('first_name');
|
||||||
|
table.string('last_name');
|
||||||
|
table.string('email').index();
|
||||||
|
table.string('phone_number').index();
|
||||||
|
table.boolean('active').index();
|
||||||
|
table.integer('role_id').unsigned().references('id').inTable('roles');
|
||||||
|
table.integer('system_user_id').unsigned();
|
||||||
|
table.dateTime('invited_at').index();
|
||||||
|
table.dateTime('invite_accepted_at').index();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('users');
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('credit_notes', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table
|
||||||
|
.integer('customer_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('contacts');
|
||||||
|
table.date('credit_note_date');
|
||||||
|
table.string('credit_note_number');
|
||||||
|
table.string('reference_no');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
|
||||||
|
table.decimal('refunded_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('invoices_amount', 13, 3).defaultTo(0);
|
||||||
|
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.text('note');
|
||||||
|
table.text('terms_conditions');
|
||||||
|
table.date('opened_at').index();
|
||||||
|
table.integer('user_id').unsigned().references('id').inTable('users');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('credit_notescredit_notes');
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('vendor_credits', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('vendor_id').unsigned().references('id').inTable('contacts');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.date('vendor_credit_date');
|
||||||
|
table.string('vendor_credit_number');
|
||||||
|
table.string('reference_no');
|
||||||
|
|
||||||
|
table.decimal('refunded_amount', 13, 3).defaultTo(0);
|
||||||
|
table.decimal('invoiced_amount', 13, 3).defaultTo(0);
|
||||||
|
|
||||||
|
table.text('note');
|
||||||
|
table.date('opened_at').index();
|
||||||
|
table.integer('user_id').unsigned().references('id').inTable('users');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('vendor_credits');
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('refund_credit_note_transactions', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date');
|
||||||
|
table
|
||||||
|
.integer('credit_note_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('credit_notes');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.string('reference_no');
|
||||||
|
table
|
||||||
|
.integer('from_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.text('description');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('refund_vendor_credit_transactions', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date');
|
||||||
|
table
|
||||||
|
.integer('vendor_credit_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('vendor_credits');
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table.string('currency_code', 3);
|
||||||
|
table.string('reference_no');
|
||||||
|
table
|
||||||
|
.integer('deposit_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.text('description');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('refund_transactions');
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('credit_note_applied_invoice', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table
|
||||||
|
.integer('credit_note_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('credit_notes');
|
||||||
|
table
|
||||||
|
.integer('invoice_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('sales_invoices');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('vendor_credit_applied_bill', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.decimal('amount', 13, 3);
|
||||||
|
table
|
||||||
|
.integer('vendor_credit_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('vendor_credits');
|
||||||
|
table.integer('bill_id').unsigned().references('id').inTable('bills');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.dropTableIfExists('vendor_credit_applied_bill')
|
||||||
|
.dropTableIfExists('credit_note_applied_invoice');
|
||||||
|
};
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('branches', (table) => {
|
||||||
|
table.increments();
|
||||||
|
|
||||||
|
table.string('name');
|
||||||
|
table.string('code');
|
||||||
|
|
||||||
|
table.string('address');
|
||||||
|
table.string('city');
|
||||||
|
table.string('country');
|
||||||
|
|
||||||
|
table.string('phone_number');
|
||||||
|
table.string('email');
|
||||||
|
table.string('website');
|
||||||
|
|
||||||
|
table.boolean('primary');
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('branches');
|
||||||
|
};
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('warehouses', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('name');
|
||||||
|
table.string('code');
|
||||||
|
|
||||||
|
table.string('address');
|
||||||
|
table.string('city');
|
||||||
|
table.string('country');
|
||||||
|
|
||||||
|
table.string('phone_number');
|
||||||
|
table.string('email');
|
||||||
|
table.string('website');
|
||||||
|
|
||||||
|
table.boolean('primary');
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('warehouses_transfers', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.date('date');
|
||||||
|
table
|
||||||
|
.integer('to_warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
table
|
||||||
|
.integer('from_warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
table.string('transaction_number');
|
||||||
|
|
||||||
|
table.date('transfer_initiated_at');
|
||||||
|
table.date('transfer_delivered_at');
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('warehouses_transfers_entries', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.integer('index');
|
||||||
|
table
|
||||||
|
.integer('warehouse_transfer_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses_transfers');
|
||||||
|
table.integer('item_id').unsigned().references('id').inTable('items');
|
||||||
|
table.string('description');
|
||||||
|
table.integer('quantity');
|
||||||
|
table.decimal('cost');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.dropTableIfExists('vendor_credit_applied_bill')
|
||||||
|
.dropTableIfExists('credit_note_applied_invoice');
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.createTable('items_warehouses_quantity', (table) => {
|
||||||
|
table.integer('item_id').unsigned().references('id').inTable('items');
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
|
||||||
|
table.integer('quantity_on_hand');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('items_warehouses_quantity');
|
||||||
|
};
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('manual_journals', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('manual_journals_entries', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('expenses_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches')
|
||||||
|
.after('user_id');
|
||||||
|
})
|
||||||
|
.table('cashflow_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches')
|
||||||
|
.after('user_id');
|
||||||
|
})
|
||||||
|
.table('contacts', (table) => {
|
||||||
|
table
|
||||||
|
.integer('opening_balance_branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches')
|
||||||
|
.after('opening_balance_at');
|
||||||
|
})
|
||||||
|
.table('refund_credit_note_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches')
|
||||||
|
.after('description');
|
||||||
|
})
|
||||||
|
.table('refund_vendor_credit_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches')
|
||||||
|
.after('description');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('manual_journals', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('manual_journals_entries', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('cashflow_transactions', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('refund_credit_note_transactions', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('refund_vendor_credit_transactions', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user