staff_user2

This commit is contained in:
jiangyong27 2025-04-02 17:41:44 +08:00
parent 9868bd0923
commit 5e9ac840b4
5 changed files with 192 additions and 251 deletions

View File

@ -42,5 +42,8 @@ func (c *Corp) GetConfig() *CorpConfig {
var cfg CorpConfig
json.Unmarshal([]byte(c.Config), &cfg)
if cfg.WorkerHour == "" {
cfg.WorkerHour = "8"
}
return &cfg
}

View File

@ -9,7 +9,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/smbrave/goutil"
"github.com/spf13/cast"
"math"
"time"
)
@ -62,6 +61,7 @@ func (s *StaffSalary) CalcSalary(salary *model.StaffSalary, month, expr string)
salary.Username = s.user.Username
salary.Status = model.StaffSalaryStatusWait
}
//已支付过的工资不能再计算了
if salary != nil && salary.Status == model.StaffSalaryStatusPayed {
return salary, nil
@ -75,7 +75,10 @@ func (s *StaffSalary) CalcSalary(salary *model.StaffSalary, month, expr string)
salary.HouseDeduct = 0
}
salary.ShouldDay = int(s.getTotalWorkDay(s.user.CorpId, s.user.Username, month))
staffUser := NewStaffUser(s.user)
staffUser.Load(month)
salary.ShouldDay = int(staffUser.GetTotalWorkDay())
// 入职月或离职月以大多数人的出勤天数为准
if isEntryMonth || isLeaveMonth {
salary.ShouldDay = int(s.getTotalWorkDayMax(s.user.CorpId, month))
@ -85,16 +88,9 @@ func (s *StaffSalary) CalcSalary(salary *model.StaffSalary, month, expr string)
salary.ShouldDay = 22
}
holiday, surplusHoliday := s.getRealVacationDay(month)
realWorkDays := s.getRealWorkDay(month)
//approvalCheckinDay := s.getApprovalCheckinDay(s.user.CorpId, s.user.Username, month)
salary.HolidayDay = staffUser.GetVacationDay()
salary.AttendDay = staffUser.GetRealWorkDay()
//鱼办特殊月份
if salary.Month == "202502" && corp.Id == 1002 {
salary.ShouldDay = 21
}
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))
@ -204,125 +200,6 @@ func (s *StaffSalary) formatFloat(salary *model.StaffSalary) {
salary.HolidayDay = butil.FloatCut(salary.HolidayDay)
}
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)
holidayMap := make(map[string]float64)
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
//不是整天数,把剩余的算上
if _, ok := holidayMap[vac.VacationDate]; !ok {
span := vac.VacationDuration - math.Floor(vac.VacationDuration)
if _, ok := holidayMap[vac.VacationDate]; !ok {
holidayMap[vac.VacationDate] = goutil.If(math.Abs(span) < 0.000001, 0, 1-span)
} else {
}
}
}
}
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
}
corp, _ := dao.NewCorpDao().Get(s.user.CorpId)
for _, checkin := range userCheckins {
//入职离职当天已经算过了
if entryTime.Format("2006-01-02") == checkin.Day || leaveTime.Format("2006-01-02") == checkin.Day {
continue
}
//有请假申请的不算出勤
approvalVacation, _ := dao.NewApprovalVacationDao().GetByUsernameDay(s.user.CorpId, s.user.Username, checkin.Day)
if approvalVacation != nil {
continue
}
if checkin.IsNormal() {
realWorkdays += 1
continue
}
//有补卡申请就直接算出勤
approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(s.user.CorpId, s.user.Username, checkin.Day)
if approvalCheckin != nil {
realWorkdays += 1
approvalCheckinDay += 1
continue
}
//其他按工作时长结算
if checkin.IsCheckin() {
shouldAttendHour := cast.ToFloat64(corp.GetConfig().WorkerHour)
lackSecond := int64(float64(3600)*(1.5+shouldAttendHour)) - (checkin.EndTime - checkin.StartTime) //加上午休的1.5小时
if lackSecond > 0 {
lackHour := float64(lackSecond/3600 + 1) //按小时取整
realWorkdays += goutil.If(lackHour > shouldAttendHour, 0, 1-lackHour/shouldAttendHour)
} else {
realWorkdays += 1
}
}
}
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)
@ -343,5 +220,4 @@ func (s *StaffSalary) getTotalWorkDayMax(corpId int64, month string) int64 {
}
}
return totalDays
}

182
service/staff_user.go Normal file
View File

