Browse Source

usage: 配方使用概况

Yi 1 year ago
parent
commit
ffeb7817ea
6 changed files with 179 additions and 1 deletions
  1. 1 1
      .drone.yml
  2. 17 0
      http/handle/group/feed_formula.go
  3. 1 0
      http/routers/group_api.go
  4. 67 0
      models/group_data.go
  5. 89 0
      module/group.go
  6. 4 0
      service/group/group.go

+ 1 - 1
.drone.yml

@@ -20,7 +20,7 @@ steps:
         from_secret: aliyun_password
       repo: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-tmr
       registry: registry.cn-hangzhou.aliyuncs.com
-      tags: [ shengmu ]
+      tags: [ 1.0.3,latest ]   # shengmu
 
 trigger:
   branch:

+ 17 - 0
http/handle/group/feed_formula.go

@@ -237,3 +237,20 @@ func CowCategoryDelete(c *gin.Context) {
 		})
 	}
 }
+
+// FeedUsage 配方使用概况
+func FeedUsage(c *gin.Context) {
+	appG := app.Gin{C: c}
+	var req models.FeedFormulaUsageRequest
+	if err := c.BindJSON(&req); err != nil {
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+	if res, err := group.FeedUsageService(&req); err != nil {
+		appG.Response(http.StatusBadRequest, e.ERROR_GET_S_FAIL, map[string]interface{}{
+			"error": err,
+		})
+	} else {
+		appG.Response(http.StatusOK, e.SUCCESS, res)
+	}
+}

+ 1 - 0
http/routers/group_api.go

@@ -23,5 +23,6 @@ func GroupAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		apiPasture.POST("forage_category/delete", group.ForageCategoryDelete)         // 饲料分类删除
 		apiPasture.POST("cattle_category/distribute", group.CowCategoryDistribute)    // 畜牧分类下发
 		apiPasture.POST("cattle_category/delete", group.CowCategoryDelete)            // 畜牧分类删除
+		apiPasture.POST("feed/usage", group.FeedUsage)                                // 配方使用概况
 	}
 }

+ 67 - 0
models/group_data.go

@@ -183,3 +183,70 @@ type FeedFormulaData struct {
 	PageSize int32           `json:"page_size"`
 	List     []*FeedTemplate `json:"list"`
 }
