mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
Merge branch 'master' of https://github.com/abouolia/Bigcapital
This commit is contained in:
@@ -7,6 +7,7 @@ import AccountsService from 'services/Accounts/AccountsService';
|
|||||||
import { IAccountDTO, IAccountsFilter } from 'interfaces';
|
import { IAccountDTO, IAccountsFilter } from 'interfaces';
|
||||||
import { ServiceError } from 'exceptions';
|
import { ServiceError } from 'exceptions';
|
||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class AccountsController extends BaseController{
|
export default class AccountsController extends BaseController{
|
||||||
@@ -112,7 +113,7 @@ export default class AccountsController extends BaseController{
|
|||||||
return [
|
return [
|
||||||
check('name')
|
check('name')
|
||||||
.exists()
|
.exists()
|
||||||
.isLength({ min: 3, max: 255 })
|
.isLength({ min: 3, max: DATATYPES_LENGTH.STRING })
|
||||||
.trim()
|
.trim()
|
||||||
.escape(),
|
.escape(),
|
||||||
check('code')
|
check('code')
|
||||||
@@ -122,16 +123,16 @@ export default class AccountsController extends BaseController{
|
|||||||
.escape(),
|
.escape(),
|
||||||
check('account_type_id')
|
check('account_type_id')
|
||||||
.exists()
|
.exists()
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('description')
|
check('description')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isLength({ max: 512 })
|
.isLength({ max: DATATYPES_LENGTH.TEXT })
|
||||||
.trim()
|
.trim()
|
||||||
.escape(),
|
.escape(),
|
||||||
check('parent_account_id')
|
check('parent_account_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import asyncMiddleware from 'api/middleware/asyncMiddleware';
|
|||||||
import AuthenticationService from 'services/Authentication';
|
import AuthenticationService from 'services/Authentication';
|
||||||
import { ILoginDTO, ISystemUser, IRegisterOTD } from 'interfaces';
|
import { ILoginDTO, ISystemUser, IRegisterOTD } from 'interfaces';
|
||||||
import { ServiceError, ServiceErrors } from "exceptions";
|
import { ServiceError, ServiceErrors } from "exceptions";
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class AuthenticationController extends BaseController{
|
export default class AuthenticationController extends BaseController{
|
||||||
@@ -60,12 +61,12 @@ export default class AuthenticationController extends BaseController{
|
|||||||
*/
|
*/
|
||||||
get registerSchema(): ValidationChain[] {
|
get registerSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('first_name').exists().trim().escape(),
|
check('first_name').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('last_name').exists().trim().escape(),
|
check('last_name').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('email').exists().isEmail().trim().escape(),
|
check('email').exists().isString().isEmail().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('phone_number').exists().trim().escape(),
|
check('phone_number').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('password').exists().trim().escape(),
|
check('password').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('country').exists().trim().escape(),
|
check('country').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { check, param, query, body, ValidationChain } from 'express-validator';
|
import { check, param, query, body, ValidationChain } from 'express-validator';
|
||||||
import BaseController from "api/controllers/BaseController";
|
import BaseController from "api/controllers/BaseController";
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
export default class ContactsController extends BaseController {
|
export default class ContactsController extends BaseController {
|
||||||
/**
|
/**
|
||||||
@@ -7,37 +8,37 @@ export default class ContactsController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
get contactDTOSchema(): ValidationChain[] {
|
get contactDTOSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('salutation').optional().trim().escape(),
|
check('salutation').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('first_name').optional().trim().escape(),
|
check('first_name').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('last_name').optional().trim().escape(),
|
check('last_name').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
|
||||||
check('company_name').optional().trim().escape(),
|
check('company_name').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('display_name').exists().trim().escape(),
|
check('display_name').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
|
||||||
check('email').optional({ nullable: true }).normalizeEmail().isEmail(),
|
check('email').optional({ nullable: true }).isString().normalizeEmail().isEmail().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('website').optional().trim().escape(),
|
check('website').optional().isString().trim().isURL().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('work_phone').optional().trim().escape(),
|
check('work_phone').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('personal_phone').optional().trim().escape(),
|
check('personal_phone').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
|
||||||
check('billing_address_1').optional().trim().escape(),
|
check('billing_address_1').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_2').optional().trim().escape(),
|
check('billing_address_2').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_city').optional().trim().escape(),
|
check('billing_address_city').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_country').optional().trim().escape(),
|
check('billing_address_country').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_email').optional().isEmail().trim().escape(),
|
check('billing_address_email').optional().isString().isEmail().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_postcode').optional().trim().escape(),
|
check('billing_address_postcode').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_phone').optional().trim().escape(),
|
check('billing_address_phone').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('billing_address_state').optional().trim().escape(),
|
check('billing_address_state').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
|
||||||
check('shipping_address_1').optional().trim().escape(),
|
check('shipping_address_1').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_2').optional().trim().escape(),
|
check('shipping_address_2').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_city').optional().trim().escape(),
|
check('shipping_address_city').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_country').optional().trim().escape(),
|
check('shipping_address_country').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_email').optional().isEmail().trim().escape(),
|
check('shipping_address_email').optional().isString().isEmail().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_postcode').optional().trim().escape(),
|
check('shipping_address_postcode').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_phone').optional().trim().escape(),
|
check('shipping_address_phone').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('shipping_address_state').optional().trim().escape(),
|
check('shipping_address_state').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
|
||||||
check('note').optional().trim().escape(),
|
check('note').optional().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
check('active').optional().isBoolean().toBoolean(),
|
check('active').optional().isBoolean().toBoolean(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -48,8 +49,10 @@ export default class ContactsController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
get contactNewDTOSchema(): ValidationChain[] {
|
get contactNewDTOSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('opening_balance').optional({ nullable: true }).isNumeric().toInt(),
|
check('opening_balance').optional({ nullable: true }).isInt({ min: 0, max: DATATYPES_LENGTH.DECIMAL_13_3 }).toInt(),
|
||||||
body('opening_balance_at').if(body('opening_balance').exists()).exists(),
|
body('opening_balance_at')
|
||||||
|
.if(body('opening_balance').exists()).exists()
|
||||||
|
.isISO8601(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export default class CustomersController extends ContactsController {
|
|||||||
*/
|
*/
|
||||||
get createCustomerDTOSchema() {
|
get createCustomerDTOSchema() {
|
||||||
return [
|
return [
|
||||||
check('currency_code').optional().trim().escape(),
|
check('currency_code').optional().isString().trim().escape().isLength({ max: 3, min: 3 }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,12 @@ export default class VendorsController extends ContactsController {
|
|||||||
*/
|
*/
|
||||||
get vendorDTOSchema(): ValidationChain[] {
|
get vendorDTOSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('currency_code').optional().trim().escape(),
|
check('currency_code')
|
||||||
|
.optional()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ min: 3, max: 3 }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { IItemCategoryOTD } from 'interfaces';
|
|||||||
import { ServiceError } from 'exceptions';
|
import { ServiceError } from 'exceptions';
|
||||||
import BaseController from 'api/controllers/BaseController';
|
import BaseController from 'api/controllers/BaseController';
|
||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ItemsCategoriesController extends BaseController {
|
export default class ItemsCategoriesController extends BaseController {
|
||||||
@@ -78,26 +79,32 @@ export default class ItemsCategoriesController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
get categoryValidationSchema() {
|
get categoryValidationSchema() {
|
||||||
return [
|
return [
|
||||||
check('name').exists().trim().escape(),
|
check('name')
|
||||||
|
.exists()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ min: 0, max: DATATYPES_LENGTH.STRING }),
|
||||||
check('parent_category_id')
|
check('parent_category_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('description')
|
check('description')
|
||||||
.optional()
|
.optional()
|
||||||
|
.isString()
|
||||||
.trim()
|
.trim()
|
||||||
.escape(),
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
check('sell_account_id')
|
check('sell_account_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('cost_account_id')
|
check('cost_account_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('inventory_account_id')
|
check('inventory_account_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import BaseController from 'api/controllers/BaseController';
|
|||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
import { ServiceError } from 'exceptions';
|
import { ServiceError } from 'exceptions';
|
||||||
import { IItemDTO } from 'interfaces';
|
import { IItemDTO } from 'interfaces';
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ItemsController extends BaseController {
|
export default class ItemsController extends BaseController {
|
||||||
@@ -78,44 +79,75 @@ export default class ItemsController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
get validateItemSchema(): ValidationChain[] {
|
get validateItemSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('name').exists(),
|
check('name').exists().isString().isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('type').exists().trim().escape()
|
check('type').exists()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
.isIn(['service', 'non-inventory', 'inventory']),
|
.isIn(['service', 'non-inventory', 'inventory']),
|
||||||
check('code').optional({ nullable: true }).trim().escape(),
|
check('code')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
// Purchase attributes.
|
// Purchase attributes.
|
||||||
check('purchasable').optional().isBoolean().toBoolean(),
|
check('purchasable').optional().isBoolean().toBoolean(),
|
||||||
check('cost_price')
|
check('cost_price')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isFloat({ min: 0, max: DATATYPES_LENGTH.DECIMAL_13_3 })
|
||||||
|
.toFloat()
|
||||||
.if(check('purchasable').equals('true'))
|
.if(check('purchasable').equals('true'))
|
||||||
.exists()
|
.exists(),
|
||||||
.isNumeric()
|
|
||||||
.toFloat(),
|
|
||||||
check('cost_account_id')
|
check('cost_account_id')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
|
.toInt()
|
||||||
.if(check('purchasable').equals('true'))
|
.if(check('purchasable').equals('true'))
|
||||||
.exists()
|
.exists(),
|
||||||
.isInt()
|
|
||||||
.toInt(),
|
|
||||||
// Sell attributes.
|
// Sell attributes.
|
||||||
check('sellable').optional().isBoolean().toBoolean(),
|
check('sellable').optional().isBoolean().toBoolean(),
|
||||||
check('sell_price')
|
check('sell_price')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isFloat({ min: 0, max: DATATYPES_LENGTH.DECIMAL_13_3 })
|
||||||
|
.toFloat()
|
||||||
.if(check('sellable').equals('true'))
|
.if(check('sellable').equals('true'))
|
||||||
.exists()
|
.exists(),
|
||||||
.isNumeric()
|
|
||||||
.toFloat(),
|
|
||||||
check('sell_account_id')
|
check('sell_account_id')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
|
.toInt()
|
||||||
.if(check('sellable').equals('true'))
|
.if(check('sellable').equals('true'))
|
||||||
.exists()
|
.exists(),
|
||||||
.isInt()
|
|
||||||
.toInt(),
|
|
||||||
check('inventory_account_id')
|
check('inventory_account_id')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
|
.toInt()
|
||||||
.if(check('type').equals('inventory'))
|
.if(check('type').equals('inventory'))
|
||||||
.exists()
|
.exists(),
|
||||||
.isInt()
|
check('sell_description')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
|
check('cost_description')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
|
check('category_id')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isInt({ min: 0, max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('sell_description').optional({ nullable: true }).trim().escape(),
|
check('note')
|
||||||
check('cost_description').optional({ nullable: true }).trim().escape(),
|
.optional()
|
||||||
|
.isString()
|
||||||
check('category_id').optional({ nullable: true }).isInt().toInt(),
|
.trim()
|
||||||
check('note').optional(),
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
|
check('active').optional().isBoolean().toBoolean(),
|
||||||
|
|
||||||
check('media_ids').optional().isArray(),
|
check('media_ids').optional().isArray(),
|
||||||
check('media_ids.*').exists().isNumeric().toInt(),
|
check('media_ids.*').exists().isNumeric().toInt(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import ManualJournalsService from 'services/ManualJournals/ManualJournalsService
|
|||||||
import { Inject, Service } from "typedi";
|
import { Inject, Service } from "typedi";
|
||||||
import { ServiceError } from 'exceptions';
|
import { ServiceError } from 'exceptions';
|
||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ManualJournalsController extends BaseController {
|
export default class ManualJournalsController extends BaseController {
|
||||||
@@ -113,30 +114,54 @@ export default class ManualJournalsController extends BaseController {
|
|||||||
get manualJournalValidationSchema() {
|
get manualJournalValidationSchema() {
|
||||||
return [
|
return [
|
||||||
check('date').exists().isISO8601(),
|
check('date').exists().isISO8601(),
|
||||||
check('journal_number').exists().trim().escape(),
|
check('journal_number')
|
||||||
check('journal_type').optional({ nullable: true }).trim().escape(),
|
.exists()
|
||||||
check('reference').optional({ nullable: true }),
|
.isString()
|
||||||
check('description').optional().trim().escape(),
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('journal_type')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('reference')
|
||||||
|
.optional({ nullable: true })
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('description')
|
||||||
|
.optional()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.TEXT }),
|
||||||
check('status').optional().isBoolean().toBoolean(),
|
check('status').optional().isBoolean().toBoolean(),
|
||||||
check('entries').isArray({ min: 2 }),
|
check('entries').isArray({ min: 2 }),
|
||||||
check('entries.*.index').exists().isNumeric().toInt(),
|
check('entries.*.index')
|
||||||
|
.exists()
|
||||||
|
.isInt({ max: DATATYPES_LENGTH.INT_10 }).toInt(),
|
||||||
check('entries.*.credit')
|
check('entries.*.credit')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isNumeric()
|
||||||
.isDecimal()
|
.isDecimal()
|
||||||
.isFloat({ max: 9999999999.999 }) // 13, 3
|
.isFloat({ max: DATATYPES_LENGTH.INT_13_3 }) // 13, 3
|
||||||
.toFloat(),
|
.toFloat(),
|
||||||
check('entries.*.debit')
|
check('entries.*.debit')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isNumeric()
|
||||||
.isDecimal()
|
.isDecimal()
|
||||||
.isFloat({ max: 9999999999.999 }) // 13, 3
|
.isFloat({ max: DATATYPES_LENGTH.INT_13_3 }) // 13, 3
|
||||||
.toFloat(),
|
.toFloat(),
|
||||||
check('entries.*.account_id').isNumeric().toInt(),
|
check('entries.*.account_id').isInt({ max: DATATYPES_LENGTH.INT_10 }).toInt(),
|
||||||
check('entries.*.note').optional(),
|
check('entries.*.note')
|
||||||
|
.optional()
|
||||||
|
.isString()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
check('entries.*.contact_id')
|
check('entries.*.contact_id')
|
||||||
.optional({ nullable: true })
|
.optional({ nullable: true })
|
||||||
.isNumeric()
|
.isInt({ max: DATATYPES_LENGTH.INT_10 })
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('entries.*.contact_type').optional().isIn(['vendor', 'customer']),
|
check('entries.*.contact_type').optional().isIn(['vendor', 'customer']),
|
||||||
]
|
]
|
||||||
|
|||||||
8
server/src/data/DataTypes.js
Normal file
8
server/src/data/DataTypes.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
export const DATATYPES_LENGTH = {
|
||||||
|
STRING: 255,
|
||||||
|
TEXT: 65535,
|
||||||
|
INT_10: 4294967295,
|
||||||
|
DECIMAL_13_3: 9999999999.999,
|
||||||
|
DECIMAL_15_5: 999999999999.999,
|
||||||
|
};
|
||||||
@@ -18,6 +18,7 @@ exports.up = function (knex) {
|
|||||||
table.text('purchase_description').nullable();
|
table.text('purchase_description').nullable();
|
||||||
table.integer('quantity_on_hand');
|
table.integer('quantity_on_hand');
|
||||||
table.text('note').nullable();
|
table.text('note').nullable();
|
||||||
|
table.boolean('active');
|
||||||
table.integer('category_id').unsigned().index().references('id').inTable('items_categories');
|
table.integer('category_id').unsigned().index().references('id').inTable('items_categories');
|
||||||
table.integer('user_id').unsigned().index();
|
table.integer('user_id').unsigned().index();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export interface IItem{
|
|||||||
|
|
||||||
quantityOnHand: number,
|
quantityOnHand: number,
|
||||||
note: string,
|
note: string,
|
||||||
|
active: boolean,
|
||||||
|
|
||||||
categoryId: number,
|
categoryId: number,
|
||||||
userId: number,
|
userId: number,
|
||||||
@@ -52,6 +53,7 @@ export interface IItemDTO {
|
|||||||
|
|
||||||
quantityOnHand: number,
|
quantityOnHand: number,
|
||||||
note: string,
|
note: string,
|
||||||
|
active: boolean,
|
||||||
|
|
||||||
categoryId: number,
|
categoryId: number,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default class CustomersService {
|
|||||||
|
|
||||||
private transformContactToCustomer(contactModel: IContact) {
|
private transformContactToCustomer(contactModel: IContact) {
|
||||||
return {
|
return {
|
||||||
...omit(contactModel, ['contactService', 'contactType']),
|
...omit(contactModel.toJSON(), ['contactService', 'contactType']),
|
||||||
customerType: contactModel.contactType,
|
customerType: contactModel.contactType,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,11 @@ export default class CustomersService {
|
|||||||
public async getCustomersList(
|
public async getCustomersList(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
customersFilter: ICustomersFilter
|
customersFilter: ICustomersFilter
|
||||||
): Promise<{ customers: ICustomer[], pagination: IPaginationMeta, filterMeta: IFilterMeta }> {
|
): Promise<{
|
||||||
|
customers: ICustomer[],
|
||||||
|
pagination: IPaginationMeta,
|
||||||
|
filterMeta: IFilterMeta,
|
||||||
|
}> {
|
||||||
const { Contact } = this.tenancy.models(tenantId);
|
const { Contact } = this.tenancy.models(tenantId);
|
||||||
const dynamicList = await this.dynamicListService.dynamicList(tenantId, Contact, customersFilter);
|
const dynamicList = await this.dynamicListService.dynamicList(tenantId, Contact, customersFilter);
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,11 @@ export default class ItemCategoriesService implements IItemCategoriesService {
|
|||||||
*/
|
*/
|
||||||
public async deleteItemCategory(tenantId: number, itemCategoryId: number, authorizedUser: ISystemUser) {
|
public async deleteItemCategory(tenantId: number, itemCategoryId: number, authorizedUser: ISystemUser) {
|
||||||
this.logger.info('[item_category] trying to delete item category.', { tenantId, itemCategoryId });
|
this.logger.info('[item_category] trying to delete item category.', { tenantId, itemCategoryId });
|
||||||
|
|
||||||
|
// Retrieve item category or throw not found error.
|
||||||
await this.getItemCategoryOrThrowError(tenantId, itemCategoryId);
|
await this.getItemCategoryOrThrowError(tenantId, itemCategoryId);
|
||||||
|
|
||||||
|
// Unassociate items with item category.
|
||||||
await this.unassociateItemsWithCategories(tenantId, itemCategoryId);
|
await this.unassociateItemsWithCategories(tenantId, itemCategoryId);
|
||||||
|
|
||||||
const { ItemCategory } = this.tenancy.models(tenantId);
|
const { ItemCategory } = this.tenancy.models(tenantId);
|
||||||
@@ -265,6 +269,9 @@ export default class ItemCategoriesService implements IItemCategoriesService {
|
|||||||
const dynamicList = await this.dynamicListService.dynamicList(tenantId, ItemCategory, filter);
|
const dynamicList = await this.dynamicListService.dynamicList(tenantId, ItemCategory, filter);
|
||||||
|
|
||||||
const itemCategories = await ItemCategory.query().onBuild((query) => {
|
const itemCategories = await ItemCategory.query().onBuild((query) => {
|
||||||
|
// Subquery to calculate sumation of assocaited items to the item category.
|
||||||
|
query.select('*', ItemCategory.relatedQuery('items').count().as('count'));
|
||||||
|
|
||||||
dynamicList.buildQuery()(query);
|
dynamicList.buildQuery()(query);
|
||||||
});
|
});
|
||||||
return { itemCategories, filterMeta: dynamicList.getResponseMeta() };
|
return { itemCategories, filterMeta: dynamicList.getResponseMeta() };
|
||||||
@@ -276,11 +283,14 @@ export default class ItemCategoriesService implements IItemCategoriesService {
|
|||||||
* @param {number|number[]} itemCategoryId -
|
* @param {number|number[]} itemCategoryId -
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
private async unassociateItemsWithCategories(tenantId: number, itemCategoryId: number|number[]): Promise<void> {
|
private async unassociateItemsWithCategories(
|
||||||
|
tenantId: number,
|
||||||
|
itemCategoryId: number | number[],
|
||||||
|
): Promise<void> {
|
||||||
const { Item } = this.tenancy.models(tenantId);
|
const { Item } = this.tenancy.models(tenantId);
|
||||||
const ids = Array.isArray(itemCategoryId) ? itemCategoryId : [itemCategoryId];
|
const ids = Array.isArray(itemCategoryId) ? itemCategoryId : [itemCategoryId];
|
||||||
|
|
||||||
await Item.query().whereIn('id', ids).patch({ category_id: null });
|
await Item.query().whereIn('category_id', ids).patch({ category_id: null });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -288,7 +298,11 @@ export default class ItemCategoriesService implements IItemCategoriesService {
|
|||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number[]} itemCategoriesIds
|
* @param {number[]} itemCategoriesIds
|
||||||
*/
|
*/
|
||||||
public async deleteItemCategories(tenantId: number, itemCategoriesIds: number[], authorizedUser: ISystemUser) {
|
public async deleteItemCategories(
|
||||||
|
tenantId: number,
|
||||||
|
itemCategoriesIds: number[],
|
||||||
|
authorizedUser: ISystemUser,
|
||||||
|
) {
|
||||||
this.logger.info('[item_category] trying to delete item categories.', { tenantId, itemCategoriesIds });
|
this.logger.info('[item_category] trying to delete item categories.', { tenantId, itemCategoriesIds });
|
||||||
const { ItemCategory } = this.tenancy.models(tenantId);
|
const { ItemCategory } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { difference } from "lodash";
|
import { defaultTo, difference } from "lodash";
|
||||||
import { Service, Inject } from "typedi";
|
import { Service, Inject } from "typedi";
|
||||||
import { IItemsFilter, IItemsService, IItemDTO, IItem } from 'interfaces';
|
import { IItemsFilter, IItemsService, IItemDTO, IItem } from 'interfaces';
|
||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
@@ -176,7 +176,10 @@ export default class ItemsService implements IItemsService {
|
|||||||
if (itemDTO.inventoryAccountId) {
|
if (itemDTO.inventoryAccountId) {
|
||||||
await this.validateItemInventoryAccountExistance(tenantId, itemDTO.inventoryAccountId);
|
await this.validateItemInventoryAccountExistance(tenantId, itemDTO.inventoryAccountId);
|
||||||
}
|
}
|
||||||
const storedItem = await Item.query().insertAndFetch({ ...itemDTO });
|
const storedItem = await Item.query().insertAndFetch({
|
||||||
|
...itemDTO,
|
||||||
|
active: defaultTo(itemDTO.active, 1),
|
||||||
|
});
|
||||||
this.logger.info('[items] item inserted successfully.', { tenantId, itemDTO });
|
this.logger.info('[items] item inserted successfully.', { tenantId, itemDTO });
|
||||||
|
|
||||||
return storedItem;
|
return storedItem;
|
||||||
|
|||||||
Reference in New Issue
Block a user