From 38c6f7308c1dd22a8ea286c3ea1de3a4e714f78f Mon Sep 17 00:00:00 2001 From: yinbentan <yinbentan@live.com> Date: 星期五, 02 八月 2024 16:44:51 +0800 Subject: [PATCH] BUG修复,新的工资计算方式添加遗漏的“考勤及补贴数据”(工作日加班时长、休息日加班时长、带徒天数、满勤奖、请假天数、工龄) --- utils/timex.go | 27 +++++++++++++ service/salary_plan.go | 88 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/service/salary_plan.go b/service/salary_plan.go index d93c850..5c6c3b1 100644 --- a/service/salary_plan.go +++ b/service/salary_plan.go @@ -9,13 +9,19 @@ "silkserver/constvar" "silkserver/models" "silkserver/pkg/logx" + "silkserver/utils" "silkserver/utils/calculator" "strconv" "strings" + "time" ) // WorkingHours 瀛樿〃锛氬伐鏃惰绠楋紙鏃ユ湡锛堝勾鏈堟棩锛夈�佸伐绉嶃�佸憳宸ュ鍚嶃�佸皬缁勩�佽溅鍙般�佷骇閲忓伐璧勩�佷笂鐝秴鏃讹紙灏忔椂锛夈�佷笂鐝秴鏃讹紙澶╋級銆佸姞鐝紙鍗曠嫭锛夈�佸姞鐝紙鍏ㄨ溅闂达級銆佸嚭鍕わ紙澶╋級銆佸甫寰掞紙澶╋級銆佷骇閲忥紙KG锛夈�佸叾瀹冿級 func WorkingHours(date string) error { + dateTime, err := time.Parse("2006-01-02", date) + if err != nil { + return err + } // 浜哄憳淇℃伅 workers, err := models.NewWorkerSearch().FindNotTotal() if err != nil { @@ -59,8 +65,13 @@ } workingHours.ShiftClockInTime = attendance.StartWorkTime workingHours.ShiftClockOutTime = attendance.EndWorkTime - workingHours.OvertimeType = constvar.ShiftOvertimeTypeTimeout - workingHours.OvertimeDuration = attendance.OverTimeDuration + if dateTime.Weekday() == 0 { + workingHours.OvertimeType = constvar.ShiftOvertimeTypeOvertime + workingHours.OvertimeDuration = decimal.NewFromInt32(1) + } else { + workingHours.OvertimeType = constvar.ShiftOvertimeTypeTimeout + workingHours.OvertimeDuration = attendance.OverTimeDuration + } } } for _, position := range workerPositions { @@ -456,7 +467,15 @@ GroupCarHeadAvgAmount decimal.Decimal // 鍚岀粍杞﹀ご宸ュ伐璧� GroupWeaversAvgAmount decimal.Decimal // 鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫 - JobDays decimal.Decimal // 鍑哄嫟澶╂暟 + WorkingDay decimal.Decimal // 涓�涓湀宸ヤ綔澶╂暟 + JobDays decimal.Decimal // 涓�涓湀鍑哄嫟澶╂暟 + + ShiftTimeout decimal.Decimal // 宸ヤ綔鏃ュ姞鐝椂闀匡紙灏忔椂锛� + ShiftOvertime decimal.Decimal // 浼戞伅鏃ュ姞鐝椂闀匡紙澶╋級 + MentorDays decimal.Decimal // 甯﹀緬澶╂暟 + FullAttendanceAward decimal.Decimal // 婊″嫟濂� + LeaveDays decimal.Decimal // 璇峰亣澶╂暟 + Seniority decimal.Decimal // 宸ラ緞 } // SalaryPlan 鐢熶骇宸ヨ祫璁$畻 @@ -465,6 +484,10 @@ return errors.New("璇蜂紶鍏ユ纭殑鏌ヨ鏃堕棿锛�") } else { date = date[:7] + } + dateTime, err := time.Parse("2006-01", date) + if err != nil { + return err } hours, err := models.NewPayrollWorkingHoursSearch().SetOrder("worker_id").SetMonthly(date).FindNotTotal() // 鍛樺伐鐨勫伐鏃剁粺璁� @@ -475,15 +498,28 @@ return errors.New(date + ":鍛樺伐鎵撳崱淇℃伅涓虹┖") } - jobQuantityMap := make(map[string]int) // 鍛樺伐鍑哄嫟缁熻 + jobQuantityMap := make(map[string]int) + shiftTimeoutMap := make(map[string]decimal.Decimal) + shiftOvertimeMap := make(map[string]decimal.Decimal) for _, hour := range hours { jobQuantityMap[hour.WorkerID] += 1 + if hour.OvertimeType == constvar.ShiftOvertimeTypeOvertime { + shiftOvertimeMap[hour.WorkerID] = hour.OvertimeDuration.Add(shiftOvertimeMap[hour.WorkerID]) + } else if hour.OvertimeType == constvar.ShiftOvertimeTypeTimeout { + shiftTimeoutMap[hour.WorkerID] = hour.OvertimeDuration.Add(shiftTimeoutMap[hour.WorkerID]) + } } - workers, err := models.NewWorkerSearch().FindNotTotal() + workers, _ := models.NewWorkerSearch().FindNotTotal() workerMap := make(map[string]*models.Worker) for _, worker := range workers { workerMap[worker.ID] = worker + } + + mentors, _ := models.NewMentorSearch().SetMonth(date).FindNotTotal() + mentorMap := make(map[string]int) + for _, mentor := range mentors { + mentorMap[mentor.WorkerId] = mentor.Days } // 鎸¤溅宸ュ伐璧� @@ -648,24 +684,35 @@ CreatedBy: "auto", } - monthKey := fmt.Sprintf("%v%v", worker.ShopNumber, worker.GroupNumber) - fallingSilkBucket := decimal.NewFromInt(0) - finishTotalAvgAmount := decimal.NewFromInt(0) - if group, ok := groupByMonthMap[monthKey]; ok { - fallingSilkBucket = group.FallingSilkBucket - finishTotalAvgAmount = group.FinishTotalAvgAmount - } + firstDay, lastDay := utils.GetLastMonthPeriod(dateTime) + _, days := utils.CalcWorkHour(firstDay, lastDay, []time.Weekday{time.Sunday}, 12.0) parameter := SalaryParameter{ - FallingSilkBucket: fallingSilkBucket, - GroupWeaversAvgAmount: finishTotalAvgAmount, - GroupCarHeadAvgAmount: finishTotalAvgAmount.Div(ready70), - JobDays: decimal.NewFromInt32(int32(dayCount)), + WorkingDay: decimal.NewFromInt32(int32(days)), + JobDays: decimal.NewFromInt32(int32(dayCount)), + FullAttendanceAward: decimal.NewFromInt32(0), // 婊″嫟濂� + LeaveDays: decimal.NewFromInt32(0), // 璇峰亣澶╂暟 + Seniority: decimal.NewFromInt32(0), // 宸ラ緞 + } + monthKey := fmt.Sprintf("%v%v", worker.ShopNumber, worker.GroupNumber) + if group, ok := groupByMonthMap[monthKey]; ok { + parameter.FallingSilkBucket = group.FallingSilkBucket + parameter.GroupWeaversAvgAmount = group.FinishTotalAvgAmount + parameter.GroupCarHeadAvgAmount = group.FinishTotalAvgAmount.Div(ready70) + } + if timeout, ok := shiftTimeoutMap[hourId]; ok { + parameter.ShiftTimeout = timeout + } + if overtime, ok := shiftOvertimeMap[hourId]; ok { + parameter.ShiftOvertime = overtime + } + if mentorDays, ok := mentorMap[hourId]; ok { + parameter.MentorDays = decimal.NewFromInt32(int32(mentorDays)) } // 鎸夋湀绠楋細鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫銆佸悓缁勮溅澶村伐宸ヨ祫銆佸嚭鍕ゅぉ鏁� if workType, ok := salaryPlansMap[worker.WorkTypeId]; ok { for _, salaryPlan := range workType.SalaryPlans { - if matched, _ := regexp.MatchString("(鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫)|(鍚岀粍杞﹀ご宸ュ伐璧�)|(鍑哄嫟澶╂暟)", salaryPlan.SalaryFormula); matched { + if matched, _ := regexp.MatchString("(鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫)|(鍚岀粍杞﹀ご宸ュ伐璧�)|(鍑哄嫟澶╂暟)|(宸ヤ綔鏃ュ姞鐝椂闀�)|(浼戞伅鏃ュ姞鐝椂闀�)|(甯﹀緬澶╂暟)|(婊″嫟濂�)|(璇峰亣澶╂暟)|(宸ラ緞)", salaryPlan.SalaryFormula); matched { temp := constitute formula, s := salaryCalculate(¶meter, salaryPlan) temp.SalaryFormula = formula @@ -710,6 +757,13 @@ formula = strings.Replace(formula, "鍚岀粍杞﹀ご宸ュ伐璧�", parameter.GroupCarHeadAvgAmount.String(), -1) formula = strings.Replace(formula, "鍑哄嫟澶╂暟", parameter.JobDays.String(), -1) + formula = strings.Replace(formula, "宸ヤ綔鏃ュ姞鐝椂闀�", parameter.ShiftTimeout.String(), -1) + formula = strings.Replace(formula, "浼戞伅鏃ュ姞鐝椂闀�", parameter.ShiftOvertime.String(), -1) + formula = strings.Replace(formula, "甯﹀緬澶╂暟", parameter.MentorDays.String(), -1) + formula = strings.Replace(formula, "婊″嫟濂�", parameter.FullAttendanceAward.String(), -1) + formula = strings.Replace(formula, "璇峰亣澶╂暟", parameter.LeaveDays.String(), -1) + formula = strings.Replace(formula, "宸ラ緞", parameter.Seniority.String(), -1) + logx.Debugf("salary formula: %v", formula) result, err := calculator.ParseAndExec(formula) diff --git a/utils/timex.go b/utils/timex.go index 98ca7b1..75ac954 100644 --- a/utils/timex.go +++ b/utils/timex.go @@ -1,6 +1,9 @@ package utils -import "time" +import ( + "slices" + "time" +) // IsOverlap 鍒ゆ柇涓や釜鏃堕棿娈垫槸鍚︽湁閲嶅彔 func IsOverlap(start1, end1, start2, end2 string) bool { @@ -22,6 +25,10 @@ return time.Now().AddDate(0, offset, 0) } +func GetDayByOffset(offset int) time.Time { + return time.Now().AddDate(0, 0, offset) +} + // GetLastMonthPeriod 杩斿洖涓婁釜鏈堢殑鏈堝垵鏃堕棿鍜屾湀鏈椂闂� func GetLastMonthPeriod(now time.Time) (firstDay time.Time, lastDay time.Time) { // 鑾峰彇鏈釜鏈堢殑绗竴澶╃殑鏃ユ湡锛堝嵆鏈湀鏈堝垵锛� @@ -40,3 +47,21 @@ func GetMonthDuration(d time.Time) (duration int) { return d.AddDate(0, 1, -1).Day() } + +func CalcWorkHour(begin, end time.Time, dayOff []time.Weekday, cellHour float32) (workHour float32, workingCount int) { + var currentTime = begin + for { + if currentTime.After(end) { + break + } + if slices.Contains(dayOff, currentTime.Weekday()) { + // nothing + } else { + workHour += cellHour + workingCount++ + } + currentTime = currentTime.AddDate(0, 0, 1) // .Add(24 * time.Hour) + } + + return float32(workHour), workingCount +} -- Gitblit v1.8.0