Browse Source

statistic: 准确性分析

Yi 1 year ago
parent
commit
936877db37

+ 0 - 2
config/app.go

@@ -1,7 +1,6 @@
 package config
 
 import (
-	"fmt"
 	"kpt-tmr-group/pkg/di"
 	"os"
 	"strings"
@@ -70,7 +69,6 @@ func Options() *AppConfig {
 
 func init() {
 	appEnv = strings.ToLower(os.Getenv("APP_ENVIRONMENT"))
-	fmt.Println("=====APP_ENVIRONMENT======", appEnv)
 	cfg := &AppConfig{}
 	var err error
 	initOnce.Do(func() {

+ 24 - 0
http/handler/dashboard/dashboard.go

@@ -35,6 +35,30 @@ func AnalysisAccuracy(c *gin.Context) {
 	c.JSON(http.StatusOK, res)
 }
 
+// TopPasture 牧场排名
+func TopPasture(c *gin.Context) {
+	var req operationPb.SearchAnalysisAccuracyRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.PastureIds, valid.Required),
+		valid.Field(&req.CattleParentCategoryId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.TopPasture(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
 // ExecutionTime 执行时间
 func ExecutionTime(c *gin.Context) {
 

+ 1 - 2
http/route/app_api.go

@@ -124,9 +124,8 @@ func AppAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 
 		// 首页仪表盘
 		opsRoute.POST("/dashboard/accuracy", dashboard.AnalysisAccuracy)
+		opsRoute.POST("/dashboard/top_pasture", dashboard.TopPasture)
 		opsRoute.POST("/dashboard/exec_time", dashboard.ExecutionTime)
-
-		// 其他
 	}
 }
 

+ 1 - 1
main.go

@@ -10,7 +10,7 @@ import (
 )
 
 func main() {
-	logrus.Info("kpe-event: is starting")
+	logrus.Info("kpt-tmr-group: is starting")
 	cmd.Execute()
 	logrus.Error("kpt-tmr-group: is shut down")
 }

+ 28 - 14
model/analysis_accuracy.go

@@ -27,18 +27,6 @@ func (c *AnalysisAccuracy) TableName() string {
 	return "analysis_accuracy"
 }
 
-type OptionsAnalysisAccuracy struct {
-	PastureId            int64  `json:"pasture_id"`
-	PastureName          string `json:"pasture_name"`
-	AllIweight           int64  `json:"all_iweight"`
-	AllLweight           int64  `json:"all_lweight"`
-	AllOweight           int64  `json:"all_oweight"`
-	AllActualWeightMinus int64  `json:"all_actual_weight_minus"`
-	AllAllowRatio        int64  `json:"all_allow_ratio"`
-	AllAlweight          int64  `json:"all_alweight"`
-	DateDay              string `json:"date_day"`
-}
-
 type SearchAnalysisAccuracyResponse struct {
 	Code int32                 `json:"code"`
 	Msg  string                `json:"msg"`
@@ -51,8 +39,8 @@ type AnalysisAccuracyData struct {
 }
 
 type Table struct {
-	TitleList []*TableList   `json:"title_list"`
-	DataList  []*interface{} `json:"data_list"`
+	TitleList []*TableList `json:"title_list"`
+	DataList  *DataList    `json:"data_list"`
 }
 
 type TableList struct {
@@ -60,6 +48,13 @@ type TableList struct {
 	Value string `json:"value"`
 }
 
+type DataList struct {
+	MixedFodderAccurateRatio    []map[string]string `json:"mixed_fodder_accurate_ratio"`
+	MixedFodderCorrectRatio     []map[string]string `json:"mixed_fodder_correct_ratio"`
+	SprinkleFodderAccurateRatio []map[string]string `json:"sprinkle_fodder_accurate_ratio"`
+	SprinkleFodderCorrectRatio  []map[string]string `json:"sprinkle_fodder_correct_ratio"`
+}
+
 type Chart struct {
 	MixedFodderAccurateRatio    *CommonValueRatio `json:"mixed_fodder_accurate_ratio"`
 	MixedFodderCorrectRatio     *CommonValueRatio `json:"mixed_fodder_correct_ratio"`
@@ -71,8 +66,27 @@ type CommonValueRatio struct {
 	MaxValue    string     `json:"max_value"`    // 最高值
 	MiddleValue string     `json:"middle_value"` // 中位值
 	MinValue    string     `json:"min_value"`    // 最低值
+	TopOneName  string     `json:"top_one_name"` // 最高值牧场名称
 	DataList    [][]string `json:"data_list"`    // 数据集合
 	PastureName []string   `json:"pasture_name"` // 牧场名称集合
 	PastureIds  []int32    `json:"pasture_ids"`
 	DateDay     []string   `json:"date_day"` // 日期集合
 }
+
+type GetPastureTopResponse struct {
+	Code int32       `json:"code"`
+	Msg  string      `json:"msg"`
+	Data *PastureTop `json:"data"`
+}
+
+type PastureTop struct {
+	MixedFodderAccurateRatio    []*PastureTopData `json:"mixed_fodder_accurate_ratio"`
+	MixedFodderCorrectRatio     []*PastureTopData `json:"mixed_fodder_correct_ratio"`
+	SprinkleFodderAccurateRatio []*PastureTopData `json:"sprinkle_fodder_accurate_ratio"`
+	SprinkleFodderCorrectRatio  []*PastureTopData `json:"sprinkle_fodder_correct_ratio"`
+}
+
+type PastureTopData struct {
+	PastureName string  `json:"pasture_name"`
+	Ratio       float64 `json:"ratio"`
+}

+ 26 - 0
model/pasture_data.go

@@ -10,3 +10,29 @@ type PastureResponse struct {
 	Msg  string      `json:"msg"`
 	Data interface{} `json:"data"`
 }
+
+type DashboardAccuracyRequest struct {
+	CattleParentCategoryId int32  `json:"cattle_parent_category_id"`
+	FeedFormulaId          int32  `json:"feed_formula_id"`
+	StartDate              string `json:"start_date"`
+	EndDate                string `json:"end_date"`
+	PastureId              int32  `json:"pasture_id"`
+}
+
+type PastureAnalysisAccuracyResponse struct {
+	Code int32                        `json:"code"`
+	Msg  string                       `json:"msg"`
+	Data *PastureAnalysisAccuracyData `json:"data"`
+}
+
+type PastureAnalysisAccuracyData struct {
+	MixedFodderAccurateRatio    []*PastureAnalysisAccuracyDataValue `json:"mixed_fodder_accurate_ratio"`    // 混料准确率
+	MixedFodderCorrectRatio     []*PastureAnalysisAccuracyDataValue `json:"mixed_fodder_correct_ratio"`     // 混料正确率
+	SprinkleFodderAccurateRatio []*PastureAnalysisAccuracyDataValue `json:"sprinkle_fodder_accurate_ratio"` // 撒料准确率
+	SprinkleFodderCorrectRatio  []*PastureAnalysisAccuracyDataValue `json:"sprinkle_fodder_correct_ratio"`  // 撒料正确率
+}
+
+type PastureAnalysisAccuracyDataValue struct {
+	DayTime string  `json:"day_time"`
+	Ratio   float64 `json:"ratio"`
+}

+ 290 - 0
module/backend/dashboard_service.go

@@ -0,0 +1,290 @@
+package backend
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"kpt-tmr-group/model"
+	"kpt-tmr-group/pkg/logger/zaplog"
+	"kpt-tmr-group/pkg/tool"
+	"kpt-tmr-group/pkg/xerr"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	"net/http"
+	"sort"
+	"sync"
+
+	"go.uber.org/multierr"
+	"go.uber.org/zap"
+)
+
+func (s *StoreEntry) SearchPrefAnalysisData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[int64]*model.PastureAnalysisAccuracyData, error) {
+	groupPastureList, err := s.FindGroupPastureListByIds(ctx, req.PastureIds)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	res := make(map[int64]*model.PastureAnalysisAccuracyData, 0)
+	wg := sync.WaitGroup{}
+	wg.Add(len(groupPastureList))
+	var muError error
+	for _, pasture := range groupPastureList {
+		go func(p *model.GroupPasture) {
+			response := &model.PastureAnalysisAccuracyResponse{}
+			body := &model.DashboardAccuracyRequest{
+				PastureId:              int32(p.Id),
+				FeedFormulaId:          req.FeedFormulaId,
+				CattleParentCategoryId: int32(req.CattleParentCategoryId),
+				StartDate:              req.StartDate,
+				EndDate:                req.EndDate,
+			}
+			if err = s.PastureHttpClient(ctx, DashboardAccuracyUrl, p.Id, body, response); err != nil {
+				muError = multierr.Append(muError, err)
+				zaplog.Error("DistributeFeedFormula",
+					zap.String("url", DashboardAccuracyUrl),
+					zap.Any("pasture", p), zap.Any("body", body),
+					zap.Any("err", err), zap.Any("response", response))
+				b, _ := json.Marshal(body)
+				resB, _ := json.Marshal(response)
+				pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["FeedFormula_Distribute"], FeedFormulaDistributeUrl, string(b), string(resB))
+				s.DB.Create(pastureDataLog)
+			}
+			if response.Code != http.StatusOK {
+				muError = multierr.Append(muError, xerr.Custom(response.Msg))
+			}
+			res[p.Id] = response.Data
+			wg.Done()
+		}(pasture)
+	}
+	wg.Wait()
+	return res, nil
+}
+
+func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
+	res := &model.SearchAnalysisAccuracyResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &model.AnalysisAccuracyData{
+			Chart: &model.Chart{},
+			Table: &model.Table{
+				TitleList: make([]*model.TableList, 0),
+				DataList:  &model.DataList{},
+			},
+		},
+	}
+	res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
+		Name:  "title",
+		Value: "牧场",
+	})
+	pastureAnalysisAccuracy, err := s.SearchPrefAnalysisData(ctx, req)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	mixedFodderAccurateRatio, mixedFodderCorrectRatio, sprinkleFodderAccurateRatio, sprinkleFodderCorrectRatio :=
+		&model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}
+	maTitleValueList, mcTitleValueList, saTitleValueList, scTitleValueList := make([]float64, 0), make([]float64, 0), make([]float64, 0), make([]float64, 0)
+	mTopOneName := ""
+	for pastureId, data := range pastureAnalysisAccuracy {
+		b, _ := json.Marshal(data)
+		zaplog.Info("pastureAnalysisAccuracy", zap.String("body", string(b)))
+		groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
+		if err != nil {
+			zaplog.Error("SearchAnalysisAccuracy GetGroupPastureListById",
+				zap.Any("pastureId", pastureId), zap.Any("error", err))
+			continue
+		}
+
+		mixedFodderAccurateRatioDataList := make([]string, 0)
+		for _, v := range data.MixedFodderAccurateRatio {
+			mixedFodderAccurateRatioDataList = append(mixedFodderAccurateRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
+			mixedFodderAccurateRatio.DateDay = append(mixedFodderAccurateRatio.DateDay, v.DayTime)
+			maTitleValueList = append(maTitleValueList, v.Ratio)
+		}
+
+		mixedFodderAccurateRatio.DataList = append(mixedFodderAccurateRatio.DataList, mixedFodderAccurateRatioDataList)
+		mixedFodderAccurateRatio.PastureIds = append(mixedFodderAccurateRatio.PastureIds, int32(pastureId))
+		mixedFodderAccurateRatio.PastureName = append(mixedFodderAccurateRatio.PastureName, groupPasture.Name)
+
+		mixedFodderCorrectRatioDataList := make([]string, 0)
+		for _, v := range data.MixedFodderCorrectRatio {
+			mixedFodderCorrectRatioDataList = append(mixedFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
+			mixedFodderCorrectRatio.DateDay = append(mixedFodderCorrectRatio.DateDay, v.DayTime)
+			mcTitleValueList = append(mcTitleValueList, v.Ratio)
+		}
+
+		mixedFodderCorrectRatio.DataList = append(mixedFodderCorrectRatio.DataList, mixedFodderCorrectRatioDataList)
+		mixedFodderCorrectRatio.PastureIds = append(mixedFodderCorrectRatio.PastureIds, int32(pastureId))
+		mixedFodderCorrectRatio.PastureName = append(mixedFodderCorrectRatio.PastureName, groupPasture.Name)
+
+		sprinkleFodderRatioDataList := make([]string, 0)
+		for _, v := range data.SprinkleFodderAccurateRatio {
+			sprinkleFodderRatioDataList = append(sprinkleFodderRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
+			sprinkleFodderAccurateRatio.DateDay = append(sprinkleFodderAccurateRatio.DateDay, v.DayTime)
+			saTitleValueList = append(saTitleValueList, v.Ratio)
+		}
+
+		sprinkleFodderAccurateRatio.DataList = append(sprinkleFodderAccurateRatio.DataList, sprinkleFodderRatioDataList)
+		sprinkleFodderAccurateRatio.PastureIds = append(sprinkleFodderAccurateRatio.PastureIds, int32(pastureId))
+		sprinkleFodderAccurateRatio.PastureName = append(sprinkleFodderAccurateRatio.PastureName, groupPasture.Name)
+
+		sprinkleFodderCorrectRatioDataList := make([]string, 0)
+		for _, v := range data.SprinkleFodderCorrectRatio {
+			sprinkleFodderCorrectRatioDataList = append(sprinkleFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
+			sprinkleFodderCorrectRatio.DateDay = append(sprinkleFodderCorrectRatio.DateDay, v.DayTime)
+			scTitleValueList = append(scTitleValueList, v.Ratio)
+		}
+
+		sprinkleFodderCorrectRatio.DataList = append(sprinkleFodderCorrectRatio.DataList, sprinkleFodderCorrectRatioDataList)
+		sprinkleFodderCorrectRatio.PastureIds = append(sprinkleFodderCorrectRatio.PastureIds, int32(pastureId))
+		sprinkleFodderCorrectRatio.PastureName = append(sprinkleFodderCorrectRatio.PastureName, groupPasture.Name)
+	}
+
+	sort.Float64s(maTitleValueList)
+	mixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", maTitleValueList[len(maTitleValueList)-1])
+	mixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", maTitleValueList[0])
+	mixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(maTitleValueList))
+	mixedFodderAccurateRatio.TopOneName = mTopOneName
+
+	sort.Float64s(mcTitleValueList)
+	mixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", mcTitleValueList[len(mcTitleValueList)-1])
+	mixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", mcTitleValueList[0])
+	mixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(mcTitleValueList))
+	mixedFodderCorrectRatio.TopOneName = mTopOneName
+
+	sort.Float64s(saTitleValueList)
+	sprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", saTitleValueList[len(saTitleValueList)-1])
+	sprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", saTitleValueList[0])
+	sprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(saTitleValueList))
+	sprinkleFodderAccurateRatio.TopOneName = mTopOneName
+
+	sort.Float64s(scTitleValueList)
+	sprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", scTitleValueList[len(scTitleValueList)-1])
+	sprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", scTitleValueList[0])
+	sprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(scTitleValueList))
+	sprinkleFodderCorrectRatio.TopOneName = mTopOneName
+
+	chart := &model.Chart{
+		MixedFodderAccurateRatio:    mixedFodderAccurateRatio,
+		MixedFodderCorrectRatio:     mixedFodderCorrectRatio,
+		SprinkleFodderAccurateRatio: sprinkleFodderAccurateRatio,
+		SprinkleFodderCorrectRatio:  sprinkleFodderCorrectRatio,
+	}
+
+	res.Data.Chart = chart
+	res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy)
+	return res, nil
+}
+
+// TopPasture 牧场排名
+func (s *StoreEntry) TopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
+	res := &model.GetPastureTopResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &model.PastureTop{
+			MixedFodderAccurateRatio:    make([]*model.PastureTopData, 0),
+			MixedFodderCorrectRatio:     make([]*model.PastureTopData, 0),
+			SprinkleFodderAccurateRatio: make([]*model.PastureTopData, 0),
+			SprinkleFodderCorrectRatio:  make([]*model.PastureTopData, 0),
+		},
+	}
+	analysisAccuracy, err := s.SearchPrefAnalysisData(ctx, req)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	fmt.Println("========analysisAccuracy=========", analysisAccuracy)
+
+	/*time1, _ := time.ParseInLocation(model.LayoutDateFormat, req.StartDate, time.Local)
+	time2, _ := time.ParseInLocation(model.LayoutDateFormat, req.EndDate, time.Local)
+	timeLen := time2.Sub(time1).Hours() / 24
+
+	mapPastureList := make(map[string][]*model.OptionsAnalysisAccuracy, 0)
+	for _, v := range analysisAccuracy {
+		mapPastureList[v.PastureName] = append(mapPastureList[v.PastureName], v)
+	}*/
+
+	mixedFodderAccurateRatio := make([]*model.PastureTopData, 0)
+	/*for pastureName, data := range mapPastureList {
+		var allValueRatio float64
+		for _, v := range data {
+			allValueRatio += float64(v.AllIweight/v.AllLweight) / 100.0
+		}
+		average := allValueRatio / timeLen
+		mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, &model.PastureTopData{
+			PastureName: pastureName,
+			Ratio:       average,
+		})
+	}*/
+	sort.Slice(mixedFodderAccurateRatio, func(i, j int) bool {
+		return mixedFodderAccurateRatio[i].Ratio > mixedFodderAccurateRatio[j].Ratio
+	})
+	res.Data.MixedFodderAccurateRatio = mixedFodderAccurateRatio
+	return res, nil
+}
+
+func (s *StoreEntry) TitleList(ctx context.Context, pastureAnalysisList map[int64]*model.PastureAnalysisAccuracyData) *model.Table {
+	res := &model.Table{
+		TitleList: make([]*model.TableList, 0),
+		DataList: &model.DataList{
+			MixedFodderAccurateRatio:    make([]map[string]string, 0),
+			MixedFodderCorrectRatio:     make([]map[string]string, 0),
+			SprinkleFodderAccurateRatio: make([]map[string]string, 0),
+			SprinkleFodderCorrectRatio:  make([]map[string]string, 0),
+		},
+	}
+
+	for pastureId, data := range pastureAnalysisList {
+		groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
+		if err != nil {
+			zaplog.Info("TitleList", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err))
+			continue
+		}
+
+		if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) {
+			res.TitleList = append(res.TitleList, &model.TableList{
+				Name:  "title",
+				Value: "牧场",
+			})
+		}
+
+		maMap := map[string]string{
+			"title": groupPasture.Name,
+		}
+		for i, v := range data.MixedFodderCorrectRatio {
+			maMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
+			if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) {
+				res.TitleList = append(res.TitleList, &model.TableList{
+					Name:  fmt.Sprintf("data%d", i+1),
+					Value: v.DayTime,
+				})
+			}
+		}
+		res.DataList.MixedFodderAccurateRatio = append(res.DataList.MixedFodderAccurateRatio, maMap)
+
+		mcMap := map[string]string{
+			"title": groupPasture.Name,
+		}
+		for i, v := range data.MixedFodderCorrectRatio {
+			mcMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
+		}
+		res.DataList.MixedFodderCorrectRatio = append(res.DataList.MixedFodderCorrectRatio, mcMap)
+
+		saMap := map[string]string{
+			"title": groupPasture.Name,
+		}
+		for i, v := range data.SprinkleFodderAccurateRatio {
+			saMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
+		}
+		res.DataList.SprinkleFodderAccurateRatio = append(res.DataList.SprinkleFodderAccurateRatio, saMap)
+
+		scMap := map[string]string{
+			"title": groupPasture.Name,
+		}
+		for i, v := range data.SprinkleFodderCorrectRatio {
+			scMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
+		}
+		res.DataList.SprinkleFodderCorrectRatio = append(res.DataList.SprinkleFodderCorrectRatio, scMap)
+	}
+
+	return res
+}

