1211 lines
39 KiB
Go
1211 lines
39 KiB
Go
|
package oa
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"dubbo.apache.org/dubbo-go/v3/common/logger"
|
|||
|
"fmt"
|
|||
|
detpartmentApi "github.com/fonchain_enterprise/fonchain-main/api/department"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/api/oa"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/e"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/model/login"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/model/oa_model"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/serializer"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/service"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/service/approval/model"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/service/oa_new/oa_logic"
|
|||
|
"github.com/fonchain_enterprise/fonchain-main/pkg/utils/holiday"
|
|||
|
"github.com/gin-gonic/gin"
|
|||
|
"github.com/jinzhu/copier"
|
|||
|
"strconv"
|
|||
|
"strings"
|
|||
|
"time"
|
|||
|
)
|
|||
|
|
|||
|
// CreateWorkingTime
|
|||
|
// 保存 考勤规则
|
|||
|
func CreateWorkingTime(c *gin.Context) {
|
|||
|
req := new(oa.WorkingTime)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("WorkingTime ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 重新组装 week 字段
|
|||
|
if req.Week != "" {
|
|||
|
weeks := strings.Split(req.Week, ",")
|
|||
|
if len(weeks) != 2 {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrAttendanceWeekMiss,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
startDay, _ := strconv.Atoi(weeks[len(weeks)-len(weeks)])
|
|||
|
endDay, _ := strconv.Atoi(weeks[len(weeks)-1])
|
|||
|
if startDay == 7 {
|
|||
|
startDay = 0
|
|||
|
}
|
|||
|
if endDay == 7 {
|
|||
|
endDay = 0
|
|||
|
}
|
|||
|
req.Week = strings.Join([]string{strconv.Itoa(startDay), strconv.Itoa(endDay)}, ",")
|
|||
|
}
|
|||
|
|
|||
|
fmt.Printf("保存的考勤规则 : %+v\n", req)
|
|||
|
// 针对 全部门 设置 考勤班次
|
|||
|
if req.IsAll == oa_model.IsAll && (req.DepartmentUID == "" || req.DepartmentUID == "null") {
|
|||
|
CreateTimeOptions(c, req)
|
|||
|
} else if (req.DepartmentUID != "" && req.DepartmentUID != "null") && req.PositionUID == "-1" {
|
|||
|
CreateTimeOptions(c, req)
|
|||
|
} else {
|
|||
|
CreateTimeOption(c, req)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// CreateTimeOptions
|
|||
|
// 保存 考勤规则 批量
|
|||
|
func CreateTimeOptions(c *gin.Context, req *oa.WorkingTime) {
|
|||
|
|
|||
|
departmentListReq := new(detpartmentApi.BaseAllRequest)
|
|||
|
departmentListRes, err := service.DepartmentProvider.BaseList(context.Background(), departmentListReq)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if departmentListRes.Data == nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: "部门信息获取失败,无法设置班次信息",
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
departmentList := make([]*detpartmentApi.BaseDetailResponse, 0)
|
|||
|
|
|||
|
if (req.DepartmentUID != "" && req.DepartmentUID != "null") && req.PositionUID == "-1" {
|
|||
|
for i := 0; i < len(departmentListRes.Data); i++ {
|
|||
|
if strconv.FormatUint(departmentListRes.Data[i].ID, 10) == req.DepartmentUID {
|
|||
|
departmentList = append(departmentList, departmentListRes.Data[i])
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
departmentList = departmentListRes.Data
|
|||
|
}
|
|||
|
|
|||
|
fmt.Println("================= Department list ========================")
|
|||
|
fmt.Printf("data : %+v\n", departmentList)
|
|||
|
//fmt.Printf("count:%+v\n", departmentListRes.Count)
|
|||
|
fmt.Println("================= Department list ========================")
|
|||
|
fmt.Println("")
|
|||
|
|
|||
|
workingTimes := new(oa.WorkingTimes)
|
|||
|
|
|||
|
for i := 0; i < len(departmentList); i++ {
|
|||
|
workingTime := oa.WorkingTime{}
|
|||
|
|
|||
|
copier.CopyWithOption(&workingTime, req, copier.Option{DeepCopy: true})
|
|||
|
|
|||
|
workingTime.DepartmentUID = strconv.FormatUint(departmentList[i].ID, 10)
|
|||
|
workingTime.DepartmentName = departmentList[i].Name
|
|||
|
|
|||
|
for j := 0; j < len(departmentList[i].AllPositions); j++ {
|
|||
|
positionWorkingTime := workingTime
|
|||
|
positionWorkingTime.PositionName = departmentList[i].AllPositions[j].Name
|
|||
|
positionWorkingTime.PositionUID = strconv.FormatInt(departmentList[i].AllPositions[j].ID, 10)
|
|||
|
workingTimes.Options = append(workingTimes.Options, &positionWorkingTime)
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
fmt.Println("================= workingTimes list ========================")
|
|||
|
fmt.Printf("workingTimes : %+v\n", workingTimes.Options)
|
|||
|
fmt.Println("================= workingTimes list ========================")
|
|||
|
fmt.Println("")
|
|||
|
|
|||
|
res, err := service.GrpcOAImpl.CreateWorkingTimeBatch(context.Background(), workingTimes)
|
|||
|
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// CreateTimeOption
|
|||
|
// 保存 考勤规则 单个
|
|||
|
func CreateTimeOption(c *gin.Context, req *oa.WorkingTime) {
|
|||
|
res, err := service.GrpcOAImpl.CreateWorkingTime(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
Data: res.ID,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// SaveTimeOption
|
|||
|
// 更新 考勤规则 单个
|
|||
|
func SaveTimeOption(c *gin.Context) {
|
|||
|
req := new(oa.WorkingTime)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("WorkingTime ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
res, err := service.GrpcOAImpl.SaveWorkingTime(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
//Data: res.ID,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// TimeOptionInUse
|
|||
|
// 设置生效班次
|
|||
|
func TimeOptionInUse(c *gin.Context) {
|
|||
|
req := new(oa.CommonReq)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("CommonRes ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res, err := service.GrpcOAImpl.WorkingTimeInUse(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// CancelTimeOption
|
|||
|
// 取消班次
|
|||
|
func CancelTimeOption(c *gin.Context) {
|
|||
|
req := new(oa.CommonReq)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("CommonRes ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res, err := service.GrpcOAImpl.CancelWorkingTime(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// TimeDuration
|
|||
|
// 计算 工作时长
|
|||
|
func TimeDuration(c *gin.Context) {
|
|||
|
req := new(oa_model.TimeOptions)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("TimeDuration ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if len(req.Times) < 1 {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: "错误的时间节点",
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
hours := timeDuration(req.Times)
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: "时长计算成功",
|
|||
|
Data: service.HandleHourLeaveFive(hours),
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// QueryNoSettingWorkingTimeNum
|
|||
|
// 查询 未设置 生效的 考勤班次 的 部门数量
|
|||
|
func QueryNoSettingWorkingTimeNum(c *gin.Context) {
|
|||
|
// 查询 已经设置生效的 考勤班次 的 部门
|
|||
|
req := new(oa.WorkingTimeListReq)
|
|||
|
req.InUse = oa_model.InUse
|
|||
|
req.Page = 1
|
|||
|
req.PageSize = 99999
|
|||
|
res, err := service.GrpcOAImpl.WorkingTimeList(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
departmentListReq := new(detpartmentApi.ListRequest)
|
|||
|
departmentListRes, err := service.DepartmentProvider.List(context.Background(), departmentListReq)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
count := new(oa_model.Count)
|
|||
|
count.NoSetting = len(departmentListRes.Data) - len(res.Data)
|
|||
|
count.Setting = len(res.Data)
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.GetMsg(e.SUCCESS),
|
|||
|
Data: count,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// WorkingTimeList
|
|||
|
// 查询 考勤班次 列表
|
|||
|
func WorkingTimeList(c *gin.Context) {
|
|||
|
req := new(oa.WorkingTimeListReq)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("WorkingTimeList ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res, err := service.GrpcOAImpl.WorkingTimeList(context.Background(), req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: res.Msg,
|
|||
|
Data: res,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// LeaveDuration
|
|||
|
// 计算 请假时长 <根据 设置的考勤班次>
|
|||
|
func LeaveDuration(c *gin.Context) {
|
|||
|
req := new(oa_model.DurationReq)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("LeaveDurationReq ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
userInfo := login.GetUserInfoFromC(c)
|
|||
|
|
|||
|
queryTimeOptions := make([]oa_model.QueryTimeOption, 0)
|
|||
|
for i := 0; i < len(userInfo.PositionUsers); i++ {
|
|||
|
queryTimeOption := oa_model.QueryTimeOption{
|
|||
|
PositionUID: strconv.FormatUint(userInfo.PositionUsers[i].PositionID, 10),
|
|||
|
DepartmentUID: strconv.FormatUint(userInfo.PositionUsers[i].DepartmentId, 10),
|
|||
|
}
|
|||
|
queryTimeOptions = append(queryTimeOptions, queryTimeOption)
|
|||
|
}
|
|||
|
|
|||
|
var err error
|
|||
|
|
|||
|
//if len(req.TimeOptions.Times) < 1 && (req.TimeOptions.Times == nil || len(req.TimeOptions.Times) > 0) {
|
|||
|
times := make([]*oa_model.TimeOption, 0)
|
|||
|
times, err = service.WorkingTimeBest(0, queryTimeOptions)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrAttendanceMiss,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
for i := 0; i < len(times); i++ {
|
|||
|
req.TimeOptions.Times = append(req.TimeOptions.Times, &oa_model.TimeOption{
|
|||
|
OnWorkTime: times[i].OnWorkTime,
|
|||
|
OffWorkTime: times[i].OffWorkTime,
|
|||
|
})
|
|||
|
}
|
|||
|
//}
|
|||
|
|
|||
|
var freeTime float64
|
|||
|
if len(req.TimeOptions.Times) > 1 && (req.TimeOptions.Times != nil || len(req.TimeOptions.Times) != 0) {
|
|||
|
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()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 计算 请假时长
|
|||
|
if len(req.ApplyTimes) != 2 {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrApplytimeDisagreement,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
err = service.VerifyTimeOrder(req.ApplyTimes)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res := oa_model.DurationRes{}
|
|||
|
|
|||
|
// 请假 日期 是 同一天
|
|||
|
// 那么只需要 拿出 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 := float64(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, err := isWeekly(queryTimeOptions, req)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
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.Printf("basicDays is : %+v\n", basicDays)
|
|||
|
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(queryTimeOptions, 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
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Data: res,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
func singleDateDurationHandle(req *oa_model.DurationReq) oa_model.DurationRes {
|
|||
|
res := oa_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)
|
|||
|
|
|||
|
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(queryTimeOptions []oa_model.QueryTimeOption, req *oa_model.DurationReq, freeTime, basicDays float64) oa_model.DurationRes {
|
|||
|
res := oa_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 := isWeekly(queryTimeOptions, 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.TakeOut.Hours = res.TakeOut.Hours + float32(wholeDurationHours*float64(basicDays-1)) + float32(addHour)
|
|||
|
res.NotTakeOut.Hours = service.HandleHourLeaveFive(float64(res.NotTakeOut.Hours))
|
|||
|
res.TakeOut.Hours = service.HandleHourLeaveFive(float64(res.TakeOut.Hours))
|
|||
|
|
|||
|
return res
|
|||
|
}
|
|||
|
|
|||
|
// 判断 请假 区间内 是否包含 休息日
|
|||
|
func isWeekly(queryTimeOptions []oa_model.QueryTimeOption, req *oa_model.DurationReq) (isWeek bool, num float64, 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
|
|||
|
if req.TimeOptions.Week == "" {
|
|||
|
startDay, endDay, err = service.WorkingTimeWeekBest(queryTimeOptions)
|
|||
|
if err != nil {
|
|||
|
fmt.Println("获取 考勤 week 错误:", err.Error())
|
|||
|
return false, 0, err
|
|||
|
}
|
|||
|
} else {
|
|||
|
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 weekDay == 0 {
|
|||
|
weekDay = 7
|
|||
|
}
|
|||
|
if m[weekDay] != weekDay && respData[i].Type != 0 {
|
|||
|
num += 1
|
|||
|
isWeek = true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if req.ApplyTimes[1].M == "上午" {
|
|||
|
if respData[len(respData)-1].Type == 1 {
|
|||
|
num = num - 0.5
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// TimeDuration
|
|||
|
// 计算 时间区间 时长
|
|||
|
func timeDuration(times []*oa_model.TimeOption) float64 {
|
|||
|
var hours float64
|
|||
|
for i := 0; i < len(times); i++ {
|
|||
|
if times[i].OnWorkTime != "" && times[i].OffWorkTime != "" {
|
|||
|
onWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2006-01-02 "+times[i].OnWorkTime+":00", time.Local)
|
|||
|
offWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2006-01-02 "+times[i].OffWorkTime+":00", time.Local)
|
|||
|
hours = hours + offWorkTime.Sub(onWorkTime).Hours()
|
|||
|
}
|
|||
|
}
|
|||
|
return hours
|
|||
|
}
|
|||
|
|
|||
|
// QueryWorkingTimeBest
|
|||
|
// 查询 最优考勤班次
|
|||
|
func QueryWorkingTimeBest(c *gin.Context) {
|
|||
|
|
|||
|
userInfo := login.GetUserInfoFromC(c)
|
|||
|
|
|||
|
queryTimeOptions := make([]oa_model.QueryTimeOption, 0)
|
|||
|
for i := 0; i < len(userInfo.PositionUsers); i++ {
|
|||
|
queryTimeOption := oa_model.QueryTimeOption{
|
|||
|
PositionUID: strconv.FormatUint(userInfo.PositionUsers[i].PositionID, 10),
|
|||
|
DepartmentUID: strconv.FormatUint(userInfo.PositionUsers[i].DepartmentId, 10),
|
|||
|
}
|
|||
|
queryTimeOptions = append(queryTimeOptions, queryTimeOption)
|
|||
|
}
|
|||
|
|
|||
|
fmt.Println("queryTimeOptions is = ==============================================")
|
|||
|
fmt.Println("queryTimeOptions is :", queryTimeOptions)
|
|||
|
fmt.Println("queryTimeOptions is = ==============================================")
|
|||
|
|
|||
|
best, err := service.WorkingTimeAndWeekBest(0, queryTimeOptions)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrAttendanceMiss,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.GetMsg(e.SUCCESS),
|
|||
|
Data: best,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// OverTimeDuration
|
|||
|
// 计算 加班时长
|
|||
|
func OverTimeDuration(c *gin.Context) {
|
|||
|
req := new(oa_model.DurationReq)
|
|||
|
res := new(oa_model.DurationRes)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("OverTimeDuration ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if len(req.ApplyTimes) < 1 {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrOvertimeDisagreement,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
err := service.VerifyTimeOrder(req.ApplyTimes)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().Format("2006-01-02")
|
|||
|
for i := 0; i < len(req.ApplyTimes); i++ {
|
|||
|
if req.ApplyTimes[i].Date == "" {
|
|||
|
req.ApplyTimes[i].Date = now
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
userInfo := login.GetUserInfoFromC(c)
|
|||
|
queryTimeOptions := make([]oa_model.QueryTimeOption, 0)
|
|||
|
for i := 0; i < len(userInfo.PositionUsers); i++ {
|
|||
|
queryTimeOption := oa_model.QueryTimeOption{
|
|||
|
PositionUID: strconv.FormatUint(userInfo.PositionUsers[i].PositionID, 10),
|
|||
|
DepartmentUID: strconv.FormatUint(userInfo.PositionUsers[i].DepartmentId, 10),
|
|||
|
}
|
|||
|
queryTimeOptions = append(queryTimeOptions, queryTimeOption)
|
|||
|
}
|
|||
|
|
|||
|
best, err := service.WorkingTimeAndWeekBest(0, queryTimeOptions)
|
|||
|
if err != nil || best == nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrAttendanceMiss,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 记录 打卡 周期
|
|||
|
isWork := service.ConfirmIsWork(best.Week, req.ApplyTimes[0].Date)
|
|||
|
|
|||
|
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[1].Date+" "+req.ApplyTimes[1].Hour+":00", time.Local)
|
|||
|
|
|||
|
if startTime.After(endTime) {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrTimeOrder,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
subStartTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+"12:00:00", time.Local)
|
|||
|
subEndTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+"13:00:00", time.Local)
|
|||
|
|
|||
|
var subHours float32
|
|||
|
if req.ApplyTimes[0].Date == req.ApplyTimes[1].Date {
|
|||
|
if req.ApplyTimes[0].Hour == req.ApplyTimes[1].Hour {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrOvertimeIsZero,
|
|||
|
//Data: res,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
if isWork {
|
|||
|
startWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+best.Times[0].OnWorkTime+":00", time.Local)
|
|||
|
endWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+best.Times[len(best.Times)-1].OffWorkTime+":00", time.Local)
|
|||
|
if startTime.Before(startWorkTime) && (!endTime.After(endWorkTime) && endTime.After(startWorkTime)) {
|
|||
|
endTime = startWorkTime
|
|||
|
} else if startTime.Before(startWorkTime) && endTime.After(endWorkTime) {
|
|||
|
subHours = float32(endWorkTime.Sub(startWorkTime).Hours())
|
|||
|
if endTime.Sub(endWorkTime).Hours() <= 1 {
|
|||
|
endTime = endWorkTime
|
|||
|
} else if 1 < endTime.Sub(endWorkTime).Hours() && endTime.Sub(endWorkTime).Hours() < 2 {
|
|||
|
subHours += 1
|
|||
|
}
|
|||
|
} else if !startTime.Before(startWorkTime) && startTime.Before(endWorkTime) {
|
|||
|
startTime = endWorkTime
|
|||
|
if endTime.After(endWorkTime) {
|
|||
|
if endTime.Sub(endWorkTime).Hours() <= 1 {
|
|||
|
endTime = endWorkTime
|
|||
|
} else if 1 < endTime.Sub(endWorkTime).Hours() && endTime.Sub(endWorkTime).Hours() < 2 {
|
|||
|
subHours += 1
|
|||
|
}
|
|||
|
} else {
|
|||
|
endTime = endWorkTime
|
|||
|
}
|
|||
|
} else if !startTime.Before(endWorkTime) && !endTime.Before(endWorkTime) {
|
|||
|
if !startTime.After(endWorkTime.Add(60 * 60 * time.Second)) {
|
|||
|
if endTime.Sub(startTime).Hours() < 2 {
|
|||
|
startTime = endWorkTime.Add(60 * 60 * time.Second)
|
|||
|
}
|
|||
|
}
|
|||
|
/*if endTime.Sub(startTime).Hours() <= 1 {
|
|||
|
startTime = endWorkTime
|
|||
|
endTime = endWorkTime
|
|||
|
} else if 1 < endTime.Sub(startTime).Hours() && endTime.Sub(startTime).Hours() < 2 {
|
|||
|
if !startTime.After(endWorkTime.Add(60 * 60 * time.Second)) {
|
|||
|
startTime = endWorkTime.Add(60 * 60 * time.Second)
|
|||
|
}
|
|||
|
}*/
|
|||
|
}
|
|||
|
} else {
|
|||
|
if startTime.Before(subStartTime) {
|
|||
|
if endTime.After(subEndTime) { // 不包含 13:00
|
|||
|
subHours += 1
|
|||
|
} else if !endTime.After(subEndTime) && !endTime.Before(subStartTime) { // 包含 12:00 13:00
|
|||
|
endTime = subStartTime
|
|||
|
}
|
|||
|
} else if !startTime.Before(subStartTime) && !startTime.After(subEndTime) {
|
|||
|
startTime = subEndTime
|
|||
|
if !endTime.After(subEndTime) && !endTime.Before(subStartTime) { // 包含 12:00 13:00
|
|||
|
endTime = subEndTime
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else { // 如果 加班 开始日期和结束日期 不是同一天 则 默认 会有 一小时 需要剔除
|
|||
|
if startTime.Before(subStartTime) {
|
|||
|
if endTime.After(subEndTime) {
|
|||
|
subHours += 2
|
|||
|
} else if !endTime.After(subEndTime) && endTime.After(subEndTime.Add(-60*60*time.Second)) {
|
|||
|
subHours += 1
|
|||
|
endTime = subEndTime.Add(-60 * 60 * time.Second)
|
|||
|
}
|
|||
|
} else if !startTime.Before(subStartTime) && !startTime.After(subStartTime.Add(60*60*time.Second)) {
|
|||
|
startTime = subStartTime.Add(60 * 60 * time.Second)
|
|||
|
if endTime.After(subEndTime) {
|
|||
|
subHours += 1
|
|||
|
} else if !endTime.After(subEndTime) && endTime.After(subEndTime.Add(-60*60*time.Second)) {
|
|||
|
endTime = subEndTime.Add(-60 * 60 * time.Second)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
startDay, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[0].Date+" "+"00:00:00", time.Local)
|
|||
|
endDay, _ := time.ParseInLocation("2006-01-02 15:04:05", req.ApplyTimes[1].Date+" "+"00:00:00", time.Local)
|
|||
|
offsetDay := endDay.Sub(startDay).Hours() / 24
|
|||
|
if offsetDay >= 2 {
|
|||
|
subHours += float32(offsetDay) - 1
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
originHour := endTime.Sub(startTime).Hours()
|
|||
|
|
|||
|
//var hour float64
|
|||
|
//hour = math.Floor(originHour / 1)
|
|||
|
//if math.Mod(originHour, 1) >= 0.5 {
|
|||
|
// hour = hour + 0.5
|
|||
|
//}
|
|||
|
|
|||
|
res.NotTakeOut.Hours = service.HandleHourLeaveFive(originHour) - subHours
|
|||
|
res.TakeOut.Hours = service.HandleHourLeaveFive(originHour) - subHours
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.GetMsg(e.SUCCESS),
|
|||
|
Data: res,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
病假: 需要查询剩余天数
|
|||
|
规则 :工作年限 > 1 day : 3 工作年限 >= 3 day : 5
|
|||
|
年假: 需要查询剩余天数
|
|||
|
规则 :工作年限 < 1 在职天数/365 * 5 舍 小数点
|
|||
|
1 <= 工作年限 < 5 day : 5
|
|||
|
5 <= 工作年限 < 10 day : 7
|
|||
|
10 <= 工作年限 < 20 day : 10
|
|||
|
20 <= 工作年限 day : 15
|
|||
|
注: 节假日 不算入 年假
|
|||
|
调休: 需要查询 加班时长
|
|||
|
规则 :总加班时长 >= 总调休时长
|
|||
|
注: 单位: h
|
|||
|
婚假:
|
|||
|
规则 :包含周末、不可间隔休、结婚日期开始六个月内休完
|
|||
|
前3天遇国假不顺延、后10天遇国假顺延
|
|||
|
注: 总时长: 13天
|
|||
|
产假:
|
|||
|
规则 :每多一个小孩 多 15 天, 难产 多 15 天
|
|||
|
注: 基础时长 158天
|
|||
|
孕检假:
|
|||
|
规则 :1~6 每月一次 7~8 每月两次 之后 每周两次 天
|
|||
|
陪产假:
|
|||
|
规则 :15天
|
|||
|
流产假:
|
|||
|
规则 :1~4 15天 4 以后 42天
|
|||
|
育儿假: 需要查询剩余天数
|
|||
|
规则 :三周岁前 每年 10天
|
|||
|
独生子女护理假: 需要查询剩余天数
|
|||
|
规则 :60岁之后 每年享有 5 天
|
|||
|
哺乳假:
|
|||
|
规则 :一周岁之前 每半天可有 0.5h 一天 1h
|
|||
|
每多一婴儿 多 0.5h
|
|||
|
|
|||
|
加班: 完结
|
|||
|
规则 :工作日加班 开始时间为 最后一次下班卡时间 结束时间在下班时间后两小时内, 时长从 下班卡后一小时开始 如果超过 两小时 则从 下班时间开始算
|
|||
|
*/
|
|||
|
|
|||
|
func CheckLeave(c *gin.Context) {
|
|||
|
req := new(oa_model.CheckLeave)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("MaritalLeaveTime ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res := new(oa_model.CheckLeaveRes)
|
|||
|
var err error
|
|||
|
|
|||
|
userInfo := login.GetUserInfoFromC(c)
|
|||
|
|
|||
|
_, forMoney, canDayOffErr := oa_logic.QueryCanDayOffUserWithWorkTimeTemplate(userInfo)
|
|||
|
if canDayOffErr != nil {
|
|||
|
lang := c.Request.Header.Get("Accept-Language")
|
|||
|
errStr := model.GetLanguageType(lang, "考勤规则查询错误")
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: errStr,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
res, err = service.CheckLeaveHandle(req, userInfo, forMoney)
|
|||
|
if err != nil {
|
|||
|
lang := c.Request.Header.Get("Accept-Language")
|
|||
|
errStr := model.GetLanguageType(lang, err.Error())
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: errStr,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Data: res,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
func AnnualLeaveDuration(c *gin.Context) {
|
|||
|
req := new(oa_model.DurationReq)
|
|||
|
res := new(oa_model.DurationRes)
|
|||
|
if err := c.ShouldBind(&req); err != nil {
|
|||
|
logger.Errorf("AnnualLeaveDuration ShouldBind err", err)
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if len(req.ApplyTimes) < 1 {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrOvertimeDisagreement,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
err := service.VerifyTimeOrder(req.ApplyTimes)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().Format("2006-01-02")
|
|||
|
for i := 0; i < len(req.ApplyTimes); i++ {
|
|||
|
if req.ApplyTimes[i].Date == "" {
|
|||
|
req.ApplyTimes[i].Date = now
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
userInfo := login.GetUserInfoFromC(c)
|
|||
|
queryTimeOptions := make([]oa_model.QueryTimeOption, 0)
|
|||
|
for i := 0; i < len(userInfo.PositionUsers); i++ {
|
|||
|
queryTimeOption := oa_model.QueryTimeOption{
|
|||
|
PositionUID: strconv.FormatUint(userInfo.PositionUsers[i].PositionID, 10),
|
|||
|
DepartmentUID: strconv.FormatUint(userInfo.PositionUsers[i].DepartmentId, 10),
|
|||
|
}
|
|||
|
queryTimeOptions = append(queryTimeOptions, queryTimeOption)
|
|||
|
}
|
|||
|
|
|||
|
// 记录 打卡 周期
|
|||
|
isWork, _, err := service.ConfirmIsWeek(oa_model.Week[time.Now().Weekday().String()], queryTimeOptions)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrConfirmweek,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
//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(req.ApplyTimes[0].Date), holiday.ConvertTime(req.ApplyTimes[1].Date), true)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrHolidayMiss,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
for i := 0; i < len(holidayRes); i++ {
|
|||
|
if holidayRes[i].Type == 0 || isWork == oa_model.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,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if req.ApplyTimes[0].M == "下午" {
|
|||
|
res.TakeOut.Days = res.TakeOut.Days - 0.5
|
|||
|
res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5
|
|||
|
}
|
|||
|
|
|||
|
if req.ApplyTimes[1].M == "上午" {
|
|||
|
res.TakeOut.Days = res.TakeOut.Days - 0.5
|
|||
|
res.NotTakeOut.Days = res.NotTakeOut.Days - 0.5
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Data: res,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
func CheckWifi(c *gin.Context) {
|
|||
|
ip := c.ClientIP()
|
|||
|
if ip == "" {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrIpMiss,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
isWifi, err := service.CheckWifi(ip)
|
|||
|
if err != nil {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: err.Error(),
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if !isWifi {
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Msg: e.ErrWifiIsNotIn,
|
|||
|
Data: ip,
|
|||
|
Status: e.Failed,
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
service.ResponseMsg(c, e.SUCCESS, serializer.Response{
|
|||
|
Data: ip,
|
|||
|
Status: e.Ok,
|
|||
|
})
|
|||
|
}
|