PSTW_CentralizeSystem/Areas/OTcalculate/Services/OvertimeExcelService.cs
2025-04-29 17:19:25 +08:00

168 lines
7.3 KiB
C#

using ClosedXML.Excel;
using System.IO;
using PSTW_CentralSystem.Models;
using PSTW_CentralSystem.Areas.OTcalculate.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PSTW_CentralSystem.Areas.OTcalculate.Services
{
public class OvertimeExcelService
{
public MemoryStream GenerateOvertimeExcel(
List<OtRegisterModel> records,
int departmentId,
string userFullName,
string departmentName,
int userStateId,
int weekendId,
List<CalendarModel> publicHolidays,
bool isAdminUser = false,
byte[]? logoImage = null // This parameter is missing in the call
)
{
var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Overtime Records");
int currentRow = 1;
// Add Header Information
if (!string.IsNullOrEmpty(userFullName))
{
worksheet.Cell(currentRow, 1).Value = $"Name: {userFullName}";
currentRow++;
}
if (!string.IsNullOrEmpty(departmentName))
{
worksheet.Cell(currentRow, 1).Value = $"Department: {departmentName}";
currentRow++;
}
currentRow++; // Add an empty row after header
// Header titles
var headers = new List<string>
{
"Day", "Date", "Office From", "Office To", "Office Break",
"After From", "After To", "After Break",
"Total OT", "Break Minutes", "Net OT"
};
if (departmentId == 2 || isAdminUser)
headers.Add("Station");
headers.Add("Description");
// Set header row
int headerRow = currentRow;
for (int i = 0; i < headers.Count; i++)
{
var cell = worksheet.Cell(headerRow, i + 1);
cell.Value = headers[i];
cell.Style.Font.Bold = true;
cell.Style.Fill.BackgroundColor = XLColor.LightGray;
cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
cell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
cell.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
}
currentRow++;
// Fill data rows
foreach (var r in records)
{
TimeSpan totalOT = CalculateTotalOT(r);
int totalBreak = (r.OfficeBreak ?? 0) + (r.AfterBreak ?? 0);
TimeSpan netOT = totalOT - TimeSpan.FromMinutes(totalBreak);
int col = 1;
var dayCell = worksheet.Cell(currentRow, col++);
dayCell.Value = r.OtDate.ToString("ddd");
dayCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
dayCell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
dayCell.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
var dateCell = worksheet.Cell(currentRow, col++);
dateCell.Value = r.OtDate.ToString("yyyy-MM-dd");
dateCell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
dateCell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
dateCell.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
// Apply background color for weekends and public holidays
var dayOfWeek = r.OtDate.DayOfWeek;
bool isWeekend = (weekendId == 1 && (dayOfWeek == DayOfWeek.Friday || dayOfWeek == DayOfWeek.Saturday)) ||
(weekendId == 2 && (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday));
bool isPublicHoliday = publicHolidays.Any(h => h.HolidayDate.Date == r.OtDate.Date);
if (isPublicHoliday)
{
dayCell.Style.Fill.BackgroundColor = XLColor.Pink;
dateCell.Style.Fill.BackgroundColor = XLColor.Pink;
}
else if (isWeekend)
{
dayCell.Style.Fill.BackgroundColor = XLColor.LightBlue;
dateCell.Style.Fill.BackgroundColor = XLColor.LightBlue;
}
worksheet.Cell(currentRow, col++).Value = FormatTime(r.OfficeFrom);
worksheet.Cell(currentRow, col++).Value = FormatTime(r.OfficeTo);
worksheet.Cell(currentRow, col++).Value = r.OfficeBreak;
worksheet.Cell(currentRow, col++).Value = FormatTime(r.AfterFrom);
worksheet.Cell(currentRow, col++).Value = FormatTime(r.AfterTo);
worksheet.Cell(currentRow, col++).Value = r.AfterBreak;
worksheet.Cell(currentRow, col++).Value = totalOT.ToString(@"hh\:mm");
worksheet.Cell(currentRow, col++).Value = totalBreak;
worksheet.Cell(currentRow, col++).Value = netOT.ToString(@"hh\:mm");
if (departmentId == 2 || isAdminUser)
worksheet.Cell(currentRow, col++).Value = r.Stations?.StationName ?? "";
worksheet.Cell(currentRow, col++).Value = r.OtDescription ?? "";
// Apply border and alignment for the rest of the row
for (int i = headers.IndexOf("Office From") + 1; i <= headers.Count; i++)
{
var cell = worksheet.Cell(currentRow, i);
cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
cell.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
cell.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
}
currentRow++;
}
// Add Total row
int totalRow = currentRow;
worksheet.Cell(totalRow, 1).Value = "TOTAL";
worksheet.Cell(totalRow, 1).Style.Font.Bold = true;
worksheet.Cell(totalRow, headers.IndexOf("Total OT") + 1).Value = $"=SUM(I{headerRow + 1}:I{totalRow - 1})";
worksheet.Cell(totalRow, headers.IndexOf("Total OT") + 1).Style.Font.Bold = true;
worksheet.Cell(totalRow, headers.IndexOf("Break Minutes") + 1).Value = $"=SUM(J{headerRow + 1}:J{totalRow - 1})";
worksheet.Cell(totalRow, headers.IndexOf("Break Minutes") + 1).Style.Font.Bold = true;
worksheet.Cell(totalRow, headers.IndexOf("Net OT") + 1).Value = $"=SUM(K{headerRow + 1}:K{totalRow - 1})";
worksheet.Cell(totalRow, headers.IndexOf("Net OT") + 1).Style.Font.Bold = true;
worksheet.Columns().AdjustToContents();
var stream = new MemoryStream();
workbook.SaveAs(stream);
stream.Position = 0;
return stream;
}
private TimeSpan CalculateTotalOT(OtRegisterModel r)
{
TimeSpan office = (r.OfficeTo ?? TimeSpan.Zero) - (r.OfficeFrom ?? TimeSpan.Zero);
TimeSpan after = (r.AfterTo ?? TimeSpan.Zero) - (r.AfterFrom ?? TimeSpan.Zero);
if (after < TimeSpan.Zero)
after += TimeSpan.FromHours(24);
return office + after;
}
private string FormatTime(TimeSpan? time)
{
return time == null || time == TimeSpan.Zero ? "" : time.Value.ToString(@"hh\:mm");
}
}
}