package Attendance import ( "ERP_ams/logs" "ERP_ams/models/Account" "fmt" "github.com/beego/beego/v2/adapter/orm" orm2 "github.com/beego/beego/v2/client/orm" "gogs.baozhida.cn/zoie/ERP_libs/lib" "strings" "time" ) const ( AttendanceDelete = iota AttendancePass AttendanceNotPass AttendanceWaitAudit ) // 考勤 type Attendance struct { Id int `orm:"column(ID);size(11);auto;pk"` T_uid string `orm:"index;size(32);null"` // 用户uuid T_type int `orm:"size(20);default(0)"` // 加班类型 加班 T_start_time time.Time `orm:"type(timestamp);null;"` // 开始时间 T_prove_img string `orm:"type(text);null;"` // 请假证明 T_end_time time.Time `orm:"type(timestamp);null;"` // 结束时间 T_duration int `orm:"size(8);null"` // 加班时长 T_text string `orm:"type(text);null"` // 请假内容 T_approver string `orm:"size(32);null"` // 审批人 T_State int `orm:"size(2);default(2)"` // 0 删除 1 通过 2 未通过 3 待审核 CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间 UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"` //auto_now 每次 model 保存时都会对时间自动更新 } func (t *Attendance) TableName() string { return "attendance" } func init() { //注册模型 orm2.Debug = true orm.RegisterModel(new(Attendance)) } type Attendance_R struct { Id int T_uid string T_user_name string T_type int T_type_name string T_start_time string T_prove_img string T_end_time string T_duration int T_text string T_approver string // 审批人uuid T_approver_name string // 审批人名称 T_State int UpdateTime string } type Attendance_S struct { Id int T_type int T_type_name string T_duration int T_text string T_approver string // 审批人uuid T_approver_name string // 审批人名称 T_State int RemainingTime int // 剩余时长 UpdateTime string } // ---------------- 特殊方法 ------------------- func AttendanceToAttendance_R(t Attendance) (r Attendance_R) { r.Id = t.Id r.T_uid = t.T_uid r.T_type = t.T_type T_type_name := Read_AttendanceType_Get(t.T_type) if t.T_type > 100 { T_type_name = "扣除-" + Read_AttendanceType_Get(t.T_type-100) } r.T_type_name = T_type_name r.T_user_name = Account.Read_User_T_name_Get(t.T_uid) r.T_start_time = t.T_start_time.Format("2006-01-02 15:04:05") r.T_prove_img = t.T_prove_img r.T_end_time = t.T_end_time.Format("2006-01-02 15:04:05") r.T_duration = t.T_duration r.T_text = t.T_text r.T_approver = t.T_approver r.T_approver_name = Account.Read_User_T_name_Get(t.T_approver) r.T_State = t.T_State r.UpdateTime = t.UpdateTime.Format("2006-01-02 15:04:05") if t.T_type > 100 { r.T_start_time = "-" r.T_end_time = "-" } return r } func AttendanceToAttendance_S(t Attendance) (r Attendance_S) { r.Id = t.Id r.T_type = t.T_type T_type_name := Read_AttendanceType_Get(t.T_type) if t.T_type > 100 { T_type_name = "扣除-" + Read_AttendanceType_Get(t.T_type-100) } r.T_type_name = T_type_name r.T_duration = t.T_duration r.T_text = t.T_text r.T_approver = t.T_approver r.T_approver_name = Account.Read_User_T_name_Get(t.T_approver) r.T_State = t.T_State r.UpdateTime = t.UpdateTime.Format("2006-01-02 15:04:05") return r } // 获取 ById func Read_Attendance_ById(id int) (r Attendance, err error) { o := orm.NewOrm() r = Attendance{Id: id} err = o.Read(&r) if err != nil { logs.Error(lib.FuncName(), err) return r, err } return r, err } // 添加 func Add_Attendance(m Attendance) (id int64, err error) { o := orm.NewOrm() id, err = o.Insert(&m) if err != nil { logs.Error(lib.FuncName(), err) return } return } // 修改 func Update_Attendance(m Attendance, cols ...string) (id int64, err error) { o := orm.NewOrm() id, err = o.Update(&m, cols...) if err != nil { logs.Error(lib.FuncName(), err) return } fmt.Println("Number of records updated in database:", id) return id, nil } // 删除 func Delete_Attendance(m Attendance) (id int64, err error) { o := orm.NewOrm() m.T_State = 0 id, err = o.Update(&m, "T_State") if err != nil { logs.Error(lib.FuncName(), err) return } fmt.Println("Number of records updated in database:", id) return id, nil } // 获取列表 func Read_Attendance_List(T_uid, T_approver string, T_overtime, T_state, page, page_z int) (r []Attendance_R, cnt int64) { o := orm.NewOrm() // 也可以直接使用 Model 结构体作为表名 var map_r []Attendance qs := o.QueryTable(new(Attendance)) var offset int64 if page <= 1 { offset = 0 } else { offset = int64((page - 1) * page_z) } cond := orm.NewCondition() cond = cond.And("T_State__gt", AttendanceDelete) if len(T_uid) > 0 { cond = cond.And("T_uid", T_uid) } // 审批人 if len(T_approver) > 0 { cond = cond.And("T_approver", T_approver) } if T_state > 0 { cond = cond.And("T_State", T_state) } if T_overtime == 1 { cond = cond.And("T_type", AttendanceOvertime) } else { cond = cond.AndNot("T_type", AttendanceOvertime) } var err error if page_z == 9999 { _, err = qs.SetCond((*orm2.Condition)(cond)).OrderBy("-Id").All(&map_r) } else { _, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond)).OrderBy("-Id").All(&map_r) } if err != nil { logs.Error(lib.FuncName(), err) return } cnt, err = qs.SetCond((*orm2.Condition)(cond)).Count() if err != nil { logs.Error(lib.FuncName(), err) return } for _, v := range map_r { r = append(r, AttendanceToAttendance_R(v)) } return r, cnt } // 财务查看的请假列表 func Read_Attendance_List_For_Finance2(T_uid, T_month string) (r []Attendance_R) { o := orm.NewOrm() // 也可以直接使用 Model 结构体作为表名 var map_r []Attendance qs := o.QueryTable(new(Attendance)) cond := orm.NewCondition() if len(T_month) == 0 { T_month = time.Now().Format("2006-01") } list := []int{AttendanceSick, AttendancePersonal} cond = cond.And("T_State", AttendancePass).And("T_uid", T_uid).And("T_type__in", list).And("T_end_time__startswith", T_month) _, err := qs.SetCond((*orm2.Condition)(cond)).OrderBy("Id").All(&map_r) if err != nil { logs.Error(lib.FuncName(), err) return } var conut int for _, v := range map_r { // 如果开始日期不是本月 //if !strings.Contains(v.T_start_time.Format("2006-01-02 15:04:05"), T_month) { // //} r = append(r, AttendanceToAttendance_R(v)) conut += v.T_duration } if len(map_r) > 0 { r = append(r, Attendance_R{ T_type_name: "统计", T_duration: conut, }) } return r } func Read_Attendance_List_For_Finance(T_uid, T_month string) (r []Attendance_R) { o := orm.NewOrm() // 也可以直接使用 Model 结构体作为表名 var map_r []Attendance qs := o.QueryTable(new(Attendance)) cond := orm.NewCondition() if len(T_month) == 0 { T_month = time.Now().Format("2006-01") } list := Get_LeaveType_List() cond = cond.And("T_State", AttendancePass).And("T_uid", T_uid). AndCond(cond.Or("T_type__in", list).Or("T_type__gt", 100)). AndCond(cond.Or("T_start_time__startswith", T_month).Or("T_end_time__startswith", T_month)) _, err := qs.SetCond((*orm2.Condition)(cond)).OrderBy("Id").All(&map_r) if err != nil { logs.Error(lib.FuncName(), err) return } var conut int for _, v := range map_r { // 如果开始日期不是本月 month, _ := lib.MonthStrToTime(T_month) if !strings.Contains(v.T_start_time.Format("2006-01-02 15:04:05"), T_month) { v.T_start_time = time.Date(month.Year(), month.Month(), 1, 9, 0, 0, 0, time.Local) v.T_duration = GetLeaveDuration(v.T_start_time, v.T_end_time) } if !strings.Contains(v.T_end_time.Format("2006-01-02 15:04:05"), T_month) { lastDays := month.AddDate(0, 1, -1) v.T_end_time = time.Date(month.Year(), month.Month(), lastDays.Day(), 17, 30, 0, 0, time.Local) v.T_duration = GetLeaveDuration(v.T_start_time, v.T_end_time) } r = append(r, AttendanceToAttendance_R(v)) conut += v.T_duration } if len(map_r) > 0 { r = append(r, Attendance_R{ T_type_name: "统计", T_duration: conut, }) } return r } // 获取列表 func Read_Attendance_List_For_Stat(T_uid string, page, page_z int) (r []Attendance_S, cnt int64) { o := orm.NewOrm() // 也可以直接使用 Model 结构体作为表名 var map_r []Attendance qs := o.QueryTable(new(Attendance)) var offset int64 if page <= 1 { offset = 0 } else { offset = int64((page - 1) * page_z) } var T_type_list = []int{AttendanceOvertime, AttendanceDaysOff, AttendanceShiftPerf} cond := orm.NewCondition() cond = cond.And("T_uid", T_uid).And("T_State", AttendancePass). AndCond(cond.Or("T_type__in", T_type_list).Or("T_type__gt", 100)) var err error if page_z == 9999 { _, err = qs.SetCond((*orm2.Condition)(cond)).OrderBy("-T_start_time").All(&map_r) } else { _, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond)).OrderBy("-T_start_time").All(&map_r) } if err != nil { logs.Error(lib.FuncName(), err) return } cnt, err = qs.SetCond((*orm2.Condition)(cond)).Count() if err != nil { logs.Error(lib.FuncName(), err) return } for _, v := range map_r { r = append(r, AttendanceToAttendance_S(v)) } return r, cnt } func GetRemainingDaysOff(T_uuid string) int { attendance, _ := Read_Attendance_List_For_Stat(T_uuid, 0, 9999) var duration int for i := 0; i < len(attendance); i++ { // 调休,转绩效 减时长 if attendance[i].T_type == AttendanceDaysOff || attendance[i].T_type == AttendanceShiftPerf || attendance[i].T_type > 100 { duration -= attendance[i].T_duration } else { // 加班 加时长 duration += attendance[i].T_duration } } return duration } // 计算请假时长 返回分钟数 // 规则:早上9:00 下午17:30 午休1小时不计入请假时长 func GetLeaveDuration(startTime, endTime time.Time) int { //开始时间的小时和分钟 s_h := startTime.Hour() s_mm := startTime.Minute() e_h := endTime.Hour() e_mm := endTime.Minute() diff_day := int(endTime.Sub(startTime).Hours() / 24) // 间隔天数 var diff_hours float32 // 间隔小时 var diff_minutes float32 // 间隔分钟 if s_h < 9 { // 开始小时早于9点,从9点起算 s_h = 9 s_mm = 0 } if e_h > 17 && e_mm > 30 { // 结束时间晚于17:30点,到17:30点止 e_h = 17 e_mm = 30 } if e_mm < s_mm { // 结束分钟数<开始分钟数,向小时借 e_mm += 60 e_h-- } diff_minutes = float32(e_mm - s_mm) if diff_day > 1 { // 跨天 diff_hours = 17.5 - float32(s_h) + float32(e_h-9) // 如果开始时间小于12点 请假小时数-1 // 如果结束时间大于13点,请假小时数-1 if s_h <= 12 { diff_hours = diff_hours - 1 } if e_h >= 13 { diff_hours = diff_hours - 1 } } else { // 不跨天 // 开始时间-结束时间跨越午休时间,间隔小时数-1 diff_hours = float32(e_h - s_h) if s_h <= 12 && e_h >= 13 { diff_hours = float32(e_h - s_h - 1) } } if diff_day > 1 { diff_day -= 1 } diff_day_hours := float32(diff_day) * 7.5 diff := int((diff_day_hours+diff_hours)*60 + diff_minutes) // 分钟数量 return diff }