From a868f820bbfe337b328d6c8919766a3f6c35905e Mon Sep 17 00:00:00 2001 From: jiangyong Date: Sun, 7 Jan 2024 17:17:33 +0800 Subject: [PATCH] checkin --- cmd/enterprise.go | 21 +---- common/model/checkin.go | 1 + common/weixin/qyweixin_checkin.go | 87 ++++++++++++-------- conf/server.conf.mac | 5 +- server/controller/staff.go | 4 +- worker/checkin.go | 130 +++++++++++++++++------------- worker/staff.go | 13 +-- worker/worker.go | 28 +++---- 8 files changed, 155 insertions(+), 134 deletions(-) diff --git a/cmd/enterprise.go b/cmd/enterprise.go index 6b0e823..111fc07 100644 --- a/cmd/enterprise.go +++ b/cmd/enterprise.go @@ -3,7 +3,6 @@ package main import ( "enterprise/common/config" "enterprise/common/global" - "enterprise/common/weixin" "enterprise/server" "enterprise/worker" ) @@ -20,25 +19,9 @@ func main() { panic(err) } } -func main3() { - config.LoadServerConfig() - global.InitGlobal() - //cfg := config.GetConfig() - worker.SyncStaffInfo() - worker.SyncStaffSalary("") - -} func main2() { config.LoadServerConfig() - //global.InitGlobal() - - pay := weixin.NewQyPay() - if err := pay.PayRedMoney(&weixin.RedMoneyReq{ - TotalAmount: 200, - Title: "加班补贴", - Userid: "jiangyong", - }); err != nil { - panic(err) - } + global.InitGlobal() + //cfg := config.GetConfig() } diff --git a/common/model/checkin.go b/common/model/checkin.go index 31c8e04..3e3752a 100644 --- a/common/model/checkin.go +++ b/common/model/checkin.go @@ -4,6 +4,7 @@ type Checkin struct { Id int64 Username string Day string + Month string Exception string Rawdata string StartTime int64 diff --git a/common/weixin/qyweixin_checkin.go b/common/weixin/qyweixin_checkin.go index f900706..de4b14d 100644 --- a/common/weixin/qyweixin_checkin.go +++ b/common/weixin/qyweixin_checkin.go @@ -9,12 +9,12 @@ import ( "github.com/smbrave/goutil" "github.com/spf13/cast" "gorm.io/gorm/utils" - "math" - "strings" "time" ) type UserCheckIn struct { + Day string + Month string UserId string Exception string Rawdata string @@ -22,6 +22,11 @@ type UserCheckIn struct { EndTime int64 } +func (u *UserCheckIn) String() string { + return fmt.Sprintf("[%s][%s][%s~%s][%s]", u.UserId, u.Day, + goutil.TimeToDateTime(u.StartTime), goutil.TimeToDateTime(u.EndTime), u.Exception) +} + type QyWeixinCheckin struct { QyWeixin } @@ -56,7 +61,7 @@ func (q *QyWeixinCheckin) GetCheckinEmployee(groupIds []string) ([]string, error groups := cast.ToSlice(result["group"]) for _, group := range groups { g := cast.ToStringMap(group) - if !utils.Contains(groupIds, cast.ToString(g["groupid"])) { + if len(groupIds) != 0 && !utils.Contains(groupIds, cast.ToString(g["groupid"])) { continue } ranges := cast.ToStringMap(g["range"]) @@ -66,15 +71,16 @@ func (q *QyWeixinCheckin) GetCheckinEmployee(groupIds []string) ([]string, error return resultUser, nil } -func (q *QyWeixinCheckin) GetCheckinData(day, userId string) (*UserCheckIn, error) { +func (q *QyWeixinCheckin) GetCheckinData(startDay, endDay string, userIds []string) ([]*UserCheckIn, error) { - dayTime, _ := time.ParseInLocation("2006-01-02", day, time.Local) + dayTime, _ := time.ParseInLocation("2006-01-02", startDay, time.Local) + endTime, _ := time.ParseInLocation("2006-01-02", endDay, time.Local) reqData := make(map[string]interface{}) reqData["opencheckindatatype"] = 1 reqData["starttime"] = dayTime.Unix() - reqData["endtime"] = dayTime.Unix() + 86400 - reqData["useridlist"] = []string{userId} + reqData["endtime"] = endTime.Unix() + 86400 + reqData["useridlist"] = userIds reqUrl := fmt.Sprintf("%s?access_token=%s", urlGetCheckinData, q.GetToken()) rspBody, err := butil.HttpPostJson(reqUrl, nil, []byte(goutil.EncodeJSON(reqData))) if err != nil { @@ -90,39 +96,50 @@ func (q *QyWeixinCheckin) GetCheckinData(day, userId string) (*UserCheckIn, erro return nil, errors.New(string(rspBody)) } - checkindatas := cast.ToSlice(result["checkindata"]) - userData := new(UserCheckIn) - userData.UserId = userId - exception := make([]string, 0) - isException := false - startTime := int64(math.MaxInt64) - endTime := int64(0) - for _, checkdata := range checkindatas { - c := cast.ToStringMap(checkdata) + datas := cast.ToSlice(result["checkindata"]) + checkData := make(map[string]*UserCheckIn) + for _, dat := range datas { + c := cast.ToStringMap(dat) exceptionType := cast.ToString(c["exception_type"]) + checkinType := cast.ToString(c["checkin_type"]) + userid := cast.ToString(c["userid"]) checkinTime := cast.ToInt64(c["checkin_time"]) + schCheckinTime := cast.ToInt64(c["sch_checkin_time"]) + if schCheckinTime == 0 { + schCheckinTime = checkinTime + } + checkDay := time.Unix(schCheckinTime, 0).Format("2006-01-02") + checkMonth := time.Unix(schCheckinTime, 0).Format("200601") + key := fmt.Sprintf("%s_%s", userid, checkDay) + var userData *UserCheckIn = nil + var ok bool + if userData, ok = checkData[key]; !ok { + userData = new(UserCheckIn) + userData.UserId = userid + userData.Day = checkDay + userData.Month = checkMonth + checkData[key] = userData + } if exceptionType != "" { - isException = true + userData.Exception += goutil.If(userData.Exception != "", ",", "") + userData.Exception += checkinType + ":" + exceptionType } + userData.Rawdata = goutil.If(userData.Rawdata == "", "", "\n") + goutil.EncodeJSON(dat) + if checkinType == "上班打卡" { + userData.StartTime = goutil.If(userData.StartTime == 0 || checkinTime < userData.StartTime, checkinTime, userData.StartTime) + } else if checkinType == "下班打卡" { + userData.EndTime = goutil.If(checkinTime > userData.EndTime, checkinTime, userData.EndTime) + } else { + log.Errorf("不支持的打卡类型:%s %s", checkinType, goutil.EncodeJSON(dat)) + } + } - exception = append(exception, exceptionType) - if checkinTime < startTime { - startTime = checkinTime - } - if checkinTime > endTime { - endTime = checkinTime + userDatas := make([]*UserCheckIn, 0) + for _, v := range checkData { + if v.StartTime > v.EndTime { + log.Errorf("user[%s][%s] checkin time error[%s~%s]", v.UserId, v.Day, goutil.TimeToDateTime(v.StartTime), goutil.TimeToDateTime(v.EndTime)) } + userDatas = append(userDatas, v) } - if startTime != int64(math.MaxInt64) { - userData.StartTime = startTime - } - userData.EndTime = endTime - userData.Rawdata = goutil.EncodeJSON(checkindatas) - if isException { - userData.Exception = strings.Join(exception, ",") - } - if userData.EndTime == 0 && userData.StartTime == 0 { - return nil, nil - } - return userData, nil + return userDatas, nil } diff --git a/conf/server.conf.mac b/conf/server.conf.mac index 25c6fea..0bce6d8 100644 --- a/conf/server.conf.mac +++ b/conf/server.conf.mac @@ -4,8 +4,8 @@ address = "0.0.0.0:9283" log_level = 6 [mysql] -host = "100.100.199.74" -port = 3307 +host = "14.22.113.49" +port = 9305 user = "root" pass = "ZW5aaGVuMIIBIj" db = "enterprise" @@ -27,6 +27,7 @@ checkin_agent = "3010011" checkin_secret = "6ljYNGt4DonZLmr9SCtgkTlOvtqmsOchBrTWwGl_GpU" checkin_group = "1,2" checkin_pay_thresold = 11 +checkin_onduty_pay_day = "" pay_secret = "JCGsxntR4E7wrEEQvWGr8_wdKtRlw48n-W6zd8lbwc4" pay_agent = "3010046" diff --git a/server/controller/staff.go b/server/controller/staff.go index fa8255b..a507460 100644 --- a/server/controller/staff.go +++ b/server/controller/staff.go @@ -35,11 +35,11 @@ func (s *Staff) Salary(ctx *gin.Context) { } func (s *Staff) SyncStaffInfo(ctx *gin.Context) { - go worker.SyncStaffInfo() + go new(worker.Staff).SyncStaffInfo() ctx.JSON(http.StatusOK, session.NewRspOk()) } func (s *Staff) SyncStaffSalary(ctx *gin.Context) { - go worker.SyncStaffSalary("") + go new(worker.Staff).SyncStaffSalary("") ctx.JSON(http.StatusOK, session.NewRspOk()) } diff --git a/worker/checkin.go b/worker/checkin.go index 535ef16..7f10f43 100644 --- a/worker/checkin.go +++ b/worker/checkin.go @@ -6,71 +6,91 @@ import ( "enterprise/common/model" "enterprise/common/weixin" log "github.com/sirupsen/logrus" - "strings" + "github.com/smbrave/goutil" "time" ) -func SyncCheckin(day string) error { +type CheckIn struct { +} + +func (c *CheckIn) SyncCheckinMonth(month string) error { + if month == "" { + month = time.Now().AddDate(0, -1, 0).Format("200601") + } cfg := config.GetConfig() + + startTime, _ := time.ParseInLocation("20060102", month+"01", time.Local) + endDay := startTime.AddDate(0, 1, -1).Format("2006-01-02") + startDay := startTime.Format("2006-01-02") + qyw := weixin.NewQyWeixinCheckin(cfg.QyWeixin.Corpid, cfg.QyWeixin.CheckinSecret, cfg.QyWeixin.CheckinAgent) - users, err := qyw.GetCheckinEmployee(strings.Split(cfg.QyWeixin.CheckinGroup, ",")) + users, err := qyw.GetCheckinEmployee(nil) if err != nil { + log.Errorf("GetCheckinEmployee error :%s", err.Error()) return err } - checkinDao := dao.NewCheckinDao() - for _, user := range users { - isNew := false - isUpdate := false - checkin, err := checkinDao.GetByDay(user, day) - if err != nil { - log.Errorf("db error :%s", err.Error()) - continue - } - if checkin == nil { - checkin = new(model.Checkin) - checkin.Day = day - checkin.Username = user - isNew = true - } + userDatas, err := qyw.GetCheckinData(startDay, endDay, users) + if err != nil { + log.Errorf("GetCheckinData[%s-%s]%s error :%s", startDay, endDay, goutil.EncodeJSON(users), err.Error()) + return err + } + for _, user := range userDatas { + c.saveToDB(user) + } + return nil +} +func (c *CheckIn) SyncCheckinDay(day string) { + cfg := config.GetConfig() + qyw := weixin.NewQyWeixinCheckin(cfg.QyWeixin.Corpid, cfg.QyWeixin.CheckinSecret, cfg.QyWeixin.CheckinAgent) + if day == "" { + day = time.Now().AddDate(0, 0, -1).Format("2006-01-02") + } + users, err := qyw.GetCheckinEmployee(nil) + if err != nil { + log.Errorf("GetCheckinEmployee error :%s", err.Error()) + return + } - realCheckin, err := qyw.GetCheckinData(day, user) - if err != nil { - log.Errorf("qyweixin get checkin error :%s", err.Error()) - continue - } - if realCheckin == nil { - continue - } - if realCheckin.StartTime != 0 && realCheckin.StartTime != checkin.StartTime { - isUpdate = true - checkin.StartTime = realCheckin.StartTime - } - if realCheckin.EndTime != 0 && realCheckin.EndTime != checkin.EndTime { - isUpdate = true - checkin.EndTime = realCheckin.EndTime - } - if realCheckin.Exception != "" && realCheckin.Exception != checkin.Exception { - checkin.Exception = realCheckin.Exception - isUpdate = true - } - checkin.Rawdata = realCheckin.Rawdata - if isNew { - _, err = checkinDao.Create(checkin) - } else { - err = checkinDao.Update(checkin) - } - if err != nil { - log.Errorf("db error :%s", err.Error()) - continue - } - if isNew { - go NotifyCheckinOnDuty(checkin) - } - if isUpdate { - go NotifyCheckinOffDuty(checkin) - } - time.Sleep(300 * time.Second) + userDatas, err := qyw.GetCheckinData(day, day, users) + if err != nil { + log.Errorf("GetCheckinData[%s-%s]%s error :%s", day, day, goutil.EncodeJSON(users), err.Error()) + return + } + + for _, user := range userDatas { + c.saveToDB(user) + } + return +} +func (c *CheckIn) saveToDB(user *weixin.UserCheckIn) error { + checkin, err := dao.NewCheckinDao().GetByDay(user.UserId, user.Day) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return err + } + isNew := false + if checkin == nil { + checkin = new(model.Checkin) + checkin.Day = user.Day + checkin.Month = user.Month + checkin.Username = user.UserId + isNew = true + } else { + checkin.Exception = user.Exception + checkin.StartTime = user.StartTime + checkin.EndTime = user.EndTime + checkin.Month = user.Month + } + + if isNew { + _, err = dao.NewCheckinDao().Create(checkin) + } else { + err = dao.NewCheckinDao().Update(checkin) + } + if err != nil { + log.Errorf("create/update db error :%s", err.Error()) + return err } return nil diff --git a/worker/staff.go b/worker/staff.go index a11c6b4..6868f82 100644 --- a/worker/staff.go +++ b/worker/staff.go @@ -15,7 +15,10 @@ import ( "time" ) -func SendStaffSalaryBill(month string) { +type Staff struct { +} + +func (s *Staff) SendStaffSalaryBill(month string) { staffSalarys, err := dao.NewStaffSalaryDao().Query(month) if err != nil { log.Errorf("db error :%s", err.Error()) @@ -42,7 +45,7 @@ func SendStaffSalaryBill(month string) { } } -func SyncStaffInfo() { +func (s *Staff) SyncStaffInfo() { cfg := config.GetConfig() hrAssiant := weixin.NewQyWeixinHR(cfg.QyWeixin.Corpid, cfg.QyWeixin.HrSecret, cfg.QyWeixin.HrSecret) @@ -88,7 +91,7 @@ func SyncStaffInfo() { } } -func SyncStaffSalary(month string) { +func (s *Staff) SyncStaffSalary(month string) { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("2006-01") } @@ -101,7 +104,7 @@ func SyncStaffSalary(month string) { log.Errorf("query staff db error :%s", err.Error()) return } - holidays, err := loadHoliday(month) + holidays, err := s.loadHoliday(month) if err != nil { log.Errorf("loadHoliday error :%s", err.Error()) return @@ -205,7 +208,7 @@ func SyncStaffSalary(month string) { } -func loadHoliday(month string) (map[string]float64, error) { +func (s *Staff) loadHoliday(month string) (map[string]float64, error) { cfg := config.GetConfig().QyWeixin approve := weixin.NewQyWeixinApprove(cfg.Corpid, cfg.ApproveSecret, cfg.ApproveAgent) startTime, _ := time.ParseInLocation("200601", month, time.Local) diff --git a/worker/worker.go b/worker/worker.go index 1317c24..f32856f 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -5,34 +5,30 @@ import ( "time" ) -func Init1() error { - - for i := 0; i < 120; i++ { - day := time.Now().AddDate(0, 0, -1-i).Format("2006-01-02") - SyncCheckin(day) - } - return nil -} func Init() error { timezone, _ := time.LoadLocation("Asia/Shanghai") cron := gocron.NewScheduler(timezone) - cron.Every(1).Hour().Do(func() { - go SyncCheckin(time.Now().Format("2006-01-02")) - }) + staff := new(Staff) + checkIn := new(CheckIn) // 每天同步企业人事信息 cron.Every(1).Day().At("01:00").Do(func() { - go SyncStaffInfo() + go staff.SyncStaffInfo() + }) + + //同步每日考勤数据 + cron.Every(1).Day().At("04:00").Do(func() { + go checkIn.SyncCheckinDay("") }) // 1-10号计算工资信息 - cron.Every(1).Month(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).At("02:00").Do(func() { - go SyncStaffSalary("") + cron.Every(1).Month(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).At("04:30").Do(func() { + go staff.SyncStaffSalary("") }) //10号晚上8点发送工资单 - cron.Every(1).Month(10).At("22:00").Do(func() { - go SendStaffSalaryBill(time.Now().AddDate(0, -1, 0).Format("200601")) + cron.Every(1).Month(10).At("20:00").Do(func() { + go staff.SendStaffSalaryBill(time.Now().AddDate(0, -1, 0).Format("200601")) }) cron.StartAsync() return nil