fonchain-fiee/pkg/service/oa_new/oa_logic/durationLogic.go

546 lines
20 KiB
Go
Raw Normal View History

2025-02-19 06:24:15 +00:00
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)
}