statistic_service.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. package backend
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  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. "sort"
  13. "strconv"
  14. "strings"
  15. "github.com/xuri/excelize/v2"
  16. "go.uber.org/zap"
  17. )
  18. type PastureClientHandler func(ctx context.Context, pastureId int64, body interface{}) error
  19. // type eventHandler func(ev map[string]interface{}, openID string, appID string, enterpriseID int, cts int64, conn redis.Conn) error
  20. // PastureDetailById 获取指定牧场详情
  21. func (s *StoreEntry) PastureDetailById(ctx context.Context, pastureId int64) (*model.GroupPasture, error) {
  22. result := &model.GroupPasture{Id: pastureId}
  23. if err := s.DB.Where("is_delete = ? and is_show = ?", operationPb.IsShow_OK, operationPb.IsShow_OK).First(result).Error; err != nil {
  24. return nil, xerr.WithStack(err)
  25. }
  26. return result, nil
  27. }
  28. func (s *StoreEntry) PastureHttpClient(ctx context.Context, apiUrl string, pastureId int64, body, response interface{}) error {
  29. pastureDetail, err := s.PastureDetailById(ctx, pastureId)
  30. if err != nil {
  31. zaplog.Error("SearchFormulaEstimateList", zap.Any("Err", err), zap.Int64("pastureId", pastureId))
  32. return xerr.Customf("该牧场数据错误,Err:%s", err)
  33. }
  34. pastureClient := model.NewPastureClient(pastureDetail)
  35. url := fmt.Sprintf("%s/%s", pastureDetail.Domain, apiUrl)
  36. result, err := pastureClient.DoPost(url, body)
  37. if err != nil {
  38. return xerr.WithStack(err)
  39. }
  40. zaplog.Info("PastureHttpClient", zap.String("url", url), zap.Any("request", body), zap.String("response", string(result)))
  41. if err = json.Unmarshal(result, response); err != nil {
  42. return xerr.WithStack(err)
  43. }
  44. return nil
  45. }
  46. // SearchFormulaEstimateList 配方评估
  47. func (s *StoreEntry) SearchFormulaEstimateList(ctx context.Context, req *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error) {
  48. body := &model.PastureCommonRequest{
  49. Name: req.ApiName,
  50. Page: req.Pagination.Page,
  51. Offset: req.Pagination.PageOffset,
  52. PageCount: req.Pagination.PageSize,
  53. ReturnType: "Map",
  54. ParamMaps: &model.FormulaEstimateParams{
  55. PastureId: fmt.Sprintf("%d", req.PastureId),
  56. StartTime: req.StartTime,
  57. StopTime: req.EndTime,
  58. Search: fmt.Sprintf("%d", req.SearchType),
  59. TempletId: fmt.Sprintf("%d", req.TemplateId),
  60. Barid: fmt.Sprintf("%d", req.BarnId),
  61. },
  62. }
  63. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  64. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  65. return nil, xerr.WithStack(err)
  66. }
  67. return response, nil
  68. }
  69. // SearchInventoryStatistics 库存管理-库存统计
  70. func (s *StoreEntry) SearchInventoryStatistics(ctx context.Context, req *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error) {
  71. body := &model.PastureCommonRequest{
  72. Name: req.ApiName,
  73. Page: req.Pagination.Page,
  74. Offset: req.Pagination.PageOffset,
  75. PageCount: req.Pagination.PageSize,
  76. ReturnType: "Map",
  77. ParamMaps: &model.InventoryStatisticsParams{
  78. PastureId: fmt.Sprintf("%d", req.PastureId),
  79. StartTime: req.StartTime,
  80. StopTime: req.EndTime,
  81. FeedName: req.FeedName,
  82. },
  83. }
  84. response := &model.PastureCommonResponse{
  85. Data: &model.PastureCommonData{
  86. List: make([]*model.InventoryStatisticsList, 0),
  87. },
  88. }
  89. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  90. return nil, xerr.WithStack(err)
  91. }
  92. return response, nil
  93. }
  94. // InventoryStatisticsExcelExport 库存管理-库存统计-报表导出
  95. func (s *StoreEntry) InventoryStatisticsExcelExport(ctx context.Context, req *operationPb.SearchInventoryStatisticsRequest) (*bytes.Buffer, error) {
  96. result, err := s.SearchInventoryStatistics(ctx, req)
  97. if err != nil {
  98. return nil, xerr.WithStack(err)
  99. }
  100. b, _ := json.Marshal(result.Data.List)
  101. inventoryStatisticsList := make([]*model.InventoryStatisticsList, 0)
  102. if err = json.Unmarshal(b, &inventoryStatisticsList); err != nil {
  103. return nil, xerr.Customf("牧场端返回数据错误")
  104. }
  105. file := excelize.NewFile()
  106. defer file.Close()
  107. streamWriter, err := file.NewStreamWriter(model.DefaultSheetName)
  108. if err != nil {
  109. return nil, xerr.WithStack(err)
  110. }
  111. // 表头
  112. titles := map[string][]interface{}{
  113. "A1": {"饲料名称", "期初", nil, "用料", nil, nil, nil, "期末"},
  114. "A2": {nil, "期初库存(kg)", "期初金额(元)", "入库重量(kg)", "系统出库重量(kg)", "人工用料重量(kg)", "损耗重量", "期末库存(kg)", "期末金额(kg)"},
  115. }
  116. for cell, values := range titles {
  117. if err = streamWriter.SetRow(cell, values); err != nil {
  118. return nil, xerr.WithStack(err)
  119. }
  120. }
  121. for i, item := range inventoryStatisticsList {
  122. cell, err := excelize.CoordinatesToCellName(1, i+3)
  123. if err != nil {
  124. zaplog.Error("InventoryStatisticsExcelExport CoordinatesToCellName", zap.Any("Err", err))
  125. continue
  126. }
  127. row := make([]interface{}, 0)
  128. row = append(row, item.FeedName, item.StartSum, item.StartPrice, item.LaidSum, item.UseSumXT, item.UseSumRG, item.UseSumXH, item.StopSum, item.StopPrice)
  129. if err = streamWriter.SetRow(cell, row); err != nil {
  130. return nil, xerr.WithStack(err)
  131. }
  132. }
  133. hvCell := map[string]string{
  134. "A1": "A2",
  135. "B1": "C1",
  136. "D1": "G1",
  137. "H1": "I1",
  138. }
  139. // 合并单元格
  140. for h, v := range hvCell {
  141. if err = streamWriter.MergeCell(h, v); err != nil {
  142. return nil, xerr.WithStack(err)
  143. }
  144. }
  145. // 修改样式
  146. /*style1, err := file.NewStyle(&excelize.Style{
  147. Fill: excelize.Fill{Type: "pattern", Color: []string{"#DFEBF6"}, Pattern: 1},
  148. Alignment: &excelize.Alignment{Horizontal: "center"},
  149. })
  150. if err != nil {
  151. return nil, xerr.WithStack(err)
  152. }
  153. style1, err := file.NewStyle(&excelize.Style{
  154. //Fill: excelize.Fill{Type: "pattern", Color: []string{"#DFEBF6"}, Pattern: 1},
  155. Alignment: &excelize.Alignment{Horizontal: "center"},
  156. })
  157. if err != nil {
  158. return nil, xerr.WithStack(err)
  159. }
  160. if err = file.SetCellStyle(model.DefaultSheetName, "A1", "A1", style1); err != nil {
  161. return nil, xerr.WithStack(err)
  162. }*/
  163. if err = streamWriter.Flush(); err != nil {
  164. return nil, xerr.WithStack(err)
  165. }
  166. return file.WriteToBuffer()
  167. }
  168. // SearchUserMaterialsStatistics 库存管理-用料分析
  169. func (s *StoreEntry) SearchUserMaterialsStatistics(ctx context.Context, req *operationPb.SearchUserMaterialsStatisticsRequest) (*model.PastureCommonResponse, error) {
  170. body := &model.PastureCommonRequest{
  171. Name: req.ApiName,
  172. Page: req.Pagination.Page,
  173. Offset: req.Pagination.PageOffset,
  174. PageCount: req.Pagination.PageSize,
  175. ReturnType: "Map",
  176. Checked: req.ErrorCheck,
  177. ParamMaps: &model.UserMaterialsStatisticsParams{
  178. PastureId: fmt.Sprintf("%d", req.PastureId),
  179. StartTime: req.StartTime,
  180. StopTime: req.EndTime,
  181. FeedName: req.FeedName,
  182. Typea: fmt.Sprintf("%d", req.TypeCheck),
  183. },
  184. }
  185. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{
  186. List: &model.UserMaterialsList{},
  187. }}
  188. if err := s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
  189. return nil, xerr.WithStack(err)
  190. }
  191. return response, nil
  192. }
  193. func (s *StoreEntry) UserMaterialsStatisticsExcelExport(ctx context.Context, req *operationPb.SearchUserMaterialsStatisticsRequest) (*bytes.Buffer, error) {
  194. result, err := s.SearchUserMaterialsStatistics(ctx, req)
  195. if err != nil {
  196. return nil, xerr.WithStack(err)
  197. }
  198. b, _ := json.Marshal(result.Data.List)
  199. userMaterialsList := &model.UserMaterialsList{}
  200. if err = json.Unmarshal(b, userMaterialsList); err != nil {
  201. return nil, xerr.Customf("牧场端返回数据错误")
  202. }
  203. file := excelize.NewFile()
  204. defer file.Close()
  205. streamWriter, err := file.NewStreamWriter(model.DefaultSheetName)
  206. if err != nil {
  207. return nil, xerr.WithStack(err)
  208. }
  209. // 表数据
  210. excelValuesList := map[int][]interface{}{}
  211. cProp := make([]string, 0)
  212. for _, data2 := range userMaterialsList.Data2 {
  213. excelValuesList[1] = append(excelValuesList[1], data2.Label)
  214. for _, c := range data2.Children {
  215. excelValuesList[2] = append(excelValuesList[2], c.Label)
  216. cProp = append(cProp, c.Prop)
  217. }
  218. }
  219. for cell, values := range excelValuesList {
  220. if err = streamWriter.SetRow(fmt.Sprintf("A%d", cell), values); err != nil {
  221. return nil, xerr.WithStack(err)
  222. }
  223. delete(excelValuesList, cell)
  224. }
  225. for i, data1 := range userMaterialsList.Data1 {
  226. data1Map, ok := data1.(map[string]interface{})
  227. if ok {
  228. for _, prop := range cProp {
  229. newValue := ""
  230. if value, yes := data1Map[prop]; yes {
  231. if value != nil {
  232. switch v := value.(type) {
  233. case string:
  234. newValue = v
  235. case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
  236. newValue = fmt.Sprintf("%d", v)
  237. default:
  238. newValue = fmt.Sprintf("%v", v)
  239. }
  240. }
  241. excelValuesList[i+3] = append(excelValuesList[i+3], newValue)
  242. }
  243. }
  244. }
  245. }
  246. excelValuesKeys := make([]int, 0)
  247. for k, _ := range excelValuesList {
  248. excelValuesKeys = append(excelValuesKeys, k)
  249. }
  250. sort.Ints(excelValuesKeys)
  251. for _, v := range excelValuesKeys {
  252. if err = streamWriter.SetRow(fmt.Sprintf("A%d", v), excelValuesList[v]); err != nil {
  253. return nil, xerr.WithStack(err)
  254. }
  255. }
  256. if err = streamWriter.Flush(); err != nil {
  257. return nil, xerr.WithStack(err)
  258. }
  259. return file.WriteToBuffer()
  260. }
  261. // SearchPriceStatistics 库存管理-价格分析
  262. func (s *StoreEntry) SearchPriceStatistics(ctx context.Context, req *operationPb.SearchPriceStatisticsRequest) (*model.PastureCommonResponse, error) {
  263. body := &model.PastureCommonRequest{
  264. Name: req.ApiName,
  265. Page: req.Pagination.Page,
  266. Offset: req.Pagination.PageOffset,
  267. PageCount: req.Pagination.PageSize,
  268. ReturnType: "Map",
  269. ParamMaps: &model.PriceStatisticsParams{
  270. PastureId: fmt.Sprintf("%d", req.PastureId),
  271. StartTime: req.StartTime,
  272. StopTime: req.EndTime,
  273. FeedName: req.FeedName,
  274. },
  275. }
  276. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  277. if err := s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
  278. return nil, xerr.WithStack(err)
  279. }
  280. return response, nil
  281. }
  282. // SearchFeedStatistics 饲喂效率-效率统计
  283. func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.SearchFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
  284. body := &model.PastureCommonRequest{
  285. Name: req.ApiName,
  286. Page: req.Pagination.Page,
  287. Offset: req.Pagination.PageOffset,
  288. PageCount: req.Pagination.PageSize,
  289. ReturnType: "Map",
  290. ParamMaps: &model.FeedStatisticsParams{
  291. PastureId: fmt.Sprintf("%d", req.PastureId),
  292. StartTime: req.StartTime,
  293. StopTime: req.StartTime,
  294. Date: req.StartTime,
  295. FeedTName: req.FormulaTemplate,
  296. BarName: req.BarnName,
  297. CowClass: req.CattleCategoryName,
  298. Times: fmt.Sprintf("%d", req.ClassNumber),
  299. },
  300. }
  301. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  302. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  303. return nil, xerr.WithStack(err)
  304. }
  305. return response, nil
  306. }
  307. // FeedChartStatistics 饲喂效率图表分析
  308. func (s *StoreEntry) FeedChartStatistics(ctx context.Context, req *operationPb.FeedChartStatisticsRequest) (*model.PastureCommonResponse, error) {
  309. body := &model.FeedChartParams{
  310. ParamMaps: &model.ParamMaps{
  311. PastureId: fmt.Sprintf("%d", req.PastureId),
  312. StartTime: req.StartTime,
  313. StopTime: req.StartTime,
  314. Status: req.Status,
  315. },
  316. }
  317. url, ok := model.UrlChart[req.ApiType]
  318. if !ok {
  319. return nil, xerr.Customf("错误的接口类型:%s", req.ApiType)
  320. }
  321. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  322. if err := s.PastureHttpClient(ctx, url, int64(req.PastureId), body, response); err != nil {
  323. return nil, xerr.WithStack(err)
  324. }
  325. return response, nil
  326. }
  327. // CowsAnalysis 饲喂效率-牛群评估
  328. func (s *StoreEntry) CowsAnalysis(ctx context.Context, req *operationPb.CowsAnalysisRequest) (*model.PastureCommonResponse, error) {
  329. body := &model.PastureCommonRequest{
  330. Name: req.ApiName,
  331. Page: req.Pagination.Page,
  332. Offset: req.Pagination.PageOffset,
  333. PageCount: req.Pagination.PageSize,
  334. ReturnType: "Map",
  335. ParamMaps: &model.MixFeedStatisticsParams{
  336. PastureId: fmt.Sprintf("%d", req.PastureId),
  337. StartTime: req.StartTime,
  338. StopTime: req.StartTime,
  339. },
  340. }
  341. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  342. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  343. return nil, xerr.WithStack(err)
  344. }
  345. return response, nil
  346. }
  347. // SearchAccuracyAggStatistics 准确性分析-汇总分析
  348. func (s *StoreEntry) SearchAccuracyAggStatistics(ctx context.Context, req *operationPb.AccuracyAggStatisticsRequest) (*model.PastureCommonResponse, error) {
  349. body := &model.FeedChartParams{
  350. ParamMaps: &model.AccuracyAggParams{
  351. PastureId: fmt.Sprintf("%d", req.PastureId),
  352. StartTime: req.StartTime,
  353. StopTime: req.EndTime,
  354. FName: req.Fname,
  355. Sort: req.Sort,
  356. Status: req.Status,
  357. Times: req.Times,
  358. Genre: req.Genre,
  359. IsDate: req.Isdate,
  360. Hlwc1: req.Hlwc1,
  361. Hlwc2: req.Hlwc2,
  362. Hlzq1: req.Hlzq1,
  363. Hlzq2: req.Hlzq2,
  364. Hlzql1: req.Hlzql1,
  365. Hlzql2: req.Hlzql2,
  366. Slwc1: req.Slwc1,
  367. Slwc2: req.Slwc2,
  368. Slzq1: req.Slzq1,
  369. Slzq2: req.Slzq2,
  370. Slzql1: req.Slzql1,
  371. Slzql2: req.Slzql2,
  372. Error: req.IsError,
  373. },
  374. }
  375. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  376. if err := s.PastureHttpClient(ctx, model.UrlSummary, int64(req.PastureId), body, response); err != nil {
  377. return nil, xerr.WithStack(err)
  378. }
  379. return response, nil
  380. }
  381. // SearchMixFeedStatistics 准确性分析-混料统计
  382. func (s *StoreEntry) SearchMixFeedStatistics(ctx context.Context, req *operationPb.MixFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
  383. times := ""
  384. if req.ClassNumber > 0 {
  385. times = fmt.Sprintf("%d", req.ClassNumber)
  386. }
  387. body := &model.PastureCommonRequest{
  388. Name: req.ApiName,
  389. Page: req.Pagination.Page,
  390. Offset: req.Pagination.PageOffset,
  391. PageCount: req.Pagination.PageSize,
  392. ReturnType: "Map",
  393. ParamMaps: &model.MixFeedStatisticsParams{
  394. PastureId: fmt.Sprintf("%d", req.PastureId),
  395. StartTime: req.StartTime,
  396. StopTime: req.StartTime,
  397. TmrTName: req.EquipmentName,
  398. ProjName: req.TrainNumber,
  399. Times: times,
  400. ButtonType: req.ButtonType,
  401. TempletName: req.FormulationName,
  402. Isuse: req.IsUse,
  403. Hlwc1: req.Hlwc1,
  404. Hlwc2: req.Hlwc2,
  405. Hlzq1: req.Hlzq1,
  406. Hlzq2: req.Hlzq2,
  407. Hlzql1: req.Hlzql1,
  408. Hlzql2: req.Hlzql2,
  409. Error: req.IsError,
  410. },
  411. }
  412. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  413. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  414. return nil, xerr.WithStack(err)
  415. }
  416. return response, nil
  417. }
  418. // SearchSprinkleStatistics 准确性分析-撒料统计
  419. func (s *StoreEntry) SearchSprinkleStatistics(ctx context.Context, req *operationPb.SprinkleStatisticsRequest) (*model.PastureCommonResponse, error) {
  420. times := ""
  421. if req.ClassNumber > 0 {
  422. times = fmt.Sprintf("%d", req.ClassNumber)
  423. }
  424. body := &model.PastureCommonRequest{
  425. Name: req.ApiName,
  426. Page: req.Pagination.Page,
  427. Offset: req.Pagination.PageOffset,
  428. PageCount: req.Pagination.PageSize,
  429. ReturnType: "Map",
  430. ParamMaps: &model.SprinkleStatisticsParams{
  431. PastureId: fmt.Sprintf("%d", req.PastureId),
  432. StartTime: req.StartTime,
  433. StopTime: req.StartTime,
  434. TmrTName: req.EquipmentName,
  435. ProjName: req.TrainNumber,
  436. Times: times,
  437. ButtonType: req.ButtonType,
  438. TempletName: req.FormulationName,
  439. Isuse: req.IsUse,
  440. Fname: req.BarnName,
  441. Slwc1: req.Slwc1,
  442. Slwc2: req.Slwc2,
  443. Slzq2: req.Slzq2,
  444. Slzq1: req.Slzq1,
  445. Slzql1: req.Slzql1,
  446. Slzql2: req.Slzql2,
  447. Error: req.IsError,
  448. },
  449. }
  450. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  451. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  452. return nil, xerr.WithStack(err)
  453. }
  454. return response, nil
  455. }
  456. // SearchProcessAnalysis 过程分析
  457. func (s *StoreEntry) SearchProcessAnalysis(ctx context.Context, req *operationPb.ProcessAnalysisRequest) (*model.PastureCommonResponse, error) {
  458. body := &model.PastureCommonRequest{
  459. Name: req.ApiName,
  460. Page: req.Pagination.Page,
  461. Offset: req.Pagination.PageOffset,
  462. PageCount: req.Pagination.PageSize,
  463. ReturnType: "Map",
  464. ParamMaps: &model.ProcessAnalysisParams{
  465. PastureId: fmt.Sprintf("%d", req.PastureId),
  466. StartTime: req.StartTime,
  467. StopTime: req.StartTime,
  468. TmrTName: req.TmrName,
  469. IsCompleted: "",
  470. LpPlanType: fmt.Sprintf("%d", req.PlanType),
  471. FClassId: req.MixFeedType,
  472. Hlzq1: req.Hlzq1,
  473. Hlzq2: req.Hlzq2,
  474. Hlwc1: req.Hlwc1,
  475. Hlwc2: req.Hlwc2,
  476. Slwc1: req.Slwc1,
  477. Slwc2: req.Slwc2,
  478. Slzq2: req.Slzq2,
  479. Slzq1: req.Slzq1,
  480. Error: req.ErrorRange,
  481. },
  482. }
  483. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  484. if err := s.PastureHttpClient(ctx, model.UrlProcess, int64(req.PastureId), body, response); err != nil {
  485. return nil, xerr.WithStack(err)
  486. }
  487. return response, nil
  488. }
  489. // GetTrainNumber 获取班次
  490. func (s *StoreEntry) GetTrainNumber(ctx context.Context, req *operationPb.TrainNumberRequest) (*operationPb.TrainNumberResponse, error) {
  491. body := &model.PastureCommonRequest{
  492. Name: req.ApiName,
  493. Page: req.Pagination.Page,
  494. Offset: req.Pagination.PageOffset,
  495. PageCount: req.Pagination.PageSize,
  496. ReturnType: "Map",
  497. ParamMaps: &model.TrainNumberParams{
  498. PastureId: fmt.Sprintf("%d", req.PastureId),
  499. InfoRName: req.InfoName,
  500. },
  501. }
  502. response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
  503. if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
  504. return nil, xerr.WithStack(err)
  505. }
  506. result := &operationPb.TrainNumberResponse{
  507. Code: http.StatusOK,
  508. Msg: "ok",
  509. Data: &operationPb.TrainNumberData{List: make([]*operationPb.FormulaOptionEnum, 0)},
  510. }
  511. if response.Data.List == nil {
  512. return result, nil
  513. }
  514. b, _ := json.Marshal(response.Data.List)
  515. trainNumberList := make([]*model.TrainNumberList, 0)
  516. if err := json.Unmarshal(b, &trainNumberList); err != nil {
  517. return nil, xerr.WithStack(err)
  518. }
  519. formulaOption := make([]*operationPb.FormulaOptionEnum, 0)
  520. if len(trainNumberList) > 0 {
  521. infoValue := trainNumberList[0].InfoValue
  522. switch infoValue {
  523. case "1":
  524. formulaOption = append(formulaOption, &operationPb.FormulaOptionEnum{
  525. Value: 1,
  526. Label: "第一班",
  527. })
  528. case "2":
  529. formulaOption = append(formulaOption, &operationPb.FormulaOptionEnum{
  530. Value: 1,
  531. Label: "第一班",
  532. }, &operationPb.FormulaOptionEnum{
  533. Value: 2,
  534. Label: "第二班",
  535. })
  536. case "3":
  537. formulaOption = append(formulaOption, &operationPb.FormulaOptionEnum{
  538. Value: 1,
  539. Label: "第一班",
  540. }, &operationPb.FormulaOptionEnum{
  541. Value: 2,
  542. Label: "第二班",
  543. }, &operationPb.FormulaOptionEnum{
  544. Value: 3,
  545. Label: "第三班",
  546. })
  547. }
  548. }
  549. result.Data.List = formulaOption
  550. return result, nil
  551. }
  552. func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
  553. dataList := &model.CommonValueRatio{
  554. MaxValue: "",
  555. MiddleValue: "",
  556. MinValue: "",
  557. PastureName: make([]string, 0),
  558. DateDay: make([]string, 0),
  559. DataList: make([][]string, 0),
  560. PastureIds: make([]int32, 0),
  561. }
  562. res := &model.SearchAnalysisAccuracyResponse{
  563. Code: http.StatusOK,
  564. Msg: "ok",
  565. Data: &model.AnalysisAccuracyData{
  566. Chart: &model.Chart{
  567. MixedFodderAccurateRatio: dataList,
  568. MixedFodderCorrectRatio: dataList,
  569. SprinkleFodderAccurateRatio: dataList,
  570. SprinkleFodderCorrectRatio: dataList,
  571. },
  572. Table: &model.Table{
  573. TitleList: make([]*model.TableList, 0),
  574. DataList: make([]*interface{}, 0),
  575. },
  576. },
  577. }
  578. res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
  579. Name: "title",
  580. Value: "牧场",
  581. })
  582. analysisAccuracy := make([]*model.OptionsAnalysisAccuracy, 0)
  583. pref := s.DB.Model(new(model.AnalysisAccuracy))
  584. if req.EndDate != "" && req.StartDate != "" {
  585. pref.Where("date_day BETWEEN ? AND ?", req.StartDate, req.EndDate)
  586. }
  587. if req.CattleParentCategoryId > 0 {
  588. pref.Where("cattle_parent_category_id = ?", req.CattleParentCategoryId)
  589. }
  590. if req.FeedFormulaId > 0 {
  591. pref.Where("feed_formula_id = ?", req.FeedFormulaId)
  592. }
  593. if len(req.PastureIds) > 0 {
  594. pref.Where("pasture_id IN ?", req.PastureIds)
  595. }
  596. 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").
  597. Group("pasture_id,pasture_name,date_day").Order("pasture_name,date_day").Find(&analysisAccuracy).Debug().Error; err != nil {
  598. return nil, xerr.WithStack(err)
  599. }
  600. mixedFodderAccurateRatio := make([]float64, 0)
  601. mapPastureName := make(map[string]bool, 0)
  602. mapDateDay := make(map[string]bool, 0)
  603. mapRatio := make(map[string]bool, 0)
  604. tableList := make([]*model.TableList, 0)
  605. for k, v := range analysisAccuracy {
  606. if _, ok := mapPastureName[v.PastureName]; !ok {
  607. res.Data.Chart.MixedFodderAccurateRatio.PastureName = append(res.Data.Chart.MixedFodderAccurateRatio.PastureName, v.PastureName)
  608. res.Data.Chart.MixedFodderAccurateRatio.PastureIds = append(res.Data.Chart.MixedFodderAccurateRatio.PastureIds, int32(v.PastureId))
  609. mapPastureName[v.PastureName] = true
  610. }
  611. dataDayFormat := strings.TrimRight(v.DateDay, "T00:00:00+08:00")
  612. if _, ok := mapDateDay[v.DateDay]; !ok {
  613. res.Data.Chart.MixedFodderAccurateRatio.DateDay = append(res.Data.Chart.MixedFodderAccurateRatio.DateDay, dataDayFormat)
  614. mapDateDay[v.DateDay] = true
  615. }
  616. valueRatio1 := float64(v.AllIweight/v.AllLweight) / 100.0
  617. if _, ok := mapRatio[v.DateDay]; !ok {
  618. valueRatio := make([]string, 0)
  619. for _, a := range analysisAccuracy {
  620. if a.DateDay == v.DateDay {
  621. valueRatio = append(valueRatio, strconv.FormatFloat(float64(a.AllIweight/a.AllLweight)/100.0, 'f', 2, 64))
  622. }
  623. }
  624. res.Data.Chart.MixedFodderAccurateRatio.DataList = append(res.Data.Chart.MixedFodderAccurateRatio.DataList, valueRatio)
  625. mapRatio[v.DateDay] = true
  626. tableList = append(tableList, &model.TableList{
  627. Name: fmt.Sprintf("date%d", k),
  628. Value: dataDayFormat,
  629. })
  630. }
  631. mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, valueRatio1)
  632. }
  633. mixedFodderAccurateRatioMaxValue, mixedFodderAccurateRatioMiddleValue, mixedFodderAccurateRatioMinValue := calculateRatio(mixedFodderAccurateRatio)
  634. res.Data.Chart.MixedFodderAccurateRatio.MaxValue = strconv.FormatFloat(mixedFodderAccurateRatioMaxValue, 'f', 2, 64)
  635. res.Data.Chart.MixedFodderAccurateRatio.MiddleValue = strconv.FormatFloat(mixedFodderAccurateRatioMiddleValue, 'f', 2, 64)
  636. res.Data.Chart.MixedFodderAccurateRatio.MinValue = strconv.FormatFloat(mixedFodderAccurateRatioMinValue, 'f', 2, 64)
  637. res.Data.Table.TitleList = append(res.Data.Table.TitleList, tableList...)
  638. return res, nil
  639. }
  640. func calculateRatio(res []float64) (float64, float64, float64) {
  641. var maxValue, middleValue, minValue, allValue float64 = 0, 0, 0, 0
  642. for _, v := range res {
  643. if v > maxValue {
  644. maxValue = v
  645. }
  646. if v <= maxValue {
  647. minValue = v
  648. }
  649. allValue += v
  650. }
  651. middleValue = allValue / float64(len(res))
  652. return maxValue, middleValue, minValue
  653. }