Ejemplo n.º 1
0
        /// <summary>
        /// 获取某一天的打卡记录,无论排班是否开始或结束
        /// </summary>
        /// <param name="nr"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public List <AttendanceRecordDetailView> GetDetailsViewByStaffAndDateWithExtrawork(string nr, DateTime datetime)
        {
            List <AttendanceRecordDetailView> records = new List <AttendanceRecordDetailView>();

            SystemSetting            setting = new SystemSettingService(this.DbString).Find();
            DataContext              dc      = new DataContext(this.DbString);
            List <ShiftScheduleView> shifts  = dc.Context.GetTable <ShiftScheduleView>().Where(s => s.staffNr.Equals(nr) && s.fullStartAt.Value.Date.Equals(datetime.Date)).OrderBy(s => s.fullStartAt).ToList();

            if (shifts.Count > 0)
            {
                /// 找出在单个shift之间的
                foreach (var s in shifts)
                {
                    DateTime sq = s.fullStartAt.Value.AddMinutes(0 - setting.validAttendanceRecordTime.Value);
                    DateTime eq = s.fullEndAt.Value.AddMinutes(setting.validAttendanceRecordTime.Value);
                    List <AttendanceRecordDetailView> shiftAttendRecords = dc.Context.GetTable <AttendanceRecordDetailView>().Where(ss => ss.recordAt >= sq && ss.recordAt <= eq && ss.staffNr.Equals(nr)).OrderBy(ss => ss.recordAt).ToList();//new List<AttendanceRecordDetailView>();
                    // records.AddRange(shiftAttendRecords);
                    foreach (var r in shiftAttendRecords)
                    {
                        if (records.FirstOrDefault(ss => s.id == r.id) == null)
                        {
                            records.Add(r);
                        }
                    }
                }

                /// 找出每两个shift之间的,及A的结束到B的开始,如果没有B,则A的开始到datetime的次日23:59:59

                foreach (var firstShift in shifts)
                {
                    ShiftScheduleView nextShift = dc.Context.GetTable <ShiftScheduleView>().Where(s => s.staffNr.Equals(nr) && s.fullStartAt > firstShift.fullEndAt).OrderBy(s => s.fullStartAt).FirstOrDefault();

                    DateTime sq = firstShift.fullEndAt.Value.AddMinutes(0 + setting.validAttendanceRecordTime.Value);
                    DateTime eq = nextShift == null?datetime.Date.AddDays(1).Add(new TimeSpan(23, 59, 59)) : nextShift.fullStartAt.Value.AddMinutes(0 - setting.validAttendanceRecordTime.Value);

                    List <AttendanceRecordDetailView> shiftAttendRecords = dc.Context.GetTable <AttendanceRecordDetailView>().Where(ss => ss.recordAt >= sq && ss.recordAt <= eq && ss.staffNr.Equals(nr)).OrderBy(ss => ss.recordAt).ToList(); //new List<AttendanceRecordDetailView>();
                                                                                                                                                                                                                                                // records.AddRange(shiftAttendRecords);
                    foreach (var r in shiftAttendRecords)
                    {
                        if (records.FirstOrDefault(ss => ss.id == r.id) == null)
                        {
                            records.Add(r);
                        }
                    }
                }
            }
            else
            {
                //ShiftScheduleView prevShift = dc.Context.GetTable<ShiftScheduleView>().Where(s => s.staffNr.Equals(nr) && s.fullEndAt < datetime).OrderByDescending(s => s.fullEndAt).FirstOrDefault();
                //ShiftScheduleView nextShift= dc.Context.GetTable<ShiftScheduleView>().Where(s => s.staffNr.Equals(nr) && s.fullStartAt > datetime).OrderBy(s => s.fullStartAt).FirstOrDefault();
                ///// 如果没有排班,则找出前一天开始,到次日的结束
                //DateTime sq = prevShift== null? datetime.Date.AddDays(-1) : prevShift.fullEndAt.Value.AddMinutes(0 + setting.validAttendanceRecordTime.Value);
                //DateTime eq = nextShift == null ? datetime.Date.AddDays(1).Add(new TimeSpan(23, 59, 59)) : nextShift.fullStartAt.Value.AddMinutes(0 - setting.validAttendanceRecordTime.Value);

                //List<AttendanceRecordDetailView> shiftAttendRecords = dc.Context.GetTable<AttendanceRecordDetailView>().Where(ss => ss.recordAt >= sq && ss.recordAt <= eq && ss.staffNr.Equals(nr)).OrderBy(ss => ss.recordAt).ToList();//new List<AttendanceRecordDetailView>();
                //records.AddRange(shiftAttendRecords);
            }
            List <AttendanceRecordDetailView> todayRecords = dc.Context.GetTable <AttendanceRecordDetailView>().Where(ss => ss.recordAt >= datetime.Date && ss.recordAt <= datetime.Date.Add(new TimeSpan(23, 59, 59)) && ss.staffNr.Equals(nr)).OrderBy(ss => ss.recordAt).ToList();

            foreach (var r in todayRecords)
            {
                if (records.FirstOrDefault(s => s.id == r.id) == null)
                {
                    records.Add(r);
                }
            }
            return(records.Distinct().OrderBy(ss => ss.recordAt).ToList());;
        }
