mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
WIP server side.
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import express from 'express';
|
||||
import { check, validationResult, param } from 'express-validator';
|
||||
import asyncMiddleware from '../middleware/asyncMiddleware';
|
||||
import { check, validationResult, param, query } from 'express-validator';
|
||||
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
||||
import Account from '@/models/Account';
|
||||
// import AccountBalance from '@/models/AccountBalance';
|
||||
import AccountType from '@/models/AccountType';
|
||||
// import JWTAuth from '@/http/middleware/jwtAuth';
|
||||
import AccountTransaction from '@/models/AccountTransaction';
|
||||
import JournalPoster from '@/services/Accounting/JournalPoster';
|
||||
import AccountBalance from '@/models/AccountBalance';
|
||||
import JWTAuth from '@/http/middleware/jwtAuth';
|
||||
import NestedSet from '../../collection/NestedSet';
|
||||
|
||||
export default {
|
||||
/**
|
||||
@@ -13,7 +16,7 @@ export default {
|
||||
router() {
|
||||
const router = express.Router();
|
||||
|
||||
// router.use(JWTAuth);
|
||||
router.use(JWTAuth);
|
||||
router.post('/',
|
||||
this.newAccount.validation,
|
||||
asyncMiddleware(this.newAccount.handler));
|
||||
@@ -23,12 +26,33 @@ export default {
|
||||
asyncMiddleware(this.editAccount.handler));
|
||||
|
||||
router.get('/:id',
|
||||
this.getAccount.validation,
|
||||
asyncMiddleware(this.getAccount.handler));
|
||||
|
||||
router.get('/',
|
||||
this.getAccountsList.validation,
|
||||
asyncMiddleware(this.getAccountsList.handler));
|
||||
|
||||
router.delete('/:id',
|
||||
this.deleteAccount.validation,
|
||||
asyncMiddleware(this.deleteAccount.handler));
|
||||
|
||||
router.post('/:id/active',
|
||||
this.activeAccount.validation,
|
||||
asyncMiddleware(this.activeAccount.handler));
|
||||
|
||||
router.post('/:id/inactive',
|
||||
this.inactiveAccount.validation,
|
||||
asyncMiddleware(this.inactiveAccount.handler));
|
||||
|
||||
router.post('/:id/recalculate-balance',
|
||||
this.recalcualteBalanace.validation,
|
||||
asyncMiddleware(this.recalcualteBalanace.handler));
|
||||
|
||||
router.post('/:id/transfer_account/:toAccount',
|
||||
this.transferToAnotherAccount.validation,
|
||||
asyncMiddleware(this.transferToAnotherAccount.handler));
|
||||
|
||||
return router;
|
||||
},
|
||||
|
||||
@@ -37,10 +61,10 @@ export default {
|
||||
*/
|
||||
newAccount: {
|
||||
validation: [
|
||||
check('name').isLength({ min: 3 }).trim().escape(),
|
||||
check('code').isLength({ max: 10 }).trim().escape(),
|
||||
check('account_type_id').isNumeric().toInt(),
|
||||
check('description').trim().escape(),
|
||||
check('name').exists().isLength({ min: 3 }).trim().escape(),
|
||||
check('code').exists().isLength({ max: 10 }).trim().escape(),
|
||||
check('account_type_id').exists().isNumeric().toInt(),
|
||||
check('description').optional().trim().escape(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const validationErrors = validationResult(req);
|
||||
@@ -50,34 +74,31 @@ export default {
|
||||
code: 'validation_error', ...validationErrors,
|
||||
});
|
||||
}
|
||||
const form = { ...req.body };
|
||||
|
||||
const { name, code, description } = req.body;
|
||||
const { account_type_id: typeId } = req.body;
|
||||
const foundAccountCodePromise = form.code
|
||||
? Account.query().where('code', form.code) : null;
|
||||
|
||||
const foundAccountCodePromise = code ? Account.where('code', code).fetch() : null;
|
||||
const foundAccountTypePromise = AccountType.where('id', typeId).fetch();
|
||||
const foundAccountTypePromise = AccountType.query()
|
||||
.findById(form.account_type_id);
|
||||
|
||||
const [foundAccountCode, foundAccountType] = await Promise.all([
|
||||
foundAccountCodePromise,
|
||||
foundAccountTypePromise,
|
||||
foundAccountCodePromise, foundAccountTypePromise,
|
||||
]);
|
||||
|
||||
if (!foundAccountCode && foundAccountCodePromise) {
|
||||
if (foundAccountCodePromise && foundAccountCode.length > 0) {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'NOT_UNIQUE_CODE', code: 100 }],
|
||||
});
|
||||
}
|
||||
if (!foundAccountType) {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'NOT_EXIST_ACCOUNT_TYPE', code: 110 }],
|
||||
errors: [{ type: 'NOT_EXIST_ACCOUNT_TYPE', code: 200 }],
|
||||
});
|
||||
}
|
||||
const account = Account.forge({
|
||||
name, code, account_type_id: typeId, description,
|
||||
});
|
||||
await Account.query().insert({ ...form });
|
||||
|
||||
await account.save();
|
||||
return res.status(200).send({ item: { ...account.attributes } });
|
||||
return res.status(200).send({ item: { } });
|
||||
},
|
||||
},
|
||||
|
||||
@@ -86,11 +107,11 @@ export default {
|
||||
*/
|
||||
editAccount: {
|
||||
validation: [
|
||||
param('id').toInt(),
|
||||
check('name').isLength({ min: 3 }).trim().escape(),
|
||||
check('code').isLength({ max: 10 }).trim().escape(),
|
||||
check('account_type_id').isNumeric().toInt(),
|
||||
check('description').trim().escape(),
|
||||
param('id').exists().toInt(),
|
||||
check('name').exists().isLength({ min: 3 }).trim().escape(),
|
||||
check('code').exists().isLength({ max: 10 }).trim().escape(),
|
||||
check('account_type_id').exists().isNumeric().toInt(),
|
||||
check('description').optional().trim().escape(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const { id } = req.params;
|
||||
@@ -101,39 +122,33 @@ export default {
|
||||
code: 'validation_error', ...validationErrors,
|
||||
});
|
||||
}
|
||||
|
||||
const account = await Account.where('id', id).fetch();
|
||||
const form = { ...req.body };
|
||||
const account = await Account.query().findById(id);
|
||||
|
||||
if (!account) {
|
||||
return res.boom.notFound();
|
||||
}
|
||||
const { name, code, description } = req.body;
|
||||
const { account_type_id: typeId } = req.body;
|
||||
const foundAccountCodePromise = (form.code && form.code !== account.code)
|
||||
? Account.query().where('code', form.code).whereNot('id', account.id) : null;
|
||||
|
||||
const foundAccountCodePromise = (code && code !== account.attributes.code)
|
||||
? Account.query({ where: { code }, whereNot: { id } }).fetch() : null;
|
||||
|
||||
const foundAccountTypePromise = (typeId !== account.attributes.account_type_id)
|
||||
? AccountType.where('id', typeId).fetch() : null;
|
||||
const foundAccountTypePromise = (form.account_type_id !== account.account_type_id)
|
||||
? AccountType.query().where('id', form.account_type_id) : null;
|
||||
|
||||
const [foundAccountCode, foundAccountType] = await Promise.all([
|
||||
foundAccountCodePromise, foundAccountTypePromise,
|
||||
]);
|
||||
|
||||
if (!foundAccountCode && foundAccountCodePromise) {
|
||||
if (foundAccountCode.length > 0 && foundAccountCodePromise) {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'NOT_UNIQUE_CODE', code: 100 }],
|
||||
});
|
||||
}
|
||||
if (!foundAccountType && foundAccountTypePromise) {
|
||||
if (foundAccountType.length <= 0 && foundAccountTypePromise) {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'NOT_EXIST_ACCOUNT_TYPE', code: 110 }],
|
||||
});
|
||||
}
|
||||
await account.patch({ ...form });
|
||||
|
||||
await account.save({
|
||||
name, code, account_type_id: typeId, description,
|
||||
});
|
||||
return res.status(200).send();
|
||||
},
|
||||
},
|
||||
@@ -142,7 +157,7 @@ export default {
|
||||
* Get details of the given account.
|
||||
*/
|
||||
getAccount: {
|
||||
valiation: [
|
||||
validation: [
|
||||
param('id').toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
@@ -165,14 +180,163 @@ export default {
|
||||
],
|
||||
async handler(req, res) {
|
||||
const { id } = req.params;
|
||||
const account = await Account.where('id', id).fetch();
|
||||
const account = await Account.query().findById(id);
|
||||
|
||||
if (!account) {
|
||||
return res.boom.notFound();
|
||||
}
|
||||
await account.destroy();
|
||||
const accountTransactions = await AccountTransaction.query()
|
||||
.where('account_id', account.id);
|
||||
|
||||
return res.status(200).send({ id: account.previous('id') });
|
||||
if (accountTransactions.length > 0) {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS', code: 100 }],
|
||||
});
|
||||
}
|
||||
await Account.query().deleteById(account.id);
|
||||
|
||||
return res.status(200).send();
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve accounts list.
|
||||
*/
|
||||
getAccountsList: {
|
||||
validation: [
|
||||
query('account_types').optional().isArray(),
|
||||
query('account_types.*').optional().isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const validationErrors = validationResult(req);
|
||||
|
||||
if (!validationErrors.isEmpty()) {
|
||||
return res.boom.badData(null, {
|
||||
code: 'validation_error', ...validationErrors,
|
||||
});
|
||||
}
|
||||
|
||||
const form = {
|
||||
account_types: [],
|
||||
...req.body,
|
||||
};
|
||||
const accounts = await Account.query()
|
||||
.modify('filterAccountTypes', form.account_types);
|
||||
|
||||
const accountsNestedSet = new NestedSet(accounts, {
|
||||
parentId: 'parentAccountId',
|
||||
});
|
||||
|
||||
return res.status(200).send({
|
||||
// ...accountsNestedSet.toArray(),
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-calculates balance of the given account.
|
||||
*/
|
||||
recalcualteBalanace: {
|
||||
validation: [
|
||||
param('id').isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const { id } = req.params;
|
||||
const account = await Account.findById(id);
|
||||
|
||||
if (!account) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'ACCOUNT.NOT.FOUND', code: 100 }],
|
||||
});
|
||||
}
|
||||
const accountTransactions = AccountTransaction.query()
|
||||
.where('account_id', account.id);
|
||||
|
||||
const journalEntries = new JournalPoster();
|
||||
journalEntries.loadFromCollection(accountTransactions);
|
||||
|
||||
// Delete the balance of the given account id.
|
||||
await AccountBalance.query().where('account_id', account.id).delete();
|
||||
|
||||
// Save calcualted account balance.
|
||||
await journalEntries.saveBalance();
|
||||
|
||||
return res.status(200).send();
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Active the given account.
|
||||
*/
|
||||
activeAccount: {
|
||||
validation: [
|
||||
param('id').exists().isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const { id } = req.params;
|
||||
const account = await Account.findById(id);
|
||||
|
||||
if (!account) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'ACCOUNT.NOT.FOUND', code: 100 }],
|
||||
});
|
||||
}
|
||||
await account.patch({ active: true });
|
||||
|
||||
return res.status(200).send({ id: account.id });
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Inactive the given account.
|
||||
*/
|
||||
inactiveAccount: {
|
||||
validation: [
|
||||
param('id').exists().isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const { id } = req.params;
|
||||
const account = await Account.findById(id);
|
||||
|
||||
if (!account) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'ACCOUNT.NOT.FOUND', code: 100 }],
|
||||
});
|
||||
}
|
||||
await account.patch({ active: false });
|
||||
|
||||
return res.status(200).send({ id: account.id });
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Transfer all journal entries of the given account to another account.
|
||||
*/
|
||||
transferToAnotherAccount: {
|
||||
validation: [
|
||||
param('id').exists().isNumeric().toInt(),
|
||||
param('toAccount').exists().isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
const validationErrors = validationResult(req);
|
||||
|
||||
if (!validationErrors.isEmpty()) {
|
||||
return res.boom.badData(null, {
|
||||
code: 'validation_error', ...validationErrors,
|
||||
});
|
||||
}
|
||||
|
||||
// const { id, toAccount: toAccountId } = req.params;
|
||||
|
||||
// const [fromAccount, toAccount] = await Promise.all([
|
||||
// Account.query().findById(id),
|
||||
// Account.query().findById(toAccountId),
|
||||
// ]);
|
||||
|
||||
// const fromAccountTransactions = await AccountTransaction.query()
|
||||
// .where('account_id', fromAccount);
|
||||
|
||||
// return res.status(200).send();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user