package service import ( "github.com/shopspring/decimal" "gorm.io/gorm" "math" "silkserver/constvar" "silkserver/models" "silkserver/utils" "sort" ) // FinenessCheck 纤度检查 func FinenessCheck(finenessRegister *models.FinenessRegister, standardMap map[string]*Standard, endCarMap map[int]bool, isNew bool) (err error) { finenessCheckItems := make([]*models.FinenessCheckItem, 0) var lastCarNo int var allFinenessList []decimal.Decimal var personFinenessList []decimal.Decimal //var carCheckNumber = 0 //单个car已检查样本数 var item *models.FinenessCheckItem var deviation, totalDeviation decimal.Decimal var finenessGrade string var roundingItemMap = make(map[float32]*models.FinenessRoundingItem, 0) lastCarNo = finenessRegister.FinenessList[0].Position for _, finenessItem := range finenessRegister.FinenessList { if lastCarNo != finenessItem.Position { //每个车号存一个models.FinenessCheckItem //carCheckNumber = 0 lastCarNo = finenessItem.Position } roundedHalfFineness := ToRoundedHalfFineness(finenessItem.Fineness) //类似四舍五入 fineness := decimal.NewFromFloat32(roundedHalfFineness) for i := 0; i < finenessItem.Quantity; i++ { allFinenessList = append(allFinenessList, fineness) personFinenessList = append(personFinenessList, fineness) } if roundingItemMap[roundedHalfFineness] == nil { roundingItemMap[roundedHalfFineness] = &models.FinenessRoundingItem{ Fineness: fineness, Quantity: finenessItem.Quantity, } } else { roundingItemMap[roundedHalfFineness].Quantity += finenessItem.Quantity } //carCheckNumber++ //if carCheckNumber == constvar.EveryPersonCarCheckNumber { //每人每车号取两个丝,所以每两个等于一个车号,存一行 models.FinenessCheckItem // carCheckNumber = 0 if endCarMap[finenessItem.Position] { //走到了某个人最后的车号,每人算一次偏差和等级 deviation = utils.Deviation(personFinenessList) totalDeviation = utils.TotalDeviation(personFinenessList, utils.Average(personFinenessList)) finenessGrade = CalcFinenessGrade(deviation, totalDeviation, decimal.Zero, decimal.Zero, decimal.Zero, standardMap) personFinenessList = personFinenessList[:0] } else { deviation = decimal.Zero totalDeviation = decimal.Zero finenessGrade = "" } item = MakeFinenessCheckItem(roundingItemMap, finenessRegister.ID, lastCarNo, deviation, totalDeviation, finenessGrade) finenessCheckItems = append(finenessCheckItems, item) roundingItemMap = make(map[float32]*models.FinenessRoundingItem, 0) //重置 //} } finenessCheck := models.FinenessCheck{ FinenessRegisterID: finenessRegister.ID, AverageFineness: utils.Average(allFinenessList), Deviation: utils.Deviation(allFinenessList), TotalDeviation: decimal.Decimal{}, Cleanliness: decimal.Decimal{}, Purity: decimal.Decimal{}, TwiceChange: decimal.Decimal{}, MarketProcessOrderNumber: "", Inspector: "", } finenessCheck.TotalDeviation = utils.TotalDeviation(allFinenessList, finenessCheck.AverageFineness) finenessCheck.FinenessGrade = CalcFinenessGrade(finenessCheck.Deviation, finenessCheck.TotalDeviation, finenessCheck.Cleanliness, finenessCheck.Purity, finenessCheck.TwiceChange, standardMap) err = models.WithTransaction(func(db *gorm.DB) error { if !isNew { err = models.NewFinenessCheckSearch().SetOrm(db).SetFinenessRegisterID(finenessRegister.ID).Delete() if err != nil { return err } err = models.NewFinenessCheckItemSearch().SetOrm(db).SetFinenessRegisterID(finenessRegister.ID).Delete() if err != nil { return err } } err := models.NewFinenessCheckSearch().SetOrm(db).Create(&finenessCheck) if err != nil { return err } if len(finenessCheckItems) > 0 { for _, v := range finenessCheckItems { v.FinenessCheckID = finenessCheck.ID } err = models.NewFinenessCheckItemSearch().SetOrm(db).CreateBatch(finenessCheckItems) if err != nil { return err } } return models.NewFinenessRegisterSearch().SetOrm(db).SetID(finenessRegister.ID).UpdateByMap(map[string]interface{}{"fineness_check_id": finenessCheck.ID}) }) return err } // MakeFinenessCheckItem 纤度检查明细 func MakeFinenessCheckItem(roundingItemMap map[float32]*models.FinenessRoundingItem, finenessRegisterID uint, position int, deviation, totalDeviation decimal.Decimal, finenessGrade string) *models.FinenessCheckItem { roundingItems := make([]*models.FinenessRoundingItem, 0, len(roundingItemMap)) for _, v := range roundingItemMap { roundingItems = append(roundingItems, &models.FinenessRoundingItem{ Fineness: v.Fineness, Quantity: v.Quantity, }) } item := &models.FinenessCheckItem{ FinenessRegisterID: finenessRegisterID, Position: position, FinenessRoundingItems: roundingItems, Deviation: deviation, TotalDeviation: totalDeviation, FinenessGrade: finenessGrade, Remark: "", } return item } type gradeRank struct { gradeName string gradeRank int } // CalcFinenessGrade 纤度等级 func CalcFinenessGrade(deviation, totalDeviation, cleanliness, purity, twiceChange decimal.Decimal, standardMap map[string]*Standard) (gradeName string) { checkItemGradeMap := make(map[constvar.CheckItem]string, 5) gradeRanks := make([]gradeRank, 0) for _, st := range standardMap { grade := "" for _, pair := range st.ValueList { switch st.CheckItem { case constvar.CheckItemDeviation: if st.SortType == ValueTypeSmallerBetter { if deviation.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if deviation.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemMaxDeviation: if st.SortType == ValueTypeSmallerBetter { if totalDeviation.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if totalDeviation.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemTwiceChange: if st.SortType == ValueTypeSmallerBetter { if twiceChange.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if twiceChange.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemCleanliness: if st.SortType == ValueTypeSmallerBetter { if cleanliness.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if cleanliness.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemPurity: if st.SortType == ValueTypeSmallerBetter { if purity.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if purity.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } } if grade != "" { break } } if grade == "" { grade = constvar.BadFinenessGradeC } checkItemGradeMap[st.CheckItem] = grade gradeRanks = append(gradeRanks, gradeRank{ gradeName: grade, gradeRank: st.GradeRank[grade], }) } if len(gradeRanks) == 0 { return "" } sort.Slice(gradeRanks, func(i, j int) bool { return gradeRanks[i].gradeRank < gradeRanks[j].gradeRank }) return gradeRanks[0].gradeName } // ToRoundedHalfFineness 小数处理(类似四舍五入) func ToRoundedHalfFineness(fineness float32) float32 { intPart := int(fineness) diff := fineness - float32(intPart) var result float32 if diff < 0.25 { result = float32(intPart) } else if diff < 0.75 { result = float32(intPart) + 0.5 } else { result = float32(intPart + 1) } // 保留一位小数,并在整数情况下在小数点后加一个零 result = float32(math.Round(float64(result)*10) / 10) return result }