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