This commit is contained in:
elforjani3
2020-11-29 18:08:10 +02:00
14 changed files with 191 additions and 85 deletions

View File

@@ -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(),
]; ];
} }

View File

@@ -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 }),
]; ];
} }

View File

@@ -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(),
]; ];
} }

View File

@@ -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 }),
]; ];
} }

View File

@@ -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 }),
]; ];
} }

View File

@@ -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(),
] ]
} }

View File

@@ -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(),

View File

@@ -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']),
] ]

View 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,
};

View File

@@ -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();

View File

@@ -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,
} }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;