From edf3066724ad442d6929210c830cb67c17277690 Mon Sep 17 00:00:00 2001
From: yinbentan <yinbentan@live.com>
Date: 星期四, 01 八月 2024 11:46:33 +0800
Subject: [PATCH] 添加工资计算自动任务

---
 models/payroll_working_hours.go |    4 
 task/salary_plan.go             |  101 ++++++++++++++++++++
 task/task_init.go               |    4 
 service/salary_plan.go          |  170 +++++++++++++++++++++++++++-------
 4 files changed, 244 insertions(+), 35 deletions(-)

diff --git a/models/payroll_working_hours.go b/models/payroll_working_hours.go
index caff2b4..86dc8bd 100644
--- a/models/payroll_working_hours.go
+++ b/models/payroll_working_hours.go
@@ -133,6 +133,10 @@
 		db = db.Where("work_type_id = ?", slf.WorkTypeID)
 	}
 
+	if slf.WorkTypeCode != "" {
+		db = db.Where("work_type_code = ?", slf.WorkTypeCode)
+	}
+
 	if slf.WorkerID != "" {
 		db = db.Where("worker_id = ?", slf.WorkerID)
 	}
diff --git a/service/salary_plan.go b/service/salary_plan.go
index c7f7aca..399be70 100644
--- a/service/salary_plan.go
+++ b/service/salary_plan.go
@@ -25,9 +25,18 @@
 	// 鎺掔彮淇℃伅(鍔熻兘缂哄け)
 	// 鎵撳崱淇℃伅锛堥�氳繃浜哄憳鍏宠仈锛�
 	attendances, err := models.NewAttendanceManageSearch().SetDate(date).FindNotTotal()
+	if err != nil {
+		return err
+	}
+	if len(attendances) == 0 {
+		return errors.New(date + ":鎵撳崱淇℃伅涓虹┖")
+	}
 
 	// 杞﹀彴淇℃伅锛堥�氳繃浜哄憳鍏宠仈锛�
 	workerPositions, err := models.NewWorkerPositionSearch().SetOverlappingDate(date, date).FindAll()
