2023-08-31 22:20:40 +08:00
|
|
|
package worker
|
|
|
|
|
|
|
|
import (
|
2023-09-01 20:01:30 +08:00
|
|
|
butil "enterprise/base/util"
|
2023-08-31 22:20:40 +08:00
|
|
|
"enterprise/common/config"
|
|
|
|
"enterprise/common/dao"
|
2023-10-08 21:22:49 +08:00
|
|
|
"enterprise/common/global"
|
2023-08-31 22:20:40 +08:00
|
|
|
"enterprise/common/model"
|
|
|
|
"enterprise/common/weixin"
|
2023-10-08 21:22:49 +08:00
|
|
|
"fmt"
|
2023-08-31 22:20:40 +08:00
|
|
|
log "github.com/sirupsen/logrus"
|
2023-09-01 20:01:30 +08:00
|
|
|
"github.com/smbrave/goutil"
|
2023-08-31 22:20:40 +08:00
|
|
|
"github.com/spf13/cast"
|
2023-09-01 20:01:30 +08:00
|
|
|
"strings"
|
|
|
|
"time"
|
2023-08-31 22:20:40 +08:00
|
|
|
)
|
|
|
|
|
2024-01-07 17:17:33 +08:00
|
|
|
type Staff struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Staff) SendStaffSalaryBill(month string) {
|
2023-10-08 21:22:49 +08:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-07 17:17:33 +08:00
|
|
|
func (s *Staff) SyncStaffInfo() {
|
2023-08-31 22:20:40 +08:00
|
|
|
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
|
2023-09-01 20:01:30 +08:00
|
|
|
staff.StaffType = staffInfo.StaffType
|
2023-08-31 22:20:40 +08:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-01 20:01:30 +08:00
|
|
|
|
2024-01-07 17:17:33 +08:00
|
|
|
func (s *Staff) SyncStaffSalary(month string) {
|
2023-09-04 19:14:02 +08:00
|
|
|
if month == "" {
|
|
|
|
month = time.Now().AddDate(0, -1, 0).Format("2006-01")
|
|
|
|
}
|
|
|
|
month = strings.ReplaceAll(month, "-", "")
|
2023-09-01 20:01:30 +08:00
|
|
|
//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
|
|
|
|
}
|
2024-01-07 17:17:33 +08:00
|
|
|
holidays, err := s.loadHoliday(month)
|
2023-09-04 19:14:02 +08:00
|
|
|
if err != nil {
|
|
|
|
log.Errorf("loadHoliday error :%s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2023-09-01 20:01:30 +08:00
|
|
|
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))
|
2023-09-04 19:14:02 +08:00
|
|
|
|
2023-09-01 20:01:30 +08:00
|
|
|
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
|
|
|
|
}
|
2023-09-04 19:14:02 +08:00
|
|
|
if entryDate%100 > 15 && isEntryMonth { // 15号以后的员工不缴社保
|
|
|
|
socialInsurence = 0
|
|
|
|
}
|
2023-09-01 20:01:30 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2023-09-04 19:14:02 +08:00
|
|
|
holiday := butil.FloatCut(holidays[staff.Username])
|
2023-09-01 20:01:30 +08:00
|
|
|
|
|
|
|
expSalary := cast.ToFloat64(staff.Salary) * discount / float64(endDate-startDate+1)
|
|
|
|
officalSalary := cast.ToFloat64(staff.Salary) / float64(endDate-startDate+1)
|
2023-09-04 19:14:02 +08:00
|
|
|
realSalary := expSalary*float64(expDays) + officalSalary*float64(officialDays) - holiday*officalSalary
|
2023-09-01 20:01:30 +08:00
|
|
|
|
|
|
|
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
|
2023-09-04 19:14:02 +08:00
|
|
|
salary.Holiday = holiday
|
2023-09-01 20:01:30 +08:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2023-09-04 19:14:02 +08:00
|
|
|
|
2024-01-07 17:17:33 +08:00
|
|
|
func (s *Staff) loadHoliday(month string) (map[string]float64, error) {
|
2023-09-04 19:14:02 +08:00
|
|
|
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, ",", 2)
|
|
|
|
hours := float64(cast.ToInt64(fields[1])) / float64(3600*8)
|
|
|
|
if v, ok := result[userId]; ok {
|
|
|
|
result[userId] = v + hours
|
|
|
|
} else {
|
|
|
|
result[userId] = hours
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|