diff --git a/Areas/OTcalculate/Controllers/HodDashboardController.cs b/Areas/OTcalculate/Controllers/HodDashboardController.cs index 0f1f920..ff10d85 100644 --- a/Areas/OTcalculate/Controllers/HodDashboardController.cs +++ b/Areas/OTcalculate/Controllers/HodDashboardController.cs @@ -12,9 +12,9 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers { [Area("OTcalculate")] [Authorize] - public class HodDashboardController : Controller + public class HouDashboardController : Controller { - public IActionResult HodApproval() + public IActionResult HouApproval() { return View(); } diff --git a/Areas/OTcalculate/Controllers/HouDashboardController.cs b/Areas/OTcalculate/Controllers/HouDashboardController.cs new file mode 100644 index 0000000..0f1f920 --- /dev/null +++ b/Areas/OTcalculate/Controllers/HouDashboardController.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using PSTW_CentralSystem.Areas.OTcalculate.Models; +using PSTW_CentralSystem.DBContext; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers +{ + [Area("OTcalculate")] + [Authorize] + public class HodDashboardController : Controller + { + public IActionResult HodApproval() + { + return View(); + } + public IActionResult OtReview() + { + return View(); + } + } +} diff --git a/Areas/OTcalculate/Controllers/OvertimeController.cs b/Areas/OTcalculate/Controllers/OvertimeController.cs index c5596ae..1b3b5d4 100644 --- a/Areas/OTcalculate/Controllers/OvertimeController.cs +++ b/Areas/OTcalculate/Controllers/OvertimeController.cs @@ -20,7 +20,7 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers return View(); } - public IActionResult OtSTatus() + public IActionResult OtStatus() { return View(); } diff --git a/Areas/OTcalculate/Services/OvertimePdfService.cs b/Areas/OTcalculate/Services/OvertimePdfService.cs index 173b241..6f54e82 100644 --- a/Areas/OTcalculate/Services/OvertimePdfService.cs +++ b/Areas/OTcalculate/Services/OvertimePdfService.cs @@ -62,6 +62,7 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Services { table.ColumnsDefinition(columns => { + columns.RelativeColumn(0.7f); // Days columns.RelativeColumn(1.1f); // Date columns.RelativeColumn(0.8f); // Office From columns.RelativeColumn(0.8f); // Office To @@ -74,13 +75,13 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Services columns.RelativeColumn(); // Net OT if (departmentId == 2) columns.RelativeColumn(); // Station - columns.RelativeColumn(0.9f); // Day Type columns.RelativeColumn(2.7f); // Description }); table.Header(header => { // Row 1 — grouped headers + header.Cell().RowSpan(2).Background("#e0f7da").Border(0.25f).Padding(5).Text("Days").FontSize(9).Bold().AlignCenter(); header.Cell().RowSpan(2).Background("#d0ead2").Border(0.25f).Padding(5).Text("Date").FontSize(9).Bold().AlignCenter(); header.Cell().ColumnSpan(3).Background("#dceefb").Border(0.25f).Padding(5).Text("Office Hours\n(8:30 - 17:30)").FontSize(9).Bold().AlignCenter(); @@ -93,17 +94,17 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Services if (departmentId == 2) header.Cell().RowSpan(2).Background("#d0f0ef").Border(0.25f).Padding(5).Text("Station").FontSize(9).Bold().AlignCenter(); - header.Cell().RowSpan(2).Background("#e0f7da").Border(0.25f).Padding(5).Text("Days").FontSize(9).Bold().AlignCenter(); header.Cell().RowSpan(2).Background("#e3f2fd").Border(0.25f).Padding(5).Text("Description").FontSize(9).Bold().AlignCenter(); + // Row 2 — subheaders only for grouped columns header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("From").FontSize(9).Bold().AlignCenter(); header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("To").FontSize(9).Bold().AlignCenter(); - header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("Break").FontSize(9).Bold().AlignCenter(); + header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("Break (min)").FontSize(9).Bold().AlignCenter(); header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("From").FontSize(9).Bold().AlignCenter(); header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("To").FontSize(9).Bold().AlignCenter(); - header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("Break").FontSize(9).Bold().AlignCenter(); + header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("Break (min)").FontSize(9).Bold().AlignCenter(); }); @@ -128,44 +129,55 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Services } else { - foreach (var r in records) + var groupedRecords = records.GroupBy(r => r.OtDate.Date); + + foreach (var group in groupedRecords) { - var totalOT = CalculateTotalOT(r); - var totalBreak = (r.OfficeBreak ?? 0) + (r.AfterBreak ?? 0); - var netOT = totalOT - TimeSpan.FromMinutes(totalBreak); + bool isFirstRow = true; - totalOTSum += totalOT.TotalHours; - totalBreakSum += totalBreak; - totalNetOt += netOT; - - string rowBg = alternate ? "#f9f9f9" : "#ffffff"; - alternate = !alternate; - - void AddCell(string value, bool alignLeft = false) + foreach (var r in group) { - var text = table.Cell().Background(rowBg).Border(0.25f).Padding(5).Text(value).FontSize(9); - if (alignLeft) - text.AlignLeft(); - else - text.AlignCenter(); - } + var totalOT = CalculateTotalOT(r); + var totalBreak = (r.OfficeBreak ?? 0) + (r.AfterBreak ?? 0); + var netOT = totalOT - TimeSpan.FromMinutes(totalBreak); - AddCell(r.OtDate.ToString("dd/MM/yyyy")); - AddCell(FormatTime(r.OfficeFrom)); - AddCell(FormatTime(r.OfficeTo)); - AddCell($"{r.OfficeBreak ?? 0} min"); - AddCell(FormatTime(r.AfterFrom)); - AddCell(FormatTime(r.AfterTo)); - AddCell($"{r.AfterBreak ?? 0} min"); - AddCell($"{(int)totalOT.TotalHours} hr {totalOT.Minutes} min"); - AddCell($"{totalBreak}"); - AddCell($"{netOT.Hours} hr {netOT.Minutes} min"); - if (departmentId == 2) - AddCell(r.Stations?.StationName ?? "N/A"); - AddCell(r.OtDays); - table.Cell().Background(rowBg).Border(0.25f).Padding(5).Text(r.OtDescription ?? "-").FontSize(9).WrapAnywhere().LineHeight(1.2f); + totalOTSum += totalOT.TotalHours; + totalBreakSum += totalBreak; + totalNetOt += netOT; + + string rowBg = alternate ? "#f9f9f9" : "#ffffff"; + alternate = !alternate; + + void AddCell(string value, bool alignLeft = false) + { + var text = table.Cell().Background(rowBg).Border(0.25f).Padding(5).Text(value).FontSize(9); + if (alignLeft) + text.AlignLeft(); + else + text.AlignCenter(); + } + + AddCell(isFirstRow ? $"{r.OtDate:ddd}" : ""); + AddCell(isFirstRow ? r.OtDate.ToString("dd/MM/yyyy") : ""); + + AddCell(FormatTime(r.OfficeFrom)); + AddCell(FormatTime(r.OfficeTo)); + AddCell($"{r.OfficeBreak ?? 0}"); + AddCell(FormatTime(r.AfterFrom)); + AddCell(FormatTime(r.AfterTo)); + AddCell($"{r.AfterBreak ?? 0}"); + AddCell($"{(int)totalOT.TotalHours} hr {totalOT.Minutes} min"); + AddCell($"{totalBreak}"); + AddCell($"{netOT.Hours} hr {netOT.Minutes} min"); + if (departmentId == 2) + AddCell(r.Stations?.StationName ?? "N/A"); + table.Cell().Background(rowBg).Border(0.25f).Padding(5).Text(r.OtDescription ?? "-").FontSize(9).WrapAnywhere().LineHeight(1.2f); + + isFirstRow = false; + } } + var totalOTTimeSpan = TimeSpan.FromHours(totalOTSum); var totalBreakTimeSpan = TimeSpan.FromMinutes(totalBreakSum); diff --git a/Areas/OTcalculate/Views/HouDashboard/HouApproval.cshtml b/Areas/OTcalculate/Views/HouDashboard/HouApproval.cshtml new file mode 100644 index 0000000..0cc15d5 --- /dev/null +++ b/Areas/OTcalculate/Views/HouDashboard/HouApproval.cshtml @@ -0,0 +1,5 @@ +@{ + ViewData["Title"] = "Overtime Approval"; + Layout = "~/Views/Shared/_Layout.cshtml"; +} + diff --git a/Areas/OTcalculate/Views/HouDashboard/OtReview.cshtml b/Areas/OTcalculate/Views/HouDashboard/OtReview.cshtml new file mode 100644 index 0000000..6693b41 --- /dev/null +++ b/Areas/OTcalculate/Views/HouDashboard/OtReview.cshtml @@ -0,0 +1,169 @@ +@{ + ViewData["Title"] = "Overtime Review"; + Layout = "~/Views/Shared/_Layout.cshtml"; +} + +
| {{ formatDate(record.otDate) }} | +{{ formatTime(record.officeFrom) }} | +{{ formatTime(record.officeTo) }} | +{{ record.officeBreak }} min | +{{ formatTime(record.afterFrom) }} | +{{ formatTime(record.afterTo) }} | +{{ record.afterBreak }} min | +{{ formatHourMinute(calcTotalTime(record)) }} | +{{ calcBreakTotal(record) }} | +{{ formatHourMinute(calcNetHours(record)) }} | +{{ record.stationName || 'N/A' }} | +{{ record.otDays}} | +
+
+ {{ record.otDescription }}
+
+ |
+ + + + + + + - + | ++ + + | +
| No overtime records found for this user and period. | +||||||||||||||
| TOTAL | ++ | {{ formatHourMinute(totalHours) }} | +{{ formatHourMinute(totalBreak) }} | +{{ formatHourMinute(totalNetTime) }} | ++ | + | ||||||||
| Date | Office Hour (8:30 - 17:30) |
After Office Hour (17:30 - 8:30) |
Total OT Hours | -Break Hours (min) | +Break (min) | Net OT Hours | Station | -Days | +Days | Description | -Action | +Action | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| From | @@ -128,24 +119,23 @@{{ calcBreakTotal(record) }} | {{ formatHourMinute(calcNetHours(record)) }} | {{ record.stationName || 'N/A' }} | -{{ record.otDays}} | +{{ record.otDays }} |
{{ record.otDescription }}
|
- - | |||||||||
| No records found for selected month and year. | +No records found. | |||||||||||||||
| TOTAL | @@ -161,49 +151,22 @@||||||||||||||||
| Month | -Year | -Submitted On | -HOD Status | -HR Status | -Details | -
|---|---|---|---|---|---|
| {{ getMonthName(status.month) }} | -{{ status.year }} | -{{ formatDate(status.submitDate) }} | -{{ status.hodStatus }} | -{{ status.hrStatus }} | -
- |
-
HOD Updates:
-HR Updates:
-