import { OrderItemBase } from '../order-item/order-item.base'; import { ServiceItemStatusEnum } from '../../enums/service-item-status.enum'; import { ServiceItemRepository } from './service-item.repository'; import { OrderItemModel } from '../../models/order-item.entity'; import { IServiceItemAttr } from '../../interfaces/service-item-attr.interface'; import { LoginUser } from '@tomei/sso'; import { ActionEnum, Activity } from '@tomei/activity-history'; import { ServiceOrder } from '../service-order/service-order'; import { ApplicationConfig, ComponentConfig } from '@tomei/config'; export class ServiceItem extends OrderItemBase { OrderNo: string; ItemType: string; Currency: string; SalePrice: number; RetailPrice: number; TaxAmount: number; TaxCode: string; TaxRate: number; SerialNo: string; BatchNo: string; Description: string; Name: string; Quantity: number; Amount: number; DueDate: Date; ServiceType: string; ServiceName: string; Remarks: string; Status: ServiceItemStatusEnum; private static _ServiceItemRepo = new ServiceItemRepository(); public constructor(serviceItemAttr?: IServiceItemAttr) { super(serviceItemAttr); if (serviceItemAttr) { this.ItemId = serviceItemAttr.ItemId; this.DueDate = serviceItemAttr.DueDate; this.ServiceType = serviceItemAttr.ServiceType; this.ServiceName = serviceItemAttr.ServiceName; this.Remarks = serviceItemAttr.Remarks; this.Status = serviceItemAttr.Status; this.OrderNo = serviceItemAttr.OrderNo; this.ItemType = serviceItemAttr.ItemType; this.Currency = serviceItemAttr.Currency; this.SalePrice = serviceItemAttr.SalePrice; this.RetailPrice = serviceItemAttr.RetailPrice; this.TaxAmount = serviceItemAttr.TaxAmount; this.TaxCode = serviceItemAttr.TaxCode; this.TaxRate = serviceItemAttr.TaxRate; this.SerialNo = serviceItemAttr.SerialNo; this.BatchNo = serviceItemAttr.BatchNo; this.Description = serviceItemAttr.Description; this.Name = serviceItemAttr.Name; this.Quantity = serviceItemAttr.Quantity; } } public static async init(ItemId?: string, dbTransaction?: any) { if (ItemId) { const storeData = await ServiceItem._ServiceItemRepo.findByPk(ItemId, { transaction: dbTransaction, include: [ { model: OrderItemModel, }, ], }); if (storeData) { return new ServiceItem({ ...storeData?.get({ plain: true }), ...storeData.OrderItem?.get({ plain: true }), }); } else { throw Error('ServiceItem not found.'); } } return new ServiceItem(); } public async create(loginUser: LoginUser, dbTransaction: any): Promise { // This method will create a new service item and order item data. try { // Part 1: Create Order Item // Call the parent create method to create a new order item. await super.create(loginUser, dbTransaction); //Part 2: Create Service Item //Set status to 'Pending' this.Status = ServiceItemStatusEnum.PENDING; //Set EntityValueAfter with the new service item properties const entityValueAfter = { ItemId: this.ItemId, DueDate: this.DueDate, ServiceType: this.ServiceType, ServiceName: this.ServiceName, Remarks: this.Remarks, Status: this.Status, }; // Call the repository create method to create a new service item. await ServiceItem._ServiceItemRepo.create(entityValueAfter, { transaction: dbTransaction, }); } catch (error) { throw error; } } async update(loginUser: LoginUser, dbTransaction: any): Promise { // This method will update the service item and order item data. try { // Part 1: Update Order Item // Call the parent update method to update the order item. await super.update(loginUser, dbTransaction); // Part 2: Update Service Item // Retrieve the old service item data const oldServiceItem = await ServiceItem._ServiceItemRepo.findByPk( this.ItemId, { transaction: dbTransaction, }, ); // Set EntityValueBefore with the new service item properties const entityValueBefore = oldServiceItem.get({ plain: true }); const payload = { DueDate: this.DueDate, ServiceType: this.ServiceType, ServiceName: this.ServiceName, Remarks: this.Remarks, Status: this.Status, }; // Call the repository update method to update the service item. await ServiceItem._ServiceItemRepo.update(payload, { where: { ItemId: this.ItemId }, transaction: dbTransaction, }); //Create EntityValueAfter with the updated service item properties const entityValueAfter = { ItemId: this.ItemId, ...payload, }; const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.UPDATE; activity.Description = `Update Service Item ${this.ItemId}`; activity.EntityId = this.ItemId; activity.EntityType = 'ServiceItem'; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } async setInProgress(loginUser: LoginUser, dbTransaction: any): Promise { // This method will update the service item status to 'In Progress'. try { this.Status = ServiceItemStatusEnum.IN_PROGRESS; // Retrieve the old service item data const oldServiceItem = await ServiceItem._ServiceItemRepo.findByPk( this.ItemId, { transaction: dbTransaction, }, ); // Set EntityValueBefore with the new service item properties const entityValueBefore = oldServiceItem.get({ plain: true }); // Call the repository update method to update the service item status. await ServiceItem._ServiceItemRepo.update( { Status: this.Status }, { where: { ItemId: this.ItemId }, transaction: dbTransaction, }, ); // Create EntityValueAfter with the updated service item properties const entityValueAfter = { ...entityValueBefore, ItemId: this.ItemId, Status: this.Status, }; //Update the service order tally const serviceOrder = await ServiceOrder.init(this.OrderNo, dbTransaction); await serviceOrder.markItemInProgress(loginUser, dbTransaction); const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.UPDATE; activity.Description = `Set Service Item ${this.ItemId} to 'In Progress'`; activity.EntityId = this.ItemId; activity.EntityType = 'ServiceItem'; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } async setCompleted(loginUser: LoginUser, dbTransaction: any): Promise { // This method will update the service item status to 'Completed'. try { this.Status = ServiceItemStatusEnum.COMPLETED; // Retrieve the old service item data const oldServiceItem = await ServiceItem._ServiceItemRepo.findByPk( this.ItemId, { transaction: dbTransaction, }, ); // Set EntityValueBefore with the new service item properties const entityValueBefore = oldServiceItem.get({ plain: true }); // Call the repository update method to update the service item status. await ServiceItem._ServiceItemRepo.update( { Status: this.Status }, { where: { ItemId: this.ItemId }, transaction: dbTransaction, }, ); // Create EntityValueAfter with the updated service item properties const entityValueAfter = { ItemId: this.ItemId, Status: this.Status, }; //Update the service order tally const serviceOrder = await ServiceOrder.init(this.OrderNo, dbTransaction); await serviceOrder.markItemDone(loginUser, dbTransaction); const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.UPDATE; activity.Description = `Set Service Item ${this.ItemId} to 'Completed'`; activity.EntityId = this.ItemId; activity.EntityType = 'ServiceItem'; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } static async findByServiceType( serviceType: string, loginUser: LoginUser, dbTransaction?: any, ) { try { const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrevileged = await loginUser.checkPrivileges( systemCode, 'ORDER_VIEW', ); if (!isPrevileged) { throw new Error( 'You do not have the required privileges to view this data.', ); } const serviceItems = await ServiceItem._ServiceItemRepo.findAll({ where: { ServiceType: serviceType }, transaction: dbTransaction, }); if (serviceItems.length === 0) { return null; } return serviceItems.map((serviceItem) => { return new ServiceItem(serviceItem.get({ plain: true })); }); } catch (error) { throw error; } } }