+
+type FeedFormulaUsageRequest struct {
+	PastureId     int32  `json:"pasture_id"`
+	FeedFormulaId int32  `json:"feed_formula_id"`
+	StartTime     string `json:"start_time"`
+	EndTime       string `json:"end_time"`
+}
+
+type FeedFormulaUsageResponse struct {
+	MixedFodderAccurateRatio    string `json:"mixed_fodder_accurate_ratio"`    // 混料准确率
+	MixedFodderCorrectRatio     string `json:"mixed_fodder_correct_ratio"`     // 混料正确率
+	SprinkleFodderAccurateRatio string `json:"sprinkle_fodder_accurate_ratio"` // 撒料准确率
+	SprinkleFodderCorrectRatio  string `json:"sprinkle_fodder_correct_ratio"`  // 撒料正确率
+	AddFeedTime                 string `json:"add_feed_time"`                  // 加料时间
+	SprinkleTime                string `json:"sprinkle_time"`                  // 撒料时间
+	StirTime                    string `json:"stir_time"`                      // 加料延迟时间
+	LastEditTime                string `json:"last_edit_time"`                 // 最后修改时间
+}
+
+type MixedDetail struct {
+	PlanTime                 string  `json:"plan_time"`                   // 计划时间
+	FeedFormulaId            int32   `json:"feed_formula_id"`             // 配方id
+	FeedFormulaName          string  `json:"feed_formula_name"`           // 配方名称
+	LWeight                  float64 `json:"l_weight"`                    // 理论重量
+	RealityWeight            float64 `json:"reality_weight"`              // 实际重量
+	PlanMixedOpts            int32   `json:"plan_mixed_opts"`             // 计划混料操作数
+	RealityMixedOpts         int32   `json:"reality_mixed_opts"`          // 已混料操作数
+	MixedOpsRatio            string  `json:"mixed_ops_ratio"`             // 混料操作率
+	MixedAutoJumpNumber      int32   `json:"mixed_auto_jump_number"`      // 混料自动跳转次数
+	MixedManualJumpNumber    int32   `json:"mixed_manual_jump_number"`    // 混料手动跳转次数
+	MixErrorNumber           int32   `json:"mix_error_number"`            // 混料误差值
+	MixedFodderAccurateRatio string  `json:"mixed_fodder_accurate_ratio"` // 混料准确率
+	Hlzq                     float64 `json:"hlzq"`
+	CancelNumber             int32   `json:"cancel_number"`               // 取消次数
+	VarianceRatio            float64 `json:"variance_ratio"`              // 方差
+	MixedFodderCorrectNumber string  `json:"mixed_fodder_correct_number"` // 混料正确数
+	MixedFodderCorrectRatio  string  `json:"mixed_fodder_correct_ratio"`  // 混料正确率
+	Hlzql                    float64 `json:"hlzql"`
+	Pid                      int32   `json:"pid"`
+	RemoveCancelCorrectRatio string  `json:"remove_cancel_correct_ratio"` // 去除取消正确率
+}
+
+type SprinkleDetail struct {
+	PlanTime                    string  `json:"plan_time"`                      // 计划时间
+	FeedFormulaId               int32   `json:"feed_formula_id"`                // 配方id
+	FeedFormulaName             string  `json:"feed_formula_name"`              // 配方名称
+	TmrName                     string  `json:"tmr_name"`                       // tmr名称
+	MixedTime                   string  `json:"mixed_time"`                     // 混料时间
+	WaitTime                    string  `json:"wait_time"`                      // 等待时间
+	LWeight                     float64 `json:"l_weight"`                       // 理论重量
+	RealityWeight               float64 `json:"reality_weight"`                 // 实际重量
+	PlanSprinkleOpts            int32   `json:"plan_sprinkle_opts"`             // 计划撒料操作数
+	RealitySprinkleOpts         int32   `json:"reality_sprinkle_opts"`          // 已撒料操作数
+	SprinkleOpsRatio            string  `json:"sprinkle_ops_ratio"`             // 撒料操作率
+	SprinkleAutoJumpNumber      int32   `json:"sprinkle_auto_jump_number"`      // 撒料自动跳转次数
+	SprinkleManualJumpNumber    int32   `json:"sprinkle_manual_jump_number"`    // 撒料手动跳转次数
+	SprinkleErrorNumber         int32   `json:"sprinkle_error_number"`          // 撒料误差值
+	SprinkleFodderAccurateRatio string  `json:"sprinkle_fodder_accurate_ratio"` // 撒料准确率
+	Slzq                        float64 `json:"slzq"`
+	CancelNumber                int32   `json:"cancel_number"`                  // 取消次数
+	VarianceRatio               float64 `json:"variance_ratio"`                 // 方差
+	SprinkleFodderCorrectNumber string  `json:"sprinkle_fodder_correct_number"` // 撒料正确数
+	SprinkleFodderCorrectRatio  string  `json:"sprinkle_fodder_correct_ratio"`  // 撒料正确率
+	Slzql                       float64 `json:"slzql"`
+	Pid                         int32   `json:"pid"`
+	RemoveCancelCorrectRatio    string  `json:"remove_cancel_correct_ratio"` // 去除取消正确率
+}

+ 89 - 0
module/group.go

@@ -2,8 +2,10 @@ package module
 
 import (
 	"errors"
+	"fmt"
 	"tmr-watch/http/handle/restful"
 	"tmr-watch/models"
+	"tmr-watch/pkg/logging"
 )
 
 const (
@@ -350,3 +352,90 @@ func FeedTemplateList(req *models.FeedFormulaListRequest) ([]*models.FeedTemplat
 	}
 	return res, total, nil
 }
