award
This commit is contained in:
parent
73a3e853df
commit
bbc9c78499
|
@ -55,11 +55,12 @@ type WxPay struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Server *Server `toml:"server"`
|
Server *Server `toml:"server"`
|
||||||
Mysql *Mysql `toml:"mysql"`
|
Mysql *Mysql `toml:"mysql"`
|
||||||
Redis *Redis `toml:"redis"`
|
UnifyMysql *Mysql `toml:"unify_mysql"`
|
||||||
QyWeixin *QyWeixin `toml:"qyweixin"`
|
Redis *Redis `toml:"redis"`
|
||||||
WxPay *WxPay `toml:"wxpay"`
|
QyWeixin *QyWeixin `toml:"qyweixin"`
|
||||||
|
WxPay *WxPay `toml:"wxpay"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEnv() string {
|
func GetEnv() string {
|
||||||
|
|
|
@ -6,5 +6,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ContextParam = "context_params"
|
ContextParam = "context_params"
|
||||||
|
SalarySocialInsurence float64 = 462.7
|
||||||
|
SalaryHouseFund float64 = 105
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,13 +3,18 @@ package dao
|
||||||
import "gorm.io/gorm"
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
|
unifyDB *gorm.DB
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetDB(d *gorm.DB) {
|
func SetDB(d *gorm.DB) {
|
||||||
db = d
|
db = d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetUnifyDB(d *gorm.DB) {
|
||||||
|
unifyDB = d
|
||||||
|
}
|
||||||
|
|
||||||
func GetDB() *gorm.DB {
|
func GetDB() *gorm.DB {
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,16 @@ func NewUserConfigDao() *UserConfigDao {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) TableName() string {
|
func (d *UserConfigDao) TableName() string {
|
||||||
return "user_config"
|
return "staff_config"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) Create(o *model.UserConfig) (int64, error) {
|
func (d *UserConfigDao) Create(o *model.StaffConfig) (int64, error) {
|
||||||
o.CreateTime = time.Now().Unix()
|
o.CreateTime = time.Now().Unix()
|
||||||
res := GetDB().Table(d.TableName()).Create(o)
|
res := GetDB().Table(d.TableName()).Create(o)
|
||||||
return o.Id, res.Error
|
return o.Id, res.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) Update(o *model.UserConfig) error {
|
func (d *UserConfigDao) Update(o *model.StaffConfig) error {
|
||||||
o.UpdateTime = time.Now().Unix()
|
o.UpdateTime = time.Now().Unix()
|
||||||
tx := GetDB().Table(d.TableName())
|
tx := GetDB().Table(d.TableName())
|
||||||
res := tx.Save(o)
|
res := tx.Save(o)
|
||||||
|
@ -31,12 +31,12 @@ func (d *UserConfigDao) Update(o *model.UserConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) Delete(id int64) error {
|
func (d *UserConfigDao) Delete(id int64) error {
|
||||||
res := GetDB().Table(d.TableName()).Delete(&model.UserConfig{}, id)
|
res := GetDB().Table(d.TableName()).Delete(&model.StaffConfig{}, id)
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) Get(id int64) (*model.UserConfig, error) {
|
func (d *UserConfigDao) Get(id int64) (*model.StaffConfig, error) {
|
||||||
var u model.UserConfig
|
var u model.StaffConfig
|
||||||
tx := GetDB().Table(d.TableName())
|
tx := GetDB().Table(d.TableName())
|
||||||
tx = tx.Where("id = ?", id)
|
tx = tx.Where("id = ?", id)
|
||||||
res := tx.First(&u)
|
res := tx.First(&u)
|
||||||
|
@ -50,8 +50,8 @@ func (d *UserConfigDao) Get(id int64) (*model.UserConfig, error) {
|
||||||
return &u, nil
|
return &u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) GetByUsername(username string) (*model.UserConfig, error) {
|
func (d *UserConfigDao) GetByUsername(username string) (*model.StaffConfig, error) {
|
||||||
var u model.UserConfig
|
var u model.StaffConfig
|
||||||
tx := GetDB().Table(d.TableName())
|
tx := GetDB().Table(d.TableName())
|
||||||
tx = tx.Where("username = ?", username)
|
tx = tx.Where("username = ?", username)
|
||||||
res := tx.First(&u)
|
res := tx.First(&u)
|
||||||
|
@ -65,8 +65,8 @@ func (d *UserConfigDao) GetByUsername(username string) (*model.UserConfig, error
|
||||||
return &u, nil
|
return &u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *UserConfigDao) Query(status int) ([]*model.UserConfig, error) {
|
func (d *UserConfigDao) Query(status int) ([]*model.StaffConfig, error) {
|
||||||
var u []*model.UserConfig
|
var u []*model.StaffConfig
|
||||||
tx := GetDB().Table(d.TableName())
|
tx := GetDB().Table(d.TableName())
|
||||||
|
|
||||||
if status != 0 {
|
if status != 0 {
|
|
@ -0,0 +1,43 @@
|
||||||
|
package dao
|
||||||
|
|
||||||
|
import (
|
||||||
|
"enterprise/common/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UnifyAdData struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnifyAdData() *UnifyAdData {
|
||||||
|
return &UnifyAdData{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *UnifyAdData) TableName() string {
|
||||||
|
return "unify_ad_data"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *UnifyAdData) QueryOwnerData(owner, startDay, endDay string) ([]*model.UnifyAdData, error) {
|
||||||
|
tx := unifyDB.Table(d.TableName())
|
||||||
|
|
||||||
|
var o []*model.UnifyAdData
|
||||||
|
|
||||||
|
tx = tx.Where("data_type = ?", "account_report")
|
||||||
|
tx = tx.Where("owner = ?", owner)
|
||||||
|
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
|
||||||
|
}
|
|
@ -69,6 +69,16 @@ func initDB() error {
|
||||||
}
|
}
|
||||||
db.Logger = &DBLogger{threshold: int64(2000)}
|
db.Logger = &DBLogger{threshold: int64(2000)}
|
||||||
dao.SetDB(db)
|
dao.SetDB(db)
|
||||||
|
|
||||||
|
unifyDsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", cfg.UnifyMysql.User,
|
||||||
|
cfg.UnifyMysql.Pass, cfg.UnifyMysql.Host, cfg.UnifyMysql.Port, cfg.UnifyMysql.Db)
|
||||||
|
db, err = gorm.Open(mysql.Open(unifyDsn), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("open dsn[%s] error[%s]", dsn, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
db.Logger = &DBLogger{threshold: int64(2000)}
|
||||||
|
dao.SetUnifyDB(db)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ type StaffInfo struct {
|
||||||
StaffType string
|
StaffType string
|
||||||
Phone string
|
Phone string
|
||||||
Idno string
|
Idno string
|
||||||
Salary string
|
BaseSalary string
|
||||||
|
PerfSalary string
|
||||||
EntryDate string
|
EntryDate string
|
||||||
OfficialDate string
|
OfficialDate string
|
||||||
LeaveDate string
|
LeaveDate string
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import butil "enterprise/base/util"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
butil "enterprise/base/util"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
StaffSalaryStatusNormal = 1
|
StaffSalaryStatusNormal = 1
|
||||||
|
@ -12,10 +17,12 @@ type StaffSalary struct {
|
||||||
Username string
|
Username string
|
||||||
Month string
|
Month string
|
||||||
BaseSalary float64
|
BaseSalary float64
|
||||||
|
PerfSalary float64
|
||||||
AttendSalary float64
|
AttendSalary float64
|
||||||
RealSalary float64
|
RealSalary float64
|
||||||
AwardSalary float64
|
AwardSalary float64
|
||||||
SocialInsurence float64
|
SocialInsurence float64
|
||||||
|
HouseFund float64
|
||||||
PersonalTax float64
|
PersonalTax float64
|
||||||
TotalDay float64
|
TotalDay float64
|
||||||
RealDay float64
|
RealDay float64
|
||||||
|
@ -26,5 +33,28 @@ type StaffSalary struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StaffSalary) GetRealSalary() float64 {
|
func (s *StaffSalary) GetRealSalary() float64 {
|
||||||
return butil.FloatCut(s.AttendSalary + s.AwardSalary - s.SocialInsurence - s.PersonalTax)
|
return butil.FloatCut(s.AttendSalary + s.PerfSalary + s.AwardSalary - s.SocialInsurence - s.PersonalTax - s.HouseFund)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StaffSalary) GetShouldSalary() float64 {
|
||||||
|
return butil.FloatCut(s.AttendSalary + s.PerfSalary + s.AwardSalary)
|
||||||
|
}
|
||||||
|
|
||||||
|
type StaffSalarySort []*StaffSalary
|
||||||
|
|
||||||
|
func (s StaffSalarySort) Len() int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
return cast.ToInt64(strings.ReplaceAll(iExtra["entryDate"], "-", "")) < cast.ToInt64(strings.ReplaceAll(jExtra["entryDate"], "-", ""))
|
||||||
|
|
||||||
|
}
|
||||||
|
func (s StaffSalarySort) Swap(i, j int) {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
type UnifyAdData struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
AppId int64 `json:"appId"`
|
||||||
|
Day string `json:"day"`
|
||||||
|
AccountType string `json:"accountType"`
|
||||||
|
AccountName string `json:"accountName"`
|
||||||
|
AccountId string `json:"accountId"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
Balance int64 `json:"balance"`
|
||||||
|
DataType string `json:"dataType"`
|
||||||
|
DataName string `json:"dataName"`
|
||||||
|
DataId string `json:"dataId"`
|
||||||
|
Cost int64 `json:"cost"`
|
||||||
|
ReturnCost int64 `json:"return_cost"`
|
||||||
|
PayAmount int64 `json:"payAmount"`
|
||||||
|
Impression int64 `json:"impression"`
|
||||||
|
Click int64 `json:"click"`
|
||||||
|
Download int64 `json:"download"`
|
||||||
|
Active int64 `json:"active"`
|
||||||
|
Register int64 `json:"register"`
|
||||||
|
Pay int64 `json:"pay"`
|
||||||
|
CreateTime int64 `json:"createTime"`
|
||||||
|
UpdateTime int64 `json:"updateTime"`
|
||||||
|
Raw string `json:"raw"`
|
||||||
|
}
|
|
@ -1,23 +1,25 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import "encoding/json"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/smbrave/goutil"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
CheckinOndutyMoneyEnable = "checkin.onduty.money.enable" //上班打卡红包
|
|
||||||
CheckinOffdutyMoneyEnable = "checkin.offduty.money.enable" //下班打卡红包
|
|
||||||
CheckinOndutyMoney = "checkin.onduty.money" //上班打卡金额
|
|
||||||
CheckinOffdutyMoney = "checkin.offduty.money" //下班打卡金额
|
|
||||||
StaffSalaryExpDiscount = "staff.salary.exp.discount" //试用期薪资折扣
|
StaffSalaryExpDiscount = "staff.salary.exp.discount" //试用期薪资折扣
|
||||||
StaffSalarySocialInsurence = "staff.salary.social.insurence" //社保扣除金额
|
StaffSalarySocialInsurence = "staff.salary.social.insurence" //社保扣除金额
|
||||||
|
StaffSalaryHouseFund = "staff.salary.house.fund" //住房公积金
|
||||||
StaffSalaryPerDay = "staff.salary.per.day" //按天计算的工资
|
StaffSalaryPerDay = "staff.salary.per.day" //按天计算的工资
|
||||||
StaffSalaryNotify = "staff.salary.notify" //是否发送工资单
|
StaffSalaryNotify = "staff.salary.notify" //是否发送工资单
|
||||||
|
StaffSalaryProfitDeduct = "staff.salary.profit.deduct" //广告收益提成
|
||||||
|
StaffSalaryProfitTarget = "staff.salary.profit.target" //广告收益目标
|
||||||
)
|
)
|
||||||
var (
|
var (
|
||||||
UserConfigStatusNormal = 1
|
StaffConfigStatusNormal = 1
|
||||||
UserConfigStatusDisable = 2
|
StaffConfigStatusDisable = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserConfig struct {
|
type StaffConfig struct {
|
||||||
Id int64
|
Id int64
|
||||||
Username string
|
Username string
|
||||||
Config string
|
Config string
|
||||||
|
@ -26,8 +28,14 @@ type UserConfig struct {
|
||||||
UpdateTime int64
|
UpdateTime int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserConfig) Get(key string) interface{} {
|
func (u *StaffConfig) Get(key string) interface{} {
|
||||||
config := make(map[string]interface{})
|
config := make(map[string]interface{})
|
||||||
json.Unmarshal([]byte(u.Config), &config)
|
json.Unmarshal([]byte(u.Config), &config)
|
||||||
return config[key]
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,14 @@ user = "root"
|
||||||
pass = "ZW5aaGVuMIIBIj"
|
pass = "ZW5aaGVuMIIBIj"
|
||||||
db = "enterprise"
|
db = "enterprise"
|
||||||
|
|
||||||
|
[unify_mysql]
|
||||||
|
host = "192.168.2.50"
|
||||||
|
port = 13307
|
||||||
|
user = "unify"
|
||||||
|
pass = "MDE2LCJIYXNoSWQiOjY"
|
||||||
|
db = "unify"
|
||||||
|
threshold = 5000
|
||||||
|
|
||||||
[redis]
|
[redis]
|
||||||
addr="192.168.2.50:6379"
|
addr="192.168.2.50:6379"
|
||||||
db=0
|
db=0
|
||||||
|
|
|
@ -10,6 +10,14 @@ user = "root"
|
||||||
pass = "ZW5aaGVuMIIBIj"
|
pass = "ZW5aaGVuMIIBIj"
|
||||||
db = "enterprise"
|
db = "enterprise"
|
||||||
|
|
||||||
|
[unify_mysql]
|
||||||
|
host = "10.0.2.157"
|
||||||
|
port = 3307
|
||||||
|
user = "unify"
|
||||||
|
pass = "MDE2LCJIYXNoSWQiOjY"
|
||||||
|
db = "unify"
|
||||||
|
threshold = 5000
|
||||||
|
|
||||||
[redis]
|
[redis]
|
||||||
addr="127.0.0.1:6379"
|
addr="127.0.0.1:6379"
|
||||||
db=0
|
db=0
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module enterprise
|
||||||
go 1.21.6
|
go 1.21.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.u8t.cn/open/gosdk v0.0.0-20240927033033-8d021096f778
|
git.u8t.cn/open/gosdk v0.0.0-20241104101317-10492bab9fd7
|
||||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.27
|
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.27
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
excelize "github.com/xuri/excelize/v2"
|
excelize "github.com/xuri/excelize/v2"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -33,7 +34,7 @@ func (s *StaffSalary) Agent(month string, ctx *gin.Context) {
|
||||||
panic(config.ErrDb.New().Append(err))
|
panic(config.ErrDb.New().Append(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
baseInfo, err := dao.NewStaffInfoDao().GetByUsername(staff.Username)
|
||||||
|
@ -51,10 +52,9 @@ func (s *StaffSalary) Agent(month string, ctx *gin.Context) {
|
||||||
item = append(item, baseInfo.Realname)
|
item = append(item, baseInfo.Realname)
|
||||||
item = append(item, cast.ToString(baseInfo.Idno))
|
item = append(item, cast.ToString(baseInfo.Idno))
|
||||||
item = append(item, cast.ToString(baseInfo.Phone))
|
item = append(item, cast.ToString(baseInfo.Phone))
|
||||||
item = append(item, cast.ToString(staff.BaseSalary))
|
item = append(item, cast.ToString(staff.GetShouldSalary()))
|
||||||
item = append(item, cast.ToString(staff.AttendSalary))
|
|
||||||
item = append(item, cast.ToString(staff.AwardSalary))
|
|
||||||
item = append(item, cast.ToString(staff.SocialInsurence))
|
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.PersonalTax))
|
||||||
item = append(item, cast.ToString(staff.GetRealSalary()))
|
item = append(item, cast.ToString(staff.GetRealSalary()))
|
||||||
|
|
||||||
|
@ -152,8 +152,9 @@ func (s *StaffSalary) Summary(month string, ctx *gin.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(config.ErrDb.New().Append(err))
|
panic(config.ErrDb.New().Append(err))
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
for _, staff := range staffSalarys {
|
for _, staff := range staffSalarys {
|
||||||
|
@ -173,12 +174,15 @@ func (s *StaffSalary) Summary(month string, ctx *gin.Context) {
|
||||||
item = append(item, cast.ToString(baseInfo.EntryDate))
|
item = append(item, cast.ToString(baseInfo.EntryDate))
|
||||||
item = append(item, cast.ToString(baseInfo.OfficialDate))
|
item = append(item, cast.ToString(baseInfo.OfficialDate))
|
||||||
item = append(item, cast.ToString(staff.BaseSalary))
|
item = append(item, cast.ToString(staff.BaseSalary))
|
||||||
item = append(item, cast.ToString(staff.AttendSalary))
|
item = append(item, cast.ToString(butil.FloatCut(staff.PerfSalary)))
|
||||||
item = append(item, cast.ToString(staff.AwardSalary))
|
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.SocialInsurence))
|
||||||
|
item = append(item, cast.ToString(staff.HouseFund))
|
||||||
item = append(item, cast.ToString(staff.PersonalTax))
|
item = append(item, cast.ToString(staff.PersonalTax))
|
||||||
item = append(item, cast.ToString(staff.TotalDay))
|
item = append(item, cast.ToString(staff.TotalDay))
|
||||||
item = append(item, cast.ToString(staff.RealDay))
|
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(extra["approvalCheckinDay"]))
|
||||||
item = append(item, cast.ToString(staff.Holiday))
|
item = append(item, cast.ToString(staff.Holiday))
|
||||||
item = append(item, cast.ToString(staff.GetRealSalary()))
|
item = append(item, cast.ToString(staff.GetRealSalary()))
|
||||||
|
@ -190,21 +194,26 @@ func (s *StaffSalary) Summary(month string, ctx *gin.Context) {
|
||||||
|
|
||||||
datas = append(datas, item)
|
datas = append(datas, item)
|
||||||
summary.BaseSalary += staff.BaseSalary
|
summary.BaseSalary += staff.BaseSalary
|
||||||
|
summary.PerfSalary += staff.PerfSalary
|
||||||
summary.AttendSalary += staff.AttendSalary
|
summary.AttendSalary += staff.AttendSalary
|
||||||
summary.AwardSalary += staff.AwardSalary
|
summary.AwardSalary += staff.AwardSalary
|
||||||
summary.SocialInsurence += staff.SocialInsurence
|
summary.SocialInsurence += staff.SocialInsurence
|
||||||
summary.PersonalTax += staff.PersonalTax
|
summary.PersonalTax += staff.PersonalTax
|
||||||
summary.Holiday += staff.Holiday
|
summary.Holiday += staff.Holiday
|
||||||
|
summary.HouseFund += staff.HouseFund
|
||||||
}
|
}
|
||||||
summary.Holiday = butil.FloatCut(summary.Holiday)
|
summary.Holiday = butil.FloatCut(summary.Holiday)
|
||||||
summary.BaseSalary = butil.FloatCut(summary.BaseSalary)
|
summary.BaseSalary = butil.FloatCut(summary.BaseSalary)
|
||||||
|
summary.PerfSalary = butil.FloatCut(summary.PerfSalary)
|
||||||
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.SocialInsurence = butil.FloatCut(summary.SocialInsurence)
|
||||||
|
summary.HouseFund = butil.FloatCut(summary.HouseFund)
|
||||||
summary.PersonalTax = butil.FloatCut(summary.PersonalTax)
|
summary.PersonalTax = butil.FloatCut(summary.PersonalTax)
|
||||||
datas = append(datas, []string{"合计", "-", "-", "-",
|
datas = append(datas, []string{"合计", "-", "-", "-",
|
||||||
cast.ToString(summary.BaseSalary), cast.ToString(summary.AttendSalary), cast.ToString(summary.AwardSalary), cast.ToString(summary.SocialInsurence),
|
cast.ToString(summary.BaseSalary), cast.ToString(summary.PerfSalary), cast.ToString(summary.AttendSalary), cast.ToString(summary.AwardSalary), cast.ToString(summary.SocialInsurence),
|
||||||
cast.ToString(summary.PersonalTax), "-", "-", "-", cast.ToString(summary.Holiday),
|
cast.ToString(summary.HouseFund),
|
||||||
|
cast.ToString(summary.PersonalTax), "-", "-", "-", "-", cast.ToString(summary.Holiday),
|
||||||
cast.ToString(butil.FloatCut(summary.GetRealSalary())), "-"})
|
cast.ToString(butil.FloatCut(summary.GetRealSalary())), "-"})
|
||||||
|
|
||||||
if xls != "" {
|
if xls != "" {
|
||||||
|
|
|
@ -0,0 +1,289 @@
|
||||||
|
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) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
//有补卡申请就直接算出勤
|
||||||
|
approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(username, checkin.Day)
|
||||||
|
if approvalCheckin != nil {
|
||||||
|
realWorkdays += 1
|
||||||
|
approvalCheckinDay += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
////有请假申请的不算出勤
|
||||||
|
//approvalVacation, _ := dao.NewApprovalVacationDao().GetByUsernameDay(username, checkin.Day)
|
||||||
|
//if approvalVacation != nil {
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
271
worker/staff.go
271
worker/staff.go
|
@ -1,17 +1,16 @@
|
||||||
package worker
|
package worker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
butil "enterprise/base/util"
|
|
||||||
"enterprise/common/config"
|
"enterprise/common/config"
|
||||||
"enterprise/common/dao"
|
"enterprise/common/dao"
|
||||||
"enterprise/common/global"
|
"enterprise/common/global"
|
||||||
"enterprise/common/model"
|
"enterprise/common/model"
|
||||||
|
"enterprise/service"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.u8t.cn/open/gosdk/qyweixin"
|
"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"
|
||||||
"math"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -44,7 +43,8 @@ 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("入职年限:%.1f", float64(spanMonth)/12))
|
message = append(message, fmt.Sprintf("入职年限:%.1f", float64(spanMonth)/12))
|
||||||
message = append(message, fmt.Sprintf("基本工资:%s", staff.Salary))
|
message = append(message, fmt.Sprintf("基本工资:%s", staff.BaseSalary))
|
||||||
|
message = append(message, fmt.Sprintf("绩效工资:%s", staff.PerfSalary))
|
||||||
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 {
|
||||||
|
@ -99,7 +99,7 @@ func (s *Staff) SyncStaffInfo() {
|
||||||
Agent: cfg.QyWeixin.EnterpriseAgent,
|
Agent: cfg.QyWeixin.EnterpriseAgent,
|
||||||
})
|
})
|
||||||
|
|
||||||
userConfigs, err := dao.NewUserConfigDao().Query(model.UserConfigStatusNormal)
|
userConfigs, err := dao.NewUserConfigDao().Query(model.StaffConfigStatusNormal)
|
||||||
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
|
||||||
|
@ -120,15 +120,16 @@ func (s *Staff) SyncStaffInfo() {
|
||||||
}
|
}
|
||||||
staff.Username = staffInfo.UserName
|
staff.Username = staffInfo.UserName
|
||||||
staff.Realname = staffInfo.RealName
|
staff.Realname = staffInfo.RealName
|
||||||
staff.Idno = staffInfo.Idno
|
staff.Idno = staffInfo.Extra["11015"]
|
||||||
staff.StaffType = staffInfo.StaffType
|
staff.StaffType = staffInfo.Extra["12003"]
|
||||||
staff.Salary = cast.ToString(staffInfo.Salary)
|
staff.BaseSalary = staffInfo.Extra["20001"]
|
||||||
staff.EntryDate = staffInfo.EntryDate
|
staff.PerfSalary = staffInfo.Extra["20005"]
|
||||||
staff.OfficialDate = staffInfo.OfficialDate
|
staff.EntryDate = time.Unix(cast.ToInt64(staffInfo.Extra["12018"]), 0).Format("2006-01-02")
|
||||||
staff.BirthDate = staffInfo.BirthDate
|
staff.OfficialDate = time.Unix(cast.ToInt64(staffInfo.Extra["12023"]), 0).Format("2006-01-02")
|
||||||
staff.BankName = staffInfo.BankName
|
staff.BirthDate = time.Unix(cast.ToInt64(staffInfo.Extra["11005"]), 0).Format("2006-01-02")
|
||||||
staff.BankCard = staffInfo.BankCard
|
staff.BankName = staffInfo.Extra["13001"]
|
||||||
staff.AlipayUid = staffInfo.AlipayUid
|
staff.BankCard = staffInfo.Extra["13002"]
|
||||||
|
staff.AlipayUid = staffInfo.Extra["20004"]
|
||||||
|
|
||||||
if staff.Id == 0 {
|
if staff.Id == 0 {
|
||||||
_, err = dao.NewStaffInfoDao().Create(staff)
|
_, err = dao.NewStaffInfoDao().Create(staff)
|
||||||
|
@ -147,11 +148,6 @@ func (s *Staff) SyncStaffSalary(month string) {
|
||||||
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, "-", "")
|
||||||
maxTotalDays := s.getTotalWorkDayMax(month)
|
|
||||||
monthTime, _ := time.ParseInLocation("200601", month, time.Local)
|
|
||||||
startDate := cast.ToInt(monthTime.Format("20060102"))
|
|
||||||
endDate := cast.ToInt(monthTime.AddDate(0, 1, -1).Format("20060102"))
|
|
||||||
salaryDao := dao.NewStaffSalaryDao()
|
|
||||||
|
|
||||||
staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal)
|
staffs, err := dao.NewStaffInfoDao().Query(model.StaffInfoStatusNormal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,128 +156,33 @@ func (s *Staff) SyncStaffSalary(month string) {
|
||||||
}
|
}
|
||||||
for _, staff := range staffs {
|
for _, staff := range staffs {
|
||||||
|
|
||||||
entryTime, _ := time.ParseInLocation("2006-01-02", staff.EntryDate, time.Local)
|
|
||||||
officalTime, _ := time.ParseInLocation("2006-01-02", staff.OfficialDate, 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)
|
|
||||||
isOfficialMonth := goutil.If(cast.ToInt(officalTime.Format("200601")) == cast.ToInt(month), true, false)
|
|
||||||
isLeaveMonth := goutil.If(cast.ToInt(leaveTime.Format("200601")) == cast.ToInt(month), true, false)
|
|
||||||
|
|
||||||
// 已离职的员工不处理
|
// 已离职的员工不处理
|
||||||
if staff.LeaveDate != "" && !isLeaveMonth {
|
if staff.LeaveDate != "" {
|
||||||
continue
|
leaveTime, _ := time.ParseInLocation("2006-01-02", staff.LeaveDate, time.Local)
|
||||||
}
|
isLeaveMonth := goutil.If(cast.ToInt(leaveTime.Format("200601")) == cast.ToInt(month), true, false)
|
||||||
|
if !isLeaveMonth {
|
||||||
salary, err := salaryDao.GetBy(staff.Username, month)
|
continue
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if salary == nil {
|
|
||||||
salary = new(model.StaffSalary)
|
|
||||||
salary.Month = month
|
|
||||||
salary.Username = staff.Username
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := dao.NewUserConfigDao().GetByUsername(staff.Username)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if config == nil {
|
|
||||||
log.Errorf("username[%s] not config,skip!!", staff.Username)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 试用期折扣
|
|
||||||
discount := cast.ToFloat64(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
|
|
||||||
}
|
|
||||||
|
|
||||||
//社保
|
|
||||||
socialInsurence := cast.ToFloat64(config.Get(model.StaffSalarySocialInsurence))
|
|
||||||
//if isEntryMonth && entryTime.Day() >= 15 {
|
|
||||||
if isEntryMonth { //入职月不买社保
|
|
||||||
socialInsurence = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 休假申请
|
|
||||||
approveVacations, err := dao.NewApprovalVacationDao().GetByUsername(staff.Username, month, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打卡正常天数+补卡天数 为正常出勤天数
|
config, err := dao.NewUserConfigDao().GetByUsername(staff.Username)
|
||||||
totalDays := s.getTotalWorkDay(staff.Username, month)
|
if err != nil || config == nil {
|
||||||
realWorkDays := s.getRealWorkDay(staff.EntryDate, staff.LeaveDate, staff.Username, month)
|
log.Errorf("username[%s] not config,skip!!", staff.Username)
|
||||||
approvalCheckinDay := s.getApprovalCheckinDay(staff.Username, month)
|
continue
|
||||||
extra := make(map[string]interface{})
|
}
|
||||||
salary.BaseSalary = cast.ToFloat64(staff.Salary)
|
salary, err := dao.NewStaffSalaryDao().GetBy(staff.Username, month)
|
||||||
salary.Holiday = holiday
|
if err != nil {
|
||||||
entryDate := cast.ToInt(strings.ReplaceAll(staff.EntryDate, "-", ""))
|
log.Errorf("db error :%s", err.Error())
|
||||||
officialDate := cast.ToInt(strings.ReplaceAll(staff.OfficialDate, "-", ""))
|
continue
|
||||||
|
|
||||||
if discount < 1.0 && isOfficialMonth {
|
|
||||||
totalMonthDay := float64(endDate - startDate + 1)
|
|
||||||
discount = discount*float64(officialDate-startDate)/totalMonthDay + 1*float64(endDate-officialDate+1)/totalMonthDay
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 入职月或离职月以大多数人的出勤天数为准
|
staffService := service.NewStaff(staff, config)
|
||||||
if isEntryMonth || isLeaveMonth {
|
salary, err = staffService.CalcSalary(salary, month)
|
||||||
totalDays = maxTotalDays
|
if err != nil {
|
||||||
|
log.Errorf("username[%s] staffService.CalcSalary error :%s", staff.Username, err.Error())
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
realWorkDays = realWorkDays + surplusHoliday
|
|
||||||
attendSalary := salary.BaseSalary * (realWorkDays / float64(totalDays)) * discount
|
|
||||||
staffSalaryPerDay := cast.ToFloat64(config.Get(model.StaffSalaryPerDay))
|
|
||||||
if staffSalaryPerDay > 0 {
|
|
||||||
attendSalary = staffSalaryPerDay * realWorkDays
|
|
||||||
}
|
|
||||||
|
|
||||||
extra["discount"] = discount
|
|
||||||
extra["approvalCheckinDay"] = approvalCheckinDay //展示依赖
|
|
||||||
extra["socialInsurence"] = socialInsurence
|
|
||||||
extra["days"] = endDate - startDate + 1
|
|
||||||
extra["startDate"] = startDate
|
|
||||||
extra["totalDays"] = totalDays
|
|
||||||
extra["realDays"] = realWorkDays
|
|
||||||
extra["startDate"] = startDate
|
|
||||||
extra["endDate"] = endDate
|
|
||||||
extra["officialDate"] = officialDate
|
|
||||||
extra["entryDate"] = entryDate
|
|
||||||
extra["isEntryMonth"] = isEntryMonth
|
|
||||||
extra["isOfficialMonth"] = isOfficialMonth
|
|
||||||
extra["surplusHoliday"] = surplusHoliday
|
|
||||||
|
|
||||||
salary.AttendSalary = butil.FloatCut(attendSalary)
|
|
||||||
salary.RealSalary = salary.GetRealSalary()
|
|
||||||
salary.SocialInsurence = socialInsurence
|
|
||||||
salary.Holiday = holiday
|
|
||||||
salary.TotalDay = float64(totalDays)
|
|
||||||
salary.RealDay = realWorkDays
|
|
||||||
|
|
||||||
salary.Extra = goutil.EncodeJSONIndent(extra)
|
|
||||||
if salary.Id == 0 {
|
if salary.Id == 0 {
|
||||||
_, err = dao.NewStaffSalaryDao().Create(salary)
|
_, err = dao.NewStaffSalaryDao().Create(salary)
|
||||||
} else {
|
} else {
|
||||||
|
@ -293,109 +194,3 @@ func (s *Staff) SyncStaffSalary(month string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 checkin.Exception == "" {
|
|
||||||
realWorkdays += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//入职离职当天已经算过了
|
|
||||||
if entryTime.Format("2006-01-02") == checkin.Day || leaveTime.Format("2006-01-02") == checkin.Day {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//有补卡申请就直接算出勤
|
|
||||||
approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(username, checkin.Day)
|
|
||||||
if approvalCheckin != nil {
|
|
||||||
realWorkdays += 1
|
|
||||||
approvalCheckinDay += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//有请假申请的不算出勤
|
|
||||||
approvalVacation, _ := dao.NewApprovalVacationDao().GetByUsernameDay(username, checkin.Day)
|
|
||||||
if approvalVacation != nil {
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue