group.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. package module
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "tmr-watch/http/handle/restful"
  7. "tmr-watch/models"
  8. )
  9. const (
  10. IsDefault = 0
  11. IsOk = 1
  12. IsNo = 2
  13. )
  14. // DistributeFeedFormula 集团饲料配方下发
  15. func DistributeFeedFormula(res []*models.FeedTemplate) error {
  16. if _, err := restful.Engine.Table(new(models.FeedTemplate)).Insert(&res); err != nil {
  17. return err
  18. }
  19. return nil
  20. }
  21. func FeedFormulaIsModify(req *models.PastureFeedFormulaIsModifyRequest) error {
  22. if _, err := restful.Engine.Table(new(models.FeedTemplate)).Cols("is_modify").
  23. Where("id = ?", req.FeedFormulaId).And("pastureid = ?", req.PastureId).
  24. Update(map[string]interface{}{"is_modify": req.IsModify}); err != nil {
  25. return err
  26. }
  27. return nil
  28. }
  29. // MixedFodderData 混料准确率
  30. func MixedFodderData(req *models.AnalysisAccuracyRequest) ([]*models.MixedFodderDataList, error) {
  31. res := make([]*models.MixedFodderDataList, 0)
  32. whereFeedFormulaIdStr := ""
  33. if req.FeedFormulaId > 0 {
  34. whereFeedFormulaIdStr = fmt.Sprintf(" AND f.ccid = %d", req.FeedFormulaId)
  35. }
  36. sql := fmt.Sprintf(`SELECT DATE(de.date) AS plan_time,
  37. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS mixed_fodder_accurate_ratio,
  38. 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
  39. FROM downloadplandtl1 de
  40. LEFT JOIN downloadedplan d ON d.id = de.pid
  41. LEFT JOIN feedtemplet f ON f.id = d.tempid
  42. WHERE de.pastureid= %d AND de.intime IS NOT NULL
  43. AND (SELECT d.lpplantype FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid) IN (0,1,4)
  44. AND de.date >= '%s' AND de.date <= '%s' %s GROUP BY de.date`, req.PastureId, req.StartDate, req.EndDate, whereFeedFormulaIdStr)
  45. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  46. return nil, err
  47. }
  48. return res, nil
  49. }
  50. // SprinkleFodderData 撒料准确率
  51. func SprinkleFodderData(req *models.AnalysisAccuracyRequest) ([]*models.SprinkleFodderDataList, error) {
  52. res := make([]*models.SprinkleFodderDataList, 0)
  53. whereFeedFormulaIdStr := ""
  54. if req.FeedFormulaId > 0 {
  55. whereFeedFormulaIdStr = fmt.Sprintf(" AND f.ccid = %d", req.FeedFormulaId)
  56. }
  57. sql := fmt.Sprintf(`SELECT DATE(d.mydate) AS plan_time,
  58. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2),SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS sprinkle_fodder_accurate_ratio,
  59. 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
  60. FROM downloadplandtl2 de
  61. JOIN downloadedplan d ON d.id=de.pid AND d.pastureid = de.pastureid
  62. LEFT JOIN feedtemplet f ON f.id = d.tempid
  63. WHERE de.pastureid = %d AND DATE(de.date) BETWEEN '%s' AND '%s' %s GROUP BY de.date`, req.PastureId, req.StartDate, req.EndDate, whereFeedFormulaIdStr)
  64. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  65. return nil, err
  66. }
  67. return res, nil
  68. }
  69. // TMRList tmr设备列表
  70. func TMRList(req *models.AnalysisAccuracyRequest) ([]*models.ProcessData, error) {
  71. res := make([]*models.ProcessData, 0)
  72. sql := fmt.Sprintf(`SELECT d.lpplantype as plan_type,d.tmrtname as tmr_name,f.ccid as c_cid,TRIM(d.pastureid) as pasture_id,TRIM(d.pid) as pid,TRIM(d.id) as id
  73. FROM downloadedplan d LEFT JOIN feedtemplet f on f.id = d.tempid WHERE d.pastureid= %d and d.intime IS NOT NULL
  74. AND d.mydate >= '%s' AND d.mydate <= '%s'`, req.PastureId, req.StartDate, req.EndDate)
  75. if req.CattleParentCategoryId > 0 {
  76. sql = fmt.Sprintf("%s AND f.ccid = %d", sql, req.CattleParentCategoryId)
  77. }
  78. if err := restful.Engine.SQL(sql).Find(res); err != nil {
  79. return nil, err
  80. }
  81. return res, nil
  82. }
  83. // MixedProcessTimeList 混料时间列表
  84. func MixedProcessTimeList(pastureId int32, id int64) ([]*models.ProcessTimeList, error) {
  85. res := make([]*models.ProcessTimeList, 0)
  86. sql := fmt.Sprintf(`SELECT IFNULL(TIMEDIFF (d1.intime,(SELECT MAX(intime) FROM downloadplandtl1_exec d2
  87. WHERE d1.pid=d2.pid AND d1.pastureid = d2.pastureid AND d2.intime<d1.intime)),TIMEDIFF(intime,(SELECT MAX(intime) FROM downloadedplan d2
  88. WHERE d1.date=d2.mydate AND d1.pastureid = d2.pastureid AND d2.id=d1.pid))) AS proess_time
  89. FROM downloadplandtl1_exec d1 WHERE d1.pastureid = %d AND d1.pid = %d ORDER BY sort`, pastureId, id)
  90. if err := restful.Engine.SQL(sql).Find(res); err != nil {
  91. return nil, err
  92. }
  93. return res, nil
  94. }
  95. // SprinkleProcessTimeList 混料时间列表
  96. func SprinkleProcessTimeList(pastureId int32, id int64) ([]*models.ProcessTimeList, error) {
  97. res := make([]*models.ProcessTimeList, 0)
  98. sql := fmt.Sprintf(`SELECT IFNULL(TIMEDIFF (d1.intime,(SELECT MAX(intime) FROM downloadplandtl2 d2
  99. WHERE d1.pid=d2.pid AND d1.pastureid = d2.pastureid AND d2.intime<d1.intime)), IMEDIFF(intime,(SELECT MAX(intime) FROM downloadplandtl1_exec d2
  100. WHERE d1.date=d2.date AND d1.pastureid = d2.pastureid AND d2.pid=d1.pid))) AS proess_time FROM downloadplandtl2 d1
  101. WHERE d1.pastureid = %d AND pid =%d ORDER BY sort`, pastureId, id)
  102. if err := restful.Engine.SQL(sql).Find(res); err != nil {
  103. return nil, err
  104. }
  105. return res, nil
  106. }
  107. func SprinkleStatistics(req *models.SprinkleStatisticsRequest) ([]*models.SprinkleStatisticsDataList, error) {
  108. res := make([]*models.SprinkleStatisticsDataList, 0)
  109. newSql := restful.Engine.Table("downloadedplan").Alias("b").
  110. Select("a.fbarid,a.fname,a.intime,a.processtime,b.times").
  111. Join("LEFT", []string{"downloadplandtl2", "a"}, "a.pastureid = b.pastureid AND b.pid = a.flpid").
  112. Where("a.pastureid = ?", req.PastureId).And("b.times > 0 ").
  113. And("a.fbarid > 0").And("a.intime IS NOT NULL").And("a.processtime IS NOT NULL")
  114. if len(req.StartDate) > 0 && len(req.EndDate) > 0 {
  115. newSql.And("a.date >= ? and a.date <= ?", req.StartDate, req.EndDate)
  116. }
  117. if req.FeedFormulaId > 0 {
  118. newSql.And("a.feedtempletid = ?", req.FeedFormulaId)
  119. }
  120. if err := newSql.GroupBy("a.fbarid ,b.intime").Limit(100).Find(&res); err != nil {
  121. return nil, err
  122. }
  123. return res, nil
  124. }
  125. func AccountDistribution(req *models.AccountDistributionRequest) error {
  126. res := &models.User{}
  127. _, err := restful.Engine.Select("pastureid,username,empname,password,phone").
  128. Where("enable = ?", IsOk).And("isdelete = ?", IsNo).And("pastureid = ?", req.PastureId).
  129. And("username = ?", req.Account).Get(res)
  130. if err != nil {
  131. return err
  132. }
  133. if res.Username == req.Account {
  134. return errors.New("该账号已经存在")
  135. }
  136. session := restful.Engine.NewSession()
  137. defer session.Close()
  138. if err = session.Begin(); err != nil {
  139. return err
  140. }
  141. // 查看牧场是否存在
  142. pastureData := &models.Pasture{}
  143. if _, err = session.Table(new(models.Pasture).TableName()).Where("pastureid = ?", req.PastureId).Get(pastureData); err != nil {
  144. return err
  145. }
  146. if pastureData.PastureId <= 0 {
  147. newPasture := models.NewPasture(int64(req.PastureId), req.PastureName, req.Address, req.UserName, req.Phone)
  148. if _, err = session.Table(new(models.Pasture).TableName()).Insert(newPasture); err != nil {
  149. return err
  150. }
  151. }
  152. // 查询牧场对应菜单是否存在
  153. menuPasture := &models.MenuPasture{}
  154. if _, err = session.Table(new(models.MenuPasture).TableName()).Where("pastureid = ?", req.PastureId).Get(menuPasture); err != nil {
  155. return err
  156. }
  157. // 创建新的超级管理员角色
  158. newRole := models.NewDefaultRole(int64(req.PastureId))
  159. if _, err = session.Table(new(models.Role).TableName()).Insert(newRole); err != nil {
  160. return err
  161. }
  162. menuList := make([]*models.Menu, 0)
  163. if err = session.Table(new(models.Menu).TableName()).Find(&menuList); err != nil {
  164. return err
  165. }
  166. if menuPasture.PastureId <= 0 {
  167. newMenuPastureList := models.NewMenuPastureList(int64(req.PastureId), menuList)
  168. if _, err = session.Table(new(models.MenuPasture).TableName()).Insert(newMenuPastureList); err != nil {
  169. return err
  170. }
  171. }
  172. NewRoleMenu := models.NewRoleMenu(int64(req.PastureId), newRole.Id, menuList)
  173. if _, err = session.Table(new(models.RoleMenu).TableName()).Insert(NewRoleMenu); err != nil {
  174. return err
  175. }
  176. // 创建用户并绑定管理员权限
  177. newUser := models.NewUser(int64(req.PastureId), req.Account, req.UserName, req.Password, req.Phone, newRole.Id)
  178. if _, err = session.Table(new(models.User).TableName()).Insert(newUser); err != nil {
  179. return err
  180. }
  181. return session.Commit()
  182. }
  183. func CattleCategoryDistribute(req *models.CowClass) error {
  184. has, err := restful.Engine.Table(new(models.CowClass).TableName()).Exist(&models.CowClass{GroupId: req.GroupId})
  185. if err != nil {
  186. return err
  187. }
  188. if has {
  189. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).
  190. Where("group_id = ?", req.GroupId).
  191. Update(map[string]interface{}{
  192. "pastureid": req.PastureId,
  193. "classcode": req.ClassCode,
  194. "classname": req.ClassName,
  195. "enable": req.Enable,
  196. "parentid": req.ParentId,
  197. "parentname": req.ParentName,
  198. }); err != nil {
  199. return err
  200. }
  201. } else {
  202. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).Insert(req); err != nil {
  203. return err
  204. }
  205. }
  206. return nil
  207. }
  208. func ForageCategoryDistribute(req *models.FeedClass) error {
  209. has, err := restful.Engine.Table(new(models.FeedClass).TableName()).Exist(&models.FeedClass{GroupId: req.GroupId})
  210. if err != nil {
  211. return err
  212. }
  213. if has {
  214. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).
  215. Where("group_id = ?", req.GroupId).
  216. Update(map[string]interface{}{
  217. "pastureid": req.PastureId,
  218. "fccode": req.FCCode,
  219. "fcname": req.FCName,
  220. "enable": req.Enable,
  221. "bigfeedclassid": req.BigFeedClassId,
  222. "bigfeedclassname": req.BigFeedClassName,
  223. }); err != nil {
  224. return err
  225. }
  226. } else {
  227. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).Insert(req); err != nil {
  228. return err
  229. }
  230. }
  231. return nil
  232. }
  233. func ForageCategoryDelete(pastureId, groupId int64) error {
  234. feedClassHas := &models.FeedClass{GroupId: groupId, PastureId: pastureId}
  235. has, err := restful.Engine.Table(new(models.FeedClass).TableName()).Exist(feedClassHas)
  236. if err != nil {
  237. return err
  238. }
  239. if has {
  240. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).ID(feedClassHas.Id).Delete(feedClassHas); err != nil {
  241. return err
  242. }
  243. }
  244. return nil
  245. }
  246. func CowCategoryDelete(pastureId, groupId int64) error {
  247. cowClassHas := &models.CowClass{GroupId: groupId, PastureId: pastureId}
  248. has, err := restful.Engine.Table(new(models.CowClass).TableName()).Exist(cowClassHas)
  249. if err != nil {
  250. return err
  251. }
  252. if has {
  253. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).ID(cowClassHas.Id).Delete(cowClassHas); err != nil {
  254. return err
  255. }
  256. }
  257. return nil
  258. }
  259. func FeedTemplateList(req *models.FeedFormulaListRequest) ([]*models.FeedTemplate, int64, error) {
  260. var (
  261. res []*models.FeedTemplate
  262. total int64
  263. err error
  264. )
  265. newSession := restful.Engine.NewSession()
  266. total, err = newSession.Table(new(models.FeedTemplate).TableName()).
  267. Where("pastureid = ?", req.PastureId).Count(&res)
  268. if err != nil {
  269. return nil, 0, err
  270. }
  271. if err = newSession.Table(new(models.FeedTemplate).TableName()).Limit(int(req.PageSize), int(req.Page-1)*int(req.PageSize)).Find(&res); err != nil {
  272. return nil, 0, err
  273. }
  274. return res, total, nil
  275. }
  276. func FeedTemplateUsageDetail(req *models.FeedFormulaUsageRequest) (*models.FeedFormulaUsageResponse, error) {
  277. mixedDetail, err := getMixedDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
  278. if err != nil {
  279. return nil, err
  280. }
  281. sprinkleDetail, err := getSprinkleDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
  282. if err != nil {
  283. return nil, err
  284. }
  285. response := &models.FeedFormulaUsageResponse{
  286. MixedFodderAccurateRatio: strconv.FormatFloat(mixedDetail.MixedFodderAccurateRatio, 'f', 2, 64) + "%",
  287. MixedFodderCorrectRatio: strconv.FormatFloat(mixedDetail.MixedFodderCorrectRatio, 'f', 3, 64) + "%",
  288. SprinkleFodderAccurateRatio: strconv.FormatFloat(sprinkleDetail.SprinkleFodderAccurateRatio, 'f', 3, 64) + "%",
  289. SprinkleFodderCorrectRatio: strconv.FormatFloat(sprinkleDetail.SprinkleFodderCorrectRatio, 'f', 3, 64) + "%",
  290. AddFeedTime: "",
  291. SprinkleTime: "",
  292. StirTime: "",
  293. LastEditTime: "",
  294. }
  295. return response, nil
  296. }
  297. func getMixedDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.MixedDetail, error) {
  298. sql := fmt.Sprintf(`SELECT * FROM (
  299. SELECT DATE(de.date) AS plan_time,
  300. IFNULL((SELECT d.templetname FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.fname) AS feed_formula_name,
  301. IFNULL((SELECT d.tempid FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),0) AS feed_formula_id,
  302. ROUND(SUM(de.lweight),2) AS l_weight,ROUND(SUM(de.actualweightminus),2) AS reality_weight,
  303. SUM(1) AS plan_mixed_opts,SUM(de.havebuttom) AS reality_mixed_opts,
  304. ROUND(SUM(de.havebuttom)/SUM(1)*100,2) AS mixed_ops_ratio,
  305. SUM(IF(de.buttontype =1,1,0)) AS mixed_auto_jump_number , SUM(IF(de.buttontype>1,1,0)) AS mixed_manual_jump_number ,
  306. ROUND(ABS(SUM(de.lweight)-SUM(de.actualweightminus)),2) AS mix_error_number,
  307. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  308. SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS mixed_fodder_accurate_ratio,
  309. IF (SUM(de.actualweightminus)>SUM(de.lweight),
  310. ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  311. ROUND((SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2)) AS hlzq,
  312. 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,
  313. ROUND(STD(ABS(de.actualweightminus-de.lweight)) ,2) AS variance_ratio,
  314. IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.feedallowratio AND de.actualweightminus<>0,1,0)),0) AS mixed_fodder_correct_number,
  315. 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,
  316. ROUND(IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.feedallowratio AND de.actualweightminus<>0,1,0))/SUM(1),0)*100,2) hlzql,
  317. TRIM(de.pid) pid,
  318. ROUND(IFNULL(SUM(IF(((ABS(de.actualweightminus-de.lweight)/de.lweight)<=3 OR (de.lweight <30 AND de.actualweightminus <30 )),
  319. 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
  320. FROM downloadplandtl1 de WHERE de.pastureid= %d 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 >= '%s' AND de.date <= '%s'
  321. GROUP BY de.date ) tmp `, pastureId, startTime, endTime)
  322. if feedFormulaId > 0 {
  323. sql = fmt.Sprintf("%s HAVING tmp.feed_formula_id = %d", sql, feedFormulaId)
  324. }
  325. dataList := &models.MixedDetail{}
  326. if _, err := restful.Engine.NewSession().SQL(sql).Get(dataList); err != nil {
  327. return nil, err
  328. }
  329. return dataList, nil
  330. }
  331. func getSprinkleDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.SprinkleDetail, error) {
  332. sql := fmt.Sprintf(`SELECT * FROM (SELECT DATE(d.mydate) AS plan_time,
  333. IFNULL((SELECT d.templetname FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.fname) AS feed_formula_name,
  334. IFNULL((SELECT d.tempid FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),0) AS feed_formula_id,
  335. d.tmrtname AS tmr_name,
  336. 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,
  337. 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,
  338. SUM(de.lweight) AS l_weight,ROUND(SUM(de.actualweightminus)) AS reality_weight,
  339. SUM(1) AS plan_sprinkle_opts,
  340. SUM(de.havebuttom) AS reality_sprinkle_opts,
  341. ROUND(SUM(de.havebuttom)/SUM(1)*100,2) AS sprinkle_ops_ratio,
  342. SUM(IF(de.buttontype =1,1,0)) AS sprinkle_auto_jump_number ,
  343. SUM(IF(de.buttontype>1,1,0)) AS sprinkle_manual_jump_number ,
  344. ABS(SUM(de.actualweightminus)-SUM(de.lweight)) AS sprinkle_error_number,
  345. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  346. SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS sprinkle_fodder_accurate_ratio,
  347. IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  348. ROUND((SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2)) slzq,
  349. 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,
  350. IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.allowratio AND de.actualweightminus<>0,1,0)),0) AS sprinkle_fodder_correct_number,
  351. 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,
  352. ROUND(IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.allowratio AND de.actualweightminus<>0,1,0))/SUM(1),0)*100,2) as slzql,
  353. TRIM(de.pid) pid,
  354. ROUND(IFNULL(SUM(IF(((ABS(de.actualweightminus-de.lweight)/de.lweight)<=3 OR (de.lweight <30 AND de.actualweightminus <30 )),
  355. 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
  356. FROM downloadplandtl2 de JOIN downloadedplan d ON d.id=de.pid AND d.pastureid = de.pastureid
  357. WHERE d.pastureid = %d AND DATE(d.mydate) BETWEEN '%s' AND '%s' AND d.lpplantype IN (0,2)) tmr `, pastureId, startTime, endTime)
  358. if feedFormulaId > 0 {
  359. sql = fmt.Sprintf("%s HAVING feed_formula_id = %d", sql, feedFormulaId)
  360. }
  361. dataList := &models.SprinkleDetail{}
  362. if _, err := restful.Engine.NewSession().SQL(sql).Get(dataList); err != nil {
  363. return nil, err
  364. }
  365. return dataList, nil
  366. }