浏览代码

2023-04-20

zoie 2 年之前
父节点
当前提交
a1371b652d
共有 12 个文件被更改,包括 408 次插入140 次删除
  1. 1 1
      .gitignore
  2. 10 8
      conf/app.conf
  3. 31 59
      controllers/Overtime.go
  4. 120 19
      controllers/leave.go
  5. 1 0
      go.mod
  6. 2 0
      go.sum
  7. 1 4
      main.go
  8. 3 0
      models/Account/Menu.go
  9. 187 27
      models/Attendance/Attendance.go
  10. 40 13
      models/Attendance/AttendanceType.go
  11. 10 7
      routers/Leave.go
  12. 2 2
      routers/Overtime.go

+ 1 - 1
.gitignore

@@ -33,6 +33,6 @@ _testmain.go
 lastupdate.tmp
 main
 nohup.out
-ERP_ams8210
+ERP_ams6701
 Makefile
 ofile

+ 10 - 8
conf/app.conf

@@ -1,5 +1,5 @@
 appname = ERP_ams
-HTTPPort = 8210
+HTTPPort = 6701
 runmode = dev
 Graceful = true
 EnableDocs = true
@@ -7,18 +7,20 @@ copyrequestbody = true
 
 Sys_Name = "ERP_AMS"
 # Nats
-NatsServer_Url = "127.0.0.1:4222"
+# NatsServer_Url = "192.168.192.251:4222"
+NatsServer_Url = "175.178.229.79:4222"
 
-# Mysql
-MysqlServer_UrlPort = "47.111.15.17:3306"
-MysqlServer_Database = "erp_user"
-MysqlServer_Username = "erp_user"
-MysqlServer_Password = "DxwTJra8k5rrMdRG"
+
+# Mysql 线上
+MysqlServer_UrlPort = "192.168.192.251:3306"
+MysqlServer_Database = "erp_ams_test"
+MysqlServer_Username = "erp_ams_test"
+MysqlServer_Password = "k24fRJB7pMrmeas3"
 MysqlServer_MaxIdleConnections = 100
 MysqlServer_MaxOpenConnections = 200
 
 # Redis
-Redis_address = "47.111.15.17:6379"
+Redis_address = "192.168.192.251:6379"
 Redis_password = ""
 Redis_dbNum = "1"
 

+ 31 - 59
controllers/Overtime.go