+
+func FeedTemplateUsageDetail(req *models.FeedFormulaUsageRequest) (*models.FeedFormulaUsageResponse, error) {
+	mixedDetail, err := getMixedDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
+	if err != nil {
+		return nil, err
+	}
+	sprinkleDetail, err := getSprinkleDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
+	if err != nil {
+		return nil, err
+	}
+
+	response := &models.FeedFormulaUsageResponse{
+		MixedFodderAccurateRatio:    mixedDetail.MixedFodderAccurateRatio,
+		MixedFodderCorrectRatio:     mixedDetail.MixedFodderCorrectNumber,
+		SprinkleFodderAccurateRatio: sprinkleDetail.SprinkleFodderAccurateRatio,
+		SprinkleFodderCorrectRatio:  sprinkleDetail.SprinkleFodderCorrectRatio,
+		AddFeedTime:                 "",
+		SprinkleTime:                "",
+		StirTime:                    "",
+		LastEditTime:                "",
+	}
+	return response, nil
+}
+
+func getMixedDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.MixedDetail, error) {
+	sql := fmt.Sprintf("SELECT * FROM ( SELECT DATE(de.`date`) as plan_time,IFNULL((SELECT d.`templetname` "+
+		"FROM `downloadedplan` d WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.`fname`) as feed_formula_name,"+
+		"ROUND(SUM(de.`lweight`),2) as l_weight,ROUND(SUM(de.`actualweightminus`),2) as reality_weight,"+
+		"SUM(1) as plan_mixed_opts,SUM(de.`havebuttom`) as reality_mixed_opts, CONCAT(ROUND(SUM(de.`havebuttom`)/SUM(1)*100,2),'%')  as mixed_ops_ratio,"+
+		"SUM(IF(de.`buttontype` =1,1,0)) as mixed_auto_jump_number , SUM(IF(de.`buttontype`>1,1,0)) as mixed_manual_jump_number , "+
+		"ROUND(ABS(SUM(de.`lweight`)-SUM(de.`actualweightminus`)),2) as mix_error_number,"+
+		" CONCAT( IF (SUM(de.`actualweightminus`)>SUM(de.`lweight`),ROUND((SUM(de.`lweight`)/SUM(de.`actualweightminus`)*100),2) ,"+
+		"ROUND((SUM(de.`actualweightminus`)/SUM(de.`lweight`)*100) ,2)),'%') as mixed_fodder_accurate_ratio,"+
+		"IF (SUM(de.`actualweightminus`)>SUM(de.`lweight`),ROUND((SUM(de.`lweight`)/SUM(de.`actualweightminus`)*100),2) ,"+
+		"ROUND((SUM(de.`actualweightminus`)/SUM(de.`lweight`)*100) ,2)) hlzq,"+
+		"SUM(CASE WHEN (ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)>3 AND  de.`lweight` >30 AND de.`actualweightminus` >30 THEN 1 ELSE 0 END) as cancel_number,"+
+		"ROUND(STD(ABS(de.`actualweightminus`-de.`lweight`)) ,2) as variance_ratio,"+
+		"IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`feedallowratio` AND de.`actualweightminus`<>0,1,0)),0) as mixed_fodder_correct_number,"+
+		"CONCAT(ROUND(IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`feedallowratio` AND de.`actualweightminus`<>0,1,0))/SUM(1),0)*100,2),'%') as mixed_fodder_correct_ratio,"+
+		"ROUND(IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`feedallowratio` AND de.`actualweightminus`<>0,1,0))/SUM(1),0)*100,2) hlzql,"+
+		"TRIM(de.pid) pid,"+
+		"CONCAT(ROUND(IFNULL(SUM(IF(((ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)<=3 OR (de.`lweight` <30 AND de.`actualweightminus` <30 )),"+
+		"IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`feedallowratio` AND de.`actualweightminus`<>0,1,0),0))/SUM(IF(((ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)<=3 OR (de.`lweight` <30 AND de.`actualweightminus` <30 )),1,0 )),0)*100,2),'%') as remove_cancel_correct_ratio "+
+		"FROM `downloadplandtl1` de WHERE  de.pastureid= ? and de.intime is not null AND (SELECT d.`lpplantype` FROM `downloadedplan` d WHERE d.pastureid = de.pastureid AND d.id = de.pid) IN (0,1,4) and de.`date` >= ? AND de.`date` <= ? "+
+		"GROUP BY de.dateORDER BY mixed_fodder_accurate_ratio DESC,feed_formula_name) tmr HAVING  feed_formula_id = ?", pastureId, startTime, endTime, feedFormulaId)
+	logging.Debug("getMixedDetail-sql", sql)
+	dataList := &models.MixedDetail{}
+	if err := restful.Engine.NewSession().SQL(sql).Find(dataList); err != nil {
+		return nil, err
+	}
+	return dataList, nil
+}
+
+func getSprinkleDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.SprinkleDetail, error) {
+	sql := fmt.Sprintf("SELECT * FROM (SELECT DATE(d.`mydate`) AS plan_time,IFNULL((SELECT d.`templetname` FROM `downloadedplan` d "+
+		"WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.`fname`) AS feed_formula_name,"+
+		"IFNULL((SELECT d.`tempid` FROM `downloadedplan` d WHERE d.pastureid = de.pastureid AND d.id = de.pid),0) AS feed_formula_id,"+
+		"d.tmrtname AS tmr_name,"+
+		"IFNULL(TIMEDIFF ((SELECT MAX(intime) FROM downloadplandtl2 d2 WHERE  d2.`pid`=de.`pid` AND d2.pastureid = de.pastureid ),(SELECT MAX(intime) FROM downloadplandtl1_exec d2 WHERE  d2.`pid`=de.`pid` AND d2.pastureid = de.pastureid )),'00:00:00')  AS mixed_time,"+
+		"IFNULL(TIMEDIFF ((SELECT MIN(intime) FROM downloadplandtl2 d2 WHERE  d2.`pid`=de.`pid` AND d2.pastureid = de.pastureid ),(SELECT MAX(intime) FROM downloadplandtl1_exec d2 WHERE  d2.`pid`=de.`pid` AND d2.pastureid = de.pastureid )),'00:00:00')  AS wait_time,"+
+		"SUM(de.`lweight`) AS l_weight,ROUND(SUM(de.`actualweightminus`)) AS reality_weight,"+
+		"SUM(1) AS plan_sprinkle_opts,"+
+		"SUM(de.`havebuttom`) AS reality_sprinkle_opts, "+
+		"CONCAT(ROUND(SUM(de.`havebuttom`)/SUM(1)*100,2),'%')  AS sprinkle_ops_ratio, "+
+		"SUM(IF(de.`buttontype` =1,1,0)) AS sprinkle_auto_jump_number ,  "+
+		"SUM(IF(de.`buttontype`>1,1,0)) AS sprinkle_manual_jump_number ,"+
+		"ABS(SUM(de.`actualweightminus`)-SUM(de.`lweight`)) AS sprinkle_error_number,"+
+		" CONCAT( IF (SUM(de.`actualweightminus`)>SUM(de.`lweight`),ROUND((SUM(de.`lweight`)/SUM(de.`actualweightminus`)*100),2) ,"+
+		"ROUND((SUM(de.`actualweightminus`)/SUM(de.`lweight`)*100) ,2)),'%') AS sprinkle_fodder_accurate_ratio,"+
+		"IF (SUM(de.`actualweightminus`)>SUM(de.`lweight`),ROUND((SUM(de.`lweight`)/SUM(de.`actualweightminus`)*100),2) ,"+
+		"ROUND((SUM(de.`actualweightminus`)/SUM(de.`lweight`)*100) ,2)) slzq,"+
+		"SUM(CASE WHEN (ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)>3 AND  de.`lweight` >30 AND de.`actualweightminus` >30 THEN 1 ELSE 0 END) AS cancel_number,"+
+		"IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`allowratio` AND de.`actualweightminus`<>0,1,0)),0) AS sprinkle_fodder_correct_number,"+
+		"CONCAT(ROUND(IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`allowratio` AND de.`actualweightminus`<>0,1,0))/SUM(1),0)*100,2),'%') AS sprinkle_fodder_correct_ratio,"+
+		"ROUND(IFNULL(SUM(IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`allowratio` AND de.`actualweightminus`<>0,1,0))/SUM(1),0)*100,2) as slzql,"+
+		"TRIM(de.pid) pid,"+
+		"CONCAT(ROUND(IFNULL(SUM(IF(((ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)<=3 OR (de.`lweight` <30 AND de.`actualweightminus` <30 )),"+
+		"IF(ABS(de.`actualweightminus`-de.`lweight`)<=de.`allowratio` AND de.`actualweightminus`<>0,1,0),0))/SUM(IF(((ABS(de.`actualweightminus`-de.`lweight`)/de.`lweight`)<=3 OR (de.`lweight` <30 AND de.`actualweightminus` <30 )),1,0 )),0)*100,2),'%') AS remove_cancel_correct_ratio "+
+		"FROM `downloadplandtl2` de JOIN `downloadedplan` d ON d.`id`=de.`pid` AND d.pastureid = de.pastureid WHERE  d.pastureid = ? AND DATE(d.`mydate`)  BETWEEN ? AND '?   AND d.lpplantype IN (0,2)) tmr HAVING  feed_formula_id = ? ",
+		pastureId, startTime, endTime, feedFormulaId)
+	logging.Debug("getSprinkleDetail-sql", sql)
+	dataList := &models.SprinkleDetail{}
+	if err := restful.Engine.NewSession().SQL(sql).Find(dataList); err != nil {
+		return nil, err
+	}
+	return dataList, nil
+}

+ 4 - 0
service/group/group.go

@@ -312,3 +312,7 @@ func CategoryDeleteService(keyWord string, req *models.CategoryDeleteRequest) er
 	}
 	return nil
 }
+
+func FeedUsageService(req *models.FeedFormulaUsageRequest) (*models.FeedFormulaUsageResponse, error) {
+	return module.FeedTemplateUsageDetail(req)
+}