package task import ( "errors" "github.com/shopspring/decimal" "silkserver/constvar" "silkserver/models" "silkserver/pkg/logx" "silkserver/utils" "strings" "time" ) func SalaryStatistics() { //加锁,只需要一个进程运行此任务 var ( lockName = "SalaryStatistics" serviceID = "silkServer" ) 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) } }() lastMonthStart, lastMonthEnd := GetLastMonthPeriod() month := lastMonthStart.Format("2006-01") //查询考勤统计 startStr := lastMonthStart.Format("2006-01-02") endStr := lastMonthEnd.Format("2006-01-02") attendances, err := models.NewAttendanceManageSearch().SetMonth(month).FindNotTotal() if err != nil { logx.Error("SalaryStatistics 查询考勤统计 err: " + err.Error()) return } if len(attendances) == 0 { logx.Warn("SalaryStatistics 查询考勤统计 empty result") return } var reportForms []*models.SalaryReportForm reportMap := make(map[string]*models.SalaryReportForm) workTypeIdMap := make(map[uint]uint) dataMap := make(map[string]utils.SalaryCalculateData) for _, attendance := range attendances { if _, ok := reportMap[attendance.WorkerId]; !ok { var rf models.SalaryReportForm rf.WorkerId = attendance.WorkerId rf.WorkerName = attendance.WorkerName rf.WorkTypeId = attendance.WorkTypeId rf.Month = month rf.Phone = attendance.PhoneNum reportMap[attendance.WorkerId] = &rf } var data utils.SalaryCalculateData if _, ok := dataMap[attendance.WorkerId]; ok { data = dataMap[attendance.WorkerId] } if attendance.WorkTypeId > 0 { workTypeIdMap[attendance.WorkTypeId] = attendance.WorkTypeId } //工作日加班时长 data.WeekdayOvertimeHours = data.WeekdayOvertimeHours.Add(attendance.OverTimeDuration) //出勤天数 if attendance.Status != constvar.Vacation { data.TotalAttendanceDays = data.TotalAttendanceDays + 1 } dataMap[attendance.WorkerId] = data } for _, v := range reportMap { reportForms = append(reportForms, v) } workTypeIds := make([]uint, 0) for _, v := range workTypeIdMap { workTypeIds = append(workTypeIds, v) } //查询工种的薪资方案和新增类型 workTypeManages, err := models.NewWorkTypeManageSearch().SetIds(workTypeIds).SetPreload(true).FindNotTotal() if err != nil { logx.Error("SalaryStatistics 查询工种的薪资方案和新增类型 err: " + err.Error()) return } if len(workTypeManages) == 0 { return } for _, form := range reportForms { details := make([]*models.SalaryDetails, 0) issueSalary := decimal.NewFromInt(0) for _, manage := range workTypeManages { if form.WorkTypeId == manage.ID { data := dataMap[form.WorkerId] for _, plan := range manage.SalaryPlans { formula := strings.ReplaceAll(plan.SalaryFormula, ",", "") var detail models.SalaryDetails detail.SalaryTypeId = plan.SalaryTypeId amount := decimal.NewFromInt(0) f := constvar.DailySilkProduction + "*" + constvar.RawSilkUnitPrice if strings.Contains(formula, f) { data, err = GetDailySilkProduction(startStr, endStr, form.WorkerId, data) if err != nil { logx.Error("SalaryStatistics 统计薪资出错 err: " + err.Error()) } } amount, err = utils.CalculateSalary(data, formula) if err != nil { logx.Error("SalaryStatistics 计算薪资出错 err: " + err.Error()) } detail.Amount = amount issueSalary = issueSalary.Add(amount) details = append(details, &detail) } } } form.Details = details form.IssueSalary = issueSalary } //插入数据库 err = models.NewSalaryReportFormSearch().CreateBatch(reportForms) if err != nil { logx.Error("SalaryStatistics 插入数据库出错 err: " + err.Error()) } } func GetDailySilkProduction(start, end, workerId string, data utils.SalaryCalculateData) (utils.SalaryCalculateData, error) { //查询机台管理 var cars []models.WorkerPosition err := models.NewWorkerPositionSearch().Orm.Table("silk_worker_position").Where("worker_id = ? and start_date >= ? and "+ "end_date <= ?", workerId, start, end).Find(&cars).Error if err != nil || len(cars) == 0 { return data, errors.New("查询机台管理出错") } endCarMap := make(map[int]int) groupMap := make(map[int]int) workshopMap := make(map[string]string) for _, car := range cars { endCarMap[car.EndWorkerPosition] = car.EndWorkerPosition groupMap[car.WorkshopGroup] = car.WorkshopGroup workshopMap[car.Workshop] = car.Workshop } groups := make([]int, 0) workshops := make([]string, 0) endCars := make([]int, 0) for _, v := range endCarMap { endCars = append(endCars, v) } for _, v := range workshopMap { workshops = append(workshops, v) } for _, v := range groupMap { groups = append(groups, v) } //查询产量登记表 var yield []models.YieldRegister err = models.NewYieldRegisterSearch().Orm.Table("silk_yield_register").Where("workshop_number in (?) and group_number "+ "in (?) and create_time >= ? and create_time <= ?", workshops, groups, start, end).Find(&yield).Error if err != nil || len(yield) == 0 { return data, errors.New("查询产量登记表出错") } yieldRegisterIds := make([]uint, 0) for _, register := range yield { yieldRegisterIds = append(yieldRegisterIds, register.ID) } yieldMap := make(map[string]decimal.Decimal) items, err := models.NewYieldRegisterItemSearch().SetYieldRegisterIds(yieldRegisterIds).SetCarNumbers(endCars).FindNotTotal() if err != nil || len(items) == 0 { return data, errors.New("查询产量登记详情表出错") } for _, register := range yield { for _, item := range items { if register.ID == item.YieldRegisterId { yieldMap[register.CreateTime] = item.PeopleYield } } } //查询纤度登记表 var fineness []models.FinenessRegister markets := make([]string, 0) err = models.NewFinenessRegisterSearch().Orm.Table("silk_fineness_register").Where("workshop_number in (?) and workshop_group "+ "in (?) and finish_date >= ? and finish_date <= ?", workshops, groups, start, end).Find(&fineness).Error if err != nil || len(fineness) == 0 { return data, errors.New("查询纤度登记表出错") } finenessIds := make([]uint, 0) for _, register := range fineness { finenessIds = append(finenessIds, register.ID) markets = append(markets, register.Market) } var checkItems []models.FinenessCheckItem err = models.NewFinenessCheckItemSearch().Orm.Table("silk_fineness_check_item").Where("fineness_register_id in (?) and "+ "position in (?)", finenessIds, endCars).Find(&checkItems).Error if err != nil || len(checkItems) == 0 { return data, errors.New("查询纤度登记详情表出错") } checkMap := make(map[string]string) marketMap := make(map[string]string) for _, item := range checkItems { for _, register := range fineness { if item.FinenessRegisterID == register.ID { checkMap[register.FinishDate] = item.FinenessGrade marketMap[register.FinishDate] = register.Market break } } } //查询不同庄口下的生丝定价 find, _, err := models.NewRawSilkPriceStandardSearch().SetMarketNames(markets).Find() if err != nil { return data, err } //计算每日工资 total := decimal.NewFromInt(0) for date, amount := range yieldMap { grade := checkMap[date] market := marketMap[date] for _, standard := range find { if standard.MarketName == market && standard.RawSilkGrade == grade { h := amount.Mul(standard.PayStandard) total = total.Add(h) break } } } data.DailySilkProduction = total data.RawSilkUnitPrice = decimal.NewFromInt(1) return data, nil } // GetLastMonthPeriod 返回上个月的月初时间和月末时间 func GetLastMonthPeriod() (time.Time, time.Time) { // 获取当前时间 now := time.Now() // 计算上个月的年份和月份 lastMonth := now.AddDate(0, -1, 0) lastYear, lastMonthNum, _ := lastMonth.Date() // 获取上个月的第一天的日期(即上个月月初) firstDayOfLastMonth := time.Date(lastYear, lastMonthNum, 1, 0, 0, 0, 0, now.Location()) // 获取本月第一天的日期(即本月月初) firstDayOfThisMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()) // 上个月月末时间即为本月月初减去一秒 lastDayOfLastMonth := firstDayOfThisMonth.Add(-time.Second) return firstDayOfLastMonth, lastDayOfLastMonth }