@ -0,0 +1,182 @@
package service
import (
"enterprise/common/dao"
"enterprise/common/model"
log "github.com/sirupsen/logrus"
"github.com/smbrave/goutil"
"github.com/spf13/cast"
"math"
"strings"
"time"
)
type StaffUser struct {
user *model.StaffUser
corp *model.Corp
month string
vacations []*model.ApprovalVacation
checkins []*model.Checkin
}
func NewStaffUser(user *model.StaffUser) *StaffUser {
uv := &StaffUser{
user: user,
}
return uv
}
func (s *StaffUser) Load(month string) {
corp, err := dao.NewCorpDao().Get(s.user.CorpId)
if err != nil {
log.Errorf("db error :%s", err.Error())
return
}
// 休假申请
approveVacations, err := dao.NewApprovalVacationDao().GetByUsername(s.user.CorpId, s.user.Username, month, "")
if err != nil {
log.Errorf("db error :%s", err.Error())
return
}
//打卡记录
userCheckins, err := dao.NewCheckinDao().Query(s.user.CorpId, s.user.Username, month, false)
if err != nil {
log.Errorf("db error :%s", err.Error())
return
}
s.vacations = approveVacations
s.checkins = userCheckins
s.corp = corp
s.month = month
}
func (v *StaffUser) GetVacationDay() float64 {
holiday := float64(0)
for _, vac := range v.vacations {
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
}
}
return holiday
}
func (s *StaffUser) GetTotalWorkDay() int64 {
return int64(len(s.checkins))
}
func (s *StaffUser) GetRealWorkDay() float64 {
realWorkdays := float64(0)
//入职当天算工作日
entryTime, _ := time.ParseInLocation("2006-01-02", s.user.EntryDate, time.Local)
if entryTime.Format("200601") == s.month {
realWorkdays += 1
}
//离职当天算工作日
leaveTime, _ := time.ParseInLocation("2006-01-02", s.user.LeaveDate, time.Local)
if leaveTime.Format("200601") == s.month {
realWorkdays += 1
}
for _, checkin := range s.checkins {
//有请假申请的不算出勤
if s.existVacation(checkin.Day) {
continue
}
//入职离职当天已经算过了
if entryTime.Format("2006-01-02") == checkin.Day || leaveTime.Format("2006-01-02") == checkin.Day {
continue
}
//有补卡记录的直接算出勤
if s.existApproveCheckin(checkin.Day) {
realWorkdays += 1
continue
}
//考勤正常算出勤
if checkin.IsNormal() {
realWorkdays += 1
continue
}
//其他情况按工作时长结算
if checkin.IsCheckin() {
shouldAttendHour := cast.ToFloat64(s.corp.GetConfig().WorkerHour)
lackSecond := int64(float64(3600)*(1.5+shouldAttendHour)) - (checkin.EndTime - checkin.StartTime) //加上午休的1.5小时
if lackSecond > 0 {
lackHour := float64(lackSecond/3600 + 1) //按小时取整
realWorkdays += goutil.If(lackHour > shouldAttendHour, 0, 1-lackHour/shouldAttendHour)
} else {
realWorkdays += 1
}
}
}
realWorkdays += s.getVacationSurplus()
return realWorkdays
}
func (v *StaffUser) existVacation(day string) bool {
queryDay := cast.ToInt(strings.ReplaceAll(day, "-", ""))
for _, vac := range v.vacations {
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)
startDay := cast.ToInt(startTime.Format("20060102"))
endDay := cast.ToInt(endTime.Format("20060102"))
if queryDay >= startDay && queryDay <= endDay {
return true
}
}
return false
}
func (s *StaffUser) existApproveCheckin(day string) bool {
//有补卡申请就直接算出勤
approvalCheckin, _ := dao.NewApprovalCheckinDao().GetByUsernameDay(s.user.CorpId, s.user.Username, day)
if approvalCheckin != nil {
return true
}
return false
}
func (s *StaffUser) getVacationSurplus() float64 {
suplusDays := float64(0)
vacationMap := make(map[string]float64)
for _, vac := range s.vacations {
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)
startDay := startTime.Format("2006-01-02")
endDay := endTime.Format("2006-01-02")
if startDay == endDay {
vacationMap[startDay] += vac.VacationDuration
continue
}
span := vac.VacationDuration - math.Floor(vac.VacationDuration)
suplusDays += goutil.If(span > 0, 1-span, 0)
}
for _, duration := range vacationMap {
if duration < 1 {
suplusDays += 1 - duration
}
}
return suplusDays
}

View File

@ -1,13 +0,0 @@
package service
import "enterprise/common/model"
type StaffUserCheckin struct {
user *model.StaffUser
}
func NewStaffUserCheckin(user *model.StaffUser) *StaffUserCheckin {
return &StaffUserCheckin{
user: user,
}
}

View File

@ -1,107 +0,0 @@
package service
import (
"enterprise/common/dao"
"enterprise/common/model"
log "github.com/sirupsen/logrus"
"time"
)
type StaffUserVacation struct {
user *model.StaffUser
corp *model.Corp
month string
vacations []*model.ApprovalVacation
vacationsMap map[string]float64
}
func NewStaffUserVacation(corp *model.Corp, user *model.StaffUser, month string) *StaffUserVacation {
uv := &StaffUserVacation{
user: user,
corp: corp,
month: month,
vacationsMap: make(map[string]float64),
}
uv.loadArr()
uv.loadMaps()
return uv
}
func (v *StaffUserVacation) loadMaps() {
vacationMap := make(map[string]float64)
for _, vac := range v.vacations {
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)
startDay := startTime.Format("2006-01-02")
endDay := endTime.Format("2006-01-02")
if startDay == endDay {
vacationMap[startDay] += vac.VacationDuration
continue
}
day := startTime.Format("2006-01-02")
for {
if day == startDay {
}
if day == endDay {
break
}
startTime = startTime.AddDate(0, 0, 1)
day = startTime.Format("2006-01-02")
}
}
//每天请假时长不超过1天
for k, duration := range vacationMap {
if duration > 1 {
vacationMap[k] = 1
}
}
v.vacationsMap = vacationMap
return
}
func (v *StaffUserVacation) loadArr() {
// 休假申请
approveVacations, err := dao.NewApprovalVacationDao().GetByUsername(v.user.CorpId, v.user.Username, v.month, "")
if err != nil {
log.Errorf("db error :%s", err.Error())
return
}
v.vacations = approveVacations
}
func (v *StaffUserVacation) GetTotalDay() float64 {
holiday := float64(0)
for _, vac := range v.vacations {
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
}
}
return holiday
}
func (v *StaffUserVacation) GetSurplusDay() float64 {
suplusDays := float64(0)
for _, duration := range v.vacationsMap {
if duration < 1 {
suplusDays += 1 - duration
}
}
return suplusDays
}