From 6297836142bcf12cb8ded37a9f26f2bddc29bf46 Mon Sep 17 00:00:00 2001 From: mashfiq Date: Tue, 28 Apr 2026 16:54:38 +0600 Subject: [PATCH] report --- .../EchoTexExceptionReportDA.cs | 61 ++- HRM.Report/Class/rptEcho.cs | 463 +++++++++++++----- ...al-edit-for-multiple-employee.component.ts | 3 +- 3 files changed, 406 insertions(+), 121 deletions(-) diff --git a/HRM.DA/DA/ExceptionReports/EchoTexExceptionReportDA.cs b/HRM.DA/DA/ExceptionReports/EchoTexExceptionReportDA.cs index 71e3965..d17f67e 100644 --- a/HRM.DA/DA/ExceptionReports/EchoTexExceptionReportDA.cs +++ b/HRM.DA/DA/ExceptionReports/EchoTexExceptionReportDA.cs @@ -1,6 +1,7 @@ using Ease.Core.DataAccess; -using System; using HRM.BO; +using Microsoft.Data.SqlClient; +using System; using System.Collections.Generic; using System.Data; using System.Linq; @@ -780,5 +781,63 @@ namespace HRM.DA } return monthlyDetail; } + internal static DataSet GetMonthlyKPIDetail(TransactionContext tc, DateTime fromDate, DateTime toDate, List empIds, List leaves, string connectionString) + { + DataSet ds = new DataSet(); + + // Convert Employee IDs to DataTable + DataTable dtEmp = new DataTable(); + dtEmp.Columns.Add("ID", typeof(int)); + + foreach (var id in empIds) + dtEmp.Rows.Add(id); + + // Convert Leaves to DataTable + DataTable dtLeave = new DataTable(); + dtLeave.Columns.Add("ID", typeof(int)); + dtLeave.Columns.Add("Code", typeof(string)); + + foreach (var lv in leaves) + dtLeave.Rows.Add(lv.ID, lv.Code); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + using (SqlCommand cmd = new SqlCommand()) + { + cmd.Connection = connection; + cmd.CommandText = "dbo.GetMonthlyKPIDetail"; + cmd.CommandType = CommandType.StoredProcedure; + + // Employee TVP + SqlParameter pEmp = cmd.Parameters.Add("@EmpIds", SqlDbType.Structured); + pEmp.Value = dtEmp; + pEmp.TypeName = "dbo.IntList"; + + // Leave TVP + SqlParameter pLeave = cmd.Parameters.Add("@Leaves", SqlDbType.Structured); + pLeave.Value = dtLeave; + pLeave.TypeName = "dbo.LeaveType"; + + // Dates + cmd.Parameters.Add("@FromDate", SqlDbType.DateTime).Value = fromDate; + cmd.Parameters.Add("@ToDate", SqlDbType.DateTime).Value = toDate; + + // Execute + using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) + { + adapter.Fill(ds); + } + } + + connection.Close(); + } + + if (ds.Tables.Count > 0) + ds.Tables[0].TableName = "MonthlyKPIDetail"; + + return ds; + } } } diff --git a/HRM.Report/Class/rptEcho.cs b/HRM.Report/Class/rptEcho.cs index 21ab7ba..9b6d631 100644 --- a/HRM.Report/Class/rptEcho.cs +++ b/HRM.Report/Class/rptEcho.cs @@ -33,6 +33,7 @@ namespace HRM.Report string tempEmpID = string.Empty; private int TotalEmp = 0; int count = 1; + double _dExtraAllowanceHours = 0; public rptEcho() { @@ -2871,143 +2872,367 @@ namespace HRM.Report #endregion #region MonthlyKPI + //public byte[] ShowMonthlyKPI(DateTime dFromDate, DateTime dToDate, string sEmpID, string reportType, int payrollTypeID) + //{ + // ReportProcessor reportProcessor = new ReportProcessor(); + + // DataSet oMonthlyKPIDetail = null; + // oMonthlyKPIDetail = new EchoTexExceptionReportService().GetMonthlyKPIDetail(dFromDate, dToDate, sEmpID); + + // var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json"); + // IConfiguration Configuration = builder.Build(); + + // string sExtraAllowanceHour = Configuration.GetSection("Attendance")["ExtraAllowanceHour"]; + // //double dExtraAllowanceHours = 0; + // if (!double.TryParse(sExtraAllowanceHour, out _dExtraAllowanceHours)) + // { + // _dExtraAllowanceHours = 13.5; // Default if Hour not given + // } + + // #region Extra + + // oMonthlyKPIDetail.Tables[0].Columns.Add("ExtraAllowance", typeof(double)); + + // if (oMonthlyKPIDetail != null && oMonthlyKPIDetail.Tables.Count > 0) + // { + // List dAttnProcessess = dAttnProcessess = new DailyAttnProcessService().Get(sEmpID, dFromDate, dToDate); + // //List oNationalHolidays = AttnNationalHoliday.GetByMonth(dFromDate.FirstDateOfYear(), dFromDate.LastDateOfYear()); + // List oShifts = new ShiftService().Get(EnumStatus.Regardless, payrollTypeID); + // List oemps = new EmployeeService().GetByEmpIDs(sEmpID); + // List oAdparameters = new ADParameterService().Get(EnumStatus.Active, EnumAllowOrDeduct.Allowance, payrollTypeID).Where(x => x.AllowDeductID == 4).ToList(); // AllowDeductID = 4 is Extra Allowance in ALLOWANCEDEDUCTION table + // List ogrades = new GradeService().Get(EnumStatus.Regardless); + + // int count = 0; + // foreach (DataRow monthlyRow in oMonthlyKPIDetail.Tables[0].Rows) + // { + // count++; + // Employee emp = oemps.Find(x => x.EmployeeNo.ToString() == monthlyRow["IDNo"].ToString()); + // if (emp == null) continue; + // DateTime attnDate = Convert.ToDateTime(monthlyRow["AttnDate"]); + // List dEmpAttn = dAttnProcessess.FindAll(x => x.EmployeeID == emp.ID && x.AttnDate.Date == attnDate.Date).ToList(); + // DataTable oDataTable = GetEmpDailyAttnNewKPI(emp.ID, dEmpAttn, emp, oShifts, oAdparameters, ogrades); + // if (oDataTable != null && oDataTable.Rows.Count > 0) + // { + // monthlyRow["ExtraAllowance"] = oDataTable.Rows[0]["ExtraAllowance"]; + // } + // else + // { + // monthlyRow["ExtraAllowance"] = 0; + // } + // } + // } + // #endregion + + + // DataTable oMnthlyKPIDtlSummary = new AttendenceDataSet.MnthlyKPIDtlSummaryDataTable(); + + // #region Summary Parts + + + // if (oMonthlyKPIDetail.Tables.Count > 0 && oMonthlyKPIDetail.Tables[0].Rows.Count > 0) + // { + // var groupedData = oMonthlyKPIDetail.Tables[0] + // .AsEnumerable() + // .GroupBy(x => x.Field("IDNo")) + // .Select(g => new { EmployeeNo = g.Key, OTSum = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())), OTAvg = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())) / g.Count(), OTGreaterThan5 = g.Count(x => Convert.ToDouble(x["OTHour"].ToString()) > 5), WH = g.Sum(x => Convert.ToDouble(x["Minutes"].ToString())) }) + // .ToList(); + + // DataRow dRow = oMnthlyKPIDtlSummary.NewRow(); + // dRow["ManPower"] = groupedData.Count(); + // dRow["PerAvgOTGreater2"] = groupedData.Count(x => x.OTAvg > 2); + // dRow["PerSumOTGreater75"] = groupedData.Count(x => x.OTSum > 75); + // dRow["PerSumOTGreater100"] = groupedData.Count(x => x.OTSum > 100); + // dRow["PerSumOTGreater52"] = groupedData.Count(x => x.OTSum > 52); + // dRow["PerOneOTGreater5"] = groupedData.Count(x => x.OTGreaterThan5 > 0); + // double wh = groupedData.Sum(c => c.WH); + // oMnthlyKPIDtlSummary.Rows.Add(dRow); + + // } + // #endregion + + // oMnthlyKPIDtlSummary.TableName = "MnthlyKPIDtlSummary"; + // oMonthlyKPIDetail.Tables.Add(oMnthlyKPIDtlSummary); + + // string RDLC = "rptMonthlyKPI.rdlc"; + + // List _parameters = new List(); + // ReportParameter rParam = new ReportParameter("FromDate", dFromDate.ToString("dd MMM yyyy")); + // _parameters.Add(rParam); + // rParam = new ReportParameter("ToDate", dToDate.LastDateOfMonth().ToString("dd MMM yyyy")); + // _parameters.Add(rParam); + + // return reportProcessor.AttendanceReportsView(null, oMonthlyKPIDetail, null, RDLC, _parameters, true, payrollTypeID, reportType); + //} + //public DataTable GetEmpDailyAttnNewKPI(int EmpID, List dAttnProcessess, Employee emp, List oShifts, List oADPrams, List ogrades) + //{ + // AttendenceDataSet.EmpDailyAttnDataTable dTable = new AttendenceDataSet.EmpDailyAttnDataTable(); + + // DateTime startTime, endTime; + + // if (!(dAttnProcessess == null || dAttnProcessess.Count <= 0)) + // { + // foreach (DailyAttnProcess dAttnProcess in dAttnProcessess) + // { + // DataRow Rowbody = dTable.NewRow(); + // Rowbody["ExtraAllowance"] = 0; + // if (oADPrams != null && emp != null) + // { + // foreach (ADParameter adparam in oADPrams) + // { + // foreach (ADParameter.ADParameterGrade grn in adparam.ADParameterGrades) + // { + // //Grade gr = ogrades.GetItem(grn.GradeID); + // Grade gr = ogrades.Find(delegate (Grade item) { return item.ID == grn.GradeID; }); + // if (gr != null && gr.ID == emp.GradeID) + // { + // if (dAttnProcess.InTime != null && dAttnProcess.InTime != DateTime.MinValue) + // { + // Shift sft = oShifts.FirstOrDefault(x => x.ID == dAttnProcess.ShiftID); + // startTime = dAttnProcess.InTime.Value.Date.Add(sft.InTime.TimeOfDay); + + // startTime = (DateTime)startTime.AddMinutes(-15) > (DateTime)dAttnProcess.InTime ? (DateTime)startTime.AddMinutes(-15) : (DateTime)dAttnProcess.InTime; + + // endTime = dAttnProcess.OutTime != null ? (DateTime)dAttnProcess.OutTime : DateTime.MinValue; + // if (endTime != DateTime.MinValue) + // { + // if (endTime.Subtract(startTime).Add(TimeSpan.FromMinutes(1)).TotalHours >= _dExtraAllowanceHours) + // { + // Rowbody["ExtraAllowance"] = 1;// ncount++; + // } + // } + + // } + // } + // } + // } + // } + + // dTable.Rows.Add(Rowbody); + // } + // } + // return dTable; + //} + + + public byte[] ShowMonthlyKPI(DateTime dFromDate, DateTime dToDate, string sEmpID, string reportType, int payrollTypeID) { - ReportProcessor reportProcessor = new ReportProcessor(); - - DataSet oMonthlyKPIDetail = null; - oMonthlyKPIDetail = new EchoTexExceptionReportService().GetMonthlyKPIDetail(dFromDate, dToDate, sEmpID); - - - #region Extra - - oMonthlyKPIDetail.Tables[0].Columns.Add("ExtraAllowance", typeof(double)); - - if (oMonthlyKPIDetail != null && oMonthlyKPIDetail.Tables.Count > 0) + int count = 0; + try { - List dAttnProcessess = dAttnProcessess = new DailyAttnProcessService().Get(sEmpID, dFromDate, dToDate); - //List oNationalHolidays = AttnNationalHoliday.GetByMonth(dFromDate.FirstDateOfYear(), dFromDate.LastDateOfYear()); - List oShifts = new ShiftService().Get(EnumStatus.Active, payrollTypeID); - List oemps = new EmployeeService().GetByEmpIDs(sEmpID); - List oAdparameters = new ADParameterService().Get(EnumStatus.Active, EnumAllowOrDeduct.Allowance, payrollTypeID).Where(x => x.AllowDeductID == 4).ToList(); // AllowDeductID = 4 is Extra Allowance in ALLOWANCEDEDUCTION table - List ogrades = new GradeService().Get(EnumStatus.Regardless); - foreach (DataRow monthlyRow in oMonthlyKPIDetail.Tables[0].Rows) + ReportProcessor reportProcessor = new ReportProcessor(); + + DataSet oMonthlyKPIDetail = null; + oMonthlyKPIDetail = new EchoTexExceptionReportService().GetMonthlyKPIDetail(dFromDate, dToDate, sEmpID); + + var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json"); + IConfiguration Configuration = builder.Build(); + + string sExtraAllowanceHour = Configuration.GetSection("Attendance")["ExtraAllowanceHour"]; + //double dExtraAllowanceHours = 0; + if (!double.TryParse(sExtraAllowanceHour, out _dExtraAllowanceHours)) { - Employee emp = oemps.Find(x => x.EmployeeNo.ToString() == monthlyRow["IDNo"].ToString()); - if (emp == null) continue; - DateTime attnDate = Convert.ToDateTime(monthlyRow["AttnDate"]); - List dEmpAttn = dAttnProcessess.FindAll(x => x.EmployeeID == emp.ID && x.AttnDate.Date == attnDate.Date).ToList(); - DataTable oDataTable = new rptEcho().GetEmpDailyAttnNewKPI(emp.ID, dEmpAttn, emp, oShifts, oAdparameters, ogrades); - if (oDataTable != null && oDataTable.Rows.Count > 0) - { - monthlyRow["ExtraAllowance"] = oDataTable.Rows[0]["ExtraAllowance"]; - } - else - { - monthlyRow["ExtraAllowance"] = 0; - } + _dExtraAllowanceHours = 13.5; // Default if Hour not given } - } - #endregion + #region Extra - DataTable oMnthlyKPIDtlSummary = new AttendenceDataSet.MnthlyKPIDtlSummaryDataTable(); + oMonthlyKPIDetail.Tables[0].Columns.Add("ExtraAllowance", typeof(double)); - #region Summary Parts - - - if (oMonthlyKPIDetail.Tables.Count > 0 && oMonthlyKPIDetail.Tables[0].Rows.Count > 0) - { - var groupedData = oMonthlyKPIDetail.Tables[0] - .AsEnumerable() - .GroupBy(x => x.Field("IDNo")) - .Select(g => new { EmployeeNo = g.Key, OTSum = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())), OTAvg = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())) / g.Count(), OTGreaterThan5 = g.Count(x => Convert.ToDouble(x["OTHour"].ToString()) > 5), WH = g.Sum(x => Convert.ToDouble(x["Minutes"].ToString())) }) - .ToList(); - - DataRow dRow = oMnthlyKPIDtlSummary.NewRow(); - dRow["ManPower"] = groupedData.Count(); - dRow["PerAvgOTGreater2"] = groupedData.Count(x => x.OTAvg > 2); - dRow["PerSumOTGreater75"] = groupedData.Count(x => x.OTSum > 75); - dRow["PerSumOTGreater100"] = groupedData.Count(x => x.OTSum > 100); - dRow["PerSumOTGreater52"] = groupedData.Count(x => x.OTSum > 52); - dRow["PerOneOTGreater5"] = groupedData.Count(x => x.OTGreaterThan5 > 0); - double wh = groupedData.Sum(c => c.WH); - oMnthlyKPIDtlSummary.Rows.Add(dRow); - - } - #endregion - - oMnthlyKPIDtlSummary.TableName = "MnthlyKPIDtlSummary"; - oMonthlyKPIDetail.Tables.Add(oMnthlyKPIDtlSummary); - - string RDLC = "rptMonthlyKPI.rdlc"; - - List _parameters = new List(); - ReportParameter rParam = new ReportParameter("FromDate", dFromDate.ToString("dd MMM yyyy")); - _parameters.Add(rParam); - rParam = new ReportParameter("ToDate", dToDate.LastDateOfMonth().ToString("dd MMM yyyy")); - _parameters.Add(rParam); - - return reportProcessor.AttendanceReportsView(null, oMonthlyKPIDetail, null, RDLC, _parameters, true, payrollTypeID, reportType); - } - public DataTable GetEmpDailyAttnNewKPI(int EmpID, List dAttnProcessess, Employee emp, List oShifts, List oADPrams, List ogrades) - { - AttendenceDataSet.EmpDailyAttnDataTable dTable = new AttendenceDataSet.EmpDailyAttnDataTable(); - - var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json"); - IConfiguration Configuration = builder.Build(); - - string sExtraAllowanceHour = Configuration.GetSection("Attendance")["ExtraAllowanceHour"]; - double dExtraAllowanceHours = 0; - if (!double.TryParse(sExtraAllowanceHour, out dExtraAllowanceHours)) - { - dExtraAllowanceHours = 13.5; // Default if Hour not given - } - DateTime startTime, endTime; - - if (!(dAttnProcessess == null || dAttnProcessess.Count <= 0)) - { - foreach (DailyAttnProcess dAttnProcess in dAttnProcessess) + if (oMonthlyKPIDetail != null && oMonthlyKPIDetail.Tables.Count > 0) { - DataRow Rowbody = dTable.NewRow(); - Rowbody["ExtraAllowance"] = 0; - if (oADPrams != null && emp != null) + List dAttnProcessess = dAttnProcessess = new DailyAttnProcessService().Get(sEmpID, dFromDate, dToDate); + //List oNationalHolidays = AttnNationalHoliday.GetByMonth(dFromDate.FirstDateOfYear(), dFromDate.LastDateOfYear()); + List oShifts = new ShiftService().Get(EnumStatus.Regardless, payrollTypeID); + List oemps = new EmployeeService().GetByEmpIDs(sEmpID); + List oAdparameters = new ADParameterService().Get(EnumStatus.Active, EnumAllowOrDeduct.Allowance, payrollTypeID).Where(x => x.AllowDeductID == 4).ToList(); // AllowDeductID = 4 is Extra Allowance in ALLOWANCEDEDUCTION table + List ogrades = new GradeService().Get(EnumStatus.Regardless); + + var empDict = oemps.ToDictionary(x => x.EmployeeNo.ToString(), x => x); + + var attnLookup = dAttnProcessess + .GroupBy(x => new { x.EmployeeID, Date = x.AttnDate.Date }) + .ToDictionary(g => (g.Key.EmployeeID, g.Key.Date), g => g.ToList()); + + var shiftDict = oShifts.ToDictionary(x => x.ID, x => x); + + var gradeEligible = new HashSet(); + foreach (var ad in oAdparameters) { - foreach (ADParameter adparam in oADPrams) + foreach (var gr in ad.ADParameterGrades) { - foreach (ADParameter.ADParameterGrade grn in adparam.ADParameterGrades) - { - //Grade gr = ogrades.GetItem(grn.GradeID); - Grade gr = ogrades.Find(delegate (Grade item) { return item.ID == grn.GradeID; }); - if (gr != null && gr.ID == emp.GradeID) - { - if (dAttnProcess.InTime != null && dAttnProcess.InTime != DateTime.MinValue) - { - Shift sft = oShifts.FirstOrDefault(x => x.ID == dAttnProcess.ShiftID); - startTime = dAttnProcess.InTime.Value.Date.Add(sft.InTime.TimeOfDay); - - startTime = (DateTime)startTime.AddMinutes(-15) > (DateTime)dAttnProcess.InTime ? (DateTime)startTime.AddMinutes(-15) : (DateTime)dAttnProcess.InTime; - - endTime = dAttnProcess.OutTime != null ? (DateTime)dAttnProcess.OutTime : DateTime.MinValue; - if (endTime != DateTime.MinValue) - { - if (endTime.Subtract(startTime).Add(TimeSpan.FromMinutes(1)).TotalHours >= dExtraAllowanceHours) - { - Rowbody["ExtraAllowance"] = 1;// ncount++; - } - } - - } - } - } + gradeEligible.Add(gr.GradeID); } } + foreach (DataRow monthlyRow in oMonthlyKPIDetail.Tables[0].Rows) + { + count++; + if(count == 341926) + { - dTable.Rows.Add(Rowbody); + } + string empNo = monthlyRow["IDNo"].ToString(); + + if (!empDict.TryGetValue(empNo, out var emp)) + { + monthlyRow["ExtraAllowance"] = 0; + continue; + } + + DateTime attnDate = Convert.ToDateTime(monthlyRow["AttnDate"]).Date; + + if (!attnLookup.TryGetValue((emp.ID, attnDate), out var dEmpAttn)) + { + monthlyRow["ExtraAllowance"] = 0; + continue; + } + + // 👇 SAME method name used + var dt = GetEmpDailyAttnNewKPI( + emp.ID, + dEmpAttn, + emp, + oShifts, + oAdparameters, + ogrades + ); + + monthlyRow["ExtraAllowance"] = + (dt != null && dt.Rows.Count > 0) + ? dt.Rows[0]["ExtraAllowance"] + : 0; + } + } + #endregion + + + DataTable oMnthlyKPIDtlSummary = new AttendenceDataSet.MnthlyKPIDtlSummaryDataTable(); + + #region Summary Parts + + + if (oMonthlyKPIDetail.Tables.Count > 0 && oMonthlyKPIDetail.Tables[0].Rows.Count > 0) + { + var groupedData = oMonthlyKPIDetail.Tables[0] + .AsEnumerable() + .GroupBy(x => x.Field("IDNo")) + .Select(g => new { EmployeeNo = g.Key, OTSum = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())), OTAvg = g.Sum(x => Convert.ToDouble(x["OTHour"].ToString())) / g.Count(), OTGreaterThan5 = g.Count(x => Convert.ToDouble(x["OTHour"].ToString()) > 5), WH = g.Sum(x => Convert.ToDouble(x["Minutes"].ToString())) }) + .ToList(); + + DataRow dRow = oMnthlyKPIDtlSummary.NewRow(); + dRow["ManPower"] = groupedData.Count(); + dRow["PerAvgOTGreater2"] = groupedData.Count(x => x.OTAvg > 2); + dRow["PerSumOTGreater75"] = groupedData.Count(x => x.OTSum > 75); + dRow["PerSumOTGreater100"] = groupedData.Count(x => x.OTSum > 100); + dRow["PerSumOTGreater52"] = groupedData.Count(x => x.OTSum > 52); + dRow["PerOneOTGreater5"] = groupedData.Count(x => x.OTGreaterThan5 > 0); + double wh = groupedData.Sum(c => c.WH); + oMnthlyKPIDtlSummary.Rows.Add(dRow); + + } + #endregion + + oMnthlyKPIDtlSummary.TableName = "MnthlyKPIDtlSummary"; + oMonthlyKPIDetail.Tables.Add(oMnthlyKPIDtlSummary); + + string RDLC = "rptMonthlyKPI.rdlc"; + + List _parameters = new List(); + ReportParameter rParam = new ReportParameter("FromDate", dFromDate.ToString("dd MMM yyyy")); + _parameters.Add(rParam); + rParam = new ReportParameter("ToDate", dToDate.LastDateOfMonth().ToString("dd MMM yyyy")); + _parameters.Add(rParam); + + return reportProcessor.AttendanceReportsView(null, oMonthlyKPIDetail, null, RDLC, _parameters, true, payrollTypeID, reportType); + } + catch(Exception e) + { + throw new ServiceException("Failed to Save Leave Year: " + e.Message, e); + var x = count; + } + } + public DataTable GetEmpDailyAttnNewKPI( + int EmpID, + List dAttnProcessess, + Employee emp, + List oShifts, + List oADPrams, + List ogrades) + { + AttendenceDataSet.EmpDailyAttnDataTable dTable = + new AttendenceDataSet.EmpDailyAttnDataTable(); + + DataRow row = dTable.NewRow(); + row["ExtraAllowance"] = 0; + + if (emp == null || dAttnProcessess == null || dAttnProcessess.Count == 0) + { + dTable.Rows.Add(row); + return dTable; + } + + // 🔥 Precompute shift dictionary + var shiftDict = oShifts.ToDictionary(x => x.ID, x => x); + + // 🔥 Precompute eligible grades + var gradeEligible = new HashSet(); + foreach (var ad in oADPrams) + { + foreach (var gr in ad.ADParameterGrades) + { + gradeEligible.Add(gr.GradeID); } } + + if(emp.GradeID != null) + { + if (!gradeEligible.Contains((int)emp.GradeID)) + { + dTable.Rows.Add(row); + return dTable; + } + } + else + { + + } + + + foreach (var dAttnProcess in dAttnProcessess) + { + if (dAttnProcess.InTime == null || dAttnProcess.InTime == DateTime.MinValue) + continue; + + if (!shiftDict.TryGetValue((int)dAttnProcess.ShiftID, out var shift)) + continue; + + DateTime shiftStart = dAttnProcess.InTime.Value.Date.Add(shift.InTime.TimeOfDay); + DateTime adjustedStart = shiftStart.AddMinutes(-15); + + DateTime startTime = adjustedStart > dAttnProcess.InTime + ? adjustedStart + : dAttnProcess.InTime.Value; + + if (dAttnProcess.OutTime == null) + continue; + + double workedHours = dAttnProcess.OutTime.Value + .Subtract(startTime) + .Add(TimeSpan.FromMinutes(1)) + .TotalHours; + + // 🚀 EARLY EXIT (biggest improvement) + if (workedHours >= _dExtraAllowanceHours) + { + row["ExtraAllowance"] = 1; + break; + } + } + + dTable.Rows.Add(row); return dTable; } + #endregion #endregion diff --git a/HRM.UI/ClientApp/src/app/attendance/attendance-manual-edit-for-multiple-employee/attendance-manual-edit-for-multiple-employee.component.ts b/HRM.UI/ClientApp/src/app/attendance/attendance-manual-edit-for-multiple-employee/attendance-manual-edit-for-multiple-employee.component.ts index c731eb4..d9c7ea9 100644 --- a/HRM.UI/ClientApp/src/app/attendance/attendance-manual-edit-for-multiple-employee/attendance-manual-edit-for-multiple-employee.component.ts +++ b/HRM.UI/ClientApp/src/app/attendance/attendance-manual-edit-for-multiple-employee/attendance-manual-edit-for-multiple-employee.component.ts @@ -63,7 +63,7 @@ export class AttendanceManualEditForMultipleEmployeeComponent implements OnInit { value: 5, name: "Natural Calamity" }, { value: 2, name: "Forget To Punch" }, { value: 9, name: 'LOA' }, - //{ value: 11, name: 'Other' }, + { value: 11, name: 'Other' }, ] isOtherRemarks: boolean = false; otherRemarks: string = ""; @@ -207,6 +207,7 @@ export class AttendanceManualEditForMultipleEmployeeComponent implements OnInit } updateobject(type: number) { + debugger; if (this.selectedRemarks != undefined) { if (this.remarksList.find(y => y.value == this.selectedRemarks).name == "Other") { this.isOtherRemarks = true;