new salary

This commit is contained in:
jiangyong27 2025-03-04 23:14:09 +08:00
parent 2f8381f2e9
commit e533de5422
29 changed files with 874 additions and 888 deletions

View File

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

View File

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

View File

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

View File

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

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

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 {
Id int64
CorpId int64
Username string
Day string
Month string

View File

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

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 (
"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)

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"`
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) {
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())
}

View File

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

View File

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

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

View File

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

View File

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

View File

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