using Ease.Core.DataAccess;
using Ease.Core.Model;
using HRM.BO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Data;
using System.Threading;
using NPOI.SS.Formula.Functions;

namespace HRM.DA
{
    public class AttendanceProcess
    {
        #region Declaration

        //public event System.EventHandler RefreshStatus;
        //List<Employee> _employees = null;
        //List<MonthlyWorkPlan> _monthlyWorkPlans = null;
        List<AttnNationalHoliday> _AttNHolidays = null;
        EnumWorkPlanGroup _empWPtype = EnumWorkPlanGroup.Fixed;
        List<AttnMonthlyBenefit> _atnMonthlyBenifits = null;
        DateTime Attdate = DateTime.MinValue;
        AttnProcessRunSummary _attnRunSummary;
        List<Shift> shifts = null;
        List<Shift> _shifts = null;

        List<Employee> employees = null;
        double _lateHour, _earlyHour, _oTHour;
        Employee employee = null;
        AttnParametarization _AttnParam = null;
        DailyAttnProcess _DailyAttnProcess = null;
        #endregion

        #region Private functions

        private EnumAttendanceType GetAttnType(DateTime empInTime, DateTime empOutTime, Shift shift, DateTime attnDate,
            MonthlyWorkPlan empMonthlyWorkPlan)
        {
            EnumAttendanceType attntype = EnumAttendanceType.Present;
            DateTime shiftInTime = attnDate.Subtract(attnDate.TimeOfDay).Add(shift.InTime.TimeOfDay);

            DateTime shiftOutTime = DateTime.MinValue;
            DateTime shiftOutTimeWithMinimumOT = DateTime.MinValue;
            double _oTHour = 0;

            if (shift.InTime <= shift.OutTime)
            {
                shiftOutTime = attnDate.Subtract(attnDate.TimeOfDay).Add(shift.OutTime.TimeOfDay);
                shiftOutTimeWithMinimumOT = attnDate.Subtract(attnDate.TimeOfDay).Add(shift.OutTime.TimeOfDay)
                    .AddMinutes(shift.MinimumOutOTHour);
            }
            else
            {
                shiftOutTime = attnDate.AddDays(1).Subtract(attnDate.TimeOfDay).Add(shift.OutTime.TimeOfDay);
                shiftOutTimeWithMinimumOT = attnDate.AddDays(1).Subtract(attnDate.TimeOfDay)
                    .Add(shift.OutTime.TimeOfDay).AddMinutes(shift.MinimumOutOTHour);
            }

            //  DateTime shiftInTimeWithLatehour = attnDate.Subtract(attnDate.TimeOfDay).Add(shift.InTime.TimeOfDay).AddMinutes(shift.LateCalcualtion);


            if (empMonthlyWorkPlan.Type != EnumWorkPlanDayType.WorkingDay)
            {
                TimeSpan OTHour = empOutTime.Subtract(empInTime);
                _oTHour = Convert.ToDouble(OTHour.Hours) +
                          (Convert.ToDouble(OTHour.Minutes) >= Convert.ToDouble(shift.MinimumOutOTHour) ? 1 : 0);
                //For Launch break
                if (_oTHour > 6)
                {
                    _oTHour = _oTHour - 1;
                }

                OTHour = empOutTime.Subtract(empOutTime);
                // for fixed group employee, night 1 am to 2 pm is rest time, so this one hour will be not included in overtime.
                if (_empWPtype == EnumWorkPlanGroup.Fixed && empInTime.Date > empOutTime.Date && empOutTime.Hour >= 1 &&
                    empOutTime.Minute >= shift.MinimumOutOTHour)
                {
                    _oTHour = _oTHour - 1;
                }

                if (empMonthlyWorkPlan.Type == EnumWorkPlanDayType.NationalHoliday)
                {
                    attntype = EnumAttendanceType.Holiday;
                }
                else if (empMonthlyWorkPlan.Type == EnumWorkPlanDayType.WeeklyHoliday)
                {
                    attntype = EnumAttendanceType.WeeklyHoliday;
                }
            }
            else
            {
                if (empOutTime > shiftOutTimeWithMinimumOT)
                {
                    TimeSpan OTHour = empOutTime.Subtract(shiftOutTime);
                    _oTHour = Convert.ToDouble(OTHour.Hours) +
                              (Convert.ToDouble(OTHour.Minutes) >= Convert.ToDouble(shift.MinimumOutOTHour) ? 1 : 0);
                }
            }

            if (_oTHour < 0) _oTHour = 0;


            return attntype;
        }

        private void CalcullateWorkdayType(DailyAttnProcess attnProcess, EmployeeWorkPlanSetup oEmpWorkplan,    
            WorkPlanGroup oEmpWPlanGroup, int payrollTypeID)
        {
            //List<ShiftRotation> oShiftRotations = null;
            //oShiftRotations = ShiftRotation.Get(oEmpWPlanGroup.Type);
            attnProcess.WorkDayType = EnumWorkPlanDayType.WorkingDay;

            if (_AttNHolidays == null)
            {
                DateTime oLastDate = attnProcess.AttnDate.LastDateOfMonth();
                DateTime oFirstDate = attnProcess.AttnDate.FirstDateOfMonth();
                _AttNHolidays =
                    new AttnNationalHolidayService().GetByMonthAndPayrollType(oFirstDate, oLastDate, payrollTypeID);
            }

            AttnNationalHoliday oAttNHoliday = _AttNHolidays.Where(o =>
                    attnProcess.AttnDate.Date >= o.FromDate.Date && attnProcess.AttnDate.Date <= o.ToDate.Date)
                .FirstOrDefault();
            if (oAttNHoliday != null)
            {
                attnProcess.WorkDayType = EnumWorkPlanDayType.NationalHoliday;
                attnProcess.ReferenceID = oAttNHoliday.ID;
                return;
            }

            if (oEmpWPlanGroup.Type == EnumWorkPlanGroup.Fixed)
            {
                if ((oEmpWorkplan.WeekEndOn != null && attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.WeekEndOn)
                    || (oEmpWorkplan.WeekEndOn2 != null && attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.WeekEndOn2))
                {
                    attnProcess.WorkDayType = EnumWorkPlanDayType.WeeklyHoliday;
                }
            }
            else
            {
                if (oEmpWorkplan.WeekEndOn != null)
                {
                    if (attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.WeekEndOn)
                        //if (attnProcess.AttnDate.DayOfWeek == (DayOfWeek)(((int)oEmpWorkplan.WeekEndOn + 1) % 7))
                    {
                        DayOfWeek DayOfWeekValue = (DayOfWeek)(((int)oEmpWorkplan.WeekEndOn + 1) % 7);
                        attnProcess.WorkDayType = EnumWorkPlanDayType.WeeklyHoliday;
                    }
                }
                //if ((oEmpWorkplan.HolidayOne != null &&
                //     attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.HolidayOne)
                //    || (oEmpWorkplan.HolidayTwo != null &&
                //        attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.HolidayTwo))
                //{
                //    if (attnProcess.AttnDate.DayOfWeek == (DayOfWeek)oEmpWorkplan.HolidayOne)
                //    {
                //        attnProcess.WorkDayType = EnumWorkPlanDayType.WeeklyHoliday;
                //    }
                //}
                else
                {
                    attnProcess.WorkDayType = AutoRotationHolidayCalc(oEmpWorkplan, attnProcess.AttnDate);
                    //if (attnProcess.AttnDate >= oEmpWorkplan.CreatedDate)
                    //{
                    //    int nShiftInterval = 7;
                    //    TimeSpan st = attnProcess.AttnDate - oEmpWorkplan.CreatedDate;
                    //    int dayCount = st.Days;
                    //    int nCircleDay = (dayCount % nShiftInterval);

                    //    if ((nShiftInterval - nCircleDay - 1) == 0)
                    //    {
                    //        attnProcess.WorkDayType = EnumWorkPlanDayType.WeeklyHoliday;
                    //    }
                    //}
                }
            }
        }
        public static EnumWorkPlanDayType AutoRotationHolidayCalc(EmployeeWorkPlanSetup oEmpWorkplan, DateTime targetDate)
        {
            EnumWorkPlanDayType oEnumWPDayType = EnumWorkPlanDayType.WorkingDay;
            if (targetDate >= oEmpWorkplan.StartDate)
            {
                int nShiftInterval = 7;
                TimeSpan st = targetDate - oEmpWorkplan.StartDate;
                int dayCount = st.Days;
                int nCircleDay = (dayCount % nShiftInterval);

                if ((nShiftInterval - nCircleDay - 1) == 0)
                {
                    oEnumWPDayType = EnumWorkPlanDayType.WeeklyHoliday;
                }

            }

            return oEnumWPDayType;
        }
        //private void CalcullateOT(DailyAttnProcess attnProcess, Shift oshift, DateTime Attdate)
        //{
        //    attnProcess.OTHour = 0;

        //    DateTime actualInTime = (DateTime)attnProcess.InTime;
        //    DateTime actualOutTime = (DateTime)attnProcess.OutTime;
        //    DateTime shiftInTime = ((DateTime)attnProcess.InTime).Date.Add(oshift.InTime.TimeOfDay);
        //    DateTime shiftOutTime = ((DateTime)attnProcess.InTime).Date.Add(oshift.OutTime.TimeOfDay);
        //    if (shiftOutTime < shiftInTime)
        //    {
        //        shiftOutTime = shiftOutTime.AddDays(1);
        //    }

        //    double standardHourWorked = shiftOutTime.Subtract(shiftInTime).TotalHours;
        //    double actualHourWorked = actualOutTime.Subtract(actualInTime).TotalHours;

        //    if (attnProcess.WorkDayType == EnumWorkPlanDayType.WorkingDay)
        //    {
        //        if (actualHourWorked > standardHourWorked)
        //        {
        //            double minutesBeforeShiftTime = 0;
        //            double minutesAfterShiftTime = 0;
        //            double inOTMinutes, outOTMinutes;
        //            inOTMinutes = outOTMinutes = 0;

        //            if (actualInTime < shiftInTime)
        //            {
        //                minutesBeforeShiftTime = shiftInTime.Subtract(actualInTime).TotalMinutes;
        //                var minimumOtInMinutes = oshift.MinimumInOTHour;

        //                if (minutesBeforeShiftTime > minimumOtInMinutes)
        //                {
        //                    inOTMinutes = minutesBeforeShiftTime;
        //                }
        //            }

        //            if ((actualHourWorked * 60.0) - (standardHourWorked * 60.0) > minutesBeforeShiftTime)
        //            {
        //                minutesAfterShiftTime = (actualHourWorked * 60.0) - (standardHourWorked * 60.0) -
        //                                        minutesBeforeShiftTime;
        //                var minimumOtOutMinutes = oshift.MinimumOutOTHour;

        //                if (minutesAfterShiftTime > minimumOtOutMinutes)
        //                {
        //                    outOTMinutes = minutesAfterShiftTime;
        //                }
        //            }

        //            if (inOTMinutes + outOTMinutes > 0)
        //            {
        //                attnProcess.OTHour = (inOTMinutes + outOTMinutes) / 60.0;
        //            }
        //        }
        //    }
        //    else
        //    {
        //        //For Launch break
        //        if (actualHourWorked > 6 && oshift.LunchHour > 0)
        //        {
        //            actualHourWorked -= (oshift.LunchHour / 60.0);
        //        }

        //        attnProcess.OTHour = actualHourWorked;
        //    }

