staff
This commit is contained in:
parent
b6e5112bb6
commit
800eefcebe
|
@ -8,7 +8,7 @@ import (
|
|||
"enterprise/worker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
func main1() {
|
||||
config.LoadServerConfig()
|
||||
global.InitGlobal()
|
||||
|
||||
|
@ -19,6 +19,13 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
}
|
||||
func main() {
|
||||
config.LoadServerConfig()
|
||||
global.InitGlobal()
|
||||
//cfg := config.GetConfig()
|
||||
worker.SyncStaffSalary("")
|
||||
|
||||
}
|
||||
|
||||
func main2() {
|
||||
config.LoadServerConfig()
|
||||
|
|
|
@ -7,7 +7,8 @@ type StaffSalary struct {
|
|||
BaseSalary float64
|
||||
RealSalary float64
|
||||
SocialInsurence float64
|
||||
Holiday int
|
||||
PersonalTax float64
|
||||
Holiday float64
|
||||
CreateTime int64
|
||||
UpdateTime int64
|
||||
Extra string
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
butil "enterprise/base/util"
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/smbrave/goutil"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type Applyer struct {
|
||||
|
@ -25,6 +27,17 @@ type Selector struct {
|
|||
Options []*Option `json:"options"`
|
||||
}
|
||||
|
||||
type Vacation struct {
|
||||
Selector *Selector `json:"selector"`
|
||||
Attendance struct {
|
||||
DateRange struct {
|
||||
NewBegin int64 `json:"new_begin"`
|
||||
NewEnd int64 `json:"new_end"`
|
||||
NewDuration int64 `json:"new_duration"`
|
||||
Type string `json:"type"`
|
||||
} `json:"date_range"`
|
||||
} `json:"attendance"`
|
||||
}
|
||||
type ApplyValue struct {
|
||||
Text string `json:"text"`
|
||||
Selector *Selector `json:"selector"`
|
||||
|
@ -37,6 +50,7 @@ type ApplyValue struct {
|
|||
Files []struct {
|
||||
FileId string `json:"file_id"`
|
||||
} `json:"files"`
|
||||
Vacation *Vacation `json:"vacation"`
|
||||
}
|
||||
|
||||
type ApplyContent struct {
|
||||
|
@ -70,6 +84,39 @@ type QyWeixinApprove struct {
|
|||
QyWeixin
|
||||
}
|
||||
|
||||
func (d *ApproveDetail) GetValue(title string) string {
|
||||
|
||||
for _, content := range d.ApplyData.Contents {
|
||||
key := content.Title[0].Text
|
||||
if key != title {
|
||||
continue
|
||||
}
|
||||
|
||||
var value string
|
||||
if content.Control == "Selector" {
|
||||
value = content.Value.Selector.Options[0].Value[0].Text
|
||||
} else if content.Control == "Text" || content.Control == "Textarea" {
|
||||
value = content.Value.Text
|
||||
} else if content.Control == "Date" {
|
||||
value = content.Value.Date.Timestamp
|
||||
} else if content.Control == "Money" {
|
||||
value = content.Value.NewMoney
|
||||
} else if content.Control == "File" {
|
||||
value = content.Value.Files[0].FileId
|
||||
} else if content.Control == "Vacation" {
|
||||
tp := content.Value.Vacation.Selector.Options[0].Value[0].Text
|
||||
duration := cast.ToString(content.Value.Vacation.Attendance.DateRange.NewDuration)
|
||||
value = tp + "," + duration
|
||||
}
|
||||
return value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *ApproveDetail) GetUserid() string {
|
||||
return d.Applyer.Userid
|
||||
}
|
||||
|
||||
func NewQyWeixinApprove(corpId, secret, agent string) *QyWeixinApprove {
|
||||
return &QyWeixinApprove{
|
||||
QyWeixin: QyWeixin{
|
||||
|
@ -94,3 +141,35 @@ func (q *QyWeixinApprove) GetDetail(spNo string) (*ApproveDetail, error) {
|
|||
}
|
||||
return rsp.Info, nil
|
||||
}
|
||||
|
||||
func (q *QyWeixinApprove) GetList(start, end int64, templateId string) ([]string, error) {
|
||||
reqUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=%s", q.GetToken())
|
||||
reqParam := make(map[string]interface{})
|
||||
reqParam["starttime"] = cast.ToString(start)
|
||||
reqParam["endtime"] = cast.ToString(end)
|
||||
reqParam["new_cursor"] = ""
|
||||
reqParam["size"] = 100
|
||||
filters := make([]interface{}, 0)
|
||||
if templateId != "" {
|
||||
filters = append(filters, map[string]interface{}{
|
||||
"key": "template_id",
|
||||
"value": templateId,
|
||||
})
|
||||
}
|
||||
|
||||
filters = append(filters, map[string]interface{}{
|
||||
"key": "sp_status",
|
||||
"value": "2",
|
||||
})
|
||||
reqParam["filters"] = filters
|
||||
rspBody, err := butil.HttpPostJson(reqUrl, nil, []byte(goutil.EncodeJSON(reqParam)))
|
||||
if err != nil {
|
||||
log.Errorf("httpPost error :%s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
result, err := q.GetResult(rspBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cast.ToStringSlice(result["sp_no_list"]), nil
|
||||
}
|
||||
|
|
8
go.mod
8
go.mod
|
@ -4,18 +4,20 @@ go 1.18
|
|||
|
||||
require (
|
||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.0.56
|
||||
github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-co-op/gocron v1.31.0
|
||||
github.com/gogap/errors v0.0.0-20210818113853-edfbba0ddea9
|
||||
github.com/gomodule/redigo v1.8.1
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
|
||||
github.com/silenceper/wechat v1.2.6
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/smbrave/goutil v0.0.0-20230602040814-2643c72c2849
|
||||
github.com/spf13/cast v1.5.1
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/wechatpay-apiv3/wechatpay-go v0.2.17
|
||||
golang.org/x/crypto v0.9.0
|
||||
gorm.io/driver/mysql v1.5.1
|
||||
gorm.io/gorm v1.25.2
|
||||
)
|
||||
|
@ -23,13 +25,11 @@ require (
|
|||
require (
|
||||
github.com/ArtisanCloud/PowerLibs/v3 v3.0.12 // indirect
|
||||
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
@ -39,7 +39,6 @@ require (
|
|||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogap/stack v0.0.0-20150131034635-fef68dddd4f8 // indirect
|
||||
github.com/gomodule/redigo v1.8.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
|
@ -67,7 +66,6 @@ require (
|
|||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
|
|
|
@ -59,7 +59,11 @@ func SyncStaffInfo() {
|
|||
}
|
||||
}
|
||||
|
||||
func CalcStaffSalary(month string) {
|
||||
func 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)
|
||||
|
||||
|
@ -68,7 +72,11 @@ func CalcStaffSalary(month string) {
|
|||
log.Errorf("query staff db error :%s", err.Error())
|
||||
return
|
||||
}
|
||||
month = strings.ReplaceAll(month, "-", "")
|
||||
holidays, err := 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"))
|
||||
|
@ -94,9 +102,7 @@ func CalcStaffSalary(month string) {
|
|||
discount = 0.8
|
||||
}
|
||||
socialInsurence := cast.ToFloat64(config.Get(model.StaffSalarySocialInsurence))
|
||||
if endDate%100 > 15 { // 15号以后的员工不缴社保
|
||||
socialInsurence = 0
|
||||
}
|
||||
|
||||
extra := make(map[string]interface{})
|
||||
|
||||
salary.BaseSalary = cast.ToFloat64(staff.Salary)
|
||||
|
@ -116,6 +122,9 @@ func CalcStaffSalary(month string) {
|
|||
if officialDate/100 == startDate/100 {
|
||||
isOfficialMonth = true
|
||||
}
|
||||
if entryDate%100 > 15 && isEntryMonth { // 15号以后的员工不缴社保
|
||||
socialInsurence = 0
|
||||
}
|
||||
|
||||
if isEntryMonth {
|
||||
expDays = endDate - entryDate + 1
|
||||
|
@ -130,10 +139,11 @@ func CalcStaffSalary(month string) {
|
|||
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) - socialInsurence
|
||||
realSalary := expSalary*float64(expDays) + officalSalary*float64(officialDays) - holiday*officalSalary
|
||||
|
||||
extra["discount"] = discount
|
||||
extra["socialInsurence"] = socialInsurence
|
||||
|
@ -152,6 +162,7 @@ func CalcStaffSalary(month string) {
|
|||
|
||||
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)
|
||||
|
@ -164,3 +175,33 @@ func CalcStaffSalary(month string) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func 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, ",", 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
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ func Init() error {
|
|||
cron.Every(1).Day().At("03:00").Do(func() {
|
||||
go SyncStaffInfo()
|
||||
})
|
||||
|
||||
cron.Every(1).Month(1, 2, 3, 4, 5).At("02:00").Do(func() {
|
||||
go SyncStaffSalary("")
|
||||
})
|
||||
cron.StartAsync()
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue