From 8646f3dcf925ed52e4d408ae657eaa81ddb7eecf Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Wed, 24 Mar 2021 11:10:58 +0200 Subject: [PATCH] fix(Items): Not display inactive items in sales and purchases. fix(item): Prevent edit inventory account of item once item has transactions. --- .../Bills/BillForm/BillFormProvider.js | 17 ++++++--- server/src/api/controllers/Items.ts | 10 +++++ server/src/models/Item.js | 4 ++ server/src/services/Items/ItemsService.ts | 38 +++++++++++++++++++ server/src/services/Items/constants.ts | 1 + 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/client/src/containers/Purchases/Bills/BillForm/BillFormProvider.js b/client/src/containers/Purchases/Bills/BillForm/BillFormProvider.js index 02df9e7da..7c74c3581 100644 --- a/client/src/containers/Purchases/Bills/BillForm/BillFormProvider.js +++ b/client/src/containers/Purchases/Bills/BillForm/BillFormProvider.js @@ -7,7 +7,7 @@ import { useBill, useSettings, useCreateBill, - useEditBill + useEditBill, } from 'hooks/query'; const BillFormContext = createContext(); @@ -26,9 +26,14 @@ function BillFormProvider({ billId, ...props }) { } = useVendors({ page_size: 10000 }); // Filter all purchasable items only. - const stringifiedFilterRoles = React.useMemo(() => JSON.stringify( - [{ "fieldKey": "purchasable", "value":true, "condition":"equals"}] - ), []); + const stringifiedFilterRoles = React.useMemo( + () => + JSON.stringify([ + { index: 1, fieldKey: 'purchasable', value: true, condition: '&&', comparator: 'equals' }, + { index: 2, fieldKey: 'active', value: true, condition: '&&', comparator: 'equals' }, + ]), + [], + ); // Handle fetch Items data table or list const { @@ -36,7 +41,7 @@ function BillFormProvider({ billId, ...props }) { isFetching: isItemsLoading, } = useItems({ page_size: 10000, - stringified_filter_roles: stringifiedFilterRoles + stringified_filter_roles: stringifiedFilterRoles, }); // Handle fetch bill details. @@ -72,7 +77,7 @@ function BillFormProvider({ billId, ...props }) { createBillMutate, editBillMutate, - setSubmitPayload + setSubmitPayload, }; return ( diff --git a/server/src/api/controllers/Items.ts b/server/src/api/controllers/Items.ts index 67df445ef..0d34d6317 100644 --- a/server/src/api/controllers/Items.ts +++ b/server/src/api/controllers/Items.ts @@ -512,9 +512,19 @@ export default class ItemsController extends BaseController { errors: [{ type: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS', message: 'Cannot change item type to inventory with item has associated transactions.', + code: 350, }], }); } + if (error.errorType === 'INVENTORY_ACCOUNT_CANNOT_MODIFIED') { + return res.status(400).send({ + errors: [{ + type: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED', + message: 'Cannot change item inventory account while the item has transactions.', + code: 360, + }] + }) + } } next(error); } diff --git a/server/src/models/Item.js b/server/src/models/Item.js index c2a7b9da1..330321e87 100644 --- a/server/src/models/Item.js +++ b/server/src/models/Item.js @@ -178,6 +178,10 @@ export default class Item extends TenantModel { relation: "items_categories.id", relationColumn: "items_categories.name", }, + active: { + label: "Active", + column: "active", + }, // user: { // label: 'User', // column: 'user_id', diff --git a/server/src/services/Items/ItemsService.ts b/server/src/services/Items/ItemsService.ts index 8fa561e8a..057680a67 100644 --- a/server/src/services/Items/ItemsService.ts +++ b/server/src/services/Items/ItemsService.ts @@ -22,6 +22,7 @@ import { ACCOUNT_TYPE, } from 'data/AccountTypes'; import { ERRORS } from './constants'; +import { AccountTransaction } from 'models'; @Service() export default class ItemsService implements IItemsService { @@ -288,6 +289,37 @@ export default class ItemsService implements IItemsService { } } + /** + * Validate the item inventory account whether modified and item + * has assocaited inventory transactions. + * @param {numnber} tenantId + * @param {IItem} oldItem + * @param {IItemDTO} newItemDTO + * @returns + */ + async validateItemInvnetoryAccountModified( + tenantId: number, + oldItem: IItem, + newItemDTO: IItemDTO + ) { + const { AccountTransaction } = this.tenancy.models(tenantId); + + if ( + newItemDTO.type !== 'inventory' || + oldItem.inventoryAccountId === newItemDTO.inventoryAccountId + ) { + return; + } + // Inventory transactions associated to the given item id. + const transactions = await AccountTransaction.query().where({ + itemId: oldItem.id, + }); + // Throw the service error in case item has associated inventory transactions. + if (transactions.length > 0) { + throw new ServiceError(ERRORS.INVENTORY_ACCOUNT_CANNOT_MODIFIED); + } + } + /** * Creates a new item. * @param {number} tenantId DTO @@ -387,6 +419,12 @@ export default class ItemsService implements IItemsService { ); } + await this.validateItemInvnetoryAccountModified( + tenantId, + oldItem, + itemDTO + ); + const newItem = await Item.query().patchAndFetchById(itemId, { ...itemModel, }); diff --git a/server/src/services/Items/constants.ts b/server/src/services/Items/constants.ts index 59ba5313d..5bae41ebd 100644 --- a/server/src/services/Items/constants.ts +++ b/server/src/services/Items/constants.ts @@ -19,4 +19,5 @@ export const ERRORS = { 'ITEM_HAS_ASSOCIATED_INVENTORY_ADJUSTMENT', ITEM_CANNOT_CHANGE_INVENTORY_TYPE: 'ITEM_CANNOT_CHANGE_INVENTORY_TYPE', TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS', + INVENTORY_ACCOUNT_CANNOT_MODIFIED: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED' };