+	if err != nil {
+		return err
+	}
 
 	list := make([]*models.PayrollWorkingHours, 0)
 	for _, worker := range workers {
@@ -70,6 +79,9 @@
 	}
 
 	err = models.WithTransaction(func(db *gorm.DB) error {
+		if len(list) == 0 {
+			return nil
+		}
 		if err := models.NewPayrollWorkingHoursSearch().SetOrm(db).SetCycle(date).Delete(); err != nil {
 			return err
 		}
@@ -88,10 +100,18 @@
 	if err != nil {
 		return err
 	}
+	if len(yieldRegisters) == 0 {
+		return errors.New(date + ":浜ч噺鐧昏涓虹┖")
+	}
+
 	finenesss, err := models.NewFinenessRegisterSearch().SetFinishDate(date).FindAll() // 绾ゅ害鐧昏
 	if err != nil {
 		return err
 	}
+	if len(finenesss) == 0 {
+		return errors.New(date + ":绾ゅ害鐧昏涓虹┖")
+	}
+
 	finenessIds := make([]uint, len(finenesss))
 	for i, fineness := range finenesss {
 		finenessIds[i] = fineness.ID
@@ -101,8 +121,15 @@
 		return err
 	}
 
-	priceStandards, _ := models.NewRawSilkPriceStandardSearch().FindNotTotal() // 鐢熶笣瀹氫环
-	priceStandardMap := make(map[string]decimal.Decimal)                       // map[搴勫彛\鏍囧彿]瀹氫环
+	priceStandards, err := models.NewRawSilkPriceStandardSearch().FindNotTotal() // 鐢熶笣瀹氫环
+	if err != nil {
+		return err
+	}
+	if len(priceStandards) == 0 {
+		return errors.New(date + ":鐢熶笣瀹氫环涓虹┖")
+	}
+
+	priceStandardMap := make(map[string]decimal.Decimal) // map[搴勫彛\鏍囧彿]瀹氫环
 	for _, price := range priceStandards {
 		key := fmt.Sprintf("%d%s", price.MarketNumber, price.RawSilkGrade)
 		priceStandardMap[key] = price.PayStandard
@@ -111,6 +138,9 @@
 	workingHours, err := models.NewPayrollWorkingHoursSearch().SetWorkTypeCode(constvar.JobTypeWeavers).SetCycle(date).FindNotTotal() // 鍛樺伐鐨勫伐鏃剁粺璁�
 	if err != nil {
 		return err
+	}
+	if len(workingHours) == 0 {
+		return errors.New(date + ":鎸¤溅宸ユ墦鍗′俊鎭负绌�")
 	}
 
 	// 杞﹀彴鎸¤溅宸ラ噸澶嶄汉鍛樻爣璁�
@@ -133,7 +163,13 @@
 	}
 	for _, workingHour := range workingHourArr {
 		key := fmt.Sprintf("%v%v%v", workingHour.WorkshopNumber, workingHour.GroupNumber, workingHour.StartCarNumber)
-		carEmployeeMap[key][workingHour.WorkerID] = true
+		if temp, ok := carEmployeeMap[key]; ok {
+			temp[workingHour.WorkerID] = true
+			carEmployeeMap[key] = temp
+		} else {
+			carEmployeeMap[key] = map[string]bool{workingHour.WorkerID: true}
+		}
+
 	}
 
 	// 鏂规2 鏍规嵁绾ゅ害鐧昏鏉ユ煡浜烘暟
@@ -241,6 +277,9 @@
 
 	}
 	err = models.WithTransaction(func(db *gorm.DB) error {
+		if len(productionCar) == 0 {
+			return nil
+		}
 		if err := models.NewPayrollProductionCarSearch().SetOrm(db).SetCycle(date).Delete(); err != nil {
 			return err
 		}
@@ -263,16 +302,27 @@
 	if err != nil {
 		return err
 	}
+	if len(productionCars) == 0 {
+		errors.New(date + ":杞﹀彴姣忓ぉ鐨勪骇閲忕粺璁′负绌�")
+	}
 
 	workingHours, err := models.NewPayrollWorkingHoursSearch().SetWorkTypeCode(constvar.JobTypeWeavers).SetCycle(date).FindNotTotal() // 鍛樺伐鐨勫伐鏃剁粺璁�
 	if err != nil {
 		return err
 	}
+	if len(workingHours) == 0 {
+		return errors.New(date + ":鎸¤溅宸ユ墦鍗′俊鎭负绌�")
+	}
 
 	groupWorkingHourMap := make(map[string]map[string]bool)
 	for _, workingHour := range workingHours {
 		key := fmt.Sprintf("%v%v", workingHour.WorkshopNumber, workingHour.GroupNumber)
-		groupWorkingHourMap[key][workingHour.WorkerID] = true
+		if temp, ok := groupWorkingHourMap[key]; ok {
+			temp[workingHour.WorkerID] = true
+			groupWorkingHourMap[key] = temp
+		} else {
+			groupWorkingHourMap[key] = map[string]bool{workingHour.WorkerID: true}
+		}
 	}
 
 	productionGroupList := make([]*models.PayrollProductionGroup, 0)
@@ -316,12 +366,13 @@
 	}
 
 	err = models.WithTransaction(func(db *gorm.DB) error {
-		err := models.NewPayrollProductionGroupSearch().SetOrm(db).SetCycle(date).Delete()
-		if err != nil {
+		if len(productionGroupList) == 0 {
+			return nil
+		}
+		if err := models.NewPayrollProductionGroupSearch().SetOrm(db).SetCycle(date).Delete(); err != nil {
 			return err
 		}
-		err = models.NewPayrollProductionGroupSearch().SetOrm(db).CreateBatch(productionGroupList)
-		if err != nil {
+		if err = models.NewPayrollProductionGroupSearch().SetOrm(db).CreateBatch(productionGroupList); err != nil {
 			return err
 		}
 		return nil
@@ -339,10 +390,16 @@
 	if err != nil {
 		return err
 	}
+	if len(workingHours) == 0 {
+		return errors.New(date + ":鎸¤溅宸ユ墦鍗′俊鎭负绌�")
+	}
 
 	productionCars, err := models.NewPayrollProductionCarSearch().SetCycle(date).FindNotTotal()
 	if err != nil {
 		return err
+	}
+	if len(productionCars) == 0 {
+		return errors.New(date + ":杞﹀彴姣忓ぉ浜ч噺缁熻涓虹┖")
 	}
 
 	productionEmployee := make([]*models.PayrollProductionWeavers, 0)
@@ -366,10 +423,16 @@
 				info.FinishTotalAmount = info.FinishTotalAmount.Add(car.FinishTotalAvgAmount)
 			}
 		}
+		if info.SilkQuantity.IsZero() {
+			continue
+		}
 		productionEmployee = append(productionEmployee, &info)
 	}
 
 	err = models.WithTransaction(func(db *gorm.DB) error {
+		if len(productionEmployee) == 0 {
+			return nil
+		}
 		if err := models.NewPayrollProductionWeaversSearch().SetOrm(db).SetCycle(date).Delete(); err != nil {
 			return err
 		}
@@ -408,6 +471,10 @@
 	if err != nil {
 		return err
 	}
+	if len(hours) == 0 {
+		return errors.New(date + ":鍛樺伐鎵撳崱淇℃伅涓虹┖")
+	}
+
 	jobQuantityMap := make(map[string]int) // 鍛樺伐鍑哄嫟缁熻
 	for _, hour := range hours {
 		jobQuantityMap[hour.WorkerID] += 1
@@ -420,7 +487,11 @@
 	}
 
 	// 鎸¤溅宸ュ伐璧�
-	weaversAmountArr, _ := models.NewPayrollProductionWeaversSearch().SetMonthly(date).FindNotTotal()
+	weaversAmountArr, err := models.NewPayrollProductionWeaversSearch().SetMonthly(date).FindNotTotal()
+	if err != nil {
+		return err
+	}
+
 	weaversAmountMap := make(map[string]*models.PayrollProductionWeavers, len(weaversAmountArr))
 	for _, weaver := range weaversAmountArr {
 		key := fmt.Sprintf("%v%v", weaver.Cycle, weaver.WorkerID)
@@ -429,12 +500,23 @@
 
 	// 宸ョ宸ヨ祫鏂规 map[宸ョ]鏂规
 	salaryPlans, _ := models.NewWorkTypeManageSearch().FindNotTotal()
+	if len(salaryPlans) == 0 {
+		return errors.New(date + ":宸ヨ祫鏂规涓虹┖")
+	}
+
 	salaryPlansMap := make(map[uint]*models.WorkTypeManage, len(salaryPlans))
 	for _, salaryPlan := range salaryPlans {
 		salaryPlansMap[salaryPlan.ID] = salaryPlan
 	}
 
 	groups, err := models.NewPayrollProductionGroupSearch().SetMonthly(date).FindNotTotal()
+	if err != nil {
+		return err
+	}
+	if len(groups) == 0 {
+		return errors.New(date + ":灏忕粍姣忓ぉ鐨勪骇閲忎负绌�")
+	}
+
 	groupMap := make(map[string]*models.PayrollProductionGroup, len(groups))
 	groupByMonthMap := make(map[string]*models.PayrollProductionGroup, len(groups))
 	for _, group := range groups {
@@ -475,36 +557,46 @@
 
 		// 鎸夊ぉ绠楋細鏃ヤ骇涓濋噺銆佺敓涓濆崟浠枫�佹《鏁般�侀噹绾ゆ暟閲忋�侀噹绾ゅ崟浠�
 		groupKey := fmt.Sprintf("%v%v%v", hour.Cycle, hour.WorkshopNumber, hour.GroupNumber)
-		group := groupMap[groupKey]
-		weaversKey := fmt.Sprintf("%v%v", hour.Cycle, hour.WorkerID)
-		weavers := weaversAmountMap[weaversKey]
-		parameter := SalaryParameter{
-			SilkQuantity:       group.SilkQuantity,
-			SilkUnitAmount:     decimal.NewFromInt32(1),
-			SilkTotalAmount:    weavers.FinishTotalAmount,
-			FallingSilkBucket:  group.FallingSilkBucket,
-			BadSilkQuantity:    group.BadSilkQuantity,
-			BadSilkUnitAmount:  decimal.NewFromInt32(1),
-			BadSilkTotalAmount: weavers.BadSilkTotalAmount,
-		}
-		if workType, ok := salaryPlansMap[hour.WorkTypeID]; ok {
-			for _, salaryPlan := range workType.SalaryPlans {
-				if matched, _ := regexp.MatchString("(鏃ヤ骇涓濋噺)|(鐢熶笣鍗曚环)|(妗舵暟)|(閲庣氦鏁伴噺)|(閲庣氦鍗曚环)", salaryPlan.SalaryFormula); matched {
-					temp := production
-					formula, s := salaryCalculate(&parameter, salaryPlan)
+		if group, ok := groupMap[groupKey]; ok {
+			weaversKey := fmt.Sprintf("%v%v", hour.Cycle, hour.WorkerID)
+			finishTotalAmount := decimal.NewFromInt32(0)
+			badSilkTotalAmount := decimal.NewFromInt32(0)
+			if weavers, ok := weaversAmountMap[weaversKey]; ok {
+				finishTotalAmount = weavers.FinishTotalAmount
+				badSilkTotalAmount = weavers.BadSilkTotalAmount
+			}
 
-					temp.SalaryFormula = formula
-					temp.SalaryPlanId = salaryPlan.ID
-					temp.Amount = temp.Amount.Add(s)
-					productionByDay = append(productionByDay, &temp) // 姣忎釜浜虹殑鎵�鏈夋柟妗�
+			parameter := SalaryParameter{
+				SilkQuantity:       group.SilkQuantity,
+				SilkUnitAmount:     decimal.NewFromInt32(1),
+				SilkTotalAmount:    finishTotalAmount,
+				FallingSilkBucket:  group.FallingSilkBucket,
+				BadSilkQuantity:    group.BadSilkQuantity,
+				BadSilkUnitAmount:  decimal.NewFromInt32(1),
+				BadSilkTotalAmount: badSilkTotalAmount,
+			}
+			if workType, ok := salaryPlansMap[hour.WorkTypeID]; ok {
+				for _, salaryPlan := range workType.SalaryPlans {
+					if matched, _ := regexp.MatchString("(鏃ヤ骇涓濋噺)|(鐢熶笣鍗曚环)|(妗舵暟)|(閲庣氦鏁伴噺)|(閲庣氦鍗曚环)", salaryPlan.SalaryFormula); matched {
+						temp := production
+						formula, s := salaryCalculate(&parameter, salaryPlan)
+
+						temp.SalaryFormula = formula
+						temp.SalaryPlanId = salaryPlan.ID
+						temp.Amount = temp.Amount.Add(s)
+						productionByDay = append(productionByDay, &temp) // 姣忎釜浜虹殑鎵�鏈夋柟妗�
+					}
+
 				}
-
 			}
 		}
 
 	}
 
 	err = models.WithTransaction(func(db *gorm.DB) error {
+		if len(productionByDay) == 0 {
+			return nil
+		}
 		if err := models.NewPayrollOtherSubsidiesSearch().SetOrm(db).SetMonthly(date).Delete(); err != nil {
 			return err
 		}
@@ -557,11 +649,16 @@
 		}
 
 		monthKey := fmt.Sprintf("%v%v", worker.ShopNumber, worker.GroupNumber)
-		group := groupByMonthMap[monthKey]
+		fallingSilkBucket := decimal.NewFromInt(0)
+		finishTotalAvgAmount := decimal.NewFromInt(0)
+		if group, ok := groupByMonthMap[monthKey]; ok {
+			fallingSilkBucket = group.FallingSilkBucket
+			finishTotalAvgAmount = group.FinishTotalAvgAmount
+		}
 		parameter := SalaryParameter{
-			FallingSilkBucket:     group.FallingSilkBucket,
-			GroupWeaversAvgAmount: group.FinishTotalAvgAmount,
-			GroupCarHeadAvgAmount: group.FinishTotalAvgAmount.Div(ready70),
+			FallingSilkBucket:     fallingSilkBucket,
+			GroupWeaversAvgAmount: finishTotalAvgAmount,
+			GroupCarHeadAvgAmount: finishTotalAvgAmount.Div(ready70),
 			JobDays:               decimal.NewFromInt32(int32(dayCount)),
 		}
 
@@ -582,6 +679,9 @@
 	}
 
 	err = models.WithTransaction(func(db *gorm.DB) error {
+		if len(constituteByMonth) == 0 {
+			return nil
+		}
 		if err := models.NewPayrollConstituteSearch().SetOrm(db).SetCycle(date).SetCreatedBy("auto").Delete(); err != nil {
 			return err
 		}
diff --git a/task/salary_plan.go b/task/salary_plan.go
new file mode 100644
index 0000000..d982645
--- /dev/null
+++ b/task/salary_plan.go
@@ -0,0 +1,101 @@
+package task
+
+import (
+	"silkserver/models"
+	"silkserver/pkg/logx"
+	"silkserver/service"
+	"silkserver/utils"
+)
+
+func WorkingHours() {
+	//鍔犻攣锛屽彧闇�瑕佷竴涓繘绋嬭繍琛屾浠诲姟
+	var (
+		lockName  = "WorkingHours"
+		serviceID = "WorkingHoursServer"
+	)
+	err := models.NewLockSearch().AcquireLock(lockName, serviceID)
+	if err != nil {
+		logx.Errorf("MonthStats AcquireLock err:%v", err)
+		return
+	}
+	defer func() {
+		err := models.NewLockSearch().ReleaseLock(lockName, serviceID)
+		if err != nil {
+			logx.Errorf("MonthStats ReleaseLock err:%v", err)
+		}
+	}()
+
+	firstDay, lastDay := utils.GetLastMonthPeriod(utils.GetMonthByOffset(-1))
+	for i := firstDay.Day() - 1; i <= lastDay.Day(); i++ {
+		localDay := firstDay.AddDate(0, 0, i-1).Format("2006-01-02")
+		err = service.WorkingHours(localDay)
+		if err != nil {
+			logx.Error(err.Error())
+		}
+	}
+
+}
+
+func ProductionCar() {
+	//鍔犻攣锛屽彧闇�瑕佷竴涓繘绋嬭繍琛屾浠诲姟
+	var (
+		lockName  = "ProductionCar"
+		serviceID = "ProductionCarServer"
+	)
+	err := models.NewLockSearch().AcquireLock(lockName, serviceID)
+	if err != nil {
+		logx.Errorf("MonthStats AcquireLock err:%v", err)
+		return
+	}
+	defer func() {
+		err := models.NewLockSearch().ReleaseLock(lockName, serviceID)
+		if err != nil {
+			logx.Errorf("MonthStats ReleaseLock err:%v", err)
+		}
+	}()
+
+	firstDay, lastDay := utils.GetLastMonthPeriod(utils.GetMonthByOffset(-1))
+	for i := 0; i < lastDay.Day(); i++ {
+		localDay := firstDay.AddDate(0, 0, i).Format("2006-01-02")
+		err = service.ProductionCar(localDay)
+		if err != nil {
+			logx.Error(err.Error())
+		}
+		err = service.ProductionGroup(localDay)
+		if err != nil {
+			logx.Error(err.Error())
+		}
+		err = service.ProductionWeavers(localDay)
+		if err != nil {
+			logx.Error(err.Error())
+		}
+	}
+
+}
+
+func SalaryPlan() {
+	//鍔犻攣锛屽彧闇�瑕佷竴涓繘绋嬭繍琛屾浠诲姟
+	var (
+		lockName  = "SalaryPlan"
+		serviceID = "SalaryPlanServer"
+	)
+	err := models.NewLockSearch().AcquireLock(lockName, serviceID)
+	if err != nil {
+		logx.Errorf("MonthStats AcquireLock err:%v", err)
+		return
+	}
+	defer func() {
+		err := models.NewLockSearch().ReleaseLock(lockName, serviceID)
+		if err != nil {
+			logx.Errorf("MonthStats ReleaseLock err:%v", err)
+		}
+	}()
+
+	lastMonth := utils.GetMonthByOffset(-1).Format("2006-01")
+
+	err = service.SalaryPlan(lastMonth)
+	if err != nil {
+		logx.Error(err.Error())
+	}
+
+}
diff --git a/task/task_init.go b/task/task_init.go
index 2008b43..3e95573 100644
--- a/task/task_init.go
+++ b/task/task_init.go
@@ -17,5 +17,9 @@
 		logx.Errorf("init task err:%v", err)
 		panic(err)
 	}
+	s.Every(1).Month(1).Do(WorkingHours)
+	s.Every(1).Month(1).Do(ProductionCar)
+	s.Every(1).Month(1).Do(SalaryPlan)
+
 	s.StartAsync()
 }

--
Gitblit v1.8.0