mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
Compare commits
56 Commits
migrate-se
...
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 |
@@ -1,3 +1,6 @@
|
|||||||
|
# App
|
||||||
|
APP_JWT_SECRET=123123
|
||||||
|
|
||||||
# Mail
|
# Mail
|
||||||
MAIL_HOST=
|
MAIL_HOST=
|
||||||
MAIL_USERNAME=
|
MAIL_USERNAME=
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ node_modules/
|
|||||||
.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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
"server2:start": "lerna run start:dev --scope \"@bigcapital/server2\"",
|
"server2:start": "lerna run start:dev --scope \"@bigcapital/server2\"",
|
||||||
"test:watch": "lerna run test:watch",
|
"test:watch": "lerna run test:watch",
|
||||||
"test:e2e": "lerna run test:e2e",
|
"test:e2e": "lerna run test:e2e",
|
||||||
|
"start:debug": "lerna run start:debug",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# App
|
||||||
|
APP_JWT_SECRET=123123
|
||||||
|
|
||||||
# Mail
|
# Mail
|
||||||
MAIL_HOST=
|
MAIL_HOST=
|
||||||
MAIL_USERNAME=
|
MAIL_USERNAME=
|
||||||
|
|||||||
@@ -20,47 +20,68 @@
|
|||||||
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
|
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-s3": "^3.576.0",
|
||||||
|
"@aws-sdk/s3-request-presigner": "^3.583.0",
|
||||||
"@bigcapital/email-components": "*",
|
"@bigcapital/email-components": "*",
|
||||||
"@bigcapital/pdf-templates": "*",
|
"@bigcapital/pdf-templates": "*",
|
||||||
"@bigcapital/utils": "*",
|
"@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/bull": "^10.2.1",
|
||||||
"@nestjs/bullmq": "^10.2.1",
|
"@nestjs/bullmq": "^10.2.2",
|
||||||
"@nestjs/cache-manager": "^2.2.2",
|
"@nestjs/cache-manager": "^2.2.2",
|
||||||
"@nestjs/common": "^10.0.0",
|
"@nestjs/common": "^10.0.0",
|
||||||
"@nestjs/config": "^3.2.3",
|
"@nestjs/config": "^3.2.3",
|
||||||
"@nestjs/core": "^10.0.0",
|
"@nestjs/core": "^10.0.0",
|
||||||
"@nestjs/event-emitter": "^2.0.4",
|
"@nestjs/event-emitter": "^2.0.4",
|
||||||
"@nestjs/jwt": "^10.2.0",
|
"@nestjs/jwt": "^10.2.0",
|
||||||
"@nestjs/passport": "^10.0.3",
|
"@nestjs/passport": "^11.0.5",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
"@nestjs/swagger": "^7.4.2",
|
"@nestjs/swagger": "^7.4.2",
|
||||||
"@nestjs/throttler": "^6.2.1",
|
"@nestjs/throttler": "^6.2.1",
|
||||||
"@supercharge/promise-pool": "^3.2.0",
|
"@supercharge/promise-pool": "^3.2.0",
|
||||||
|
"@types/nodemailer": "^6.4.17",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
"@types/ramda": "^0.30.2",
|
"@types/ramda": "^0.30.2",
|
||||||
"accounting": "^0.4.1",
|
"accounting": "^0.4.1",
|
||||||
"async": "^3.2.0",
|
"async": "^3.2.0",
|
||||||
|
"async-mutex": "^0.5.0",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"bull": "^4.16.3",
|
"bull": "^4.16.3",
|
||||||
"bullmq": "^5.21.1",
|
"bullmq": "^5.25.6",
|
||||||
"cache-manager": "^6.1.1",
|
"cache-manager": "^6.1.1",
|
||||||
"cache-manager-redis-store": "^3.0.1",
|
"cache-manager-redis-store": "^3.0.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
|
"deepdash": "^5.3.9",
|
||||||
"express-validator": "^7.2.0",
|
"express-validator": "^7.2.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"fp-ts": "^2.16.9",
|
"fp-ts": "^2.16.9",
|
||||||
"js-money": "^0.6.3",
|
"ioredis": "^5.6.0",
|
||||||
"is-my-json-valid": "^2.20.5",
|
"is-my-json-valid": "^2.20.5",
|
||||||
|
"js-money": "^0.6.3",
|
||||||
"knex": "^3.1.0",
|
"knex": "^3.1.0",
|
||||||
"lamda": "^0.4.1",
|
"lamda": "^0.4.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"mathjs": "^9.4.0",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
|
"moment-range": "^4.0.2",
|
||||||
|
"moment-timezone": "^0.5.43",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"mysql2": "^3.11.3",
|
"mysql2": "^3.11.3",
|
||||||
"nestjs-cls": "^4.4.1",
|
"multer": "1.4.5-lts.1",
|
||||||
|
"multer-s3": "^3.0.1",
|
||||||
|
"nestjs-cls": "^5.2.0",
|
||||||
"nestjs-i18n": "^10.4.9",
|
"nestjs-i18n": "^10.4.9",
|
||||||
|
"nestjs-redis": "^1.3.3",
|
||||||
|
"nodemailer": "^6.3.0",
|
||||||
"object-hash": "^2.0.3",
|
"object-hash": "^2.0.3",
|
||||||
"objection": "^3.1.5",
|
"objection": "^3.1.5",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
@@ -73,11 +94,14 @@
|
|||||||
"ramda": "^0.30.1",
|
"ramda": "^0.30.1",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
|
"remeda": "^2.19.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"serialize-interceptor": "^1.1.7",
|
"serialize-interceptor": "^1.1.7",
|
||||||
"strategy": "^1.1.1",
|
"strategy": "^1.1.1",
|
||||||
|
"stripe": "^16.10.0",
|
||||||
"uniqid": "^5.2.0",
|
"uniqid": "^5.2.0",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
"yup": "^0.28.1",
|
"yup": "^0.28.1",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
@@ -87,6 +111,7 @@
|
|||||||
"@nestjs/testing": "^10.0.0",
|
"@nestjs/testing": "^10.0.0",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/jest": "^29.5.2",
|
"@types/jest": "^29.5.2",
|
||||||
|
"@types/mathjs": "^6.0.12",
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.1",
|
||||||
"@types/supertest": "^6.0.0",
|
"@types/supertest": "^6.0.0",
|
||||||
"@types/yup": "^0.29.13",
|
"@types/yup": "^0.29.13",
|
||||||
@@ -96,6 +121,7 @@
|
|||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
|
"mustache": "^3.0.3",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "^7.0.0",
|
"supertest": "^7.0.0",
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ import lemonsqueezy from './lemonsqueezy';
|
|||||||
import s3 from './s3';
|
import s3 from './s3';
|
||||||
import openExchange from './open-exchange';
|
import openExchange from './open-exchange';
|
||||||
import posthog from './posthog';
|
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 = [
|
export const config = [
|
||||||
systemDatabase,
|
systemDatabase,
|
||||||
@@ -18,4 +24,10 @@ export const config = [
|
|||||||
s3,
|
s3,
|
||||||
openExchange,
|
openExchange,
|
||||||
posthog,
|
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',
|
||||||
|
}));
|
||||||
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,
|
||||||
|
},
|
||||||
|
}));
|
||||||
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,
|
||||||
|
}));
|
||||||
@@ -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),
|
||||||
|
}));
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import * as path from 'path';
|
||||||
import { registerAs } from '@nestjs/config';
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('tenantDatabase', () => ({
|
export default registerAs('tenantDatabase', () => ({
|
||||||
@@ -6,4 +7,7 @@ export default registerAs('tenantDatabase', () => ({
|
|||||||
port: process.env.TENANT_DB_PORT || process.env.DB_PORT || 5432,
|
port: process.env.TENANT_DB_PORT || process.env.DB_PORT || 5432,
|
||||||
user: process.env.TENANT_DB_USER || process.env.DB_USER,
|
user: process.env.TENANT_DB_USER || process.env.DB_USER,
|
||||||
password: process.env.TENANT_DB_PASSWORD || process.env.DB_PASSWORD,
|
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;
|
||||||
|
}
|
||||||
@@ -180,6 +180,7 @@ export const events = {
|
|||||||
* Sales estimates service.
|
* Sales estimates service.
|
||||||
*/
|
*/
|
||||||
saleEstimate: {
|
saleEstimate: {
|
||||||
|
onViewed: 'onSaleEstimateViewed',
|
||||||
onPdfViewed: 'onSaleEstimatePdfViewed',
|
onPdfViewed: 'onSaleEstimatePdfViewed',
|
||||||
|
|
||||||
onCreating: 'onSaleEstimateCreating',
|
onCreating: 'onSaleEstimateCreating',
|
||||||
@@ -212,9 +213,7 @@ export const events = {
|
|||||||
|
|
||||||
onPreMailSend: 'onSaleEstimatePreMailSend',
|
onPreMailSend: 'onSaleEstimatePreMailSend',
|
||||||
onMailSend: 'onSaleEstimateMailSend',
|
onMailSend: 'onSaleEstimateMailSend',
|
||||||
onMailSent: 'onSaleEstimateMailSend',
|
onMailSent: 'onSaleEstimateMailSent',
|
||||||
|
|
||||||
onViewed: 'onSaleEstimateViewed',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -753,4 +752,24 @@ export const events = {
|
|||||||
onCheckoutSessionCompleted: 'onStripeCheckoutSessionCompleted',
|
onCheckoutSessionCompleted: 'onStripeCheckoutSessionCompleted',
|
||||||
onAccountUpdated: 'onStripeAccountUpdated',
|
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,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,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);
|
||||||
|
}
|
||||||
|
}
|
||||||
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;
|
||||||
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',
|
||||||
|
};
|
||||||
@@ -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');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('bills', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('bills_payments', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('vendor_credits', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
})
|
||||||
|
.table('inventory_adjustments', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('bills', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('bills_payments', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('vendor_credits', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
})
|
||||||
|
.table('inventory_adjustments', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('sales_estimates', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('sales_receipts', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('payment_receives', (table) => {
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('credit_notes', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('sales_estimates', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('sales_receipts', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('payment_receives', (table) => {
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('credit_notes', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('inventory_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
})
|
||||||
|
.table('inventory_cost_lot_tracker', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('branch_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('branches');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('inventory_transactions', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
})
|
||||||
|
.table('inventory_cost_lot_tracker', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
table.dropColumn('branch_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('items_entries', (table) => {
|
||||||
|
table
|
||||||
|
.integer('warehouse_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('warehouses');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('items_entries', (table) => {
|
||||||
|
table.dropColumn('warehouse_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('sales_estimates', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9);
|
||||||
|
})
|
||||||
|
.table('sales_receipts', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('payment_receives', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('bills', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('bills_payments', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('credit_notes', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('vendor_credits', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table.string('currency_code', 3).after('debit');
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('manual_journals', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('cashflow_transactions', (table) => {
|
||||||
|
table.string('currency_code', 3).after('amount');
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('expenses_transactions', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('refund_credit_note_transactions', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('refund_vendor_credit_transactions', (table) => {
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('bill_located_costs', (table) => {
|
||||||
|
table.string('currency_code', 3).after('amount');
|
||||||
|
table.decimal('exchange_rate', 13, 9).after('currency_code');
|
||||||
|
})
|
||||||
|
.table('contacts', (table) => {
|
||||||
|
table
|
||||||
|
.decimal('opening_balance_exchange_rate', 13, 9)
|
||||||
|
.after('opening_balance_at');
|
||||||
|
})
|
||||||
|
.table('items', (table) => {
|
||||||
|
table.dropColumn('currency_code');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('sales_estimates', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('sales_receipts', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('payment_receives', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('bills', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('bills_payments', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('credit_notes', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('vendor_credits', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table.dropColumn('currency_code');
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('manual_journals', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('cashflow_transactions', (table) => {
|
||||||
|
table.dropColumn('currency_code');
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('expenses_transactions', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('refund_credit_note_transactions', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('refund_vendor_credit_transactions', (table) => {
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('bill_located_costs', (table) => {
|
||||||
|
table.dropColumn('currency_code');
|
||||||
|
table.dropColumn('exchange_rate');
|
||||||
|
})
|
||||||
|
.table('contacts', (table) => {
|
||||||
|
table.dropColumn('opening_balance_exchange_rate');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('sales_invoices', (table) => {
|
||||||
|
table
|
||||||
|
.integer('writtenoff_expense_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('sales_invoices', (table) => {
|
||||||
|
table.dropColumn('writtenoff_expense_account_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.raw(
|
||||||
|
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_1 SHIPPING_ADDRESS1 VARCHAR(255)'
|
||||||
|
)
|
||||||
|
.raw(
|
||||||
|
'ALTER TABLE CONTACTS CHANGE SHIPPING_ADDRESS_2 SHIPPING_ADDRESS2 VARCHAR(255)'
|
||||||
|
)
|
||||||
|
.raw(
|
||||||
|
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_1 BILLING_ADDRESS1 VARCHAR(255)'
|
||||||
|
)
|
||||||
|
.raw(
|
||||||
|
'ALTER TABLE CONTACTS CHANGE BILLING_ADDRESS_2 BILLING_ADDRESS2 VARCHAR(255)'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('contacts', (table) => {});
|
||||||
|
};
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('cashflow_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('cashflow_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table
|
||||||
|
.integer('credit_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('cashflow_transactions', () => {});
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('accounts', (table) => {
|
||||||
|
table.date('seeded_at').after('currency_code').nullable();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {};
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('projects', (table) => {
|
||||||
|
table.increments('id').comment('Auto-generated id');
|
||||||
|
table.string('name');
|
||||||
|
table.integer('contact_id').unsigned();
|
||||||
|
table.date('deadline');
|
||||||
|
table.decimal('cost_estimate');
|
||||||
|
table.string('status');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('tasks', (table) => {
|
||||||
|
table.increments('id').comment('Auto-generated id');
|
||||||
|
table.string('name');
|
||||||
|
table.string('charge_type');
|
||||||
|
table.decimal('rate');
|
||||||
|
table.decimal('estimate_hours').unsigned();
|
||||||
|
table.decimal('actual_hours').unsigned();
|
||||||
|
table.decimal('invoiced_hours').unsigned().default(0);
|
||||||
|
table
|
||||||
|
.integer('project_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('times', (table) => {
|
||||||
|
table.increments('id').comment('Auto-generated id');
|
||||||
|
table.integer('duration').unsigned();
|
||||||
|
table.string('description');
|
||||||
|
table.date('date');
|
||||||
|
|
||||||
|
table.integer('taskId').unsigned().references('id').inTable('tasks');
|
||||||
|
table
|
||||||
|
.integer('project_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
})
|
||||||
|
.table('manual_journals_entries', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
})
|
||||||
|
.table('bills', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
table.decimal('invoiced_amount').unsigned().defaultTo(0);
|
||||||
|
})
|
||||||
|
.table('items_entries', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
|
||||||
|
table.integer('project_ref_id').unsigned();
|
||||||
|
table.string('project_ref_type');
|
||||||
|
table.decimal('project_ref_invoiced_amount').unsigned().defaultTo(0);
|
||||||
|
})
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
})
|
||||||
|
.table('expenses_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('projectId')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('projects');
|
||||||
|
table.decimal('invoiced_amount').unsigned().defaultTo(0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTable('tasks');
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('expense_transaction_categories', (table) => {
|
||||||
|
table.integer('projectId').unsigned().references('id').inTable('projects');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('users', (table) => {
|
||||||
|
table.dropColumn('phone_number');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.table('users', (table) => {});
|
||||||
|
};
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('tax_rates', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.string('name');
|
||||||
|
table.string('code');
|
||||||
|
table.decimal('rate');
|
||||||
|
table.string('description');
|
||||||
|
table.boolean('is_non_recoverable').defaultTo(false);
|
||||||
|
table.boolean('is_compound').defaultTo(false);
|
||||||
|
table.boolean('active').defaultTo(false);
|
||||||
|
table.date('deleted_at');
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.table('items_entries', (table) => {
|
||||||
|
table.boolean('is_inclusive_tax').defaultTo(false);
|
||||||
|
table
|
||||||
|
.integer('tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
|
table.decimal('tax_rate').unsigned();
|
||||||
|
})
|
||||||
|
.table('sales_invoices', (table) => {
|
||||||
|
table.boolean('is_inclusive_tax').defaultTo(false);
|
||||||
|
table.decimal('tax_amount_withheld');
|
||||||
|
})
|
||||||
|
.createTable('tax_rate_transactions', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table
|
||||||
|
.integer('tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
|
table.string('reference_type');
|
||||||
|
table.integer('reference_id');
|
||||||
|
table.decimal('rate').unsigned();
|
||||||
|
table.integer('tax_account_id').unsigned();
|
||||||
|
})
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
|
table.decimal('tax_rate').unsigned();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('tax_rates');
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('bills', (table) => {
|
||||||
|
table.boolean('is_inclusive_tax').defaultTo(false);
|
||||||
|
table.decimal('tax_amount_withheld');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.table('bills', () => {});
|
||||||
|
};
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
exports.up = (knex) => {
|
||||||
|
return knex.schema.table('items', (table) => {
|
||||||
|
table
|
||||||
|
.integer('sell_tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
|
table
|
||||||
|
.integer('purchase_tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) => {
|
||||||
|
return knex.schema.dropTableIfExists('tax_rates');
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('storage', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table.string('key').notNullable();
|
||||||
|
table.string('path').notNullable();
|
||||||
|
table.string('extension').notNullable();
|
||||||
|
table.integer('expire_in');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('storage');
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.alterTable('items_entries', (table) => {
|
||||||
|
table.decimal('rate', 15, 5).alter();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.table('items_entries', (table) => {});
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('plaid_items', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.integer('tenant_id').unsigned();
|
||||||
|
table.string('plaid_item_id');
|
||||||
|
table.string('plaid_institution_id');
|
||||||
|
table.string('plaid_access_token');
|
||||||
|
table.string('last_cursor');
|
||||||
|
table.string('status');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('accounts', (table) => {
|
||||||
|
table.string('plaid_account_id');
|
||||||
|
table.string('account_mask').nullable();
|
||||||
|
table.decimal('bank_balance', 15, 5);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('cashflow_transactions', (table) => {
|
||||||
|
table.string('plaid_transaction_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable(
|
||||||
|
'uncategorized_cashflow_transactions',
|
||||||
|
(table) => {
|
||||||
|
table.increments('id');
|
||||||
|
table.date('date').index();
|
||||||
|
table.decimal('amount');
|
||||||
|
table.string('currency_code');
|
||||||
|
table.string('reference_no').index();
|
||||||
|
table.string('payee');
|
||||||
|
table
|
||||||
|
.integer('account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.string('description');
|
||||||
|
table.string('categorize_ref_type');
|
||||||
|
table.integer('categorize_ref_id').unsigned();
|
||||||
|
table.boolean('categorized').defaultTo(false);
|
||||||
|
table.string('plaid_transaction_id');
|
||||||
|
table.timestamps();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('uncategorized_cashflow_transactions');
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('accounts', (table) => {
|
||||||
|
table.integer('uncategorized_transactions').defaultTo(0);
|
||||||
|
table.boolean('is_system_account').defaultTo(true);
|
||||||
|
table.boolean('is_feeds_active').defaultTo(false);
|
||||||
|
table.datetime('last_feeds_updated_at').nullable();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('cashflow_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('uncategorized_transaction_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('uncategorized_cashflow_transactions');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.table('cashflow_transactions', (table) => {
|
||||||
|
table.dropColumn('uncategorized_transaction_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('storage');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('documents', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table.string('key').notNullable();
|
||||||
|
table.string('mime_type').notNullable();
|
||||||
|
table.integer('size').unsigned();
|
||||||
|
table.string('origin_name');
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('documents');
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.createTable('document_links', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table.string('model_ref').notNullable();
|
||||||
|
table.string('model_id').notNullable();
|
||||||
|
table.integer('document_id').unsigned();
|
||||||
|
table.datetime('expires_at').nullable();
|
||||||
|
table.timestamps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.dropTableIfExists('document_links');
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.createTable('bank_rules', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table.string('name');
|
||||||
|
table.integer('order').unsigned();
|
||||||
|
|
||||||
|
table
|
||||||
|
.integer('apply_if_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.string('apply_if_transaction_type');
|
||||||
|
|
||||||
|
table.string('assign_category');
|
||||||
|
table
|
||||||
|
.integer('assign_account_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('accounts');
|
||||||
|
table.string('assign_payee');
|
||||||
|
table.string('assign_memo');
|
||||||
|
|
||||||
|
table.string('conditions_type');
|
||||||
|
|
||||||
|
table.timestamps();
|
||||||
|
})
|
||||||
|
.createTable('bank_rule_conditions', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table
|
||||||
|
.integer('rule_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('bank_rules');
|
||||||
|
table.string('field');
|
||||||
|
table.string('comparator');
|
||||||
|
table.string('value');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.dropTableIfExists('bank_rules')
|
||||||
|
.dropTableIfExists('bank_rule_conditions');
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user