package worker import ( butil "enterprise/base/util" "enterprise/common/config" "enterprise/common/dao" "enterprise/common/global" "enterprise/common/model" "enterprise/common/weixin" "fmt" log "github.com/sirupsen/logrus" "github.com/smbrave/goutil" "github.com/spf13/cast" "strings" "time" ) 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()) return } for _, staffSalary := range staffSalarys { if staffSalary.BaseSalary < 0.1 { continue } message := make([]string, 0) message = append(message, fmt.Sprintf("【工资单】[%s][%s]", staffSalary.Username, month)) message = append(message, fmt.Sprintf("基本工资:%.2f", staffSalary.BaseSalary)) message = append(message, fmt.Sprintf("出勤工资:%.2f", staffSalary.RealSalary)) if staffSalary.AwardSalary >= 0.1 { message = append(message, fmt.Sprintf("额外工资:%.2f", staffSalary.AwardSalary)) } message = append(message, fmt.Sprintf("社保扣除:%.2f", staffSalary.SocialInsurence)) message = append(message, fmt.Sprintf("个税扣除:%.2f", staffSalary.PersonalTax)) message = append(message, fmt.Sprintf("实发工资:%.2f", butil.FloatCut(staffSalary.RealSalary+staffSalary.AwardSalary-staffSalary.SocialInsurence-staffSalary.PersonalTax))) if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) } } } func (s *Staff) SyncStaffInfo() { cfg := config.GetConfig() hrAssiant := weixin.NewQyWeixinHR(cfg.QyWeixin.Corpid, cfg.QyWeixin.HrSecret, cfg.QyWeixin.HrSecret) userConfigs, err := dao.NewUserConfigDao().Query(model.UserConfigStatusNormal) if err != nil { log.Errorf("query staff db error :%s", err.Error()) return } for _, user := range userConfigs { staffInfo, err := hrAssiant.GetStaffInfo(user.Username) if err != nil { log.Errorf("getstaff info username[%s] error :%s", user.Username, err.Error()) continue } staff, err := dao.NewStaffInfoDao().GetByUsername(user.Username) if err != nil { log.Errorf("db error :%s", err.Error()) continue } if staff == nil { staff = new(model.StaffInfo) } staff.Username = staffInfo.UserName staff.Realname = staffInfo.RealName staff.Idno = staffInfo.Idno staff.StaffType = staffInfo.StaffType staff.Salary = cast.ToString(staffInfo.Salary) staff.EntryDate = staffInfo.EntryDate staff.OfficialDate = staffInfo.OfficialDate staff.BirthDate = staffInfo.BirthDate staff.BankName = staffInfo.BankName staff.BankCard = staffInfo.BankCard if staff.Id == 0 { _, err = dao.NewStaffInfoDao().Create(staff) } else { err = dao.NewStaffInfoDao().Update(staff) } if err != nil { log.Errorf("db error :%s", err.Error()) } } } func (s *Staff) SyncStaffSalary(month string) { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("2006-01") } month = strings.ReplaceAll(month, "-", "") //cfg := config.GetConfig() //hrAssiant := weixin.NewQyWeixinHR(cfg.QyWeixin.Corpid, cfg.QyWeixin.HrSecret, cfg.QyWeixin.HrSecret) staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal) if err != nil { log.Errorf("query staff db error :%s", err.Error()) return } holidays, err := s.loadHoliday(month) if err != nil { log.Errorf("loadHoliday error :%s", err.Error()) return } monthTime, _ := time.ParseInLocation("200601", month, time.Local) startDate := cast.ToInt(monthTime.Format("20060102")) endDate := cast.ToInt(monthTime.AddDate(0, 1, -1).Format("20060102")) salaryDao := dao.NewStaffSalaryDao() for _, staff := range staffs { salary, err := salaryDao.GetBy(staff.Username, month) if err != nil { log.Errorf("db error :%s", err.Error()) continue } if salary == nil { salary = new(model.StaffSalary) salary.Month = month salary.Username = staff.Username } config, err := dao.NewUserConfigDao().GetByUsername(staff.Username) if err != nil { log.Errorf("db error :%s", err.Error()) continue } discount := cast.ToFloat64(config.Get(model.StaffSalaryExpDiscount)) if discount == 0.0 { discount = 0.8 } socialInsurence := cast.ToFloat64(config.Get(model.StaffSalarySocialInsurence)) extra := make(map[string]interface{}) salary.BaseSalary = cast.ToFloat64(staff.Salary) salary.Holiday = 0 entryDate := cast.ToInt(strings.ReplaceAll(staff.EntryDate, "-", "")) officialDate := cast.ToInt(strings.ReplaceAll(staff.OfficialDate, "-", "")) isEntryMonth := false isOfficialMonth := false expDays := 0 officialDays := 0 if entryDate/100 == startDate/100 { isEntryMonth = true } if officialDate/100 == startDate/100 { isOfficialMonth = true } if entryDate%100 > 15 && isEntryMonth { // 15号以后的员工不缴社保 socialInsurence = 0 } if isEntryMonth { expDays = endDate - entryDate + 1 officialDays = 0 } else if isOfficialMonth { expDays = officialDate - startDate + 1 officialDays = endDate - officialDate } else if endDate < officialDate { expDays = endDate - startDate + 1 officialDays = 0 } else { officialDays = endDate - startDate + 1 expDays = 0 } holiday := butil.FloatCut(holidays[staff.Username]) expSalary := cast.ToFloat64(staff.Salary) * discount / float64(endDate-startDate+1) officalSalary := cast.ToFloat64(staff.Salary) / float64(endDate-startDate+1) realSalary := expSalary*float64(expDays) + officalSalary*float64(officialDays) - holiday*officalSalary extra["discount"] = discount extra["socialInsurence"] = socialInsurence extra["expDays"] = expDays extra["officialDays"] = officialDays extra["expSalary"] = butil.FloatCut(expSalary) extra["officalSalary"] = butil.FloatCut(officalSalary) extra["days"] = endDate - startDate + 1 extra["realDays"] = expDays + officialDays extra["startDate"] = startDate extra["endDate"] = endDate extra["officialDate"] = officialDate extra["entryDate"] = entryDate extra["isEntryMonth"] = isEntryMonth extra["isOfficialMonth"] = isOfficialMonth salary.RealSalary = butil.FloatCut(realSalary) salary.SocialInsurence = socialInsurence salary.Holiday = holiday salary.Extra = goutil.EncodeJSONIndent(extra) if salary.Id == 0 { _, err = dao.NewStaffSalaryDao().Create(salary) } else { err = dao.NewStaffSalaryDao().Update(salary) } if err != nil { log.Errorf("db error :%s", err.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) endTime := startTime.AddDate(0, 1, 0) spNos, err := approve.GetList(startTime.Unix(), endTime.Unix()-1, "3WLJF6naF5jhnXvwisuPmE85wVMYcy1S1ZvYibkw") if err != nil { log.Errorf("approve getlist error :%s", err.Error()) return nil, err } result := make(map[string]float64) for _, spNo := range spNos { detail, err := approve.GetDetail(spNo) if err != nil { log.Errorf("approve GetDetail error :%s", err.Error()) return nil, err } userId := detail.GetUserid() holidayType := detail.GetValue("请假类型") fields := strings.SplitN(holidayType, ",", 4) hours := float64(cast.ToInt64(fields[3])) / float64(3600*8) if v, ok := result[userId]; ok { result[userId] = v + hours } else { result[userId] = hours } } return result, nil }