package oa_logic import ( "errors" "fmt" "github.com/fonchain_enterprise/fonchain-main/api/oa" "github.com/fonchain_enterprise/fonchain-main/pkg/e" "github.com/fonchain_enterprise/fonchain-main/pkg/service" "github.com/fonchain_enterprise/fonchain-main/pkg/service/oa_new/common" "github.com/fonchain_enterprise/fonchain-main/pkg/service/oa_new/model" "github.com/fonchain_enterprise/fonchain-main/pkg/utils/holiday" "go.uber.org/zap" "strconv" "strings" "time" ) func LeaveDurationHandle(applyTimes model.Data, workingTime *oa.WorkingTime) (res model.DurationRes, err error) { req := new(model.DurationReq) res = model.DurationRes{} req.ApplyTimes = applyTimes.ApplyTimes fmt.Println("====================================== workingTime ====================================================") fmt.Printf("workingTime is %+v\n", workingTime) fmt.Println("====================================== workingTime ====================================================") var times []*model.TimeOption for i := 0; i < len(workingTime.Time); i++ { times = append(times, &model.TimeOption{ OnWorkTime: workingTime.Time[i].OnWorkTime, OffWorkTime: workingTime.Time[i].OffWorkTime, }) } req.TimeOptions.Times = times if workingTime.IsWorkDay == model.IsWorkDay { req.TimeOptions.Week = "1,5" } if workingTime.Week != "" { req.TimeOptions.Week = workingTime.Week } fmt.Println("====================================== workingTime ====================================================") fmt.Printf("workingTime is %+v\n", workingTime) fmt.Println("====================================== workingTime ====================================================") // 计算 请假时长 if len(req.ApplyTimes) != 2 { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrApplytimeDisagreement, // Status: e.Failed, //}) return res, errors.New(e.ErrApplytimeDisagreement) } verifyTimeOrderErr := VerifyTimeOrder(req.ApplyTimes) if verifyTimeOrderErr != nil { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: verifyTimeOrderErr.Error(), // Status: e.Failed, //}) return res, verifyTimeOrderErr } var freeTime float64 if len(req.TimeOptions.Times) > 1 { for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) if i+1 < len(req.TimeOptions.Times) { onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i+1].OnWorkTime+":00", time.Local) } else { break } freeTime = freeTime + onWorkTime.Sub(offWorkTime).Hours() } } // 请假 日期 是 同一天 // 那么只需要 拿出 hours 或者 m 做 计算 // 请假 日期 是 同一天 // 那么只需要 拿出 hours 或者 m 做 计算 if req.ApplyTimes[0].Date == req.ApplyTimes[1].Date { if req.ApplyTimes[0].M != "" && req.ApplyTimes[1].M != "" { if req.ApplyTimes[0].M == req.ApplyTimes[1].M { res.TakeOut.Days = 0.5 res.NotTakeOut.Days = 0.5 } else { res.TakeOut.Days = 1 res.NotTakeOut.Days = 1 } } if req.ApplyTimes[0].Hour != "" { res = SingleDateDurationHandle(req) } } else { basicDays := len(holiday.SplitDates(req.ApplyTimes[0].Date, req.ApplyTimes[1].Date, "2006-01-02")) - 1 if req.ApplyTimes[0].M != "" && req.ApplyTimes[1].M != "" { if req.ApplyTimes[0].M == req.ApplyTimes[1].M { // 如果 同为 上午 或者 下午 则 记为 1.5 res.TakeOut.Days = res.TakeOut.Days + 1.5 res.NotTakeOut.Days = res.NotTakeOut.Days + 1.5 } else { if req.ApplyTimes[0].M == "上午" { // 如果 不相同 则 记为 1 res.TakeOut.Days = res.TakeOut.Days + 2 res.NotTakeOut.Days = res.NotTakeOut.Days + 2 } else if req.ApplyTimes[0].M == "下午" { res.TakeOut.Days = res.TakeOut.Days + 1 res.NotTakeOut.Days = res.NotTakeOut.Days + 1 } } isWeek, num, weekNumErr := WeekNum(req) if weekNumErr != nil { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: err.Error(), // Status: e.Failed, //}) return res, weekNumErr } if isWeek { basicDays = basicDays - num } fmt.Println("===================== 打印 isWeek num info ===================================") fmt.Printf("isWeek is : %+v\n", isWeek) fmt.Printf("num is : %+v\n", num) fmt.Println("===================== 打印 isWeek num info ===================================") res.TakeOut.Days = res.TakeOut.Days + float32(basicDays-1) res.NotTakeOut.Days = res.NotTakeOut.Days + float32(basicDays-1) } if req.ApplyTimes[0].Hour != "" { res = MultiDateDurationHandle(req, freeTime, basicDays) } } if res.TakeOut.Days == 0 && res.TakeOut.Hours == 0 && res.NotTakeOut.Days == 0 && res.NotTakeOut.Hours == 0 { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrLeaveDurationIsZero, // //Data: res, // Status: e.Failed, //}) return res, errors.New(e.ErrLeaveDurationIsZero) } return res, nil } func AnnualLeaveDurationHandle(applyTimes model.Data, workingTime *oa.WorkingTime) (res *model.DurationRes, err error) { res = new(model.DurationRes) // 记录 打卡 周期 isWork, err := IsWorkDay(common.CurrentDateStr(), workingTime.Week, workingTime.IsWorkDay) if err != nil { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrConfirmweek, // Status: e.Failed, //}) zap.L().Error("判断是否是工作日错误", zap.Error(err)) return res, errors.New(e.ErrConfirmweek) } //startTime,_ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+"00:00:00", time.Local) //endTime,_ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+"00:00:00", time.Local) holidayRes, err := holiday.GetMultiData(holiday.ConvertTime(applyTimes.ApplyTimes[0].Date), holiday.ConvertTime(applyTimes.ApplyTimes[1].Date), true) if err != nil { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrHolidayMiss, // Status: e.Failed, //}) zap.L().Error("获取节假日信息错误", zap.Error(err)) return res, errors.New(e.ErrHolidayMiss) } for i := 0; i < len(holidayRes); i++ { if holidayRes[i].Type == 0 || isWork { res.TakeOut.Days += 1 res.NotTakeOut.Days += 1 } } if res.TakeOut.Days == 0 && res.TakeOut.Hours == 0 && res.NotTakeOut.Days == 0 && res.NotTakeOut.Hours == 0 { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrLeaveDurationIsZero, // //Data: res, // Status: e.Failed, //}) zap.L().Error("请假时长为0", zap.Error(err)) return res, errors.New(e.ErrLeaveDurationIsZero) } if applyTimes.ApplyTimes[0].M == "下午" { res.TakeOut.Days = res.TakeOut.Days - 0.5 res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5 } if applyTimes.ApplyTimes[1].M == "上午" { res.TakeOut.Days = res.TakeOut.Days - 0.5 res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5 } return res, nil } func CalcAllDayDurationHandle(applyTimes model.Data) (res *model.DurationRes, err error) { res = new(model.DurationRes) holidayRes, err := holiday.GetMultiData(holiday.ConvertTime(applyTimes.ApplyTimes[0].Date), holiday.ConvertTime(applyTimes.ApplyTimes[1].Date), true) if err != nil { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrHolidayMiss, // Status: e.Failed, //}) zap.L().Error("获取节假日信息错误", zap.Error(err)) return res, errors.New(e.ErrHolidayMiss) } for i := 0; i < len(holidayRes); i++ { res.TakeOut.Days += 1 res.NotTakeOut.Days += 1 } if res.TakeOut.Days == 0 && res.TakeOut.Hours == 0 && res.NotTakeOut.Days == 0 && res.NotTakeOut.Hours == 0 { //service.ResponseMsg(c, e.SUCCESS, serializer.Response{ // Msg: e.ErrLeaveDurationIsZero, // Status: e.Failed, //}) zap.L().Error("请假时长为0", zap.Error(err)) return res, errors.New(e.ErrLeaveDurationIsZero) } if applyTimes.ApplyTimes[0].M == "下午" { res.TakeOut.Days = res.TakeOut.Days - 0.5 res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5 } if applyTimes.ApplyTimes[1].M == "上午" { res.TakeOut.Days = res.TakeOut.Days - 0.5 res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5 } return res, nil } func OutWorkDurationHandle(applyTimes model.Data) (res *model.DurationRes, err error) { res = new(model.DurationRes) startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", applyTimes.ApplyTimes[0].Date+" "+applyTimes.ApplyTimes[0].Hour+":00", time.Local) endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", applyTimes.ApplyTimes[1].Date+" "+applyTimes.ApplyTimes[1].Hour+":00", time.Local) if applyTimes.ApplyTimes[1].Hour == "23:59" { endTime = endTime.Add(1 * time.Minute) } // 计算 请假时长 res.NotTakeOut.Hours = service.HandleHourLeaveFive(endTime.Sub(startTime).Hours()) res.TakeOut.Hours = res.NotTakeOut.Hours return res, nil } func SingleDateDurationHandle(req *model.DurationReq) model.DurationRes { res := model.DurationRes{} startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.ApplyTimes[0].Hour+":00", time.Local) //hasChangeStartTime := false endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.ApplyTimes[1].Hour+":00", time.Local) if req.ApplyTimes[1].Hour == "23:59" { endTime = endTime.Add(1 * time.Minute) } var subHour float64 = 0 var commonSubHour float64 = 0 for i := 0; i < len(req.TimeOptions.Times); i++ { // 由于 设置的 考勤班次规则 可能 会出现 上下班 打卡多次的 情况 所以 要遍历 考勤规则 onWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) // 此处 应该是 进入到下一个 打卡区间 if !endTime.Before(offWorkTime) { // 如果 开始时间 在 上班时间之前 则 差值 增加 及 上班时间 减去 开始时间 if !endTime.Before(offWorkTime) || endTime.Equal(offWorkTime) { // 开始时间在 下班之前 结束时间 在 下一个 上班时间 之后 subHour + 下一个上班时间 到 前一个 下班时间的 间隔 if i > 0 { preOffWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.TimeOptions.Times[i-1].OffWorkTime+":00", time.Local) if startTime.Before(preOffWorkTime) { subHour = subHour + onWorkTime.Sub(preOffWorkTime).Hours() } } } if i+1 <= len(req.TimeOptions.Times)-1 { nextOnWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.TimeOptions.Times[i+1].OnWorkTime+":00", time.Local) if !startTime.Before(offWorkTime) && !startTime.After(nextOnWorkTime) { // 开始时间在 下班时间之后 在下一个上班时间之前 则 将 subHour + 下一个上班时间 到 开始时间的 间隔 subHour = subHour + nextOnWorkTime.Sub(startTime).Hours() } continue } } if i == len(req.TimeOptions.Times)-1 { break } } // 单独 处理 结束时间 是否是在 最后一次打卡之后 lastOffWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.TimeOptions.Times[len(req.TimeOptions.Times)-1].OffWorkTime+":00", time.Local) if endTime.After(lastOffWorkTime) { commonSubHour = commonSubHour + endTime.Sub(lastOffWorkTime).Hours() } // 单独 处理 结束时间 是否是在 最后一次打卡之后 firstOnWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+req.TimeOptions.Times[len(req.TimeOptions.Times)-len(req.TimeOptions.Times)].OnWorkTime+":00", time.Local) if !startTime.After(firstOnWorkTime) { commonSubHour = commonSubHour + firstOnWorkTime.Sub(startTime).Hours() } res.NotTakeOut.Hours = service.HandleHourLeaveFive(endTime.Sub(startTime).Hours() - commonSubHour) res.TakeOut.Hours = service.HandleHourLeaveFive(endTime.Sub(startTime).Hours() - subHour - commonSubHour) return res } func MultiDateDurationHandle(req *model.DurationReq, freeTime float64, basicDays int) model.DurationRes { res := model.DurationRes{} startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.ApplyTimes[0].Hour+":00", time.Local) endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.ApplyTimes[1].Hour+":00", time.Local) var otherSubHour float64 = 0 var addHour float64 = 0 var wholeDurationHours float64 = 0 for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) wholeDurationHours = wholeDurationHours + offWorkTime.Sub(onWorkTime).Hours() } // 计算 开始 当天的 时长 for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) // 如果 开始时间 在 上班时间之前 则 差值 增加 及 上班时间 减去 开始时间 // 此时 循环结束 if !startTime.After(onWorkTime) { //subHour = subHour + onWorkTime.Sub(startTime).Hours() addHour = addHour + offWorkTime.Sub(onWorkTime).Hours() continue } if startTime.After(onWorkTime) && !startTime.After(offWorkTime) { // 开始时间 在 区间内 则 用开始时间 减去 上班时间 结束 循环 addHour = addHour + offWorkTime.Sub(startTime).Hours() //continue } if startTime.After(offWorkTime) { continue } } for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) // 如果 开始时间 在 上班时间之前 则 差值 增加 及 上班时间 减去 开始时间 // 此时 循环结束 if !startTime.After(onWorkTime) { otherSubHour = otherSubHour + freeTime break } if startTime.After(onWorkTime) && startTime.Before(offWorkTime) { // 开始时间 在 区间内 则 用开始时间 减去 上班时间 结束 循环 if i == 0 { otherSubHour = otherSubHour + freeTime break } if i > 0 { preOffWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i-1].OffWorkTime+":00", time.Local) otherSubHour = otherSubHour + onWorkTime.Sub(preOffWorkTime).Hours() break } } } // 计算 结束 当天的 时长 for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) // 如果 开始时间 在 上班时间之前 则 差值 增加 及 上班时间 减去 开始时间 // 此时 循环结束 if !endTime.After(onWorkTime) { continue } if endTime.After(onWorkTime) && endTime.Before(offWorkTime) { // 开始时间 在 区间内 则 用开始时间 减去 上班时间 结束 循环 addHour = addHour + endTime.Sub(onWorkTime).Hours() break } if !endTime.Before(offWorkTime) { addHour = addHour + offWorkTime.Sub(onWorkTime).Hours() } } for i := 0; i < len(req.TimeOptions.Times); i++ { var offWorkTime, onWorkTime = time.Time{}, time.Time{} onWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OnWorkTime+":00", time.Local) offWorkTime, _ = time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i].OffWorkTime+":00", time.Local) // 如果 开始时间 在 上班时间之前 则 差值 增加 及 上班时间 减去 开始时间 // 此时 循环结束 if !endTime.After(onWorkTime) { continue } if endTime.After(onWorkTime) && endTime.Before(offWorkTime) { // 开始时间 在 区间内 则 用开始时间 减去 上班时间 结束 循环 if i > 0 { preOffWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+req.TimeOptions.Times[i-1].OffWorkTime+":00", time.Local) otherSubHour = otherSubHour + onWorkTime.Sub(preOffWorkTime).Hours() break } } if !endTime.Before(offWorkTime) { if i == len(req.TimeOptions.Times)-1 { otherSubHour = otherSubHour + freeTime } } } // TODO 判断 两个时间点 之间 是否超过一天 // 处理 超过一天 需要 把 freeTime 加上 !!!!!!! isWeek, num, err := WeekNum(req) if err != nil { return res } if isWeek { basicDays = basicDays - num } fmt.Println("===================== 打印 isWeek num info ===================================") fmt.Printf("isWeek is : %+v\n", isWeek) fmt.Printf("num is : %+v\n", num) fmt.Println("===================== 打印 isWeek num info ===================================") res.NotTakeOut.Hours = res.NotTakeOut.Hours + float32((wholeDurationHours+freeTime)*float64(basicDays-1)) + float32(addHour+otherSubHour) res.NotTakeOut.Hours = service.HandleHourLeaveFive(float64(res.NotTakeOut.Hours)) res.TakeOut.Hours = res.TakeOut.Hours + float32(wholeDurationHours*float64(basicDays-1)) + float32(addHour) res.TakeOut.Hours = service.HandleHourLeaveFive(float64(res.TakeOut.Hours)) return res } // WeekNum 判断 请假 区间内 是否包含 休息日 func WeekNum(req *model.DurationReq) (isWeek bool, num int, err error) { dates := holiday.SplitDates(holiday.ConvertTime(req.ApplyTimes[0].Date), holiday.ConvertTime(req.ApplyTimes[1].Date), "20060102") respData, err := holiday.GetCacheHolidayInfo(dates) if err != nil { fmt.Println("获取 日期信息 错误:", err.Error()) return false, 0, err } var startDay, endDay int startDay, _ = strconv.Atoi(strings.Split(req.TimeOptions.Week, ",")[0]) endDay, _ = strconv.Atoi(strings.Split(req.TimeOptions.Week, ",")[1]) m := make(map[int]int, 0) for i := startDay; i <= endDay; i++ { m[i] = i } fmt.Println("===================== 打印 week info ===================================") fmt.Printf("week info is : %+v\n", m) fmt.Println("===================== 打印 week info ===================================") // 默认 (1,5) 现在根据 查询出来的 week 做判断 for i := 0; i < len(respData); i++ { weekDay := int(respData[i].WeekDay) if m[weekDay] != weekDay && respData[i].Type != 0 { num += 1 isWeek = true } } return } func VerifyTimeOrder(applyTimes []model.ApplyTime) error { if len(applyTimes) != 2 { return errors.New(e.ErrApplyTime) } start, _ := time.ParseInLocation("2006-01-02", applyTimes[0].Date, time.Local) end, _ := time.ParseInLocation("2006-01-02", applyTimes[1].Date, time.Local) if !start.After(end) { if applyTimes[0].M != "" || applyTimes[1].M != "" { if start.Equal(end) { if applyTimes[0].M == "下午" && applyTimes[1].M == "上午" { return errors.New(e.ErrTimeOrder) } } return nil } if applyTimes[0].Hour != "" && applyTimes[1].Hour != "" { if start.Equal(end) { startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", applyTimes[0].Date+" "+applyTimes[0].Hour+":00", time.Local) endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", applyTimes[1].Date+" "+applyTimes[1].Hour+":00", time.Local) if startTime.After(endTime) { return errors.New(e.ErrTimeOrder) } } return nil } } return errors.New(e.ErrTimeOrder) }