UNPKG

@tomei/product

Version:

NestJS package for product module

592 lines (538 loc) 18.6 kB
import { ProductWithInventoryBase } from '../../base/product-with-inventory/product-with-inventory.base'; import { ClassError, RecordNotFoundError } from '@tomei/general'; import { ProductJewelleryRepository } from './jewellery-product.repository'; import { IJewelleryProductAttr } from '../../interfaces/product-jewellery-attr.interface'; import { ProductWithInventoryModel } from '../../entities/product-with-inventory.entity'; import { ProductJewelleryModel } from '../../entities/product-jewellery.entity'; import { ProductModel } from '../../entities/product.entity'; import cuid from '../../helpers/cuid'; import { LoginUser } from '@tomei/sso'; import { StockProfileModel, StockProfile } from '@tomei/stock'; import { Op } from 'sequelize'; import { ActionEnum, Activity } from '@tomei/activity-history'; import { SettingsCategoryModel } from '../../entities/settings-category.entity'; import { SettingsCollectionModel } from '../../entities/settings-collection.entity'; import { SettingsGroupModel } from '../../entities/settings-group.entity'; import { ProductCertificateModel } from '../../entities/product-certificate.entity'; import { ProductTagModel } from '../../entities/product-tag.entity'; import { ProductBrandModel } from '../../entities/product-brand.entity'; import { ProductCustomizeOptionModel } from '../../entities/product-customize-option.entity'; import { ProductMaterialModel } from '../../entities/product-material.entity'; import { IProductVariantCreate } from '../../interfaces/product-variant-create.interface'; import { ProductVariantWithInventory } from '../variant-product-with-inventory/variant-product-with-inventory'; import { ProductVariantType } from '../../enum/product-variant.enum'; interface IProductJewelleryInitParam { productId?: string; productInfo?: IJewelleryProductAttr; } export class ProductJewellery extends ProductWithInventoryBase { ObjectType = 'ProductJewellery'; private _ProfileId: string; private _Surface: string; private _Uniqueness: string; private _HasCertificateYN = 'N'; private static _ProductJewelleryRepository = new ProductJewelleryRepository(); get ProductId() { return super.ProductId; } set ProductId(productId: string) { super.ProductId = productId; } get ProfileId() { return this._ProfileId; } private set ProfileId(id: string) { this._ProfileId = id; } get Surface() { return this._Surface; } set Surface(surface: string) { this._Surface = surface; } get Uniqueness() { return this._Uniqueness; } set Uniqueness(uniqueness: string) { this._Uniqueness = uniqueness; } get HasCertificateYN() { return this._HasCertificateYN; } set HasCertificateYN(hasCertificateYN: string) { this._HasCertificateYN = hasCertificateYN; } get UOM() { return super.UOM; } get TotalUnits() { return super.TotalUnits; } get TotalUnitsAvailable() { return super.TotalUnitsAvailable; } get TotalUnitsInCurrentOrder() { return super.TotalUnitsInCurrentOrder; } get TotalUnitsSold() { return super.TotalUnitsSold; } get TotalUnitsReserved() { return super.TotalUnitsReserved; } get TotalUnitsOnConsignment() { return super.TotalUnitsOnConsignment; } get TotalUnitsUnderMaintenance() { return super.TotalUnitsUnderMaintenance; } get TotalUnitsVoid() { return super.TotalUnitsVoid; } get TotalUnitsInTransit() { return super.TotalUnitsInTransit; } get TotalUnitsBackOrdered() { return super.TotalUnitsBackOrdered; } get TotalUnitsPreOrdered() { return super.TotalUnitsPreOrdered; } get StockLowAlertLevel() { return super.StockLowAlertLevel; } get StockReorderLevel() { return super.StockReorderLevel; } get BufferStockLevel() { return super.BufferStockLevel; } protected constructor(productJewelleryAttr) { super(productJewelleryAttr); this._ProfileId = productJewelleryAttr.ProfileId; this._Surface = productJewelleryAttr.Surface; this._Uniqueness = productJewelleryAttr.Uniqueness; this._HasCertificateYN = productJewelleryAttr.HasCertificateYN; } static async init( options: IProductJewelleryInitParam, ): Promise<ProductJewellery> { try { const { productId, productInfo } = options; if (productId) { const product = await ProductJewellery._ProductJewelleryRepository.findOne({ where: { ProductId: productId, }, include: [ { model: ProductWithInventoryModel, include: [ { model: ProductModel, }, ], }, ], }); const productAttr: IJewelleryProductAttr = { ProductId: product.ProductId, Name: product.ProductWithInventory.Product.Name, Description: product.ProductWithInventory.Product.Description, SKU: product.ProductWithInventory.Product.SKU, Type: product.ProductWithInventory.Product.Type, Remark: product.ProductWithInventory.Product.Remark, IsTaxableYN: product.ProductWithInventory.Product.IsTaxableYN, TaxCode: product.ProductWithInventory.Product.TaxCode, IsPriceInclusiveTaxYN: product.ProductWithInventory.Product.IsPriceInclusiveTaxYN, Status: product.ProductWithInventory.Product.Status, VerifiedYN: product.ProductWithInventory.Product.VerifiedYN, VerifiedById: product.ProductWithInventory.Product.VerifiedById, VerifiedAt: product.ProductWithInventory.Product.VerifiedAt, VariantLevels: product.ProductWithInventory.Product.VariantLevels, VariantTypeLevel1: product.ProductWithInventory.Product.VariantTypeLevel1, VariantTypeLevel2: product.ProductWithInventory.Product.VariantTypeLevel2, VariantTypeLevel3: product.ProductWithInventory.Product.VariantTypeLevel3, CreatedById: product.ProductWithInventory.Product.CreatedById, CreatedAt: product.ProductWithInventory.Product.CreatedAt, UpdatedById: product.ProductWithInventory.Product.UpdatedById, UpdatedAt: product.ProductWithInventory.Product.UpdatedAt, UpdatedSSYN: product.ProductWithInventory.Product.UpdatedSSYN, UOM: product.ProductWithInventory.UOM, TotalUnits: product.ProductWithInventory.TotalUnits, TotalUnitsAvailable: product.ProductWithInventory.TotalUnitsAvailable, TotalUnitsInCurrentOrder: product.ProductWithInventory.TotalUnitsInCurrentOrder, TotalUnitsSold: product.ProductWithInventory.TotalUnitsSold, TotalUnitsReserved: product.ProductWithInventory.TotalUnitsReserved, TotalUnitsOnConsignment: product.ProductWithInventory.TotalUnitsOnConsignment, TotalUnitsUnderMaintenance: product.ProductWithInventory.TotalUnitsUnderMaintenance, TotalUnitsVoid: product.ProductWithInventory.TotalUnitsVoid, TotalUnitsInTransit: product.ProductWithInventory.TotalUnitsInTransit, TotalUnitsBackOrdered: product.ProductWithInventory.TotalUnitsBackOrdered, TotalUnitsPreOrdered: product.ProductWithInventory.TotalUnitsPreOrdered, StockLowAlertLevel: product.ProductWithInventory.StockLowAlertLevel, StockReorderLevel: product.ProductWithInventory.StockReorderLevel, BufferStockLevel: product.ProductWithInventory.BufferStockLevel, ProfileId: product.ProfileId, Surface: product.Surface, Uniqueness: product.Uniqueness, HasCertificateYN: product.HasCertificateYN, PreviousSKU: product.ProductWithInventory.Product.PreviousSKU, }; if (productAttr) { const productJewellery = new ProductJewellery(productAttr); return productJewellery; } else { throw Error('ProductId not found.'); } } else { if (!productInfo) { throw Error('Product info is required.'); } return new ProductJewellery(productInfo); } } catch (err) { throw Error('Failed to instantiate ProductJewellery.'); } } async create( loginUser: LoginUser, dbTransaction: any, profileId?: string, ): Promise<any> { try { if (!profileId) { throw new Error('ProfileId is required.'); } let stockProfile: StockProfile; try { stockProfile = await StockProfile.init(profileId); } catch (error) { if (error.message && error.message === 'ProfileId not found') { throw new RecordNotFoundError( 'ProductJewelleryErrMsg01', 'Stock Profile not found. Please create Stock Profile first.', ); } else { throw error; } } this.ProfileId = stockProfile.ProfileId; const parentData = await super.create(loginUser, dbTransaction); const data = await ProductJewellery._ProductJewelleryRepository.create( { ProfileId: this._ProfileId, ProductId: parentData.ProductId, Surface: this._Surface, Uniqueness: this._Uniqueness, HasCertificateYN: this._HasCertificateYN, }, { transaction: dbTransaction, }, ); const entityValueAfter = data.get({ plain: true }); const activity = new Activity(); activity.ActivityId = cuid(); activity.Action = ActionEnum.CREATE; activity.Description = 'Add new product with inventory'; activity.EntityType = 'ProductWithInventory'; activity.EntityId = data.ProductId; activity.EntityValueBefore = JSON.stringify({}); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } static async findAll( loginUser: LoginUser, dbTransaction?: any, searchOptions?: { page: any; rows: any; search: any }, ): Promise< ProductJewelleryModel[] | { rows: ProductJewelleryModel[]; count: number } > { try { await super.findAll(loginUser); if (searchOptions.page && searchOptions.rows) { const offset = searchOptions.rows * (searchOptions.page - 1); let searchObj: any; try { searchObj = searchOptions.search ? JSON.parse(searchOptions.search) : {}; } catch (err) { throw new Error('Bad value for search.'); } const { StoreId, CategoryCode, CollectionCode, CertificateId, GroupCode, Brand, TagId, CustomizeOptionId, MaterialId, ...prodFilter } = searchObj; const productQueryObj = {}; Object.entries(prodFilter).forEach(([key, value]) => { productQueryObj[key] = { [Op.substring]: value, }; }); return await ProductJewellery._ProductJewelleryRepository.findAllWithPagination( { productQuery: { whereProduct: productQueryObj, StoreId, CategoryCode, CollectionCode, CertificateId, GroupCode, Brand, TagId, CustomizeOptionId, MaterialId, }, rows: searchOptions.rows, offset, transaction: dbTransaction, }, ); } else { return await ProductJewellery._ProductJewelleryRepository.findAll( dbTransaction, ); } } catch (error) { throw error; } } public async update( loginUser: LoginUser, productInfo?: IJewelleryProductAttr, dbTransaction?: any, ): Promise<any> { try { const updatedInfo = await super.update( loginUser, productInfo, dbTransaction, ); return updatedInfo; } catch (error) { throw error; } } public async deactivate( loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { super.deactivate(loginUser, dbTransaction); } public async verify( loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { try { await super.verify(loginUser, dbTransaction); } catch (error) { throw error; } } public async delete( loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { try { await super.delete(loginUser, dbTransaction); } catch (error) { throw error; } } public async activate( loginUser: LoginUser, dbTransaction?: any, ): Promise<void> { try { await super.activate(loginUser, dbTransaction); } catch (error) { throw error; } } static async findOne( options: any, dbTransaction?: any, ): Promise<ProductJewelleryModel> { try { //check if option string const dbOptions = typeof options !== 'string' ? options : { where: { ProductId: options, }, include: [ { model: ProductWithInventoryModel, include: [ { model: ProductModel, include: [ { model: SettingsCategoryModel, attributes: ['Code', 'Name', 'Description', 'Status'], }, { model: SettingsCollectionModel, attributes: ['Code', 'Name', 'Description', 'Status'], }, { model: SettingsGroupModel, attributes: ['Code', 'Name', 'Description', 'Status'], }, { model: ProductCertificateModel }, { model: ProductTagModel }, { model: ProductBrandModel }, { model: ProductCustomizeOptionModel }, { model: ProductMaterialModel }, { model: SettingsGroupModel, }, ], }, ], }, { model: StockProfileModel, }, ], }; return await ProductJewellery._ProductJewelleryRepository.findOne({ ...dbOptions, transaction: dbTransaction, }); } catch (error) { throw error; } } public async addVariant( addVariantInfo: IProductVariantCreate, loginUser: LoginUser, dbTransaction?: any, ) { try { const product = await ProductJewellery._Repository.findOne({ where: { SKU: addVariantInfo.SKU, }, transaction: dbTransaction, }); if (product) { throw new ClassError( 'ProductVariant', 'ProductVariantErrMsg03', 'SKU must be unique.', ); } const variant = await ProductVariantWithInventory.init(); variant.ProductId = this.ProductId; variant.Name = addVariantInfo.Name; variant.Description = addVariantInfo.Description; variant.Type = addVariantInfo.Type; variant.Level = addVariantInfo.Level; variant.StockLowAlertLevel = addVariantInfo.StockLowAlertLevel; variant.StockReorderLevel = addVariantInfo.StockReorderLevel; variant.BufferStockLevel = addVariantInfo.BufferStockLevel; await variant.setSKU(addVariantInfo.SKU); await variant.setParentId(addVariantInfo.ParentId); await variant.setColour(addVariantInfo.Colour); await variant.setSize(addVariantInfo.Size); switch (variant.Type) { case ProductVariantType.HEIGHT: await variant.setMinMax( variant.Type, addVariantInfo.MinHeight, addVariantInfo.MaxHeight, ); break; case ProductVariantType.LENGTH: await variant.setMinMax( variant.Type, addVariantInfo.MinLength, addVariantInfo.MaxLength, ); break; case ProductVariantType.WIDTH: await variant.setMinMax( variant.Type, addVariantInfo.MinWidth, addVariantInfo.MaxWidth, ); break; case ProductVariantType.WEIGHT: await variant.setMinMax( variant.Type, addVariantInfo.MinWeight, addVariantInfo.MaxWeight, ); break; default: break; } await variant.create(loginUser, dbTransaction); return { VariantId: variant.VariantId, ProductId: variant.ProductId, Name: variant.Name, Description: variant.Description, SKU: variant.SKU, Size: variant.Size, Colour: variant.Colour, Type: variant.Type, Level: variant.Level, ParentId: variant.ParentId, MinWeight: variant.MinWeight, MaxWeight: variant.MaxWeight, MinWidth: variant.MinWidth, MaxWidth: variant.MaxWidth, MinHeight: variant.MinHeight, MaxHeight: variant.MaxHeight, MinLength: variant.MinLength, MaxLength: variant.MaxLength, Status: variant.Status, CreatedById: variant.CreatedById, CreatedAt: variant.CreatedAt, UpdatedById: variant.UpdatedById, UpdatedAt: variant.UpdatedAt, UpdatedSSYN: variant.UpdatedSSYN, TotalUnitsAvailable: variant.TotalUnitsAvailable, TotalUnitsInCurrentOrder: variant.TotalUnitsInCurrentOrder, TotalUnitsSold: variant.TotalUnitsSold, TotalUnitsReserved: variant.TotalUnitsReserved, TotalUnitsInTransit: variant.TotalUnitsInTransit, TotalUnitsOnConsignment: variant.TotalUnitsOnConsignment, TotalUnitsBackOrdered: variant.TotalUnitsBackOrdered, TotalUnitsPreOrdered: variant.TotalUnitsPreOrdered, StockLowAlertLevel: variant.StockLowAlertLevel, StockReorderLevel: variant.StockReorderLevel, BufferStockLevel: variant.BufferStockLevel, }; } catch (error) { throw error; } } }