UNPKG

@tomei/sso

Version:
506 lines (469 loc) 19.1 kB
import { ClassError, ObjectBase } from '@tomei/general'; import { IUserReportingHierarchyAttr } from '../../interfaces/user-reporting-hierarchy.interface'; import { UserReportingHierarchyRepository } from './user-reporting-hierarchy.repository'; import { User } from '../login-user/user'; import { ApplicationConfig } from '@tomei/config'; import { ActionEnum, Activity } from '@tomei/activity-history'; import { Op } from 'sequelize'; export class UserReportingHierarchy extends ObjectBase implements IUserReportingHierarchyAttr { ObjectId: string; ObjectName: string; ObjectType = 'UserReportingHierarchy'; TableName = 'sso_UserReportingHierarchy'; ReportingUserId: number; UserId: number; Rank: number; Status: string; private _CreatedById: number; private _CreatedAt: Date; private _UpdatedById: number; private _UpdatedAt: Date; private static _Repo = new UserReportingHierarchyRepository(); get UserReportingHierarchyId(): number { return parseInt(this.ObjectId); } set UserReportingHierarchyId(value: number) { this.ObjectId = value.toString(); } get CreatedById(): number { return this._CreatedById; } get CreatedAt(): Date { return this._CreatedAt; } get UpdatedById(): number { return this._UpdatedById; } get UpdatedAt(): Date { return this._UpdatedAt; } private constructor(params?: IUserReportingHierarchyAttr) { super(); if (params) { this.ObjectId = params.UserReportingHierarchyId.toString(); this.ReportingUserId = params.ReportingUserId; this.UserId = params.UserId; this.Rank = params.Rank; this.Status = params.Status; this._CreatedById = params.CreatedById; this._CreatedAt = params.CreatedAt; this._UpdatedById = params.UpdatedById; this._UpdatedAt = params.UpdatedAt; } } public static async init( userReportingHierarchyId?: number, dbTransaction?: any, ): Promise<UserReportingHierarchy> { try { if (userReportingHierarchyId) { const data = await UserReportingHierarchy._Repo.findByPk( userReportingHierarchyId.toString(), dbTransaction, ); if (!data) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg01', 'UserReportingHierarchy not found', 'init', 400, ); } return new UserReportingHierarchy(data.get({ plain: true })); } return new UserReportingHierarchy(); } catch (error) { throw error; } } async createUserReportingHierarchy( loginUser: User, //The user performing the operation(typically the logged -in user). dbTransaction: any, //Database transaction object to ensure the operation is atomic. reportingUserId: number, //The ID of the user who will do the reporting. userId: number, //The Id of the user who need to be reported to. rank: number, //The rank to be assigned to the user. status: 'Active' | 'Inactive', //The initial status of relationship. ): Promise<UserReportingHierarchy> { // Returns a ReportingUserHierarchy instance representing the newly created record. try { //Creates a new User Reporting Hierarchy entry in the sso_UserReportingHierarchy table. // Privilege Checking // Call the loginUser.checkPrivileges() method by passing: // SystemCode: Retrieve from app config. // PrivilegeCode: "GROUP_REPORTING_USER_CREATE". const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'USER_REPORTING_HIERARCHY_CREATE', ); if (!isPrivileged) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg02', 'User does not have the required privileges', 'createUserReportingHierarchy', 403, ); } // Validate Input Parameters // Ensure userId exists in the sso_User table by calling the User.init() method. await User.init(dbTransaction, userId); await User.init(dbTransaction, reportingUserId); // Query the sso_UserReportingHierarchy table to see if the relationship is already defined for the user. let userReportingHierarchy = await UserReportingHierarchy._Repo.findOne({ where: { ReportingUserId: reportingUserId, UserId: userId, }, transaction: dbTransaction, }); // If the record already exists, throw an error. if (userReportingHierarchy) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg03', 'Relationship already exists', 'createUserReportingHierarchy', 400, ); } //Query the sso_UserReportingHierarchy table to see if the rank already exists for the reporting user. //If the rank already exists, throw an error indicating the rank is already exist. userReportingHierarchy = await UserReportingHierarchy._Repo.findOne({ where: { ReportingUserId: reportingUserId, Rank: rank, }, transaction: dbTransaction, }); if (userReportingHierarchy) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg04', 'Rank already exists', 'createUserReportingHierarchy', 400, ); } //Check if one rank before the new rank is not already assigned to the user, if not throw an error if (rank > 1) { const userReportingHierarchyBefore = await UserReportingHierarchy._Repo.findOne({ where: { ReportingUserId: reportingUserId, Rank: rank - 1, }, transaction: dbTransaction, }); if (!userReportingHierarchyBefore) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg05', 'Rank before the new rank is not yet assigned to the user', 'createUserReportingHierarchy', 400, ); } } // Create ReportingUserHierarchy Entry // If validation and privilege checks pass, insert a new record in the sso_UserReportingHierarchy table this.ReportingUserId = reportingUserId; this.UserId = userId; this.Rank = rank; this.Status = status; this._CreatedById = loginUser.UserId; this._CreatedAt = new Date(); this._UpdatedAt = new Date(); this._UpdatedById = loginUser.UserId; const entityValueAfter: any = { ReportingUserId: reportingUserId, UserId: userId, Rank: rank, Status: status, CreatedById: loginUser.UserId, CreatedAt: this._CreatedAt, UpdatedById: loginUser.UserId, UpdatedAt: this._UpdatedAt, }; userReportingHierarchy = await UserReportingHierarchy._Repo.create( entityValueAfter, { transaction: dbTransaction, }, ); entityValueAfter.UserReportingHierarchyId = userReportingHierarchy.UserReportingHierarchyId; // Record Create Activity // Instantiate a new activity from the Activity class, and set:\ // ActivityId: activity.createId() // Action: ActionEnum.Create // Description: Create User Reporting Hierarchy // EntityType: ReportingUserHierarchy // EntityId: newReportingUserHierarchy.ReportingUserHierarchyId // EntityValueBefore: Stringified empty object({}) // EntityValueAfter: EntityValueAfter(stringified representation of the newly created entity) const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.CREATE; activity.Description = 'Create User Reporting Hierarchy'; activity.EntityType = 'UserReportingHierarchy'; activity.EntityId = userReportingHierarchy.UserReportingHierarchyId.toString(); activity.EntityValueBefore = JSON.stringify({}); activity.EntityValueAfter = JSON.stringify(entityValueAfter); // Call the activity create() method by passing: // dbTransaction // userId: loginUser.UserId await activity.create(loginUser.ObjectId, dbTransaction); // Return the Created ReportingUserHierarchy // Return the newly created ReportingUserHierarchy instance return this; } catch (error) { throw error; } } async updateUserReportingHierarchy( loginUser: User, //The user performing the operation(typically the logged -in user). dbTransaction: any, //Database transaction object to ensure the operation is atomic. reportingUserId: number, //The ID of the user who will do the reporting. userId: number, //The ID of the user who need to be reported to. rank: number, //The rank to be assigned to the user. status: 'Active' | 'Inactive', //The initial status of the user. ): Promise<UserReportingHierarchy> { // Returns a ReportingUserHierarchy instance representing the updated record. try { //Update a User Reporting Hierarchy entry in the sso_UserReportingHierarchy table. // Validate Input Parameters // Ensure userId exists in the sso_User table by calling the User.init() method. await User.init(dbTransaction, userId); await User.init(dbTransaction, reportingUserId); // Privilege Checking // Call the loginUser.checkPrivileges() method by passing: // SystemCode: Retrieve from app config. // PrivilegeCode: "GROUP_REPORTING_USER_UPDATE". const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'USER_REPORTING_HIERARCHY_UPDATE', ); if (!isPrivileged) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg02', 'User does not have the required privileges', 'updateUserReportingHierarchy', 403, ); } // Query the sso_UserReportingHierarchy table to see if the userId already exists. const userReportingHierarchy = await UserReportingHierarchy._Repo.findOne( { where: { ReportingUserId: reportingUserId, UserId: userId, UserReportingHierarchyId: { [Op.ne]: this.UserReportingHierarchyId, }, }, transaction: dbTransaction, }, ); // If the user already exists, throw an error indicating the reporting user is already part of reporting hierarchy. if (userReportingHierarchy) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg03', 'Relationship already exists', 'updateUserReportingHierarchy', ); } //Query the sso_UserReportingHierarchy table to see if the rank already exists in the specified groupCode. //If the rank already exists, throw an error indicating the rank is already in part of reporting hierarchy. const userReportingRank = await UserReportingHierarchy._Repo.findOne({ where: { ReportingUserId: reportingUserId, Rank: rank, UserReportingHierarchyId: { [Op.ne]: this.UserReportingHierarchyId, }, }, transaction: dbTransaction, }); if (userReportingRank) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg04', 'Rank already exists', 'updateUserReportingHierarchy', ); } //Check if rank before the new rank is not already assigned to the user if (rank > 1) { const userReportingRankBefore = await UserReportingHierarchy._Repo.findOne({ where: { ReportingUserId: reportingUserId, Rank: rank - 1, UserReportingHierarchyId: { [Op.ne]: this.UserReportingHierarchyId, }, }, transaction: dbTransaction, }); if (!userReportingRankBefore) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg05', 'Rank before the new rank is not yet assigned to the user', 'updateUserReportingHierarchy', ); } } // UPDATE ReportingUserHierarchy Entry // If validation and privilege checks pass, insert a new record in the sso_UserReportingHierarchy table. const entityValueBefore: any = { UserReportingHierarchyId: this.UserReportingHierarchyId, ReportingUserId: this.ReportingUserId, UserId: this.UserId, Rank: this.Rank, Status: this.Status, CreatedById: this._CreatedById, CreatedAt: this._CreatedAt, UpdatedById: this._UpdatedById, UpdatedAt: this._UpdatedAt, }; this.ReportingUserId = reportingUserId; this.UserId = userId; this.Rank = rank; this.Status = status; this._CreatedById = this.CreatedById; this._CreatedAt = this.CreatedAt; this._UpdatedAt = new Date(); this._UpdatedById = loginUser.UserId; const entityValueAfter: any = { ReportingUserId: reportingUserId, UserId: userId, Rank: rank, Status: status, CreatedById: this.CreatedById, CreatedAt: this._CreatedAt, UpdatedById: loginUser.UserId, UpdatedAt: this._UpdatedAt, }; await UserReportingHierarchy._Repo.update(entityValueAfter, { where: { UserReportingHierarchyId: this.UserReportingHierarchyId, }, transaction: dbTransaction, }); // Record Update Activity // Instantiate a new activity from the Activity class, and set:\ // ActivityId: activity.createId() // Action: ActionEnum.Update // Description: Update User Reporting Hierarchy // EntityType: ReportingUserHierarchy // EntityId: newReportingUserHierarchy.ReportingUserHierarchyId // EntityValueBefore: Stringified empty object({}) // EntityValueAfter: EntityValueAfter(stringified representation of the newly created entity) const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.UPDATE; activity.Description = 'Update User Reporting Hierarchy'; activity.EntityType = 'UserReportingHierarchy'; activity.EntityId = this.UserReportingHierarchyId.toString(); activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); // Call the activity create() method by passing: // dbTransaction // userId: loginUser.UserId await activity.create(loginUser.ObjectId, dbTransaction); // Return the Updated ReportingUserHierarchy // Return the updated ReportingUserHierarchy instance, including all the relevant details like ReportingUserHierarchyId, groupCode, userId, rank, status, and timestamps for CreatedAt. return this; } catch (error) { throw error; } } public static async removeUserReportingHierarchy( loginUser: User, //The user performing the operation, used for privilege checking and logging. dbTransaction: any, // The database transaction object to ensure the operation's atomicity. userReportingHierarchyId: number, //The ID of the UserReportingHierarchy to be removed. ): Promise<void> { // This method removes a UserReportingHierarchy record from the database. try { // Part 1: Privilege Checking // Call loginUser.checkPrivileges() method by passing: // SystemCode: Retrieve from app config. // PrivilegeCode: "USER_REPORTING_HIERARCHY_REMOVE". const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const isPrivileged = await loginUser.checkPrivileges( systemCode, 'USER_REPORTING_HIERARCHY_REMOVE', ); if (!isPrivileged) { throw new ClassError( 'UserReportingHierarchy', 'UserReportingHierarchyErrMsg06', 'Insufficient privileges to remove reporting hierarchy', 'removeUserReportingHierarchy', 403, ); } // Part 2: Find User // Call UserReportingHierarchy.init(dbTransaction, UserReportingHierarchyId) to check if the user exists. const userReportingHierarchy = await UserReportingHierarchy.init( userReportingHierarchyId, dbTransaction, ); // Part 3: Remove User // Call UserReportingHierarchy._Repo.destroy({ where: { UserReportingHierarchyId: UserReportingHierarchyId }, transaction: dbTransaction }) to remove the user from the database. await UserReportingHierarchy._Repo.destroy( userReportingHierarchyId, dbTransaction, ); // Part 4: Record Create Activity // Initialise EntityValueBefore variable and set it to the UserReportingHierarchy instance before destruction. const entityValueBefore = { UserReportingHierarchyId: userReportingHierarchy.UserReportingHierarchyId, ReportingUserId: userReportingHierarchy.ReportingUserId, UserId: userReportingHierarchy.UserId, Rank: userReportingHierarchy.Rank, Status: userReportingHierarchy.Status, CreatedById: userReportingHierarchy.CreatedById, CreatedAt: userReportingHierarchy.CreatedAt, UpdatedById: userReportingHierarchy.UpdatedById, UpdatedAt: userReportingHierarchy.UpdatedAt, }; // Instantiate a new activity from the Activity class, and set: const activity = new Activity(); // ActivityId: activity.createId() // Action: ActionEnum.Delete // Description: Remove User Reporting Hierarchy // EntityType: UserReportingHierarchy // EntityId: userReportingHierarchyId // EntityValueBefore: Stringified representation of the UserReportingHierarchy instance before destroy // EntityValueAfter: Stringified empty object ({}) activity.ActivityId = activity.createId(); activity.Action = ActionEnum.DELETE; activity.Description = 'Remove User Reporting Hierarchy'; activity.EntityType = 'UserReportingHierarchy'; activity.EntityId = userReportingHierarchy.toString(); activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify({}); // Call the activity.create() method by passing: // dbTransaction // userId: loginUser.UserId await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } }