|
@@ -7,6 +7,7 @@ import (
|
|
|
"git.baozhida.cn/ERP_libs/lib"
|
|
|
"github.com/beego/beego/v2/adapter/orm"
|
|
|
orm2 "github.com/beego/beego/v2/client/orm"
|
|
|
+ "strings"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
@@ -19,16 +20,15 @@ const (
|
|
|
|
|
|
// 考勤
|
|
|
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(200);default(0)"` // 加班类型 加班
|
|
|
- T_start_time time.Time `orm:"type(timestamp);null;"` // 开始时间
|
|
|
- T_start_prove string `orm:"size(200);null;"` // 开始证明
|
|
|
- T_end_time time.Time `orm:"type(timestamp);null;"` // 结束时间
|
|
|
- T_end_prove string `orm:"size(200);null;"` // 开始证明
|
|
|
- T_duration int `orm:"size(8);null"` // 加班时长
|
|
|
- T_text string `orm:"type(text);null"` // 请假内容
|
|
|
- T_approver string `orm:"size(32);null"` // 审批人
|
|
|
+ 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:"size(200);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 第一次保存时才设置时间
|
|
@@ -52,9 +52,8 @@ type Attendance_R struct {
|
|
|
T_type int
|
|
|
T_type_name string
|
|
|
T_start_time string
|
|
|
- T_start_prove string
|
|
|
+ T_prove_img string
|
|
|
T_end_time string
|
|
|
- T_end_prove string
|
|
|
T_duration int
|
|
|
T_text string
|
|
|
T_approver string // 审批人uuid
|
|
@@ -84,9 +83,8 @@ func AttendanceToAttendance_R(t Attendance) (r Attendance_R) {
|
|
|
r.T_type_name = Read_AttendanceType_Get(t.T_type)
|
|
|
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_start_prove = t.T_start_prove
|
|
|
+ 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_end_prove = t.T_end_prove
|
|
|
r.T_duration = t.T_duration
|
|
|
r.T_text = t.T_text
|
|
|
r.T_approver = t.T_approver
|
|
@@ -159,7 +157,7 @@ func Delete_Attendance(m Attendance) (id int64, err error) {
|
|
|
}
|
|
|
|
|
|
// 获取列表
|
|
|
-func Read_Attendance_List(T_uid, T_approver, T_month string, T_overtime, T_state, page, page_z int) (r []Attendance_R, cnt int64) {
|
|
|
+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 结构体作为表名
|
|
@@ -177,21 +175,18 @@ func Read_Attendance_List(T_uid, T_approver, T_month string, T_overtime, T_state
|
|
|
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 len(T_month) == 0 {
|
|
|
- T_month = time.Now().Format("2006-01")
|
|
|
- }
|
|
|
if T_overtime == 1 {
|
|
|
cond = cond.And("T_type", AttendanceOvertime)
|
|
|
-
|
|
|
+ } else {
|
|
|
+ cond = cond.AndNot("T_type", AttendanceOvertime)
|
|
|
}
|
|
|
- cond = cond.And("T_end_time__startswith", T_month)
|
|
|
var err error
|
|
|
if page_z == 9999 {
|
|
|
_, err = qs.SetCond((*orm2.Condition)(cond)).OrderBy("-Id").All(&map_r)
|
|
@@ -217,8 +212,101 @@ func Read_Attendance_List(T_uid, T_approver, T_month string, T_overtime, T_state
|
|
|
|
|
|
}
|
|
|
|
|
|
+// 财务查看的请假列表
|
|
|
+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).And("T_type__in", list).
|
|
|
+ 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, T_month string, page, page_z int) (r []Attendance_S, cnt int64) {
|
|
|
+func Read_Attendance_List_For_Stat(T_uid string, page, page_z int) (r []Attendance_S, cnt int64) {
|
|
|
|
|
|
o := orm.NewOrm()
|
|
|
// 也可以直接使用 Model 结构体作为表名
|
|
@@ -237,12 +325,13 @@ func Read_Attendance_List_For_Stat(T_uid, T_month string, page, page_z int) (r [
|
|
|
cond := orm.NewCondition()
|
|
|
cond = cond.And("T_State__gt", AttendanceDelete).And("T_uid", T_uid).And("T_State", AttendancePass).And("T_type__in", T_type_list)
|
|
|
|
|
|
- if len(T_month) == 0 {
|
|
|
- T_month = time.Now().Format("2006-01")
|
|
|
- }
|
|
|
- cond = cond.And("T_end_time__startswith", T_month)
|
|
|
+ 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)
|
|
|
+ _, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond)).OrderBy("Id").All(&map_r)
|
|
|
+ }
|
|
|
|
|
|
if err != nil {
|
|
|
logs.Error(lib.FuncName(), err)
|
|
@@ -261,3 +350,74 @@ func Read_Attendance_List_For_Stat(T_uid, T_month string, page, page_z int) (r [
|
|
|
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 {
|
|
|
+ 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
|
|
|
+}
|