@tomei/product
Version:
NestJS package for product module
537 lines (468 loc) • 14.4 kB
text/typescript
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}`,
);
}
}
}