        //    if (attnProcess.OTHour < 0)
        //    {
        //        attnProcess.OTHour = 0;
        //    }
        //}
        private void CalcullateOT(bool isOtEligible, DailyAttnProcess attnProcess, Shift oshift, DateTime Attdate)
        {
            // all in one 
            attnProcess.OTHour = 0;
            // it will calculate total working hour
            if (attnProcess.InTime != null && attnProcess.OutTime != null)
            {
                attnProcess.OTHour = 0;

                DateTime actualInTime = (DateTime)attnProcess.InTime;
                DateTime actualOutTime = (DateTime)attnProcess.OutTime;

                DateTime shiftInTime = ((DateTime)attnProcess.InTime).Date.Add(oshift.InTime.TimeOfDay);
                DateTime shiftOutTime = ((DateTime)attnProcess.InTime).Date.Add(oshift.OutTime.TimeOfDay);


                if (shiftOutTime < shiftInTime)
                {
                    shiftOutTime = shiftOutTime.AddDays(1);
                }

                double standardHourWorked = shiftOutTime.Subtract(shiftInTime).TotalHours;
                double actualHourWorked = actualOutTime.Subtract(actualInTime).TotalHours;
                if (isOtEligible)
                {
                    if (attnProcess.WorkDayType == EnumWorkPlanDayType.WorkingDay)
                    {
                        #region working day

                            double minutesBeforeShiftTime = 0;
                            double minutesAfterShiftTime = 0;
                            double inOTMinutes, outOTMinutes;
                            inOTMinutes = outOTMinutes = 0;

                            if (actualInTime < shiftInTime)
                            {
                                minutesBeforeShiftTime = shiftInTime.Subtract(actualInTime).TotalMinutes;
                                var minimumOtInMinutes = oshift.MinimumInOTHour;

                                if (minutesBeforeShiftTime > minimumOtInMinutes)
                                {
                                    inOTMinutes = minutesBeforeShiftTime;
                                }
                            }

                            if (shiftOutTime < actualOutTime)
                            {
                                minutesAfterShiftTime = actualOutTime.Subtract(shiftOutTime).TotalMinutes; 
                                var minimumOtOutMinutes = oshift.MinimumOutOTHour;

                                if (minutesAfterShiftTime > minimumOtOutMinutes)
                                {
                                    outOTMinutes = minutesAfterShiftTime;
                                }
                            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                            if (inOTMinutes + outOTMinutes > 0)
                            {
                                attnProcess.OTHour = (inOTMinutes + outOTMinutes);
                            attnProcess.OTHour = Math.Round(Math.Floor(attnProcess.OTHour / 60) +
                                        ((attnProcess.OTHour % 60) / 100),2);
                            }
                        #endregion working day
                    }
                    else
                    {
                        double tempactualHourWorked = actualOutTime.Subtract(actualInTime).TotalHours;
                        actualHourWorked -= oshift.LunchHour ;
                        attnProcess.OTHour = Math.Round(Math.Floor(actualHourWorked / 60) +
                                    ((actualHourWorked % 60) / 100), 2);
                    }
                    if (attnProcess.OTHour < 0)
                        attnProcess.OTHour = 0;
                } 
            }
            //only for lifung
            attnProcess.OTHour = 0;
            if (attnProcess.WorkHour > 8) attnProcess.OTHour = Math.Round( attnProcess.WorkHour - 8,2);
        }
        private void CalcullateOTEchoTex(bool isOtEligible, DailyAttnProcess attnProcess, Shift oshift, DateTime Attdate, bool _IsOTFractionate)
        {
            double _oTHour = 0;
            attnProcess.OTHour = 0;
            if (isOtEligible == false || (attnProcess.InTime == DateTime.MinValue || attnProcess.InTime == null) || (attnProcess.OutTime == DateTime.MinValue || attnProcess.OutTime == null))
            {
                return;
            }

            DateTime shiftInTime = (DateTime)attnProcess.InTime;
            DateTime originalShiftInTime = Attdate.Subtract(Attdate.TimeOfDay).Add(oshift.InTime.TimeOfDay);

            // if anyone comes early than shift time 
            // then that will not be considderred in OT
            if (originalShiftInTime > shiftInTime)
            {
                shiftInTime = originalShiftInTime;
            }

            DateTime shiftOutTime = (DateTime)attnProcess.OutTime;
            DateTime originalShiftOutTime = DateTime.MinValue;
            TimeSpan shiftTimeDifference = new TimeSpan(0);
            TimeSpan shiftTotalTimeWithMinimumOT = new TimeSpan(0);

            if (oshift.InTime.TimeOfDay > oshift.OutTime.TimeOfDay)
            {
                originalShiftOutTime = originalShiftInTime.Date.AddDays(1).Add(oshift.OutTime.TimeOfDay);
            }
            else
            {
                originalShiftOutTime = originalShiftInTime.Date.Add(oshift.OutTime.TimeOfDay);
            }

            shiftTimeDifference = originalShiftOutTime - originalShiftInTime;

            shiftTotalTimeWithMinimumOT = shiftTimeDifference.Add(TimeSpan.FromMinutes(oshift.MinimumOTHour));

            TimeSpan OTHour = TimeSpan.FromHours(0);

            if (attnProcess.WorkDayType != EnumWorkPlanDayType.WorkingDay)
            {
                OTHour = attnProcess.OutTime.Value.Subtract((DateTime)attnProcess.InTime);
            }
            else
            {
                if (shiftOutTime.Subtract(shiftInTime).TotalHours > shiftTotalTimeWithMinimumOT.TotalHours)
                {
                    OTHour = shiftOutTime.Subtract(shiftInTime) - shiftTimeDifference;
                }
            }

            // Normal OT Calcullation
            //_oTHour = Convert.ToDouble(OTHour.Hours) + (Convert.ToDouble(OTHour.Minutes) >= Convert.ToDouble(oshift.MinimumOTHour) ? 
            //          (_IsOTFractionate?  (Convert.ToDouble(OTHour.Minutes)/60) : 1) 
            //          : 0);

            // Echo OT Calcullation
            _oTHour = OTHour.Hours;

            if (Convert.ToDouble(OTHour.Minutes) >= Convert.ToDouble(oshift.MinimumOTHour))
            {
                if (_IsOTFractionate)
                {
                    _oTHour += (60 - Convert.ToDouble(oshift.MinimumOTHour)) > Convert.ToDouble(OTHour.Minutes) ? (Convert.ToDouble(OTHour.Minutes) / 60) : 1;
                }
                else
                {
                    _oTHour += 1;
                }
            }
            // Echo OT Calcullation End 

            if (_oTHour < 0) _oTHour = 0;

            attnProcess.OTHour = _oTHour;
        }
        #endregion

        public void MobileDataThreadProcess(List<AttnMobileRawData> offlineData)
        {
            if (offlineData == null || offlineData.Count == 0)
                return;

            var Groupdate =
                        from dateGroup in offlineData
                        group dateGroup by dateGroup.AttnDate;
            
            Employee oemp = new EmployeeService().Get(offlineData[0].EmpID);
            List<Employee> emps = new List<Employee>();
            emps.Add(oemp);
            User ouser = new UserService().Get(oemp.EmployeeNo); 
            foreach(var item in Groupdate)
            {            
                Thread myNewThread = new Thread(() => Process(item.Key, 
                    EnumProcessMode.Auto, oemp.PayrollTypeID, ouser.ID, emps));
                myNewThread.Start();
                
            }

            //Thread myNewThread = new Thread(() => SendMail(oTran));
            //myNewThread.Start();

        }


        #region Public Functions
        public void Process(DateTime ProcessDate, EnumProcessMode prMode, int payrollTypeID, int processUserID)
        {
            DateTime endDate = DateTime.Today.Date;
            List<Employee> emp = new EmployeeService().Get(EnumEmployeeStatus.Regardless, payrollTypeID);
            _shifts = new ShiftService().GetAllShift();
            for (DateTime currentDate = ProcessDate; currentDate <= endDate; currentDate = currentDate.AddDays(1))
            {
                Process(currentDate, EnumProcessMode.Auto, payrollTypeID, processUserID, emp);
            }
        }

        public void Process(DateTime fromDate, EnumProcessMode prMode, int payrollTypeID, int processUserID, List<Employee> emps)
        {
            bool isEchoTex = new SystemConfigarationService().GetconfigBooleanValue(EnumConfigurationType.Logic, "attendence", "echotexprocess");
            if (isEchoTex == true)
            {
                echoTexProcess(fromDate, prMode, payrollTypeID, processUserID, emps);
                return;
            }
            _attnRunSummary = new AttnProcessRunSummary();
            _attnRunSummary.ProcessMode = prMode;
        //    bool isInOutApplicable = false;
            
            _shifts = _shifts ?? new ShiftService().GetAllShift();
            
            string msg = "";
            try
            {
                #region Initialization for Attendence Process

                Attdate = fromDate;
   //             isInOutApplicable = new SystemConfigarationService().GetconfigBooleanValue(EnumConfigurationType.Logic, "attendence", "inoutapplicable");

                List<DailyAttnProcess> dailyattProcesses = new List<DailyAttnProcess>();
                List<DailyAttendanceAllowance> dailyAttendanceAllowances = new List<DailyAttendanceAllowance>();

                List<EmpFieldTrack> oEmpFieldTracks = new List<EmpFieldTrack>();

                DateTime startTime = new DateTime(Attdate.Year, Attdate.Month, Attdate.Day, 5, 20, 0);
                DateTime ToTime = Attdate.AddDays(1);
                ToTime = new DateTime(ToTime.Year, ToTime.Month, ToTime.Day, 10, 0, 0);
                LeaveEntry empLeaveEntry = null;
                List<ActingResponsibilitySetup> _tempraryShifts = new ActingResponsibilitySetupService().GetTemporaryShiftEmployee(Attdate);
                List<EmployeeWorkPlanSetup> empWPGroups = new EmployeeWorkPlanSetupService().Get();

                List<DailyAttnProcess> manualAttnProcesses = null;
                List<SearchEmployee> _employees = emps !=null?  Employee.getSearchEmp(emps): null;
                if (emps == null || emps.Count == 0)
                {
                    SearchManager omg = new SearchManager();
                    omg.SearchFrom = EnumSearchFrom.Employee;
                    omg.Parameter.AddDefaultParameter(payrollTypeID, EnumEmployeeStatus.Live);
                    omg.Parameter.Add(EnumSearchParameter.JoiningDate, EnumSQLOperator.SmallerThan, 
                        EnumSearchObjDataType.Date, Attdate.AddDays(1));
                    _employees = new SearchEmployeeService().Find(omg);
                }
                List<Employee> discontinueEmps = new EmployeeService().GetDiscontinueEmp(Attdate, DateTime.Now, payrollTypeID);
                DateTime oLastDate = fromDate;
                DateTime oFirstDate = fromDate;
                _AttNHolidays = new AttnNationalHolidayService().GetByMonthAndPayrollType(oFirstDate, oLastDate, payrollTypeID);
                List<AttnRawData> attRawdata = new AttnRawDataService().Get(startTime, ToTime, payrollTypeID);// get raw data by a date and order by date, employee, punchTime
                List<EmployeeOutsideDuty> outSideDuties = new EmployeeOutsideDutyService().Get(Attdate); // get transaction  by the a rate 
                List<LeaveEntry> leaves = new LeaveEntryService().Get(Attdate); // workplans by the date
                List<LeaveParameter> lvParameters = new LeaveParameterService().Get(EnumStatus.Regardless, payrollTypeID, null, false);

                if (discontinueEmps != null && discontinueEmps.Count > 0)
                {
                    foreach (Employee emp in discontinueEmps)
                    {
                        if (_employees.Any(x => x.ID == emp.ID) == false)
                            _employees.Add(emp.getSearchEmployee());
                    }
                }

                manualAttnProcesses = new DailyAttnProcessService().GetManualProcess(payrollTypeID, Attdate);
                if (_employees.Count == 1)
                {
                    manualAttnProcesses.RemoveAll(o => o.EmployeeID != _employees[0].ID);
                }

                foreach (DailyAttnProcess item in manualAttnProcesses)
                {
                    //if (leaves != null && leaves.Count > 0)
                    //{
                    //    if (item.AttenType == EnumAttendanceType.Leave)
                    //    {
                    //        empLeaveEntry = leaves.Where(lv => lv.EmpID == item.EmployeeID).FirstOrDefault();
                    //        item.leaveEntry = empLeaveEntry;
                    //    }
                    //}
                    dailyattProcesses.Add(item);
                }
                List<MonthlyWorkPlan> monthlyWorkPlans = new MonthlyWorkPlanService().GetByDate(Attdate, payrollTypeID);
                #endregion
                if (monthlyWorkPlans == null || monthlyWorkPlans.Count == 0)
                {
                    throw new Exception("Monthly work plan is not yet set for the selected date of month.");
                }

                foreach (SearchEmployee emp in _employees)
                {
                    Shift oshift = null;

                    msg = emp.EmployeeNo + " " + emp.Name + " Date:" + Attdate.ToString(" dd MMM yy");
                    #region EmployeeWise Setup
                    // 1. If Joining date is after Attendendence date then no attendence

                //    if (emp.JoiningDate > Attdate) continue;

                    var manualEntry = manualAttnProcesses.Where(obj => obj.EmployeeID == emp.ID).ToList();
                    if (manualEntry.Count > 0) continue; //####

                    DailyAttnProcess attnProcess = new DailyAttnProcess();
                    attnProcess.SearchEmployee = emp;
                    attnProcess.CreatedBy = processUserID;
                    attnProcess.CreatedDate = DateTime.Today;
                    attnProcess.AttnDate = Attdate;
                    attnProcess.EmployeeID = emp.EmployeeID;
                    attnProcess.IsManualEntry = false;
                    _lateHour = 0; _earlyHour = 0; _oTHour = 0;

                    List<AttnRawData> empAttnData = null;
                    EmployeeOutsideDuty empOutsideDuty = null;

                    if (attRawdata != null && attRawdata.Count > 0)
                        empAttnData = attRawdata.Where(erd => erd.EmployeeID == emp.ID).OrderBy(erd => erd.PunchTime).ToList();
                    if (outSideDuties != null && outSideDuties.Count > 0)
                        empOutsideDuty = outSideDuties.Where(od => od.EmployeeID == emp.ID).FirstOrDefault();
                    if (leaves != null && leaves.Count > 0)
                        empLeaveEntry = leaves.Where(lv => lv.EmpID == emp.ID).FirstOrDefault();


                    EmployeeWorkPlanSetup oEmpWorkplan = empWPGroups.Where(oGr => oGr.EmployeeID == emp.ID).FirstOrDefault();

                    // 3. If There is no EmployeeWorkPlanSetup then no attendence
                    //if (oEmpWorkplan == null) 
                    //{
                    //    continue;
                    //    //throw new Exception("Employee Work-Group is not Defined for " + emp.Name + " (" + emp.EmployeeNo + ")");
                    //}

                    //   WorkPlanGroup oEmpWPlanGroup = workPlanGroups.Where(o => o.ID.Integer == oEmpWorkplan.WorkPlanGroupID.Integer).Single();

                    #endregion

                    #region Calcullate ShiftID and WorkPlan Day Type

                    MonthlyWorkPlan mplan = null;
                    ActingResponsibilitySetup tempShiftEmployee = _tempraryShifts.Where(o => o.EmployeeID == attnProcess.EmployeeID).FirstOrDefault();
                    mplan = GetPlanwithEmployee(Attdate, emp.EmployeeID, empWPGroups, monthlyWorkPlans, null);
                    if(emp.EmployeeNo=="BP0010")
                    { 
                    }
                    attnProcess.MonthlyWorkPlan = mplan;
                    if (attnProcess.MonthlyWorkPlan != null)
                    {
                        attnProcess.ShiftID = mplan.ShiftID;
                        attnProcess.Shift = _shifts.FirstOrDefault(x => x.ID == mplan.ShiftID);
                        attnProcess.WorkDayType = mplan.Type;
                        attnProcess.ActualShiftID = null;
                        if (tempShiftEmployee != null)
                        {
                            // set original shift into the temporary shiftt
                            if (tempShiftEmployee.ShiftID == null)
                            {
                                attnProcess.ActualShiftID = attnProcess.ShiftID;
                                mplan = GetPlanwithEmployee(Attdate, emp.ID, empWPGroups, monthlyWorkPlans, tempShiftEmployee);
                                attnProcess.ShiftID = mplan.ShiftID;
                            }
                            else
                            {
                                attnProcess.ActualShiftID = attnProcess.ShiftID;
                                attnProcess.ShiftID = tempShiftEmployee.ShiftID;
                            }

                            if (tempShiftEmployee.IsHoliday)
                            {
                                _earlyHour = 0;
                                _lateHour = 0;
                                attnProcess.InTime = null;
                                attnProcess.OutTime = null;
                                attnProcess.IsLate = false;
                                attnProcess.EarlyHour = 0;
                                attnProcess.LateHour = 0;
                                attnProcess.WorkDayType = EnumWorkPlanDayType.WeeklyHoliday;
                            }
                            else
                            {
                                attnProcess.WorkDayType = EnumWorkPlanDayType.WorkingDay;
                            }
                        }
                    }
                    else
                    {
                        attnProcess.AttenType = EnumAttendanceType.Absent;
                        attnProcess.Comments = "Roster is not yet assigned."; 
                        dailyattProcesses.Add(attnProcess);
                        continue;
                        //throw new Exception("Monthly Roster not found for the employee(" + attnProcess.Employee.EmployeeNo + ")" + attnProcess.Employee.Name);
                    }
                    //attnProcess.WorkDayType = 0;// attnProcess.MonthlyWorkPlan.Type;
                    //attnProcess.ReferenceID = 0;// attnProcess.MonthlyWorkPlan.HolidayID;
                    #endregion

                    #region calculate In/Out time & work day type

                    /*
                    * if ShiftID found and attendence data exists
                    *      Calcullate InTime and OutTime
                    *      If elligable for OT calcullate OT according to DayType(Holiday or Workday)
                    */

                    if (empAttnData != null && empAttnData.Count > 0 && attnProcess.ShiftID != null)
                    {
                        attnProcess.AttenType = EnumAttendanceType.Present;
                        attnProcess.InTime = null;
                        attnProcess.OutTime = null;

                        oshift = _shifts.FirstOrDefault(x => x.ID == attnProcess.ShiftID);

                        if (oshift == null) continue;

                        attnProcess.InTime = GetShiftInOutTime(empAttnData, attnProcess, oshift.ID, true);
                        attnProcess.OutTime = GetShiftInOutTime(empAttnData, attnProcess, oshift.ID, false);

                        if (attnProcess.InTime != null) attnProcess.InTime = ((DateTime)attnProcess.InTime).RemoveSecondsAndMiliseconds();
                        if (attnProcess.OutTime != null) attnProcess.OutTime = ((DateTime)attnProcess.OutTime).RemoveSecondsAndMiliseconds();

                        #region Calcullate Late & Delay & Early

                        #region previous Early and Late calculation
                        //if (attnProcess.InTime != null && totalLateMinute > oshift.LateCalcualtion)
                        //{
                        //    //     attnProcess.AttenType = EnumAttendanceType.Late;
                        //    attnProcess.IsLate = true;
                        //    _lateHour = (totalLateMinute) / 60;
                        //}

                        //if (attnProcess.OutTime != null && attnProcess.OutTime != null && ((DateTime)attnProcess.OutTime).Day == attnProcess.AttnDate.Day)
                        //{
                        //    if (oshift.OutTime.TimeOfDay.Subtract(((DateTime)attnProcess.OutTime).TimeOfDay).TotalMinutes > 0)
                        //    {
                        //        _earlyHour = oshift.OutTime.TimeOfDay.Subtract(((DateTime)attnProcess.OutTime).TimeOfDay).TotalMinutes / 60;
                        //    }
                        //} 
                        #endregion

                        this.CalculateLateAndDelay(attnProcess, _shifts);
                        #endregion
                    }

                    #endregion

                    if (empOutsideDuty != null)
                    {
                        attnProcess.AttenType = EnumAttendanceType.OutSideDuty;
                        attnProcess.ReferenceID = empOutsideDuty.ID;
                    }
                    if (empLeaveEntry != null && (empLeaveEntry.LeaveStatus == EnumLeaveStatus.Approved))
                    {
                        attnProcess.AttenType = EnumAttendanceType.Leave;
                        attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                    }

                    #region Calcullate not present status
                    if (attnProcess.WorkDayType == EnumWorkPlanDayType.WeeklyHoliday
                         || attnProcess.WorkDayType == EnumWorkPlanDayType.NationalHoliday)
                    {
                        if (empOutsideDuty != null)
                        {
                            attnProcess.AttenType = EnumAttendanceType.OutSideDuty;
                            attnProcess.ReferenceID = empOutsideDuty.ID;
                            attnProcess.Comments = empOutsideDuty.Comments;
                        }
                        if (empLeaveEntry != null && (empLeaveEntry.LeaveStatus == EnumLeaveStatus.Approved)
                           && lvParameters.Where(x => x.LeaveId == empLeaveEntry.LeaveID).Any(x => x.IgnoreHoliday == false))
                        {
                            attnProcess.AttenType = EnumAttendanceType.Leave;
                            attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                            attnProcess.Comments = empLeaveEntry.Remarks;
                        }
                    }
                    if (attnProcess.InTime == null || attnProcess.OutTime == null)
                    {
                        if (empLeaveEntry != null && (empLeaveEntry.LeaveStatus == EnumLeaveStatus.Approved))
                        {
                            #region Check Leave Entry
                            // Check wether Ignore Holidays
                            if (lvParameters.Where(x => x.LeaveId == empLeaveEntry.LeaveID).Any(x => x.IgnoreHoliday))
                            {
                                if (attnProcess.WorkDayType == EnumWorkPlanDayType.WeeklyHoliday)
                                    attnProcess.AttenType = EnumAttendanceType.WeeklyHoliday;
                                else if (attnProcess.WorkDayType == EnumWorkPlanDayType.NationalHoliday)
                                    attnProcess.AttenType = EnumAttendanceType.Holiday;
                                else
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Leave;
                                    attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                                }
                            }
                            else
                            {
                                if (attnProcess.AttenType != EnumAttendanceType.Present)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Leave;
                                    attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                                }
                                else
                                {
                                    _earlyHour = 0;
                                    _lateHour = 0;
                                    attnProcess.IsLate = false;
                                    attnProcess.EarlyHour = 0;
                                    attnProcess.LateHour = 0;
                                }
                            }
                            #endregion
                        }
                        else if (empOutsideDuty != null)
                        {
                            attnProcess.AttenType = EnumAttendanceType.OutSideDuty;
                            attnProcess.ReferenceID = empOutsideDuty.ID;
                        }
                        else if (attnProcess.WorkDayType == EnumWorkPlanDayType.WeeklyHoliday)
                            attnProcess.AttenType = EnumAttendanceType.WeeklyHoliday;
                        else if (attnProcess.WorkDayType == EnumWorkPlanDayType.NationalHoliday)
                            attnProcess.AttenType = EnumAttendanceType.Holiday;
                        else if ((attnProcess.InTime != null && attnProcess.InTime != DateTime.MinValue) || 
                            (attnProcess.OutTime != null && attnProcess.OutTime != DateTime.MinValue))
                        {
                            attnProcess.AttenType = EnumAttendanceType.Present;
                        }
                        else
                        {
                            attnProcess.AttenType = EnumAttendanceType.Absent;
                        }
                    }

                    if (attnProcess.InTime != null && attnProcess.Shift.hasAbsentTime == true
                        && attnProcess.WorkDayType == EnumWorkPlanDayType.WorkingDay)
                    {
                        if (attnProcess.Shift.InTime.TimeOfDay <= attnProcess.Shift.OutTime.TimeOfDay)
                        {
                            if (((DateTime)attnProcess.InTime).TimeOfDay > attnProcess.Shift.AbsentTime.TimeOfDay)
                            {
                                attnProcess.AttenType = EnumAttendanceType.Absent;
                            }
                        }
                        else
                        {
                            if (attnProcess.Shift.AbsentTime.TimeOfDay <= attnProcess.Shift.OutTime.TimeOfDay)
                            {
                                if (((DateTime)attnProcess.InTime).TimeOfDay > attnProcess.Shift.AbsentTime.TimeOfDay &&
                                    ((DateTime)attnProcess.InTime).TimeOfDay <= attnProcess.Shift.OutTime.TimeOfDay)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Absent;
                                }
                            }
                            else
                            {
                                if (!(((DateTime)attnProcess.InTime).TimeOfDay < attnProcess.Shift.AbsentTime.TimeOfDay
                                    && ((DateTime)attnProcess.InTime).TimeOfDay > attnProcess.Shift.OutTime.TimeOfDay))
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Absent;
                                }
                            }
                        }
                    }

                    #endregion


                    CalcullateOT(true, attnProcess, attnProcess.Shift, Attdate);

                    #region New Attendance Benefit Process
                    if(attnProcess.AttenType != EnumAttendanceType.Absent &&  attnProcess.InTime != null && attnProcess.OutTime != null)
                         attnProcess.Benifits = CalculateDailyAttendanceAllowance(attnProcess, payrollTypeID, processUserID);
                    #endregion

                    dailyattProcesses.Add(attnProcess); // Add the process to collection
                }

                msg = "Saving Data: ";
                new DailyAttnProcessService().Save(dailyattProcesses, _atnMonthlyBenifits);

