Browse Source

计算工资 3

leiy 1 year ago
parent
commit
14bc1a778e

+ 298 - 150
OASystem/OASystem.Api/OAMethodLib/PayrollComputation.cs

@@ -1,4 +1,5 @@
 using Google.Protobuf.WellKnownTypes;
+using NPOI.OpenXmlFormats.Spreadsheet;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI;
 using OASystem.Domain;
 using OASystem.Domain.Entities.PersonnelModule;
@@ -46,8 +47,6 @@ namespace OASystem.API.OAMethodLib
                 userNames = nameData.Data;
             }
 
-
-
             //获取所有打卡数据
             CheckInView checkIn = await _qiYeWeChatApiService.GetCheckin_MonthDataAsync(startDt, endDt); //时间段内所有 打卡数据
             if (checkIn.errcode != 0)
@@ -66,8 +65,7 @@ namespace OASystem.API.OAMethodLib
                 _result.Msg = startDt + " - " + endDt + "请假 类型数据 获取失败!";
                 return _result;
             }
-
-
+            
             foreach (var pm_wsInfo in pm_WageSheetDattaSources)
             {
                 string itemName = userNames.Where(it => it.Id == pm_wsInfo.UserId).FirstOrDefault().CnName;
@@ -101,16 +99,6 @@ namespace OASystem.API.OAMethodLib
                 if (checkInData == null) { continue; }
                 string acctid = checkInData.base_info.acctid; //用户Id
 
-               
-
-                List<Sp_Detail> sp_reissuecard_details = new List<Sp_Detail>();
-                sp_reissuecard_details = await _qiYeWeChatApiService.GetApprovalDetailsAsync(startDt, endDt, acctid, 2, 2); //时间段内所有 已同意的 补卡 审批数据
-                if (sp_reissuecard_details.Count <= 0)
-                {
-                    _result.Msg += startDt + " - " + endDt + "  " + itemName + "  打卡补卡 审批数据获取未获取到!\r\n";
-                    continue;
-                }
-
                 //当月总计数据
                 Summary_Info? summary_Info = checkInData.summary_info;
                 if (summary_Info == null) { continue; }
@@ -239,7 +227,8 @@ namespace OASystem.API.OAMethodLib
                             {
                                 SubTypeId = leaveType,
                                 SubType = typeName,
-                                Start_end_time_dt = startEndTiime,
+                                StartTimeDt = date_Range.new_begin_dt,
+                                EndTimeDt = date_Range.new_end_dt,
                                 Duration = new_duration,
                                 Deduction = thisTypeDeduction,
                                 //Reason = apply_data.reason,
@@ -262,26 +251,46 @@ namespace OASystem.API.OAMethodLib
                 #endregion
 
 
-                #region 打卡补卡 处理
+                Ex_Items ex_Items_dk = new Ex_Items() { Type = "打卡" };    //打卡
+                List<Ex_Item> ex_Item_Infos = new List<Ex_Item>();
+                #region 打卡补卡 补卡次数 处理
 
-                if (reissueCardNum == 3)
+                if (reissueCardNum > 0)
                 {
-                    reissuecard_deduction += 10;
-                }
-                else if (reissueCardNum >= 4)
-                {
-                    reissuecard_deduction += 50;
+                    if (reissueCardNum <= 3)
+                    {
+                        reissuecard_deduction += 10 * reissueCardNum;
+                    }
+                    else if (reissueCardNum > 3) //补卡超过三 每补卡一次 50 CNY
+                    {
+                        int for_reissueCardNum = reissueCardNum - 3;
+
+                        for (int i = 0; i < for_reissueCardNum; i++)
+                        {
+                            reissuecard_deduction += 50;
+                        }
+                    }
+
+                    Ex_Item ex_reissueCard = new Ex_Item()
+                    {
+                        SubTypeId = 7,
+                        SubType = "补卡次数",
+                        Deduction = reissuecard_deduction,
+                        Reason = "补卡:员工发现自己漏打卡时,需及时提起补卡申请,并说明情况。试用期员工每月有 2 次\r\n补卡机会,超过 2 次不足 5 次的部分,按 10 元/次处罚,5 次及以上的漏卡,按 50 元/次处罚;正式员工每月 3 次以内的补卡,按 10 元/次处罚,3 次及以上的漏卡,按 50 元/次处罚。\r\n补卡路径为:企微-工作台-审批-打卡补卡。",
+                        unit = string.Empty
+                    };
+
+                    ex_Item_Infos.Add(ex_reissueCard);
                 }
+                
 
                 #endregion
 
-                Ex_Items ex_Items_dk = new Ex_Items() { Type = "打卡" };    //打卡
-                //List<Ex_Item> ex_reissuecard_Items = new List<Ex_Item>();
-                List<dynamic> ex_reissuecard_Items = new List<dynamic>();
-                List<Sp_Detail> sp_reissuecard_item_InfosData = sp_reissuecard_details.Where(it => it.applyer.userid == acctid).ToList();
-
-                #region 打卡异常处理 统计 1-迟到;2-早退;3-缺卡;4-旷工;5-地点异常;6-设备异常;
+                List<Ex_Item> ex_reissuecard_Items = new List<Ex_Item>();
+                //List<dynamic> ex_reissuecard_Items = new List<dynamic>();
+                List<Sp_Detail> sp_reissuecard_details = new List<Sp_Detail>();
 
+                //统计迟到次数
                 int beLateNum = 0,           // 1-迟到;
                     leaveEarlyNum = 0,       // 2-早退;
                     dummyDeckNum = 0,        // 3-缺卡;
@@ -303,132 +312,271 @@ namespace OASystem.API.OAMethodLib
                     }
                 }
 
