Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HRIS - 429] - [BUGTASK] When Approving or Disapproving an Overtime Request as a Manager, it does not update the Overtime Request status to approved/disapproved and also in the User My DTR the Status of Overtime is not updated. #338

Merged
merged 4 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions api/NotificationDataClasses/OvertimeData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ public class OvertimeData
public string Type { get; set; } = default!;
public string Status { get; set; } = default!;
public string? Remarks { get; set; } = default!;

public bool? IsManagerApproved { get; set; }
public bool? IsLeaderApproved { get; set; }

public string? OvertimeId { get; set; }
}

public class OvertimeManagerData : OvertimeData
Expand Down
5 changes: 5 additions & 0 deletions api/Schema/Queries/OvertimeQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
return await _overtimeService.GetOvertime(UserId);
}

public async Task<DTOs.MyOvertimeDTO> GetOvertimeById(int id)
{
return await _overtimeService.GetOvertimeById(id);

Check warning on line 20 in api/Schema/Queries/OvertimeQuery.cs

View workflow job for this annotation

GitHub Actions / Build Backend

Possible null reference return.

Check warning on line 20 in api/Schema/Queries/OvertimeQuery.cs

View workflow job for this annotation

GitHub Actions / Build Backend

Possible null reference return.
}

public async Task<List<DTOs.OvertimeDTO>> GetAllOvertime()
{
return await _overtimeService.Index();
Expand Down
200 changes: 116 additions & 84 deletions api/Services/ApprovalService.cs

Large diffs are not rendered by default.

54 changes: 44 additions & 10 deletions api/Services/NotificationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ public async Task<List<OvertimeNotification>> createOvertimeNotification(Overtim
DateFiled = (DateTime)overtime.CreatedAt!,
Type = NotificationDataTypeEnum.REQUEST,
Status = _overtimeService.GetOvertimeRequestStatus(overtime),
Remarks = overtime.Remarks
Remarks = overtime.Remarks,
IsLeaderApproved = overtime.IsLeaderApproved,
IsManagerApproved = overtime.IsManagerApproved,
OvertimeId = overtime.Id.ToString()
}
);

Expand Down Expand Up @@ -196,7 +199,11 @@ public async Task<List<OvertimeNotification>> createOvertimeNotification(Overtim
DateFiled = (DateTime)overtime.CreatedAt,
Type = NotificationDataTypeEnum.REQUEST,
Status = _overtimeService.GetOvertimeRequestStatus(overtime),
Remarks = overtime.Remarks
Remarks = overtime.Remarks,
IsLeaderApproved = overtime.IsLeaderApproved,
IsManagerApproved = overtime.IsManagerApproved,
OvertimeId = overtime.Id.ToString()
// TODO: create the part when either the manager/leader disapproves, it will update so that the other can't update
}
);

Expand Down Expand Up @@ -582,33 +589,60 @@ public async Task<LeaveNotification> createLeaveApproveDisapproveNotification(Le
}
}

public async Task<OvertimeNotification> createOvertimeApproveDisapproveNotification(Overtime overtime, int fromUserId, bool IsApproved)
public async Task<OvertimeNotification> CreateOvertimeApproveDisapproveNotification(Overtime overtime, int fromUserId, bool IsApproved)
{
using (HrisContext context = _contextFactory.CreateDbContext())
{
//for time entries
var timeEntry = context.TimeEntries.Find(overtime.TimeEntryId);
//from the time entry, get the time in and time out
var timeInEntry = timeEntry?.EndTime + TimeSpan.FromHours(1);
var timeOutEntry = context.Times.Find(timeEntry?.TimeOutId);

var timeIn = timeInEntry?.ToString(@"hh\:mm");
var timeOut = timeOutEntry?.TimeHour.ToString(@"hh\:mm");

var managerStatus = overtime.IsManagerApproved switch
{
true => RequestStatus.APPROVED,
false => RequestStatus.DISAPPROVED,
null => RequestStatus.PENDING // if IsManagerApproved is nullable
};

var leaderStatus = overtime.IsLeaderApproved switch
{
true => RequestStatus.APPROVED,
false => RequestStatus.DISAPPROVED,
null => RequestStatus.PENDING // if IsLeaderApproved is nullable
};

var user = context.Users.Find(fromUserId);
var projectNames = context.MultiProjects.Where(x => x.OvertimeId == overtime.Id && x.Type == MultiProjectTypeEnum.OVERTIME).Select(x => x.ProjectId == ProjectId.OTHER_PROJECT ? overtime.OtherProject : x.Project.Name);
var dataToUser = JsonSerializer.Serialize(new
{
User = new
{
Id = user?.Id,
Id = user?.Id, // Explicitly naming the properties
Name = user?.Name,
AvatarLink = _userService.GenerateAvatarLink(user?.ProfileImageId ?? default(int))
},
Projects = projectNames,
RequestedMinutes = overtime.RequestedMinutes,
Projects = projectNames, // This one is fine because it's already a named property
RequestedMinutes = overtime.RequestedMinutes, // Explicitly naming the properties
DateRequested = overtime.OvertimeDate,
ApprovedMinutes = overtime.ApprovedMinutes,
DateFiled = overtime.CreatedAt,
Type = IsApproved ? NotificationDataTypeEnum.APPROVE : NotificationDataTypeEnum.DISAPPROVE,
Status = IsApproved ? RequestStatus.APPROVED : RequestStatus.DISAPPROVED,
Remarks = overtime.Remarks,
ManagerRemarks = overtime.ManagerRemarks,
RequestedTimeIn = overtime.TimeEntry.TimeIn!.TimeHour.ToString(@"hh\:mm"),
RequestedTimeOut = overtime.TimeEntry.TimeOut!.TimeHour.ToString(@"hh\:mm")
}
);
RequestedTimeIn = timeIn,
RequestedTimeOut = timeOut,
Duration = overtime.RequestedMinutes,
ManagerApproveStatus = managerStatus,
LeaderApproveStatus = leaderStatus,

});


