package task import ( "encoding/json" "fmt" "github.com/shopspring/decimal" "gorm.io/gorm" "time" "wms/constvar" "wms/models" "wms/pkg/logx" "wms/service" ) func MonthStats() (err error) { //加锁,只需要一个进程运行此任务 var ( lockName = "monthStats" serviceID = "wms" ) err = models.NewLockSearch().AcquireLock(lockName, serviceID) if err != nil { logx.Errorf("MonthStats AcquireLock err:%v", err) return } defer func() { if err != nil { service.SendAlarm("月度统计执行失败", "报错: "+err.Error()) } err = models.NewLockSearch().ReleaseLock(lockName, serviceID) if err != nil { logx.Errorf("MonthStats ReleaseLock err:%v", err) service.SendAlarm("月度统计执行成功解锁失败", err.Error()) } }() date := time.Now().Format("2006-01") lastDate := time.Now().AddDate(0, -1, 0).Format("2006-01") oldRecords, err := models.NewMonthStatsSearch().SetDate(lastDate).SetFields("id, product_id").FindNotTotal() if err != nil { logx.Errorf("MonthStats get last date record err:%v", err) return } oldRecordsMap := models.MonthStatsMap(oldRecords) //本月期初数量/上月结余数量 groupSumList, err := models.NewLocationProductAmountSearch().GroupSum("product_id", "amount") productIds := make([]string, 0, len(groupSumList)) for _, groupSum := range groupSumList { productIds = append(productIds, groupSum.Class) } products, err := models.NewMaterialSearch().SetFields("id, name, unit, weight, more_unit, more_unit_value").SetIDs(productIds).FindNotTotal() if err != nil { logx.Errorf("MonthStats get products err:%v", err) return } productMap := models.MaterialMap(products) beginTime, endTime := GetLastMonthPeriod() inputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeIncoming) if err != nil { logx.Errorf("MonthStats GetStatsByOperationType input err:%v", err) return } outputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeOutgoing) if err != nil { logx.Errorf("MonthStats GetStatsByOperationType output err:%v", err) return } var record models.MonthStats err = models.NewMonthStatsSearch().SetDate(date).Delete() if err != nil { return } for _, groupSum := range groupSumList { productId := groupSum.Class if productMap[productId] == nil { continue } product := productMap[productId] amount := groupSum.Sum record = models.MonthStats{ ProductId: productId, ProductName: product.Name, BeginAmount: amount, Unit: product.Unit, Weight: product.Weight.Mul(amount), Date: date, } var ( moreUnits string inputMoreUnits string outputMoreUnits string ) if *product.MoreUnit { moreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList)) inputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList)) outputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList)) for _, unitItem := range product.MoreUnitList { moreValueArr = append(moreValueArr, models.UnitItems{ Amount: amount.Mul(unitItem.Amount), Unit: unitItem.Unit, Floating: unitItem.Floating, }) bys, _ := json.Marshal(moreValueArr) moreUnits = string(bys) if !inputMap[productId].IsZero() { inputMoreValueArr = append(inputMoreValueArr, models.UnitItems{ Amount: inputMap[productId].Mul(unitItem.Amount), Unit: unitItem.Unit, Floating: unitItem.Floating, }) bys, _ = json.Marshal(inputMoreValueArr) inputMoreUnits = string(bys) } if !outputMap[productId].IsZero() { outputMoreValueArr = append(outputMoreValueArr, models.UnitItems{ Amount: outputMap[productId].Mul(unitItem.Amount), Unit: unitItem.Unit, Floating: unitItem.Floating, }) bys, _ = json.Marshal(outputMoreValueArr) outputMoreUnits = string(bys) } } } record.BeginMoreUnits = moreUnits err = models.WithTransaction(func(db *gorm.DB) error { err = models.NewMonthStatsSearch().SetOrm(db).Create(&record) if err != nil { logx.Errorf("NewMonthStatsSearch Create err:%v, record: %+v", err, record) service.SendAlarm("月度统计创建本月失败", fmt.Sprintf("NewMonthStatsSearch Create err:%v, record: %+v", err, record)) } if oldRecordsMap[productId] != nil && (!inputMap[productId].IsZero() || !outputMap[productId].IsZero()) { record.InputAmount = inputMap[productId] record.InputMoreUnits = inputMoreUnits record.OutputAmount = outputMap[productId] record.OutputMoreUnits = outputMoreUnits m := map[string]interface{}{ "input_amount": inputMap[productId], "input_more_units": inputMoreUnits, "output_amount": outputMap[productId], "output_more_units": outputMoreUnits, "end_more_units": moreUnits, "end_amount": amount, } err = models.NewMonthStatsSearch().SetOrm(db).SetID(oldRecordsMap[productId].Id).UpdateByMap(m) if err != nil { logx.Errorf("NewMonthStatsSearch UpdateByMap err:%v, id:%v, m:%+v", err, oldRecordsMap[productId].ID, m) service.SendAlarm("月度统计更改上月失败", fmt.Sprintf("NewMonthStatsSearch Create err:%v, record: %+v", err, record)) } } return nil }) } if err == nil { service.SendAlarm("月度统计执行成功", "") } return } func GetStatsByOperationType(beginTime, endTime time.Time, operationType constvar.BaseOperationType) (m map[string]decimal.Decimal, err error) { operationIds, err := models.NewOperationSearch().SetBaseOperationType(operationType).SetFields("id").SetTimeBetween(beginTime, endTime).FindIds() if err != nil { return } groupSumList, err := models.NewOperationDetailsSearch().SetOperationIds(operationIds).SetFields("product_id, amount").GroupSum("product_id", "amount") if err != nil { return } m = make(map[string]decimal.Decimal, len(groupSumList)) for _, v := range groupSumList { m[v.Class] = v.Sum } return } // 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 }