-                //foreach (Sp_Info sp_reissuecard_item in sp_reissuecard_item_InfosData)
-                //{
-                //    DateTime apply_time_dt = sp_reissuecard_item.apply_time_dt; //申请时间
-                //    List<string>? approval_name = sp_reissuecard_item.approval_name; //审核人
-
-                //    Comm sp_comm = sp_reissuecard_item.comm;
-                //    if (sp_comm != null)
-                //    {
-                //        if (sp_comm.applydata != null)
-                //        {
-                //            List<ApplyInfo> applyInfos = sp_comm.applydata;
-                //            if (applyInfos.Count > 0)
-                //            {
-                //                //Ex_Item ex_reissuecard_Item = new Ex_Item();
-                //                dynamic ex_reissuecard_Item = null;
-                //                string text = applyInfos.Where(it => it.type == "text").FirstOrDefault().value.ToString(); //异常状态
-                //                DateTime? datehour = applyInfos.Where(it => it.type == "datehour").FirstOrDefault().valueDt;//补卡时间
-                //                string textarea = applyInfos.Where(it => it.type == "textarea").FirstOrDefault().value.ToString();//补卡事由
-                //                if (text.Contains("未打卡"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 0,
-                //                        SubType = "未打卡",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("迟到"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 1,
-                //                        SubType = "迟到",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("早退"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 2,
-                //                        SubType = "早退",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("缺卡"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 3,
-                //                        SubType = "缺卡",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("旷工"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 4,
-                //                        SubType = "旷工",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("地点异常"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 5,
-                //                        SubType = "地点异常",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                else if (text.Contains("设备异常"))
-                //                {
-                //                    ex_reissuecard_Item = new
-                //                    {
-                //                        SubTypeId = 6,
-                //                        SubType = "设备异常",
-                //                        title = text,
-                //                        datehour = datehour == null ? "" : Convert.ToDateTime(datehour).ToString("yyyy-MM-dd HH:mm:ss"),
-                //                        textarea = textarea,
-                //                        apply_time_dt = apply_time_dt,
-                //                        approval_name = approval_name
-                //                    };
-                //                }
-                //                if (ex_reissuecard_Item != null)
-                //                {
-                //                    ex_reissuecard_Items.Add(ex_reissuecard_Item);
-                //                }
-                //            }
-                //        }
-                //    }
-                //}
-
-                if (ex_reissuecard_Items.Count > 0)
+
+                //打卡记录
+                CheckInDataView checkInDataView = new CheckInDataView();
+                checkInDataView = await _qiYeWeChatApiService.GetCheckinDataAsync(new List<string>() { acctid },3,startDt,endDt);
+
+                if (checkInDataView.errcode != 0)
                 {
-                    ex_Items_dk.Ex_ItemInfo = ex_reissuecard_Items.OrderBy(it => it.SubTypeId).ThenBy(it => it.datehour).ToList();
-                    ex_Items.Add(ex_Items_dk);
+                    _result.Msg += startDt + " - " + endDt + "  " + itemName + " 打卡记录 "+ checkInDataView.errmsg + " \r\n";
                 }
 
-                #endregion
+                //筛选时间异常的打卡记录
+                List<CheckInDataInfo> checkInDataInfos = checkInDataView.checkindata.Where(it => !string.IsNullOrEmpty(it.exception_type)).ToList();
 