Ejemplo n.º 2
0
        public void CalculateAttendRecordWithExtrawork(DateTime datetime, List <string> shiftCodes = null, StaffSearchModel searchModel = null)
        {
            // 是否是休息日
            IWorkAndRestService wars = new WorkAndRestService(this.DbString);
            WorkAndRest         wr   = wars.FindByDate(datetime);
            bool          isRestDay  = wars.IsRestDay(wr);
            SystemSetting setting    = new SystemSettingService(this.DbString).Find();


            DataContext dc = new DataContext(this.DbString);



            // 计算在职人员的考勤
            List <Staff> staffs = dc.Context.GetTable <Staff>().Where(s => (s.workStatus == (int)WorkStatus.OnWork) || (s.workStatus == (int)WorkStatus.OffWork && s.resignAt >= datetime)).ToList();

            foreach (Staff staff in staffs)
            {
                double workdayHour = 0;

                double extraHour = 0;
                // 异常情况
                List <AttendanceExceptionType> exceptions = new List <AttendanceExceptionType>();
                if (staff.nr.Equals("201471"))
                {
                    string s = "201471";
                }
                // 获取已经结束的排班
                List <ShiftScheduleView> shifts = dc.Context.GetTable <ShiftScheduleView>().Where(s => s.staffNr.Equals(staff.nr) && s.fullStartAt.Value.Date == datetime.Date && s.fullEndAt <= DateTime.Now).ToList();
                if (shifts.Count > 0)
                {
                    foreach (var shift in shifts)
                    {
                        DateTime validSQ = shift.fullStartAt.Value.AddMinutes(0 - setting.validAttendanceRecordTime.Value);
                        DateTime validEQ = shift.fullEndAt.Value.AddMinutes(0 + setting.validAttendanceRecordTime.Value);
                        DateTime sq      = validSQ;
                        DateTime eq      = shift.shiftType == (int)ShiftType.Today ? datetime.Date.AddDays(1).AddHours(8) : datetime.Date.AddDays(1).AddHours(23);

                        ShiftScheduleView nextShift = new ShiftSheduleService(this.DbString).GetNextShiftScheduleView(staff.nr, shift.fullEndAt.Value);

                        if (nextShift != null)
                        {
                            if ((nextShift.fullStartAt.Value.Date - shift.fullStartAt.Value.Date).TotalDays < 2)
                            {
                                eq = nextShift.fullStartAt.Value.AddMinutes(0 - setting.validAttendanceRecordTime.Value);
                            }
                        }

                        List <AttendanceRecordDetail> records = new AttendanceRecordDetailService(this.DbString).GetByStaffAndTimespan(staff.nr, sq, eq);
                        if (records.Count == 0)
                        {
                            // 旷工,可能他有请假。。。
                            exceptions.Add(AttendanceExceptionType.Absence);
                        }
                        else
                        {
                            /// 清洗数据
                            MarkRepeatRecordByMinute(records, (float)setting.repeatAttendanceRecordTime.Value);
                            records = records.Where(s => s.isRepeatedData == false).ToList();

                            // 如果考勤记录不配对,如 进-出 的偶数被,则是打开记录不完整
                            // 但是这不影响计算
                            if (records.Count % 2 != 0)
                            {
                                exceptions.Add(AttendanceExceptionType.MessRecord);
                            }

                            /// 开始计算
                            /// 早到的使用排班开始时间,晚到的算迟到,提早走的算早退
                            /// 此处不涉及到多次进出-计算目前只能算出大概,很难精确
                            /// 打卡迟了肯定算迟到
                            /// 如果早退了一般不会来加班了
                            // 是否有早打卡?
                            // int hasEarlyCount= records.Where(s => s.recordAt < shift.fullStartAt.Value).Count();

                            if (records.Count == 1)
                            {
                                exceptions.Add(AttendanceExceptionType.MessRecord);
                                /// 以下都是推测,都是要人为的调整的
                                DateTime recordAt = records[0].recordAt;
                                // 如果是早来,迟走,可能是忘记打卡了
                                if (recordAt < shift.fullStartAt.Value || (records.Last().recordAt >= shift.fullEndAt.Value && recordAt <= validEQ))
                                {
                                    /// 如果早来超过一个小时,可能是加班
                                    if (recordAt <= shift.fullStartAt.Value.AddHours(-1))
                                    {
                                        extraHour = (shift.fullStartAt.Value - recordAt).TotalHours;
                                    }
                                    workdayHour = (shift.fullEndAt.Value - shift.fullStartAt.Value).TotalHours;
                                }// 如果迟走超过一个小时,可能是加班,即使此处误判,也需要加班单存在的
                                else if (recordAt >= shift.fullEndAt.Value.AddHours(1))
                                {
                                    exceptions.Add(AttendanceExceptionType.ExtraWork);
                                    workdayHour = (shift.fullEndAt.Value - shift.fullStartAt.Value).TotalHours;
                                    extraHour   = (recordAt - shift.fullEndAt.Value).TotalHours;
                                }
                                else
                                {
                                    // 如果只有一次打卡记录在应该的工作区间内,则需要人工手动调整了!
                                }
                            }
                            else
                            {
                                DateTime firstD = records.First().recordAt;
                                DateTime lastD  = records.Last().recordAt;
                                // 正常上班,无加班
                                // 1. 如果走时间在排班结束范围外内,则算整个排班时间
                                if (lastD >= shift.fullEndAt.Value &&
                                    lastD <= validEQ)
                                {
                                    if (firstD <= shift.fullStartAt)
                                    {
                                        /// 如果早来超过一个小时,可能是加班
                                        if (firstD <= shift.fullStartAt.Value.AddHours(-1))
                                        {
                                            extraHour = (shift.fullStartAt.Value - firstD).TotalHours;
                                        }
                                        // 正常
                                        workdayHour = (shift.fullEndAt.Value - shift.fullStartAt.Value).TotalHours;
                                    }
                                    else
                                    {
                                        // 迟到
                                        exceptions.Add(AttendanceExceptionType.Late);
                                        workdayHour = (shift.fullEndAt.Value - firstD).TotalHours;
                                    }
                                }
                                else
                                {
                                    if (lastD < shift.fullEndAt.Value)
                                    {
                                        // 早退
                                        exceptions.Add(AttendanceExceptionType.EarlyLeave);
                                        if (firstD < shift.fullStartAt)
                                        {
                                            /// 如果早来超过一个小时,可能是加班
                                            if (firstD <= shift.fullStartAt.Value.AddHours(-1))
                                            {
                                                extraHour = (shift.fullStartAt.Value - firstD).TotalHours;
                                            }
                                            workdayHour = (lastD - shift.fullStartAt.Value).TotalHours;
                                        }
                                        else
                                        {
                                            // 迟到+早退
                                            exceptions.Add(AttendanceExceptionType.Late);
                                            workdayHour = (lastD - firstD).TotalHours;
                                        }
                                    }
                                    else
                                    {
                                        if (lastD >= shift.fullEndAt.Value.AddHours(1))
                                        {
                                            exceptions.Add(AttendanceExceptionType.ExtraWork);

                                            workdayHour = (shift.fullEndAt.Value - shift.fullStartAt.Value).TotalHours;
                                            extraHour   = (lastD - shift.fullEndAt.Value).TotalHours;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    // 如果没有排班怎么计算?
                    // 如果没有排班,应该都是加班
                    // TODO, 根据目前和德晋HR了解情况,会排班,所以这种情况暂时不考虑
                }
                /// 暂时对没有排班的不处理
                if (shifts.Count > 0)
                {
                    // 基本工时都是 8 小时,不分部门和职称
                    if (workdayHour > 8)
                    {
                        workdayHour = 8;
                    }

                    /// 如果是双休或节假日都算加班!无论是否有排班
                    if (isRestDay)
                    {
                        extraHour  += workdayHour;
                        workdayHour = 0;
                    }
                    extraHour   = Math.Round(extraHour, 1);
                    workdayHour = Math.Round(workdayHour, 1);

                    // 如果是成型课 或者 行政课的司机,则加班不减0.5h,其它的都减
                    if (extraHour > 0)
                    {
                        exceptions.Add(AttendanceExceptionType.ExtraWork);
                        if (staff.IsMinusExtraWorkHour)
                        {
                            extraHour -= 0.5;
                            if (extraHour < 0)
                            {
                                extraHour = 0;
                            }
                        }
                        ExtraWorkRecord extraRecord = new ExtraWorkRecordService(this.DbString).FindByStaffNrAndDete(staff.nr, datetime.Date);
                        if (extraRecord == null)
                        {
                            exceptions.Add(AttendanceExceptionType.ExtraWorkNoRecord);
                        }
                        else
                        {
                            if (extraHour != extraRecord.duration)
                            {
                                exceptions.Add(AttendanceExceptionType.ExtraWorkHourNotMatch);
                            }

                            if (wr.dateType != extraRecord.ExtraWorkType.systemCode)
                            {
                                exceptions.Add(AttendanceExceptionType.ExtraWorkTypeNotMatch);
                            }
                        }
                    }

                    DataContext         comitDC   = new DataContext(this.DbString);
                    AttendanceRecordCal calRecord = comitDC.Context.GetTable <AttendanceRecordCal>().FirstOrDefault(s => s.staffNr.Equals(staff.nr) && s.attendanceDate.Equals(datetime.Date));

                    exceptions = exceptions.Distinct().ToList();
                    int?extraType = extraHour == 0 ? null : wr.dateType;
                    if (calRecord == null)
                    {
                        comitDC.Context.GetTable <AttendanceRecordCal>().InsertOnSubmit(new AttendanceRecordCal()
                        {
                            staffNr              = staff.nr,
                            attendanceDate       = datetime.Date,
                            oriWorkingHour       = workdayHour,
                            actWorkingHour       = workdayHour,
                            oriExtraWorkingHour  = extraHour,
                            actExtraWorkingHour  = extraHour,
                            extraworkType        = extraType,
                            attendanceExceptions = exceptions.Distinct().ToList(),
                            createdAt            = DateTime.Now
                        });
                    }
                    else
                    {
                        calRecord.extraworkType        = extraType;
                        calRecord.oriWorkingHour       = calRecord.actWorkingHour = workdayHour;
                        calRecord.oriExtraWorkingHour  = calRecord.actExtraWorkingHour = extraHour;
                        calRecord.createdAt            = DateTime.Now;
                        calRecord.attendanceExceptions = exceptions;
                    }
                    comitDC.Context.SubmitChanges();
                }
            }
        }