package service import ( "github.com/shopspring/decimal" "gorm.io/gorm" "math" "silkserver/constvar" "silkserver/models" "silkserver/utils" "sort" ) func FinenessCheck(finenessRegister *models.FinenessRegister, isNew bool) (err error) { standardMap, err := GetSilkRankStandard() if err != nil { return err } finenessCheckItems := make([]*models.FinenessCheckItem, 0) var lastCarNo int var allFinenessList []decimal.Decimal var personFinenessList []decimal.Decimal var carCheckNumber = 0 //单个car已检查样本数 endCarMap, err := GetWorkshopEndCarMap(finenessRegister.Workshop, finenessRegister.WorkshopGroup) if err != nil { return err } var item *models.FinenessCheckItem var deviation decimal.Decimal var finenessGrade string var roundingItemMap = make(map[float32]*models.FinenessRoundingItem, 0) for _, finenessItem := range finenessRegister.FinenessList { roundedHalfFineness := ToRoundedHalfFineness(finenessItem.Fineness) fineness := decimal.NewFromFloat32(roundedHalfFineness) allFinenessList = append(allFinenessList, fineness) personFinenessList = append(personFinenessList, fineness) carCheckNumber++ if carCheckNumber == constvar.EveryPersonCarCheckNumber { carCheckNumber = 0 if endCarMap[finenessItem.Position] { //走到了某个人最后的车号,每人算一次偏差和等级 deviation = utils.Deviation(personFinenessList) finenessGrade = CalcFinenessGrade(item.Deviation, item.TotalDeviation, item.Cleanliness, item.Purity, item.TwiceChange, standardMap) personFinenessList = personFinenessList[:0] } } if lastCarNo != finenessItem.Position { //每个车号存一个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: finenessRegister.ID, Position: lastCarNo, FinenessRoundingItems: roundingItems, Deviation: deviation, FinenessGrade: finenessGrade, Remark: "", } finenessCheckItems = append(finenessCheckItems, item) lastCarNo = finenessItem.Position roundingItemMap = make(map[float32]*models.FinenessRoundingItem, 0) } if roundingItemMap[roundedHalfFineness] == nil { roundingItemMap[roundedHalfFineness] = &models.FinenessRoundingItem{ Fineness: fineness, Quantity: 1, } } else { roundingItemMap[roundedHalfFineness].Quantity++ } } 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.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 } type gradeRank struct { gradeName string gradeRank int } 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 { if st.StartFineness.GreaterThan(deviation) || st.EndFineness.LessThan(deviation) { continue } grade := "" for _, pair := range st.ValueList { switch st.CheckItem { case constvar.CheckItemDeviation: if st.SortType == SortTypeAsc { if deviation.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if deviation.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemMaxDeviation: if st.SortType == SortTypeAsc { if totalDeviation.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if totalDeviation.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemTwiceChange: if st.SortType == SortTypeAsc { if twiceChange.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if twiceChange.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemCleanliness: if st.SortType == SortTypeAsc { if cleanliness.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if cleanliness.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } case constvar.CheckItemPurity: if st.SortType == SortTypeAsc { if purity.LessThanOrEqual(pair.RankValue) { grade = pair.RankName } } else { if purity.GreaterThanOrEqual(pair.RankValue) { grade = pair.RankName } } } if grade != "" { break } } if grade != "" { 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 } 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 } func FinenessReCheck(finenessCheck *models.FinenessCheck) (err error) { standardMap, err := GetSilkRankStandard() if err != nil { return err } finenessCheck.FinenessGrade = CalcFinenessGrade(finenessCheck.Deviation, finenessCheck.TotalDeviation, finenessCheck.Cleanliness, finenessCheck.Purity, finenessCheck.TwiceChange, standardMap) return }