message:`You've been invited to "${dto.title}" on ${newDate(dto.meetingDate).toLocaleDateString('en-US')} at ${startTime.toLocaleTimeString('en-US',{hour:'2-digit',minute:'2-digit'})}.${dto.location?` Location: ${dto.location}`:''}`,
actionUrl:'/meetings',
entityType:'meeting',
entityId:meeting.id,
});
}catch{/* non-critical */}
}
this.logger.log(`Meeting "${dto.title}" created by ${currentUser.email} with ${dto.inviteeIds.length} invitees`);
title:`Review Actual Salary: ${request.user.firstName}${request.user.lastName}`,
message:`Schedule change approved for ${request.user.firstName}${request.user.lastName}. Base salary changed from ${request.currentBaseSalaryPiasters} to ${request.proposedBaseSalaryPiasters} piasters. Review and update Actual Salary if needed.`,
actionUrl:`/admin/contractors/${request.userId}`,
});
}catch{/* non-critical */}
}
}else{
try{
awaitthis.notificationsService.create({
userId:request.userId,
type:'IMPORTANT',
category:'SYSTEM',
title:'Schedule Change Rejected',
message:`Your schedule change request was rejected. Reason: ${dto.rejectionReason}`,
entityType:'scheduleChangeRequest',
entityId:id,
});
}catch{/* non-critical */}
}
this.logger.log(`Schedule change request ${id}${dto.decision} by ${currentUser.email}`);
returnupdated;
}
asyncdirectEdit(
userId:string,
newSchedule:Record<string,string>,
currentUser:RequestUser,
):Promise<any>{
if(currentUser.role!=='SUPER_ADMIN'){
thrownewForbiddenException('Only Super Admin can directly edit schedules');
}
constuser=awaitthis.prisma.user.findFirst({
where:{id:userId,deletedAt:null},
});
if(!user)thrownewNotFoundException('User not found');