statistic_service.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package backend
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "go.uber.org/zap"
  7. "kpt-tmr-group/model"
  8. "kpt-tmr-group/pkg/logger/zaplog"
  9. "kpt-tmr-group/pkg/xerr"
  10. operationPb "kpt-tmr-group/proto/go/backend/operation"
  11. "net/http"
  12. "strconv"
  13. "strings"
  14. )
  15. type PastureClientHandler func(ctx context.Context, pastureId int64, body interface{}) error
  16. // type eventHandler func(ev map[string]interface{}, openID string, appID string, enterpriseID int, cts int64, conn redis.Conn) error
  17. // PastureDetailById 获取指定牧场详情
  18. func (s *StoreEntry) PastureDetailById(ctx context.Context, pastureId int64) (*model.GroupPasture, error) {
  19. result := &model.GroupPasture{Id: pastureId}
  20. if err := s.DB.Where("is_delete = ? and is_show = ?", operationPb.IsShow_OK, operationPb.IsShow_OK).First(result).Error; err != nil {
  21. return nil, xerr.WithStack(err)
  22. }
  23. return result, nil
  24. }
  25. func (s *StoreEntry) PastureHttpClient(ctx context.Context, apiUrl string, pastureId int64, body interface{}, response interface{}) error {
  26. pastureDetail, err := s.PastureDetailById(ctx, pastureId)
  27. if err != nil {
  28. zaplog.Error("SearchFormulaEstimateList", zap.Any("Err", err), zap.Int64("pastureId", pastureId))
  29. return xerr.Customf("该牧场数据错误,Err:%s", err)
  30. }
  31. pastureClient := model.NewPastureClient(pastureDetail)
  32. url := fmt.Sprintf("%s/%s", pastureDetail.Domain, apiUrl)
  33. result, err := pastureClient.DoPost(url, body)
  34. if err != nil {
  35. return xerr.WithStack(err)
  36. }
  37. if err = json.Unmarshal(result, response); err != nil {
  38. return xerr.WithStack(err)
  39. }
  40. return nil
  41. }
  42. // SearchFormulaEstimateList 配方评估
  43. func (s *StoreEntry) SearchFormulaEstimateList(ctx context.Context, req *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error) {
  44. body := &model.PastureCommonRequest{
  45. Name: req.ApiName,
  46. Page: req.Pagination.Page,
  47. Offset: req.Pagination.PageOffset,
  48. PageCount: req.Pagination.PageSize,
  49. ReturnType: "Map",
  50. ParamMaps: &model.FormulaEstimateParams{
  51. PastureId: fmt.Sprintf("%d", req.PastureId),
  52. StartTime: req.StartTime,
  53. StopTime: req.EndTime,
  54. InputDatetime: nil,
  55. Search: fmt.Sprintf("%d", req.SearchType),
  56. TempletId: fmt.Sprintf("%d", req.TemplateId),
  57. Barid: fmt.Sprintf("%d", req.BarnId),
  58. },
  59. }
  60. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  61. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  62. return nil, xerr.WithStack(err)
  63. }
  64. return response, nil
  65. }
  66. // SearchInventoryStatistics 库存管理-库存统计
  67. func (s *StoreEntry) SearchInventoryStatistics(ctx context.Context, req *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error) {
  68. body := &model.PastureCommonRequest{
  69. Name: req.ApiName,
  70. Page: req.Pagination.Page,
  71. Offset: req.Pagination.PageOffset,
  72. PageCount: req.Pagination.PageSize,
  73. ReturnType: "Map",
  74. ParamMaps: &model.InventoryStatisticsParams{
  75. PastureId: fmt.Sprintf("%d", req.PastureId),
  76. StartTime: req.StartTime,
  77. StopTime: req.EndTime,
  78. FeedName: req.FeedName,
  79. },
  80. }
  81. response := &model.PastureCommonResponse{
  82. Data: &model.PastureCommonData{
  83. List: make([]*model.InventoryStatisticsList, 0),
  84. },
  85. }
  86. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  87. return nil, xerr.WithStack(err)
  88. }
  89. return response, nil
  90. }
  91. // SearchUserMaterialsStatistics 库存管理-用料分析
  92. func (s *StoreEntry) SearchUserMaterialsStatistics(ctx context.Context, req *operationPb.SearchUserMaterialsStatisticsRequest) (*model.PastureCommonResponse, error) {
  93. body := &model.PastureCommonRequest{
  94. Name: req.ApiName,
  95. Page: req.Pagination.Page,
  96. Offset: req.Pagination.PageOffset,
  97. PageCount: req.Pagination.PageSize,
  98. ReturnType: "Map",
  99. Checked: req.ErrorCheck,
  100. ParamMaps: &model.UserMaterialsStatisticsParams{
  101. PastureId: fmt.Sprintf("%d", req.PastureId),
  102. StartTime: req.StartTime,
  103. StopTime: req.EndTime,
  104. FeedName: req.FeedName,
  105. Typea: fmt.Sprintf("%d", req.TypeCheck),
  106. },
  107. }
  108. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  109. if err := s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
  110. return nil, xerr.WithStack(err)
  111. }
  112. return response, nil
  113. }
  114. // SearchFeedStatistics 饲喂效率-效率统计
  115. func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.SearchFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
  116. body := &model.PastureCommonRequest{
  117. Name: req.ApiName,
  118. Page: req.Pagination.Page,
  119. Offset: req.Pagination.PageOffset,
  120. PageCount: req.Pagination.PageSize,
  121. ReturnType: "Map",
  122. ParamMaps: &model.FeedStatisticsParams{
  123. PastureId: fmt.Sprintf("%d", req.PastureId),
  124. StartTime: req.StartTime,
  125. StopTime: req.StartTime,
  126. FeedName: req.FormulaTemplate,
  127. BarName: req.BarnName,
  128. CowClass: req.CattleCategoryName,
  129. Times: fmt.Sprintf("%d", req.ClassNumber),
  130. },
  131. }
  132. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  133. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  134. return nil, xerr.WithStack(err)
  135. }
  136. return response, nil
  137. }
  138. // FeedChartStatistics 饲喂效率图表分析
  139. func (s *StoreEntry) FeedChartStatistics(ctx context.Context, req *operationPb.FeedChartStatisticsRequest) (*model.PastureCommonResponse, error) {
  140. body := &model.FeedChartParams{
  141. ParamMaps: &model.ParamMaps{
  142. PastureId: fmt.Sprintf("%d", req.PastureId),
  143. StartTime: req.StartTime,
  144. StopTime: req.StartTime,
  145. Status: req.Status,
  146. },
  147. }
  148. url, ok := model.FeedCharUrl[req.ApiType]
  149. if !ok {
  150. return nil, xerr.Customf("错误的接口类型:%s", req.ApiType)
  151. }
  152. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  153. if err := s.PastureHttpClient(ctx, url, int64(req.PastureId), body, response); err != nil {
  154. return nil, xerr.WithStack(err)
  155. }
  156. return response, nil
  157. }
  158. func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
  159. dataList := &model.CommonValueRatio{
  160. MaxValue: "",
  161. MiddleValue: "",
  162. MinValue: "",
  163. PastureName: make([]string, 0),
  164. DateDay: make([]string, 0),
  165. DataList: make([][]string, 0),
  166. PastureIds: make([]int32, 0),
  167. }
  168. res := &model.SearchAnalysisAccuracyResponse{
  169. Code: http.StatusOK,
  170. Msg: "ok",
  171. Data: &model.AnalysisAccuracyData{
  172. Chart: &model.Chart{
  173. MixedFodderAccurateRatio: dataList,
  174. MixedFodderCorrectRatio: dataList,
  175. SprinkleFodderAccurateRatio: dataList,
  176. SprinkleFodderCorrectRatio: dataList,
  177. },
  178. Table: &model.Table{
  179. TitleList: make([]*model.TableList, 0),
  180. DataList: make([]*interface{}, 0),
  181. },
  182. },
  183. }
  184. res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
  185. Name: "title",
  186. Value: "牧场",
  187. })
  188. analysisAccuracy := make([]*model.OptionsAnalysisAccuracy, 0)
  189. pref := s.DB.Model(new(model.AnalysisAccuracy))
  190. if req.EndDate != "" && req.StartDate != "" {
  191. pref.Where("date_day BETWEEN ? AND ?", req.StartDate, req.EndDate)
  192. }
  193. if req.CattleParentCategoryId > 0 {
  194. pref.Where("cattle_parent_category_id = ?", req.CattleParentCategoryId)
  195. }
  196. if req.FeedFormulaId > 0 {
  197. pref.Where("feed_formula_id = ?", req.FeedFormulaId)
  198. }
  199. if len(req.PastureIds) > 0 {
  200. pref.Where("pasture_id IN ?", req.PastureIds)
  201. }
  202. 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").
  203. Group("pasture_id,pasture_name,date_day").Order("pasture_name,date_day").Find(&analysisAccuracy).Debug().Error; err != nil {
  204. return nil, xerr.WithStack(err)
  205. }
  206. mixedFodderAccurateRatio := make([]float64, 0)
  207. mapPastureName := make(map[string]bool, 0)
  208. mapDateDay := make(map[string]bool, 0)
  209. mapRatio := make(map[string]bool, 0)
  210. tableList := make([]*model.TableList, 0)
  211. for k, v := range analysisAccuracy {
  212. if _, ok := mapPastureName[v.PastureName]; !ok {
  213. res.Data.Chart.MixedFodderAccurateRatio.PastureName = append(res.Data.Chart.MixedFodderAccurateRatio.PastureName, v.PastureName)
  214. res.Data.Chart.MixedFodderAccurateRatio.PastureIds = append(res.Data.Chart.MixedFodderAccurateRatio.PastureIds, int32(v.PastureId))
  215. mapPastureName[v.PastureName] = true
  216. }
  217. dataDayFormat := strings.TrimRight(v.DateDay, "T00:00:00+08:00")
  218. if _, ok := mapDateDay[v.DateDay]; !ok {
  219. res.Data.Chart.MixedFodderAccurateRatio.DateDay = append(res.Data.Chart.MixedFodderAccurateRatio.DateDay, dataDayFormat)
  220. mapDateDay[v.DateDay] = true
  221. }
  222. valueRatio1 := float64(v.AllIweight/v.AllLweight) / 100.0
  223. if _, ok := mapRatio[v.DateDay]; !ok {
  224. valueRatio := make([]string, 0)
  225. for _, a := range analysisAccuracy {
  226. if a.DateDay == v.DateDay {
  227. valueRatio = append(valueRatio, strconv.FormatFloat(float64(a.AllIweight/a.AllLweight)/100.0, 'f', 2, 64))
  228. }
  229. }
  230. res.Data.Chart.MixedFodderAccurateRatio.DataList = append(res.Data.Chart.MixedFodderAccurateRatio.DataList, valueRatio)
  231. mapRatio[v.DateDay] = true
  232. tableList = append(tableList, &model.TableList{
  233. Name: fmt.Sprintf("date%d", k),
  234. Value: dataDayFormat,
  235. })
  236. }
  237. mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, valueRatio1)
  238. }
  239. mixedFodderAccurateRatioMaxValue, mixedFodderAccurateRatioMiddleValue, mixedFodderAccurateRatioMinValue := calculateRatio(mixedFodderAccurateRatio)
  240. res.Data.Chart.MixedFodderAccurateRatio.MaxValue = strconv.FormatFloat(mixedFodderAccurateRatioMaxValue, 'f', 2, 64)
  241. res.Data.Chart.MixedFodderAccurateRatio.MiddleValue = strconv.FormatFloat(mixedFodderAccurateRatioMiddleValue, 'f', 2, 64)
  242. res.Data.Chart.MixedFodderAccurateRatio.MinValue = strconv.FormatFloat(mixedFodderAccurateRatioMinValue, 'f', 2, 64)
  243. res.Data.Table.TitleList = append(res.Data.Table.TitleList, tableList...)
  244. return res, nil
  245. }
  246. func calculateRatio(res []float64) (float64, float64, float64) {
  247. var maxValue, middleValue, minValue, allValue float64 = 0, 0, 0, 0
  248. for _, v := range res {
  249. if v > maxValue {
  250. maxValue = v
  251. }
  252. if v <= maxValue {
  253. minValue = v
  254. }
  255. allValue += v
  256. }
  257. middleValue = allValue / float64(len(res))
  258. return maxValue, middleValue, minValue
  259. }