@tomei/rental
Version:
Tomei Rental Package
918 lines (818 loc) • 30.4 kB
text/typescript
import { ClassError, ObjectBase } from '@tomei/general';
import { RentalHirerChangeRequestRepository } from './rental-hirer-change-request.repository';
import { ApplicationConfig, ComponentConfig } from '@tomei/config';
import { LoginUser } from '@tomei/sso';
import { ActionEnum, Activity } from '@tomei/activity-history';
import { HirerChangeRequestTypeEnum } from '../../enum/rental-hirer-change-request-type';
import { HirerChangeRequestStatusEnum } from '../../enum/rental-hirer-change-request-status';
import {
IRentalHirerChangeRequestAttr,
IRentalHirerChangeRequestUpdate,
} from '../../interfaces';
import { Rental } from '../rental/rental';
import {
HirerChangeRequestHirerRoleEnum,
RentalAccountTypeEnum,
} from '../../enum';
import { Op } from 'sequelize';
import { JointHirerRepository } from '../../components/joint-hirer/joint-hirer.repository';
import { HirerChangeRequestSignatureRepository } from '../hirer-change-request-signature/hirer-change-request-signature.repository';
import { HirerChangeRequestSignature } from '../hirer-change-request-signature/hirer-change-request-signature';
import { HirerChangeRequestNewHirer } from '../hirer-change-request-new-hirer/hirer-change-request-new-hirer';
import { HirerChangeRequestRemoveHirer } from '../hirer-change-request-remove-hirer/hirer-change-request-remove-hirer';
import { JointHirer } from '../joint-hirer/joint-hirer';
export class RentalHirerChangeRequest
extends ObjectBase
implements IRentalHirerChangeRequestAttr
{
ObjectId: string;
ObjectName: string;
ObjectType: string = 'RentalHirerChangeRequest';
TableName: string = 'rental_HirerChangeRequest';
RentalId: string;
Type: HirerChangeRequestTypeEnum;
Status: HirerChangeRequestStatusEnum;
RequestedAt: Date;
RequestedById: string;
RequestingHirerId: string;
RequestingHirerType: HirerChangeRequestHirerRoleEnum;
CancelRemarks: string;
UpdatedAt: Date;
UpdatedById: string;
Signatures: HirerChangeRequestSignature[] = [];
Rental: Rental | null = null;
get RequestId(): string {
return this.ObjectId;
}
set RequestId(value: string) {
this.ObjectId = value;
}
protected static _Repository = new RentalHirerChangeRequestRepository();
protected static _HirerSignatureRepository =
new HirerChangeRequestSignatureRepository();
protected static _JointHirerRepository = new JointHirerRepository();
protected constructor(
hirerChangeRequestAttr?: IRentalHirerChangeRequestAttr,
) {
super();
if (hirerChangeRequestAttr) {
this.RequestId = hirerChangeRequestAttr.RequestId;
this.RentalId = hirerChangeRequestAttr.RentalId;
this.Type = hirerChangeRequestAttr.Type;
this.Status = hirerChangeRequestAttr.Status;
this.RequestedAt = hirerChangeRequestAttr.RequestedAt;
this.RequestedById = hirerChangeRequestAttr.RequestedById;
this.RequestingHirerId = hirerChangeRequestAttr.RequestingHirerId;
this.RequestingHirerType = hirerChangeRequestAttr.RequestingHirerType;
this.CancelRemarks = hirerChangeRequestAttr.CancelRemarks;
this.UpdatedAt = hirerChangeRequestAttr.UpdatedAt;
this.UpdatedById = hirerChangeRequestAttr.UpdatedById;
}
}
toJSON(): IRentalHirerChangeRequestAttr {
return {
RequestId: this.RequestId,
RentalId: this.RentalId,
Type: this.Type,
Status: this.Status,
RequestedAt: this.RequestedAt,
RequestedById: this.RequestedById,
RequestingHirerId: this.RequestingHirerId,
RequestingHirerType: this.RequestingHirerType,
CancelRemarks: this.CancelRemarks,
UpdatedAt: this.UpdatedAt,
UpdatedById: this.UpdatedById,
};
}
public static async init(requestId?: string, dbTransaction?: any) {
try {
if (requestId) {
const hirerChangeReq =
await RentalHirerChangeRequest._Repository.findByPk(
requestId,
dbTransaction,
);
if (hirerChangeReq) {
return new RentalHirerChangeRequest(
hirerChangeReq.get({ plain: true }),
);
} else {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg00',
'HirerChangeRequest not found',
);
}
}
return new RentalHirerChangeRequest();
} catch (error) {
console.error('Error initializing RentalHirerChangeRequest:', error);
throw error;
}
}
private async checkForDuplicate(dbTransaction: any) {
try {
if (!this.RentalId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg08',
'RentalId is required to check for duplicate requests.',
);
}
const isDuplicate = await RentalHirerChangeRequest._Repository.findAll({
where: {
RentalId: this.RentalId,
Type: this.Type,
Status: {
[Op.notIn]: [
HirerChangeRequestStatusEnum.COMPLETED,
HirerChangeRequestStatusEnum.CANCELLED,
],
},
},
transaction: dbTransaction,
});
if (isDuplicate.length > 0) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg04',
'Duplicate record detected.',
);
}
} catch (error) {
throw error;
}
}
public async getSignatures(dbTransaction: any) {
try {
if (this.Signatures.length > 0) {
return this.Signatures;
}
const hirers =
await RentalHirerChangeRequest._HirerSignatureRepository.findAll({
where: {
RequestId: this.RequestId,
},
transaction: dbTransaction,
});
this.Signatures = await Promise.all(
hirers.map(async (hirer) => {
return await HirerChangeRequestSignature.init(
hirer.SignatureId,
dbTransaction,
);
}),
);
return this.Signatures;
} catch (error) {
throw error;
}
}
private async checkIsAllSigned(dbTransaction) {
try {
const listUpdatedHirer = await this.getSignatures(dbTransaction);
if (listUpdatedHirer.length > 0) {
return listUpdatedHirer.every((record) => record.SignedAt !== null);
} else {
return false;
}
} catch (error) {
throw error;
}
}
private async create(loginUser: LoginUser, dbTransaction?: any) {
try {
// Part 1: Check Privilege
// 1.1 Make sure user got "HIRER_CHANGE_REQUEST" privilege
const systemCode =
ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'HIRER_CHANGE_REQUEST',
);
if (!isPrivileged) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg01',
"You do not have 'HIRER_CHANGE_REQUEST' privilege.",
);
}
// Part 2: Validation Rental
// 2.1 Make sure this.RentalId and this.RequestingHirerId got value.
if (!this.RentalId || !this.RequestingHirerId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg02',
'RentalId and RequestingHirerId are required.',
);
}
const rental = await Rental.init(dbTransaction, this.RentalId);
// 2.2 Only allow for joint account
if (rental.AccountType !== RentalAccountTypeEnum.JOINT) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg03',
'Only Rental with Joint Account Type Allowed.',
);
}
// 2.3 only allow for rental account where its joint hirer not maximum yet (at this step you've retrieve the number of joint hirer)
const jointHirers = await rental.getJointHirers(dbTransaction);
if (this.Type === HirerChangeRequestTypeEnum.ADD) {
const maxJointHirer = ComponentConfig.getComponentConfigValue(
'@tomei/rental',
'maxJointHirerLength',
);
if (jointHirers?.length >= maxJointHirer) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg05',
'Joint Hirer exceed max joint hirer length.',
);
}
}
// For Remove type, we don't need to check the max joint hirer length
// but we need to ensure that there is at least one joint hirer left after removal
if (
this.Type == HirerChangeRequestTypeEnum.REMOVE &&
jointHirers?.length <= 1
) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg05',
'Cannot remove the last joint hirer.',
);
}
// 2.4 avoid duplicate request, call this.checkForDuplicate() private method, this method will ensure no record with same RentalId and same Type and Status is not "Completed" or "Cancelled"
await this.checkForDuplicate(dbTransaction);
// Part 3: Create Hirer Change Request and Hirer Change Request Hirer Records
// 3.1 Set other attributes
this.ObjectId = this.createId();
this.RequestedById = loginUser.ObjectId;
this.RequestedAt = new Date();
this.UpdatedById = loginUser.ObjectId;
this.UpdatedAt = new Date();
this.Status = HirerChangeRequestStatusEnum.PENDINGSIGNATURES;
this.RequestingHirerType =
rental.CustomerId === this.RequestingHirerId
? HirerChangeRequestHirerRoleEnum.MAIN
: HirerChangeRequestHirerRoleEnum.JOINT;
// 3.2 Set Entity value after
const entityValueAfter: IRentalHirerChangeRequestAttr = {
RequestId: this.RequestId,
RentalId: this.RentalId,
Type: this.Type,
Status: this.Status,
RequestedById: this.RequestedById,
RequestedAt: this.RequestedAt,
RequestingHirerId: this.RequestingHirerId,
RequestingHirerType: this.RequestingHirerType,
CancelRemarks: this.CancelRemarks,
UpdatedById: this.UpdatedById,
UpdatedAt: this.UpdatedAt,
};
// 3.3 Call repo class create method by passing the class attributes and db transaction.
await RentalHirerChangeRequest._Repository.create(entityValueAfter, {
transaction: dbTransaction,
});
// Generate signatures, call this.generateSignature by passing:
await this.generateSignatures(loginUser, dbTransaction);
//Part 4: Record Create Hirer Change Request Activity
const activity = new Activity();
activity.ObjectId = this._createId();
activity.Action = ActionEnum.CREATE;
activity.Description =
this.Type === HirerChangeRequestTypeEnum.ADD
? 'Add New Hirer'
: 'Remove Hirer';
activity.EntityId = this.ObjectId;
activity.EntityType = this.ObjectType;
activity.EntityValueBefore = JSON.stringify({});
activity.EntityValueAfter = JSON.stringify(entityValueAfter);
await activity.create(loginUser.ObjectId, dbTransaction);
return this;
} catch (error) {
throw error;
}
}
public async update(
loginUser: LoginUser,
dbTransaction: any,
params: IRentalHirerChangeRequestUpdate,
) {
try {
// Part 1: Validation
// 1.1 Check if RequestId is not null if null return error
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg06',
'RequestId are required.',
);
}
// Part 2: Update Hirer Change Request Hirer Records
// 2.1 Set entityValueBefore
const entityValueBefore: IRentalHirerChangeRequestAttr = {
RequestId: this.RequestId,
RentalId: this.RentalId,
Type: this.Type,
Status: this.Status,
RequestedById: this.RequestedById,
RequestedAt: this.RequestedAt,
RequestingHirerId: this.RequestingHirerId,
RequestingHirerType: this.RequestingHirerType,
CancelRemarks: this.CancelRemarks,
UpdatedById: this.UpdatedById,
UpdatedAt: this.UpdatedAt,
};
// 2.2 Check if jointHirerId, customerId is null or not
let { jointHirerId, customerId } = params;
if (!customerId && !jointHirerId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg07',
'At least one of customerId or jointHirerId must be provided.',
);
}
// 2.3 Get list hirer related to request then find hirer with same CustomerId, if found update the hirer record (make it signed)
const listHirer = await this.getSignatures(dbTransaction);
if (listHirer?.length > 0) {
let foundHirer = listHirer?.find((record) => {
record.CustomerId === customerId;
});
let hirer = await HirerChangeRequestSignature.init(
foundHirer.SignatureId,
dbTransaction,
);
await hirer.update(loginUser, dbTransaction);
}
// 2.4 Check if all hirer in request is signed, if yes check request Type:
// Type = "Add" = update Request status to “AwaitingNewHirer”
// Type = "Remove" = flag the joint hirer record status to "Inactive" & update Request status to "Completed"
const isSigned = await this.checkIsAllSigned(dbTransaction);
if (isSigned) {
if (this.Type === HirerChangeRequestTypeEnum.ADD) {
this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
} else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
// TODO: Currently JointHirer dont have status props
await RentalHirerChangeRequest._JointHirerRepository.update(
{ Status: 'Inactive' },
{
where: {
HirerId: this.RequestId,
},
transaction: dbTransaction,
},
);
this.Status = HirerChangeRequestStatusEnum.COMPLETED;
}
}
// 2.5 Set entityValueAfter
const entityValueAfter: IRentalHirerChangeRequestAttr = {
RequestId: this.RequestId,
RentalId: this.RentalId,
Type: this.Type,
Status: this.Status,
RequestedById: this.RequestedById,
RequestedAt: this.RequestedAt,
RequestingHirerId: this.RequestingHirerId,
RequestingHirerType: this.RequestingHirerType,
CancelRemarks: this.CancelRemarks,
UpdatedById: this.UpdatedById,
UpdatedAt: this.UpdatedAt,
};
// 2.6 Call repo class update method by passing the class attributes and db transaction.
await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
where: {
RequestId: this.RequestId,
},
transaction: dbTransaction,
});
//Part 3: Record Create Hirer Change Request Activity
const activity = new Activity();
activity.ObjectId = this._createId();
activity.Action = ActionEnum.UPDATE;
activity.Description = 'Update Hirer Change Request';
activity.EntityId = this.ObjectId;
activity.EntityType = this.ObjectType;
activity.EntityValueBefore = JSON.stringify(entityValueBefore);
activity.EntityValueAfter = JSON.stringify(entityValueAfter);
await activity.create(loginUser.ObjectId, dbTransaction);
return this;
} catch (error) {
throw error;
}
}
public async generateSignatures(loginUser: LoginUser, dbTransaction?: any) {
try {
if (!this.RentalId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg09',
'RentalId is required to create signatures.',
);
}
// 1. If this.Rental is null, set it to Rental instantiation using this.RentalId
if (!this.Rental) {
this.Rental = await Rental.init(dbTransaction, this.RentalId);
}
// 2. Prepare all signature data (main + joint) in one go
const jointHirers = await this.Rental.getJointHirers(dbTransaction);
// Main hirer signature
const mainSignature = await HirerChangeRequestSignature.init();
mainSignature.RequestId = this.RequestId;
mainSignature.CustomerId = this.Rental.CustomerId;
mainSignature.HirerType = HirerChangeRequestHirerRoleEnum.MAIN;
mainSignature.Method = 'Upload';
// Joint hirer signatures
const jointSignaturePromises = jointHirers.map(async (jointHirer) => {
const signature = await HirerChangeRequestSignature.init();
signature.RequestId = this.RequestId;
signature.JointHirerId = jointHirer.HirerId;
signature.HirerType = HirerChangeRequestHirerRoleEnum.JOINT;
signature.Method = 'Upload';
return signature;
});
const jointSignatures = await Promise.all(jointSignaturePromises);
// 3. Create all signatures in parallel
await Promise.all([
mainSignature.create(loginUser, dbTransaction),
...jointSignatures.map((sig) => sig.create(loginUser, dbTransaction)),
]);
this.Signatures = [mainSignature, ...jointSignatures];
} catch (error) {
console.error('Error creating signatures:', error);
throw error;
}
}
public async createAddRequest(
newHirer: {
FullName: string;
IdNo: string;
IdType: string;
Email?: string;
ContactNo: string;
Relationship: string;
Address: string;
City: string;
State: string;
Postcode: string;
Country: string;
},
loginUser: LoginUser,
dbTransaction?: any,
): Promise<{
hirerChangeRequest: RentalHirerChangeRequest;
NewHirer: HirerChangeRequestNewHirer;
}> {
try {
// Validations
// 1. Make sure newHirer required fields cannot be null.
if (
!newHirer.FullName ||
!newHirer.IdNo ||
!newHirer.IdType ||
!newHirer.ContactNo ||
!newHirer.Address ||
!newHirer.City ||
!newHirer.State ||
!newHirer.Postcode ||
!newHirer.Country
) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg10',
'FullName, IdNo, IdType, ContactNo, and Address are required.',
);
}
// 2. Set this.Type to "Add".
this.Type = HirerChangeRequestTypeEnum.ADD;
// 3. Call this.create by passing:
// loginUser, dbTransaction
await this.create(loginUser, dbTransaction);
// 4. Insert into hirerChangeRequest_NewHirer
const nh = await HirerChangeRequestNewHirer.init();
nh.RequestId = this.RequestId;
nh.FullName = newHirer.FullName;
nh.Email = newHirer.Email;
nh.IdType = newHirer.IdType;
nh.IdNo = newHirer.IdNo;
nh.ContactNo = newHirer.ContactNo;
nh.Relationship = newHirer.Relationship;
nh.Address = newHirer.Address;
nh.City = newHirer.City;
nh.State = newHirer.State;
nh.Postcode = newHirer.Postcode;
nh.Country = newHirer.Country;
await nh.create(loginUser, dbTransaction);
// 5. Return HirerChangeRequest instance and NewHirer instance.
return {
hirerChangeRequest: this,
NewHirer: nh,
};
} catch (error) {
console.error('Error creating add request:', error);
throw error;
}
}
public async createRemoveRequest(
loginUser: LoginUser,
dbTransaction: any,
targetHirerId: string,
): Promise<{
hirerChangeRequest: RentalHirerChangeRequest;
RemoveHirer: HirerChangeRequestRemoveHirer;
}> {
try {
// 1. Make sure targetHirerId can be instantiated into JointHirer class (existing joint hirer)
await JointHirer.init(targetHirerId, dbTransaction);
// 2. Set this.Type to "Remove"
this.Type = HirerChangeRequestTypeEnum.REMOVE;
// 3. Call this.create() method by passing loginUser, dbTransaction
await this.create(loginUser, dbTransaction);
// 4. Insert into hirerChangeRequest_RemoveHirer
const removeHirer = await HirerChangeRequestRemoveHirer.init();
removeHirer.RequestId = this.RequestId;
removeHirer.TargetHirerId = targetHirerId;
await removeHirer.create(loginUser, dbTransaction);
// 5. Return the returned HirerChangeRequest instance and RemoveHirer instance.
return {
hirerChangeRequest: this,
RemoveHirer: removeHirer,
};
} catch (error) {
console.error('Error creating remove request:', error);
throw error;
}
}
public static async findAll(
loginUser: LoginUser,
dbTransaction: any,
rentalId: string,
): Promise<RentalHirerChangeRequest[]> {
try {
// 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
const systemCode =
ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'HIRER_CHANGE_REQUEST',
);
if (!isPrivileged) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg01',
"You do not have 'HIRER_CHANGE_REQUEST' privilege.",
);
}
// 2. Make sure rentalId not null.
if (!rentalId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg12',
'rentalId is required.',
);
}
// 3. Instantiate rental (to check rental id valid)
await Rental.init(dbTransaction, rentalId);
// 4. Call Repo.findAll({ where: { RentalId: rentalId }, transaction: dbTransaction })
const records = await RentalHirerChangeRequest._Repository.findAll({
where: { RentalId: rentalId },
transaction: dbTransaction,
});
// 5. Instantiate the returned items
const result = (records || []).map(
(rec) => new RentalHirerChangeRequest(rec.get({ plain: true })),
);
// 6. Return the instance array
return result;
} catch (error) {
console.error('Error finding all RentalHirerChangeRequest:', error);
throw error;
}
}
public async getNewHirer(
dbTransaction: any,
): Promise<HirerChangeRequestNewHirer> {
try {
// 1. Make sure this.RequestId got value.
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg13',
'RequestId is required to get new hirer.',
);
}
// 2. Call HirerChangeRequestNewHirer.findAll()
const newHirerRecords = await HirerChangeRequestNewHirer.findAll(
{
RequestId: this.RequestId,
},
dbTransaction,
);
// 3. Return the newHirer instance
return newHirerRecords[0] || null;
} catch (error) {
console.error('Error getting new hirer:', error);
throw error;
}
}
public async getRemoveHirer(
dbTransaction: any,
): Promise<HirerChangeRequestRemoveHirer> {
try {
// 1. Make sure this.RequestId got value.
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg13',
'RequestId is required to get remove hirer.',
);
}
// 2. Call HirerChangeRequestRemoveHirer.findAll()
const removeHirerRecords = await HirerChangeRequestRemoveHirer.findAll(
{
RequestId: this.RequestId,
},
dbTransaction,
);
// 3. Return the removeHirer instance
return removeHirerRecords[0] || null;
} catch (error) {
console.error('Error getting remove hirer:', error);
throw error;
}
}
public async sign(
loginUser: LoginUser,
dbTransaction: any,
signatureId: string,
): Promise<HirerChangeRequestSignature> {
try {
// 1. Make sure this.RequestId got value.
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg13',
'RequestId is required to sign signature.',
);
}
// Validate signatureId
const hcrSignature = await HirerChangeRequestSignature.init(
signatureId,
dbTransaction,
);
//Call hcrSignature.markSigned() method by passing loginUser and dbTransaction
await hcrSignature.markSigned(loginUser, dbTransaction);
// const isSigned = await this.checkIsAllSigned(dbTransaction);
// if (isSigned && this.Type === HirerChangeRequestTypeEnum.ADD) {
// this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
// this.UpdatedAt = new Date();
// this.UpdatedById = loginUser.ObjectId;
// await RentalHirerChangeRequest._Repository.update(this.toJSON(), {
// where: { RequestId: this.RequestId },
// transaction: dbTransaction,
// });
// }
return hcrSignature;
} catch (error) {
throw error;
}
}
public async complete(
loginUser: LoginUser,
dbTransaction: any,
customerId?: string,
customerType?: string,
): Promise<RentalHirerChangeRequest> {
// 1. Validations
// a. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'HIRER_CHANGE_REQUEST',
);
if (!isPrivileged) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg01',
"You do not have 'HIRER_CHANGE_REQUEST' privilege.",
);
}
// b. Make sure this.RequestId not null.
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg06',
'RequestId is required.',
);
}
// c. Make sure all signatures are signed.
const signatures = await this.getSignatures(dbTransaction);
if (!signatures.length || !signatures.every((sig) => sig.SignedAt)) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg14',
'All signatures must be signed before completing the request.',
);
}
// 2. Create/Remove Hirer
if (this.Type === HirerChangeRequestTypeEnum.ADD) {
//Make sure CustomerId is set, if not throw error
if (!customerId || !customerType) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg15',
'CustomerId and CustomerType are required for new hirer.',
);
}
// c. Create joint hirer using JointHirer.create()
const jointHirer = await JointHirer.init();
jointHirer.RentalId = this.RentalId;
jointHirer.CustomerId = customerId;
jointHirer.CustomerType = customerType;
await jointHirer.create(loginUser, dbTransaction);
} else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
// a. Get joint hirer from remove hirer request
const removeHirer = await this.getRemoveHirer(dbTransaction);
const jointHirer = await JointHirer.init(
removeHirer.TargetHirerId,
dbTransaction,
);
//Call jointHirer.remove() method by passing loginUser and dbTransaction
await jointHirer.remove(loginUser, dbTransaction);
}
// 3. Call _Repo update method
const now = new Date();
const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
this.Status = HirerChangeRequestStatusEnum.COMPLETED;
this.UpdatedAt = new Date();
this.UpdatedById = loginUser.ObjectId;
const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
where: { RequestId: this.RequestId },
transaction: dbTransaction,
});
// 4. Record activity history
const activity = new Activity();
activity.ObjectId = this._createId();
activity.Action = ActionEnum.UPDATE;
activity.Description = `Mark request as completed.`;
activity.EntityId = this.RequestId;
activity.EntityType = this.ObjectType;
activity.EntityValueBefore = JSON.stringify(entityValueBefore);
activity.EntityValueAfter = JSON.stringify(entityValueAfter);
await activity.create(loginUser.ObjectId, dbTransaction);
// 5. Return updated instance
return this;
}
public async cancel(
loginUser: LoginUser,
dbTransaction: any,
cancelRemarks: string,
): Promise<RentalHirerChangeRequest> {
// 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'HIRER_CHANGE_REQUEST',
);
if (!isPrivileged) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg01',
"You do not have 'HIRER_CHANGE_REQUEST' privilege.",
);
}
// 2. Make sure this.RequestId not null.
if (!this.RequestId) {
throw new ClassError(
'HirerChangeRequest',
'HirerChangeRequestErrMsg06',
'RequestId is required.',
);
}
// 3. Call _Repo.update() method
const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
this.Status = HirerChangeRequestStatusEnum.CANCELLED;
this.CancelRemarks = cancelRemarks;
this.UpdatedAt = new Date();
this.UpdatedById = loginUser.ObjectId;
const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
where: { RequestId: this.RequestId },
transaction: dbTransaction,
});
// 4. Record activity history
const activity = new Activity();
activity.ObjectId = this._createId();
activity.Action = ActionEnum.UPDATE;
activity.Description = `Cancel hirer change request.`;
activity.EntityId = this.RequestId;
activity.EntityType = this.ObjectType;
activity.EntityValueBefore = JSON.stringify(entityValueBefore);
activity.EntityValueAfter = JSON.stringify(entityValueAfter);
await activity.create(loginUser.ObjectId, dbTransaction);
// 5. Return updated instance
return this;
}
}