@@ -5,12 +5,12 @@ import (
 	"ERP_ams/conf"
 	"ERP_ams/models/Account"
 	"ERP_ams/models/Attendance"
+	"fmt"
 	userlibs "git.baozhida.cn/ERP_libs/User"
 	"git.baozhida.cn/ERP_libs/lib"
 	beego "github.com/beego/beego/v2/server/web"
 	"math"
 	"strconv"
-	"time"
 )
 
 type OvertimeController struct {
@@ -34,21 +34,10 @@ func (c *OvertimeController) Overtime_List() {
 	if page_z < 1 {
 		page_z = conf.Page_size
 	}
-	// 年月 2023-01
-	T_month := c.GetString("T_month")
-
-	if len(T_month) > 0 {
-		_, err := time.Parse("2006-01", T_month)
-		if err != nil {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
-			c.ServeJSON()
-			return
-		}
-	}
 
 	userList, _ := NatsServer.Read_User_List_All()
 	Account.Read_User_All_Map(userList)
-	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List("", c.User.T_uuid, T_month, 1, Attendance.AttendanceWaitAudit, page, page_z)
+	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List("", c.User.T_uuid, 1, Attendance.AttendanceWaitAudit, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -74,17 +63,9 @@ func (c *OvertimeController) Overtime_User_List() {
 	if len(T_uuid) == 0 {
 		T_uuid = c.User.T_uuid
 	}
-	// 年月 2023-01
-	T_month := c.GetString("T_month")
-	if len(T_month) > 0 {
-		_, err := time.Parse("2006-01", T_month)
-		if err != nil {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
-			c.ServeJSON()
-			return
-		}
-	}
-	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List(T_uuid, "", T_month, 1, 0, page, page_z)
+	userList, _ := NatsServer.Read_User_List_All()
+	Account.Read_User_All_Map(userList)
+	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List(T_uuid, "", 1, 0, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -95,9 +76,8 @@ func (c *OvertimeController) Overtime_User_List() {
 
 func (c *OvertimeController) Overtime_Add() {
 	T_start_time := c.GetString("T_start_time")
-	T_start_prove := c.GetString("T_start_prove")
+	T_prove_img := c.GetString("T_prove_img")
 	T_end_time := c.GetString("T_end_time")
-	T_end_prove := c.GetString("T_end_prove")
 	T_duration, _ := c.GetInt("T_duration")
 	T_text := c.GetString("T_text")
 	T_approver := c.GetString("T_approver")
@@ -114,16 +94,15 @@ func (c *OvertimeController) Overtime_Add() {
 		return
 	}
 	var_ := Attendance.Attendance{
-		T_uid:         c.User.T_uuid,
-		T_type:        Attendance.AttendanceOvertime,
-		T_start_time:  startTime,
-		T_start_prove: T_start_prove,
-		T_end_time:    endTime,
-		T_end_prove:   T_end_prove,
-		T_duration:    T_duration,
-		T_text:        T_text,
-		T_approver:    T_approver,
-		T_State:       Attendance.AttendanceWaitAudit,
+		T_uid:        c.User.T_uuid,
+		T_type:       Attendance.AttendanceOvertime,
+		T_start_time: startTime,
+		T_prove_img:  T_prove_img,
+		T_end_time:   endTime,
+		T_duration:   T_duration,
+		T_text:       T_text,
+		T_approver:   T_approver,
+		T_State:      Attendance.AttendanceWaitAudit,
 	}
 
 	_, err := Attendance.Add_Attendance(var_)
@@ -134,6 +113,7 @@ func (c *OvertimeController) Overtime_Add() {
 	}
 
 	NatsServer.AddUserLogs(c.User.T_uuid, "我的加班", "添加", var_)
+	NatsServer.AddNews(T_approver, fmt.Sprintf("您有一条【%s】的加班审批待处理", c.User.T_name), "/overtime")
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: var_.Id}
 	c.ServeJSON()
@@ -144,9 +124,8 @@ func (c *OvertimeController) Overtime_Update() {
 	T_id, _ := c.GetInt("T_id")
 	T_type, _ := c.GetInt("T_type")
 	T_start_time := c.GetString("T_start_time")
-	T_start_prove := c.GetString("T_start_prove")
+	T_prove_img := c.GetString("T_prove_img")
 	T_end_time := c.GetString("T_end_time")
-	T_end_prove := c.GetString("T_end_prove")
 	T_duration, _ := c.GetInt("T_duration")
 	T_text := c.GetString("T_text")
 	T_approver := c.GetString("T_approver")
@@ -159,7 +138,7 @@ func (c *OvertimeController) Overtime_Update() {
 	}
 
 	if leave.T_State == Attendance.AttendancePass {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权修改!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "加班审批已通过,禁止修改!"}
 		c.ServeJSON()
 		return
 	}
@@ -178,9 +157,7 @@ func (c *OvertimeController) Overtime_Update() {
 		leave.T_start_time = startTime
 
 	}
-	if len(T_start_prove) > 0 {
-		leave.T_start_prove = T_start_prove
-	}
+	leave.T_prove_img = T_prove_img
 
 	if len(T_end_time) > 0 {
 		endTime, is := lib.TimeStrToTime(T_end_time)
@@ -191,9 +168,6 @@ func (c *OvertimeController) Overtime_Update() {
 		}
 		leave.T_end_time = endTime
 	}
-	if len(T_end_prove) > 0 {
-		leave.T_end_prove = T_end_prove
-	}
 
 	if T_duration > 0 {
 		leave.T_duration = T_duration
@@ -207,7 +181,7 @@ func (c *OvertimeController) Overtime_Update() {
 	}
 	leave.T_State = Attendance.AttendanceWaitAudit
 
-	_, err = Attendance.Update_Attendance(leave, "T_type", "T_start_time", "T_start_prove", "T_end_time", "T_end_prove", "T_duration", "T_text", "T_approver", "T_State")
+	_, err = Attendance.Update_Attendance(leave, "T_type", "T_start_time", "T_prove_img", "T_end_time", "T_duration", "T_text", "T_approver", "T_State")
 	if err != nil {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败"}
 		c.ServeJSON()
@@ -254,6 +228,7 @@ func (c *OvertimeController) Overtime_Approval() {
 	}
 
 	NatsServer.AddUserLogs(c.User.T_uuid, "加班审批", "审批", leave)
+	NatsServer.AddNews(leave.T_uid, "您的加班申请已通过", "/myOvertime")
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: id}
 	c.ServeJSON()
@@ -272,7 +247,7 @@ func (c *OvertimeController) Overtime_Del() {
 	}
 
 	if leave.T_State == Attendance.AttendancePass {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权删除!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "加班审批已通过,禁止删除!"}
 		c.ServeJSON()
 		return
 	}
@@ -302,23 +277,20 @@ func (c *OvertimeController) Overtime_Stat() {
 	if page_z < 1 {
 		page_z = conf.Page_size
 	}
-	// 年月 2023-01
-	T_month := c.GetString("T_month")
-	if len(T_month) > 0 {
-		_, err := time.Parse("2006-01", T_month)
-		if err != nil {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
-			c.ServeJSON()
-			return
-		}
+	T_uuid := c.GetString("T_uuid")
+	if len(T_uuid) == 0 {
+		T_uuid = c.User.T_uuid
 	}
 
-	attendance, cnt := Attendance.Read_Attendance_List_For_Stat(c.User.T_uuid, T_month, page, page_z)
+	attendance, cnt := Attendance.Read_Attendance_List_For_Stat(T_uuid, page, page_z)
 
+	userList, _ := NatsServer.Read_User_List_All()
+	Account.Read_User_All_Map(userList)
 	var duration int
 	for i := 0; i < len(attendance); i++ {
 		if attendance[i].T_type == Attendance.AttendanceDaysOff || attendance[i].T_type == Attendance.AttendanceShiftPerf {
 			duration -= attendance[i].T_duration
+			attendance[i].T_duration = -attendance[i].T_duration
 		} else {
 			duration += attendance[i].T_duration
 		}
@@ -329,7 +301,7 @@ func (c *OvertimeController) Overtime_Stat() {
 	type R_JSONS struct {
 		//必须的大写开头
 		Data          interface{}
-		RemainingTime int
+		RemainingTime int // 剩余时长
 		Num           int64
 		Page          int
 		Page_size     int
@@ -337,7 +309,7 @@ func (c *OvertimeController) Overtime_Stat() {
 
 	var r_jsons R_JSONS
 	r_jsons.Num = cnt
-	r_jsons.RemainingTime = duration
+	r_jsons.RemainingTime = Attendance.GetRemainingDaysOff(T_uuid)
 	r_jsons.Data = attendance
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))

+ 120 - 19
controllers/leave.go

@@ -5,6 +5,7 @@ import (
 	"ERP_ams/conf"
 	"ERP_ams/models/Account"
 	"ERP_ams/models/Attendance"
+	"fmt"
 	userlibs "git.baozhida.cn/ERP_libs/User"
 	"git.baozhida.cn/ERP_libs/lib"
 	beego "github.com/beego/beego/v2/server/web"
@@ -35,20 +36,9 @@ func (c *LeaveController) Leave_List() {
 	if page_z < 1 {
 		page_z = conf.Page_size
 	}
-	// 年月 2023-01
-	T_month := c.GetString("T_month")
-	if len(T_month) > 0 {
-		_, err := time.Parse("2006-01", T_month)
-		if err != nil {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
-			c.ServeJSON()
-			return
-		}
-	}
-
 	userList, _ := NatsServer.Read_User_List_All()
 	Account.Read_User_All_Map(userList)
-	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List("", c.User.T_uuid, T_month, 0, Attendance.AttendanceWaitAudit, page, page_z)
+	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List("", c.User.T_uuid, 0, Attendance.AttendanceWaitAudit, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -73,9 +63,28 @@ func (c *LeaveController) Leave_User_List() {
 	if len(T_uuid) == 0 {
 		T_uuid = c.User.T_uuid
 	}
+
+	userList, _ := NatsServer.Read_User_List_All()
+	Account.Read_User_All_Map(userList)
+	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List(T_uuid, "", 0, 0, page, page_z)
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
+
+// 财务
+func (c *LeaveController) Leave_Finance_List() {
+	var r_jsons lib.R_JSONS
+
+	T_uuid := c.GetString("T_uuid")
+	if len(T_uuid) == 0 {
+		T_uuid = c.User.T_uuid
+	}
 	// 年月 2023-01
 	T_month := c.GetString("T_month")
-
 	if len(T_month) > 0 {
 		_, err := time.Parse("2006-01", T_month)
 		if err != nil {
@@ -84,10 +93,7 @@ func (c *LeaveController) Leave_User_List() {
 			return
 		}
 	}
-
-	r_jsons.Data, r_jsons.Num = Attendance.Read_Attendance_List(T_uuid, "", T_month, 0, 0, page, page_z)
-	r_jsons.Page = page
-	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
+	r_jsons.Data = Attendance.Read_Attendance_List_For_Finance(T_uuid, T_month)
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
 	c.ServeJSON()
@@ -119,6 +125,16 @@ func (c *LeaveController) Leave_Add() {
 		c.ServeJSON()
 		return
 	}
+
+	if T_type == Attendance.AttendanceDaysOff {
+		duration := Attendance.GetRemainingDaysOff(c.User.T_uuid)
+		if T_duration > duration {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "超过可调休时长!"}
+			c.ServeJSON()
+			return
+		}
+	}
+
 	var_ := Attendance.Attendance{
 		T_uid:        c.User.T_uuid,
 		T_type:       T_type,
@@ -138,6 +154,7 @@ func (c *LeaveController) Leave_Add() {
 	}
 
 	NatsServer.AddUserLogs(c.User.T_uuid, "我的请假", "添加", var_)
+	NatsServer.AddNews(T_approver, fmt.Sprintf("您有一条【%s】的请假审批待处理", c.User.T_name), "/leave")
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id}
 	c.ServeJSON()
@@ -191,7 +208,7 @@ func (c *LeaveController) Leave_Update() {
 	}
 
 	if leave.T_State == Attendance.AttendancePass {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权修改!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "请假审批已通过,禁止修改!"}
 		c.ServeJSON()
 		return
 	}
@@ -278,6 +295,7 @@ func (c *LeaveController) Leave_Approval() {
 	}
 
 	NatsServer.AddUserLogs(c.User.T_uuid, "我的请假", "审批", leave)
+	NatsServer.AddNews(leave.T_uid, "您的请假申请已通过", "/myOvertime")
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: id}
 	c.ServeJSON()
@@ -295,7 +313,7 @@ func (c *LeaveController) Leave_Del() {
 	}
 
 	if leave.T_State == Attendance.AttendancePass {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权删除!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "请假审批已通过,禁止删除!"}
 		c.ServeJSON()
 		return
 	}
@@ -313,3 +331,86 @@ func (c *LeaveController) Leave_Del() {
 	c.ServeJSON()
 	return
 }
+
+// 获取剩余调休时长
+func (c *LeaveController) Leave_RemainingDaysOff() {
+
+	duration := Attendance.GetRemainingDaysOff(c.User.T_uuid)
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: duration}
+	c.ServeJSON()
+	return
+}
+
+// 计算请假时长
+func (c *LeaveController) Leave_Duration() {
+
+	T_start_time := c.GetString("T_start_time")
+	T_end_time := c.GetString("T_end_time")
+
+	startTime, is := lib.TimeStrToTime(T_start_time)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式不正确"}
+		c.ServeJSON()
+		return
+	}
+	endTime, is := lib.TimeStrToTime(T_end_time)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式不正确"}
+		c.ServeJSON()
+		return
+	}
+
+	//开始时间的小时和分钟
+	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_m := int((diff_day_hours+diff_hours)*60 + diff_minutes) // 分钟数量
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: diff_m}
+	c.ServeJSON()
+	return
+}

+ 1 - 0
go.mod

@@ -35,6 +35,7 @@ require (
 	github.com/prometheus/common v0.37.0 // indirect
 	github.com/prometheus/procfs v0.8.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
+	github.com/shopspring/decimal v1.3.1 // indirect
 	github.com/signintech/gopdf v0.16.1 // indirect
 	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
 	golang.org/x/crypto v0.5.0 // indirect

+ 2 - 0
go.sum

@@ -274,6 +274,8 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
+github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
+github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
 github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=

+ 1 - 4
main.go

@@ -5,7 +5,6 @@ import (
 	"ERP_ams/conf"
 	"ERP_ams/logs"
 	_ "ERP_ams/models/Account"
-	"ERP_ams/models/Attendance"
 	_ "ERP_ams/routers"
 	"fmt"
 	"github.com/beego/beego/v2/adapter/orm"
@@ -22,7 +21,7 @@ func init() {
 	orm.RegisterDriver("mysql", orm.DRMySQL)
 	//orm.RegisterDataBase("default", "mysql", "zdxq:7e5853d9178edfcc@tcp(47.108.133.234:3306)/zdxq?charset=utf8",100,200)
 	orm.RegisterDataBase("default", "mysql",
-		conf.MysqlServer_Username+":"+conf.MysqlServer_Password+"@tcp("+conf.MysqlServer_UrlPort+")/"+conf.MysqlServer_Database+"?charset=utf8mb4&loc=Local&parseTime=True",
+		conf.MysqlServer_Username+":"+conf.MysqlServer_Password+"@tcp("+conf.MysqlServer_UrlPort+")/"+conf.MysqlServer_Database+"?charset=utf8mb4&loc=Asia%2FShanghai&parseTime=True",
 		conf.MysqlServer_MaxIdleConnections, conf.MysqlServer_MaxOpenConnections)
 	orm.RunSyncdb("default", false, false) // 创建数据库
 }
@@ -55,8 +54,6 @@ func main() {
 	beego.BConfig.RecoverPanic = true
 	beego.BConfig.RecoverFunc = RecoverPanic
 
-	go Attendance.Read_AttendanceType_All() // 初始化请假类型
-
 	beego.Run()
 
 }

+ 3 - 0
models/Account/Menu.go

@@ -32,6 +32,9 @@ func init() {
 
 // 获取列表
 func Read_API_List_ByPower(T_power_id string, Menu_Bind string) (maps []menulibs.API) {
+	if len(Menu_Bind) == 0 {
+		return
+	}
 	o := orm.NewOrm()
 	APIDao := menulibs.NewAPI(o, RedisCache_API)
 	maps, err := APIDao.Read_API_List_ByPower(T_power_id, Menu_Bind)

+ 187 - 27
models/Attendance/Attendance.go

@@ -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
+}

+ 40 - 13
models/Attendance/AttendanceType.go

@@ -1,12 +1,20 @@
 package Attendance
 
+import "sort"
+
 const (
-	AttendanceOvertime  = iota // 0 加班
-	AttendanceSick             // 1 病假
-	AttendancePersonal         // 2 事假
-	AttendanceDaysOff          // 3 调休
-	AttendanceAnnual           // 4 年假
-	AttendanceShiftPerf        // 5 转绩效
+	AttendanceOvertime      = iota // 0 加班
+	AttendancePersonal             // 1 事假
+	AttendanceSick                 // 2 病假
+	AttendanceDaysOff              // 3 调休
+	AttendanceAnnual               // 4 年假
+	AttendanceShiftPerf            // 5 转绩效
+	AttendanceMarriage             // 婚假
+	AttendanceFuneral              // 丧假
+	AttendanceMaternity            // 产假
+	AttendanceBreastfeeding        // 哺乳假
+	Attendancepaternity            // 陪产假
+
 )
 
 // 请假类型
@@ -16,12 +24,17 @@ type AttendanceType struct {
 }
 
 var AttendanceType_list = map[int]string{
-	AttendanceOvertime:  "加班",
-	AttendanceSick:      "病假",
-	AttendancePersonal:  "事假",
-	AttendanceDaysOff:   "调休",
-	AttendanceAnnual:    "年假",
-	AttendanceShiftPerf: "转绩效",
+	AttendanceOvertime:      "加班",
+	AttendanceSick:          "病假",
+	AttendancePersonal:      "事假",
+	AttendanceDaysOff:       "调休",
+	AttendanceAnnual:        "年假",
+	AttendanceShiftPerf:     "转绩效",
+	AttendanceFuneral:       "丧假",
+	AttendanceMarriage:      "婚假",
+	AttendanceMaternity:     "产假",
+	AttendanceBreastfeeding: "哺乳假",
+	Attendancepaternity:     "陪产假",
 }
 
 // 获取全部
@@ -38,7 +51,7 @@ func Read_AttendanceType_Get(id int) string {
 func Read_AttendanceType_All() (r []AttendanceType) {
 
 	for k, v := range AttendanceType_list {
-		if k == AttendanceOvertime {
+		if k == AttendanceOvertime || k == AttendanceShiftPerf {
 			continue
 		}
 		r = append(r, AttendanceType{
@@ -46,5 +59,19 @@ func Read_AttendanceType_All() (r []AttendanceType) {
 			T_name: v,
 		})
 	}
+	sort.Slice(r, func(i, j int) bool {
+		return r[i].Id < r[j].Id
+	})
+	return r
+}
+
+func Get_LeaveType_List() (r []int) {
+
+	for k, _ := range AttendanceType_list {
+		if k == AttendanceOvertime || k == AttendanceShiftPerf {
+			continue
+		}
+		r = append(r, k)
+	}
 	return r
 }

+ 10 - 7
routers/Leave.go

@@ -7,13 +7,16 @@ import (
 
 func init() {
 	ns := beego.NewNamespace("/Leave",
-		beego.NSRouter("/List", &controllers.LeaveController{}, "*:Leave_List"),           // 请假列表
-		beego.NSRouter("/User_list", &controllers.LeaveController{}, "*:Leave_User_List"), // 获取请假
-		beego.NSRouter("/Add", &controllers.LeaveController{}, "*:Leave_Add"),             // 添加请假
-		beego.NSRouter("/Deduct", &controllers.LeaveController{}, "*:Leave_Deduct"),       // 扣除
-		beego.NSRouter("/Edit", &controllers.LeaveController{}, "*:Leave_Update"),         // 修改请假
-		beego.NSRouter("/Approval", &controllers.LeaveController{}, "*:Leave_Approval"),   // 请假审批
-		beego.NSRouter("/Del", &controllers.LeaveController{}, "*:Leave_Del"),             // 删除请假
+		beego.NSRouter("/List", &controllers.LeaveController{}, "*:Leave_List"),                 // 请假列表
+		beego.NSRouter("/User_list", &controllers.LeaveController{}, "*:Leave_User_List"),       // 获取请假
+		beego.NSRouter("/Finance_List", &controllers.LeaveController{}, "*:Leave_Finance_List"), // 财务列表
+		beego.NSRouter("/Add", &controllers.LeaveController{}, "*:Leave_Add"),                   // 添加请假
+		beego.NSRouter("/Deduct", &controllers.LeaveController{}, "*:Leave_Deduct"),             // 扣除
+		beego.NSRouter("/Edit", &controllers.LeaveController{}, "*:Leave_Update"),               // 修改请假
+		beego.NSRouter("/Approval", &controllers.LeaveController{}, "*:Leave_Approval"),         // 请假审批
+		beego.NSRouter("/Del", &controllers.LeaveController{}, "*:Leave_Del"),                   // 删除请假
+		beego.NSRouter("/DaysOff", &controllers.LeaveController{}, "*:Leave_RemainingDaysOff"),  // 剩余调休时长
+		beego.NSRouter("/Duration", &controllers.LeaveController{}, "*:Leave_Duration"),  // 剩余调休时长
 
 	)
 	// 请假类型

+ 2 - 2
routers/Overtime.go

@@ -7,8 +7,8 @@ import (
 
 func init() {
 	ns := beego.NewNamespace("/Overtime",
-		beego.NSRouter("/List", &controllers.OvertimeController{}, "*:Overtime_List"),           // 加班列表
-		beego.NSRouter("/User_list", &controllers.OvertimeController{}, "*:Overtime_User_List"), // 获取加班
+		beego.NSRouter("/List", &controllers.OvertimeController{}, "*:Overtime_List"),           // 管理员审核列表
+		beego.NSRouter("/User_list", &controllers.OvertimeController{}, "*:Overtime_User_List"), // 用户列表
 		beego.NSRouter("/Add", &controllers.OvertimeController{}, "*:Overtime_Add"),             // 添加加班
 		beego.NSRouter("/Edit", &controllers.OvertimeController{}, "*:Overtime_Update"),         // 修改加班
 		beego.NSRouter("/Approval", &controllers.OvertimeController{}, "*:Overtime_Approval"),   // 加班审批