+ 1 - 0
module/backend/interface.go

@@ -149,6 +149,7 @@ type StatisticService interface {
 
 	GetTrainNumber(ctx context.Context, req *operationPb.TrainNumberRequest) (*operationPb.TrainNumberResponse, error)
 	SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error)
+	TopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error)
 }
 
 type WxAppletService interface {

+ 15 - 0
module/backend/mock/kptservice.go

@@ -1108,6 +1108,21 @@ func (mr *MockKptServiceMockRecorder) SearchUserMaterialsStatistics(arg0, arg1 i
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchUserMaterialsStatistics", reflect.TypeOf((*MockKptService)(nil).SearchUserMaterialsStatistics), arg0, arg1)
 }
 
+// TopPasture mocks base method.
+func (m *MockKptService) TopPasture(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "TopPasture", arg0, arg1)
+	ret0, _ := ret[0].(*model.GetPastureTopResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// TopPasture indicates an expected call of TopPasture.
+func (mr *MockKptServiceMockRecorder) TopPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopPasture", reflect.TypeOf((*MockKptService)(nil).TopPasture), arg0, arg1)
+}
+
 // UserMaterialsStatisticsExcelExport mocks base method.
 func (m *MockKptService) UserMaterialsStatisticsExcelExport(arg0 context.Context, arg1 *operationPb.SearchUserMaterialsStatisticsRequest) (*bytes.Buffer, error) {
 	m.ctrl.T.Helper()

+ 24 - 20
module/backend/pasture_service.go

@@ -36,25 +36,6 @@ var (
 		operationPb.ForageCategoryParent_HALF_ROUGHAGE_HALF_CONCENTRATE: "粗料精料各半",
 		operationPb.ForageCategoryParent_OTHER:                          "其他",
 	}
-	ForageSourceMap = map[operationPb.ForageSource_Kind]string{
-		operationPb.ForageSource_SYSTEM_BUILT_IN: "系统内置",
-		operationPb.ForageSource_USER_DEFINED:    "用户自定义",
-	}
-	ForagePlanTypeMap = map[operationPb.ForagePlanType_Kind]string{
-		operationPb.ForagePlanType_INVALID:     "无",
-		operationPb.ForagePlanType_FORKLIFT:    "铲车",
-		operationPb.ForagePlanType_CONCENTRATE: "精料",
-	}
-	JumpDelaTypeMap = map[operationPb.JumpDelaType_Kind]string{
-		operationPb.JumpDelaType_INVALID: "禁用",
-		operationPb.JumpDelaType_THREE:   "3秒",
-		operationPb.JumpDelaType_SIX:     "6秒",
-		operationPb.JumpDelaType_NINE:    "9秒",
-	}
-	IsShowMap = map[operationPb.IsShow_Kind]string{
-		operationPb.IsShow_OK: "是",
-		operationPb.IsShow_NO: "否",
-	}
 )
 
 // CreateGroupPasture 创建集团牧场
@@ -66,6 +47,29 @@ func (s *StoreEntry) CreateGroupPasture(ctx context.Context, req *operationPb.Ad
 	return nil
 }
 
+func (s *StoreEntry) FindGroupPastureListByIds(ctx context.Context, pastureIds []int32) ([]*model.GroupPasture, error) {
+	groupPastureList := make([]*model.GroupPasture, 0)
+	if err := s.DB.Model(new(model.GroupPasture)).Where("is_delete = ? ", operationPb.IsShow_OK).
+		Where("id IN ?", pastureIds).
+		Find(&groupPastureList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return groupPastureList, nil
+}
+
+func (s *StoreEntry) GetGroupPastureListById(ctx context.Context, pastureId int64) (*model.GroupPasture, error) {
+	groupPasture := &model.GroupPasture{
+		Id: int64(pastureId),
+	}
+	if err := s.DB.Model(new(model.GroupPasture)).Where("is_delete = ? ", operationPb.IsShow_OK).
+		First(&groupPasture).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return groupPasture, nil
+}
+
 // EditGroupPasture 创建集团牧场
 func (s *StoreEntry) EditGroupPasture(ctx context.Context, req *operationPb.AddPastureRequest) error {
 	groupPasture := &model.GroupPasture{Id: int64(req.Id)}
@@ -114,7 +118,7 @@ func (s *StoreEntry) SearchGroupPastureList(ctx context.Context, req *operationP
 	}
 
 	if err := pref.Order("id desc").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)).
-		Find(&groupPasture).Debug().Error; err != nil {
+		Find(&groupPasture).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 

+ 4 - 119
module/backend/statistic_service.go

@@ -11,8 +11,6 @@ import (
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"sort"
-	"strconv"
-	"strings"
 
 	"github.com/xuri/excelize/v2"
 
@@ -21,7 +19,10 @@ import (
 
 type PastureClientHandler func(ctx context.Context, pastureId int64, body interface{}) error
 
-const FeedFormulaDistributeUrl = "pasture/feed_formula/distribute"
+const (
+	FeedFormulaDistributeUrl = "pasture/feed_formula/distribute"
+	DashboardAccuracyUrl     = "pasture/dashboard/accuracy_data"
+)
 
 // type eventHandler func(ev map[string]interface{}, openID string, appID string, enterpriseID int, cts int64, conn redis.Conn) error
 
@@ -619,119 +620,3 @@ func (s *StoreEntry) GetTrainNumber(ctx context.Context, req *operationPb.TrainN
 	result.Data.List = formulaOption
 	return result, nil
 }
-
-func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
-
-	dataList := &model.CommonValueRatio{
-		MaxValue:    "",
-		MiddleValue: "",
-		MinValue:    "",
-		PastureName: make([]string, 0),
-		DateDay:     make([]string, 0),
-		DataList:    make([][]string, 0),
-		PastureIds:  make([]int32, 0),
-	}
-	res := &model.SearchAnalysisAccuracyResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &model.AnalysisAccuracyData{
-			Chart: &model.Chart{
-				MixedFodderAccurateRatio:    dataList,
-				MixedFodderCorrectRatio:     dataList,
-				SprinkleFodderAccurateRatio: dataList,
-				SprinkleFodderCorrectRatio:  dataList,
-			},
-			Table: &model.Table{
-				TitleList: make([]*model.TableList, 0),
-				DataList:  make([]*interface{}, 0),
-			},
-		},
-	}
-	res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
-		Name:  "title",
-		Value: "牧场",
-	})
-
-	analysisAccuracy := make([]*model.OptionsAnalysisAccuracy, 0)
-	pref := s.DB.Model(new(model.AnalysisAccuracy))
-	if req.EndDate != "" && req.StartDate != "" {
-		pref.Where("date_day BETWEEN ? AND ?", req.StartDate, req.EndDate)
-	}
-
-	if req.CattleParentCategoryId > 0 {
-		pref.Where("cattle_parent_category_id = ?", req.CattleParentCategoryId)
-	}
-	if req.FeedFormulaId > 0 {
-		pref.Where("feed_formula_id = ?", req.FeedFormulaId)
-	}
-
-	if len(req.PastureIds) > 0 {
-		pref.Where("pasture_id IN ?", req.PastureIds)
-	}
-
-	if err := pref.Select("pasture_id,pasture_name,date_day,sum(iweight) as all_iweight,sum(lweight) as all_lweight,sum(oweight) as all_oweight,sum(actual_weight_minus) as all_actual_weight_minus,sum(allow_ratio) as all_allow_ratio,sum(alweight) as all_alweight").
-		Group("pasture_id,pasture_name,date_day").Order("pasture_name,date_day").Find(&analysisAccuracy).Debug().Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	mixedFodderAccurateRatio := make([]float64, 0)
-	mapPastureName := make(map[string]bool, 0)
-	mapDateDay := make(map[string]bool, 0)
-	mapRatio := make(map[string]bool, 0)
-	tableList := make([]*model.TableList, 0)
-	for k, v := range analysisAccuracy {
-		if _, ok := mapPastureName[v.PastureName]; !ok {
-			res.Data.Chart.MixedFodderAccurateRatio.PastureName = append(res.Data.Chart.MixedFodderAccurateRatio.PastureName, v.PastureName)
-			res.Data.Chart.MixedFodderAccurateRatio.PastureIds = append(res.Data.Chart.MixedFodderAccurateRatio.PastureIds, int32(v.PastureId))
-			mapPastureName[v.PastureName] = true
-		}
-
-		dataDayFormat := strings.TrimRight(v.DateDay, "T00:00:00+08:00")
-		if _, ok := mapDateDay[v.DateDay]; !ok {
-			res.Data.Chart.MixedFodderAccurateRatio.DateDay = append(res.Data.Chart.MixedFodderAccurateRatio.DateDay, dataDayFormat)
-			mapDateDay[v.DateDay] = true
-		}
-
-		valueRatio1 := float64(v.AllIweight/v.AllLweight) / 100.0
-		if _, ok := mapRatio[v.DateDay]; !ok {
-			valueRatio := make([]string, 0)
-			for _, a := range analysisAccuracy {
-				if a.DateDay == v.DateDay {
-					valueRatio = append(valueRatio, strconv.FormatFloat(float64(a.AllIweight/a.AllLweight)/100.0, 'f', 2, 64))
-				}
-			}
-			res.Data.Chart.MixedFodderAccurateRatio.DataList = append(res.Data.Chart.MixedFodderAccurateRatio.DataList, valueRatio)
-			mapRatio[v.DateDay] = true
-			tableList = append(tableList, &model.TableList{
-				Name:  fmt.Sprintf("date%d", k),
-				Value: dataDayFormat,
-			})
-		}
-		mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, valueRatio1)
-	}
-
-	mixedFodderAccurateRatioMaxValue, mixedFodderAccurateRatioMiddleValue, mixedFodderAccurateRatioMinValue := calculateRatio(mixedFodderAccurateRatio)
-	res.Data.Chart.MixedFodderAccurateRatio.MaxValue = strconv.FormatFloat(mixedFodderAccurateRatioMaxValue, 'f', 2, 64)
-	res.Data.Chart.MixedFodderAccurateRatio.MiddleValue = strconv.FormatFloat(mixedFodderAccurateRatioMiddleValue, 'f', 2, 64)
-	res.Data.Chart.MixedFodderAccurateRatio.MinValue = strconv.FormatFloat(mixedFodderAccurateRatioMinValue, 'f', 2, 64)
-
-	res.Data.Table.TitleList = append(res.Data.Table.TitleList, tableList...)
-
-	return res, nil
-}
-
-func calculateRatio(res []float64) (float64, float64, float64) {
-	var maxValue, middleValue, minValue, allValue float64 = 0, 0, 0, 0
-	for _, v := range res {
-		if v > maxValue {
-			maxValue = v
-		}
-		if v <= maxValue {
-			minValue = v
-		}
-
-		allValue += v
-	}
-	middleValue = allValue / float64(len(res))
-	return maxValue, middleValue, minValue
-}

