From e533de5422bcf7ef47b1c8011b24e62eb24c5a7d Mon Sep 17 00:00:00 2001 From: jiangyong27 Date: Tue, 4 Mar 2025 23:14:09 +0800 Subject: [PATCH 1/2] new salary --- cmd/enterprise.go | 3 +- common/dao/approval_checkin.go | 3 +- common/dao/approval_vacation.go | 6 +- common/dao/checkin.go | 9 +- common/dao/staff_config.go | 85 ----- common/dao/staff_info.go | 84 ----- common/dao/staff_salary.go | 17 +- common/dao/staff_user.go | 102 ++++++ common/dao/unify_kct_summary.go | 41 +++ common/model/checkin.go | 1 + common/model/corp.go | 3 + common/model/staff_config.go | 41 --- common/model/staff_info.go | 26 -- common/model/staff_salary.go | 70 ++-- common/model/staff_user.go | 63 ++++ .../model/{unify_ad_data.go => unify_data.go} | 13 + common/registry/salary.go | 35 ++ server/controller/staff.go | 6 +- server/service/qyweixin_approve.go | 19 +- server/service/staff_salary.go | 196 ++++------- service/salary_calculator/init.go | 8 + .../salary_calculator_1000.go | 89 +++++ .../salary_calculator_1000_wujiefeng.go | 60 ++++ service/staff.go | 320 ------------------ service/staff_salary.go | 220 ++++++++++++ worker/approval.go | 16 +- worker/checkin.go | 42 ++- worker/staff.go | 148 +++----- worker/worker.go | 36 +- 29 files changed, 874 insertions(+), 888 deletions(-) delete mode 100644 common/dao/staff_config.go delete mode 100644 common/dao/staff_info.go create mode 100644 common/dao/staff_user.go create mode 100644 common/dao/unify_kct_summary.go delete mode 100644 common/model/staff_config.go delete mode 100644 common/model/staff_info.go create mode 100644 common/model/staff_user.go rename common/model/{unify_ad_data.go => unify_data.go} (78%) create mode 100644 common/registry/salary.go create mode 100644 service/salary_calculator/init.go create mode 100644 service/salary_calculator/salary_calculator_1000.go create mode 100644 service/salary_calculator/salary_calculator_1000_wujiefeng.go delete mode 100644 service/staff.go create mode 100644 service/staff_salary.go diff --git a/cmd/enterprise.go b/cmd/enterprise.go index db06fbf..758fb1a 100644 --- a/cmd/enterprise.go +++ b/cmd/enterprise.go @@ -4,6 +4,7 @@ import ( "enterprise/common/config" "enterprise/common/global" "enterprise/server" + _ "enterprise/service/salary_calculator" "enterprise/worker" ) @@ -12,7 +13,7 @@ func main() { config.LoadAliPay() global.InitGlobal() - if err := worker.Init(); err != nil { + if err := worker.InitCorp(1000); err != nil { panic(err) } diff --git a/common/dao/approval_checkin.go b/common/dao/approval_checkin.go index b0fc3b1..d359466 100644 --- a/common/dao/approval_checkin.go +++ b/common/dao/approval_checkin.go @@ -78,11 +78,12 @@ func (d *ApprovalCheckinDao) GetByUsernameMonth(username, month string) ([]*mode return u, nil } -func (d *ApprovalCheckinDao) GetByUsernameDay(username, day string) (*model.ApprovalCheckin, error) { +func (d *ApprovalCheckinDao) GetByUsernameDay(corpId int64, username, day string) (*model.ApprovalCheckin, error) { var u model.ApprovalCheckin tx := GetDB().Table(d.TableName()) tx = tx.Where("checkin_date = ?", day) tx = tx.Where("username = ?", username) + tx = tx.Where("corp_id = ?", corpId) res := tx.First(&u) if res.Error == gorm.ErrRecordNotFound { diff --git a/common/dao/approval_vacation.go b/common/dao/approval_vacation.go index 8f3648a..daa3456 100644 --- a/common/dao/approval_vacation.go +++ b/common/dao/approval_vacation.go @@ -66,9 +66,10 @@ func (d *ApprovalVacationDao) GetBySpNo(corpId int64, spNo string) (*model.Appro return &u, nil } -func (d *ApprovalVacationDao) GetByUsername(username, month, day string) ([]*model.ApprovalVacation, error) { +func (d *ApprovalVacationDao) GetByUsername(corpId int64, username, month, day string) ([]*model.ApprovalVacation, error) { var u []*model.ApprovalVacation tx := GetDB().Table(d.TableName()) + tx.Where("corp_id = ?", corpId) if month != "" { tx = tx.Where("month = ?", month) } @@ -83,9 +84,10 @@ func (d *ApprovalVacationDao) GetByUsername(username, month, day string) ([]*mod return u, nil } -func (d *ApprovalVacationDao) GetByUsernameDay(username, day string) (*model.ApprovalVacation, error) { +func (d *ApprovalVacationDao) GetByUsernameDay(corpId int64, username, day string) (*model.ApprovalVacation, error) { var u model.ApprovalVacation tx := GetDB().Table(d.TableName()) + tx = tx.Where("corp_id = ?", corpId) tx = tx.Where("vacation_date = ?", day) tx = tx.Where("username = ?", username) diff --git a/common/dao/checkin.go b/common/dao/checkin.go index f7c3c49..69aa39a 100644 --- a/common/dao/checkin.go +++ b/common/dao/checkin.go @@ -66,9 +66,10 @@ func (d *CheckinDao) GetByDay(userId, day string) (*model.Checkin, error) { return &u, nil } -func (d *CheckinDao) CountUsername(month string) ([]*model.UsernameCount, error) { +func (d *CheckinDao) CountUsername(corpId int64, month string) ([]*model.UsernameCount, error) { var userCount []*model.UsernameCount tx := GetDB().Table(d.TableName()) + tx = tx.Where("corp_id = ?", corpId) tx = tx.Where("month = ?", month) tx.Select("username,COUNT(1) AS count") tx.Group("username") @@ -80,8 +81,9 @@ func (d *CheckinDao) CountUsername(month string) ([]*model.UsernameCount, error) return userCount, nil } -func (d *CheckinDao) Query(username, month string, filterException bool) ([]*model.Checkin, error) { +func (d *CheckinDao) Query(corpId int64, username, month string, filterException bool) ([]*model.Checkin, error) { tx := GetDB().Table(d.TableName()) + tx = tx.Where("corp_id = ?", corpId) tx = tx.Where("month = ?", month) tx = tx.Where("username = ?", username) if filterException { @@ -96,9 +98,10 @@ func (d *CheckinDao) Query(username, month string, filterException bool) ([]*mod return u, nil } -func (d *CheckinDao) QueryDay(day string) ([]*model.Checkin, error) { +func (d *CheckinDao) QueryDay(corpId int64, day string) ([]*model.Checkin, error) { tx := GetDB().Table(d.TableName()) tx = tx.Where("day = ?", day) + tx.Where("corp_id = ?", corpId) var u []*model.Checkin tx = tx.Find(&u) diff --git a/common/dao/staff_config.go b/common/dao/staff_config.go deleted file mode 100644 index 95a99db..0000000 --- a/common/dao/staff_config.go +++ /dev/null @@ -1,85 +0,0 @@ -package dao - -import ( - "enterprise/common/model" - "gorm.io/gorm" - "time" -) - -type UserConfigDao struct { -} - -func NewUserConfigDao() *UserConfigDao { - return &UserConfigDao{} -} - -func (d *UserConfigDao) TableName() string { - return "staff_config" -} - -func (d *UserConfigDao) Create(o *model.StaffConfig) (int64, error) { - o.CreateTime = time.Now().Unix() - res := GetDB().Table(d.TableName()).Create(o) - return o.Id, res.Error -} - -func (d *UserConfigDao) Update(o *model.StaffConfig) error { - o.UpdateTime = time.Now().Unix() - tx := GetDB().Table(d.TableName()) - res := tx.Save(o) - return res.Error -} - -func (d *UserConfigDao) Delete(id int64) error { - res := GetDB().Table(d.TableName()).Delete(&model.StaffConfig{}, id) - return res.Error -} - -func (d *UserConfigDao) Get(id int64) (*model.StaffConfig, error) { - var u model.StaffConfig - tx := GetDB().Table(d.TableName()) - tx = tx.Where("id = ?", id) - res := tx.First(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return &u, nil -} - -func (d *UserConfigDao) GetByUsername(username string) (*model.StaffConfig, error) { - var u model.StaffConfig - tx := GetDB().Table(d.TableName()) - tx = tx.Where("username = ?", username) - res := tx.First(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return &u, nil -} - -func (d *UserConfigDao) Query(status int) ([]*model.StaffConfig, error) { - var u []*model.StaffConfig - tx := GetDB().Table(d.TableName()) - - if status != 0 { - tx = tx.Where("status = ?", status) - } - - res := tx.Find(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return u, nil -} diff --git a/common/dao/staff_info.go b/common/dao/staff_info.go deleted file mode 100644 index ffab4b5..0000000 --- a/common/dao/staff_info.go +++ /dev/null @@ -1,84 +0,0 @@ -package dao - -import ( - "enterprise/common/model" - "gorm.io/gorm" - "time" -) - -type StaffInfoDao struct { -} - -func NewStaffInfoDao() *StaffInfoDao { - return &StaffInfoDao{} -} - -func (d *StaffInfoDao) TableName() string { - return "staff_info" -} - -func (d *StaffInfoDao) Create(o *model.StaffInfo) (int64, error) { - o.CreateTime = time.Now().Unix() - res := GetDB().Table(d.TableName()).Create(o) - return o.Id, res.Error -} - -func (d *StaffInfoDao) Update(o *model.StaffInfo) error { - o.UpdateTime = time.Now().Unix() - tx := GetDB().Table(d.TableName()) - res := tx.Save(o) - return res.Error -} - -func (d *StaffInfoDao) Delete(id int64) error { - res := GetDB().Table(d.TableName()).Delete(&model.StaffInfo{}, id) - return res.Error -} - -func (d *StaffInfoDao) Get(id int64) (*model.StaffInfo, error) { - var u model.StaffInfo - tx := GetDB().Table(d.TableName()) - tx = tx.Where("id = ?", id) - res := tx.First(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return &u, nil -} - -func (d *StaffInfoDao) GetByUsername(username string) (*model.StaffInfo, error) { - var u model.StaffInfo - tx := GetDB().Table(d.TableName()) - tx = tx.Where("username = ?", username) - res := tx.First(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return &u, nil -} - -func (d *StaffInfoDao) Query(status int) ([]*model.StaffInfo, error) { - var u []*model.StaffInfo - tx := GetDB().Table(d.TableName()) - if status != 0 { - tx = tx.Where("status = ?", status) - } - - res := tx.Find(&u) - if res.Error == gorm.ErrRecordNotFound { - return nil, nil - } - - if res.Error != nil { - return nil, res.Error - } - return u, nil -} diff --git a/common/dao/staff_salary.go b/common/dao/staff_salary.go index 3d7c802..eb5ad4c 100644 --- a/common/dao/staff_salary.go +++ b/common/dao/staff_salary.go @@ -50,10 +50,11 @@ func (d *StaffSalaryDao) Get(id int64) (*model.StaffSalary, error) { return &u, nil } -func (d *StaffSalaryDao) GetBy(username, month string) (*model.StaffSalary, error) { +func (d *StaffSalaryDao) GetBy(corpId, userId int64, month string) (*model.StaffSalary, error) { var u model.StaffSalary tx := GetDB().Table(d.TableName()) - tx = tx.Where("username = ?", username) + tx = tx.Where("corp_id = ?", corpId) + tx = tx.Where("user_id = ?", userId) tx = tx.Where("month = ?", month) res := tx.First(&u) if res.Error == gorm.ErrRecordNotFound { @@ -66,17 +67,17 @@ func (d *StaffSalaryDao) GetBy(username, month string) (*model.StaffSalary, erro return &u, nil } -func (d *StaffSalaryDao) Query(month, username string, master *string) ([]*model.StaffSalary, error) { +func (d *StaffSalaryDao) Query(corpId, userId int64, month string) ([]*model.StaffSalary, error) { var u []*model.StaffSalary tx := GetDB().Table(d.TableName()) + + tx.Where("corp_id = ?", corpId) + if month != "" { tx = tx.Where("month = ?", month) } - if username != "" { - tx.Where("username = ?", username) - } - if master != nil { - tx.Where("master = ?", *master) + if userId != 0 { + tx.Where("user_id = ?", userId) } tx.Order("month DESC") diff --git a/common/dao/staff_user.go b/common/dao/staff_user.go new file mode 100644 index 0000000..42a570c --- /dev/null +++ b/common/dao/staff_user.go @@ -0,0 +1,102 @@ +package dao + +import ( + "enterprise/common/model" + "gorm.io/gorm" + "time" +) + +type StaffUserDao struct { +} + +func NewStaffUserDao() *StaffUserDao { + return &StaffUserDao{} +} + +func (d *StaffUserDao) TableName() string { + return "staff_user" +} + +func (d *StaffUserDao) Create(o *model.StaffUser) (int64, error) { + o.CreateTime = time.Now().Unix() + res := GetDB().Table(d.TableName()).Create(o) + return o.Id, res.Error +} + +func (d *StaffUserDao) Update(o *model.StaffUser) error { + o.UpdateTime = time.Now().Unix() + tx := GetDB().Table(d.TableName()) + res := tx.Save(o) + return res.Error +} + +func (d *StaffUserDao) Delete(id int64) error { + res := GetDB().Table(d.TableName()).Delete(&model.StaffUser{}, id) + return res.Error +} + +func (d *StaffUserDao) Get(id int64) (*model.StaffUser, error) { + var u model.StaffUser + tx := GetDB().Table(d.TableName()) + tx = tx.Where("id = ?", id) + res := tx.First(&u) + if res.Error == gorm.ErrRecordNotFound { + return nil, nil + } + + if res.Error != nil { + return nil, res.Error + } + return &u, nil +} + +func (d *StaffUserDao) GetByUsername(corpId int64, username string) (*model.StaffUser, error) { + var u model.StaffUser + tx := GetDB().Table(d.TableName()) + tx.Where("corp_id = ?", corpId) + tx = tx.Where("username = ?", username) + res := tx.First(&u) + if res.Error == gorm.ErrRecordNotFound { + return nil, nil + } + + if res.Error != nil { + return nil, res.Error + } + return &u, nil +} + +func (d *StaffUserDao) GetByPhone(corpId int64, phone string) (*model.StaffUser, error) { + var u model.StaffUser + tx := GetDB().Table(d.TableName()) + tx.Where("corp_id = ?", corpId) + tx = tx.Where("phone = ?", phone) + res := tx.First(&u) + if res.Error == gorm.ErrRecordNotFound { + return nil, nil + } + + if res.Error != nil { + return nil, res.Error + } + return &u, nil +} + +func (d *StaffUserDao) Query(corpId int64, status int) ([]*model.StaffUser, error) { + var u []*model.StaffUser + tx := GetDB().Table(d.TableName()) + tx.Where("corp_id = ?", corpId) + if status != 0 { + tx = tx.Where("status = ?", status) + } + + res := tx.Find(&u) + if res.Error == gorm.ErrRecordNotFound { + return nil, nil + } + + if res.Error != nil { + return nil, res.Error + } + return u, nil +} diff --git a/common/dao/unify_kct_summary.go b/common/dao/unify_kct_summary.go new file mode 100644 index 0000000..9d544b1 --- /dev/null +++ b/common/dao/unify_kct_summary.go @@ -0,0 +1,41 @@ +package dao + +import ( + "enterprise/common/model" + "gorm.io/gorm" +) + +type UnifyKctData struct { +} + +func NewUnifyKctData() *UnifyKctData { + return &UnifyKctData{} +} + +func (d *UnifyKctData) TableName() string { + return "view_unify_kct_summary" +} + +func (d *UnifyKctData) QueryData(startDay, endDay string) ([]*model.UnifyKctSummary, error) { + tx := unifyDB.Table(d.TableName()) + + var o []*model.UnifyKctSummary + + if startDay != "" { + tx = tx.Where("day >= ?", startDay) + } + if endDay != "" { + tx = tx.Where("day <= ?", endDay) + } + tx.Order("day DESC") + + tx = tx.Find(&o) + if tx.Error == gorm.ErrRecordNotFound { + return o, nil + } + + if tx.Error != nil { + return nil, tx.Error + } + return o, nil +} diff --git a/common/model/checkin.go b/common/model/checkin.go index 3e3752a..e539401 100644 --- a/common/model/checkin.go +++ b/common/model/checkin.go @@ -2,6 +2,7 @@ package model type Checkin struct { Id int64 + CorpId int64 Username string Day string Month string diff --git a/common/model/corp.go b/common/model/corp.go index 12ec832..0173c34 100644 --- a/common/model/corp.go +++ b/common/model/corp.go @@ -14,6 +14,9 @@ type CorpConfig struct { TplIdRefund string `json:"tplid_refund"` TplIdVacation string `json:"tplid_vacation"` TplIdPayment string `json:"tplid_payment"` + + SocialDeduct string `json:"social_deduct"` + HouseDeduct string `json:"house_deduct"` } type Corp struct { diff --git a/common/model/staff_config.go b/common/model/staff_config.go deleted file mode 100644 index 18348d7..0000000 --- a/common/model/staff_config.go +++ /dev/null @@ -1,41 +0,0 @@ -package model - -import ( - "encoding/json" - "github.com/smbrave/goutil" -) - -var ( - StaffSalaryExpDiscount = "staff.salary.exp.discount" //试用期薪资折扣 - StaffSalarySocialInsurence = "staff.salary.social.insurence" //社保扣除金额 - StaffSalaryHouseFund = "staff.salary.house.fund" //住房公积金 - StaffSalaryPerDay = "staff.salary.per.day" //按天计算的工资 - StaffSalaryNotify = "staff.salary.notify" //是否发送工资单 - StaffSalaryProfitDeduct = "staff.salary.profit.deduct" //广告收益提成 - StaffSalaryProfitTarget = "staff.salary.profit.target" //广告收益目标 -) -var ( - StaffConfigStatusNormal = 1 - StaffConfigStatusDisable = 2 -) - -type StaffConfig struct { - Id int64 - Username string - Config string - Status int - CreateTime int64 - UpdateTime int64 -} - -func (u *StaffConfig) Get(key string) interface{} { - config := make(map[string]interface{}) - json.Unmarshal([]byte(u.Config), &config) - return config[key] -} - -func (u *StaffConfig) Exist(key string) bool { - config := make(map[string]interface{}) - json.Unmarshal([]byte(u.Config), &config) - return goutil.If(config[key] == nil, false, true) -} diff --git a/common/model/staff_info.go b/common/model/staff_info.go deleted file mode 100644 index 569ffb0..0000000 --- a/common/model/staff_info.go +++ /dev/null @@ -1,26 +0,0 @@ -package model - -var ( - StaffInfoStatusNormal = 1 - StaffInfoStatusDisable = 2 -) - -type StaffInfo struct { - Id int64 - Username string - Realname string - Master string - AlipayUid string - StaffType string - Phone string - Idno string - BaseSalary string - PerfSalary string - EntryDate string - OfficialDate string - LeaveDate string - BankName string - BankCard string - CreateTime int64 - UpdateTime int64 -} diff --git a/common/model/staff_salary.go b/common/model/staff_salary.go index 2857a98..5483f7d 100644 --- a/common/model/staff_salary.go +++ b/common/model/staff_salary.go @@ -3,49 +3,48 @@ package model import ( "encoding/json" butil "enterprise/base/util" + "github.com/smbrave/goutil" "github.com/spf13/cast" "strings" ) -var ( - StaffSalaryStatusNormal = 1 - StaffSalaryStatusDisable = 2 -) - type StaffSalary struct { - Id int64 - Username string - Master string - Month string - BaseSalary float64 - PerfSalary float64 - AttendSalary float64 - RealSalary float64 - AwardSalary float64 - SocialInsurence float64 - HouseFund float64 - PersonalTax float64 - TotalDay float64 - RealDay float64 - Holiday float64 - CreateTime int64 - UpdateTime int64 - Extra string -} - -func (s *StaffSalary) GetRealSalary() float64 { - if s.Master == "" { - return butil.FloatCut(s.AttendSalary + s.PerfSalary + s.AwardSalary - s.SocialInsurence - s.PersonalTax - s.HouseFund) - } - - return butil.FloatCut(s.BaseSalary) + Id int64 + CorpId int64 + UserId int64 + UserName string + Month string + Salary float64 + AttendSalary float64 + TargetSalary float64 + AwardSalary float64 + OtherSalary float64 + ShouldDay int + AttendDay float64 + HolidayDay float64 + SocialDeduct float64 + HouseDeduct float64 + PersonalDeduct float64 + OtherDeduct float64 + CreateTime int64 + UpdateTime int64 + Extra string + Comment string } func (s *StaffSalary) GetShouldSalary() float64 { - if s.Master == "" { - return butil.FloatCut(s.AttendSalary + s.PerfSalary + s.AwardSalary) - } - return butil.FloatCut(s.BaseSalary) + return butil.FloatCut(s.AttendSalary + s.TargetSalary + s.AwardSalary + s.OtherSalary) +} +func (s *StaffSalary) GetRealSalary() float64 { + return butil.FloatCut(s.AttendSalary + s.TargetSalary + s.AwardSalary + s.OtherSalary - + s.SocialDeduct - s.HouseDeduct - s.PersonalDeduct - s.OtherDeduct) +} + +func (s *StaffSalary) SetExtra(key string, value interface{}) { + var extra map[string]interface{} + json.Unmarshal([]byte(s.Extra), &extra) + extra[key] = value + s.Extra = goutil.EncodeJSON(extra) } type StaffSalarySort []*StaffSalary @@ -57,6 +56,7 @@ func (s StaffSalarySort) Len() int { func (s StaffSalarySort) Less(i, j int) bool { var iExtra map[string]string var jExtra map[string]string + json.Unmarshal([]byte(s[i].Extra), &iExtra) json.Unmarshal([]byte(s[j].Extra), &jExtra) diff --git a/common/model/staff_user.go b/common/model/staff_user.go new file mode 100644 index 0000000..1c0fbc9 --- /dev/null +++ b/common/model/staff_user.go @@ -0,0 +1,63 @@ +package model + +import "encoding/json" + +var ( + StaffUserStatusOnline = 1 //在职 + StaffUserStatusOffline = 2 //离职 + StaffUserStatusAttach = 3 //挂靠 +) + +type UserSalary struct { + Base string `json:"base"` //基本工资 + Target string `json:"target"` //绩效工资 +} + +type UserPayee struct { + AlipayUid string `json:"alipay_uid"` //支付宝UID + BankName string `json:"bank_name"` //银行名称 + BankCard string `json:"bank_card"` //银行账号 +} + +type UserConfig struct { + SocialDeduct string `json:"social_deduct"` //社保扣除 + HouseDeduct string `json:"house_deduct"` //公积金扣除 + SalaryCalcutor string `json:"salary_calcutor"` //工资计算器 + PerftTarget string `json:"perft_target"` //绩效目标 +} + +type StaffUser struct { + Id int64 + CorpId int64 + Username string + Realname string + Phone string + Idno string + EntryDate string + OfficialDate string + LeaveDate string + Salary string + Payee string + Config string + CreateTime int64 + UpdateTime int64 + Status int +} + +func (u *StaffUser) GetSalary() *UserSalary { + var salary UserSalary + json.Unmarshal([]byte(u.Salary), &salary) + return &salary +} + +func (u *StaffUser) GetConfig() *UserConfig { + var salary UserConfig + json.Unmarshal([]byte(u.Config), &salary) + return &salary +} + +func (u *StaffUser) GetPayee() *UserPayee { + var salary UserPayee + json.Unmarshal([]byte(u.Payee), &salary) + return &salary +} diff --git a/common/model/unify_ad_data.go b/common/model/unify_data.go similarity index 78% rename from common/model/unify_ad_data.go rename to common/model/unify_data.go index 7d9ccb6..80d4642 100644 --- a/common/model/unify_ad_data.go +++ b/common/model/unify_data.go @@ -25,3 +25,16 @@ type UnifyAdData struct { UpdateTime int64 `json:"updateTime"` Raw string `json:"raw"` } + +type UnifyKctSummary struct { + Day string + NewUser int64 + ActivityUser int64 + PayNum int64 + PayAmount int64 + SignPayAmount int64 + SignPayNum int64 + RefundNum int64 + RefundAmount int64 + Cost int64 +} diff --git a/common/registry/salary.go b/common/registry/salary.go new file mode 100644 index 0000000..78c46f9 --- /dev/null +++ b/common/registry/salary.go @@ -0,0 +1,35 @@ +package registry + +import ( + "enterprise/common/model" + "github.com/spf13/cast" +) + +var ( + salaryFactory map[string]SalaryCalculatorFactory +) + +func init() { + salaryFactory = make(map[string]SalaryCalculatorFactory) +} + +type SalaryCalculator interface { + Calculate(salary *model.StaffSalary) +} + +type SalaryCalculatorFactory func(corp *model.Corp, user *model.StaffUser) SalaryCalculator + +func RegisterSalaryCalculator(name string, factory SalaryCalculatorFactory) { + salaryFactory[name] = factory +} + +func NewSalaryCalculator(corp *model.Corp, user *model.StaffUser) SalaryCalculator { + factory := salaryFactory[cast.ToString(corp.Id)+"_"+user.Username] + if factory == nil { + factory = salaryFactory[cast.ToString(corp.Id)] + } + if factory == nil { + return nil + } + return factory(corp, user) +} diff --git a/server/controller/staff.go b/server/controller/staff.go index f60c950..b2aa505 100644 --- a/server/controller/staff.go +++ b/server/controller/staff.go @@ -35,15 +35,15 @@ func (s *Staff) Salary(ctx *gin.Context) { } func (s *Staff) SalaryHistory(ctx *gin.Context) { - new(service.StaffSalary).History(ctx) + } func (s *Staff) SyncStaffInfo(ctx *gin.Context) { - go new(worker.Staff).SyncStaffInfo() + ctx.JSON(http.StatusOK, session.NewRspOk()) } func (s *Staff) SyncStaffSalary(ctx *gin.Context) { - go new(worker.Staff).SyncStaffSalary("") + go new(worker.Staff).SyncStaffSalary(1000, "") ctx.JSON(http.StatusOK, session.NewRspOk()) } diff --git a/server/service/qyweixin_approve.go b/server/service/qyweixin_approve.go index 3c4df00..73e4b7c 100644 --- a/server/service/qyweixin_approve.go +++ b/server/service/qyweixin_approve.go @@ -227,8 +227,8 @@ func (a *Approve) refundWxpay(data *model.ApprovalRefund) error { return nil } -func (a *Approve) refundAlipay(staff *model.StaffInfo, data *model.ApprovalRefund) error { - +func (a *Approve) refundAlipay(staff *model.StaffUser, data *model.ApprovalRefund) error { + userPayee := staff.GetPayee() cli := config.GetAliPayClient("batiao") var req alipay.FundTransUniTransfer req.Remark = "报销_" + data.SpNo @@ -240,7 +240,7 @@ func (a *Approve) refundAlipay(staff *model.StaffInfo, data *model.ApprovalRefun payee := new(alipay.PayeeInfo) req.PayeeInfo = payee payee.IdentityType = "ALIPAY_USER_ID" - payee.Identity = staff.AlipayUid + payee.Identity = userPayee.AlipayUid rsp, err := cli.FundTransUniTransfer(context.Background(), req) if err != nil { @@ -289,16 +289,16 @@ func (a *Approve) handleRefund(detail *qyweixin.ApproveDetail, spStatus int) { if a.corp.Id != 1000 { return } - staff, err := dao.NewStaffInfoDao().GetByUsername(newData.Username) + staffUser, err := dao.NewStaffUserDao().GetByUsername(1000, newData.Username) if err != nil { log.Errorf("db error :%s", err.Error()) return } - + userPayee := staffUser.GetPayee() // 支付费用 var payType = "weixin" - if staff != nil && staff.AlipayUid != "" { - err = a.refundAlipay(staff, newData) + if userPayee.AlipayUid != "" { + err = a.refundAlipay(staffUser, newData) payType = "alipay" } else { err = a.refundWxpay(newData) @@ -331,7 +331,7 @@ func (a *Approve) handleRefund(detail *qyweixin.ApproveDetail, spStatus int) { } func (a *Approve) HandleRefundApprove(approve *model.ApprovalRefund) error { - staff, err := dao.NewStaffInfoDao().GetByUsername(approve.Username) + staff, err := dao.NewStaffUserDao().GetByUsername(approve.CorpId, approve.Username) if err != nil { return err } @@ -341,7 +341,8 @@ func (a *Approve) HandleRefundApprove(approve *model.ApprovalRefund) error { // 支付费用 var payType = "weixin" - if staff != nil && staff.AlipayUid != "" { + payee := staff.GetPayee() + if payee.AlipayUid != "" { err = a.refundAlipay(staff, approve) payType = "alipay" } else { diff --git a/server/service/staff_salary.go b/server/service/staff_salary.go index a1f744e..d77b9b6 100644 --- a/server/service/staff_salary.go +++ b/server/service/staff_salary.go @@ -1,12 +1,10 @@ package service import ( - "encoding/json" butil "enterprise/base/util" "enterprise/common/config" "enterprise/common/dao" "enterprise/common/model" - "enterprise/service" "fmt" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -28,57 +26,9 @@ var ( type StaffSalary struct { } -func (s *StaffSalary) History(ctx *gin.Context) { - username := ctx.Query("username") - staffSalarys, err := dao.NewStaffSalaryDao().Query("", username, nil) - if err != nil { - panic(config.ErrDb.New().Append(err)) - } - - header := []string{"月份", "基本工资", "绩效工资", "出勤工资", "奖金", "社保扣除", "公积金扣除", "个税扣除", "应出勤天数", "实际出勤天数", "补卡天数", "请假天数", "实发工资"} - datas := make([][]string, 0) - - for _, staff := range staffSalarys { - baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) - if err != nil { - log.Errorf("db error :%s", err.Error()) - continue - } - if baseInfo == nil { - continue - } - extra := make(map[string]interface{}) - json.Unmarshal([]byte(staff.Extra), &extra) - item := make([]string, 0) - - item = append(item, cast.ToString(staff.Month)) - item = append(item, cast.ToString(staff.BaseSalary)) - item = append(item, cast.ToString(butil.FloatCut(staff.PerfSalary))) - item = append(item, cast.ToString(butil.FloatCut(staff.AttendSalary))) - item = append(item, cast.ToString(butil.FloatCut(staff.AwardSalary))) - item = append(item, cast.ToString(staff.SocialInsurence)) - item = append(item, cast.ToString(staff.HouseFund)) - item = append(item, cast.ToString(staff.PersonalTax)) - item = append(item, cast.ToString(staff.TotalDay)) - item = append(item, cast.ToString(staff.RealDay)) - - item = append(item, cast.ToString(extra["approvalCheckinDay"])) - item = append(item, cast.ToString(staff.Holiday)) - item = append(item, cast.ToString(staff.GetRealSalary())) - datas = append(datas, item) - - } - - ctx.HTML(http.StatusOK, "salary.html", gin.H{ - "title": username + "工资汇总", - "header": header, - "data": datas, - }) -} - func (s *StaffSalary) Agent(month string, ctx *gin.Context) { xls := ctx.Query("xls") - staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", nil) + staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month) if err != nil { panic(config.ErrDb.New().Append(err)) } @@ -86,26 +36,27 @@ func (s *StaffSalary) Agent(month string, ctx *gin.Context) { header := []string{"姓名", "身份证号", "电话", "应发工资", "社保扣除", "公积金扣除", "个税扣除", "实发工资"} datas := make([][]string, 0) for _, staff := range staffSalarys { - baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) + userInfo, err := dao.NewStaffUserDao().Get(staff.UserId) if err != nil { log.Errorf("db error :%s", err.Error()) continue } - if baseInfo == nil { + if userInfo == nil { continue } - if staff.BaseSalary == 0 { + userSalary := userInfo.GetSalary() + if userSalary.Base == "" { continue } item := make([]string, 0) - item = append(item, baseInfo.Realname) - item = append(item, cast.ToString(baseInfo.Idno)) - item = append(item, cast.ToString(baseInfo.Phone)) + item = append(item, userInfo.Realname) + item = append(item, cast.ToString(userInfo.Idno)) + item = append(item, cast.ToString(userInfo.Phone)) item = append(item, cast.ToString(staff.GetShouldSalary())) - item = append(item, cast.ToString(staff.SocialInsurence)) - item = append(item, cast.ToString(staff.HouseFund)) - item = append(item, cast.ToString(staff.PersonalTax)) + item = append(item, cast.ToString(staff.SocialDeduct)) + item = append(item, cast.ToString(staff.HouseDeduct)) + item = append(item, cast.ToString(staff.PersonalDeduct)) item = append(item, cast.ToString(staff.GetRealSalary())) datas = append(datas, item) @@ -140,7 +91,7 @@ func (s *StaffSalary) Agent(month string, ctx *gin.Context) { func (s *StaffSalary) Bank(month string, ctx *gin.Context) { xls := ctx.Query("xls") - staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", nil) + staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month) if err != nil { panic(config.ErrDb.New().Append(err)) } @@ -148,22 +99,25 @@ func (s *StaffSalary) Bank(month string, ctx *gin.Context) { header := []string{"账号", "户名", "金额", "开户行", "开户地", "收款备注"} datas := make([][]string, 0) for _, staff := range staffSalarys { - baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) + userInfo, err := dao.NewStaffUserDao().Get(staff.UserId) if err != nil { log.Errorf("db error :%s", err.Error()) continue } - if baseInfo == nil { + if userInfo == nil { continue } - if staff.BaseSalary == 0 { + userSalary := userInfo.GetSalary() + userPayee := userInfo.GetPayee() + if userSalary.Base == "" { continue } + item := make([]string, 0) - item = append(item, baseInfo.BankCard) - item = append(item, baseInfo.Realname) + item = append(item, userPayee.BankCard) + item = append(item, userInfo.Realname) item = append(item, cast.ToString(staff.GetRealSalary())) - item = append(item, cast.ToString(baseInfo.BankName)) + item = append(item, cast.ToString(userPayee.BankName)) item = append(item, "重庆市") item = append(item, fmt.Sprintf("%s工资", month)) datas = append(datas, item) @@ -198,86 +152,86 @@ func (s *StaffSalary) Bank(month string, ctx *gin.Context) { func (s *StaffSalary) Summary(month string, ctx *gin.Context) { xls := ctx.Query("xls") - masterBank := "" - staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", &masterBank) + staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month) if err != nil { panic(config.ErrDb.New().Append(err)) } sort.Sort(model.StaffSalarySort(staffSalarys)) - header := []string{"姓名", "身份证号", "入职日期", "转正日期", "基本工资", "绩效工资", "出勤工资", "附属工资", "奖金", "社保扣除", "公积金扣除", "个税扣除", "应出勤天数", "实际出勤天数", "出勤率", "补卡天数", "请假天数", "实发工资", "状态"} + header := []string{"姓名", "入职日期", "转正日期", "基本工资", "绩效工资", "出勤收入", "绩效收入", "奖金收入", "其他收入", "社保扣除", "公积金扣除", + "个税扣除", "应出勤天数", "实际出勤天数", "请假天数", "实发工资", "状态"} datas := make([][]string, 0) summary := new(model.StaffSalary) totalCount := 0 - totalSlaveSalary := float64(0) - for _, staff := range staffSalarys { - baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) + for _, salary := range staffSalarys { + userInfo, err := dao.NewStaffUserDao().Get(salary.UserId) if err != nil { log.Errorf("db error :%s", err.Error()) continue } - if baseInfo == nil { + if userInfo == nil { continue } - extra := make(map[string]interface{}) - json.Unmarshal([]byte(staff.Extra), &extra) + userSalary := userInfo.GetSalary() + //extra := make(map[string]interface{}) + //json.Unmarshal([]byte(salary.Extra), &extra) item := make([]string, 0) - item = append(item, baseInfo.Realname) - item = append(item, cast.ToString(baseInfo.Idno)) - item = append(item, cast.ToString(baseInfo.EntryDate)) - item = append(item, cast.ToString(baseInfo.OfficialDate)) - item = append(item, cast.ToString(staff.BaseSalary)) - item = append(item, cast.ToString(butil.FloatCut(staff.PerfSalary))) - item = append(item, cast.ToString(butil.FloatCut(staff.AttendSalary))) + item = append(item, userInfo.Realname) + item = append(item, cast.ToString(userInfo.EntryDate)) + item = append(item, cast.ToString(userInfo.OfficialDate)) + item = append(item, userSalary.Base) + item = append(item, userSalary.Target) + item = append(item, cast.ToString(butil.FloatCut(salary.AttendSalary))) + item = append(item, cast.ToString(butil.FloatCut(salary.TargetSalary))) + item = append(item, cast.ToString(butil.FloatCut(salary.AwardSalary))) + item = append(item, cast.ToString(butil.FloatCut(salary.OtherSalary))) - slaveSalary := float64(0) - info, _ := dao.NewStaffInfoDao().GetByUsername(staff.Username) - if info != nil { - slaveSalary = service.NewStaff(info, nil).GetSlaveSalary(month) - } + item = append(item, cast.ToString(butil.FloatCut(salary.SocialDeduct))) + item = append(item, cast.ToString(butil.FloatCut(salary.HouseDeduct))) + item = append(item, cast.ToString(butil.FloatCut(salary.PersonalDeduct))) + item = append(item, cast.ToString(salary.ShouldDay)) - item = append(item, cast.ToString(butil.FloatCut(slaveSalary))) - item = append(item, cast.ToString(butil.FloatCut(staff.AwardSalary))) - item = append(item, cast.ToString(staff.SocialInsurence)) - item = append(item, cast.ToString(staff.HouseFund)) - item = append(item, cast.ToString(staff.PersonalTax)) - item = append(item, cast.ToString(staff.TotalDay)) - item = append(item, cast.ToString(staff.RealDay)) - item = append(item, fmt.Sprintf("%d%%", int(100*staff.RealDay/staff.TotalDay))) - item = append(item, cast.ToString(extra["approvalCheckinDay"])) - item = append(item, cast.ToString(staff.Holiday)) - item = append(item, cast.ToString(staff.GetRealSalary()+slaveSalary)) - if staff.TotalDay != cast.ToFloat64(staff.RealDay)+cast.ToFloat64(staff.Holiday) { + item = append(item, cast.ToString(butil.FloatCut(salary.AttendDay))) + item = append(item, cast.ToString(butil.FloatCut(salary.HolidayDay))) + item = append(item, cast.ToString(salary.GetRealSalary())) + if cast.ToFloat64(salary.ShouldDay) != cast.ToFloat64(salary.AttendDay)+cast.ToFloat64(salary.HolidayDay) { item = append(item, "【异常】") } else { item = append(item, "") } - //item = append(item, fmt.Sprintf("https://e.batiao8.com/staff/salary/history?username=%s", baseInfo.Username)) + totalCount += 1 - totalSlaveSalary += slaveSalary + datas = append(datas, item) - summary.BaseSalary += staff.BaseSalary - summary.PerfSalary += staff.PerfSalary - summary.AttendSalary += staff.AttendSalary - summary.AwardSalary += staff.AwardSalary - summary.SocialInsurence += staff.SocialInsurence - summary.PersonalTax += staff.PersonalTax - summary.Holiday += staff.Holiday - summary.HouseFund += staff.HouseFund + summary.Salary += salary.Salary + + summary.TargetSalary += salary.TargetSalary + summary.AttendSalary += salary.AttendSalary + summary.AwardSalary += salary.AwardSalary + summary.OtherSalary += salary.OtherSalary + + summary.SocialDeduct += salary.SocialDeduct + summary.HouseDeduct += salary.HouseDeduct + summary.PersonalDeduct += salary.PersonalDeduct + summary.OtherDeduct += salary.OtherDeduct + summary.AttendDay += salary.AttendDay + summary.HolidayDay += salary.HolidayDay } - summary.Holiday = butil.FloatCut(summary.Holiday) - summary.BaseSalary = butil.FloatCut(summary.BaseSalary) - summary.PerfSalary = butil.FloatCut(summary.PerfSalary) + summary.HolidayDay = butil.FloatCut(summary.HolidayDay) + summary.Salary = butil.FloatCut(summary.Salary) + summary.TargetSalary = butil.FloatCut(summary.TargetSalary) summary.AttendSalary = butil.FloatCut(summary.AttendSalary) summary.AwardSalary = butil.FloatCut(summary.AwardSalary) - summary.SocialInsurence = butil.FloatCut(summary.SocialInsurence) - summary.HouseFund = butil.FloatCut(summary.HouseFund) - summary.PersonalTax = butil.FloatCut(summary.PersonalTax) - datas = append(datas, []string{"合计", cast.ToString(totalCount), "-", "-", - cast.ToString(summary.BaseSalary), cast.ToString(summary.PerfSalary), cast.ToString(summary.AttendSalary), cast.ToString(totalSlaveSalary), - cast.ToString(summary.AwardSalary), cast.ToString(summary.SocialInsurence), cast.ToString(summary.HouseFund), - cast.ToString(summary.PersonalTax), "-", "-", "-", "-", cast.ToString(summary.Holiday), - cast.ToString(butil.FloatCut(summary.GetRealSalary() + totalSlaveSalary)), "-"}) + summary.SocialDeduct = butil.FloatCut(summary.SocialDeduct) + summary.HouseDeduct = butil.FloatCut(summary.HouseDeduct) + summary.PersonalDeduct = butil.FloatCut(summary.PersonalDeduct) + summary.OtherDeduct = butil.FloatCut(summary.OtherDeduct) + + datas = append(datas, []string{"合计", cast.ToString(totalCount), "-", + cast.ToString(summary.Salary), "-", cast.ToString(summary.AttendSalary), cast.ToString(summary.TargetSalary), cast.ToString(summary.AwardSalary), cast.ToString(summary.OtherSalary), + cast.ToString(summary.SocialDeduct), cast.ToString(summary.HouseDeduct), cast.ToString(summary.PersonalDeduct), + "-", "-", cast.ToString(summary.HolidayDay), + cast.ToString(butil.FloatCut(summary.GetRealSalary())), "-"}) if xls != "" { filename := fmt.Sprintf("summary_%s.xlsx", time.Now().Format("20060102_150405")) diff --git a/service/salary_calculator/init.go b/service/salary_calculator/init.go new file mode 100644 index 0000000..88b8f53 --- /dev/null +++ b/service/salary_calculator/init.go @@ -0,0 +1,8 @@ +package salary_calculator + +import "enterprise/common/registry" + +func init() { + registry.RegisterSalaryCalculator("1000", NewSalaryCalculator1000) + registry.RegisterSalaryCalculator("1000_wujiefeng", NewSalaryCalculator1000Wujiefeng) +} diff --git a/service/salary_calculator/salary_calculator_1000.go b/service/salary_calculator/salary_calculator_1000.go new file mode 100644 index 0000000..75b944d --- /dev/null +++ b/service/salary_calculator/salary_calculator_1000.go @@ -0,0 +1,89 @@ +package salary_calculator + +import ( + butil "enterprise/base/util" + "enterprise/common/dao" + "enterprise/common/model" + "enterprise/common/registry" + log "github.com/sirupsen/logrus" + "github.com/smbrave/goutil" + "github.com/spf13/cast" + "strings" + "time" +) + +const ( + SalaryCalculatorOperation = "operation" //运营计算工资的方法 +) + +type SalaryCalculator1000 struct { + corp *model.Corp + user *model.StaffUser +} + +func NewSalaryCalculator1000(corp *model.Corp, user *model.StaffUser) registry.SalaryCalculator { + return &SalaryCalculator1000{ + corp: corp, + user: user, + } +} + +func (s *SalaryCalculator1000) Calculate(salary *model.StaffSalary) { + userSlary := s.user.GetSalary() + userConfig := s.user.GetConfig() + if s.user.Status == model.StaffUserStatusAttach { //挂靠直接算工资 + salary.AttendSalary = cast.ToFloat64(userSlary.Base) + salary.TargetSalary = cast.ToFloat64(userSlary.Target) + return + } + + salary.AttendSalary = cast.ToFloat64(userSlary.Base) * (salary.AttendDay / float64(salary.ShouldDay)) + salary.TargetSalary = cast.ToFloat64(userSlary.Target) + + if userConfig.SalaryCalcutor == SalaryCalculatorOperation { + s.operationCalculate(salary) + } +} + +func (s *SalaryCalculator1000) operationCalculate(salary *model.StaffSalary) { + userConfig := s.user.GetConfig() + if userConfig.PerftTarget == "" { + return + } + s.getExtraSalary(salary) +} + +func (s *SalaryCalculator1000) getExtraSalary(salary *model.StaffSalary) { + fields := strings.Split(s.user.GetConfig().PerftTarget, ",") + perfTarget := cast.ToFloat64(fields[0]) + awardRate := cast.ToFloat64(fields[1]) + + monthTime, _ := time.ParseInLocation("200601", salary.Month, time.Local) + startDay := monthTime.Format("2006-01-02") + endDay := monthTime.AddDate(0, 1, -1).Format("2006-01-02") + datas, err := dao.NewUnifyAdData().QueryOwnerData(s.user.Username, startDay, endDay) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + sumProfitAmount := int64(0) + for _, data := range datas { + sumProfitAmount += data.PayAmount - data.Cost + } + totalProfit := cast.ToFloat64(goutil.FormatMoney(sumProfitAmount)) + salary.SetExtra("totalProfit", cast.ToString(totalProfit)) + + //1算提成 + userSalary := s.user.GetSalary() + awardSalary := float64(0) + targetSalary := float64(0) + if totalProfit > perfTarget { + awardSalary = totalProfit * awardRate + if awardSalary < 0 { + awardSalary = 0 + } + targetSalary = cast.ToFloat64(userSalary.Target) + } + salary.TargetSalary = butil.FloatCut(targetSalary) + salary.AwardSalary = butil.FloatCut(awardSalary) +} diff --git a/service/salary_calculator/salary_calculator_1000_wujiefeng.go b/service/salary_calculator/salary_calculator_1000_wujiefeng.go new file mode 100644 index 0000000..5607974 --- /dev/null +++ b/service/salary_calculator/salary_calculator_1000_wujiefeng.go @@ -0,0 +1,60 @@ +package salary_calculator + +import ( + "enterprise/common/dao" + "enterprise/common/model" + "enterprise/common/registry" + log "github.com/sirupsen/logrus" + "github.com/smbrave/goutil" + "github.com/spf13/cast" + "time" +) + +type SalaryCalculator1000Wujiefeng struct { + corp *model.Corp + user *model.StaffUser +} + +func NewSalaryCalculator1000Wujiefeng(corp *model.Corp, user *model.StaffUser) registry.SalaryCalculator { + return &SalaryCalculator1000Wujiefeng{ + corp: corp, + user: user, + } +} + +func (s *SalaryCalculator1000Wujiefeng) Calculate(salary *model.StaffSalary) { + baseCalculate := NewSalaryCalculator1000(s.corp, s.user) + baseCalculate.Calculate(salary) + + monthTime, _ := time.ParseInLocation("200601", salary.Month, time.Local) + + sumProfitAmount1 := int64(0) + sumProfitAmount2 := int64(0) + + //本月 + datas, err := dao.NewUnifyKctData().QueryData(monthTime.Format("2006-01-02"), monthTime.AddDate(0, 1, -1).Format("2006-01-02")) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + + for _, data := range datas { + sumProfitAmount1 += data.PayAmount - data.RefundAmount - data.Cost + } + + //上月 + datas, err = dao.NewUnifyKctData().QueryData(monthTime.AddDate(0, -1, 0).Format("2006-01-02"), + monthTime.AddDate(0, 0, -1).Format("2006-01-02")) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + + for _, data := range datas { + sumProfitAmount2 += data.PayAmount - data.RefundAmount - data.Cost + } + salary.SetExtra("sumProfitAmount1", sumProfitAmount1) + salary.SetExtra("sumProfitAmount2", sumProfitAmount2) + userSalary := s.user.GetSalary() + salary.TargetSalary = goutil.If(sumProfitAmount1-sumProfitAmount2 > 0, cast.ToFloat64(userSalary.Target)*float64(sumProfitAmount1)/float64(sumProfitAmount2), 0) +} diff --git a/service/staff.go b/service/staff.go deleted file mode 100644 index 5bef6ab..0000000 --- a/service/staff.go +++ /dev/null @@ -1,320 +0,0 @@ -package service - -import ( - butil "enterprise/base/util" - "enterprise/common/config" - "enterprise/common/dao" - "enterprise/common/model" - log "github.com/sirupsen/logrus" - "github.com/smbrave/goutil" - "github.com/spf13/cast" - "math" - "strings" - "time" -) - -type Staff struct { - info *model.StaffInfo - config *model.StaffConfig -} - -func NewStaff(info *model.StaffInfo, config *model.StaffConfig) *Staff { - return &Staff{ - info: info, - config: config, - } -} - -func (s *Staff) GetSlaveSalary(month string) float64 { - slaveSalarys, err := dao.NewStaffSalaryDao().Query(month, "", &s.info.Username) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return 0 - } - - totalSumSalary := float64(0) - if len(slaveSalarys) != 0 { - for _, slaveSalary := range slaveSalarys { - totalSumSalary += slaveSalary.BaseSalary - } - } - return totalSumSalary -} - -func (s *Staff) CalcSlaveSalary(salary *model.StaffSalary, month string) (*model.StaffSalary, error) { - if salary == nil { - salary = new(model.StaffSalary) - salary.Month = month - salary.Username = s.info.Username - } - salary.BaseSalary = cast.ToFloat64(s.info.BaseSalary) - salary.Master = s.info.Master - extra := make(map[string]interface{}) - extra["entryDate"] = s.info.EntryDate //展示排序依赖 - salary.Extra = goutil.EncodeJSON(extra) - - return salary, nil -} - -func (s *Staff) CalcSalary(salary *model.StaffSalary, month string) (*model.StaffSalary, error) { - staff := s.info - if salary == nil { - salary = new(model.StaffSalary) - salary.Month = month - salary.Username = s.info.Username - } - - entryTime, _ := time.ParseInLocation("2006-01-02", staff.EntryDate, time.Local) - leaveTime, _ := time.ParseInLocation("2006-01-02", staff.LeaveDate, time.Local) - isEntryMonth := goutil.If(cast.ToInt(entryTime.Format("200601")) == cast.ToInt(month), true, false) - isLeaveMonth := goutil.If(cast.ToInt(leaveTime.Format("200601")) == cast.ToInt(month), true, false) - - // 试用期折扣 - discount := s.getDiscount(month) - - //社保和公积金 - socialInsurence := goutil.If(s.config.Exist(model.StaffSalarySocialInsurence), cast.ToFloat64(s.config.Get(model.StaffSalarySocialInsurence)), config.SalarySocialInsurence) - //houseFund := goutil.If(s.config.Exist(model.StaffSalaryHouseFund), cast.ToFloat64(s.config.Get(model.StaffSalaryHouseFund)), config.SalaryHouseFund) - houseFund := cast.ToFloat64(s.config.Get(model.StaffSalaryHouseFund)) - if isEntryMonth { //入职月不买社保 - socialInsurence = 0 - houseFund = 0 - } - - holiday, surplusHoliday := s.getRealVacationDay(staff.Username, month) - totalDays := s.getTotalWorkDay(staff.Username, month) - realWorkDays := s.getRealWorkDay(staff.EntryDate, staff.LeaveDate, staff.Username, month) - approvalCheckinDay := s.getApprovalCheckinDay(staff.Username, month) - - // 入职月或离职月以大多数人的出勤天数为准 - if isEntryMonth || isLeaveMonth { - totalDays = s.getTotalWorkDayMax(month) - } - - salary.BaseSalary = cast.ToFloat64(staff.BaseSalary) - - realWorkDays = realWorkDays + surplusHoliday - atttendRate := float64(realWorkDays) / float64(totalDays) - attendSalary := salary.BaseSalary * atttendRate * discount - staffSalaryPerDay := cast.ToFloat64(s.config.Get(model.StaffSalaryPerDay)) - if staffSalaryPerDay > 0 { - attendSalary = staffSalaryPerDay * realWorkDays - } - - extra := make(map[string]interface{}) - extra["approvalCheckinDay"] = approvalCheckinDay //展示依赖 - extra["entryDate"] = staff.EntryDate //展示排序依赖 - - awardSalay, perfSalary := s.getExtraSalary(month) - - salary.Holiday = holiday - salary.PerfSalary = perfSalary - salary.AwardSalary = awardSalay - salary.AttendSalary = butil.FloatCut(attendSalary) - salary.RealSalary = salary.GetRealSalary() - salary.SocialInsurence = socialInsurence - salary.HouseFund = houseFund - salary.Holiday = holiday - salary.TotalDay = float64(totalDays) - salary.RealDay = realWorkDays - salary.Extra = goutil.EncodeJSONIndent(extra) - - return salary, nil -} - -func (s *Staff) getExtraSalary(month string) (float64, float64) { - monthTime, _ := time.ParseInLocation("200601", month, time.Local) - startDay := monthTime.Format("2006-01-02") - endDay := monthTime.AddDate(0, 1, -1).Format("2006-01-02") - datas, err := dao.NewUnifyAdData().QueryOwnerData(s.info.Username, startDay, endDay) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return 0, 0 - } - sumProfitAmount := int64(0) - for _, data := range datas { - sumProfitAmount += data.PayAmount - data.Cost - } - totalProfit := cast.ToFloat64(goutil.FormatMoney(sumProfitAmount)) - - //1算提成 - awardSalary := float64(0) - if s.config.Exist(model.StaffSalaryProfitDeduct) { - deductRate := cast.ToFloat64(s.config.Get(model.StaffSalaryProfitDeduct)) - awardSalary = totalProfit * deductRate - if awardSalary < 0 { - awardSalary = 0 - } - } - - //2算绩效 - perfSalary := cast.ToFloat64(s.info.PerfSalary) - if s.config.Exist(model.StaffSalaryProfitTarget) { - profitTarget := cast.ToFloat64(s.config.Get(model.StaffSalaryProfitTarget)) - if totalProfit < 0 { - perfSalary = 0 - awardSalary = 0 - } else if totalProfit < profitTarget { - perfSalary = perfSalary * (totalProfit / profitTarget) - awardSalary = 0 - } - } - return awardSalary, perfSalary -} - -func (s *Staff) getDiscount(month string) float64 { - officalTime, _ := time.ParseInLocation("2006-01-02", s.info.OfficialDate, time.Local) - monthTime, _ := time.ParseInLocation("200601", month, time.Local) - startDate := cast.ToInt(monthTime.Format("20060102")) - endDate := cast.ToInt(monthTime.AddDate(0, 1, -1).Format("20060102")) - officialDate := cast.ToInt(strings.ReplaceAll(s.info.OfficialDate, "-", "")) - isOfficialMonth := goutil.If(cast.ToInt(officalTime.Format("200601")) == cast.ToInt(month), true, false) - - // 试用期折扣 - discount := cast.ToFloat64(s.config.Get(model.StaffSalaryExpDiscount)) - if discount == 0.0 { - discount = 0.8 - } - if cast.ToInt(monthTime.Format("200601")) > cast.ToInt(officalTime.Format("200601")) { - discount = 1.0 - } - if discount < 1.0 && isOfficialMonth { - totalMonthDay := float64(endDate - startDate + 1) - discount = discount*float64(officialDate-startDate)/totalMonthDay + 1*float64(endDate-officialDate+1)/totalMonthDay - } - return discount -} - -func (s *Staff) getRealVacationDay(username, month string) (float64, float64) { - // 休假申请 - approveVacations, err := dao.NewApprovalVacationDao().GetByUsername(username, month, "") - if err != nil { - log.Errorf("db error :%s", err.Error()) - return 0, 0 - } - - holiday := float64(0) - surplusHoliday := float64(0) - for _, vac := range approveVacations { - startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", vac.VacationStartTime, time.Local) - endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", vac.VacationEndTime, time.Local) - - //同一天请假时长大于8小时算一天 - if startTime.Format("2006-01-02") == endTime.Format("2006-01-02") && vac.VacationDuration > 1 { - holiday += 1 - } else { - holiday += vac.VacationDuration - //不是整天数,把剩余的算上 - span := vac.VacationDuration - math.Floor(vac.VacationDuration) - surplusHoliday += goutil.If(math.Abs(span) < 0.000001, 0, 1-span) - } - } - return holiday, surplusHoliday -} - -func (s *Staff) getApprovalCheckinDay(username, month string) int { - approvalDay := int(0) - userCheckins, err := dao.NewCheckinDao().Query(username, month, false) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return approvalDay - } - for _, checkin := range userCheckins { - - approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(username, checkin.Day) - if approvalCheckin != nil { - approvalDay += 1 - } - - } - return approvalDay -} - -func (s *Staff) getRealWorkDay(entryDate, leaveDate, username, month string) float64 { - realWorkdays := float64(0) - userCheckins, err := dao.NewCheckinDao().Query(username, month, false) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return realWorkdays - } - approvalCheckinDay := 0 - - //入职当天算工作日 - entryTime, _ := time.ParseInLocation("2006-01-02", entryDate, time.Local) - if entryTime.Format("200601") == month { - realWorkdays += 1 - } - - //离职当天算工作日 - leaveTime, _ := time.ParseInLocation("2006-01-02", leaveDate, time.Local) - if leaveTime.Format("200601") == month { - realWorkdays += 1 - } - - for _, checkin := range userCheckins { - - //入职离职当天已经算过了 - if entryTime.Format("2006-01-02") == checkin.Day || leaveTime.Format("2006-01-02") == checkin.Day { - continue - } - - if checkin.Exception == "" { - realWorkdays += 1 - continue - } - - ////有请假申请的不算出勤 - approvalVacation, _ := dao.NewApprovalVacationDao().GetByUsernameDay(username, checkin.Day) - if approvalVacation != nil { - continue - } - - //有补卡申请就直接算出勤 - approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(username, checkin.Day) - if approvalCheckin != nil { - realWorkdays += 1 - approvalCheckinDay += 1 - continue - } - - // 迟到的按时间折算 - if strings.Contains(checkin.Exception, "上班打卡:时间异常") { - stTime := time.Unix(checkin.StartTime, 0) - later := float64(stTime.Hour() - 8) //迟到小时数,从9点算 - if later > 8 { - later = 8 - } - realWorkdays += (8 - later) / 8 - continue - } - } - return realWorkdays -} - -func (s *Staff) getTotalWorkDay(username, month string) int64 { - checkins, _ := dao.NewCheckinDao().Query(username, month, false) - return int64(len(checkins)) -} - -func (s *Staff) getTotalWorkDayMax(month string) int64 { - // 最多人数的应出勤天数 为真正的出勤天数 - userCounts, err := dao.NewCheckinDao().CountUsername(month) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return 0 - } - mp := make(map[int64]int) - totalDays := int64(0) - for _, uc := range userCounts { - mp[uc.Count] += 1 - } - minCount := 0 - for k, v := range mp { - if v > minCount { - minCount = v - totalDays = k - } - } - return totalDays - -} diff --git a/service/staff_salary.go b/service/staff_salary.go new file mode 100644 index 0000000..a47e1e1 --- /dev/null +++ b/service/staff_salary.go @@ -0,0 +1,220 @@ +package service + +import ( + "enterprise/common/dao" + "enterprise/common/model" + "enterprise/common/registry" + log "github.com/sirupsen/logrus" + "github.com/smbrave/goutil" + "github.com/spf13/cast" + "math" + "strings" + "time" +) + +type StaffSalary struct { + user *model.StaffUser +} + +func NewStaffSalary(user *model.StaffUser) *StaffSalary { + return &StaffSalary{ + user: user, + } +} + +func (s *StaffSalary) CalcSalary(salary *model.StaffSalary, month string) (*model.StaffSalary, error) { + corp, err := dao.NewCorpDao().Get(s.user.CorpId) + if err != nil { + return nil, err + } + userSalary := s.user.GetSalary() + userConfig := s.user.GetConfig() + corpConfig := corp.GetConfig() + if userSalary.Base == "" && userSalary.Target == "" { + return nil, nil + } + if salary == nil { + salary = new(model.StaffSalary) + salary.Month = month + salary.CorpId = s.user.CorpId + salary.UserId = s.user.Id + salary.UserName = s.user.Username + } + + entryTime, _ := time.ParseInLocation("2006-01-02", s.user.EntryDate, time.Local) + leaveTime, _ := time.ParseInLocation("2006-01-02", s.user.LeaveDate, time.Local) + isEntryMonth := goutil.If(cast.ToInt(entryTime.Format("200601")) == cast.ToInt(month), true, false) + isLeaveMonth := goutil.If(cast.ToInt(leaveTime.Format("200601")) == cast.ToInt(month), true, false) + + //社保和公积金 + salary.SocialDeduct = 0 + salary.HouseDeduct = 0 + if isEntryMonth { //入职月不买社保 + salary.SocialDeduct = 0 + salary.HouseDeduct = 0 + } + + salary.ShouldDay = int(s.getTotalWorkDay(s.user.CorpId, s.user.Username, month)) + // 入职月或离职月以大多数人的出勤天数为准 + if isEntryMonth || isLeaveMonth { + salary.ShouldDay = int(s.getTotalWorkDayMax(s.user.CorpId, month)) + } + + holiday, surplusHoliday := s.getRealVacationDay(month) + realWorkDays := s.getRealWorkDay(month) + approvalCheckinDay := s.getApprovalCheckinDay(s.user.CorpId, s.user.Username, month) + + salary.HolidayDay = holiday + salary.AttendDay = realWorkDays + surplusHoliday + salary.Salary = cast.ToFloat64(userSalary.Base) + cast.ToFloat64(userSalary.Target) + salary.SocialDeduct = goutil.If(userConfig.SocialDeduct != "", cast.ToFloat64(userConfig.SocialDeduct), cast.ToFloat64(corpConfig.SocialDeduct)) + salary.HouseDeduct = goutil.If(userConfig.HouseDeduct != "", cast.ToFloat64(userConfig.HouseDeduct), cast.ToFloat64(corpConfig.HouseDeduct)) + + extra := make(map[string]interface{}) + extra["approvalCheckinDay"] = approvalCheckinDay //展示依赖 + extra["entryDate"] = s.user.EntryDate //展示排序依赖 + extra["leaveDate"] = s.user.LeaveDate //展示排序依赖 + extra["baseSalary"] = userSalary.Base + extra["targetSalary"] = userSalary.Target + + salary.Extra = goutil.EncodeJSONIndent(extra) + + calculator := registry.NewSalaryCalculator(corp, s.user) + if calculator != nil { + calculator.Calculate(salary) + } + return salary, nil +} + +func (s *StaffSalary) getRealVacationDay(month string) (float64, float64) { + // 休假申请 + approveVacations, err := dao.NewApprovalVacationDao().GetByUsername(s.user.CorpId, s.user.Username, month, "") + if err != nil { + log.Errorf("db error :%s", err.Error()) + return 0, 0 + } + + holiday := float64(0) + surplusHoliday := float64(0) + for _, vac := range approveVacations { + startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", vac.VacationStartTime, time.Local) + endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", vac.VacationEndTime, time.Local) + + //同一天请假时长大于8小时算一天 + if startTime.Format("2006-01-02") == endTime.Format("2006-01-02") && vac.VacationDuration > 1 { + holiday += 1 + } else { + holiday += vac.VacationDuration + //不是整天数,把剩余的算上 + span := vac.VacationDuration - math.Floor(vac.VacationDuration) + surplusHoliday += goutil.If(math.Abs(span) < 0.000001, 0, 1-span) + } + } + return holiday, surplusHoliday +} + +func (s *StaffSalary) getApprovalCheckinDay(corpId int64, username, month string) int { + approvalDay := int(0) + userCheckins, err := dao.NewCheckinDao().Query(corpId, username, month, false) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return approvalDay + } + for _, checkin := range userCheckins { + approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(corpId, username, checkin.Day) + if approvalCheckin != nil { + approvalDay += 1 + } + + } + return approvalDay +} + +func (s *StaffSalary) getRealWorkDay(month string) float64 { + realWorkdays := float64(0) + userCheckins, err := dao.NewCheckinDao().Query(s.user.CorpId, s.user.Username, month, false) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return realWorkdays + } + approvalCheckinDay := 0 + + //入职当天算工作日 + entryTime, _ := time.ParseInLocation("2006-01-02", s.user.EntryDate, time.Local) + if entryTime.Format("200601") == month { + realWorkdays += 1 + } + + //离职当天算工作日 + leaveTime, _ := time.ParseInLocation("2006-01-02", s.user.LeaveDate, time.Local) + if leaveTime.Format("200601") == month { + realWorkdays += 1 + } + + for _, checkin := range userCheckins { + + //入职离职当天已经算过了 + if entryTime.Format("2006-01-02") == checkin.Day || leaveTime.Format("2006-01-02") == checkin.Day { + continue + } + + if checkin.Exception == "" { + realWorkdays += 1 + continue + } + + //有请假申请的不算出勤 + approvalVacation, _ := dao.NewApprovalVacationDao().GetByUsernameDay(s.user.CorpId, s.user.Username, checkin.Day) + if approvalVacation != nil { + continue + } + + //有补卡申请就直接算出勤 + approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(s.user.CorpId, s.user.Username, checkin.Day) + if approvalCheckin != nil { + realWorkdays += 1 + approvalCheckinDay += 1 + continue + } + + // 迟到的按时间折算 + if strings.Contains(checkin.Exception, "上班打卡:时间异常") { + stTime := time.Unix(checkin.StartTime, 0) + later := float64(stTime.Hour() - 8) //迟到小时数,从9点算 + if later > 8 { + later = 8 + } + realWorkdays += (8 - later) / 8 + continue + } + } + return realWorkdays +} + +func (s *StaffSalary) getTotalWorkDay(corpId int64, username, month string) int64 { + checkins, _ := dao.NewCheckinDao().Query(corpId, username, month, false) + return int64(len(checkins)) +} + +func (s *StaffSalary) getTotalWorkDayMax(corpId int64, month string) int64 { + // 最多人数的应出勤天数 为真正的出勤天数 + userCounts, err := dao.NewCheckinDao().CountUsername(corpId, month) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return 0 + } + mp := make(map[int64]int) + totalDays := int64(0) + for _, uc := range userCounts { + mp[uc.Count] += 1 + } + minCount := 0 + for k, v := range mp { + if v > minCount { + minCount = v + totalDays = k + } + } + return totalDays + +} diff --git a/worker/approval.go b/worker/approval.go index ab88a02..2c551c7 100644 --- a/worker/approval.go +++ b/worker/approval.go @@ -1,7 +1,6 @@ package worker import ( - "enterprise/common/config" "enterprise/common/dao" "enterprise/common/model" "git.u8t.cn/open/gosdk/qyweixin" @@ -14,7 +13,8 @@ type Approval struct { corpConfig *model.CorpConfig } -func NewApproval(corp *model.Corp) *Approval { +func NewApproval(corpId int64) *Approval { + corp, _ := dao.NewCorpDao().Get(corpId) return &Approval{ corp: corp, corpConfig: corp.GetConfig(), @@ -33,10 +33,16 @@ func (s *Approval) getTemplateId(tp string) string { return "" } -func (s *Approval) Sync(month, tp string) { +func (s *Approval) Sync(corpId int64, month, tp string) { + corp, err := dao.NewCorpDao().Get(corpId) + if err != nil { + log.Errorf("db error:%s", err.Error()) + return + } + corpConfig := corp.GetConfig() templateId := s.getTemplateId(tp) - cfg := config.GetConfig().QyWeixin - approve := qyweixin.NewAppApprove(&qyweixin.AppConfig{Corpid: cfg.Corpid, Secret: cfg.ApproveSecret, Agent: cfg.ApproveAgent}) + + approve := qyweixin.NewAppApprove(&qyweixin.AppConfig{Corpid: corpConfig.CorpId, Secret: corpConfig.ApproveSecret, Agent: corpConfig.ApproveAgent}) startTime, _ := time.ParseInLocation("200601", month, time.Local) endTime := startTime.AddDate(0, 1, 0) spNos, err := approve.GetList(startTime.Unix(), endTime.Unix()-1, templateId) diff --git a/worker/checkin.go b/worker/checkin.go index 8bcbd80..bf2c1b1 100644 --- a/worker/checkin.go +++ b/worker/checkin.go @@ -1,7 +1,6 @@ package worker import ( - "enterprise/common/config" "enterprise/common/dao" "enterprise/common/global" "enterprise/common/model" @@ -18,26 +17,33 @@ type Checkin struct { corpConfig *model.CorpConfig } -func NewCheckin(corp *model.Corp) *Checkin { +func NewCheckin(corpId int64) *Checkin { + corp, _ := dao.NewCorpDao().Get(corpId) return &Checkin{ corp: corp, corpConfig: corp.GetConfig(), } } -func (c *Checkin) SyncCheckinMonth(month string) error { +func (c *Checkin) SyncCheckinMonth(corpId int64, month string) error { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("200601") } - cfg := config.GetConfig() + corp, err := dao.NewCorpDao().Get(corpId) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return err + } + + cfg := corp.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 := qyweixin.NewAppCheckin(&qyweixin.AppConfig{ - Corpid: cfg.QyWeixin.Corpid, - Secret: cfg.QyWeixin.EnterpriseSecret, - Agent: cfg.QyWeixin.EnterpriseAgent, + Corpid: cfg.CorpId, + Secret: cfg.EnterpriseSecret, + Agent: cfg.EnterpriseAgent, }) users, err := qyw.GetCheckinEmployee(nil) if err != nil { @@ -56,12 +62,18 @@ func (c *Checkin) SyncCheckinMonth(month string) error { return nil } -func (c *Checkin) SyncCheckinDay(day string) { - cfg := config.GetConfig() +func (c *Checkin) SyncCheckinDay(corpId int64, day string) { + corp, err := dao.NewCorpDao().Get(corpId) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + + cfg := corp.GetConfig() qyw := qyweixin.NewAppCheckin(&qyweixin.AppConfig{ - Corpid: cfg.QyWeixin.Corpid, - Secret: cfg.QyWeixin.EnterpriseSecret, - Agent: cfg.QyWeixin.EnterpriseAgent, + Corpid: cfg.CorpId, + Secret: cfg.EnterpriseSecret, + Agent: cfg.EnterpriseAgent, }) if day == "" { day = time.Now().AddDate(0, 0, -1).Format("2006-01-02") @@ -84,11 +96,11 @@ func (c *Checkin) SyncCheckinDay(day string) { return } -func (c *Checkin) MonitorCheckinDay(day string) { +func (c *Checkin) MonitorCheckinDay(corpId int64, day string) { if day == "" { day = time.Now().AddDate(0, 0, -1).Format("2006-01-02") } - checkins, err := dao.NewCheckinDao().QueryDay(day) + checkins, err := dao.NewCheckinDao().QueryDay(corpId, day) if err != nil { log.Errorf("db error :%s", err.Error()) return @@ -97,7 +109,7 @@ func (c *Checkin) MonitorCheckinDay(day string) { if checkin.Exception == "" { continue } - approvals, err := dao.NewApprovalVacationDao().GetByUsername(checkin.Username, "", checkin.Day) + approvals, err := dao.NewApprovalVacationDao().GetByUsername(corpId, checkin.Username, "", checkin.Day) if err != nil { log.Errorf("db error :%s", err.Error()) continue diff --git a/worker/staff.go b/worker/staff.go index de96110..3a8f711 100644 --- a/worker/staff.go +++ b/worker/staff.go @@ -1,13 +1,11 @@ package worker import ( - "enterprise/common/config" "enterprise/common/dao" "enterprise/common/global" "enterprise/common/model" "enterprise/service" "fmt" - "git.u8t.cn/open/gosdk/qyweixin" log "github.com/sirupsen/logrus" "github.com/smbrave/goutil" "github.com/spf13/cast" @@ -18,8 +16,8 @@ import ( type Staff struct { } -func (s *Staff) MontorWorkAge() { - staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal) +func (s *Staff) MontorWorkAge(corpId int64) { + staffs, err := dao.NewStaffUserDao().Query(corpId, model.StaffUserStatusOnline) if err != nil { log.Errorf("db error :%s", err.Error()) return @@ -38,13 +36,15 @@ func (s *Staff) MontorWorkAge() { entryMonth := (nowDate.Year()-entryDate.Year())*12 + int(nowDate.Month()) - int(entryDate.Month()) officalDay := (OfficialDate.Unix() - nowDate.Unix()) / 86400 log.Infof("staff[%s] entryDate[%s] spanMonth[%.1f]", staff.Username, staff.EntryDate, float64(entryMonth)/12.0) + + salary := staff.GetSalary() if nowDate.Day() == 1 && entryMonth%6 == 0 { message := make([]string, 0) message = append(message, fmt.Sprintf("【员工半年提醒】[%s]", staff.Realname)) message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate)) message = append(message, fmt.Sprintf("入职年限:%.1f", float64(entryMonth)/12)) - message = append(message, fmt.Sprintf("基本工资:%s", staff.BaseSalary)) - message = append(message, fmt.Sprintf("绩效工资:%s", staff.PerfSalary)) + message = append(message, fmt.Sprintf("基本工资:%s", salary.Base)) + message = append(message, fmt.Sprintf("绩效工资:%s", salary.Target)) message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno)) if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { @@ -57,131 +57,70 @@ func (s *Staff) MontorWorkAge() { message = append(message, fmt.Sprintf("【员工转正提醒】[%s]", staff.Realname)) message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate)) message = append(message, fmt.Sprintf("转正时间:%s", staff.OfficialDate)) - message = append(message, fmt.Sprintf("基本工资:%s", staff.BaseSalary)) - message = append(message, fmt.Sprintf("绩效工资:%s", staff.PerfSalary)) + message = append(message, fmt.Sprintf("基本工资:%s", salary.Base)) + message = append(message, fmt.Sprintf("绩效工资:%s", salary.Target)) message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno)) if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) } } - } } -func (s *Staff) SendStaffSalaryBill(month string) { - masterBlank := "" - staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", &masterBlank) +func (s *Staff) SendStaffSalaryBill(corpId int64, month string) { + staffSalarys, err := dao.NewStaffSalaryDao().Query(corpId, 0, month) if err != nil { log.Errorf("db error :%s", err.Error()) return } + for _, staffSalary := range staffSalarys { - if staffSalary.BaseSalary < 0.1 { + if staffSalary.Salary < 0.1 { continue } - userConfig, err := dao.NewUserConfigDao().GetByUsername(staffSalary.Username) + user, err := dao.NewStaffUserDao().Get(staffSalary.UserId) if err != nil { log.Errorf("db error :%s", err.Error()) 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.AttendSalary)) + message = append(message, fmt.Sprintf("【工资单】[%s][%s]", user.Username, month)) + message = append(message, fmt.Sprintf("基本工资:%.2f", staffSalary.Salary)) + if staffSalary.AttendSalary >= 0.1 { + message = append(message, fmt.Sprintf("出勤工资:%.2f", staffSalary.AttendSalary)) + } if staffSalary.AwardSalary >= 0.1 { - message = append(message, fmt.Sprintf("额外工资:%.2f", staffSalary.AwardSalary)) + message = append(message, fmt.Sprintf("奖金收入:%.2f", staffSalary.AwardSalary)) + } + if staffSalary.OtherSalary >= 0.1 { + message = append(message, fmt.Sprintf("其他收入:%.2f", staffSalary.OtherSalary)) } - //附属工资 - var slaveSalary float64 = 0 - staff, _ := dao.NewStaffInfoDao().GetByUsername(staffSalary.Username) - if staff != nil { - slaveSalary = service.NewStaff(staff, nil).GetSlaveSalary(month) - if slaveSalary > 0.1 { - message = append(message, fmt.Sprintf("附属工资:%.2f", slaveSalary)) - } - } - - message = append(message, fmt.Sprintf("社保扣除:%.2f", staffSalary.SocialInsurence)) - message = append(message, fmt.Sprintf("个税扣除:%.2f", staffSalary.PersonalTax)) - message = append(message, fmt.Sprintf("实发工资:%.2f", staffSalary.GetRealSalary()+slaveSalary)) + message = append(message, fmt.Sprintf("社保扣除:%.2f", staffSalary.SocialDeduct+staffSalary.HouseDeduct)) + message = append(message, fmt.Sprintf("个税扣除:%.2f", staffSalary.PersonalDeduct)) + message = append(message, fmt.Sprintf("实发工资:%.2f", staffSalary.GetRealSalary())) if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) } - if userConfig != nil && cast.ToBool(userConfig.Get(model.StaffSalaryNotify)) == true { - if err := global.SendMessage([]string{userConfig.Username}, strings.Join(message, "\n")); err != nil { - log.Errorf("send message error :%s", err.Error()) - } - } + } } -func (s *Staff) SyncStaffInfo() { - cfg := config.GetConfig() - hrAssiant := qyweixin.NewAppHr(&qyweixin.AppConfig{ - Corpid: cfg.QyWeixin.Corpid, - Secret: cfg.QyWeixin.EnterpriseSecret, - Agent: cfg.QyWeixin.EnterpriseAgent, - }) - - userConfigs, err := dao.NewUserConfigDao().Query(model.StaffConfigStatusNormal) - 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.Extra["11015"] - staff.StaffType = staffInfo.Extra["12003"] - staff.BaseSalary = staffInfo.Extra["20001"] - staff.PerfSalary = staffInfo.Extra["20005"] - staff.EntryDate = time.Unix(cast.ToInt64(staffInfo.Extra["12018"]), 0).Format("2006-01-02") - staff.OfficialDate = time.Unix(cast.ToInt64(staffInfo.Extra["12023"]), 0).Format("2006-01-02") - staff.BankName = staffInfo.Extra["13001"] - staff.BankCard = staffInfo.Extra["13002"] - staff.AlipayUid = staffInfo.Extra["20004"] - - 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) { +func (s *Staff) SyncStaffSalary(corpId int64, month string) { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("2006-01") } month = strings.ReplaceAll(month, "-", "") - staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal) + staffs, err := dao.NewStaffUserDao().Query(corpId, 0) if err != nil { log.Errorf("query staff db error :%s", err.Error()) return } for _, staff := range staffs { - // 已离职的员工不处理 if staff.LeaveDate != "" { leaveTime, _ := time.ParseInLocation("2006-01-02", staff.LeaveDate, time.Local) @@ -191,31 +130,20 @@ func (s *Staff) SyncStaffSalary(month string) { } } - salary, err := dao.NewStaffSalaryDao().GetBy(staff.Username, month) + salary, err := dao.NewStaffSalaryDao().GetBy(corpId, staff.Id, month) if err != nil { log.Errorf("db error :%s", err.Error()) continue } - //附属员工直接生成工资单 - if staff.Master != "" { - staffService := service.NewStaff(staff, nil) - salary, err = staffService.CalcSlaveSalary(salary, month) - } else { - config, err := dao.NewUserConfigDao().GetByUsername(staff.Username) - if err != nil || config == nil { - log.Errorf("username[%s] not config,skip!!", staff.Username) - continue - } - if config.Status == model.StaffConfigStatusDisable { - continue - } - staffService := service.NewStaff(staff, config) - salary, err = staffService.CalcSalary(salary, month) - if err != nil { - log.Errorf("username[%s] staffService.CalcSalary error :%s", staff.Username, err.Error()) - continue - } + staffService := service.NewStaffSalary(staff) + salary, err = staffService.CalcSalary(salary, month) + if err != nil { + log.Errorf("username[%s] staffService.CalcSalary error :%s", staff.Username, err.Error()) + continue + } + if salary == nil { + continue } if salary.Id == 0 { diff --git a/worker/worker.go b/worker/worker.go index b51d66c..ae6d14a 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -1,56 +1,54 @@ package worker import ( - "enterprise/common/dao" "enterprise/common/model" "github.com/go-co-op/gocron" "time" ) -func Init() error { +func InitCorp(corpId int64) error { - corp, _ := dao.NewCorpDao().Get(1000) timezone, _ := time.LoadLocation("Asia/Shanghai") cron := gocron.NewScheduler(timezone) staff := new(Staff) - checkIn := NewCheckin(corp) - // 每天同步企业人事信息 - cron.Every(1).Day().At("01:00").Do(func() { - go staff.SyncStaffInfo() - }) cron.Every(1).Day().At("09:00").Do(func() { - go staff.MontorWorkAge() + go staff.MontorWorkAge(corpId) }) //同步每日考勤数据 cron.Every(1).Day().At("05:00").Do(func() { - go checkIn.SyncCheckinDay("") + checkIn := NewCheckin(corpId) + go checkIn.SyncCheckinDay(corpId, "") }) cron.Every(1).Day().At("08:00").Do(func() { - go checkIn.MonitorCheckinDay("") + checkIn := NewCheckin(corpId) + go checkIn.MonitorCheckinDay(corpId, "") }) //每月1号同步上月考勤、补卡审批、请假审批、报销审批 cron.Every(1).Month(1).At("05:30").Do(func() { + checkIn := NewCheckin(corpId) + checkIn.SyncCheckinMonth(corpId, "") lastMonth := time.Now().AddDate(0, -1, 0).Format("200601") - checkIn.SyncCheckinMonth("") - approve := NewApproval(corp) - approve.Sync(lastMonth, model.ApprovalTypeCheckin) - approve.Sync(lastMonth, model.ApprovalTypeVacation) - approve.Sync(lastMonth, model.ApprovalTypeRefund) - approve.Sync(lastMonth, model.ApprovalTypePayment) + approve := NewApproval(corpId) + approve.Sync(corpId, lastMonth, model.ApprovalTypeCheckin) + approve.Sync(corpId, lastMonth, model.ApprovalTypeVacation) + approve.Sync(corpId, lastMonth, model.ApprovalTypeRefund) + approve.Sync(corpId, lastMonth, model.ApprovalTypePayment) }) // 1号计算工资信息 cron.Every(1).Month(1, 2, 3, 4, 5, 6, 7, 8, 9).At("06:00").Do(func() { - go staff.SyncStaffSalary("") + go staff.SyncStaffSalary(corpId, "") + //go staff.SyncStaffSalary(1002, "") }) //10号晚上8点发送工资单 cron.Every(1).Month(10).At("20:00").Do(func() { - go staff.SendStaffSalaryBill(time.Now().AddDate(0, -1, 0).Format("200601")) + go staff.SendStaffSalaryBill(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) + //go staff.SendStaffSalaryBill(1002, time.Now().AddDate(0, -1, 0).Format("200601")) }) cron.StartAsync() return nil From f475a829b96f2d011448da87e171e46d068baee1 Mon Sep 17 00:00:00 2001 From: jiangyong27 Date: Tue, 4 Mar 2025 23:27:13 +0800 Subject: [PATCH 2/2] new salary2 --- cmd/enterprise.go | 9 ++++--- worker/checkin.go | 10 +++----- worker/worker.go | 63 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/cmd/enterprise.go b/cmd/enterprise.go index 758fb1a..8851715 100644 --- a/cmd/enterprise.go +++ b/cmd/enterprise.go @@ -13,9 +13,12 @@ func main() { config.LoadAliPay() global.InitGlobal() - if err := worker.InitCorp(1000); err != nil { - panic(err) - } + checkIn := worker.NewCheckin(1002) + checkIn.SyncCheckinMonth("") + + return + + worker.InitCorp() if err := server.Start(); err != nil { panic(err) diff --git a/worker/checkin.go b/worker/checkin.go index bf2c1b1..fdd80d9 100644 --- a/worker/checkin.go +++ b/worker/checkin.go @@ -24,17 +24,12 @@ func NewCheckin(corpId int64) *Checkin { corpConfig: corp.GetConfig(), } } -func (c *Checkin) SyncCheckinMonth(corpId int64, month string) error { +func (c *Checkin) SyncCheckinMonth(month string) error { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("200601") } - corp, err := dao.NewCorpDao().Get(corpId) - if err != nil { - log.Errorf("db error :%s", err.Error()) - return err - } - cfg := corp.GetConfig() + cfg := c.corp.GetConfig() startTime, _ := time.ParseInLocation("20060102", month+"01", time.Local) endDay := startTime.AddDate(0, 1, -1).Format("2006-01-02") @@ -147,6 +142,7 @@ func (c *Checkin) saveToDB(user *qyweixin.UserCheckIn) error { checkin.EndTime = user.EndTime checkin.Month = user.Month checkin.Rawdata = user.Rawdata + checkin.CorpId = c.corp.Id if isNew { _, err = dao.NewCheckinDao().Create(checkin) diff --git a/worker/worker.go b/worker/worker.go index ae6d14a..7f3ca62 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -6,15 +6,18 @@ import ( "time" ) -func InitCorp(corpId int64) error { - +func InitCorp() { timezone, _ := time.LoadLocation("Asia/Shanghai") cron := gocron.NewScheduler(timezone) - staff := new(Staff) + InitCorp1000(cron) + InitCorp1002(cron) - cron.Every(1).Day().At("09:00").Do(func() { - go staff.MontorWorkAge(corpId) - }) + cron.StartAsync() +} + +func InitCorp1002(cron *gocron.Scheduler) { + corpId := int64(1002) + staff := new(Staff) //同步每日考勤数据 cron.Every(1).Day().At("05:00").Do(func() { @@ -29,7 +32,7 @@ func InitCorp(corpId int64) error { //每月1号同步上月考勤、补卡审批、请假审批、报销审批 cron.Every(1).Month(1).At("05:30").Do(func() { checkIn := NewCheckin(corpId) - checkIn.SyncCheckinMonth(corpId, "") + checkIn.SyncCheckinMonth("") lastMonth := time.Now().AddDate(0, -1, 0).Format("200601") approve := NewApproval(corpId) @@ -50,6 +53,48 @@ func InitCorp(corpId int64) error { go staff.SendStaffSalaryBill(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) //go staff.SendStaffSalaryBill(1002, time.Now().AddDate(0, -1, 0).Format("200601")) }) - cron.StartAsync() - return nil +} + +func InitCorp1000(cron *gocron.Scheduler) { + corpId := int64(1000) + staff := new(Staff) + cron.Every(1).Day().At("09:00").Do(func() { + go staff.MontorWorkAge(corpId) + }) + + //同步每日考勤数据 + cron.Every(1).Day().At("05:00").Do(func() { + checkIn := NewCheckin(corpId) + go checkIn.SyncCheckinDay(corpId, "") + }) + cron.Every(1).Day().At("08:00").Do(func() { + checkIn := NewCheckin(corpId) + go checkIn.MonitorCheckinDay(corpId, "") + }) + + //每月1号同步上月考勤、补卡审批、请假审批、报销审批 + cron.Every(1).Month(1).At("05:30").Do(func() { + checkIn := NewCheckin(corpId) + checkIn.SyncCheckinMonth("") + lastMonth := time.Now().AddDate(0, -1, 0).Format("200601") + + approve := NewApproval(corpId) + approve.Sync(corpId, lastMonth, model.ApprovalTypeCheckin) + approve.Sync(corpId, lastMonth, model.ApprovalTypeVacation) + approve.Sync(corpId, lastMonth, model.ApprovalTypeRefund) + approve.Sync(corpId, lastMonth, model.ApprovalTypePayment) + }) + + // 1号计算工资信息 + cron.Every(1).Month(1, 2, 3, 4, 5, 6, 7, 8, 9).At("06:00").Do(func() { + go staff.SyncStaffSalary(corpId, "") + //go staff.SyncStaffSalary(1002, "") + }) + + //10号晚上8点发送工资单 + cron.Every(1).Month(10).At("20:00").Do(func() { + go staff.SendStaffSalaryBill(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) + //go staff.SendStaffSalaryBill(1002, time.Now().AddDate(0, -1, 0).Format("200601")) + }) + }