// Notification to Requesting User
var notificationToUser = new OvertimeNotification
Expand Down
20 changes: 20 additions & 0 deletions api/Services/OvertimeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@ public async Task<List<MyOvertimeDTO>> GetOvertime(int UserId)
.ToListAsync();
}
}

public async Task<MyOvertimeDTO?> GetOvertimeById(int id)
{
using (HrisContext context = _contextFactory.CreateDbContext())
{
// Find the Overtime entity by ID and return a single DTO object
return await context.Overtimes
.Include(x => x.MultiProjects)
.ThenInclude(x => x.Project)
.Include(x => x.MultiProjects)
.ThenInclude(x => x.ProjectLeader)
.Include(x => x.Manager)
.ThenInclude(x => x.Role)
.Where(w => w.Id == id)
.OrderByDescending(x => x.CreatedAt)
.Select(x => new MyOvertimeDTO(x))
.SingleOrDefaultAsync(); // Use SingleOrDefaultAsync to return a single MyOvertimeDTO or null
}
}

public async Task<List<OvertimeDTO>> Index()
{
var domain = _httpService.getDomainURL();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import moment from 'moment'
import React, { FC } from 'react'
import React, { FC, useEffect, useState } from 'react'

import { INotification } from '~/utils/interfaces'
import RequestStatusChip from '~/components/atoms/RequestStatusChip'
import { useGetOvertimeById } from '~/hooks/useOvertimeQuery'

type Props = {
notification: INotification
}

const OvertimeDetails: FC<Props> = ({ notification }): JSX.Element => {
const { project, date, duration, dateFiled, status, remarks } = notification
const { project, date, duration, dateFiled, remarks } = notification

const [overtimeId, setOvertimeId] = useState<number | null>(null) // Ensure the type is clear and initialized correctly
useEffect(() => {
if (notification.overtimeId !== undefined) {
setOvertimeId(parseInt(notification.overtimeId))
}
}, [notification.overtimeId])

const { data } = useGetOvertimeById(overtimeId ?? 0) // Fallback to 0 if overtimeId is null

const overtime = data?.overtimeById

let managerApprovalState = 'Pending'
if (overtime?.isManagerApproved === true) {
managerApprovalState = 'Approved'
} else if (overtime?.isManagerApproved === false) {
managerApprovalState = 'Disapproved'
}

return (
<>
Expand All @@ -32,9 +51,13 @@ const OvertimeDetails: FC<Props> = ({ notification }): JSX.Element => {
{moment(new Date(dateFiled)).fromNow()}
</span>
</li>
<li className="inline-flex items-center space-x-3 pt-2">
{/* <li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Status: </span>
<RequestStatusChip label={status.toLocaleLowerCase()} />
</li> */}
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Manager Status: </span>
<RequestStatusChip label={managerApprovalState.toLocaleLowerCase()} />
</li>
<li className="inline-flex flex-col space-y-2 pt-2">
<span className="text-slate-600">Remarks: </span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,27 @@ type Props = {
const OvertimeResolvedDetails: FC<Props> = ({ notification }): JSX.Element => {
const {
date,
status,
project,
remarks,
duration,
dateFiled,
managerRemarks,
requestedTimeIn,
requestedTimeOut
requestedTimeOut,
managerApproveStatus,
leaderApproveStatus
} = notification

let manager = ''
if (managerApproveStatus != null) {
manager = managerApproveStatus.toLowerCase()
}

let leader = ''
if (leaderApproveStatus != null) {
leader = leaderApproveStatus.toLowerCase()
}

return (
<>
<li className="inline-flex items-center space-x-3">
Expand All @@ -33,7 +44,9 @@ const OvertimeResolvedDetails: FC<Props> = ({ notification }): JSX.Element => {
</li>
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Duration: </span>
<span className="flex items-center font-medium">{duration}</span>
<span className="flex items-center font-medium">
{duration !== null && duration !== undefined ? `${duration} mins` : '---'}
</span>
</li>
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Time In: </span>
Expand All @@ -46,16 +59,20 @@ const OvertimeResolvedDetails: FC<Props> = ({ notification }): JSX.Element => {
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Date Filed: </span>
<span className="flex items-center font-medium">
{moment(new Date(dateFiled)).format('MMM DD, YYYY')} &bull; {``}
{moment(new Date(dateFiled)).format('MMM DD, YYYY')} &bull;{' '}
{moment(new Date(dateFiled)).fromNow()}
</span>
</li>
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Status: </span>
<RequestStatusChip label={status.toLocaleLowerCase()} />
<span className="text-slate-600">Leader Status: </span>
<RequestStatusChip label={leader} />
</li>
<li className="inline-flex items-center space-x-3 pt-2">
<span className="text-slate-600">Manager Status: </span>
<RequestStatusChip label={manager} />
</li>
<li className="inline-flex flex-col space-y-2 pt-2">
<span className="text-slate-600">Manager Remarks: </span>
<span className="text-slate-600">Manager&apos;s Remarks: </span>
<span className="font-medium">{managerRemarks}</span>
</li>
<li className="inline-flex flex-col space-y-2 pt-2">
Expand Down
Loading
Loading