+ 1 - 1
pkg/logger/logrus/log.go

@@ -35,7 +35,7 @@ func init() {
 	)
 	logrus.SetOutput(writer) // logrus 设置日志的输出方式
 	// Only log the warning severity or above.
-	logrus.SetLevel(WarnLevel)
+	logrus.SetLevel(DebugLevel)
 }
 
 // These are the different logging levels. You can set the logging level to log

+ 25 - 0
pkg/tool/tool.go

@@ -67,3 +67,28 @@ func Md5String(input string) string {
 	s.Write([]byte(digest))
 	return hex.EncodeToString(s.Sum(nil))
 }
+
+// TimeBetween 获取指定时间范围内天数
+// eg startTime => "2023-06-01" endTime => "2023-06-03"
+// return ["2023-06-01","2023-06-02","2023-06-03"]
+func TimeBetween(startTime, endTime string) []string {
+	startDate, _ := time.ParseInLocation("2006-01-02", startTime, time.Local)
+	endDate, _ := time.ParseInLocation("2006-01-02", endTime, time.Local)
+	timeList := make([]string, 0)
+	for endDate.After(startDate) {
+		timeList = append(timeList, startDate.Format("2006-01-02"))
+		startDate = startDate.AddDate(0, 0, 1)
+	}
+	timeList = append(timeList, endTime)
+	return timeList
+}
+
+// Median 获取切片的中位值
+func Median(nums []float64) float64 {
+	n := len(nums)
+	if n%2 == 0 {
+		return (nums[n/2-1] + nums[n/2]) / float64(2)
+	} else {
+		return nums[n/2]
+	}
+}