UNPKG

@tomei/product

Version:

NestJS package for product module

537 lines (468 loc) 14.4 kB
import { TreeNodeBase } from '@tomei/general'; import { StatusEnum } from '../../enum/status.enum'; import { ProductCategoryRepository } from './category-product.repository'; import { IProductCategory } from '../../interfaces/product-category-attr.interface'; import { LoginUser } from '@tomei/sso'; import { ApplicationConfig } from '@tomei/config'; import { ActionEnum, Activity } from '@tomei/activity-history'; import cuid from '../../helpers/cuid'; import { IProductCategoryUpdate } from '../../interfaces/product-category-update-attr.interface'; import { Op } from 'sequelize'; import { ProductProductCategory } from '../product-product-category/product-product-category'; import { PlatformCategoryMapping } from '../platform-category-mapping-product/platform-category-mapping-product'; interface IMappingInfoParam { platform: string; platformCategoryId: string; platformCategoryName: string; } export class ProductCategory extends TreeNodeBase<ProductCategory> { ObjectId: string; ObjectName: string; ObjectType = 'ProductCategory'; TableName: string; Code: string; CodePath: string; ParentCode: string; Name: string; Description: string; isChildrenLoaded: boolean; isParentLoaded: boolean; private _Status = StatusEnum.ACTIVE; private _CreatedById: string; private _CreatedAt: Date; private _UpdatedById: string; private _UpdatedAt: Date; private static _Repository = new ProductCategoryRepository(); get Status() { return this._Status; } get CreatedById() { return this._CreatedById; } get CreatedAt() { return this._CreatedAt; } get UpdatedById() { return this._UpdatedById; } get UpdatedAt() { return this._UpdatedAt; } private constructor(productCategory?: IProductCategory) { super(); if (productCategory) { this.Code = productCategory.Code; this.CodePath = productCategory.CodePath; this.ParentCode = productCategory.ParentCode; this.Name = productCategory.Name; this.Description = productCategory.Description; this._Status = productCategory.Status; this._CreatedById = productCategory.CreatedById; this._CreatedAt = productCategory.CreatedAt; this._UpdatedById = productCategory.UpdatedById; this._UpdatedAt = productCategory.UpdatedAt; } } static async init(code?: string) { try { if (code) { const productCategory = await ProductCategory._Repository.findByPk(code); if (!productCategory) { throw new Error('Product Category not found.'); } const data: IProductCategory = { Code: productCategory.Code, CodePath: productCategory.CodePath, ParentCode: productCategory.ParentCode, Name: productCategory.Name, Description: productCategory.Description, Status: productCategory.Status, CreatedById: productCategory.CreatedById, CreatedAt: productCategory.CreatedAt, UpdatedById: productCategory.UpdatedById, UpdatedAt: productCategory.UpdatedAt, }; return new ProductCategory(data); } return new ProductCategory(); } catch (error) { throw error; } } async loadChildren() { if (!this.Code) { throw new Error('Code is missing.'); } const children = await ProductCategory._Repository.findAll({ where: { ParentCode: this.Code }, order: [['CreatedAt', 'ASC']], }); this.children = children.map((child) => { return new ProductCategory(child); }); this.isChildrenLoaded = true; } async loadParent() { if (!this.Code) { throw new Error('Code is missing.'); } if (this.ParentCode) { if (this.ParentCode !== this.Code) { const parent = await ProductCategory._Repository.findByPk( this.ParentCode, ); this.parent = new ProductCategory(parent); } } this.isParentLoaded = true; } public async create( loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { try { const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'ProductCategory - Create', ); if (!isPrivileged) { throw new Error( `Forbidden Error, does not have right privilege - "ProductCategory - Create"`, ); } if (!this.Code) { throw new Error('Code is required.'); } if (!this.Name) { throw new Error('Name is required.'); } if (!this.Description) { throw new Error('Description is required.'); } this._CreatedById = loginUser.ObjectId; this._CreatedAt = new Date(); this._UpdatedById = loginUser.ObjectId; this._UpdatedAt = new Date(); const createdData = await ProductCategory._Repository.create( { Code: this.Code, Name: this.Name, Description: this.Description, CodePath: this.CodePath, ParentCode: this.ParentCode, Status: this.Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: this.UpdatedById, UpdatedAt: this.UpdatedAt, }, { transaction: dbTransaction, }, ); const activity = new Activity(); activity.ActivityId = cuid(); activity.Action = ActionEnum.CREATE; activity.Description = 'Create Product Category'; activity.EntityType = 'ProductCategory'; activity.EntityId = this.Code; activity.EntityValueBefore = JSON.stringify({}); activity.EntityValueAfter = JSON.stringify( createdData.get({ plain: true }), ); await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } public async update( payload: IProductCategoryUpdate, loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { try { const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'ProductCategory - Update', ); if (!isPrivileged) { throw new Error( `Forbidden Error, does not have right privilege - "ProductCategory - Update"`, ); } const entityValueBefore = { Code: this.Code, Name: this.Name, Description: this.Description, CodePath: this.CodePath, ParentCode: this.ParentCode, Status: this.Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: this.UpdatedById, UpdatedAt: this.UpdatedAt, }; if (payload.Description) { this.Description = payload.Description; } if (payload.ParentCode) { this.ParentCode = payload.ParentCode; } if (payload.Status) { this._Status = payload.Status; } if (payload.Code) { this.Code = payload.Code; if (this.ParentCode === this.Code) { this.ParentCode = payload.Code; } } if (payload.Name) { this.Name = payload.Name; this.CodePath = await this.getPath(); await this.checkAndUpdateChildrenCodePath( payload.Name, this.Name, dbTransaction, ); } this._UpdatedById = loginUser.ObjectId; this._UpdatedAt = new Date(); const entityValueAfter = { Code: this.Code, Name: this.Name, Description: this.Description, CodePath: this.CodePath, ParentCode: this.ParentCode, Status: this.Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: this.UpdatedById, UpdatedAt: this.UpdatedAt, }; ProductCategory._Repository.update( { ...entityValueAfter, }, { where: { Code: entityValueBefore.Code, }, transaction: dbTransaction, }, ); const activity = new Activity(); activity.ActivityId = cuid(); activity.Action = ActionEnum.UPDATE; activity.Description = 'Update Product Category'; activity.EntityType = 'ProductCategory'; activity.EntityId = this.Code; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); return; } catch (error) { throw error; } } private async checkAndUpdateChildrenCodePath( oldName: string, newName: string, dbTransaction: any, ) { const isLeaf = await this.isLeaf(); if (isLeaf) { return; } const childrens = await ProductCategory._Repository.findAll({ where: { CodePath: { [Op.like]: `${oldName} > %`, }, }, transaction: dbTransaction, }); childrens.forEach(async (children) => { const newCodePath = children.CodePath.replace(oldName, newName); await children.update( { CodePath: newCodePath }, { transaction: dbTransaction }, ); }); } static async findAll( loginUser: LoginUser, dbTransaction?: any, page?: number, rows?: number, search = {}, ): Promise<any> { try { // Privilege checking const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'ProductCategory - View', ); if (!isPrivileged) { throw new Error( `Forbidden Error, does not have right privilege - "ProductCategory - View"`, ); } // Retrieve listing const whereObj = {}; Object.entries(search).forEach(([key, value]) => { if (key === 'Status') { whereObj[key] = value; } else { whereObj[key] = { [Op.substring]: value, }; } }); let options: any = { where: whereObj, order: [['CreatedAt', 'DESC']], transaction: dbTransaction, }; if (page && rows) { const offset = rows * (page - 1); options = { ...options, offset, limit: rows, }; } const result = await ProductCategory._Repository.findAndCountAll(options); return result; } catch (error) { throw error; } } async delete(loginUser: LoginUser, dbTransaction?: any): Promise<void> { try { //call login user check privilege check if login user have privilege to delete const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'ProductCategory - Delete', ); if (!isPrivileged) { throw new Error( `Forbidden Error, does not have right privilege - "ProductCategory - Delete"`, ); } const entityValueBefore = { Code: this.Code, Name: this.Name, Description: this.Description, CodePath: this.CodePath, ParentCode: this.ParentCode, Status: this.Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: this.UpdatedById, UpdatedAt: this.UpdatedAt, }; const isProductAssigned = await ProductProductCategory.CheckProductAssignToCategory( this.Code, dbTransaction, ); await this.loadChildren(); const isGotSubCategory = this.children.length > 0; if (isProductAssigned || isGotSubCategory) { this._Status = StatusEnum.DEACTIVATED; const childrens = await ProductCategory._Repository.findAll({ where: { CodePath: { [Op.like]: `${this.Name}%`, }, }, transaction: dbTransaction, }); childrens.forEach(async (children) => { const productCategory = await ProductCategory.init(children.Code); await productCategory.update( { Status: StatusEnum.DEACTIVATED, }, loginUser, dbTransaction, ); }); await ProductCategory._Repository.update( { Status: StatusEnum.DEACTIVATED, }, { where: { Code: this.Code, }, transaction: dbTransaction, }, ); return; } else { await ProductCategory._Repository.delete(this.Code, dbTransaction); const activity = new Activity(); activity.ActivityId = cuid(); activity.Action = ActionEnum.DELETE; activity.Description = 'Delete Product Category'; activity.EntityType = 'ProductCategory'; activity.EntityId = this.Code; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify({}); await activity.create(loginUser.ObjectId, dbTransaction); return; } } catch (error) { throw error; } } public async assignPlatfromMapping( loginUser: LoginUser, dbTransaction: any, mappingInfo: IMappingInfoParam, ) { try { const pcm = await new PlatformCategoryMapping(); pcm.Code = this.Code; pcm.Platform = mappingInfo.platform; pcm.PlatformCategoryId = mappingInfo.platformCategoryId; pcm.PlatformCategoryName = mappingInfo.platformCategoryName; return pcm.create(loginUser, dbTransaction); } catch (error) { throw new Error( `An Error occured when retriving product collection: ${error.message}`, ); } } public async getPlatformMapping( loginUser: LoginUser, dbTransaction: any, page?: number, row?: number, ) { try { return PlatformCategoryMapping.findAll( loginUser, dbTransaction, this.Code, page, row, ); } catch (error) { throw new Error( `An Error occured when retriving product collection: ${error.message}`, ); } } }