+                //处理 未打卡的记录是否已经通过假勤审批
+                List<CheckInDataInfo> leave_checkInDataInfos = new List<CheckInDataInfo>();
+                if (checkInDataInfos.Count > 0)
+                {
+                    foreach (var leaveItem in ex_ItemInfos)
+                    {
+                        if (leaveItem.StartTimeDt.ToString("yyyy-MM-dd").Equals(leaveItem.EndTimeDt.ToString("yyyy-MM-dd"))) //单天
+                        {
+                            leave_checkInDataInfos.AddRange(checkInDataInfos.Where(it => it.checkin_time_dt.ToString("yyyy-MM-dd") == leaveItem.StartTimeDt.ToString("yyyy-MM-dd")).ToList());
+                        }
+                        else //多天
+                        {
+                            leave_checkInDataInfos.AddRange(checkInDataInfos.Where(it => it.checkin_time_dt >= leaveItem.StartTimeDt && it.checkin_time_dt <=leaveItem.EndTimeDt ).ToList());
+
+                        }
+                    }
+                }
+
+                //处理 时间异常的记录是否已经通过补卡审批
+                List<CheckInDataInfo> pullcard_checkInDataInfos = new List<CheckInDataInfo>();
+                if (leave_checkInDataInfos.Count > 0)
+                {
+                    //获取异常打卡数据 并且 未通过假勤审批
+                    pullcard_checkInDataInfos = checkInDataInfos.Except(leave_checkInDataInfos).ToList();
+
+                    if (pullcard_checkInDataInfos.Count > 0)
+                    {
+
+
+                        #region 打卡异常处理 统计 1-迟到;2-早退;3-缺卡;4-旷工;5-地点异常;6-设备异常;
+
+                        //sp_reissuecard_details = await _qiYeWeChatApiService.GetApprovalDetailsAsync(startDt, endDt, acctid, 2, 2); //时间段内所有 已同意的 补卡 审批数据
+                        //if (sp_reissuecard_details.Count <= 0)
+                        //{
+                        //    _result.Msg += startDt + " - " + endDt + "  " + itemName + "  打卡补卡 审批数据获取未获取到!\r\n";
+                        //    continue;
+                        //}
+
+                        //#region 打卡补卡
+
+                        //foreach (var pullcardItem in sp_reissuecard_details)
+                        //{
+                        //    Apply_data? apply_data = pullcardItem.apply_data;
+                        //    if (apply_data != null)
+                        //    {
+                        //        List<ContentsItem> contents = apply_data.contents;
+                        //        ContentsItem content_Vacation = contents.Where(it => it.control == "Vacation").FirstOrDefault();  //请假类型 
+                        //        ContentsItem content_Textarea = contents.Where(it => it.control == "Textarea").FirstOrDefault();  //多行文本 
+
+                        //        if (content_Vacation != null)
+                        //        {
+                        //            Vacation vacation = content_Vacation.value.vacation;
+                        //            Attendance attendance = vacation.attendance; //假勤组件
+                        //            Selector selector = vacation.selector;       //请假类型
+
+                        //            List<OptionsItem> optionsItems = selector.options; //key 请假类型 id
+                        //            List<TitleItem> value = optionsItems[0].value; // value 文本描述值
+
+                        //            int leaveType = int.Parse(optionsItems[0].key);  //key 请假子类型 id
+                        //            Date_range date_Range = attendance.date_range;
+
+                        //            decimal thisTypeDeduction = 0.00M;//当前类型扣款
+                        //            string leave_starttime = date_Range.new_begin_dt.ToString("HH:mm");
+                        //            string leave_endtime = date_Range.new_end_dt.ToString("HH:mm");
+
+                        //            string typeName = string.Empty;
+                        //            int leaveTypeId = leaveType;
+                        //            var leaveTypeData = vacationLeaveTypes.Where(it => it.id == leaveTypeId).FirstOrDefault();
+
+                        //            if (leaveTypeData != null) { typeName = leaveTypeData.name; }
+                        //            //计算请假类型扣款金额
+
+                        //            int new_duration = 0;
+                        //            if (date_Range.type == "halfday")
+                        //            {
+                        //                new_duration = date_Range.new_duration / 86400;
+                        //            }
+                        //            else if (date_Range.type == "hour")
+                        //            {
+                        //                new_duration = date_Range.new_duration / 3600;
+                        //            }
+                        //            decimal leave_meals = 0.00M;
+                        //            CalculateTypeFee(leaveType, date_Range.type, leave_starttime, leave_endtime, amountPayable, work_days, new_duration,
+                        //                out leave_meals, out thisTypeDeduction);
+
+                        //            meal_deduction += leave_meals;
+                        //            string startEndTiime = startEndTiime = date_Range.new_begin_dt.ToString("yyyy-MM-dd HH:mm") + " - " +
+                        //                date_Range.new_end_dt.ToString("yyyy-MM-dd HH:mm");
+
+                        //        }
+                        //    }
+                        //}
+
+                        #endregion
+
+                        foreach (var pc_ex_item in pullcard_checkInDataInfos)
+                        {
+
+                            CheckInDayDataView checkInDayDataView = await _qiYeWeChatApiService.GetCheckInDayDataAsync(new List<string>() { acctid },startDt,endDt);
+
+                            if (checkInDayDataView.errcode != 0)
+                            {
+                                _result.Msg += startDt + " - " + endDt + "  " + itemName + "  异常信息数据获取未获取到!\r\n";
+                                continue;
+                            }
+                            List<Root> roots_words= checkInDayDataView.datas.Where(it => it.base_info.day_type == 0).ToList(); //获取工作日日报信息
+                            List<Root> roots_exs = checkInDayDataView.datas.Where(it => it.exception_infos.Count > 0).ToList();
+                            Root roots_ex = roots_exs.Where(it => it.base_info.dateDt == pc_ex_item.sch_checkin_time_dt).FirstOrDefault();
+                            List<Exception_infos> exception_infos = roots_ex.exception_infos;
+
+                            List<Exception_infos> exception_infos1 = checkInDayDataView.datas[29].exception_infos;
+                            string exc_type = pc_ex_item.exception_type;
+
+                            if (exc_type.Contains("时间异常") || exc_type.Contains("未打卡")) // 时间异常  未打卡
+                            {
+                                int day_time_minute = (60 * 7) + 30;
+
+                                Exception_infos beLate_ex = exception_infos.Where(it => it.exception == 1).FirstOrDefault(); //迟到
+                                decimal day_miner_unit = dailyWage / 15;  //以0.5小时为单位 
+
+                                if (beLate_ex != null)
+                                {
+                                    if (beLateNum > 0) //迟到次数
+                                    {
+                                        //1:一个自然月内,不足 10 分钟的迟到/早退,不超过 2 次的部分,不做处罚;3 次及以上,按50 元 / 次处罚;
+                                        //2:超过 10 分钟(含 10 分钟),不足 60 分钟的迟到 / 早退,按 50 元 / 次处罚;
+                                        //3:超过 60 分钟(含 60 分钟),不足 3 小时的迟到 / 早退,且无请假者,按旷工半日处理;超过 3 小时的迟到 / 早退,且无请假者,按旷工一日处理。
+
+                                        Ex_Item beLate_belate_ex = new Ex_Item()
+                                        {
+                                            SubTypeId = 4,
+                                            SubType = "旷工",
+                                            unit = "分钟",
+                                        };
+                                        decimal day_beLate_deduction = 0.00M;
+                                        if (beLate_ex.duration >= 10 && beLate_ex.duration <= 60)
+                                        {
+                                            day_beLate_deduction = beLateNum * 50;
+                                            beLate_belate_ex.SubTypeId = 1;
+                                            beLate_belate_ex.SubType = "迟到";
+                                        }
+                                        else if (beLate_ex.duration > 60 && beLate_ex.duration <= 180)
+                                        {
+                                            day_beLate_deduction = day_miner_unit * 6; //3小时
+
+                                        }
+                                        else day_beLate_deduction = dailyWage;
+
+                                        beLate_deduction += day_beLate_deduction;
+
+
+                                        beLate_belate_ex.Duration = beLate_ex.duration;
+                                        beLate_belate_ex.Deduction = day_beLate_deduction;
+                                        ex_reissuecard_Items.Add(beLate_belate_ex);
+                                    }
+
+
+                                    if (leaveEarlyNum > 0) // 早退次数
+                                    {
+                                        //1:一个自然月内,不足 10 分钟的迟到/早退,不超过 2 次的部分,不做处罚;3 次及以上,按50 元 / 次处罚;
+                                        //2:超过 10 分钟(含 10 分钟),不足 60 分钟的迟到 / 早退,按 50 元 / 次处罚;
+                                        //3:超过 60 分钟(含 60 分钟),不足 3 小时的迟到 / 早退,且无请假者,按旷工半日处理;超过 3 小时的迟到 / 早退,且无请假者,按旷工一日处理。
+
+                                        Ex_Item beLate_belate_ex = new Ex_Item()
+                                        {
+                                            SubTypeId = 4,
+                                            SubType = "旷工",
+                                            unit = "分钟",
+                                        };
+                                        decimal day_beLate_deduction = 0.00M;
+                                        if (beLate_ex.duration >= 10 && beLate_ex.duration <= 60)
+                                        {
+                                            day_beLate_deduction = beLateNum * 50;
+                                            beLate_belate_ex.SubTypeId = 3;
+                                            beLate_belate_ex.SubType = "未打卡/漏卡";
+                                        }
+                                        else if (beLate_ex.duration > 60 && beLate_ex.duration <= 180)
+                                        {
+                                            day_beLate_deduction = day_miner_unit * 6; //3小时
+
+                                        }
+                                        else day_beLate_deduction = dailyWage;
+
+                                        beLate_deduction += day_beLate_deduction;
+
+                                        beLate_belate_ex.Duration = beLate_ex.duration;
+                                        beLate_belate_ex.Deduction = day_beLate_deduction;
+                                        ex_reissuecard_Items.Add(beLate_belate_ex);
+                                    }
+
+                                    if (dummyDeckNum > 0)  //缺卡
+                                    {
+                                        Ex_Item beLate_belate_ex = new Ex_Item()
+                                        {
+                                            SubTypeId = 4,
+                                            SubType = "旷工",
+                                            unit = "分钟",
+                                        };
+                                        decimal day_beLate_deduction = 0.00M;
+                                        if (beLate_ex.duration >= 10 && beLate_ex.duration <= 60)
+                                        {
+                                            day_beLate_deduction = beLateNum * 50;
+                                            beLate_belate_ex.SubTypeId = 2;
+                                            beLate_belate_ex.SubType = "早退";
+                                        }
+                                        else if (beLate_ex.duration > 60 && beLate_ex.duration <= 180)
+                                        {
+                                            day_beLate_deduction = day_miner_unit * 6; //3小时
+
+                                        }
+                                        else day_beLate_deduction = dailyWage;
+
+                                        beLate_deduction += day_beLate_deduction;
+
+                                        beLate_belate_ex.Duration = beLate_ex.duration;
+                                        beLate_belate_ex.Deduction = day_beLate_deduction;
+                                        ex_reissuecard_Items.Add(beLate_belate_ex);
+                                    }
+
+                                    if (minerNum > 0)   //矿工
+                                    {
+                                        Ex_Item beLate_belate_ex = new Ex_Item()
+                                        {
+                                            SubTypeId = 4,
+                                            SubType = "旷工",
+                                            unit = "分钟",
+                                        };
+                                        decimal day_beLate_deduction = 0.00M;
+                                        
+                                        if (beLate_ex.duration > 60 && beLate_ex.duration <= 180)
+                                        {
+                                            day_beLate_deduction = day_miner_unit * 6; //3小时
+
+                                        }
+                                        else day_beLate_deduction = dailyWage;
+
+                                        beLate_deduction += day_beLate_deduction;
+
+                                        beLate_belate_ex.Duration = beLate_ex.duration;
+                                        beLate_belate_ex.Deduction = day_beLate_deduction;
+                                        ex_reissuecard_Items.Add(beLate_belate_ex);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (ex_reissuecard_Items.Count > 0拿工资)
+                {
+                    ex_Items_dk.Ex_ItemInfo = ex_reissuecard_Items;
+                }
 
                 #region 应发合计 实发合计 扣款合计(假勤扣款,其他扣款,社保扣款,公积金代扣,个税扣款)
 

+ 19 - 0
OASystem/OASystem.Api/OAMethodLib/QiYeWeChatAPI/IQiYeWeChatApiService.cs

@@ -43,6 +43,25 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
         /// <returns></returns>
         Task<CheckInView> GetCheckin_MonthDataRedisAsync(DateTime startDt, DateTime endDt);
 
+        /// <summary>
+        /// 获取打卡记录数据
+        /// </summary>
+        /// <param name="useridlist">需要获取打卡记录的用户列表</param>
+        /// <param name="opencheckindatatype">打卡类型。1:上下班打卡;2:外出打卡;3:全部打卡</param>
+        /// <param name="startDt">获取打卡记录的开始时间。Unix时间戳</param>
+        /// <param name="endDt">获取打卡记录的结束时间。Unix时间戳</param>
+        /// <returns></returns>
+        Task<CheckInDataView> GetCheckinDataAsync(List<string> useridlist, int opencheckindatatype, DateTime startDt, DateTime endDt);
+
+        /// <summary>
+        /// 获取打卡日报数据
+        /// </summary>
+        /// <param name="useridlist"></param>
+        /// <param name="startDt"></param>
+        /// <param name="endDt"></param>
+        /// <returns></returns>
+        Task<CheckInDayDataView> GetCheckInDayDataAsync(List<string> useridlist, DateTime startDt, DateTime endDt);
+
         /// <summary>
         /// 获取审批数据(旧)
         /// </summary>

+ 140 - 3
OASystem/OASystem.Api/OAMethodLib/QiYeWeChatAPI/QiYeWeChatApiService.cs

@@ -296,7 +296,7 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
         #region 打卡
 
         /// <summary>
-        /// 获取月打卡数据(redis缓存)
+        /// 获取月打卡记录数据
         /// </summary>
         /// <param name="startDt"></param>
         /// <param name="endDt"></param>
@@ -320,7 +320,7 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
                 return checkInView;
             }
 
-            //获取打卡数据 token
+            //获取打卡数据 token
             Access_TokenView access_Token = await GetTokenAsync(2);
             if (access_Token.errcode != 0)
             {
@@ -427,6 +427,144 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
             return checkInView;
         }
 
+        /// <summary>
+        /// 获取打卡记录数据
+        /// </summary>
+        /// <param name="useridlist">需要获取打卡记录的用户列表</param>
+        /// <param name="opencheckindatatype">打卡类型。1:上下班打卡;2:外出打卡;3:全部打卡</param>
+        /// <param name="startDt">获取打卡记录的开始时间。Unix时间戳</param>
+        /// <param name="endDt">获取打卡记录的结束时间。Unix时间戳</param>
+        /// <returns></returns>
+        public async Task<CheckInDataView> GetCheckinDataAsync(List<string> useridlist, int opencheckindatatype, DateTime startDt, DateTime endDt)
+        {
+            CheckInDataView checkInDataView = new CheckInDataView();
+
+            //参数处理
+            if (useridlist.Count <= 0)
+            {
+                checkInDataView.errmsg = "请填写企业微信用户id,可为多个!";
+                return checkInDataView;
+            }
+
+            if (useridlist.Count > 100)
+            {
+                checkInDataView.errmsg = "用户列表不超过100个。若用户超过100个,请分批获取!";
+                return checkInDataView;
+            }
+
+            //获取打卡数据 token
+            Access_TokenView access_Token = await GetTokenAsync(2);
+            if (access_Token.errcode != 0)
+            {
+                checkInDataView.errcode = access_Token.errcode;
+                checkInDataView.errmsg = string.Format("【企业微信】【获取打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
+                return checkInDataView;
+            }
+
+            string url = string.Format("/cgi-bin/checkin/getcheckindata?access_token={0}", access_Token.access_token);
+
+            DateTime centerDt = startDt.AddDays(30);
+            long startTs = (long)(startDt - _1970).TotalSeconds;
+            long centerTs = (long)(centerDt - _1970).TotalSeconds;
+            long endTs = (long)(endDt - _1970).TotalSeconds;
+
+            CheckInData_Request checkInData_Req = new CheckInData_Request()
+            {
+                access_token = access_Token.access_token,
+                opencheckindatatype = opencheckindatatype, 
+                useridlist = useridlist,
+                starttime = startTs, 
+                endtime = centerTs
+            };
+
+            var json = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var create_Req = await _httpClient.PostAsync(url, content);
+            var stringResponse = await create_Req.Content.ReadAsStringAsync();
+
+            checkInDataView = System.Text.Json.JsonSerializer.Deserialize<CheckInDataView>(stringResponse,
+                new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+            if (checkInDataView.errcode != 0)
+            {
+                return checkInDataView;
+            }
+            if (centerTs != endTs)
+            {
+                checkInData_Req.starttime = centerTs;
+                checkInData_Req.endtime = endTs;
+
+                var json1 = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
+                var content1 = new StringContent(json1, Encoding.UTF8, "application/json");
+                var create_Req1 = await _httpClient.PostAsync(url, content1);
+                var stringResponse1 = await create_Req1.Content.ReadAsStringAsync();
+
+                CheckInDataView checkInDataView1 = System.Text.Json.JsonSerializer.Deserialize<CheckInDataView>(stringResponse1,
+                    new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+                if (checkInDataView1.errcode !=  0)
+                {
+                    return checkInDataView1;
+                }
+                checkInDataView.checkindata.AddRange(checkInDataView1.checkindata);
+                return checkInDataView;
+            }
+
+
+            return checkInDataView;
+        }
+
+
+        /// <summary>
+        /// 获取打卡日报数据
+        /// </summary>
+        /// <param name="useridlist"></param>
+        /// <param name="startDt"></param>
+        /// <param name="endDt"></param>
+        /// <returns></returns>
+        public async Task<CheckInDayDataView> GetCheckInDayDataAsync(List<string> useridlist, DateTime startDt, DateTime endDt)
+        {
+            CheckInDayDataView checkInDayDataView = new CheckInDayDataView();
+
+            //参数处理
+            if (useridlist.Count <= 0)
+            {
+                checkInDayDataView.errmsg = "请填写企业微信用户id,可为多个!";
+                return checkInDayDataView;
+            }
+
+
+            //获取打卡数据 token
+            Access_TokenView access_Token = await GetTokenAsync(2);
+            if (access_Token.errcode != 0)
+            {
+                checkInDayDataView.errcode = access_Token.errcode;
+                checkInDayDataView.errmsg = string.Format("【企业微信】【获取打卡日报数据】【Token】【Msg】{0}", access_Token.errmsg);
+                return checkInDayDataView;
+            }
+
+            string url = string.Format("/cgi-bin/checkin/getcheckin_daydata?access_token={0}", access_Token.access_token);
+
+            long startTs = (long)(startDt - _1970).TotalSeconds;
+            long endTs = (long)(endDt - _1970).TotalSeconds;
+
+            var checkInData_Req = new 
+            {
+                access_token = access_Token.access_token,
+                useridlist = useridlist,
+                starttime = startTs,
+                endtime = endTs
+            };
+
+            var json = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var create_Req = await _httpClient.PostAsync(url, content);
+            var stringResponse = await create_Req.Content.ReadAsStringAsync();
+
+            checkInDayDataView = System.Text.Json.JsonSerializer.Deserialize<CheckInDayDataView>(stringResponse,
+                new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+            return checkInDayDataView;
+        }
         #endregion
 
         #region 审批
@@ -759,7 +897,6 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
                 return details;
             }
 
-
             ApprovalInfoView approvalInfoView = new ApprovalInfoView();
             approvalInfoView = await GetApprovalInfoAsync(startDt,endDt, creator,sp_status, record_type);
             if (approvalInfoView.errcode != 0)

+ 40 - 0
OASystem/OASystem.Domain/Dtos/QiYeWeChat/CheckInData_Request.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OASystem.Domain.Dtos.QiYeWeChat
+{
+    /// <summary>
+    /// 企业微信 
+    /// 获取打卡记录数据 Dto
+    /// </summary>
+    public class CheckInData_Request
+    {
+        /// <summary>
+        /// 调用接口凭证。必须使用打卡应用的Secret获取access_token,获取方式参考:文档-获取access_token
+        /// </summary>
+        public string access_token { get; set; }
+
+        /// <summary>
+        /// 打卡类型。1:上下班打卡;2:外出打卡;3:全部打卡
+        /// </summary>
+        public int opencheckindatatype { get; set; }
+
+        /// <summary>
+        /// 获取打卡记录的开始时间。Unix时间戳
+        /// </summary>
+        public long starttime { get; set; }
+
+        /// <summary>
+        /// 获取打卡记录的结束时间。Unix时间戳
+        /// </summary>
+        public long endtime { get; set; }
+
+        /// <summary>
+        /// 需要获取打卡记录的用户列表
+        /// </summary>
+        public List<string> useridlist { get; set; }
+    }
+}

+ 7 - 2
OASystem/OASystem.Domain/ViewModels/PersonnelModule/WageSheetView.cs

@@ -358,9 +358,14 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         public decimal Deduction { get; set; }
 
         /// <summary>
-        /// 起止时间
+        /// 开始时间
         /// </summary>
-        public string? Start_end_time_dt { get; set; }
+        public DateTime StartTimeDt { get; set; }
+
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public DateTime EndTimeDt { get; set; }
 
         /// <summary>
         /// 请假时长

+ 38 - 0
OASystem/OASystem.Domain/ViewModels/QiYeWeChat/ApprovalDataView.cs

@@ -348,6 +348,12 @@ namespace OASystem.Domain.ViewModels.QiYeWeChat
         ///// 
         ///// </summary>
         //public List<string> sum_field { get; set; }
+
+        /// <summary>
+        /// 补卡类型模板值
+        /// </summary>
+        public Punch_Correction punch_correction { get; set; }
+
         /// <summary>
         /// 关联审批单的模板
         /// </summary>
@@ -370,6 +376,38 @@ namespace OASystem.Domain.ViewModels.QiYeWeChat
         //public List<string> wedrive_files { get; set; }
     }
 
+    /// <summary>
+    /// 补卡模板 值
+    /// </summary>
+    public class Punch_Correction
+    {
+        /// <summary>
+        /// 异常状态说明 状态 未打卡 
+        /// </summary>
+        public string state { get; set; }
+
+        /// <summary>
+        /// 补卡时间 
+        /// </summary>
+        public long time { get; set; }
+
+        /// <summary>
+        /// 开始时间 
+        /// </summary>
+        public DateTime time_dt
+        {
+            get
+            {
+                return new DateTime(time * 10000000 + 621355968000000000L).ToLocalTime();
+            }
+        }
+
+        /// <summary>
+        /// ?
+        /// </summary>
+        public long date { get; set; }
+    }
+
     /// <summary>
     /// 部门内容,即申请人在此控件选择的部门,多选模式下可能有多个
     /// </summary>

+ 128 - 0
OASystem/OASystem.Domain/ViewModels/QiYeWeChat/CheckInDataView.cs

@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OASystem.Domain.ViewModels.QiYeWeChat
+{
+    /// <summary>
+    /// 打卡记录数据
+    /// </summary>
+    public class CheckInDataView : ResponseBase
+    {
+        public List<CheckInDataInfo> checkindata { get; set; }
+    }
+
+    public class CheckInDataInfo
+    {
+        /// <summary>
+        /// 用户id
+        /// </summary>
+        public string userid { get; set; }
+
+        /// <summary>
+        /// 打卡规则名称
+        /// </summary>
+        public string groupname { get; set; }
+
+        /// <summary>
+        /// 打卡类型。字符串,目前有:上班打卡,下班打卡,外出打卡
+        /// </summary>
+        public string checkin_type { get; set; }
+
+        /// <summary>
+        /// 异常类型,字符串,包括:时间异常,地点异常,未打卡,wifi异常,非常用设备。如果有多个异常,以分号间隔
+        /// </summary>
+        public string exception_type { get; set; }
+
+        /// <summary>
+        /// 打卡时间。Unix时间戳
+        /// </summary>
+        public long checkin_time { get; set; }
+
+        /// <summary>
+        /// 打卡时间。Unix时间戳
+        /// </summary>
+        public DateTime checkin_time_dt {
+            get
+            {
+                return new DateTime(checkin_time * 10000000 + 621355968000000000L).ToLocalTime();
+            }
+        }
+
+        /// <summary>
+        /// 打卡地点title
+        /// </summary>
+        public string location_title { get; set; }
+
+        /// <summary>
+        /// 打卡地点详情
+        /// </summary>
+        public string location_detail { get; set; }
+
+        /// <summary>
+        /// 打卡wifi名称
+        /// </summary>
+        public string wifiname { get; set; }
+
+        /// <summary>
+        /// 打卡备注
+        /// </summary>
+        public string notes { get; set; }
+
+        /// <summary>
+        /// 打卡的MAC地址/bssid
+        /// </summary>
+        public string wifimac { get; set; }
+
+        /// <summary>
+        /// 打卡的附件media_id,可使用media/get获取附件
+        /// </summary>
+        public List<string> mediaids { get; set; }
+
+        /// <summary>
+        /// 位置打卡地点纬度,是实际纬度的1000000倍,与腾讯地图一致采用GCJ-02坐标系统标准
+        /// </summary>
+        public long lat { get; set; }
+
+        /// <summary>
+        /// 位置打卡地点经度,是实际经度的1000000倍,与腾讯地图一致采用GCJ-02坐标系统标准
+        /// </summary>
+        public long lng { get; set; }
+
+        /// <summary>
+        /// 打卡设备id
+        /// </summary>
+        public string deviceid { get; set; }
+
+        /// <summary>
+        /// 标准打卡时间,指此次打卡时间对应的标准上班时间或标准下班时间
+        /// </summary>
+        public long sch_checkin_time { get; set; }
+
+        /// <summary>
+        /// 打卡时间。Unix时间戳
+        /// </summary>
+        public DateTime sch_checkin_time_dt
+        {
+            get
+            {
+                return new DateTime(sch_checkin_time * 10000000 + 621355968000000000L).ToLocalTime();
+            }
+        }
+
+        /// <summary>
+        /// 规则id,表示打卡记录所属规则的id
+        /// </summary>
+        public int groupid { get; set; }
+        /// <summary>
+        /// 班次id,表示打卡记录所属规则中,所属班次的id
+        /// </summary>
+        public int schedule_id { get; set; }
+        /// <summary>
+        /// 时段id,表示打卡记录所属规则中,某一班次中的某一时段的id,如上下班时间为9:00-12:00、13:00-18:00的班次中,9:00-12:00为其中一组时段
+        /// </summary>
+        public int timeline_id { get; set; }
+    }
+}

+ 240 - 0
OASystem/OASystem.Domain/ViewModels/QiYeWeChat/CheckInDayDataView.cs

@@ -0,0 +1,240 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OASystem.Domain.ViewModels.QiYeWeChat
+{
+    /// <summary>
+    /// 打卡日报数据 View
+    /// </summary>
+    public class CheckInDayDataView : ResponseBase
+    {
+
+        public List<Root> datas { get; set; }
+
+    }
+
+    public class Root
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Base_info? base_info { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public Summary_info? summary_info { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public List<Holiday_infos>? holiday_infos { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public List<Exception_infos>? exception_infos { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public Ot_info? ot_info { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public List<Sp_itemsItem>? sp_items { get; set; }
+    }
+
+    public class Exception_infos
+    {
+        /// <summary>
+        /// 校准状态类型:1-迟到;2-早退;3-缺卡;4-旷工;5-地点异常;6-设备异常
+        /// </summary>
+        public int exception { get; set; }
+
+        /// <summary>
+        /// 当日此异常的次数
+        /// </summary>
+        public int count { get; set; }
+
+        /// <summary>
+        /// 当日此异常的时长(迟到/早退/旷工才有值)
+        /// </summary>
+        public int duration { get; set; }
+    }
+
+    public class Holiday_infos
+    {
+        public string? sp_number { get; set; }
+
+        public Sp_title? sp_title { get; set; }
+
+        public Sp_description? sp_description { get; set; }
+    }
+
+
+    public class Sp_title
+    {
+        public List<TitleItem>? data { get; set; }
+
+    }
+
+
+    public class Sp_description
+    {
+
+        public List<TitleItem>? data { get; set; }
+    }
+
+
+    public class CheckintimeItem
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public int work_sec { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int off_work_sec { get; set; }
+    }
+
+    public class Rule_info
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public int groupid { get; set; }
+        /// <summary>
+        /// 普通白班
+        /// </summary>
+        public string groupname { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int scheduleid { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string schedulename { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public List<CheckintimeItem> checkintime { get; set; }
+    }
+
+    public class Base_info
+    {
+        /// <summary>
+        /// 日报日期
+        /// </summary>
+        public long date { get; set; }
+
+        /// <summary>
+        /// 日报日期 dt
+        /// </summary>
+        public DateTime dateDt {
+            get
+            {
+                return new DateTime(date * 10000000 + 621355968000000000L).ToLocalTime();
+            }
+        }
+
+        /// <summary>
+        /// 记录类型:1-固定上下班;2-外出(此报表中不会出现外出打卡数据);3-按班次上下班;4-自由签到;5-加班;7-无规则
+        /// </summary>
+        public int record_type { get; set; }
+        /// <summary>
+        /// 打卡人员姓名
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 打卡人员别名
+        /// </summary>
+        public string name_ex { get; set; }
+        /// <summary>
+        /// 打卡人员所在部门,会显示所有所在部门
+        /// </summary>
+        public string departs_name { get; set; }
+        /// <summary>
+        /// 打卡人员账号,即userid
+        /// </summary>
+        public string acctid { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public Rule_info rule_info { get; set; }
+        /// <summary>
+        /// 日报类型:0-工作日日报;1-休息日日报
+        /// </summary>
+        public int day_type { get; set; }
+    }
+
+    public class Summary_info
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public int checkin_count { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int regular_work_sec { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int standard_work_sec { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int earliest_time { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int lastest_time { get; set; }
+    }
+
+    public class Ot_info
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public int ot_status { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int ot_duration { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public List<string> exception_duration { get; set; }
+    }
+
+    public class Sp_itemsItem
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public int type { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int vacation_id { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int count { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int duration { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int time_type { get; set; }
+        /// <summary>
+        /// 年假
+        /// </summary>
+        public string name { get; set; }
+    }
+
+}