package controllers import ( "github.com/gin-gonic/gin" "github.com/shopspring/decimal" "github.com/xuri/excelize/v2" "silkserver/constvar" "silkserver/controllers/request" "silkserver/controllers/response" "silkserver/extend/code" "silkserver/extend/util" "silkserver/middleware" "silkserver/models" "silkserver/pkg/logx" "silkserver/pkg/structx" "silkserver/pkg/timex" "time" ) type AttendanceController struct { } // GetTemplate // @Tags 考勤管理 // @Summary 获取模版列表 // @Produce application/json // @Param object body request.TemplateCategoryRequest true "参数" // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/getTemplate [post] func (slf AttendanceController) GetTemplate(c *gin.Context) { var params request.TemplateCategoryRequest if err := c.ShouldBind(¶ms); err != nil { util.ResponseFormat(c, code.RequestParamError, err.Error()) return } list, err := models.NewFileTemplateAttachmentSearch().SetCategory(params.Category).Find() if err != nil { util.ResponseFormat(c, code.RequestParamError, "查找失败") return } util.ResponseFormat(c, code.Success, list) } // AttendanceInput // // @Tags 考勤管理 // @Summary 考勤导入 // @Produce application/xlsx // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/attendanceInput [post] func (slf AttendanceController) AttendanceInput(c *gin.Context) { file, _, err := c.Request.FormFile("file") if err != nil { logx.Error(err.Error()) util.ResponseFormat(c, code.RequestParamError, "文件读取失败") return } defer file.Close() //读取excel文件 f, err := excelize.OpenReader(file) if err != nil { logx.Error(err.Error()) util.ResponseFormat(c, code.RequestParamError, err) return } defer f.Close() rows, err := f.GetRows("Sheet1") if err != nil { logx.Error(err.Error()) util.ResponseFormat(c, code.RequestParamError, err) return } if len(rows) <= 1 { logx.Error(err.Error()) util.ResponseFormat(c, code.RequestParamError, "该文件没有数据内容") return } attendances := make([]*models.AttendanceManage, 0) workerIds := make([]string, 0) idMap := make(map[string]interface{}) info := middleware.GetUserInfo(c) for k, row := range rows { if k == 0 { continue } var am models.AttendanceManage am.Date = row[0] am.WorkerId = row[1] am.WorkerName = row[2] am.StartWorkTime = row[3] am.EndWorkTime = row[4] if am.WorkerId != "" { idMap[am.WorkerId] = "" } am.AddPeople = info.NickName am.CreateTime = timex.TimeToString2(time.Now()) am.Status = constvar.Normal attendances = append(attendances, &am) } for K, _ := range idMap { workerIds = append(workerIds, K) } //查询人员工种 workers, err := models.NewWorkerSearch().SetIds(workerIds).FindNotTotal() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } for _, attendance := range attendances { for _, worker := range workers { if attendance.WorkerId == worker.ID { attendance.WorkTypeId = worker.WorkTypeId attendance.PhoneNum = worker.PhoneNum break } } } //查询加班规则 rule, _ := models.NewAttendanceRuleSearch().First() //查询班次信息 schedules, err := models.NewShiftScheduleSearch().SetResourceIDs(workerIds).SetResourceType(constvar.ResourceTypeWorker).FindNotTotal() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } scheduleIds := make([]string, 0) for _, schedule := range schedules { scheduleIds = append(scheduleIds, schedule.ID) } shifts, _ := models.NewShiftScheduleShiftSearch().SetShiftScheduleIDs(scheduleIds).SetPreload(true).FindNotTotal() for _, schedule := range schedules { for _, shift := range shifts { if schedule.ID == shift.ShiftScheduleID { schedule.Shift = append(schedule.Shift, &shift.Shift) } } } var overTime int64 = 0 hour := decimal.NewFromInt(3600) if rule.WeekdayRule == 2 { overTime = rule.OverTimeStart.Mul(hour).IntPart() } for _, attendance := range attendances { for _, schedule := range schedules { if attendance.WorkerId == schedule.ResourceID { if len(schedule.Shift) > 0 { attendance.Classes = schedule.Shift[0].Name if len(schedule.Shift[0].ShiftTime) > 0 { t := schedule.Shift[0].ShiftTime[0] attendance.ClassesStartTime = t.StartTime attendance.ClassesEndTime = t.EndTime //判断打卡时间 t1, _ := timex.StringToClock(attendance.EndWorkTime) t2, _ := timex.StringToClock(t.EndTime) endWork := t1.Unix() endClasses := t2.Unix() if endWork < endClasses { attendance.Status = constvar.Abnormal } else if endWork > endClasses { //判断加班 if rule.WeekdayRule == 2 { ot := endWork - endClasses if ot > overTime { attendance.OverTimeDuration = decimal.NewFromInt(ot).DivRound(hour, 2) attendance.Status = constvar.Overtime } } } } } break } } } //插入考勤数据 err = models.NewAttendanceManageSearch().CreateBatch(attendances) if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } util.ResponseFormat(c, code.Success, "导入成功") } // GetAttendanceList // // @Tags 考勤管理 // @Summary 获取考勤列表 // @Produce application/json // @Param object body request.GetAttendanceList true "参数" // @Param Authorization header string true "token" // @Success 200 {object} util.ResponseList{data=[]models.AttendanceManage} "成功" // @Router /api-jl/v1/attendance/getAttendanceList [post] func (slf AttendanceController) GetAttendanceList(c *gin.Context) { var params request.GetAttendanceList err := c.BindJSON(¶ms) if err != nil { util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误") return } manages, total, err := models.NewAttendanceManageSearch().SetPage(params.Page, params.PageSize).SetOrder("created_at desc").Find() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } util.ResponseFormatList(c, code.Success, manages, total) } // UpdateAttendance // // @Tags 考勤管理 // @Summary 更新考勤 // @Produce application/json // @Param object body request.UpdateAttendance true "参数" // @Param Authorization header string true "token" // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/updateAttendance [post] func (slf AttendanceController) UpdateAttendance(c *gin.Context) { var params request.UpdateAttendance err := c.BindJSON(¶ms) if err != nil { util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误") return } if params.Date == "" || params.WorkerId == "" { util.ResponseFormat(c, code.RequestParamError, "人员id和考勤日期不能为空") return } count, err := models.NewAttendanceManageSearch().SetDate(params.Date).SetWorkerId(params.WorkerId).Count() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } if count > 0 { m := make(map[string]interface{}) m["status"] = params.Status m["over_time_duration"] = params.OverTimeDuration err = models.NewAttendanceManageSearch().SetDate(params.Date).SetWorkerId(params.WorkerId).UpdateByMap(m) if err != nil { util.ResponseFormat(c, code.RequestParamError, "更新失败") return } } else { var manage models.AttendanceManage err = structx.AssignTo(params, &manage) if err != nil { util.ResponseFormat(c, code.RequestParamError, "数据转换失败") return } info := middleware.GetUserInfo(c) manage.AddPeople = info.NickName manage.CreateTime = timex.TimeToString2(time.Now()) err = models.NewAttendanceManageSearch().Create(&manage) if err != nil { util.ResponseFormat(c, code.RequestParamError, "更新失败") return } } util.ResponseFormat(c, code.Success, "更新成功") } // GetAttendanceStatistic // // @Tags 考勤管理 // @Summary 获取考勤统计 // @Produce application/json // @Param object body request.GetAttendanceStatistic true "参数" // @Param Authorization header string true "token" // @Success 200 {object} util.Response{data=response.AttendanceList} "成功" // @Router /api-jl/v1/attendance/getAttendanceStatistic [post] func (slf AttendanceController) GetAttendanceStatistic(c *gin.Context) { var params request.GetAttendanceStatistic err := c.BindJSON(¶ms) if err != nil { util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误") return } if params.Month == "" { util.ResponseFormat(c, code.RequestParamError, "参数不能为空") return } //获取月份天数 location, err := time.ParseInLocation("2006-01", params.Month, time.Local) if err != nil { util.ResponseFormat(c, code.RequestParamError, "月份格式错误") return } year, month, _ := location.Date() weeks := timex.GetWeeksOfMonth(year, month) manages, err := models.NewAttendanceManageSearch().SetMonth(params.Month).SetKeyword(params.Keyword).SetPreload(true).FindNotTotal() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } weekMap := map[string]string{ "Sunday": "周日", "Monday": "周一", "Tuesday": "周二", "Wednesday": "周三", "Thursday": "周四", "Friday": "周五", "Saturday": "周六", } m := make(map[string]response.AttendanceStatistic) for _, manage := range manages { var as response.AttendanceStatistic if _, ok := m[manage.WorkerId]; ok { as = m[manage.WorkerId] } else { as.WorkerId = manage.WorkerId as.WorkerName = manage.WorkerName as.WorkType = manage.WorkType.WorkName as.Month = params.Month as.WorkTypeId = manage.WorkTypeId var details []response.AttendanceDetail for _, week := range weeks { for _, day := range week { var ad response.AttendanceDetail ad.Date = day.Day() ad.WeekDay = weekMap[day.Weekday().String()] ad.Status = constvar.Vacation details = append(details, ad) } } as.Details = details } as.WeekdayOverTime = as.WeekdayOverTime.Add(manage.OverTimeDuration) as.ActualAttendanceDays = as.ActualAttendanceDays + 1 time2, _ := timex.StringToTime2(manage.Date) day := time2.Day() detail := as.Details[day-1] detail.Status = manage.Status detail.StartWorkTime = manage.StartWorkTime detail.EndWorkTime = manage.EndWorkTime detail.ClassesStartTime = manage.ClassesStartTime detail.ClassesEndTime = manage.ClassesEndTime detail.Classes = manage.Classes as.Details[day-1] = detail m[manage.WorkerId] = as } var list response.AttendanceList for _, statistic := range m { list.List = append(list.List, statistic) } util.ResponseFormat(c, code.Success, list) } // DeleteAttendanceInfo // // @Tags 考勤管理 // @Summary 删除考勤信息 // @Produce application/json // @Param object body request.DeleteAttendanceInfo true "参数" // @Param Authorization header string true "token" // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/deleteAttendanceInfo [delete] func (slf AttendanceController) DeleteAttendanceInfo(c *gin.Context) { var params request.DeleteAttendanceInfo err := c.BindJSON(¶ms) if err != nil { util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误") return } err = models.NewAttendanceManageSearch().SetIds(params.Ids).Delete() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } util.ResponseFormat(c, code.Success, "删除成功") } // GetAttendanceRule // // @Tags 考勤管理 // @Summary 获取加班规则 // @Produce application/json // @Param Authorization header string true "token" // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/getAttendanceRule [get] func (slf AttendanceController) GetAttendanceRule(c *gin.Context) { rule, err := models.NewAttendanceRuleSearch().First() if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } util.ResponseFormat(c, code.Success, rule) } // SaveAttendanceRule // // @Tags 考勤管理 // @Summary 保存加班规则 // @Produce application/json // @Param object body models.AttendanceRule true "参数" // @Param Authorization header string true "token" // @Success 200 {object} util.Response "成功" // @Router /api-jl/v1/attendance/saveAttendanceRule [post] func (slf AttendanceController) SaveAttendanceRule(c *gin.Context) { var rule models.AttendanceRule err := c.BindJSON(&rule) if err != nil { util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误") return } err = models.NewAttendanceRuleSearch().Save(&rule) if err != nil { util.ResponseFormat(c, code.RequestParamError, err) return } util.ResponseFormat(c, code.Success, "保存成功") }