             //   msg = "Saving Allowance Data: ";
             //   new DailyAttendanceAllowanceService().Save(dailyAttendanceAllowances);
            }
            catch (ServiceException ex)
            {
                throw new ServiceException(msg + ex.Message, ex);
            }
            catch (Exception e)
            {
                throw new ServiceException(msg + e.Message, e);
            }

        }

        public void CalculateLateAndDelay(DailyAttnProcess attnProcess, List<Shift> shifts)
        {
            double totalLateMinute = 0;
            DateTime temptime;
            if (attnProcess.ShiftID == null) return;
            Shift oshift = shifts.FirstOrDefault(x => x.ID == (int)attnProcess.ShiftID);
            if (oshift == null) return;
            CalculateLateAndDelay(attnProcess, oshift);
        }

        public void CalculateOverTime(DailyAttnProcess attnProcess, Shift shift)
        {
            if (attnProcess.ShiftID == null) return;
            CalcullateOT(true, attnProcess, shift, attnProcess.AttnDate);
        }

        public void CalculateLateAndDelay(DailyAttnProcess attnProcess, Shift oshift)
        {
            double totalLateMinute = 0;
            DateTime temptime;
            attnProcess.IsLate = false;
            attnProcess.LateHour = 0;
            attnProcess.EarlyHour = 0;
            _lateHour =0;
            _earlyHour = 0;
            if (oshift != null && attnProcess.InTime != null)
            {
                temptime = oshift.InTime.AddMinutes(oshift.FlexibleHour);

                if (((DateTime)attnProcess.InTime).TimeOfDay > temptime.TimeOfDay)
                {
                    totalLateMinute = ((DateTime)attnProcess.InTime).TimeOfDay.Subtract(temptime.TimeOfDay).TotalMinutes;
                    totalLateMinute = Math.Floor(totalLateMinute);// removing second
                    if (totalLateMinute > oshift.LateCalcualtion)
                    {
                        attnProcess.IsLate = true;
                        _lateHour = Math.Round( Math.Floor(totalLateMinute/60) + (totalLateMinute % 60)/100,2);  
                        
                    }
                }
            }
            double earlyhour = 0;
            if (oshift != null && attnProcess.InTime !=null && attnProcess.OutTime != null)
            {
                DateTime tempshiftTime = oshift.OutTime;
                if (oshift.FlexibleHour == 0)
                {
                    DateTime workInTime = (DateTime) attnProcess.InTime;
                    DateTime shiftInTime = new DateTime(workInTime.Year, workInTime.Month, workInTime.Day, oshift.InTime.Hour, oshift.InTime.Minute, 0);
                    if(workInTime < shiftInTime)  workInTime = shiftInTime;

                    DateTime workoutTime = (DateTime)attnProcess.OutTime;
                    DateTime shiftoutTime = new DateTime(workoutTime.Year, workoutTime.Month, workoutTime.Day, oshift.OutTime.Hour, oshift.OutTime.Minute, 0);
                    if (workoutTime > shiftoutTime) workoutTime = shiftoutTime;

                    //   double workHour = (workoutTime).Subtract((DateTime)workInTime).TotalMinutes;
                       double workHour = ((DateTime)attnProcess.OutTime).Subtract((DateTime)attnProcess.InTime).TotalMinutes;
                    workHour = Math.Floor(workHour); //removing second



                    attnProcess.OTHour = workHour - 480;// Math.Round(Math.Floor(workHour / 60) + (workHour % 60) / 100, 2);
                    if (attnProcess.OTHour < 0) attnProcess.OTHour = 0;
                    else attnProcess.OTHour = Math.Round(Math.Floor(attnProcess.OTHour / 60) + (attnProcess.OTHour % 60) / 100, 2);

                    workHour = workHour - oshift.LunchHour;
                    if (workHour < 0) workHour = 0;
                //    if (workHour> oshift.WorkHour*60) workHour = oshift.WorkHour * 60;
                    attnProcess.WorkHour = Math.Round(Math.Floor(workHour / 60) + (workHour % 60) / 100, 2);


                    if (((DateTime)attnProcess.OutTime).TimeOfDay < shiftoutTime.TimeOfDay)
                    {
                        _earlyHour = (shiftoutTime).Subtract((DateTime)attnProcess.OutTime).TotalMinutes;
                        _earlyHour = Math.Floor(_earlyHour);// removing second
                        earlyhour = _earlyHour;
                        _earlyHour = Math.Round(Math.Floor(_earlyHour / 60) + (_earlyHour % 60) / 100, 2);
                    }


                }
                // let calcualte workhour with flexible time later
            }

            attnProcess.LateHour = _lateHour;
            attnProcess.EarlyHour = _earlyHour;
            _DailyAttnProcess= attnProcess;

           
        }

        public DailyAttnProcess CalulateLateAndDelayForMobileAttendance(DailyAttnProcess oAttnProcess, Shift oShift)
        {
            CalculateLateAndDelay(oAttnProcess, oShift);
            return _DailyAttnProcess;
        }
        public DailyAttnProcess CalulateOverTimeForMobileAttendance(DailyAttnProcess oAttnProcess, Shift oShift)
        {
            CalcullateOT(true,oAttnProcess, oShift, oAttnProcess.AttnDate);
            return _DailyAttnProcess;
        }
        public List<DailyAttendanceAllowance> CalculateDailyAttendanceAllowance(DailyAttnProcess pDailyattProcesses, int payrolltypeid, int userid)
        {
            List<DailyAttendanceAllowance> items = new List<DailyAttendanceAllowance>();

            //DailyAttendanceAllowance tempDailyAttendanceAllowance = new DailyAttendanceAllowance();
            //tempDailyAttendanceAllowance.AttnDate = pDailyattProcesses.AttnDate;
            //tempDailyAttendanceAllowance.EmployeeID = pDailyattProcesses.EmployeeID;
            //tempDailyAttendanceAllowance.ShiftID = (int)pDailyattProcesses.ShiftID;
            //tempDailyAttendanceAllowance.PayrollTypeID = pEmployee.PayrollTypeID;


            if (pDailyattProcesses.ShiftID == null) return items;

            if (pDailyattProcesses.Shift.HasBenefits)
            {
                if (pDailyattProcesses.Shift.HasExtraHourAllowance && pDailyattProcesses.OutTime != null && pDailyattProcesses.OutTime != DateTime.MinValue &&
                    ((DateTime)pDailyattProcesses.OutTime).TimeOfDay > pDailyattProcesses.Shift.ExtraHourAllowanceFromTime.TimeOfDay)
                {
                    
                    DailyAttendanceAllowance ExtraHour = new DailyAttendanceAllowance();
                    ExtraHour.BenifitsType = EnumattnBeniftsType.Allowance;
                    ExtraHour.OtherBenifitItemID = pDailyattProcesses.Shift.ExtraHourAllowanceID;
                    ExtraHour.OtherBenifitValue = Convert.ToInt32(Math.Round(((DateTime)pDailyattProcesses.OutTime).TimeOfDay.Subtract(pDailyattProcesses.Shift.ExtraHourAllowanceFromTime.TimeOfDay).TotalHours));
                    items.Add(ExtraHour);
                }

                if ((pDailyattProcesses.Shift.HasHolidayAllowance &&  pDailyattProcesses.AttenType == EnumAttendanceType.WeeklyHoliday || pDailyattProcesses.AttenType == EnumAttendanceType.Holiday) &&
                    ((pDailyattProcesses.InTime != null && pDailyattProcesses.InTime != DateTime.MinValue) && 
                    (pDailyattProcesses.OutTime != null && pDailyattProcesses.OutTime != DateTime.MinValue)))
                {
                    //tempDailyAttendanceAllowance.HolidayAllowance = Convert.ToInt32(Math.Round(((DateTime)pDailyattProcesses.OutTime).Subtract(((DateTime)pDailyattProcesses.InTime)).TotalHours));
                 //   tempDailyAttendanceAllowance.HolidayAllowance = 1;
                    DailyAttendanceAllowance hilidayAlloance = new DailyAttendanceAllowance();
                    hilidayAlloance.BenifitsType = EnumattnBeniftsType.Allowance;
                    hilidayAlloance.OtherBenifitItemID = pDailyattProcesses.Shift.HolidayAllowanceID;
                    hilidayAlloance.OtherBenifitValue = 1;
                    items.Add(hilidayAlloance);
                }

                if (pDailyattProcesses.Shift.HasNightAllowance && pDailyattProcesses.Shift.IsOverlapingDay)
                {
                    DailyAttendanceAllowance NightAllowance = new DailyAttendanceAllowance();
                    NightAllowance.BenifitsType = EnumattnBeniftsType.Allowance;
                    NightAllowance.OtherBenifitItemID = pDailyattProcesses.Shift.NightAllowanceID;
                    NightAllowance.OtherBenifitValue = 1;
                    items.Add(NightAllowance);
                }
                        

                if(pDailyattProcesses.Shift.HasOtherAllowance)
                {
                    DailyAttendanceAllowance OtherAllowance = new DailyAttendanceAllowance();
                    OtherAllowance.BenifitsType = EnumattnBeniftsType.Allowance;
                    OtherAllowance.OtherBenifitItemID = pDailyattProcesses.Shift.OtherAllowanceID;
                    OtherAllowance.OtherBenifitValue = 1;
                    items.Add(OtherAllowance);
                }

                if (pDailyattProcesses.Shift.HasTiffinAllowance)
                {
                    DailyAttendanceAllowance OtherAllowance = new DailyAttendanceAllowance();
                    OtherAllowance.BenifitsType = EnumattnBeniftsType.Allowance;
                    OtherAllowance.OtherBenifitItemID = pDailyattProcesses.Shift.TiffinAllowanceID;
                    OtherAllowance.OtherBenifitValue = 1;
                    items.Add(OtherAllowance);
                }

                if (pDailyattProcesses.Shift.HasSpecialAllowance)
                {
                    DailyAttendanceAllowance OtherAllowance = new DailyAttendanceAllowance();
                    OtherAllowance.BenifitsType = EnumattnBeniftsType.Allowance;
                    OtherAllowance.OtherBenifitItemID = pDailyattProcesses.Shift.SpecialAllowanceID;
                    OtherAllowance.OtherBenifitValue = 1;
                    items.Add(OtherAllowance);
                }

                if (pDailyattProcesses.Shift.HasRegularOverTime == true 
                    && pDailyattProcesses.OTHour > 0)
                {
                    if ( pDailyattProcesses.Shift.HasHolidayOverTime == true && 
                                (pDailyattProcesses.WorkDayType == EnumWorkPlanDayType.NationalHoliday ||
                                 pDailyattProcesses.WorkDayType == EnumWorkPlanDayType.WeeklyAndNational ))
                    {
                        // do nothing
                    }
                    else
                    {
                        DailyAttendanceAllowance RegularOverTime = new DailyAttendanceAllowance();
                        RegularOverTime.BenifitsType = EnumattnBeniftsType.OT;
                        RegularOverTime.OtherBenifitItemID = pDailyattProcesses.Shift.RegularOverTimeAllowanceID;
                        RegularOverTime.OtherBenifitValue = pDailyattProcesses.OTHour;
                        items.Add(RegularOverTime);

                    }
                }

                if(pDailyattProcesses.Shift.HasRegularOverTime == true && 
                    pDailyattProcesses.Shift.HasHolidayOverTime == true && pDailyattProcesses.OTHour > 0 &&
                        (pDailyattProcesses.WorkDayType == EnumWorkPlanDayType.NationalHoliday ||
                        pDailyattProcesses.WorkDayType == EnumWorkPlanDayType.WeeklyAndNational 
                         ))
                {
                   
                    DailyAttendanceAllowance HolidayOverTime = new DailyAttendanceAllowance();
                    HolidayOverTime.BenifitsType = EnumattnBeniftsType.OT;
                    HolidayOverTime.OtherBenifitItemID = pDailyattProcesses.Shift.HolidayOverTimeAllowanceID;
                    HolidayOverTime.OtherBenifitValue = Convert.ToInt32(Math.Round(pDailyattProcesses.OTHour)); 
                    items.Add(HolidayOverTime); 
                }

                if (this._AttnParam == null) this._AttnParam = new AttnParametarizationService().Get(payrolltypeid);
                if (this._AttnParam == null) throw new Exception("Failed to get Attendance parameters");
                items.ForEach(x =>
                {
                    x.AttnDate = pDailyattProcesses.AttnDate;
                    x.EmployeeID = pDailyattProcesses.EmployeeID;
                    x.ShiftID = (int)pDailyattProcesses.ShiftID;
                    x.PayrollTypeID = payrolltypeid;
                    x.CreatedBy = userid;
                    x.CreatedDate = DateTime.Now;
                    x.SalaryMonth = GlobalFunctions.GetAttandaceSalaryMonth(x.AttnDate, this._AttnParam.MonthStartDay);
                });
            }


            //DailyAttendanceAllowance tempDailyAttendanceAllowance = new DailyAttendanceAllowance();
            //tempDailyAttendanceAllowance.AttnDate = pDailyattProcesses.AttnDate;
            //tempDailyAttendanceAllowance.EmployeeID = pDailyattProcesses.EmployeeID;
            //tempDailyAttendanceAllowance.ShiftID = (int)pDailyattProcesses.ShiftID;
            //tempDailyAttendanceAllowance.PayrollTypeID = pEmployee.PayrollTypeID;

            return items;
        }
        public List<AttnMonthlyBenefit> AttnMonthlyBenefitProcess_prev(List<DailyAttnProcess> dailyattProcesses, bool IsManualEntry, int payrollTypeId)
        {
            // this function is per previous system
            List<AttnWiseAllowance> oAttnWiseAllowances = new AttnWiseAllowanceService().Get(payrollTypeId);
            if (oAttnWiseAllowances == null || oAttnWiseAllowances.Count == 0) return null;

            AttnParametarization oAttnParam = new AttnParametarizationService().Get(payrollTypeId);
            #region AttnMonthlyBenefit Process
            string empids = string.Empty;
            DateTime tempIntime = DateTime.MinValue;
            DateTime tempOuttime = DateTime.MinValue;
            DateTime outTime = DateTime.MinValue;
            try
            {
                #region Distinct Employee
                List<DailyAttnProcess> distinctEmployee = dailyattProcesses
                              .GroupBy(p => p.EmployeeID)
                              .Select(g => g.First())
                              .ToList();

                if (distinctEmployee.Count == 1)
                {
                    empids = distinctEmployee[0].EmployeeID.ToString();
                }
                else
                {
                    foreach (DailyAttnProcess dap in distinctEmployee)
                    {
                        empids += dap.EmployeeID.ToString() + ",";
                    }
                    empids = empids.Trim(',');
                }
                #endregion

                List<DailyAttnProcess> distinctAttnDate = dailyattProcesses
                                              .GroupBy(p => p.AttnDate)
                                              .Select(g => g.First())
                                              .ToList();

                DateTime fromdate = GlobalFunctions.FirstDateOfMonth(distinctAttnDate[0].AttnDate.Date);
                DateTime todate = GlobalFunctions.LastDateOfMonth(distinctAttnDate[0].AttnDate.Date);

                List<Shift> shifts = new ShiftService().GetAllShift();
                string propertyName = string.Empty;
                bool isCalculatedValue = false;
                DateTime applicableMonth = DateTime.MinValue;
                double calculatedfValue = 0;
                _atnMonthlyBenifits = new List<AttnMonthlyBenefit>();
                //     omonthlyWorkPlan = new List<MonthlyWorkPlan>();

                if (distinctAttnDate.Count == 1)
                {
                    //      omonthlyWorkPlan = MonthlyWorkPlan.GetByDate(distinctAttnDate[0].AttnDate.Date);
                    AttnMnthBenefitValueMapper obj_Mapper = new AttnMnthBenefitValueMapper(distinctAttnDate[0].AttnDate.Date, oAttnParam.MonthStartDay, out applicableMonth);
                    _atnMonthlyBenifits = new AttnMonthlyBenefitService().Get(empids, applicableMonth);
                }
                else
                {
                    foreach (DailyAttnProcess daProcess in distinctAttnDate)
                    {
                        DateTime tempTime = DateTime.MinValue;
                        AttnMnthBenefitValueMapper obj_Mapper = new AttnMnthBenefitValueMapper(daProcess.AttnDate.Date, oAttnParam.MonthStartDay, out applicableMonth);
                        List<AttnMonthlyBenefit> _atnMonthlyBenifitTemp = new AttnMonthlyBenefitService().Get(empids, applicableMonth);
                        //        omonthlyWorkPlan.AddRange(MonthlyWorkPlan.GetByDate(daProcess.AttnDate.Date));
                        foreach (AttnMonthlyBenefit itemAMB in _atnMonthlyBenifitTemp)
                        {
                            if (!_atnMonthlyBenifits.Exists(o => o.EmployeeID == itemAMB.EmployeeID && o.SalaryMonth == itemAMB.SalaryMonth && o.ItemType == itemAMB.ItemType && o.ItemID == itemAMB.ItemID))
                            {
                                _atnMonthlyBenifits.Add(itemAMB);
                            }
                        }
                    }
                }
                Employee employee = null;
                foreach (DailyAttnProcess item in dailyattProcesses)
                {
                    employee = item.Employee;
                    PropertyInfo propertyInfo, propertyInfoIs;
                    AttnMnthBenefitValueMapper objMapper = new AttnMnthBenefitValueMapper(item.AttnDate.Date, oAttnParam.MonthStartDay, out applicableMonth);
                    propertyName = objMapper[item.AttnDate];
                    List<AttnWiseAllowance> itemAttnWiseAllowwances = new AttnWiseAllowanceService().GetAllApplicableItem(oAttnWiseAllowances, item);

                    if (itemAttnWiseAllowwances == null) continue;

                    itemAttnWiseAllowwances = itemAttnWiseAllowwances.GroupBy(p => p.ID).Select(g => g.First()).ToList();
                    propertyInfo = typeof(AttnMonthlyBenefit).GetProperties().FirstOrDefault(p => p.Name == propertyName);
                    propertyInfoIs = typeof(AttnMonthlyBenefit).GetProperties().FirstOrDefault(p => p.Name == "Is" + propertyName);

                    List<AttnMonthlyBenefit> _aMBenifits = _atnMonthlyBenifits.Where(o => o.EmployeeID == item.EmployeeID).ToList();
                    if (IsManualEntry == true)
                    {
                        for (int i = 0; i < _aMBenifits.Count(); i++)
                        {
                            calculatedfValue = 0;
                            propertyInfo.SetValue(_aMBenifits[i], 0, null);
                            propertyInfoIs.SetValue(_aMBenifits[i], false, null);
                            _aMBenifits[i] = new AttnMonthlyBenefitService().CalculateTotal(_aMBenifits[i]);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < _aMBenifits.Count(); i++)
                        {
                            calculatedfValue = 0;
                            isCalculatedValue = (bool)propertyInfoIs.GetValue(_aMBenifits[i], null);
                            if (isCalculatedValue) continue;
                            propertyInfo.SetValue(_aMBenifits[i], 0, null);
                            _aMBenifits[i] = new AttnMonthlyBenefitService().CalculateTotal(_aMBenifits[i]);
                        }
                    }

                    foreach (AttnWiseAllowance attSetup in itemAttnWiseAllowwances)
                    {

                        employee = item.Employee;
                        AttnMonthlyBenefit oAttnWiseBenefit = _atnMonthlyBenifits
                                                             .FirstOrDefault(x => x.EmployeeID == item.EmployeeID
                                                              && attSetup.ProvisionID == x.ItemID
                                                              && attSetup.ProvisionType == x.ItemType
                                                              && x.SalaryMonth == GlobalFunctions.GetAttandaceSalaryMonth(item.AttnDate.Date, oAttnParam.MonthStartDay));
                        if (oAttnWiseBenefit == null)
                        {
                            oAttnWiseBenefit = new AttnMonthlyBenefit();
                            oAttnWiseBenefit.EmployeeID = item.EmployeeID;
                            oAttnWiseBenefit.ItemType = attSetup.ProvisionType;
                            oAttnWiseBenefit.ItemID = attSetup.ProvisionID;
                            oAttnWiseBenefit.SalaryMonth = GlobalFunctions.GetAttandaceSalaryMonth(item.AttnDate.Date, oAttnParam.MonthStartDay);
                            _atnMonthlyBenifits.Add(oAttnWiseBenefit);
                        }

                        propertyInfo = typeof(AttnMonthlyBenefit).GetProperties().FirstOrDefault(p => p.Name == propertyName);
                        calculatedfValue = (double)propertyInfo.GetValue(oAttnWiseBenefit, null);
                        propertyInfoIs = typeof(AttnMonthlyBenefit).GetProperties().FirstOrDefault(p => p.Name == "Is" + propertyName);
                        isCalculatedValue = (bool)propertyInfoIs.GetValue(oAttnWiseBenefit, null);
                        if (IsManualEntry == false)
                        {
                            if (isCalculatedValue)
                            {
                                continue;
                            }
                        }
                        if (oAttnWiseBenefit.ItemType == enumPayrollComponentType.Over_Time)
                        {
                            calculatedfValue = new AttnMonthlyBenefitService().CalculateOvertimeValue(attSetup, item, payrollTypeId);
                            propertyInfo.SetValue(oAttnWiseBenefit, calculatedfValue, null);
                        }

                        if (oAttnWiseBenefit.ItemType == enumPayrollComponentType.Allowance)
                        {
                            calculatedfValue = new AttnMonthlyBenefitService().CalculateAllowanceValue(attSetup, item);
                            propertyInfo.SetValue(oAttnWiseBenefit, calculatedfValue, null);
                        }
                        oAttnWiseBenefit = new AttnMonthlyBenefitService().CalculateTotal(oAttnWiseBenefit);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return _atnMonthlyBenifits;
            #endregion
        }

        #endregion
        public static MonthlyWorkPlan GetPlanwithEmployee(DateTime EffectDate, int employeeid,
    List<EmployeeWorkPlanSetup> plans, List<MonthlyWorkPlan> MworkPlans,
    ActingResponsibilitySetup temporaryShiftEmp)
        {

            MonthlyWorkPlan dPlan = null;
            if (temporaryShiftEmp == null)
            {
                EmployeeWorkPlanSetup workGroup = plans.FirstOrDefault(x => x.EmployeeID == employeeid);
                if (workGroup != null)
                {
                    dPlan = MworkPlans.FirstOrDefault(x => x.WorkPlanGroupID == workGroup.WorkPlanGroupID && x.WorkDate == EffectDate);
                    if (dPlan != null)
                        dPlan.EmployeeID = employeeid;

                }
            }
            else
            {
                dPlan = MworkPlans.FirstOrDefault(x => x.WorkPlanGroupID == temporaryShiftEmp.WorkPlanGroupID && x.WorkDate == EffectDate);
                dPlan.EmployeeID = employeeid;
            }
            return dPlan;
        }

        private DateTime? GetShiftInOutTime(List<AttnRawData> RawData, DailyAttnProcess attnProcess, int shiftID, bool InCheck)
        {
            DateTime? Returntime = null;
            Shift oShift = _shifts.FirstOrDefault(x => x.ID == shiftID);
            if (InCheck == true)
            {

                DateTime MinInTime = new DateTime(attnProcess.AttnDate.Year,
                                    attnProcess.AttnDate.Month,
                                    attnProcess.AttnDate.Day,
                                    oShift.InTime.Hour - 3,
                                    0,
                                    0);
                DateTime inDate = attnProcess.AttnDate;
                int hour = oShift.InTime.Hour + 4;
                if (hour > 23)
                {
                    inDate = inDate.AddDays(1);
                    hour = hour - 23;
                }
                DateTime MaxInTime = new DateTime(inDate.Year,
                                    inDate.Month,
                                    inDate.Day,
                                    hour,
                                    0,
                                    0);

                List<AttnRawData> rsts = RawData.Where(x => x.PunchTime > MinInTime && x.PunchTime < MaxInTime).ToList();
                if (rsts != null && rsts.Count > 0) Returntime = rsts.Min(x => x.PunchTime);
            }
            else
            {
                DateTime fromtime = attnProcess.AttnDate;
                int hour = oShift.InTime.Hour + 2;
                if (oShift.InTime.Hour + 2 > 23)
                {
                    fromtime = fromtime.AddDays(1);
                    hour = oShift.InTime.Hour + 2 - 23;
                }

                DateTime MinOutTime = new DateTime(attnProcess.AttnDate.Year,
                                    fromtime.Month,
                                    fromtime.Day,
                                    hour, 0, 0);

                DateTime oDate = attnProcess.AttnDate;
                hour = 23;
                if (oShift.IsOverlapingDay)
                {
                    hour = 11;
                    oDate = attnProcess.AttnDate.AddDays(1);
                }
                else
                {
                    hour = 5;
                    oDate = attnProcess.AttnDate.AddDays(1);
                }
                DateTime MaxOutTime = new DateTime(oDate.Year,
                                   oDate.Month,
                                   oDate.Day,
                                   hour,
                                   0,
                                   0);

                List<AttnRawData> rsts = RawData.Where(x => x.PunchTime > MinOutTime && x.PunchTime < MaxOutTime).ToList();
                if (rsts != null && rsts.Count > 0) Returntime = rsts.Max(x => x.PunchTime);
            }
            return Returntime;


        }

        private void AddError(AttnProcessRunSummary oAttnRunSummary, EnumErrorType enumErrorType,
            string errorDescription, Employee emp)
        {
            if (oAttnRunSummary.AttnProcessRunDetails == null)
                oAttnRunSummary.AttnProcessRunDetails = new List<AttnProcessRunDetail>();

            oAttnRunSummary.AttnProcessRunDetails.Add(new AttnProcessRunDetail()
            {
                EnumErrorType = enumErrorType,
                Description = errorDescription,
                EmployeeNo = emp == null ? string.Empty : emp.EmployeeNo,
                EmployeeName = emp == null ? string.Empty : emp.Name
            });

            if (enumErrorType == EnumErrorType.ServiceException || enumErrorType == EnumErrorType.Exception)
            {
                oAttnRunSummary.ProcessStatus = EnumAttnProcessStatus.Error;
            }
            else
            {
                oAttnRunSummary.ProcessStatus = EnumAttnProcessStatus.SuccessWithError;
            }
        }

        //private void CalcullateOTandWorkHour(DailyAttnProcess attnProcess, bool isOTEligable, DateTime Attdate)
        //{
        //    attnProcess.OTHour = 0;
        //    attnProcess.WorkHour = 0;

        //    if (attnProcess.AttenType == EnumAttendanceType.Present || attnProcess.AttenType == EnumAttendanceType.Late)
        //    {
        //        if (attnProcess.InTime != null && attnProcess.InTime != DateTime.MinValue && attnProcess.OutTime != null && attnProcess.OutTime != DateTime.MinValue)
        //        {
        //            DateTime actualInTime = (DateTime)attnProcess.InTime;

        //            double actualHourWorked = ((DateTime)attnProcess.OutTime).Subtract((DateTime)attnProcess.InTime).TotalHours;

        //            //if (attnProcess.HasDualShift)
        //            //{
        //            //    if (attnProcess.InTime2 != DateTime.MinValue && attnProcess.OutTime2 != DateTime.MinValue)
        //            //    {
        //            //        actualHourWorked += attnProcess.OutTime2.Subtract(attnProcess.InTime2).TotalHours;
        //            //    }
        //            //}
        //            //else if (attnProcess.OutTime2 != DateTime.MinValue)
        //            //{
        //            //    actualHourWorked = attnProcess.OutTime2.Subtract(attnProcess.InTime).TotalHours;
        //            //}


        //            double standardHourWorked = attnProcess.Shift.WorkHour + (attnProcess.Shift.LunchHour / 60.0);
        //            DateTime shiftInTime = ((DateTime)attnProcess.InTime).Date.Add(attnProcess.Shift.InTime.TimeOfDay);
        //            //DateTime shiftOutTime = shiftInTime.AddHours(standardHourWorked);

        //            if (attnProcess.WorkDayType == EnumWorkPlanDayType.WorkingDay)
        //            {
        //                if (actualHourWorked > standardHourWorked)
        //                {
        //                    attnProcess.WorkHour = attnProcess.Shift.WorkHour;
        //                    double minutesBeforeShiftTime = 0;
        //                    double minutesAfterShiftTime = 0;
        //                    double inOTMinutes, outOTMinutes;
        //                    inOTMinutes = outOTMinutes = 0;

        //                    if (actualInTime < shiftInTime)
        //                    {
        //                        minutesBeforeShiftTime = shiftInTime.Subtract(actualInTime).TotalMinutes;
        //                        var minimumOtInMinutes = attnProcess.Shift.MinimumInOTHour;

        //                        if (minimumOtInMinutes == 0)
        //                            inOTMinutes = minutesBeforeShiftTime;
        //                        else
        //                            inOTMinutes = minimumOtInMinutes *
        //                                          Math.Floor((minutesBeforeShiftTime +
        //                                                      attnProcess.Shift.MinimumInGraceTime) /
        //                                                     minimumOtInMinutes);
        //                    }

        //                    if ((actualHourWorked * 60.0) - (standardHourWorked * 60.0) > minutesBeforeShiftTime)
        //                    {
        //                        minutesAfterShiftTime = (actualHourWorked * 60.0) - (standardHourWorked * 60.0) -
        //                                                minutesBeforeShiftTime;
        //                        var minimumOtOutMinutes = attnProcess.Shift.MinimumOutOTHour;

        //                        if (minimumOtOutMinutes == 0)
        //                            outOTMinutes = minutesAfterShiftTime;
        //                        else
        //                            outOTMinutes = minimumOtOutMinutes *
        //                                           Math.Floor((minutesAfterShiftTime +
        //                                                       attnProcess.Shift.MinimumOutGraceTime) /
        //                                                      minimumOtOutMinutes);
        //                    }

        //                    if (inOTMinutes + outOTMinutes > 0)
        //                    {
        //                        attnProcess.OTHour = (inOTMinutes + outOTMinutes) / 60.0;
        //                    }
        //                }
        //                else
        //                {
        //                    attnProcess.WorkHour = actualHourWorked - (attnProcess.Shift.LunchHour / 60.0);
        //                }
        //            }
        //            else
        //            {
        //                double minutesBeforeShiftTime = 0;
        //                double minutesAfterShiftTime = 0;
        //                double inOTMinutes, outOTMinutes;
        //                inOTMinutes = outOTMinutes = 0;

        //                if (actualInTime < shiftInTime)
        //                {
        //                    minutesBeforeShiftTime = shiftInTime.Subtract(actualInTime).TotalMinutes;
        //                    var minimumOtInMinutes = attnProcess.Shift.MinimumInOTHour;

        //                    if (minimumOtInMinutes == 0)
        //                        inOTMinutes = minutesBeforeShiftTime;
        //                    else
        //                        inOTMinutes = minimumOtInMinutes *
        //                                      Math.Floor(
        //                                          (minutesBeforeShiftTime + attnProcess.Shift.MinimumInGraceTime) /
        //                                          minimumOtInMinutes);
        //                }

        //                if ((actualHourWorked * 60.0) - (standardHourWorked * 60.0) > minutesBeforeShiftTime)
        //                {
        //                    minutesAfterShiftTime = (actualHourWorked * 60.0) - (standardHourWorked * 60.0) -
        //                                            minutesBeforeShiftTime;
        //                    var minimumOtOutMinutes = attnProcess.Shift.MinimumOutOTHour;

        //                    if (minimumOtOutMinutes == 0)
        //                        outOTMinutes = minutesAfterShiftTime;
        //                    else
        //                        outOTMinutes = minimumOtOutMinutes *
        //                                       Math.Floor(
        //                                           (minutesAfterShiftTime + attnProcess.Shift.MinimumOutGraceTime) /
        //                                           minimumOtOutMinutes);
        //                }

        //                var regualarMinutes = (actualHourWorked * 60) - minutesBeforeShiftTime - minutesAfterShiftTime;

        //                //Holiday OT applicable after 6 Hours
        //                if (actualHourWorked >= 6)
        //                {
        //                    attnProcess.OTHour = ((regualarMinutes + inOTMinutes + outOTMinutes) / 60.0) -
        //                                         (attnProcess.Shift.LunchHour / 60.0);
        //                }
        //                else
        //                {
        //                    attnProcess.WorkHour = actualHourWorked;
        //                }
        //            }


        //            attnProcess.OTHour = attnProcess.OTHour > 0 && isOTEligable ? attnProcess.OTHour : 0;
        //            attnProcess.WorkHour = attnProcess.WorkHour < 0
        //                ? 0
        //                : attnProcess.WorkHour - (attnProcess.AttenType == EnumAttendanceType.Late ? 1 : 0);
        //        }
        //    }
        //}

        private int GetAppropriateShiftID(List<Shift> oShifts, int currentShiftID, DateTime inTime)
        {
            int shiftID = currentShiftID;
            var currentShift = oShifts.FirstOrDefault(x => x.ID == shiftID);
            double minuteDifference = 24 * 60;
            if (currentShift != null)
            {
                minuteDifference = Math.Abs((new DateTime(inTime.Year, inTime.Month, inTime.Day,
                        currentShift.InTime.Hour, currentShift.InTime.Minute, currentShift.InTime.Second) - inTime)
                    .TotalMinutes);
            }

            foreach (var shift in oShifts)
            {
                var shiftInTime = new DateTime(inTime.Year, inTime.Month, inTime.Day, shift.InTime.Hour,
                    shift.InTime.Minute, shift.InTime.Second);
                // +/- 10 minutes 
                if ((Math.Abs((shiftInTime - inTime).TotalMinutes) + 10) < minuteDifference)
                {
                    minuteDifference = Math.Abs((shiftInTime - inTime).TotalMinutes);
                    shiftID = shift.ID;
                }
            }

            return shiftID;
        }

        private List<Shift> GetLocationTypewiseShifts(List<Shift> shifts, int shiftID)
        {
            List<Shift> oSameLocationShifts = new List<Shift>();
            if (shifts.Any(x => x.ID == shiftID))
            {
                var locationType = shifts.First(x => x.ID == shiftID).Location;
                oSameLocationShifts = shifts.Where(x => x.Location == locationType).ToList();
            }

            return oSameLocationShifts;
        }


        public static void GetAttendanceDateRange(out DateTime startDate, out DateTime endDate)
        {
            startDate = endDate = DateTime.MinValue;
            startDate = DateTime.Today.AddDays(-7);
            endDate = DateTime.Today;
        }


        public static List<DailyAttnProcess>
            GetNotSubmittedAttnData(Employee oEmp, DateTime fromDate, DateTime toDate) //,bool isCurrentMonth)
        {
            if (oEmp == null)
            {
                throw new CustomException(EnumExceptionType.Validation, "No Employee selected.");
            }

            List<DailyAttnProcess> oNotYetSubmittedAttnDatas =
                new DailyAttnProcessService().GetAttnDataByWFStatus(fromDate, toDate, oEmp.ID.ToString(),
                    EnumWFAttnStatus.None);

            return oNotYetSubmittedAttnDatas;
        }


        //public List<AttnMonthlyBenefit> AttnMonthlyBenefitProcess(List<DailyAttnProcess> dailyattProcesses,
        //    bool IsManualEntry, int payrollTypeID)
        //{
        //    List<DailyAttnProcess> tempATT = new List<DailyAttnProcess>();
        //    List<AttnNationalHoliday> attNHolidays = null;
        //    List<ActingResponsibilitySetup> _tempShiftEmployees = null;
        //    List<EmployeeWorkPlanSetup> _EmployeeWorkPlanSetups = null;
        //    EmployeeWorkPlanSetup ewps = null;
        //    AttnShiftWiseNationalHoliday attnShiftHoliday = null;
        //    List<MonthlyWorkPlan> _monthlyWorkPlan = null;
        //    MonthlyWorkPlan monthlyWorkPlanActual = null;
        //    MonthlyWorkPlan monthlyWorkPlanTemp = null;
        //    Shift temporaryShift = null;
        //    bool IsWorkingDay = true;

        //    #region AttnMonthlyBenefit Process

        //    string empids = string.Empty;
        //    //double totalOT = 0;
        //    DateTime tempIntime = DateTime.MinValue;
        //    DateTime tempOuttime = DateTime.MinValue;
        //    DateTime outTime = DateTime.MinValue;
        //    try
        //    {
        //        List<DailyAttnProcess> distinctEmployee = dailyattProcesses
        //            .GroupBy(p => p.EmployeeID)
        //            .Select(g => g.First())
        //            .ToList();

        //        List<DailyAttnProcess> distinctAttnDate = dailyattProcesses
        //            .GroupBy(p => p.AttnDate)
        //            .Select(g => g.First())
        //            .ToList();
        //        if (distinctEmployee.Count == 1)
        //        {
        //            empids = distinctEmployee[0].EmployeeID.ToString();
        //        }
        //        else
        //        {
        //            foreach (DailyAttnProcess dap in distinctEmployee)
        //            {
        //                empids += dap.EmployeeID.ToString() + ",";
        //            }

        //            empids = empids.Trim(',');
        //        }

        //        DateTime fromdate = GlobalFunctions.FirstDateOfMonth(distinctAttnDate[0].AttnDate.Date);
        //        DateTime todate = GlobalFunctions.LastDateOfMonth(distinctAttnDate[0].AttnDate.Date);
        //        attNHolidays =
        //            new AttnNationalHolidayService().GetByMonthAndPayrollType(fromdate, todate, payrollTypeID);
        //        List<Shift> shifts = new ShiftService().Get(string.Empty, string.Empty, EnumStatus.Regardless, payrollTypeID);
        //        string propertyName = string.Empty;
        //        bool isCalculatedValue = false;
        //        DateTime applicableMonth = DateTime.MinValue;
        //        double calculatedfValue = 0;
        //        _atnMonthlyBenifits = new List<AttnMonthlyBenefit>();
        //        _tempShiftEmployees = new List<ActingResponsibilitySetup>();
        //        _EmployeeWorkPlanSetups = new EmployeeWorkPlanSetupService().Get();
        //        _monthlyWorkPlan = new List<MonthlyWorkPlan>();
        //        if (distinctAttnDate.Count == 1)
        //        {
        //            //  _monthlyWorkPlan = new MonthlyWorkPlanService().GetByDate(distinctAttnDate[0].AttnDate.Date);
        //            AttnMnthBenefitValueMapper obj_Mapper =
        //                new AttnMnthBenefitValueMapper(distinctAttnDate[0].AttnDate.Date, out applicableMonth);
        //            _atnMonthlyBenifits = new AttnMonthlyBenefitService().Get(empids, applicableMonth);
        //        }
        //        else
        //        {
        //            foreach (DailyAttnProcess daProcess in distinctAttnDate)
        //            {
        //                DateTime tempTime = DateTime.MinValue;
        //                AttnMnthBenefitValueMapper obj_Mapper =
        //                    new AttnMnthBenefitValueMapper(daProcess.AttnDate.Date, out applicableMonth);
        //                List<AttnMonthlyBenefit> _atnMonthlyBenifitTemp =
        //                    new AttnMonthlyBenefitService().Get(empids, applicableMonth);
        //                //   _monthlyWorkPlan.AddRange(new MonthlyWorkPlanService().GetByDate(daProcess.AttnDate.Date));
        //                foreach (AttnMonthlyBenefit itemAMB in _atnMonthlyBenifitTemp)
        //                {
        //                    if (!_atnMonthlyBenifits.Exists(o =>
        //                        o.EmployeeID == itemAMB.EmployeeID && o.SalaryMonth == itemAMB.SalaryMonth &&
        //                        o.ItemType == itemAMB.ItemType && o.ItemID == itemAMB.ItemID))
        //                    {
        //                        _atnMonthlyBenifits.Add(itemAMB);
        //                    }
        //                }
        //            }
        //        }

        //        AttnNationalHoliday oAttNHoliday = null;
        //        List<AttnWiseAllowance> oAttnWiseAllowances = new List<AttnWiseAllowance>();
        //        oAttnWiseAllowances = new AttnWiseAllowanceService().Get(payrollTypeID);
        //        Employee employee = null;
        //        List<Leave> oLeaves =
        //            new LeaveService().Get(EnumStatus.Regardless, string.Empty, string.Empty, payrollTypeID);
        //        foreach (DailyAttnProcess item in dailyattProcesses)
        //        {
        //            ewps = _EmployeeWorkPlanSetups.Where(o => o.EmployeeID == item.EmployeeID).FirstOrDefault();
        //            if (ewps == null)
        //            {
        //                //throw new Exception("Employee WorkPlan Not Defined for " + employee.EmployeeNo);
        //                continue;
        //            }


        //            //totalOT = 0;
        //            employee = item.Employee;
        //            attnShiftHoliday = null;

        //            monthlyWorkPlanActual = _monthlyWorkPlan.Where(o =>
        //                o.WorkPlanGroupID == ewps.WorkPlanGroupID && o.WorkDate == item.AttnDate.Date).FirstOrDefault();
        //            temporaryShift = null;
        //            PropertyInfo propertyInfo;
        //            PropertyInfo propertyInfoIs;
        //            AttnMnthBenefitValueMapper objMapper =
        //                new AttnMnthBenefitValueMapper(item.AttnDate.Date, out applicableMonth);
        //            propertyName = objMapper[item.AttnDate];

        //            if (attNHolidays.Count > 0)
        //                oAttNHoliday = attNHolidays.Where(o =>
        //                        item.AttnDate.Date >= o.FromDate.Date && item.AttnDate.Date <= o.ToDate.Date)
        //                    .FirstOrDefault();
        //            if (oAttNHoliday != null && oAttNHoliday.AttnShiftWiseNationalHolidays.Count > 0)
        //            {
        //                //if (item.TempShiftID != null)
        //                //{
        //                //    monthlyWorkPlanTemp = _monthlyWorkPlan.Where(o =>
        //                //        o.WorkDate == item.AttnDate.Date && o.Type == item.WorkDayType &&
        //                //        o.ShiftID == item.TempShiftID).FirstOrDefault();
        //                //    if (monthlyWorkPlanTemp != null)
        //                //        attnShiftHoliday = oAttNHoliday.AttnShiftWiseNationalHolidays
        //                //            .Where(o => o.WorkPlanGroupID == monthlyWorkPlanTemp.WorkPlanGroupID)
        //                //            .FirstOrDefault();
        //                //}
        //                //else
        //                attnShiftHoliday = oAttNHoliday.AttnShiftWiseNationalHolidays
        //                    .Where(o => o.WorkPlanGroupID == monthlyWorkPlanActual.WorkPlanGroupID)
        //                    .FirstOrDefault();

        //                if (attnShiftHoliday == null)
        //                    oAttNHoliday = null;
        //            }

        //            List<AttnWiseAllowance> itemAttnWiseAllowwances =
        //                AttnWiseAllowanceService.GetAllApplicableItem(oAttnWiseAllowances, item, oAttNHoliday, oLeaves,
        //                    IsWorkingDay);

        //            if (itemAttnWiseAllowwances == null) continue;

        //            itemAttnWiseAllowwances = itemAttnWiseAllowwances
        //                .GroupBy(p => p.ID)
        //                .Select(g => g.First())
        //                .ToList();
        //            // Make Zero of Current Date
        //            propertyInfo = typeof(AttnMonthlyBenefit).GetProperties()
        //                .FirstOrDefault(p => p.Name == propertyName);
        //            propertyInfoIs = typeof(AttnMonthlyBenefit).GetProperties()
        //                .FirstOrDefault(p => p.Name == "Is" + propertyName);

        //            List<AttnMonthlyBenefit> _aMBenifits =
        //                _atnMonthlyBenifits.Where(o => o.EmployeeID == item.EmployeeID).ToList();
        //            if (IsManualEntry == true)
        //            {
        //                foreach (AttnMonthlyBenefit attnMB in _aMBenifits)
        //                {
        //                    calculatedfValue = 0;
        //                    propertyInfo.SetValue(attnMB, 0, null);
        //                    propertyInfoIs.SetValue(attnMB, false, null);
        //                    attnMB.Total = attnMB.Value1 + attnMB.Value2 + attnMB.Value3 + attnMB.Value4 +
        //                                   attnMB.Value5 + attnMB.Value6 + attnMB.Value7 + attnMB.Value8 +
        //                                   attnMB.Value9 + attnMB.Value10
        //                                   + attnMB.Value11 + attnMB.Value12 + attnMB.Value13 + attnMB.Value14 +
        //                                   attnMB.Value15 + attnMB.Value16 + attnMB.Value17 + attnMB.Value18 +
        //                                   attnMB.Value19 + attnMB.Value20
        //                                   + attnMB.Value21 + attnMB.Value22 + attnMB.Value23 + attnMB.Value24 +
        //                                   attnMB.Value25 + attnMB.Value26 + attnMB.Value27 + attnMB.Value28 +
        //                                   attnMB.Value29 + attnMB.Value30
        //                                   + attnMB.Value31 + attnMB.Adjustment;
        //                }
        //            }
        //            else
        //            {
        //                foreach (AttnMonthlyBenefit attnMB in _aMBenifits)
        //                {
        //                    calculatedfValue = 0;
        //                    isCalculatedValue = (bool)propertyInfoIs.GetValue(attnMB, null);
        //                    if (isCalculatedValue) continue;
        //                    propertyInfo.SetValue(attnMB, 0, null);
        //                    attnMB.Total = attnMB.Value1 + attnMB.Value2 + attnMB.Value3 + attnMB.Value4 +
        //                                   attnMB.Value5 + attnMB.Value6 + attnMB.Value7 + attnMB.Value8 +
        //                                   attnMB.Value9 + attnMB.Value10
        //                                   + attnMB.Value11 + attnMB.Value12 + attnMB.Value13 + attnMB.Value14 +
        //                                   attnMB.Value15 + attnMB.Value16 + attnMB.Value17 + attnMB.Value18 +
        //                                   attnMB.Value19 + attnMB.Value20
        //                                   + attnMB.Value21 + attnMB.Value22 + attnMB.Value23 + attnMB.Value24 +
        //                                   attnMB.Value25 + attnMB.Value26 + attnMB.Value27 + attnMB.Value28 +
        //                                   attnMB.Value29 + attnMB.Value30
        //                                   + attnMB.Value31 + attnMB.Adjustment;
        //                }
        //            }

        //            //if (totalOT > 0 && (item.AttenType == EnumAttendanceType.Leave || item.AttenType == EnumAttendanceType.Absent || item.AttenType == EnumAttendanceType.WeeklyHoliday))
        //            //{
        //            //    if (!itemAttnWiseAllowwances.Exists(o => o.ProvisionType == enumPayrollComponentType.Allowance && o.ProvisionID == 82))
        //            //    {
        //            //        itemAttnWiseAllowwances.Add(oAttnWiseAllowances.Where(o => o.ProvisionType == enumPayrollComponentType.Allowance && o.ProvisionID == 82).FirstOrDefault());
        //            //    }
        //            //}

        //            //if (item.TempShiftID != null)
        //            //{
        //            //    if (totalOT == 0 && monthlyWorkPlanActual.Type == EnumWorkPlanDayType.WeeklyHoliday)
        //            //    {
        //            //        itemAttnWiseAllowwances.RemoveAll(o => o.ProvisionType == enumPayrollComponentType.Allowance && o.ProvisionID == 107);
        //            //    }
        //            //    if (monthlyWorkPlanActual.Type == EnumWorkPlanDayType.WorkingDay && monthlyWorkPlanActual.Shift.IsOverlapingDay == true && (item.AttenType == EnumAttendanceType.Present || item.AttenType == EnumAttendanceType.WeeklyHoliday) && item.AttenType != EnumAttendanceType.Absent)
        //            //    {
        //            //        if (!itemAttnWiseAllowwances.Exists(o => o.ProvisionType == enumPayrollComponentType.Allowance && o.ProvisionID == 107))
        //            //        {
        //            //            itemAttnWiseAllowwances.Add(oAttnWiseAllowances.Where(o => o.ProvisionType == enumPayrollComponentType.Allowance && o.ProvisionID == 107).FirstOrDefault());
        //            //        }
        //            //    }
        //            //}

        //            foreach (AttnWiseAllowance attSetup in itemAttnWiseAllowwances)
        //            {
        //                employee = item.Employee;
        //                AttnMonthlyBenefit oAttnWiseBenefit = _atnMonthlyBenifits
        //                    .FirstOrDefault(x => x.EmployeeID == item.EmployeeID
        //                                         && attSetup.ProvisionID == x.ItemID
        //                                         && attSetup.ProvisionType == x.ItemType
        //                                         && x.SalaryMonth ==
        //                                         GlobalFunctions.AttendanceMonthEnd(item.AttnDate.Date));
        //                //if  oAttnWiseBenefit is not null and IsEdited true for the selected date, then continue

        //                if (oAttnWiseBenefit == null)
        //                {
        //                    oAttnWiseBenefit = new AttnMonthlyBenefit();
        //                    oAttnWiseBenefit.EmployeeID = item.EmployeeID;
        //                    oAttnWiseBenefit.ItemType = attSetup.ProvisionType;
        //                    oAttnWiseBenefit.ItemID = attSetup.ProvisionID;
        //                    oAttnWiseBenefit.SalaryMonth = GlobalFunctions.AttendanceMonthEnd(item.AttnDate.Date);
        //                    _atnMonthlyBenifits.Add(oAttnWiseBenefit);
        //                }

        //                propertyInfo = typeof(AttnMonthlyBenefit).GetProperties()
        //                    .FirstOrDefault(p => p.Name == propertyName);
        //                calculatedfValue = (double)propertyInfo.GetValue(oAttnWiseBenefit, null);
        //                propertyInfoIs = typeof(AttnMonthlyBenefit).GetProperties()
        //                    .FirstOrDefault(p => p.Name == "Is" + propertyName);
        //                isCalculatedValue = (bool)propertyInfoIs.GetValue(oAttnWiseBenefit, null);
        //                if (IsManualEntry == false)
        //                {
        //                    if (isCalculatedValue)
        //                    {
        //                        continue;
        //                    }
        //                }
        //                //else
        //                //{
        //                //if (attSetup.ProvisionType == enumPayrollComponentType.Over_Time)
        //                //{
        //                //    if (isCalculatedValue)
        //                //    {
        //                //        continue;
        //                //    }
        //                //}
        //                //}
        //                //Shift sft = shifts.Where(o => o.ID == item.ShiftID).FirstOrDefault();
        //                //if (item.TempShiftID != null)
        //                //    temporaryShift = shifts.Where(o => o.ID == item.TempShiftID).FirstOrDefault();
        //                //if (temporaryShift != null && attSetup.ProvisionType == enumPayrollComponentType.Ordinary_Hour)
        //                //    calculatedfValue = attSetup.GetCalculatedHour(item, temporaryShift, oLeaves);
        //                //else
        //                //    calculatedfValue = attSetup.GetCalculatedHour(item, sft, oLeaves);

        //                //#region InsurancePolicy
        //                //The reason behind this code block: Sometimes employee don't get their applicable conveyance even if he/she is present. 
        //                //if (attSetup.ProvisionType == enumPayrollComponentType.Allowance && attSetup.ProvisionID == AttendanceBenefitTypeIDConstant.Conveyance_Allowance && calculatedfValue == 0)
        //                //{
        //                //    if (item.AttenType == EnumAttendanceType.Present && item.InTime != DateTime.MinValue && item.OutTime != DateTime.MinValue)
        //                //    {
        //                //        calculatedfValue = 1;
        //                //        propertyInfoIs.SetValue(oAttnWiseBenefit, true, null);
        //                //    }
        //                //}

        //                //if (attSetup.ProvisionType == enumPayrollComponentType.Ordinary_Hour)
        //                //    item.ORDHour = calculatedfValue;

        //                //#endregion
        //                //if (calculatedfValue > 0 || newValue >0)
        //                //{

        //                if (oAttnWiseBenefit.ItemType == enumPayrollComponentType.Over_Time)
        //                {
        //                    calculatedfValue = new AttnMonthlyBenefitService().CalculateOvertimeValue(attSetup, item, payrollTypeID);
        //                }

        //                propertyInfo.SetValue(oAttnWiseBenefit, calculatedfValue, null);
        //                oAttnWiseBenefit.Total =
        //                    oAttnWiseBenefit.Value1 + oAttnWiseBenefit.Value2 + oAttnWiseBenefit.Value3 +
        //                    oAttnWiseBenefit.Value4 + oAttnWiseBenefit.Value5 + oAttnWiseBenefit.Value6 +
        //                    oAttnWiseBenefit.Value7 + oAttnWiseBenefit.Value8 + oAttnWiseBenefit.Value9 +
        //                    oAttnWiseBenefit.Value10
        //                    + oAttnWiseBenefit.Value11 + oAttnWiseBenefit.Value12 + oAttnWiseBenefit.Value13 +
        //                    oAttnWiseBenefit.Value14 + oAttnWiseBenefit.Value15 + oAttnWiseBenefit.Value16 +
        //                    oAttnWiseBenefit.Value17 + oAttnWiseBenefit.Value18 + oAttnWiseBenefit.Value19 +
        //                    oAttnWiseBenefit.Value20
        //                    + oAttnWiseBenefit.Value21 + oAttnWiseBenefit.Value22 + oAttnWiseBenefit.Value23 +
        //                    oAttnWiseBenefit.Value24 + oAttnWiseBenefit.Value25 + oAttnWiseBenefit.Value26 +
        //                    oAttnWiseBenefit.Value27 + oAttnWiseBenefit.Value28 + oAttnWiseBenefit.Value29 +
        //                    oAttnWiseBenefit.Value30
        //                    + oAttnWiseBenefit.Value31 + oAttnWiseBenefit.Adjustment;

        //                if (oAttnWiseBenefit.ItemType == enumPayrollComponentType.Over_Time)
        //                {
        //                    oAttnWiseBenefit.Amount =
        //                        AttnMonthlyBenefitService.CalculateOvertimeAmount(attSetup, item,
        //                            oAttnWiseBenefit.Total, payrollTypeID);
        //                }

        //                //}
        //            }
        //        }

        //        // process go here
        //    }
        //    catch (Exception ex)
        //    {
        //        throw new Exception(ex.Message);
        //    }


        //    return _atnMonthlyBenifits;

        //    #endregion
        //}

        public static void RefreshAttendanceRegularizationApplyObject(AttendanceRegularizationDTO attendanceRegularizationDTO, DailyAttnProcess dailyAttnProcess)
        {
            bool isChanged = false;
            DateTime tempDateTime = DateTime.MinValue;
            EnumAttendanceType previousStatus;
            DateTime? previousInTime = DateTime.MinValue;
            DateTime? previousOutTime = DateTime.MinValue;
            previousInTime = dailyAttnProcess.InTime;
            previousOutTime = dailyAttnProcess.OutTime;
            previousStatus = dailyAttnProcess.AttenType;
            dailyAttnProcess.IsManualEntry = true;
            EnumAttendanceType value = attendanceRegularizationDTO.Status;
            dailyAttnProcess.AttenType = value;
            if (previousStatus != value)
                isChanged = true;
            if (!string.IsNullOrEmpty(attendanceRegularizationDTO.Comments))
            {
                dailyAttnProcess.Comments = attendanceRegularizationDTO.Comments;
                isChanged = true;
            }

            if (attendanceRegularizationDTO.InTime != null && attendanceRegularizationDTO.InTime != DateTime.MinValue)
            {
                if (attendanceRegularizationDTO.InTime != null)
                {
                    tempDateTime = (DateTime)attendanceRegularizationDTO.InTime;
                    dailyAttnProcess.InTime = new DateTime(dailyAttnProcess.AttnDate.Year, dailyAttnProcess.AttnDate.Month, dailyAttnProcess.AttnDate.Day, tempDateTime.Hour, tempDateTime.Minute, tempDateTime.Second);
                }
            }

            if (attendanceRegularizationDTO.OutTime != DateTime.MinValue)
            {
                if (attendanceRegularizationDTO.OutTime != null)
                {
                    dailyAttnProcess.OutTime = (DateTime)attendanceRegularizationDTO.OutTime;
                }
            }
            if (previousInTime != dailyAttnProcess.InTime)
                isChanged = true;
            if (previousOutTime != dailyAttnProcess.OutTime)
                isChanged = true;

            if (isChanged == true)
            {
                dailyAttnProcess.ActualInTime = previousInTime;
                dailyAttnProcess.ActualOutTime = previousOutTime;
                dailyAttnProcess.WFStatus = EnumWFAttnStatus.EmpSubmitted;
            }
            else
            {
                dailyAttnProcess.WFStatus = EnumWFAttnStatus.NotApplicable;
            }
        }

        public static void RefreshAttendanceRegularizationApproveOrRejectObject(AttendanceRegularizationDTO attendanceRegularizationDTO,
            DailyAttnProcess dailyAttnProcess)
        {
            bool isChanged = false;
            EnumAttendanceType previousStatus;
            DateTime? previousInTime = dailyAttnProcess.InTime;
            DateTime? previousOutTime = dailyAttnProcess.OutTime;
            previousStatus = dailyAttnProcess.AttenType;
            dailyAttnProcess.IsManualEntry = true;
            EnumAttendanceType value = attendanceRegularizationDTO.Status;
            dailyAttnProcess.AttenType = value;
            if (previousStatus != value)
                isChanged = true;
            if (!string.IsNullOrEmpty(attendanceRegularizationDTO.LMRemarks))
            {
                dailyAttnProcess.LMRemarks = attendanceRegularizationDTO.LMRemarks;
                isChanged = true;
            }

            if (attendanceRegularizationDTO.InTime != null && attendanceRegularizationDTO.InTime != DateTime.MinValue)
            {
                if (attendanceRegularizationDTO.InTime != null)
                {
                    DateTime tempDateTime = (DateTime)attendanceRegularizationDTO.InTime;
                    dailyAttnProcess.InTime = new DateTime(dailyAttnProcess.AttnDate.Year, dailyAttnProcess.AttnDate.Month, dailyAttnProcess.AttnDate.Day, tempDateTime.Hour, tempDateTime.Minute, tempDateTime.Second);
                }
            }

            if (attendanceRegularizationDTO.OutTime != DateTime.MinValue)
            {
                if (attendanceRegularizationDTO.OutTime != null)
                {
                    dailyAttnProcess.OutTime = (DateTime)attendanceRegularizationDTO.OutTime;
                }
            }
            if (previousInTime != dailyAttnProcess.InTime)
                isChanged = true;
            if (previousOutTime != dailyAttnProcess.OutTime)
                isChanged = true;
            dailyAttnProcess.WFStatus = attendanceRegularizationDTO.WFStatus;
            if (isChanged == true)
            {
                dailyAttnProcess.ActualInTime = previousInTime;
                dailyAttnProcess.ActualOutTime = previousOutTime;

            }
        }


        public static List<AttendanceRegularizationDTO> GetNotSubmittedAttnData(List<DailyAttnProcess> dailyAttnProcesses, int payrollTypeId)
        {
            List<AttendanceRegularizationDTO> attendanceRegularizationDTOs = new List<AttendanceRegularizationDTO>();
            List<Shift> Shifts = new ShiftService().GetAllShift();
            List<Leave> oLeaves = new LeaveService().GetAll();
            List<AttnNationalHoliday> nationalHolidays = new AttnNationalHolidayService().Get(EnumStatus.Regardless, payrollTypeId);

            foreach (DailyAttnProcess dailyAttnProcess in dailyAttnProcesses)
            {
                Shift shift = Shifts.FirstOrDefault(x => x.ID == dailyAttnProcess.ShiftID);

                AttendanceRegularizationDTO attendanceRegularizationDTO = new AttendanceRegularizationDTO();
                attendanceRegularizationDTO.DailyAttnProcessID = dailyAttnProcess.ID;

                attendanceRegularizationDTO.AttendanceDate = dailyAttnProcess.AttnDate.ToString("dd MMM yyyy");
                attendanceRegularizationDTO.Shift = shift != null ? shift.Name : string.Empty;
                attendanceRegularizationDTO.InTime = dailyAttnProcess.InTime != null ? dailyAttnProcess.InTime : null;
                attendanceRegularizationDTO.OutTime = dailyAttnProcess.OutTime != null ? dailyAttnProcess.OutTime : null;
                attendanceRegularizationDTO.lateHour = dailyAttnProcess.LateHour;
                attendanceRegularizationDTO.earlyHour = dailyAttnProcess.EarlyHour;
                attendanceRegularizationDTO.workHour = dailyAttnProcess.WorkHour;
                attendanceRegularizationDTO.otHour = dailyAttnProcess.OTHour;
                attendanceRegularizationDTO.IsLate = dailyAttnProcess.IsLate;




                attendanceRegularizationDTO.ActualInTime = dailyAttnProcess.ActualInTime != null ? dailyAttnProcess.ActualInTime : null;
                attendanceRegularizationDTO.ActualOutTime = dailyAttnProcess.ActualOutTime != null ? dailyAttnProcess.ActualOutTime : null;
                attendanceRegularizationDTO.WFStatus = dailyAttnProcess.WFStatus;
                attendanceRegularizationDTO.WFStatusDescription = DailyAttnProcess.getWFstatusDescription(dailyAttnProcess.WFStatus);
                attendanceRegularizationDTO.Status = dailyAttnProcess.AttenType;
                attendanceRegularizationDTO.StatusDescription = dailyAttnProcess.AttenType.ToString();
                attendanceRegularizationDTO.Comments = dailyAttnProcess.Comments;
                attendanceRegularizationDTO.LMRemarks = dailyAttnProcess.LMRemarks;
                attendanceRegularizationDTO.empRemarks = dailyAttnProcess.EmpRemarks;
                if (dailyAttnProcess.AttenType == EnumAttendanceType.Leave && dailyAttnProcess.ReferenceID != null)
                {
                    Leave oLeave = oLeaves.Where(o => o.ID == dailyAttnProcess.ReferenceID).FirstOrDefault();
                    attendanceRegularizationDTO.ReferenceId = (int)dailyAttnProcess.ReferenceID;
                    attendanceRegularizationDTO.Reference = oLeave == null ? "" : oLeave.Description;
                }
                else if (dailyAttnProcess.AttenType == EnumAttendanceType.Holiday && dailyAttnProcess.ReferenceID != null)
                {
                    AttnNationalHoliday nationalHoliday = nationalHolidays.Where(o => o.ID == dailyAttnProcess.ReferenceID).FirstOrDefault();
                    attendanceRegularizationDTO.ReferenceId = (int)dailyAttnProcess.ReferenceID;
                    attendanceRegularizationDTO.Reference = nationalHoliday == null ? "" : nationalHoliday.Description;
                }
                else
                {
                    attendanceRegularizationDTO.ReferenceId = 0;
                    attendanceRegularizationDTO.Reference = string.Empty;
                }
                attendanceRegularizationDTOs.Add(attendanceRegularizationDTO);
            }
            return attendanceRegularizationDTOs;
        }
        public static List<DailyAttnProcess> GetNotSubmittedAttnDataForLM(string oEmps, DateTime fromDate, DateTime toDate) //,bool isCurrentMonth)
        {
            if (oEmps == "")
            {
                throw new CustomException(EnumExceptionType.Validation, "No Employee selected.");
            }
            List<DailyAttnProcess> oNotYetSubmittedAttnDatas = new DailyAttnProcessService().GetAttnDataByWFStatusForLM(fromDate, toDate, oEmps, EnumWFAttnStatus.EmpSubmitted);

            return oNotYetSubmittedAttnDatas;
        }


        public List<SalaryProcessStatus> BenifitProcess(int userid, int PayrollTypeId)
        {
            try
            {
                List<SalaryProcessStatus> ErrorList = new List<SalaryProcessStatus>();
                List<ADParameterEmployee> AdparamEmployee = new List<ADParameterEmployee>();
                List<EmployeeUnAuthorizeLeave> uleaves = new List<EmployeeUnAuthorizeLeave>();
                List<EmployeeOverTime> EmpOverTimes = new List<EmployeeOverTime>();
                DailyAttnProcessService dapService = new DailyAttnProcessService();
                TermParameterService tps = new TermParameterService();
                AttnWiseAllowance attnAllow = new AttnWiseAllowance();

                //  List<Employee> employees = new EmployeeService().GetByEmpIDs("352,70");
                 List<Employee> employees = new EmployeeService().GetAllEmps();
                List<ADParameter> oadParameters = new ADParameterService().GetWithDetail(EnumStatus.Active, PayrollTypeId);
                PayrollType oPayrollType = new PayrollTypeService().Get(PayrollTypeId);
                List<TermParameter> termParameters = tps.GetwithDetail(oPayrollType.ID);
                AttnParametarization oAttnParam = new AttnParametarizationService().Get(oPayrollType.ID);

                DateTime attnStartDate = GlobalFunctions.AttendanceMonthStart(GlobalExtensions.FirstDateOfMonth(oPayrollType.NextPayProcessDate), oAttnParam.MonthStartDay);
                DateTime attnEndDate = GlobalFunctions.AttendanceMonthEnd(attnStartDate.AddDays(1), oAttnParam.MonthStartDay);

                List<UnAuthorizeLeaveParam> oauthParams = new UnAuthorizeLeaveParamService().Get(oPayrollType.ID, true);
                DateTime nextPayMonth = oPayrollType.NextPayProcessDate;

                if (oauthParams == null || oauthParams.Count == 0)
                {
                    ErrorList.Add(new SalaryProcessStatus("", "", " No Authorize Leave parameter found"));
                }

                #region Absent Deduct
 
                    DataSet EmpAbsentDays = dapService.GetUnauthorizeCount(attnStartDate, attnEndDate,  oPayrollType.ID);
                    if (EmpAbsentDays != null
                    && EmpAbsentDays.Tables[0] != null
                    && EmpAbsentDays.Tables[0].Rows.Count > 0
                    && oauthParams.Count > 0)
                    {

                        foreach (DataRow oRow in EmpAbsentDays.Tables[0].Rows)
                        {
                            Employee oemp = employees.FirstOrDefault(x => x.ID == Convert.ToInt32(oRow["EMPLOYEEID"].ToString()));
                            if (oemp == null)
                            {
                                ErrorList.Add(new SalaryProcessStatus("", "", " Employee not found, Internal ID:" + oRow["EMPLOYEEID"].ToString()));
                                continue;
                            }

                            double tempAmount = 0;
                            double absentAcount = 0;
                            double provAbsent = 0;
                            if (oAttnParam.AbsentProvLeaveID != null && (oemp.ConfirDate == DateTime.MinValue || (oemp.ConfirDate >
                                attnStartDate && oemp.ConfirDate < attnEndDate)))
                            {

                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, (int)oAttnParam.AbsentProvLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Absent Provisional Parameter not found."));
                                    continue;
                                }
                                absentAcount = dapService.AbsentCount(attnStartDate, (DateTime)oemp.ConfirDate == DateTime.MinValue ? attnEndDate : (DateTime)oemp.ConfirDate, oemp.ID, oPayrollType.ID);

                                if (absentAcount > 4)
                                {
                                    tempAmount = absentAcount - 4;
                                    absentAcount = 1;
                                }
                                provAbsent = absentAcount + tempAmount / 3;
                                EmployeeUnAuthorizeLeave uProvisionEmp = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.AbsentProvLeaveID,
                                    nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                    provAbsent, param.ID, false);
                                uleaves.Add(uProvisionEmp);
                            }

                            tempAmount = 0;
                        if (oRow["TOTAL"] == DBNull.Value)
                        {
                            continue;
                        }
                            absentAcount = Convert.ToDouble(oRow["TOTAL"]);

                            if (absentAcount > 0)
                            {
                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, 1);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Absent Parameter not found."));
                                    continue;
                                }
                                EmployeeUnAuthorizeLeave uleave = new EmployeeUnAuthorizeLeave(oemp.ID, 1,
                                    nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                    absentAcount, param.ID, false);
                                uleaves.Add(uleave);
                            }
                        }
                    }
       
                #endregion Absent Deduct

                if (oAttnParam.lwpLeaveTypeID != null)
                {
                    DataSet EmpLWPDays = dapService.GetZandDocLeaveDays(attnStartDate, attnEndDate, EnumAttendanceType.Leave, oPayrollType.ID, oAttnParam.lwpLeaveTypeID);
                    #region LWP deduct
                    if (EmpLWPDays != null
                    && EmpLWPDays.Tables[0] != null
                    && EmpLWPDays.Tables[0].Rows.Count > 0
                    && oauthParams.Count > 0
                    )
                    {
                        UnAuthorizeLeaveParam oprm = new BO.UnAuthorizeLeaveParam();
                        foreach (DataRow oRow in EmpLWPDays.Tables[0].Rows)
                        {
                            Employee oemp = employees.FirstOrDefault(x => x.ID == Convert.ToInt32(oRow["EMPLOYEEID"].ToString()));
                            if (oemp == null)
                            {
                                ErrorList.Add(new SalaryProcessStatus("", "", " Employee not found, Internal ID:" + oRow["EMPLOYEEID"].ToString()));
                                continue;
                            }

                            int absentAcount = 0;
                            absentAcount = Convert.ToInt32(oRow["TOTAL"].ToString()) - absentAcount;
                            if (oAttnParam.lwpProvLeaveID > 0 && (oemp.ConfirDate == DateTime.MinValue || (oemp.ConfirDate >
                                attnStartDate && oemp.ConfirDate < attnEndDate)))
                            {


                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, (int)oAttnParam.lwpProvLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Absent Provisional Parameter not found."));
                                    continue;
                                }

                                if (absentAcount > 0)
                                {
                                    EmployeeUnAuthorizeLeave uProvisionEmp = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.lwpProvLeaveID,
                                        nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                        absentAcount, param.ID, false);
                                    uleaves.Add(uProvisionEmp);
                                }
                                absentAcount = Convert.ToInt32(oRow["TOTAL"].ToString()) - absentAcount;

                            }



                            if (absentAcount > 0)
                            {
                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, (int)oAttnParam.lwpLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Absent Provisional Parameter not found."));
                                    continue;
                                }
                                EmployeeUnAuthorizeLeave uleave = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.lwpLeaveID,
                                    nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                    absentAcount, param.ID, false);
                                uleaves.Add(uleave);
                            }
                        }
                    }
                    #endregion LWP deduct
                }
                if (oAttnParam.MaternityLeaveTypeID != null)
                {
                    DataSet EmpMaternitydays = dapService.GetZandDocLeaveDays(attnStartDate, attnEndDate, EnumAttendanceType.Leave, oPayrollType.ID, oAttnParam.MaternityLeaveTypeID);
                    #region Maternity Deduction
                    if (EmpMaternitydays != null
                    && EmpMaternitydays.Tables[0] != null
                    && EmpMaternitydays.Tables[0].Rows.Count > 0
                    && oauthParams.Count > 0
                    )
                    {
                        UnAuthorizeLeaveParam oprm = new BO.UnAuthorizeLeaveParam();
                        foreach (DataRow oRow in EmpMaternitydays.Tables[0].Rows)
                        {
                            Employee oemp = employees.FirstOrDefault(x => x.ID == Convert.ToInt32(oRow["EMPLOYEEID"].ToString()));
                            if (oemp == null)
                            {
                                ErrorList.Add(new SalaryProcessStatus("", "", " Employee not found, Internal ID:" + oRow["EMPLOYEEID"].ToString()));
                                continue;
                            }

                            int absentAcount = 0;
                            absentAcount = Convert.ToInt32(oRow["TOTAL"].ToString()) ;


                            if (absentAcount > 0)
                            {
                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, (int)oAttnParam.MaternityUnAuthLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Maternity Benifits Parameters not found."));
                                    continue;
                                }
                                EmployeeUnAuthorizeLeave uleave = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.MaternityLeaveTypeID,
                                    nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                    absentAcount, param.ID, false);
                                uleaves.Add(uleave);
                            }
                        }
                    }
                    #endregion Maternity Deduction
                }


                #region Late Deduct
                // Late Calculation
                if(oAttnParam.lateAbsentLeaveID != null)
                {
                    DataSet LateDays = dapService.GetWorkingDayLateCount(attnStartDate, attnEndDate, oPayrollType.ID);
                    if (LateDays != null && LateDays.Tables[0] != null
                            && LateDays.Tables[0].Rows.Count > 0 && oAttnParam.lateAbsentLeaveID > 0)
                    {

                        foreach (DataRow oRow in LateDays.Tables[0].Rows)
                        {


                            int nCount = Convert.ToInt32(oRow["TOTAL"].ToString());
                            if (nCount < oAttnParam.MonthlyLateForAbsent) continue;
                            if (oAttnParam.MonthlyLateForAbsent == 0) continue;
                            nCount = nCount / oAttnParam.MonthlyLateForAbsent;

                            Employee oemp = employees.FirstOrDefault(x => x.ID == Convert.ToInt32(oRow["EMPLOYEEID"].ToString()));
                            int ProvisionLateAcount = 0;


                            int lateAbsentCount = 0;
                            if (oAttnParam.lateAbsentProvLeaveID != null && (oemp.ConfirDate == DateTime.MinValue || (oemp.ConfirDate >
                                attnStartDate && oemp.ConfirDate < attnEndDate)))
                            {
                                ProvisionLateAcount = dapService.GetLateCount(attnStartDate, (DateTime)oemp.ConfirDate == DateTime.MinValue ? attnEndDate : (DateTime)oemp.ConfirDate, oemp.ID, oPayrollType.ID);
                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, oemp.ID, (int)oAttnParam.lateAbsentProvLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Late Absent Provisional Parameter not found."));
                                }
                                int tempAmount = 0;
                                if (ProvisionLateAcount > 4)
                                {
                                    lateAbsentCount = 1;
                                    tempAmount = ProvisionLateAcount - 4;
                                }
                                lateAbsentCount = lateAbsentCount + tempAmount / 3;
                                if (lateAbsentCount > 0)
                                {
                                    EmployeeUnAuthorizeLeave uProvisionEmp = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.lateAbsentProvLeaveID,
                                       nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                       lateAbsentCount, param.ID, false);
                                    uleaves.Add(uProvisionEmp);
                                }

                            }


                            int TotallateCount = Convert.ToInt32(oRow["TOTAL"].ToString()) - ProvisionLateAcount;
                            int lateAbsent = 0;
                            if (TotallateCount > 4)
                            {
                                lateAbsent = 1;
                                TotallateCount = TotallateCount - 4;
                            }

                            lateAbsent = lateAbsent + TotallateCount / 3;

                            if (lateAbsent > 0)
                            {
                                UnAuthorizeLeaveParam param = UnAuthorizeLeaveParam.GetParameter(oauthParams, (int)oemp.GradeID, (int)oAttnParam.lateAbsentLeaveID);
                                if (param == null)
                                {
                                    ErrorList.Add(new SalaryProcessStatus(oemp.EmployeeNo, oemp.Name, " Late Absent Parameter not found."));
                                }
                                EmployeeUnAuthorizeLeave ulateCount = new EmployeeUnAuthorizeLeave(oemp.ID, (int)oAttnParam.lateAbsentLeaveID,
                                   nextPayMonth, nextPayMonth, attnStartDate, attnEndDate, null,
                                   lateAbsent, param.ID, false);
                                uleaves.Add(ulateCount);
                            }
                        }
                    }

                }
                #endregion 

                if (oAttnParam.AllPresentAllowanceID != null)
                {
                    DataSet PresentDays = dapService.GetZandDocLeaveDays(attnStartDate, attnEndDate, EnumAttendanceType.Present, oPayrollType.ID, null);

                    foreach (Employee emp in employees)
                    {
                        if (emp.PayrollTypeID != oPayrollType.ID) continue;
                        if (emp.GradeID == null)
                        {
                            ErrorList.Add(new SalaryProcessStatus(emp.EmployeeNo, emp.Name, " Employee Not yet Assigned to grade"));
                            continue;

                        }
                        List<ADParameter> applicableParams = new ADParameterService().GetApplicableParameters(emp, (int)emp.GradeID, oadParameters);
                        if (applicableParams == null)
                        {
                            ErrorList.Add(new SalaryProcessStatus(emp.EmployeeNo, emp.Name, " No Alloance parameters found for Attendance Bonus"));
                            continue;
                        }

                        ADParameter applicableParam = new ADParameterService().GetApplicableParameter(emp, (int)emp.GradeID, oadParameters, (int)oAttnParam.AllPresentAllowanceID);

                        if (applicableParam != null)
                        {
                            DataRow pdr = PresentDays.Tables[0].AsEnumerable().FirstOrDefault(x =>
                            Convert.ToInt32(x["EmployeeID"].ToString()) == emp.ID);
                            if (pdr == null) continue;
                            double prdays = Convert.ToDouble(pdr["TOTAL"].ToString());

                            if (prdays >= oAttnParam.AllPresentAllowanceDays)
                            {
                                ADParameterEmployee adparamEmp = new ADParameterEmployee();
                                adparamEmp.EmployeeID = emp.ID;
                                adparamEmp.MonthlyAmount = prdays * applicableParam.FlatAmount;
                                adparamEmp.Days = prdays;
                                adparamEmp.Periodicity = EnumPeriodicity.Monthly;
                                adparamEmp.FormDate = GlobalFunctions.FirstDateOfMonth(oPayrollType.NextPayProcessDate);
                                adparamEmp.TillDate = GlobalFunctions.LastDateOfMonth(oPayrollType.NextPayProcessDate);
                                adparamEmp.ADParameterID = applicableParam.ID;
                                adparamEmp.ADEmpType = EnumADEmpType.AppliedToIndividual;
                                adparamEmp.AllowDeductID = (int)oAttnParam.AllPresentAllowanceID;
                                adparamEmp.Arreartype = EnumArrearType.NotPresent;
                                adparamEmp.CreatedBy = userid;
                                adparamEmp.CreatedDate = DateTime.Today;
                                AdparamEmployee.Add(adparamEmp);
                            }
                        }
                    }
                }

                #region Attendance Allowance process

                List<Shift> shifts = new List<Shift>();
                DataTable dtDailyAttendanceAllowances = new DataTable();

                shifts = new ShiftService().GetAllShiftByPayrollType(PayrollTypeId);

                dtDailyAttendanceAllowances = new DailyAttendanceAllowanceService().GetByAttnbySalaryMonth(oPayrollType.NextPayProcessDate, PayrollTypeId);
                if (dtDailyAttendanceAllowances != null && dtDailyAttendanceAllowances.Rows.Count > 0)
                {
                    foreach (DataRow item in dtDailyAttendanceAllowances.Rows)
                    {
                        Employee tempEmployee = employees.Where(emp => emp.ID.ToString() == item["EmployeeID"].ToString()).FirstOrDefault();
                        EnumattnBeniftsType btype = (EnumattnBeniftsType)Convert.ToInt32(item["type"].ToString());
                        if (btype == EnumattnBeniftsType.Allowance)
                        AdparamEmployee = MakeADParameterEmployeeObj(ref AdparamEmployee, ref ErrorList, tempEmployee,
                            oadParameters,
                            oPayrollType, Convert.ToInt32(item["ItemID"].ToString()), Convert.ToInt32(item["value"].ToString()), userid);
                       else if(btype == EnumattnBeniftsType.OT)
                           EmpOverTimes = MakeEmployeeOvertimeObj(ref EmpOverTimes, ref ErrorList, tempEmployee, termParameters, 
                           oPayrollType, Convert.ToInt32(item["ItemID"].ToString()), Convert.ToDouble(item["value"].ToString()), userid);
                    }
                }
                else
                {
                    List<Term> terms = new TermService().Get(EnumStatus.Active, PayrollTypeId);
                    foreach (Term trm in terms)
                    {   
                        DataSet EmpOTHours = new ShiftTermService().GetEmpOT(oPayrollType.NextPayProcessDate, trm.ID);
                        foreach (DataRow Dr in EmpOTHours.Tables[0].Rows)
                        {
                            Employee tempEmployee = employees.Where(emp => emp.ID.ToString() == Dr["EmployeeID"].ToString()).FirstOrDefault();
                            if (tempEmployee == null) continue;
                            if (tempEmployee.GradeID == null)
                            {
                                ErrorList.Add(new SalaryProcessStatus(tempEmployee.EmployeeNo, tempEmployee.Name, "Grade not assinged"));
                                continue;

                            }
                            if (Dr["TotalOT"] == DBNull.Value)
                            {
                              //  ErrorList.Add(new SalaryProcessStatus(tempEmployee.EmployeeNo, tempEmployee.Name, "value can't be null "));
                                continue;
                            }

                            EmpOverTimes = MakeEmployeeOvertimeObj(ref EmpOverTimes, ref ErrorList, tempEmployee, termParameters,
                               oPayrollType, trm.ID, Convert.ToDouble(Dr["TotalOT"]), userid);
                        }
                    }
                }

                #endregion

                if (ErrorList.Count == 0)
                {
                    if (AdparamEmployee.Count > 0 || EmpOverTimes.Count > 0 || uleaves.Count > 0)
                    {
                        new AttnMonthlyBenefitService().SaveAsBenifits(oPayrollType.ID, AdparamEmployee, EmpOverTimes, uleaves);

                    }
                    else ErrorList.Add(new SalaryProcessStatus("", "", "There is nothing to process or Save. please check your Attandance data and related setups"));
                }

                return ErrorList;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private List<ADParameterEmployee> MakeADParameterEmployeeObj(ref List<ADParameterEmployee> AdparamEmployee, ref List<SalaryProcessStatus> ErrorList,
            Employee tempEmployee, List<ADParameter> oadParameters,
            PayrollType oPayrollType, int allowanceId, double total, int userid)
        {
            List<ADParameter> applicableParams = new ADParameterService().GetApplicableParameters(tempEmployee, (int)tempEmployee.GradeID, oadParameters);
            if (applicableParams == null)
            {
                ErrorList.Add(new SalaryProcessStatus(tempEmployee.EmployeeNo, tempEmployee.Name, " No Alloance/Benifits parameters found in live allowance/Benifits list"));
                return AdparamEmployee;
            }
            var AppliedIndvParam = applicableParams.Where(x => x.EntitleType == EnumEntitleType.Individual && x.IsDependsOnAttendance == true && x.Periodicity == EnumPeriodicity.Monthly && x.AllowDeductID == allowanceId).ToList();
            if (AppliedIndvParam == null)
            {
                ErrorList.Add(new SalaryProcessStatus(tempEmployee.EmployeeNo, tempEmployee.Name, "  Individualy and depand on Attandance declared Alloance/Benifits parameters found in live allowance/Benifits list"));
                return AdparamEmployee;
            }
            foreach (ADParameter indvParam in AppliedIndvParam)
            {
                ADParameterEmployee adparamEmp = new ADParameterEmployee();
                adparamEmp.EmployeeID = tempEmployee.ID;
                adparamEmp.MonthlyAmount = total * indvParam.FlatAmount;
                adparamEmp.Periodicity = EnumPeriodicity.Monthly;
                adparamEmp.Days = total;
                adparamEmp.FormDate = GlobalFunctions.FirstDateOfMonth(oPayrollType.NextPayProcessDate);
                adparamEmp.TillDate = GlobalFunctions.LastDateOfMonth(oPayrollType.NextPayProcessDate);
                adparamEmp.ADParameterID = indvParam.ID;
                adparamEmp.ADEmpType = EnumADEmpType.AppliedToIndividual;
                adparamEmp.AllowDeductID = allowanceId;
                adparamEmp.Arreartype = EnumArrearType.NotPresent;
                adparamEmp.CreatedBy = userid;
                adparamEmp.CreatedDate = DateTime.Today;

                AdparamEmployee.Add(adparamEmp);
            }

            return AdparamEmployee;
        }
        private List<EmployeeOverTime> MakeEmployeeOvertimeObj(ref List<EmployeeOverTime> EmpOverTimes, ref List<SalaryProcessStatus> ErrorList, Employee tempEmployee,  
            List<TermParameter> oParameters, PayrollType oPayrollType, int termid, double total, int userid)
        {
            AttnWiseAllowance attnAllow = new AttnWiseAllowance();
            if(oParameters.Count ==0) return EmpOverTimes;

            TermParameter empTermParam = TermParameter.GetParameter(oParameters, (int) tempEmployee.GradeID, termid);
            if (empTermParam == null)
            {
                ErrorList.Add(new SalaryProcessStatus(tempEmployee.EmployeeNo, tempEmployee.Name, "OT setup not found"));
                return EmpOverTimes;
            }
            EmployeeOverTime empot = new EmployeeOverTime();
            empot.EmployeeID = tempEmployee.ID;
            empot.OTMonth = oPayrollType.NextPayProcessDate;
            empot.PayrollTypeID = oPayrollType.ID;
            empot.TermID = termid;
            empot.TermParameterID = empTermParam.TermID;
            empot.OTHours = total;
            empot.Value = empTermParam.Amount;
            empot.CreatedBy = userid;
            empot.CreatedDate = DateTime.Today;
            empot.MonthDate = oPayrollType.NextPayProcessDate;
            EmpOverTimes.Add(empot);
            return EmpOverTimes;
        }




            
        public void echoTexProcess(DateTime Attdate, EnumProcessMode prMode, int payrolltypeid, int processUserID, List< Employee> employees)
        {

            AttnProcessRunSummary oAttnRunSummary = new AttnProcessRunSummary();
            bool isInOutApplicable = false;
            try
            {

                #region Load Attendence Raw Data
                // AttnRawData.RunScriptCollectRawData(Attdate);
                new AttnRawDataService().RunScriptCollectRawData(Attdate);
                #endregion

                #region Initialization for Attendence Process

                isInOutApplicable = new SystemConfigarationService().GetconfigBooleanValue(EnumConfigurationType.Logic, "attendence", "inoutapplicable");

                bool _IsOTFractionate = new SystemConfigarationService().GetconfigBooleanValue(EnumConfigurationType.Logic, "overtime", "fractionateothour");

                var sinMissingHour = new SystemConfigarationService().GetconfigValue(EnumConfigurationType.Logic, "overtime", "inmissinghour" );

                double inMissingHour = 0;
                if (sinMissingHour != null) inMissingHour = Convert.ToDouble(sinMissingHour);

                List<DailyAttnProcess> dailyattProcesses = new List<DailyAttnProcess>();
                List<EmpFieldTrack> oEmpFieldTracks = new List<EmpFieldTrack>();
                List<AccessCard> oAccessCards =new  AccessCardService().Get(EnumCardStatus.Attached);
                List<CardOperation> oCardOperations =new CardOperationService().Get();

                DateTime startTime = new DateTime(Attdate.Year, Attdate.Month, Attdate.Day, 4, 0, 0);
                DateTime ToTime = Attdate.AddDays(1);
                ToTime = new DateTime(ToTime.Year, ToTime.Month, ToTime.Day, 10, 0, 0);

                List<ShiftRotation> CounterClockRotation = new ShiftRotationService().Get(EnumStatus.Regardless, payrolltypeid);

                List<EmployeeWorkPlanSetup> empWPGroups = new EmployeeWorkPlanSetupService().GetAll();

                List<Shift> shifts =new  ShiftService().GetAllShift();
                List<WorkPlanGroup> workPlanGroups = new WorkPlanGroupService().GetAll();
                if( employees == null) employees = new EmployeeService().GetAllLive();
                List<Employee> discontinueEmps =new  EmployeeService().GetDiscontinueEmp(Attdate, DateTime.Now, payrolltypeid);

                //List<AttnRawData> attRawdata = new AttnRawDataService().Get(startTime, ToTime, payrolltypeid);// get raw data by a date and order by date, employee, punchTime
                List<AttnRawData> attRawdata = new AttnRawDataService().GetWithoutMobileRawData(startTime, ToTime, payrolltypeid);// get raw data by a date without MobileRawData and order by date, employee, punchTime
                List<EmployeeOutsideDuty> outSideDuties = new EmployeeOutsideDutyService().Get(Attdate); // get transaction  by the a rate 
                List<LeaveEntry> leaves = new LeaveEntryService().Get(Attdate); // workplans by the date

                // Short leave for a particullar Day Should be between 6:00 AM Current Day to 6:00 AM Next Day. [Change can be done according to business logic]
                List<EmployeeShortLeave> shortLeaves = new EmployeeShortLeaveService().Get(Attdate.Date.AddHours(6), Attdate.Date.AddDays(1).AddHours(6));

                //oEmpFieldTracks =new EmpFieldTrackService().Get().Where(obj => obj.TranDateTime.Date == Attdate.Date).ToList();
                List<LeaveParameter> lvParameters = new LeaveParameterService().Get(true, payrolltypeid);

                if (discontinueEmps != null && discontinueEmps.Count > 0)
                {
                    foreach (Employee emp in discontinueEmps)
                    {
                        if (employees.FindIndex(x=>x.ID == emp.ID) != -1)
                            employees.Add(emp);
                    }
                }

                List<DailyAttnProcess> prvDayattns = new DailyAttnProcessService().GetshotList(Attdate.AddDays(-1));



                List<DailyAttnProcess> manualAttnProcesses = new DailyAttnProcessService().GetManualProcess(payrolltypeid, Attdate);

                //foreach (DailyAttnProcess item in manualAttnProcesses)
                //{
                //    dailyattProcesses.Add(item);
                //}


                #endregion

                foreach (Employee emp in employees)
                {

                    //EmpTempid = emp.ID.Integer;

                    #region EmployeeWise Setup

                    // 1. If Joining date is after Attendendence date then no attendence
                    if (emp.JoiningDate > Attdate)
                    {
                        continue;
                    }

                    // 2. If End of Contract date is less than or equal Attendendence date then no attendence
                    if (emp.EndOfContractDate != null && emp.EndOfContractDate.Value <= Attdate)
                    {
                        continue;
                    }

                    DailyAttnProcess attnProcess = new DailyAttnProcess();
                    DailyAttnProcess manualEntry = manualAttnProcesses
                                      .FirstOrDefault(obj => obj.EmployeeID == emp.ID);

                    // 2. If Attendendence is manually enterred 
                    if (manualEntry != null)
                    {
                        // 2.1 If Both In and Out are Manually Enterred then add the item
                        if (!manualEntry.OnlyManualInTime && !manualEntry.OnlyManualOutTime)
                        {
                            dailyattProcesses.Add(manualEntry);
                            continue;
                        }

                        attnProcess = manualEntry;
                    }
                    else
                    {
                        attnProcess.AttnDate = Attdate;
                        attnProcess.EmployeeID = emp.ID;
                        attnProcess.IsManualEntry = false;
                    }


                    attnProcess.AttenType = EnumAttendanceType.Present;

                    List<AttnRawData> empAttnData = null;

                    EmployeeOutsideDuty empOutsideDuty = null;

                    LeaveEntry empLeaveEntry = null;


                    #region Some fine tuning in Employee's attendence RawData

                    if (attRawdata != null && attRawdata.Count > 0)
                    {
                        empAttnData = attRawdata.Where(erd => erd.EmployeeID == emp.ID)
                                                .OrderBy(erd => erd.PunchTime)
                                                .ToList();

                        #region Remove Previously assigned Cards data in Current Date

                        if (emp.CardID != null && emp.CardID !=null)
                        {
                            AccessCard accessCardEmp = oAccessCards.FirstOrDefault(x => x.ID == emp.CardID);

                            if (accessCardEmp != null)
                            {
                                CardOperation oEmpCardOperation = oCardOperations
                                                                  .FirstOrDefault(x => x.CardNumber.Trim().ToUpper() == accessCardEmp.CardNumber.Trim().ToUpper()
                                                                                    && x.EmployeeID == emp.ID);
                                if (oEmpCardOperation != null)
                                {
                                    // if Current Date is Greater than currently assigned Cards assingnDate
                                    if (Attdate.Date > oEmpCardOperation.AssignDate)
                                    {
                                        // Remove Previously assigned Cards Data
                                        empAttnData = empAttnData.Where(x => x.CardNo.Trim().ToUpper() == oEmpCardOperation.CardNumber.ToUpper()).ToList();
                                    }
                                }
                            }
                        }
                        #endregion

                        // If empAttendence Data exist and
                        if (empAttnData.Count > 0)
                        {
                            // If empAttendence Data's first punchTime is greater than current date's last Time
                            if (empAttnData[0].PunchTime > new DateTime(ToTime.Year, ToTime.Month, ToTime.Day, 2, 0, 0))
                            {
                                // We Clear empAttendence Data
                                empAttnData = new List<AttnRawData>();
                            }
                            else
                            {
                                // Gets Employees Previous Days Attendence
                                DailyAttnProcess op = prvDayattns.Where(itm => itm.EmployeeID == emp.ID)
                                                                 .OrderByDescending(itm => itm.OutTime)
                                                                 .FirstOrDefault();

                                // if Previous day attendence exists
                                if (op != null)

                                {
                                    //  Previous Day's Out time Exists
                                    if (op.OutTime != null)
                                    {

                                        while (empAttnData.Count > 0)
                                        {
                                            // Take the Current First Attndence Data
                                            AttnRawData ordata = empAttnData[0];
                                            // If PunchTime is less than Previous Date's OutTime  OR
                                            // Difference is less Than 10 minutes
                                            if (ordata.PunchTime <= op.OutTime || Math.Abs((((DateTime)ordata.PunchTime - (DateTime)op.OutTime)).TotalMinutes) < 10)
                                            {
                                                // discard that attendence entry
                                                empAttnData.Remove(ordata);
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // What to do??
                                    }
                                }

                            }

                            if (isInOutApplicable)
                            {
                                empAttnData = empAttnData
                                              .OrderBy(erd => (int)erd.EntryMode)
                                              .ThenBy(erd => erd.PunchTime)
                                              .ToList();
                            }
                        }
                    }

                    #endregion

                    if (outSideDuties != null && outSideDuties.Count > 0)
                    {
                        empOutsideDuty = outSideDuties.Where(od => od.EmployeeID == emp.ID)
                                                      .FirstOrDefault();

                    }



                    EmployeeWorkPlanSetup oEmpWorkplan = empWPGroups.Where(oGr => oGr.EmployeeID == emp.ID)
                                                                    .SingleOrDefault();

                    // 3. If There is no EmployeeWorkPlanSetup then no attendence
                    if (oEmpWorkplan == null)
                    {
                        //oAttnRunSummary.AddError(EnumErrorType.WorkGroupUndefine, "Employee WorkPlan Not Defined.", emp);

                        continue;
                    }

                    WorkPlanGroup oEmpWPlanGroup = workPlanGroups.Where(o => o.ID == oEmpWorkplan.WorkPlanGroupID)
                                                                 .Single();


                    //oEmpWPlanGroup = workPlanGroups.Where(o => o.ID == 28)
                    //                                             .Single();
                    #endregion

                    #region Calcullate ShiftID and WorkPlan Day Type

                    // not needed now
                    // _empWPtype = oEmpWPlanGroup.Type; // Set Workplan Type
                    // Get ShiftID from WorkPlan for Fixed workplan

                    if (oEmpWPlanGroup.Type == EnumWorkPlanGroup.Fixed)
                    {
                        switch (Attdate.DayOfWeek)
                        {
                            case DayOfWeek.Friday:
                                attnProcess.ShiftID = oEmpWorkplan.FridayShiftID;
                                break;
                            case DayOfWeek.Monday:
                                attnProcess.ShiftID = oEmpWorkplan.MondayShiftID;
                                break;
                            case DayOfWeek.Saturday:
                                attnProcess.ShiftID = oEmpWorkplan.SaturdayShiftID;
                                break;
                            case DayOfWeek.Sunday:
                                attnProcess.ShiftID = oEmpWorkplan.SundayShiftID;
                                break;
                            case DayOfWeek.Thursday:
                                attnProcess.ShiftID = oEmpWorkplan.ThursdayShiftID;
                                break;
                            case DayOfWeek.Tuesday:
                                attnProcess.ShiftID = oEmpWorkplan.TuesdayShiftID;
                                break;
                            case DayOfWeek.Wednesday:
                                attnProcess.ShiftID = oEmpWorkplan.WednesdayShiftID;
                                break;
                            default:
                                break;

                        }

                    }
                    // Calcullate ShiftID for Rotation workplan
                    else
                    {
                        if (empAttnData != null && empAttnData.Count > 0)
                        {
                            DateTime inTime = empAttnData[0].PunchTime;
                            double nminutes = 10000;
                            List<ShiftRotation> osrs;
                            DateTime shiftInTime, shiftOutTime;
                            Shift oshift;

                            osrs = CounterClockRotation.Where(x => x.WorkPlanType == oEmpWPlanGroup.Type).ToList();


                            foreach (ShiftRotation sr in osrs)
                            {
                                oshift = shifts.Single(o => o.ID == sr.ShiftID);

                                shiftInTime = Attdate.Subtract(Attdate.TimeOfDay).Add(oshift.InTime.TimeOfDay);

                                TimeSpan ospan = (inTime - shiftInTime);

                                if (nminutes > Math.Abs(ospan.TotalMinutes))
                                {
                                    nminutes = Math.Abs(ospan.TotalMinutes);
                                    if(!attnProcess.IsManualEntry)          //This Condition is added for manual Shift change
                                        attnProcess.ShiftID = sr.ShiftID;
                                }
                            }

                            oshift = shifts.Single(o => o.ID == attnProcess.ShiftID);
                            shiftInTime = Attdate.Subtract(Attdate.TimeOfDay).Add(oshift.InTime.TimeOfDay);
                            shiftOutTime = Attdate.Subtract(Attdate.TimeOfDay).Add(oshift.OutTime.TimeOfDay);
                            if (shiftOutTime < shiftInTime) shiftOutTime = shiftOutTime.AddDays(1);

                            if (Math.Abs((shiftOutTime - shiftInTime).TotalMinutes) < nminutes)
                            {
                                attnProcess.ShiftID = null;
                                empAttnData = new List<AttnRawData>();
                            }

                        }
                    }

                    CalcullateWorkdayType(attnProcess, oEmpWorkplan, oEmpWPlanGroup, 1);

                    #region Leave Calcullation

                    if (leaves != null && leaves.Count > 0)
                    {
                        empLeaveEntry = leaves.Where(lv => lv.EmpID == emp.ID
                                                          && (lv.LeaveStatus == EnumLeaveStatus.Approved || lv.LeaveStatus == EnumLeaveStatus.Availed))
                                              .FirstOrDefault();
                        if (empLeaveEntry != null)
                        {
                            // Check wether Ignore Holidays
                            if (lvParameters.Where(x => x.LeaveId == empLeaveEntry.LeaveID).Any(x => x.IgnoreHoliday))
                            {
                                if (attnProcess.WorkDayType == EnumWorkPlanDayType.WeeklyHoliday)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.WeeklyHoliday;
                                }
                                else if (attnProcess.WorkDayType == EnumWorkPlanDayType.NationalHoliday)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Holiday;
                                }
                                else
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Leave;
                                    attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                                    dailyattProcesses.Add(attnProcess);
                                    continue;
                                }
                            }
                            else
                            {
                                attnProcess.AttenType = EnumAttendanceType.Leave;
                                attnProcess.ReferenceID = empLeaveEntry.LeaveID;
                                dailyattProcesses.Add(attnProcess);
                                continue;
                            }

                        }

                    }
                    #endregion

                    #endregion

                    #region calculate In/Out time and With Other Things

                    /*
                     * if ShiftID found and attendence data exists
                     *      Calcullate InTime and OutTime
                     *      If elligable for OT calcullate OT according to DayType(Holiday or Workday)
                     */

                    if (empAttnData != null && empAttnData.Count > 0 && attnProcess.ShiftID != null && attnProcess.ShiftID != 0)
                    {
                        Shift oshift = shifts.FirstOrDefault(x=>x.ID == attnProcess.ShiftID);


                        oshift.OutTime = oshift.InTime.Date
                                                      .AddDays(oshift.OutTime.TimeOfDay < oshift.InTime.TimeOfDay ? 1 : 0)
                                                      .Add(oshift.OutTime.TimeOfDay);

                        #region Calcullate In Out

                        if (!isInOutApplicable)
                        {

                            attnProcess.InTime = attnProcess.IsManualEntry && attnProcess.OnlyManualInTime ?
                                                 attnProcess.InTime : empAttnData[0].PunchTime;


                            if (!(attnProcess.IsManualEntry && attnProcess.OnlyManualOutTime))
                            {
                                int outInitialIndex = attnProcess.IsManualEntry && attnProcess.OnlyManualInTime ?
                                                  0 : 1;
                                if (empAttnData.Count > outInitialIndex)
                                {
                                    attnProcess.OutTime = empAttnData[empAttnData.Count - 1].PunchTime;

                                    //TimeSpan otime = attnProcess.OutTime - attnProcess.InTime;
                                    // here we defined that total working hour is 19 hour in a day.
                                    for (int i = empAttnData.Count - 1; i >= outInitialIndex; i--)
                                    {
                                        TimeSpan ntime =(DateTime) empAttnData[i].PunchTime - (DateTime) attnProcess.InTime;
                                        if (oEmpWPlanGroup.Type != EnumWorkPlanGroup.Fixed)
                                        {
                                            if (!oshift.IsOverlapingDay  // if not overlapping days
                                                && empAttnData[i].PunchTime.Date > attnProcess.InTime // But it overlaps 
                                                && empAttnData[i].PunchTime.Subtract(empAttnData[i].PunchTime.Date).TotalHours > 4) //then check weather it is more than 4 hour next Day
                                            {
                                                // then ignore
                                                continue;
                                            }
                                            else
                                            {
                                                if (ntime.TotalHours <= 14)
                                                {
                                                    attnProcess.OutTime = empAttnData[i].PunchTime;
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            attnProcess.OutTime = null;

                                            if (empAttnData[i].PunchTime.Date > attnProcess.InTime && ntime.TotalHours > 16)
                                                continue;
                                            else
                                            {
                                                attnProcess.OutTime = empAttnData[i].PunchTime;
                                                break;
                                            }
                                        }
                                    }

                                    if (attnProcess.OutTime != null)
                                    {
                                        if (Math.Abs( ((DateTime)attnProcess.InTime - (DateTime)attnProcess.OutTime).TotalMinutes) < 10)
                                        {
                                            attnProcess.OutTime = null;
                                        }
                                    }
                                }
                            }

                        }
                        else
                        {
                            List<AttnRawData> empInRawData = empAttnData.Where(rd => rd.EntryMode == EnumEntryMode.In)
                                                                        .OrderBy(rd => rd.PunchTime)
                                                                        .ToList();
                            List<AttnRawData> empOutRawData = empAttnData.Where(rd => rd.EntryMode == EnumEntryMode.Out)
                                                                        .OrderByDescending(rd => rd.PunchTime)
                                                                        .ToList();

                            if (empInRawData.Count > 0)
                            {
                                attnProcess.InTime = attnProcess.IsManualEntry && attnProcess.OnlyManualInTime ?
                                               attnProcess.InTime : empInRawData[0].PunchTime;

                                if (!(attnProcess.IsManualEntry && attnProcess.OnlyManualOutTime))
                                {
                                    if (empOutRawData.Count > 0)
                                    {
                                        attnProcess.OutTime = empOutRawData[0].PunchTime;
                                        foreach (AttnRawData item in empOutRawData)
                                        {
                                            TimeSpan ntime = (DateTime) item.PunchTime - (DateTime) attnProcess.InTime;

                                            if (oEmpWPlanGroup.Type != EnumWorkPlanGroup.Fixed)
                                            {
                                                if (ntime.TotalHours <= 16)
                                                {
                                                    attnProcess.OutTime = item.PunchTime;
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                attnProcess.OutTime = null;
                                                if (item.PunchTime.Date > ((DateTime) attnProcess.InTime).Date && item.PunchTime.Hour > 5)
                                                    continue;
                                                else
                                                {
                                                    attnProcess.OutTime = item.PunchTime;
                                                    break;
                                                }
                                            }
                                        }
                                    }

                                    if (attnProcess.OutTime != null)
                                    {
                                        if (Math.Abs(((DateTime)attnProcess.InTime - (DateTime)attnProcess.OutTime).TotalMinutes) < 10)
                                        {
                                            attnProcess.OutTime = null;
                                        }
                                    }
                                }
                            }

                        }

                        #endregion

                        CalcInOutCorrection(inMissingHour, shifts, attnProcess);

                        if (attnProcess.InTime != null)
                        {
                            oshift.InTime = ((DateTime) attnProcess.InTime).Date.Add(oshift.InTime.TimeOfDay);
                            oshift.OutTime = oshift.InTime.Date
                                                      .AddDays(oshift.OutTime.TimeOfDay < oshift.InTime.TimeOfDay ? 1 : 0)
                                                      .Add(oshift.OutTime.TimeOfDay);
                            oshift.AbsentTime = oshift.InTime.Date
                                                      .AddDays(oshift.AbsentTime.TimeOfDay < oshift.InTime.TimeOfDay ? 1 : 0)
                                                      .Add(oshift.AbsentTime.TimeOfDay);

                            #region Calcullate Late, Delay, Early & Absent

                            double lateOrDelayTime = ((DateTime) attnProcess.InTime).TimeOfDay.Subtract(oshift.InTime.TimeOfDay).TotalMinutes;

                            if (oshift.LateCalcualtion != 0 && lateOrDelayTime > oshift.LateCalcualtion)
                            {
                                attnProcess.AttenType = EnumAttendanceType.Late;
                                attnProcess.IsLate = true;
                                attnProcess.LateHour = (lateOrDelayTime - oshift.LateCalcualtion) / 60;
                            }
                            if (oshift.DelayCalcualtion != 0 && lateOrDelayTime > oshift.DelayCalcualtion)
                            {
                                attnProcess.AttenType = EnumAttendanceType.Delay;
                                attnProcess.IsLate = true;
                                attnProcess.LateHour = (lateOrDelayTime - oshift.DelayCalcualtion) / 60;
                            }

                            if (oshift.EarlyExitBefore != 0 && attnProcess.OutTime != null)
                            {
                                double minutesEarly;
                                minutesEarly = oshift.OutTime.Subtract(oshift.InTime).TotalMinutes - ((DateTime) attnProcess.OutTime).Subtract((DateTime)attnProcess.InTime).TotalMinutes;
                                if (minutesEarly > oshift.EarlyExitBefore)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Early;
                                    attnProcess.EarlyHour = (minutesEarly - oshift.EarlyExitBefore) / 60;
                                }
                            }


                            //if(attnProcess.OutTime != DateTime.MinValue && oshift.HalfdayBarrierHour >0 &&  attnProcess.OutTime.Subtract(attnProcess.InTime).TotalHours <= oshift.HalfdayBarrierHour)
                            //{
                            //    attnProcess.AttenType = EnumAttendanceType.HalfDay; 
                            //}

                            if (attnProcess.OutTime != null && oshift.HalfdayBarrierHour > 0 && 
                                ((DateTime)attnProcess.OutTime).Subtract((DateTime)attnProcess.InTime).TotalHours 
                                <= oshift.HalfdayBarrierHour)
                            {
                                attnProcess.AttenType = EnumAttendanceType.HalfDay;
                                EmployeeShortLeave empShortLeave = shortLeaves.FirstOrDefault(x => x.EmployeeID == emp.ID);
                                double totalWorkingHour = 0;
                                if (empShortLeave != null)
                                {
                                    // Mutually Exclusive
                                    if (attnProcess.InTime >= empShortLeave.ToDate || attnProcess.OutTime <= empShortLeave.FromDate)
                                    {
                                        totalWorkingHour =((DateTime) attnProcess.OutTime).Subtract((DateTime)attnProcess.InTime).TotalHours + empShortLeave.ToDate.Subtract(empShortLeave.FromDate).TotalHours;
                                    }
                                    else
                                    {
                                        DateTime calStartTime =(DateTime) attnProcess.InTime <(DateTime) empShortLeave.FromDate ? (DateTime) attnProcess.InTime : empShortLeave.FromDate;
                                        DateTime calEndTime =(DateTime) attnProcess.OutTime >  empShortLeave.ToDate ? (DateTime) attnProcess.OutTime : empShortLeave.ToDate;
                                        totalWorkingHour = calEndTime.Subtract(calStartTime).TotalHours;
                                    }

                                    if (totalWorkingHour >= oshift.HalfdayBarrierHour)
                                    {
                                        attnProcess.AttenType = EnumAttendanceType.Present;
                                        attnProcess.Comments = "Short Leave";
                                        attnProcess.Reason = "Short Leave";
                                    }
                                }
                            }

                            if (oshift.hasAbsentTime)
                            {

                                if (attnProcess.InTime > oshift.AbsentTime)
                                {
                                    attnProcess.AttenType = EnumAttendanceType.Absent;
                                }
                            }

                            #endregion
                            CalcullateOTEchoTex(emp.IsEligibleOT, attnProcess, oshift, Attdate, _IsOTFractionate);
                            //CalcullateOTEchoTex(!emp.IsEligibleOT, attnProcess, oshift, Attdate, true);

                        }
                    }

                    #endregion

                    #region Calcullate MobileAttendence if Not found in rawData

                    if (attnProcess.InTime == null && oEmpFieldTracks.Any(obj => obj.EmployeeID == attnProcess.EmployeeID))
                    {
                        List<EmpFieldTrack> oCurrentEmpFTracks = oEmpFieldTracks.Where(obj => obj.EmployeeID == attnProcess.EmployeeID).OrderBy(o => o.TranDateTime).ToList();
                        attnProcess.InTime = oCurrentEmpFTracks[0].TranDateTime;
                        if (oCurrentEmpFTracks.Count > 1)
                            attnProcess.OutTime = oCurrentEmpFTracks[oCurrentEmpFTracks.Count - 1].TranDateTime;
                        attnProcess.AttenType = EnumAttendanceType.Present;
                    }

                    #endregion

                    CalcInOutCorrection(inMissingHour, shifts, attnProcess);

                    #region Calcullate not present status

                    if (attnProcess.InTime == null && attnProcess.OutTime == null)
                    {

                        if (empOutsideDuty != null)
                        {
                            attnProcess.AttenType = EnumAttendanceType.OutSideDuty;
                            attnProcess.ReferenceID = empOutsideDuty.ID;
                        }
                        else if (attnProcess.WorkDayType == EnumWorkPlanDayType.WeeklyHoliday)
                        {
                            attnProcess.AttenType = EnumAttendanceType.WeeklyHoliday;
                        }
                        else if (attnProcess.WorkDayType == EnumWorkPlanDayType.NationalHoliday)
                        {
                            attnProcess.AttenType = EnumAttendanceType.Holiday;
                        }
                        else
                        {
                            attnProcess.AttenType = EnumAttendanceType.Absent;
                        }
                    }

                    #endregion

                    dailyattProcesses.Add(attnProcess); // Add the process to collection
                }

                //if (dailyattProcesses.Count == 0)
                //    throw new ServiceException("After process Raw data, no attandance found for the selected date.");
                //DailyAttnProcess.Save(dailyattProcesses, false);

                new DailyAttnProcessService().Save(dailyattProcesses, null);
            }
            catch (ServiceException ex)
            {
                throw new ServiceException(ex.Message, ex);
            }
            catch (Exception e)
            {
                throw new ServiceException(e.Message, e);
            }

        }
        private static void CalcInOutCorrection(double inMissingHour, List<Shift> shifts, DailyAttnProcess attnProcess)
        {
            // If There is InMissing Hour in Logic
            if (inMissingHour > 0)
            {
                Shift oEmpshift = shifts.FirstOrDefault(x=>x.ID == attnProcess.ShiftID);

                if (oEmpshift != null)
                {
                    if(attnProcess.InTime != null )
                        oEmpshift.InTime = ((DateTime) attnProcess.InTime).Date.Add(oEmpshift.InTime.TimeOfDay);

                    if (attnProcess.InTime != null && oEmpshift.InTime.AddHours(inMissingHour) < attnProcess.InTime)
                    {
                        DateTime previousIn = (DateTime) attnProcess.InTime;
                        attnProcess.InTime = null;
                        attnProcess.LateHour = 0;

                        if (attnProcess.OutTime == null || oEmpshift.OutTime.AddHours(inMissingHour) < attnProcess.OutTime)
                        {
                            attnProcess.OutTime = previousIn;
                        }
                    }
                }
            }
        }

    }
}