new #2

Merged
jiangyong merged 2 commits from new into master 2025-03-04 23:28:33 +08:00
29 changed files with 874 additions and 888 deletions
Showing only changes of commit e533de5422 - Show all commits

View File

@ -4,6 +4,7 @@ import (
"enterprise/common/config" "enterprise/common/config"
"enterprise/common/global" "enterprise/common/global"
"enterprise/server" "enterprise/server"
_ "enterprise/service/salary_calculator"
"enterprise/worker" "enterprise/worker"
) )
@ -12,7 +13,7 @@ func main() {
config.LoadAliPay() config.LoadAliPay()
global.InitGlobal() global.InitGlobal()
if err := worker.Init(); err != nil { if err := worker.InitCorp(1000); err != nil {
panic(err) panic(err)
} }

View File

@ -78,11 +78,12 @@ func (d *ApprovalCheckinDao) GetByUsernameMonth(username, month string) ([]*mode
return u, nil 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 var u model.ApprovalCheckin
tx := GetDB().Table(d.TableName()) tx := GetDB().Table(d.TableName())
tx = tx.Where("checkin_date = ?", day) tx = tx.Where("checkin_date = ?", day)
tx = tx.Where("username = ?", username) tx = tx.Where("username = ?", username)
tx = tx.Where("corp_id = ?", corpId)
res := tx.First(&u) res := tx.First(&u)
if res.Error == gorm.ErrRecordNotFound { if res.Error == gorm.ErrRecordNotFound {

View File

@ -66,9 +66,10 @@ func (d *ApprovalVacationDao) GetBySpNo(corpId int64, spNo string) (*model.Appro
return &u, nil 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 var u []*model.ApprovalVacation
tx := GetDB().Table(d.TableName()) tx := GetDB().Table(d.TableName())
tx.Where("corp_id = ?", corpId)
if month != "" { if month != "" {
tx = tx.Where("month = ?", month) tx = tx.Where("month = ?", month)
} }
@ -83,9 +84,10 @@ func (d *ApprovalVacationDao) GetByUsername(username, month, day string) ([]*mod
return u, nil 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 var u model.ApprovalVacation
tx := GetDB().Table(d.TableName()) tx := GetDB().Table(d.TableName())
tx = tx.Where("corp_id = ?", corpId)
tx = tx.Where("vacation_date = ?", day) tx = tx.Where("vacation_date = ?", day)
tx = tx.Where("username = ?", username) tx = tx.Where("username = ?", username)

View File

@ -66,9 +66,10 @@ func (d *CheckinDao) GetByDay(userId, day string) (*model.Checkin, error) {
return &u, nil 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 var userCount []*model.UsernameCount
tx := GetDB().Table(d.TableName()) tx := GetDB().Table(d.TableName())
tx = tx.Where("corp_id = ?", corpId)
tx = tx.Where("month = ?", month) tx = tx.Where("month = ?", month)
tx.Select("username,COUNT(1) AS count") tx.Select("username,COUNT(1) AS count")
tx.Group("username") tx.Group("username")
@ -80,8 +81,9 @@ func (d *CheckinDao) CountUsername(month string) ([]*model.UsernameCount, error)
return userCount, nil 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 := GetDB().Table(d.TableName())
tx = tx.Where("corp_id = ?", corpId)
tx = tx.Where("month = ?", month) tx = tx.Where("month = ?", month)
tx = tx.Where("username = ?", username) tx = tx.Where("username = ?", username)
if filterException { if filterException {
@ -96,9 +98,10 @@ func (d *CheckinDao) Query(username, month string, filterException bool) ([]*mod
return u, nil 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 := GetDB().Table(d.TableName())
tx = tx.Where("day = ?", day) tx = tx.Where("day = ?", day)
tx.Where("corp_id = ?", corpId)
var u []*model.Checkin var u []*model.Checkin
tx = tx.Find(&u) tx = tx.Find(&u)

View File

@ -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
}

View File

@ -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
}

View File

@ -50,10 +50,11 @@ func (d *StaffSalaryDao) Get(id int64) (*model.StaffSalary, error) {
return &u, nil 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 var u model.StaffSalary
tx := GetDB().Table(d.TableName()) 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) tx = tx.Where("month = ?", month)
res := tx.First(&u) res := tx.First(&u)
if res.Error == gorm.ErrRecordNotFound { if res.Error == gorm.ErrRecordNotFound {
@ -66,17 +67,17 @@ func (d *StaffSalaryDao) GetBy(username, month string) (*model.StaffSalary, erro
return &u, nil 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 var u []*model.StaffSalary
tx := GetDB().Table(d.TableName()) tx := GetDB().Table(d.TableName())
tx.Where("corp_id = ?", corpId)
if month != "" { if month != "" {
tx = tx.Where("month = ?", month) tx = tx.Where("month = ?", month)
} }
if username != "" { if userId != 0 {
tx.Where("username = ?", username) tx.Where("user_id = ?", userId)
}
if master != nil {
tx.Where("master = ?", *master)
} }
tx.Order("month DESC") tx.Order("month DESC")

102
common/dao/staff_user.go Normal file
View File

@ -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
}

View File

@ -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
}

View File

@ -2,6 +2,7 @@ package model
type Checkin struct { type Checkin struct {
Id int64 Id int64
CorpId int64
Username string Username string
Day string Day string
Month string Month string

View File

@ -14,6 +14,9 @@ type CorpConfig struct {
TplIdRefund string `json:"tplid_refund"` TplIdRefund string `json:"tplid_refund"`
TplIdVacation string `json:"tplid_vacation"` TplIdVacation string `json:"tplid_vacation"`
TplIdPayment string `json:"tplid_payment"` TplIdPayment string `json:"tplid_payment"`
SocialDeduct string `json:"social_deduct"`
HouseDeduct string `json:"house_deduct"`
} }
type Corp struct { type Corp struct {

View File

@ -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)
}

View File

@ -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
}

View File

@ -3,49 +3,48 @@ package model
import ( import (
"encoding/json" "encoding/json"
butil "enterprise/base/util" butil "enterprise/base/util"
"github.com/smbrave/goutil"
"github.com/spf13/cast" "github.com/spf13/cast"
"strings" "strings"
) )
var (
StaffSalaryStatusNormal = 1
StaffSalaryStatusDisable = 2
)
type StaffSalary struct { type StaffSalary struct {
Id int64 Id int64
Username string CorpId int64
Master string UserId int64
UserName string
Month string Month string
BaseSalary float64 Salary float64
PerfSalary float64
AttendSalary float64 AttendSalary float64
RealSalary float64 TargetSalary float64
AwardSalary float64 AwardSalary float64
SocialInsurence float64 OtherSalary float64
HouseFund float64 ShouldDay int
PersonalTax float64 AttendDay float64
TotalDay float64 HolidayDay float64
RealDay float64 SocialDeduct float64
Holiday float64 HouseDeduct float64
PersonalDeduct float64
OtherDeduct float64
CreateTime int64 CreateTime int64
UpdateTime int64 UpdateTime int64
Extra string Extra string
} Comment 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)
} }
func (s *StaffSalary) GetShouldSalary() float64 { func (s *StaffSalary) GetShouldSalary() float64 {
if s.Master == "" { return butil.FloatCut(s.AttendSalary + s.TargetSalary + s.AwardSalary + s.OtherSalary)
return butil.FloatCut(s.AttendSalary + s.PerfSalary + s.AwardSalary)
} }
return butil.FloatCut(s.BaseSalary) 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 type StaffSalarySort []*StaffSalary
@ -57,6 +56,7 @@ func (s StaffSalarySort) Len() int {
func (s StaffSalarySort) Less(i, j int) bool { func (s StaffSalarySort) Less(i, j int) bool {
var iExtra map[string]string var iExtra map[string]string
var jExtra map[string]string var jExtra map[string]string
json.Unmarshal([]byte(s[i].Extra), &iExtra) json.Unmarshal([]byte(s[i].Extra), &iExtra)
json.Unmarshal([]byte(s[j].Extra), &jExtra) json.Unmarshal([]byte(s[j].Extra), &jExtra)

View File

@ -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
}

View File

@ -25,3 +25,16 @@ type UnifyAdData struct {
UpdateTime int64 `json:"updateTime"` UpdateTime int64 `json:"updateTime"`
Raw string `json:"raw"` 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
}

35
common/registry/salary.go Normal file
View File

@ -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)
}

View File

@ -35,15 +35,15 @@ func (s *Staff) Salary(ctx *gin.Context) {
} }
func (s *Staff) SalaryHistory(ctx *gin.Context) { func (s *Staff) SalaryHistory(ctx *gin.Context) {
new(service.StaffSalary).History(ctx)
} }
func (s *Staff) SyncStaffInfo(ctx *gin.Context) { func (s *Staff) SyncStaffInfo(ctx *gin.Context) {
go new(worker.Staff).SyncStaffInfo()
ctx.JSON(http.StatusOK, session.NewRspOk()) ctx.JSON(http.StatusOK, session.NewRspOk())
} }
func (s *Staff) SyncStaffSalary(ctx *gin.Context) { func (s *Staff) SyncStaffSalary(ctx *gin.Context) {
go new(worker.Staff).SyncStaffSalary("") go new(worker.Staff).SyncStaffSalary(1000, "")
ctx.JSON(http.StatusOK, session.NewRspOk()) ctx.JSON(http.StatusOK, session.NewRspOk())
} }

View File

@ -227,8 +227,8 @@ func (a *Approve) refundWxpay(data *model.ApprovalRefund) error {
return nil 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") cli := config.GetAliPayClient("batiao")
var req alipay.FundTransUniTransfer var req alipay.FundTransUniTransfer
req.Remark = "报销_" + data.SpNo req.Remark = "报销_" + data.SpNo
@ -240,7 +240,7 @@ func (a *Approve) refundAlipay(staff *model.StaffInfo, data *model.ApprovalRefun
payee := new(alipay.PayeeInfo) payee := new(alipay.PayeeInfo)
req.PayeeInfo = payee req.PayeeInfo = payee
payee.IdentityType = "ALIPAY_USER_ID" payee.IdentityType = "ALIPAY_USER_ID"
payee.Identity = staff.AlipayUid payee.Identity = userPayee.AlipayUid
rsp, err := cli.FundTransUniTransfer(context.Background(), req) rsp, err := cli.FundTransUniTransfer(context.Background(), req)
if err != nil { if err != nil {
@ -289,16 +289,16 @@ func (a *Approve) handleRefund(detail *qyweixin.ApproveDetail, spStatus int) {
if a.corp.Id != 1000 { if a.corp.Id != 1000 {
return return
} }
staff, err := dao.NewStaffInfoDao().GetByUsername(newData.Username) staffUser, err := dao.NewStaffUserDao().GetByUsername(1000, newData.Username)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
return return
} }
userPayee := staffUser.GetPayee()
// 支付费用 // 支付费用
var payType = "weixin" var payType = "weixin"
if staff != nil && staff.AlipayUid != "" { if userPayee.AlipayUid != "" {
err = a.refundAlipay(staff, newData) err = a.refundAlipay(staffUser, newData)
payType = "alipay" payType = "alipay"
} else { } else {
err = a.refundWxpay(newData) 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 { 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 { if err != nil {
return err return err
} }
@ -341,7 +341,8 @@ func (a *Approve) HandleRefundApprove(approve *model.ApprovalRefund) error {
// 支付费用 // 支付费用
var payType = "weixin" var payType = "weixin"
if staff != nil && staff.AlipayUid != "" { payee := staff.GetPayee()
if payee.AlipayUid != "" {
err = a.refundAlipay(staff, approve) err = a.refundAlipay(staff, approve)
payType = "alipay" payType = "alipay"
} else { } else {

View File

@ -1,12 +1,10 @@
package service package service
import ( import (
"encoding/json"
butil "enterprise/base/util" butil "enterprise/base/util"
"enterprise/common/config" "enterprise/common/config"
"enterprise/common/dao" "enterprise/common/dao"
"enterprise/common/model" "enterprise/common/model"
"enterprise/service"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -28,57 +26,9 @@ var (
type StaffSalary struct { 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) { func (s *StaffSalary) Agent(month string, ctx *gin.Context) {
xls := ctx.Query("xls") xls := ctx.Query("xls")
staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", nil) staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month)
if err != nil { if err != nil {
panic(config.ErrDb.New().Append(err)) panic(config.ErrDb.New().Append(err))
} }
@ -86,26 +36,27 @@ func (s *StaffSalary) Agent(month string, ctx *gin.Context) {
header := []string{"姓名", "身份证号", "电话", "应发工资", "社保扣除", "公积金扣除", "个税扣除", "实发工资"} header := []string{"姓名", "身份证号", "电话", "应发工资", "社保扣除", "公积金扣除", "个税扣除", "实发工资"}
datas := make([][]string, 0) datas := make([][]string, 0)
for _, staff := range staffSalarys { for _, staff := range staffSalarys {
baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) userInfo, err := dao.NewStaffUserDao().Get(staff.UserId)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue
} }
if baseInfo == nil { if userInfo == nil {
continue continue
} }
if staff.BaseSalary == 0 { userSalary := userInfo.GetSalary()
if userSalary.Base == "" {
continue continue
} }
item := make([]string, 0) item := make([]string, 0)
item = append(item, baseInfo.Realname) item = append(item, userInfo.Realname)
item = append(item, cast.ToString(baseInfo.Idno)) item = append(item, cast.ToString(userInfo.Idno))
item = append(item, cast.ToString(baseInfo.Phone)) item = append(item, cast.ToString(userInfo.Phone))
item = append(item, cast.ToString(staff.GetShouldSalary())) item = append(item, cast.ToString(staff.GetShouldSalary()))
item = append(item, cast.ToString(staff.SocialInsurence)) item = append(item, cast.ToString(staff.SocialDeduct))
item = append(item, cast.ToString(staff.HouseFund)) item = append(item, cast.ToString(staff.HouseDeduct))
item = append(item, cast.ToString(staff.PersonalTax)) item = append(item, cast.ToString(staff.PersonalDeduct))
item = append(item, cast.ToString(staff.GetRealSalary())) item = append(item, cast.ToString(staff.GetRealSalary()))
datas = append(datas, item) 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) { func (s *StaffSalary) Bank(month string, ctx *gin.Context) {
xls := ctx.Query("xls") xls := ctx.Query("xls")
staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", nil) staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month)
if err != nil { if err != nil {
panic(config.ErrDb.New().Append(err)) panic(config.ErrDb.New().Append(err))
} }
@ -148,22 +99,25 @@ func (s *StaffSalary) Bank(month string, ctx *gin.Context) {
header := []string{"账号", "户名", "金额", "开户行", "开户地", "收款备注"} header := []string{"账号", "户名", "金额", "开户行", "开户地", "收款备注"}
datas := make([][]string, 0) datas := make([][]string, 0)
for _, staff := range staffSalarys { for _, staff := range staffSalarys {
baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username) userInfo, err := dao.NewStaffUserDao().Get(staff.UserId)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue
} }
if baseInfo == nil { if userInfo == nil {
continue continue
} }
if staff.BaseSalary == 0 { userSalary := userInfo.GetSalary()
userPayee := userInfo.GetPayee()
if userSalary.Base == "" {
continue continue
} }
item := make([]string, 0) item := make([]string, 0)
item = append(item, baseInfo.BankCard) item = append(item, userPayee.BankCard)
item = append(item, baseInfo.Realname) item = append(item, userInfo.Realname)
item = append(item, cast.ToString(staff.GetRealSalary())) 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, "重庆市")
item = append(item, fmt.Sprintf("%s工资", month)) item = append(item, fmt.Sprintf("%s工资", month))
datas = append(datas, item) 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) { func (s *StaffSalary) Summary(month string, ctx *gin.Context) {
xls := ctx.Query("xls") xls := ctx.Query("xls")
masterBank := "" staffSalarys, err := dao.NewStaffSalaryDao().Query(1000, 0, month)
staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", &masterBank)
if err != nil { if err != nil {
panic(config.ErrDb.New().Append(err)) panic(config.ErrDb.New().Append(err))
} }
sort.Sort(model.StaffSalarySort(staffSalarys)) sort.Sort(model.StaffSalarySort(staffSalarys))
header := []string{"姓名", "身份证号", "入职日期", "转正日期", "基本工资", "绩效工资", "出勤工资", "附属工资", "奖金", "社保扣除", "公积金扣除", "个税扣除", "应出勤天数", "实际出勤天数", "出勤率", "补卡天数", "请假天数", "实发工资", "状态"} header := []string{"姓名", "入职日期", "转正日期", "基本工资", "绩效工资", "出勤收入", "绩效收入", "奖金收入", "其他收入", "社保扣除", "公积金扣除",
"个税扣除", "应出勤天数", "实际出勤天数", "请假天数", "实发工资", "状态"}
datas := make([][]string, 0) datas := make([][]string, 0)
summary := new(model.StaffSalary) summary := new(model.StaffSalary)
totalCount := 0 totalCount := 0
totalSlaveSalary := float64(0) for _, salary := range staffSalarys {
for _, staff := range staffSalarys { userInfo, err := dao.NewStaffUserDao().Get(salary.UserId)
baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue
} }
if baseInfo == nil { if userInfo == nil {
continue continue
} }
extra := make(map[string]interface{}) userSalary := userInfo.GetSalary()
json.Unmarshal([]byte(staff.Extra), &extra) //extra := make(map[string]interface{})
//json.Unmarshal([]byte(salary.Extra), &extra)
item := make([]string, 0) item := make([]string, 0)
item = append(item, baseInfo.Realname) item = append(item, userInfo.Realname)
item = append(item, cast.ToString(baseInfo.Idno)) item = append(item, cast.ToString(userInfo.EntryDate))
item = append(item, cast.ToString(baseInfo.EntryDate)) item = append(item, cast.ToString(userInfo.OfficialDate))
item = append(item, cast.ToString(baseInfo.OfficialDate)) item = append(item, userSalary.Base)
item = append(item, cast.ToString(staff.BaseSalary)) item = append(item, userSalary.Target)
item = append(item, cast.ToString(butil.FloatCut(staff.PerfSalary))) item = append(item, cast.ToString(butil.FloatCut(salary.AttendSalary)))
item = append(item, cast.ToString(butil.FloatCut(staff.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) item = append(item, cast.ToString(butil.FloatCut(salary.SocialDeduct)))
info, _ := dao.NewStaffInfoDao().GetByUsername(staff.Username) item = append(item, cast.ToString(butil.FloatCut(salary.HouseDeduct)))
if info != nil { item = append(item, cast.ToString(butil.FloatCut(salary.PersonalDeduct)))
slaveSalary = service.NewStaff(info, nil).GetSlaveSalary(month) item = append(item, cast.ToString(salary.ShouldDay))
}
item = append(item, cast.ToString(butil.FloatCut(slaveSalary))) item = append(item, cast.ToString(butil.FloatCut(salary.AttendDay)))
item = append(item, cast.ToString(butil.FloatCut(staff.AwardSalary))) item = append(item, cast.ToString(butil.FloatCut(salary.HolidayDay)))
item = append(item, cast.ToString(staff.SocialInsurence)) item = append(item, cast.ToString(salary.GetRealSalary()))
item = append(item, cast.ToString(staff.HouseFund)) if cast.ToFloat64(salary.ShouldDay) != cast.ToFloat64(salary.AttendDay)+cast.ToFloat64(salary.HolidayDay) {
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, "【异常】") item = append(item, "【异常】")
} else { } else {
item = append(item, "") item = append(item, "")
} }
//item = append(item, fmt.Sprintf("https://e.batiao8.com/staff/salary/history?username=%s", baseInfo.Username))
totalCount += 1 totalCount += 1
totalSlaveSalary += slaveSalary
datas = append(datas, item) datas = append(datas, item)
summary.BaseSalary += staff.BaseSalary summary.Salary += salary.Salary
summary.PerfSalary += staff.PerfSalary
summary.AttendSalary += staff.AttendSalary summary.TargetSalary += salary.TargetSalary
summary.AwardSalary += staff.AwardSalary summary.AttendSalary += salary.AttendSalary
summary.SocialInsurence += staff.SocialInsurence summary.AwardSalary += salary.AwardSalary
summary.PersonalTax += staff.PersonalTax summary.OtherSalary += salary.OtherSalary
summary.Holiday += staff.Holiday
summary.HouseFund += staff.HouseFund 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.HolidayDay = butil.FloatCut(summary.HolidayDay)
summary.BaseSalary = butil.FloatCut(summary.BaseSalary) summary.Salary = butil.FloatCut(summary.Salary)
summary.PerfSalary = butil.FloatCut(summary.PerfSalary) summary.TargetSalary = butil.FloatCut(summary.TargetSalary)
summary.AttendSalary = butil.FloatCut(summary.AttendSalary) summary.AttendSalary = butil.FloatCut(summary.AttendSalary)
summary.AwardSalary = butil.FloatCut(summary.AwardSalary) summary.AwardSalary = butil.FloatCut(summary.AwardSalary)
summary.SocialInsurence = butil.FloatCut(summary.SocialInsurence) summary.SocialDeduct = butil.FloatCut(summary.SocialDeduct)
summary.HouseFund = butil.FloatCut(summary.HouseFund) summary.HouseDeduct = butil.FloatCut(summary.HouseDeduct)
summary.PersonalTax = butil.FloatCut(summary.PersonalTax) summary.PersonalDeduct = butil.FloatCut(summary.PersonalDeduct)
datas = append(datas, []string{"合计", cast.ToString(totalCount), "-", "-", summary.OtherDeduct = butil.FloatCut(summary.OtherDeduct)
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), datas = append(datas, []string{"合计", cast.ToString(totalCount), "-",
cast.ToString(summary.PersonalTax), "-", "-", "-", "-", cast.ToString(summary.Holiday), cast.ToString(summary.Salary), "-", cast.ToString(summary.AttendSalary), cast.ToString(summary.TargetSalary), cast.ToString(summary.AwardSalary), cast.ToString(summary.OtherSalary),
cast.ToString(butil.FloatCut(summary.GetRealSalary() + totalSlaveSalary)), "-"}) cast.ToString(summary.SocialDeduct), cast.ToString(summary.HouseDeduct), cast.ToString(summary.PersonalDeduct),
"-", "-", cast.ToString(summary.HolidayDay),
cast.ToString(butil.FloatCut(summary.GetRealSalary())), "-"})
if xls != "" { if xls != "" {
filename := fmt.Sprintf("summary_%s.xlsx", time.Now().Format("20060102_150405")) filename := fmt.Sprintf("summary_%s.xlsx", time.Now().Format("20060102_150405"))

View File

@ -0,0 +1,8 @@
package salary_calculator
import "enterprise/common/registry"
func init() {
registry.RegisterSalaryCalculator("1000", NewSalaryCalculator1000)
registry.RegisterSalaryCalculator("1000_wujiefeng", NewSalaryCalculator1000Wujiefeng)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}

220
service/staff_salary.go Normal file
View File

@ -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
}

View File

@ -1,7 +1,6 @@
package worker package worker
import ( import (
"enterprise/common/config"
"enterprise/common/dao" "enterprise/common/dao"
"enterprise/common/model" "enterprise/common/model"
"git.u8t.cn/open/gosdk/qyweixin" "git.u8t.cn/open/gosdk/qyweixin"
@ -14,7 +13,8 @@ type Approval struct {
corpConfig *model.CorpConfig corpConfig *model.CorpConfig
} }
func NewApproval(corp *model.Corp) *Approval { func NewApproval(corpId int64) *Approval {
corp, _ := dao.NewCorpDao().Get(corpId)
return &Approval{ return &Approval{
corp: corp, corp: corp,
corpConfig: corp.GetConfig(), corpConfig: corp.GetConfig(),
@ -33,10 +33,16 @@ func (s *Approval) getTemplateId(tp string) string {
return "" 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) 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) startTime, _ := time.ParseInLocation("200601", month, time.Local)
endTime := startTime.AddDate(0, 1, 0) endTime := startTime.AddDate(0, 1, 0)
spNos, err := approve.GetList(startTime.Unix(), endTime.Unix()-1, templateId) spNos, err := approve.GetList(startTime.Unix(), endTime.Unix()-1, templateId)

View File

@ -1,7 +1,6 @@
package worker package worker
import ( import (
"enterprise/common/config"
"enterprise/common/dao" "enterprise/common/dao"
"enterprise/common/global" "enterprise/common/global"
"enterprise/common/model" "enterprise/common/model"
@ -18,26 +17,33 @@ type Checkin struct {
corpConfig *model.CorpConfig corpConfig *model.CorpConfig
} }
func NewCheckin(corp *model.Corp) *Checkin { func NewCheckin(corpId int64) *Checkin {
corp, _ := dao.NewCorpDao().Get(corpId)
return &Checkin{ return &Checkin{
corp: corp, corp: corp,
corpConfig: corp.GetConfig(), corpConfig: corp.GetConfig(),
} }
} }
func (c *Checkin) SyncCheckinMonth(month string) error { func (c *Checkin) SyncCheckinMonth(corpId int64, month string) error {
if month == "" { if month == "" {
month = time.Now().AddDate(0, -1, 0).Format("200601") 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) startTime, _ := time.ParseInLocation("20060102", month+"01", time.Local)
endDay := startTime.AddDate(0, 1, -1).Format("2006-01-02") endDay := startTime.AddDate(0, 1, -1).Format("2006-01-02")
startDay := startTime.Format("2006-01-02") startDay := startTime.Format("2006-01-02")
qyw := qyweixin.NewAppCheckin(&qyweixin.AppConfig{ qyw := qyweixin.NewAppCheckin(&qyweixin.AppConfig{
Corpid: cfg.QyWeixin.Corpid, Corpid: cfg.CorpId,
Secret: cfg.QyWeixin.EnterpriseSecret, Secret: cfg.EnterpriseSecret,
Agent: cfg.QyWeixin.EnterpriseAgent, Agent: cfg.EnterpriseAgent,
}) })
users, err := qyw.GetCheckinEmployee(nil) users, err := qyw.GetCheckinEmployee(nil)
if err != nil { if err != nil {
@ -56,12 +62,18 @@ func (c *Checkin) SyncCheckinMonth(month string) error {
return nil return nil
} }
func (c *Checkin) SyncCheckinDay(day string) { func (c *Checkin) SyncCheckinDay(corpId int64, day string) {
cfg := config.GetConfig() 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{ qyw := qyweixin.NewAppCheckin(&qyweixin.AppConfig{
Corpid: cfg.QyWeixin.Corpid, Corpid: cfg.CorpId,
Secret: cfg.QyWeixin.EnterpriseSecret, Secret: cfg.EnterpriseSecret,
Agent: cfg.QyWeixin.EnterpriseAgent, Agent: cfg.EnterpriseAgent,
}) })
if day == "" { if day == "" {
day = time.Now().AddDate(0, 0, -1).Format("2006-01-02") day = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
@ -84,11 +96,11 @@ func (c *Checkin) SyncCheckinDay(day string) {
return return
} }
func (c *Checkin) MonitorCheckinDay(day string) { func (c *Checkin) MonitorCheckinDay(corpId int64, day string) {
if day == "" { if day == "" {
day = time.Now().AddDate(0, 0, -1).Format("2006-01-02") 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 { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
return return
@ -97,7 +109,7 @@ func (c *Checkin) MonitorCheckinDay(day string) {
if checkin.Exception == "" { if checkin.Exception == "" {
continue continue
} }
approvals, err := dao.NewApprovalVacationDao().GetByUsername(checkin.Username, "", checkin.Day) approvals, err := dao.NewApprovalVacationDao().GetByUsername(corpId, checkin.Username, "", checkin.Day)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue

View File

@ -1,13 +1,11 @@
package worker package worker
import ( import (
"enterprise/common/config"
"enterprise/common/dao" "enterprise/common/dao"
"enterprise/common/global" "enterprise/common/global"
"enterprise/common/model" "enterprise/common/model"
"enterprise/service" "enterprise/service"
"fmt" "fmt"
"git.u8t.cn/open/gosdk/qyweixin"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/smbrave/goutil" "github.com/smbrave/goutil"
"github.com/spf13/cast" "github.com/spf13/cast"
@ -18,8 +16,8 @@ import (
type Staff struct { type Staff struct {
} }
func (s *Staff) MontorWorkAge() { func (s *Staff) MontorWorkAge(corpId int64) {
staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal) staffs, err := dao.NewStaffUserDao().Query(corpId, model.StaffUserStatusOnline)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
return return
@ -38,13 +36,15 @@ func (s *Staff) MontorWorkAge() {
entryMonth := (nowDate.Year()-entryDate.Year())*12 + int(nowDate.Month()) - int(entryDate.Month()) entryMonth := (nowDate.Year()-entryDate.Year())*12 + int(nowDate.Month()) - int(entryDate.Month())
officalDay := (OfficialDate.Unix() - nowDate.Unix()) / 86400 officalDay := (OfficialDate.Unix() - nowDate.Unix()) / 86400
log.Infof("staff[%s] entryDate[%s] spanMonth[%.1f]", staff.Username, staff.EntryDate, float64(entryMonth)/12.0) 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 { if nowDate.Day() == 1 && entryMonth%6 == 0 {
message := make([]string, 0) message := make([]string, 0)
message = append(message, fmt.Sprintf("【员工半年提醒】[%s]", staff.Realname)) message = append(message, fmt.Sprintf("【员工半年提醒】[%s]", staff.Realname))
message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate)) message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate))
message = append(message, fmt.Sprintf("入职年限:%.1f", float64(entryMonth)/12)) message = append(message, fmt.Sprintf("入职年限:%.1f", float64(entryMonth)/12))
message = append(message, fmt.Sprintf("基本工资:%s", staff.BaseSalary)) message = append(message, fmt.Sprintf("基本工资:%s", salary.Base))
message = append(message, fmt.Sprintf("绩效工资:%s", staff.PerfSalary)) message = append(message, fmt.Sprintf("绩效工资:%s", salary.Target))
message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno)) message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno))
if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { 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.Realname))
message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate)) message = append(message, fmt.Sprintf("入职时间:%s", staff.EntryDate))
message = append(message, fmt.Sprintf("转正时间:%s", staff.OfficialDate)) message = append(message, fmt.Sprintf("转正时间:%s", staff.OfficialDate))
message = append(message, fmt.Sprintf("基本工资:%s", staff.BaseSalary)) message = append(message, fmt.Sprintf("基本工资:%s", salary.Base))
message = append(message, fmt.Sprintf("绩效工资:%s", staff.PerfSalary)) message = append(message, fmt.Sprintf("绩效工资:%s", salary.Target))
message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno)) message = append(message, fmt.Sprintf("身份证号:%s", staff.Idno))
if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil {
log.Errorf("send message error :%s", err.Error()) log.Errorf("send message error :%s", err.Error())
} }
} }
} }
} }
func (s *Staff) SendStaffSalaryBill(month string) { func (s *Staff) SendStaffSalaryBill(corpId int64, month string) {
masterBlank := "" staffSalarys, err := dao.NewStaffSalaryDao().Query(corpId, 0, month)
staffSalarys, err := dao.NewStaffSalaryDao().Query(month, "", &masterBlank)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
return return
} }
for _, staffSalary := range staffSalarys { for _, staffSalary := range staffSalarys {
if staffSalary.BaseSalary < 0.1 { if staffSalary.Salary < 0.1 {
continue continue
} }
userConfig, err := dao.NewUserConfigDao().GetByUsername(staffSalary.Username) user, err := dao.NewStaffUserDao().Get(staffSalary.UserId)
if err != nil { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue
} }
message := make([]string, 0) message := make([]string, 0)
message = append(message, fmt.Sprintf("【工资单】[%s][%s]", staffSalary.Username, month)) message = append(message, fmt.Sprintf("【工资单】[%s][%s]", user.Username, month))
message = append(message, fmt.Sprintf("基本工资:%.2f", staffSalary.BaseSalary)) message = append(message, fmt.Sprintf("基本工资:%.2f", staffSalary.Salary))
if staffSalary.AttendSalary >= 0.1 {
message = append(message, fmt.Sprintf("出勤工资:%.2f", staffSalary.AttendSalary)) message = append(message, fmt.Sprintf("出勤工资:%.2f", staffSalary.AttendSalary))
}
if staffSalary.AwardSalary >= 0.1 { 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))
} }
//附属工资 message = append(message, fmt.Sprintf("社保扣除:%.2f", staffSalary.SocialDeduct+staffSalary.HouseDeduct))
var slaveSalary float64 = 0 message = append(message, fmt.Sprintf("个税扣除:%.2f", staffSalary.PersonalDeduct))
staff, _ := dao.NewStaffInfoDao().GetByUsername(staffSalary.Username) message = append(message, fmt.Sprintf("实发工资:%.2f", staffSalary.GetRealSalary()))
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))
if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil {
log.Errorf("send message error :%s", err.Error()) 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() { func (s *Staff) SyncStaffSalary(corpId int64, month string) {
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) {
if month == "" { if month == "" {
month = time.Now().AddDate(0, -1, 0).Format("2006-01") month = time.Now().AddDate(0, -1, 0).Format("2006-01")
} }
month = strings.ReplaceAll(month, "-", "") month = strings.ReplaceAll(month, "-", "")
staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal) staffs, err := dao.NewStaffUserDao().Query(corpId, 0)
if err != nil { if err != nil {
log.Errorf("query staff db error :%s", err.Error()) log.Errorf("query staff db error :%s", err.Error())
return return
} }
for _, staff := range staffs { for _, staff := range staffs {
// 已离职的员工不处理 // 已离职的员工不处理
if staff.LeaveDate != "" { if staff.LeaveDate != "" {
leaveTime, _ := time.ParseInLocation("2006-01-02", staff.LeaveDate, time.Local) 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 { if err != nil {
log.Errorf("db error :%s", err.Error()) log.Errorf("db error :%s", err.Error())
continue continue
} }
//附属员工直接生成工资单 staffService := service.NewStaffSalary(staff)
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) salary, err = staffService.CalcSalary(salary, month)
if err != nil { if err != nil {
log.Errorf("username[%s] staffService.CalcSalary error :%s", staff.Username, err.Error()) log.Errorf("username[%s] staffService.CalcSalary error :%s", staff.Username, err.Error())
continue continue
} }
if salary == nil {
continue
} }
if salary.Id == 0 { if salary.Id == 0 {

View File

@ -1,56 +1,54 @@
package worker package worker
import ( import (
"enterprise/common/dao"
"enterprise/common/model" "enterprise/common/model"
"github.com/go-co-op/gocron" "github.com/go-co-op/gocron"
"time" "time"
) )
func Init() error { func InitCorp(corpId int64) error {
corp, _ := dao.NewCorpDao().Get(1000)
timezone, _ := time.LoadLocation("Asia/Shanghai") timezone, _ := time.LoadLocation("Asia/Shanghai")
cron := gocron.NewScheduler(timezone) cron := gocron.NewScheduler(timezone)
staff := new(Staff) 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() { 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() { 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() { cron.Every(1).Day().At("08:00").Do(func() {
go checkIn.MonitorCheckinDay("") checkIn := NewCheckin(corpId)
go checkIn.MonitorCheckinDay(corpId, "")
}) })
//每月1号同步上月考勤、补卡审批、请假审批、报销审批 //每月1号同步上月考勤、补卡审批、请假审批、报销审批
cron.Every(1).Month(1).At("05:30").Do(func() { 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") lastMonth := time.Now().AddDate(0, -1, 0).Format("200601")
checkIn.SyncCheckinMonth("")
approve := NewApproval(corp) approve := NewApproval(corpId)
approve.Sync(lastMonth, model.ApprovalTypeCheckin) approve.Sync(corpId, lastMonth, model.ApprovalTypeCheckin)
approve.Sync(lastMonth, model.ApprovalTypeVacation) approve.Sync(corpId, lastMonth, model.ApprovalTypeVacation)
approve.Sync(lastMonth, model.ApprovalTypeRefund) approve.Sync(corpId, lastMonth, model.ApprovalTypeRefund)
approve.Sync(lastMonth, model.ApprovalTypePayment) approve.Sync(corpId, lastMonth, model.ApprovalTypePayment)
}) })
// 1号计算工资信息 // 1号计算工资信息
cron.Every(1).Month(1, 2, 3, 4, 5, 6, 7, 8, 9).At("06:00").Do(func() { 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点发送工资单 //10号晚上8点发送工资单
cron.Every(1).Month(10).At("20:00").Do(func() { 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() cron.StartAsync()
return nil return nil