///<summary>Will throw an exception if already clocked in.</summary> public static void ClockIn(long employeeNum) { //we'll get this again, because it may have been a while and may be out of date ClockEvent clockEvent = ClockEvents.GetLastEvent(employeeNum); if (clockEvent == null) //new employee clocking in { clockEvent = new ClockEvent(); clockEvent.EmployeeNum = employeeNum; clockEvent.ClockStatus = TimeClockStatus.Home; ClockEvents.Insert(clockEvent); //times handled } else if (clockEvent.ClockStatus == TimeClockStatus.Break) //only incomplete breaks will have been returned. //clocking back in from break { clockEvent.TimeEntered2 = MiscData.GetNowDateTime(); clockEvent.TimeDisplayed2 = clockEvent.TimeEntered2; ClockEvents.Update(clockEvent); } else //normal clock in/out { if (clockEvent.TimeDisplayed2.Year < 1880) //already clocked in { throw new Exception(Lans.g("ClockEvents", "Error. Already clocked in.")); } else //clocked out for home or lunch. Need to clock back in by starting a new row. { TimeClockStatus tcs = clockEvent.ClockStatus; clockEvent = new ClockEvent(); clockEvent.EmployeeNum = employeeNum; clockEvent.ClockStatus = tcs; ClockEvents.Insert(clockEvent); //times handled } } }
///<summary></summary> public static bool IsClockedIn(long employeeNum) { ClockEvent clockEvent = ClockEvents.GetLastEvent(employeeNum); if (clockEvent == null) //new employee { return(false); } else if (clockEvent.ClockStatus == TimeClockStatus.Break) //only incomplete breaks will have been returned. //so currently on break { return(false); } else //normal clock in/out row found { if (clockEvent.TimeDisplayed2.Year < 1880) //already clocked in { return(true); } else //clocked out for home or lunch. { return(false); } } }
/// <summary>Used to sum a partial weeks worth of regular hours from clock events and time spans.</summary> private static TimeSpan prevWeekRegHoursHelper(long employeeNum, DateTime startDate, DateTime endDate) { string errors = ""; List <ClockEvent> listCE = new List <ClockEvent>(); List <TimeAdjust> listTA = new List <TimeAdjust>(); try { listCE = ClockEvents.GetListForTimeCardManage(employeeNum, startDate, endDate); }catch (Exception ex) { errors += ex.Message; } try { listTA = TimeAdjusts.GetListForTimeCardManage(employeeNum, startDate, endDate); }catch (Exception ex) { errors += ex.Message; } TimeSpan retVal = TimeSpan.Zero; for (int i = 0; i < listCE.Count; i++) { retVal += listCE[i].TimeDisplayed2 - listCE[i].TimeDisplayed1; if (listCE[i].AdjustIsOverridden) //Manual override { retVal += listCE[i].Adjust; } else { retVal += listCE[i].AdjustAuto; } } for (int i = 0; i < listTA.Count; i++) { retVal += listTA[i].RegHours; } return(retVal); }
///<summary>Special logic needs to be run for the phone system when users clock out.</summary> private static void ClockOutForHQ(long employeeNum) { //The name showing for this extension might change to a different user. //It would only need to change if the employee clocking out is not assigned to the current extension. (assigned ext set in the employee table) //Get the information corresponding to the employee clocking out. PhoneEmpDefault pedClockingOut = PhoneEmpDefaults.GetOne(employeeNum); if (pedClockingOut == null) { return; //This should never happen. } //Get the employee that is normally assigned to this extension (assigned ext set in the employee table). long permanentLinkageEmployeeNum = Employees.GetEmpNumAtExtension(pedClockingOut.PhoneExt); if (permanentLinkageEmployeeNum >= 1) //Extension is nomrally assigned to an employee. { if (employeeNum != permanentLinkageEmployeeNum) //This is not the normally linked employee so let's revert back to the proper employee. { PhoneEmpDefault pedRevertTo = PhoneEmpDefaults.GetOne(permanentLinkageEmployeeNum); //Make sure the employee we are about to revert is not logged in at yet a different workstation. This would be rare but it's worth checking. if (pedRevertTo != null && !ClockEvents.IsClockedIn(pedRevertTo.EmployeeNum)) { //Revert to the permanent extension for this PhoneEmpDefault. pedRevertTo.PhoneExt = pedClockingOut.PhoneExt; PhoneEmpDefaults.Update(pedRevertTo); //Update phone table to match this change. Phones.SetPhoneStatus(ClockStatusEnum.Home, pedRevertTo.PhoneExt, pedRevertTo.EmployeeNum); } } } //Now let's switch this employee back to his normal extension. Employee employeeClockingOut = Employees.GetEmp(employeeNum); if (employeeClockingOut == null) //should not get here { return; } if (employeeClockingOut.PhoneExt != pedClockingOut.PhoneExt) //Revert PhoneEmpDefault and Phone to the normally assigned extension for this employee. //Start by setting this employee back to their normally assigned extension. { pedClockingOut.PhoneExt = employeeClockingOut.PhoneExt; //Now check to see if we are about to steal yet a third employee's extension. Phone phoneCurrentlyOccupiedBy = Phones.GetPhoneForExtension(Phones.GetPhoneList(), employeeClockingOut.PhoneExt); if (phoneCurrentlyOccupiedBy != null && //There is yet a third employee who is currently occupying this extension. ClockEvents.IsClockedIn(phoneCurrentlyOccupiedBy.EmployeeNum)) { //The third employee is clocked in so set our employee extension to 0. //The currently clocked in employee will retain the extension for now. //Our employee will retain the proper extension next time they clock in. pedClockingOut.PhoneExt = 0; //Update the phone table accordingly. Phones.UpdatePhoneToEmpty(pedClockingOut.EmployeeNum, -1); } PhoneEmpDefaults.Update(pedClockingOut); } //Update phone table to match this change. Phones.SetPhoneStatus(ClockStatusEnum.Home, pedClockingOut.PhoneExt, employeeClockingOut.EmployeeNum); }
/// <summary>Used to sum a partial weeks worth of rate2 hours from clock events.</summary> private static TimeSpan prevWeekDiffHoursHelper(long employeeNum, DateTime startDate, DateTime endDate) { List <ClockEvent> listCE = ClockEvents.GetListForTimeCardManage(employeeNum, startDate, endDate); TimeSpan retVal = TimeSpan.Zero; for (int i = 0; i < listCE.Count; i++) { if (listCE[i].Rate2Hours != TimeSpan.FromHours(-1)) //Manual override { retVal += listCE[i].Rate2Hours; } else { retVal += listCE[i].Rate2Auto; } } return(retVal); }
///<summary>Will throw an exception if already clocked out.</summary> public static void ClockOut(long employeeNum, TimeClockStatus clockStatus) { ClockEvent clockEvent = ClockEvents.GetLastEvent(employeeNum); if (clockEvent == null) //new employee never clocked in { throw new Exception(Lans.g("ClockEvents", "Error. New employee never clocked in.")); } else if (clockEvent.ClockStatus == TimeClockStatus.Break) //only incomplete breaks will have been returned. { throw new Exception(Lans.g("ClockEvents", "Error. Already clocked out for break."));; } else //normal clock in/out { if (clockEvent.TimeDisplayed2.Year < 1880) //clocked in. { if (clockStatus == TimeClockStatus.Break) //clocking out on break //leave the half-finished event alone and start a new one { clockEvent = new ClockEvent(); clockEvent.EmployeeNum = employeeNum; clockEvent.ClockStatus = TimeClockStatus.Break; ClockEvents.Insert(clockEvent); //times handled } else //finish the existing event { clockEvent.TimeEntered2 = MiscData.GetNowDateTime(); clockEvent.TimeDisplayed2 = clockEvent.TimeEntered2; clockEvent.ClockStatus = clockStatus; //whatever the user selected ClockEvents.Update(clockEvent); } } else //clocked out for home or lunch. { throw new Exception(Lans.g("ClockEvents", "Error. Already clocked out.")); } } }
///<summary>Returns clockevent information for all non-hidden employees. Used only in the time card manage window.</summary> /// <param name="IsPrintReport">Only applicable to ODHQ. If true, will add ADP pay numer and note. The query takes about 9 seconds if this is set top true vs. about 2 seconds if set to false.</param> public static DataTable GetTimeCardManage(DateTime startDate, DateTime stopDate) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <DataTable>(MethodBase.GetCurrentMethod(), startDate, stopDate)); } //Construct empty table------------------------------------------------------------------------------------------------------------------------ DataTable retVal = new DataTable(); retVal.Columns.Add("PayrollID"); retVal.Columns.Add("EmployeeNum"); retVal.Columns.Add("firstName"); retVal.Columns.Add("lastName"); retVal.Columns.Add("totalHours"); //should be sum of RegularHours and OvertimeHours retVal.Columns.Add("rate1Hours"); retVal.Columns.Add("rate1OTHours"); retVal.Columns.Add("rate2Hours"); retVal.Columns.Add("rate2OTHours"); //retVal.Columns.Add("ClockEventAdjustTotal"); //retVal.Columns.Add("TimeAdjust");//adjustments to regular time from timeAdjust entries. Not a net zero effect on total hours worked. //retVal.Columns.Add("TimeAdjustOT");//OT adjustments from timeAdjust entries. OT time adjust has net zero effect. Non-OT time adjust alters total hours worked. //retVal.Columns.Add("PaidBreakTime");//paid breaks. Is adjusted by pressing calcDaily. retVal.Columns.Add("Note"); //Loop through employees. Each employee adds one row to table -------------------------------------------------------------------------------- List <ClockEvent> listClockEventsAllPlusPevWeek = new List <ClockEvent>(); List <ClockEvent> listClockEventsBreakAllPlusPrevWeek = new List <ClockEvent>(); List <TimeAdjust> listTimeAdjustAllPlusPrevWeek = new List <TimeAdjust>(); List <Employee> listEmployees = Employees.GetForTimeCard(); for (int e = 0; e < listEmployees.Count; e++) { string employeeErrors = ""; string note = ""; DataRow dataRowCur = retVal.NewRow(); dataRowCur.ItemArray.Initialize(); //changes all nulls to blanks and zeros. //PayrollID------------------------------------------------------------------------------------------------------------------------------------- dataRowCur["PayrollID"] = listEmployees[e].PayrollID; //EmployeeNum and Name---------------------------------------------------------------------------------------------------------------------------------- dataRowCur["EmployeeNum"] = listEmployees[e].EmployeeNum; dataRowCur["firstName"] = listEmployees[e].FName; dataRowCur["lastName"] = listEmployees[e].LName; //Begin calculations------------------------------------------------------------------------------------------------------------------------------------ //each list below will contain one entry per week. List <TimeSpan> listTsRegularHoursWeekly = new List <TimeSpan>(); //Total non-overtime hours. Used for calculation, not displayed or part of dataTable. List <TimeSpan> listTsOTHoursWeekly = new List <TimeSpan>(); //Total overtime hours. Used for calculation, not displayed or part of dataTable. List <TimeSpan> listTsDifferentialHoursWeekly = new List <TimeSpan>(); //Not included in total hours worked. tsDifferentialHours is differant than r2Hours and r2OTHours //TimeSpan tsClockEventNetAdjust =new TimeSpan(); //TimeSpan tsTimeAdjust =new TimeSpan(); //TimeSpan tsTimeAdjustOT =new TimeSpan(); //TimeSpan tsPaidBreakTime =new TimeSpan(); List <ClockEvent> listClockEvents = new List <ClockEvent>(); List <TimeAdjust> listTimeAdjusts = new List <TimeAdjust>(); try { listClockEvents = ClockEvents.GetListForTimeCardManage(listEmployees[e].EmployeeNum, startDate, stopDate); }catch (Exception ex) { employeeErrors += ex.Message; } try { listTimeAdjusts = TimeAdjusts.GetListForTimeCardManage(listEmployees[e].EmployeeNum, startDate, stopDate); }catch (Exception ex) { employeeErrors += ex.Message; } //report errors in note column and move to next employee.---------------------------------------------------------------- if (employeeErrors != "") { dataRowCur["Note"] = employeeErrors.Trim(); retVal.Rows.Add(dataRowCur); continue; //display employee errors in note field for employee. All columns will be blank for just this employee. } //sum values for each week---------------------------------------------------------------------------------------------------- List <DateTime> weekStartDates = weekStartHelper(startDate, stopDate); for (int i = 0; i < weekStartDates.Count; i++) { listTsRegularHoursWeekly.Add(TimeSpan.Zero); listTsOTHoursWeekly.Add(TimeSpan.Zero); listTsDifferentialHoursWeekly.Add(TimeSpan.Zero); } int weekCur = 0; for (int i = 0; i < listClockEvents.Count; i++) { //set current week for clock event for (int j = 0; j < weekStartDates.Count; j++) { if (listClockEvents[i].TimeDisplayed1 < weekStartDates[j].AddDays(7)) { weekCur = j; //clock event occurs during the week "j" break; } } if (i == 0) //we only want the comment from the first clock event entry. { note = listClockEvents[i].Note; } //TimeDisplayed----- listTsRegularHoursWeekly[weekCur] += listClockEvents[i].TimeDisplayed2 - listClockEvents[i].TimeDisplayed1; //Adjusts----- if (listClockEvents[i].AdjustIsOverridden) { listTsRegularHoursWeekly[weekCur] += listClockEvents[i].Adjust; } else { listTsRegularHoursWeekly[weekCur] += listClockEvents[i].AdjustAuto; } //OverTime----- if (listClockEvents[i].OTimeHours != TimeSpan.FromHours(-1)) //Manual override { listTsOTHoursWeekly[weekCur] += listClockEvents[i].OTimeHours; listTsRegularHoursWeekly[weekCur] += -listClockEvents[i].OTimeHours; } else { listTsOTHoursWeekly[weekCur] += listClockEvents[i].OTimeAuto; listTsRegularHoursWeekly[weekCur] += -listClockEvents[i].OTimeAuto; } //Differential/Rate2 if (listClockEvents[i].Rate2Hours != TimeSpan.FromHours(-1)) //Manual override { listTsDifferentialHoursWeekly[weekCur] += listClockEvents[i].Rate2Hours; } else { listTsDifferentialHoursWeekly[weekCur] += listClockEvents[i].Rate2Auto; } } //reset current week to itterate through time adjusts weekCur = 0; for (int i = 0; i < listTimeAdjusts.Count; i++) //list of timeAdjusts have already been filtered. All timeAdjusts in this list are applicable. //set current week for time adjusts----- { for (int j = 0; j < weekStartDates.Count; j++) { if (listTimeAdjusts[i].TimeEntry < weekStartDates[j].AddDays(7)) { weekCur = j; //clock event occurs during the week "j" break; } } listTsRegularHoursWeekly[weekCur] += listTimeAdjusts[i].RegHours; listTsOTHoursWeekly[weekCur] += listTimeAdjusts[i].OTimeHours; } //Overtime should have already been calculated by CalcWeekly(); No calculations needed, just sum values.------------------------------------------------------ double totalHoursWorked = 0; double totalRegularHoursWorked = 0; double totalOTHoursWorked = 0; double totalDiffHoursWorked = 0; //sum weekly totals. for (int i = 0; i < weekStartDates.Count; i++) { totalHoursWorked += listTsRegularHoursWeekly[i].TotalHours; totalHoursWorked += listTsOTHoursWeekly[i].TotalHours; totalRegularHoursWorked += listTsRegularHoursWeekly[i].TotalHours; totalOTHoursWorked += listTsOTHoursWeekly[i].TotalHours; totalDiffHoursWorked += listTsDifferentialHoursWeekly[i].TotalHours; } //Regular time at R1 and R2 double rate1ratio = 0; if (totalHoursWorked != 0) { rate1ratio = 1 - totalDiffHoursWorked / totalHoursWorked; } dataRowCur["totalHours"] = TimeSpan.FromHours(totalHoursWorked).ToString(); double r1Hours = rate1ratio * totalRegularHoursWorked; double r2Hours = totalRegularHoursWorked - r1Hours; double r1OTHours = rate1ratio * totalOTHoursWorked; double r2OTHours = totalHoursWorked - r1Hours - r2Hours - r1OTHours; //"self correcting math" uses guaranteed to total correctly. dataRowCur["rate1Hours"] = TimeSpan.FromHours(r1Hours).ToString(); dataRowCur["rate2Hours"] = TimeSpan.FromHours(r2Hours).ToString(); dataRowCur["rate1OTHours"] = TimeSpan.FromHours(r1OTHours).ToString(); dataRowCur["rate2OTHours"] = TimeSpan.FromHours(r2OTHours).ToString(); dataRowCur["Note"] = note; retVal.Rows.Add(dataRowCur); continue; } return(retVal); }