group.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. package module
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "strconv"
  7. "time"
  8. "tmr-watch/http/handle/restful"
  9. "tmr-watch/models"
  10. operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
  11. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/pasture"
  12. "github.com/xormplus/xorm"
  13. )
  14. // DistributeFeedFormula 接受集团饲料配方下发
  15. func DistributeFeedFormula(feedTemplateList []*models.FeedTemplate) error {
  16. tx := restful.Engine.NewSession()
  17. defer tx.Close()
  18. for _, feedTemplate := range feedTemplateList {
  19. // 过滤掉没有饲料详情的配方
  20. if len(feedTemplate.FeedFormulaDetail) <= 0 {
  21. continue
  22. }
  23. if _, err := tx.Table(new(models.FeedTemplate)).Insert(feedTemplate); err != nil {
  24. return err
  25. }
  26. feedFormulaDetail := make([]*models.FeedTemplateDetail, 0)
  27. for _, f := range feedTemplate.FeedFormulaDetail {
  28. f.FtId = feedTemplate.Id
  29. feedFormulaDetail = append(feedFormulaDetail, f)
  30. }
  31. if _, err := tx.Table(new(models.FeedTemplateDetail)).Insert(feedFormulaDetail); err != nil {
  32. return err
  33. }
  34. }
  35. return tx.Commit()
  36. }
  37. // CancelDistributeFeedFormula 集团饲料配方取消下发
  38. func CancelDistributeFeedFormula(pastureId int64, ids []int64) error {
  39. if _, err := restful.Engine.Table(new(models.FeedTemplate)).
  40. Where("id IN ?", ids).Where("pasture_id = ?", pastureId).Update(map[string]interface{}{"enable": 2, "is_modify": 2}); err != nil {
  41. return err
  42. }
  43. return nil
  44. }
  45. func FeedFormulaIsModify(req *models.PastureFeedFormulaIsModifyRequest) error {
  46. if _, err := restful.Engine.Table(new(models.FeedTemplate)).Cols("is_modify").
  47. Where("id = ?", req.FeedFormulaId).And("pastureid = ?", req.PastureId).
  48. Update(map[string]interface{}{"is_modify": req.IsModify}); err != nil {
  49. return err
  50. }
  51. return nil
  52. }
  53. // MixedFodderData 混料准确率
  54. func MixedFodderData(req *models.AnalysisAccuracyRequest) ([]*models.MixedFodderDataList, error) {
  55. res := make([]*models.MixedFodderDataList, 0)
  56. whereFeedFormulaIdStr := ""
  57. if req.FeedFormulaId > 0 {
  58. whereFeedFormulaIdStr = fmt.Sprintf(" AND f.ccid = %d", req.FeedFormulaId)
  59. }
  60. sql := fmt.Sprintf(`SELECT DATE(de.date) AS plan_time,
  61. 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,
  62. 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
  63. FROM downloadplandtl1 de
  64. LEFT JOIN downloadedplan d ON d.id = de.pid
  65. LEFT JOIN feedtemplet f ON f.id = d.tempid
  66. WHERE de.pastureid= %d AND de.intime IS NOT NULL
  67. AND (SELECT d.lpplantype FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid) IN (0,1,4)
  68. AND de.date >= '%s' AND de.date <= '%s' %s GROUP BY de.date`, req.PastureId, req.StartDate, req.EndDate, whereFeedFormulaIdStr)
  69. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  70. return nil, err
  71. }
  72. return res, nil
  73. }
  74. // SprinkleFodderData 撒料准确率
  75. func SprinkleFodderData(req *models.AnalysisAccuracyRequest) ([]*models.SprinkleFodderDataList, error) {
  76. res := make([]*models.SprinkleFodderDataList, 0)
  77. whereFeedFormulaIdStr := ""
  78. if req.FeedFormulaId > 0 {
  79. whereFeedFormulaIdStr = fmt.Sprintf(" AND f.ccid = %d", req.FeedFormulaId)
  80. }
  81. sql := fmt.Sprintf(`SELECT DATE(d.mydate) AS plan_time,
  82. 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,
  83. 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
  84. FROM downloadplandtl2 de
  85. JOIN downloadedplan d ON d.id=de.pid AND d.pastureid = de.pastureid
  86. LEFT JOIN feedtemplet f ON f.id = d.tempid
  87. WHERE de.pastureid = %d AND DATE(de.date) BETWEEN '%s' AND '%s' %s GROUP BY de.date`, req.PastureId, req.StartDate, req.EndDate, whereFeedFormulaIdStr)
  88. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  89. return nil, err
  90. }
  91. return res, nil
  92. }
  93. // TMRList tmr设备列表
  94. func TMRList(req *models.AnalysisAccuracyRequest) ([]*models.ProcessData, error) {
  95. res := make([]*models.ProcessData, 0)
  96. sql := fmt.Sprintf(`SELECT d.lpplantype as plan_type,
  97. d.tmrtname as tmr_name,
  98. f.ccid as c_cid,
  99. TRIM(d.pastureid) as pasture_id,
  100. TRIM(d.pid) as pid,
  101. TRIM(d.id) as id
  102. FROM downloadedplan d
  103. LEFT JOIN feedtemplet f on f.id = d.tempid
  104. WHERE d.pastureid= %d and d.intime IS NOT NULL
  105. AND d.mydate >= '%s' AND d.mydate <= '%s'`, req.PastureId, req.StartDate, req.EndDate)
  106. if req.CattleParentCategoryId > 0 {
  107. sql = fmt.Sprintf("%s AND f.ccid = %d", sql, req.CattleParentCategoryId)
  108. }
  109. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  110. return nil, err
  111. }
  112. return res, nil
  113. }
  114. // MixedProcessTimeList 混料时间列表
  115. func MixedProcessTimeList(pastureId int32, id int64) ([]*models.ProcessTimeList, error) {
  116. res := make([]*models.ProcessTimeList, 0)
  117. sql := fmt.Sprintf(`SELECT IFNULL(TIMEDIFF (d1.intime,(SELECT MAX(intime) FROM downloadplandtl1_exec d2
  118. WHERE d1.pid=d2.pid AND d1.pastureid = d2.pastureid AND d2.intime<d1.intime)),TIMEDIFF(intime,(SELECT MAX(intime) FROM downloadedplan d2
  119. WHERE d1.date=d2.mydate AND d1.pastureid = d2.pastureid AND d2.id=d1.pid))) AS process_time
  120. FROM downloadplandtl1_exec d1 WHERE d1.pastureid = %d AND d1.pid = %d ORDER BY sort`, pastureId, id)
  121. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  122. return nil, err
  123. }
  124. return res, nil
  125. }
  126. // SprinkleProcessTimeList 混料时间列表
  127. func SprinkleProcessTimeList(pastureId int32, id int64) ([]*models.ProcessTimeList, error) {
  128. res := make([]*models.ProcessTimeList, 0)
  129. sql := fmt.Sprintf(`SELECT IFNULL(TIMEDIFF (d1.intime,(SELECT MAX(intime) FROM downloadplandtl2 d2
  130. WHERE d1.pid=d2.pid AND d1.pastureid = d2.pastureid AND d2.intime<d1.intime)), TIMEDIFF(intime,(SELECT MAX(intime) FROM downloadplandtl1_exec d2
  131. WHERE d1.date=d2.date AND d1.pastureid = d2.pastureid AND d2.pid=d1.pid))) AS process_time FROM downloadplandtl2 d1
  132. WHERE d1.pastureid = %d AND pid =%d ORDER BY sort`, pastureId, id)
  133. if err := restful.Engine.SQL(sql).Find(&res); err != nil {
  134. return nil, err
  135. }
  136. return res, nil
  137. }
  138. func SprinkleStatistics(req *models.SprinkleStatisticsRequest) ([]*models.SprinkleStatisticsDataList, error) {
  139. res := make([]*models.SprinkleStatisticsDataList, 0)
  140. newSql := restful.Engine.Table("downloadedplan").Alias("b").
  141. Select("a.fbarid,a.fname,a.intime,a.processtime,b.times").
  142. Join("LEFT", []string{"downloadplandtl2", "a"}, "a.pastureid = b.pastureid AND b.pid = a.flpid").
  143. Where("a.pastureid = ?", req.PastureId).And("b.times > 0 ").
  144. And("a.fbarid > 0").And("a.intime IS NOT NULL").And("a.processtime IS NOT NULL")
  145. if len(req.StartDate) > 0 && len(req.EndDate) > 0 {
  146. newSql.And("a.date >= ? and a.date <= ?", req.StartDate, req.EndDate)
  147. }
  148. if req.FeedFormulaId > 0 {
  149. newSql.And("a.feedtempletid = ?", req.FeedFormulaId)
  150. }
  151. if err := newSql.GroupBy("a.fbarid ,b.intime").Limit(100).Find(&res); err != nil {
  152. return nil, err
  153. }
  154. return res, nil
  155. }
  156. func AccountDistribution(req *models.AccountDistributionRequest) error {
  157. res := &models.User{}
  158. _, err := restful.Engine.Select("pastureid,username,empname,password,phone").
  159. Where("enable = ?", operationPb.IsShow_OK).And("isdelete = ?", operationPb.IsShow_NO).And("pastureid = ?", req.PastureId).
  160. And("username = ?", req.Account).Get(res)
  161. if err != nil {
  162. return err
  163. }
  164. if res.Username == req.Account {
  165. return errors.New("该账号已经存在")
  166. }
  167. session := restful.Engine.NewSession()
  168. defer session.Close()
  169. if err = session.Begin(); err != nil {
  170. return err
  171. }
  172. // 查看牧场是否存在
  173. pastureData := &models.Pasture{}
  174. if _, err = session.Table(new(models.Pasture).TableName()).Where("pastureid = ?", req.PastureId).Get(pastureData); err != nil {
  175. return err
  176. }
  177. if pastureData.PastureId <= 0 {
  178. newPasture := models.NewPasture(int64(req.PastureId), req.PastureName, req.Address, req.UserName, req.Phone)
  179. if _, err = session.Table(new(models.Pasture).TableName()).Insert(newPasture); err != nil {
  180. return err
  181. }
  182. }
  183. // 查询牧场对应菜单是否存在
  184. menuPasture := &models.MenuPasture{}
  185. if _, err = session.Table(new(models.MenuPasture).TableName()).Where("pastureid = ?", req.PastureId).Get(menuPasture); err != nil {
  186. return err
  187. }
  188. // 创建新的超级管理员角色
  189. newRole := models.NewDefaultRole(int64(req.PastureId))
  190. if _, err = session.Table(new(models.Role).TableName()).Insert(newRole); err != nil {
  191. return err
  192. }
  193. menuList := make([]*models.Menu, 0)
  194. if err = session.Table(new(models.Menu).TableName()).Find(&menuList); err != nil {
  195. return err
  196. }
  197. if menuPasture.PastureId <= 0 {
  198. newMenuPastureList := models.NewMenuPastureList(int64(req.PastureId), menuList)
  199. if _, err = session.Table(new(models.MenuPasture).TableName()).Insert(newMenuPastureList); err != nil {
  200. return err
  201. }
  202. }
  203. NewRoleMenu := models.NewRoleMenu(int64(req.PastureId), newRole.Id, menuList)
  204. if _, err = session.Table(new(models.RoleMenu).TableName()).Insert(NewRoleMenu); err != nil {
  205. return err
  206. }
  207. // 创建用户并绑定管理员权限
  208. newUser := models.NewUser(int64(req.PastureId), req.Account, req.UserName, req.Password, req.Phone, newRole.Id)
  209. if _, err = session.Table(new(models.User).TableName()).Insert(newUser); err != nil {
  210. return err
  211. }
  212. return session.Commit()
  213. }
  214. func CattleCategoryDistribute(req *models.CowClass) error {
  215. has, err := restful.Engine.Table(new(models.CowClass).TableName()).Exist(&models.CowClass{GroupId: req.GroupId})
  216. if err != nil {
  217. return err
  218. }
  219. if has {
  220. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).
  221. Where("group_id = ?", req.GroupId).
  222. Update(map[string]interface{}{
  223. "pastureid": req.PastureId,
  224. "classcode": req.ClassCode,
  225. "classname": req.ClassName,
  226. "enable": req.Enable,
  227. "parentid": req.ParentId,
  228. "parentname": req.ParentName,
  229. }); err != nil {
  230. return err
  231. }
  232. } else {
  233. lastData := &models.CowClass{}
  234. if err = restful.Engine.Table(new(models.CowClass).TableName()).OrderBy("id desc").GetFirst(lastData).Error; err != nil {
  235. req.Id = 1
  236. } else {
  237. req.Id = lastData.Id + 1
  238. }
  239. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).Insert(req); err != nil {
  240. return err
  241. }
  242. }
  243. return nil
  244. }
  245. func ForageCategoryDistribute(req *models.FeedClass) error {
  246. has, err := restful.Engine.Table(new(models.FeedClass).TableName()).Exist(&models.FeedClass{GroupId: req.GroupId})
  247. if err != nil {
  248. return err
  249. }
  250. if has {
  251. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).
  252. Where("group_id = ?", req.GroupId).
  253. Update(map[string]interface{}{
  254. "pastureid": req.PastureId,
  255. "fccode": req.FCCode,
  256. "fcname": req.FCName,
  257. "enable": req.Enable,
  258. "bigfeedclassid": req.BigFeedClassId,
  259. "bigfeedclassname": req.BigFeedClassName,
  260. }); err != nil {
  261. return err
  262. }
  263. } else {
  264. lastData := &models.FeedClass{}
  265. if err = restful.Engine.Table(new(models.FeedClass).TableName()).OrderBy("id desc").GetFirst(lastData).Error; err != nil {
  266. req.Id = 1
  267. } else {
  268. req.Id = lastData.Id + 1
  269. }
  270. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).Insert(req); err != nil {
  271. return err
  272. }
  273. }
  274. return nil
  275. }
  276. func ForageCategoryDelete(pastureId, groupId int64) error {
  277. feedClassHas := &models.FeedClass{GroupId: groupId, PastureId: pastureId}
  278. has, err := restful.Engine.Table(new(models.FeedClass).TableName()).Exist(feedClassHas)
  279. if err != nil {
  280. return err
  281. }
  282. if has {
  283. if _, err = restful.Engine.Table(new(models.FeedClass).TableName()).ID(feedClassHas.Id).Delete(feedClassHas); err != nil {
  284. return err
  285. }
  286. }
  287. return nil
  288. }
  289. func CowCategoryDelete(pastureId, groupId int64) error {
  290. cowClassHas := &models.CowClass{GroupId: groupId, PastureId: pastureId}
  291. has, err := restful.Engine.Table(new(models.CowClass).TableName()).Exist(cowClassHas)
  292. if err != nil {
  293. return err
  294. }
  295. if has {
  296. if _, err = restful.Engine.Table(new(models.CowClass).TableName()).ID(cowClassHas.Id).Delete(cowClassHas); err != nil {
  297. return err
  298. }
  299. }
  300. return nil
  301. }
  302. func FeedTemplateList(req *models.FeedListRequest) ([]*models.FeedTemplate, int64, error) {
  303. var (
  304. res []*models.FeedTemplate
  305. total int64
  306. err error
  307. )
  308. newSession := restful.Engine.NewSession()
  309. total, err = newSession.Table(new(models.FeedTemplate).TableName()).
  310. Where("pastureid = ?", req.PastureId).Count(&res)
  311. if err != nil {
  312. return nil, 0, err
  313. }
  314. if err = newSession.Table(new(models.FeedTemplate).TableName()).Limit(int(req.PageSize), int(req.Page-1)*int(req.PageSize)).Find(&res); err != nil {
  315. return nil, 0, err
  316. }
  317. return res, total, nil
  318. }
  319. func FeedList(req *models.FeedListRequest) ([]*models.Feed, int64, error) {
  320. var (
  321. res []*models.Feed
  322. total int64
  323. err error
  324. )
  325. newSession := restful.Engine.NewSession()
  326. total, err = newSession.Table(new(models.Feed).TableName()).
  327. Where("pastureid = ?", req.PastureId).Count(&res)
  328. if err != nil {
  329. return nil, 0, err
  330. }
  331. if err = newSession.Table(new(models.Feed).TableName()).Limit(int(req.PageSize), int(req.Page-1)*int(req.PageSize)).Find(&res); err != nil {
  332. return nil, 0, err
  333. }
  334. return res, total, nil
  335. }
  336. func FeedTemplateDetailList(req *models.FeedListRequest) ([]*models.FeedTemplateDetail, int64, error) {
  337. var (
  338. res []*models.FeedTemplateDetail
  339. total int64
  340. err error
  341. )
  342. newSession := restful.Engine.NewSession()
  343. total, err = newSession.Table(new(models.FeedTemplateDetail).TableName()).
  344. Where("pastureid = ?", req.PastureId).Count(&res)
  345. if err != nil {
  346. return nil, 0, err
  347. }
  348. if err = newSession.Table(new(models.FeedTemplateDetail).TableName()).Limit(int(req.PageSize), int(req.Page-1)*int(req.PageSize)).Find(&res); err != nil {
  349. return nil, 0, err
  350. }
  351. return res, total, nil
  352. }
  353. func FeedTemplateUsageDetail(req *models.FeedFormulaUsageRequest) (*models.FeedFormulaUsageResponse, error) {
  354. mixedDetail, err := getMixedDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
  355. if err != nil {
  356. return nil, err
  357. }
  358. sprinkleDetail, err := getSprinkleDetail(req.PastureId, req.FeedFormulaId, req.StartTime, req.EndTime)
  359. if err != nil {
  360. return nil, err
  361. }
  362. response := &models.FeedFormulaUsageResponse{
  363. MixedFodderAccurateRatio: strconv.FormatFloat(mixedDetail.MixedFodderAccurateRatio, 'f', 2, 64) + "%",
  364. MixedFodderCorrectRatio: strconv.FormatFloat(mixedDetail.MixedFodderCorrectRatio, 'f', 3, 64) + "%",
  365. SprinkleFodderAccurateRatio: strconv.FormatFloat(sprinkleDetail.SprinkleFodderAccurateRatio, 'f', 3, 64) + "%",
  366. SprinkleFodderCorrectRatio: strconv.FormatFloat(sprinkleDetail.SprinkleFodderCorrectRatio, 'f', 3, 64) + "%",
  367. AddFeedTime: "",
  368. SprinkleTime: "",
  369. StirTime: "",
  370. LastEditTime: "",
  371. }
  372. return response, nil
  373. }
  374. func getMixedDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.MixedDetail, error) {
  375. sql := fmt.Sprintf(`SELECT * FROM (
  376. SELECT DATE(de.date) AS plan_time,
  377. IFNULL((SELECT d.templetname FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.fname) AS feed_formula_name,
  378. IFNULL((SELECT d.tempid FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),0) AS feed_formula_id,
  379. ROUND(SUM(de.lweight),2) AS l_weight,ROUND(SUM(de.actualweightminus),2) AS reality_weight,
  380. SUM(1) AS plan_mixed_opts,SUM(de.havebuttom) AS reality_mixed_opts,
  381. ROUND(SUM(de.havebuttom)/SUM(1)*100,2) AS mixed_ops_ratio,
  382. SUM(IF(de.buttontype =1,1,0)) AS mixed_auto_jump_number , SUM(IF(de.buttontype>1,1,0)) AS mixed_manual_jump_number ,
  383. ROUND(ABS(SUM(de.lweight)-SUM(de.actualweightminus)),2) AS mix_error_number,
  384. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  385. SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS mixed_fodder_accurate_ratio,
  386. IF (SUM(de.actualweightminus)>SUM(de.lweight),
  387. ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  388. ROUND((SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2)) AS hlzq,
  389. 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,
  390. ROUND(STD(ABS(de.actualweightminus-de.lweight)) ,2) AS variance_ratio,
  391. IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.feedallowratio AND de.actualweightminus<>0,1,0)),0) AS mixed_fodder_correct_number,
  392. 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,
  393. ROUND(IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.feedallowratio AND de.actualweightminus<>0,1,0))/SUM(1),0)*100,2) hlzql,
  394. TRIM(de.pid) pid,
  395. ROUND(IFNULL(SUM(IF(((ABS(de.actualweightminus-de.lweight)/de.lweight)<=3 OR (de.lweight <30 AND de.actualweightminus <30 )),
  396. 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
  397. 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'
  398. GROUP BY de.date ) tmp `, pastureId, startTime, endTime)
  399. if feedFormulaId > 0 {
  400. sql = fmt.Sprintf("%s HAVING tmp.feed_formula_id = %d", sql, feedFormulaId)
  401. }
  402. dataList := &models.MixedDetail{}
  403. if _, err := restful.Engine.NewSession().SQL(sql).Get(dataList); err != nil {
  404. return nil, err
  405. }
  406. return dataList, nil
  407. }
  408. func getSprinkleDetail(pastureId, feedFormulaId int32, startTime, endTime string) (*models.SprinkleDetail, error) {
  409. sql := fmt.Sprintf(`SELECT * FROM (SELECT DATE(d.mydate) AS plan_time,
  410. IFNULL((SELECT d.templetname FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),de.fname) AS feed_formula_name,
  411. IFNULL((SELECT d.tempid FROM downloadedplan d WHERE d.pastureid = de.pastureid AND d.id = de.pid),0) AS feed_formula_id,
  412. d.tmrtname AS tmr_name,
  413. 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,
  414. 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,
  415. SUM(de.lweight) AS l_weight,ROUND(SUM(de.actualweightminus)) AS reality_weight,
  416. SUM(1) AS plan_sprinkle_opts,
  417. SUM(de.havebuttom) AS reality_sprinkle_opts,
  418. ROUND(SUM(de.havebuttom)/SUM(1)*100,2) AS sprinkle_ops_ratio,
  419. SUM(IF(de.buttontype =1,1,0)) AS sprinkle_auto_jump_number ,
  420. SUM(IF(de.buttontype>1,1,0)) AS sprinkle_manual_jump_number ,
  421. ABS(SUM(de.actualweightminus)-SUM(de.lweight)) AS sprinkle_error_number,
  422. CONCAT( IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  423. SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2) AS sprinkle_fodder_accurate_ratio,
  424. IF (SUM(de.actualweightminus)>SUM(de.lweight),ROUND((SUM(de.lweight)/SUM(de.actualweightminus)*100),2) ,
  425. ROUND((SUM(de.actualweightminus)/SUM(de.lweight)*100) ,2)) slzq,
  426. 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,
  427. IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.allowratio AND de.actualweightminus<>0,1,0)),0) AS sprinkle_fodder_correct_number,
  428. 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,
  429. ROUND(IFNULL(SUM(IF(ABS(de.actualweightminus-de.lweight)<=de.allowratio AND de.actualweightminus<>0,1,0))/SUM(1),0)*100,2) as slzql,
  430. TRIM(de.pid) pid,
  431. ROUND(IFNULL(SUM(IF(((ABS(de.actualweightminus-de.lweight)/de.lweight)<=3 OR (de.lweight <30 AND de.actualweightminus <30 )),
  432. 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
  433. FROM downloadplandtl2 de JOIN downloadedplan d ON d.id=de.pid AND d.pastureid = de.pastureid
  434. WHERE d.pastureid = %d AND DATE(d.mydate) BETWEEN '%s' AND '%s' AND d.lpplantype IN (0,2)) tmr `, pastureId, startTime, endTime)
  435. if feedFormulaId > 0 {
  436. sql = fmt.Sprintf("%s HAVING feed_formula_id = %d", sql, feedFormulaId)
  437. }
  438. dataList := &models.SprinkleDetail{}
  439. if _, err := restful.Engine.NewSession().SQL(sql).Get(dataList); err != nil {
  440. return nil, err
  441. }
  442. return dataList, nil
  443. }
  444. func FeedFormulaVersion(pastureId int64, req *models.FeedFormulaUpdateVersionRequest) error {
  445. if req.Belong == 0 {
  446. return nil
  447. }
  448. DbSession := restful.Engine.NewSession()
  449. defer DbSession.Close()
  450. // 开启事务
  451. if err := DbSession.Begin(); err != nil {
  452. return err
  453. }
  454. feedDetailVersion := &models.FeedDetailVersion{
  455. FeedTemplateId: req.FeedTemplateId,
  456. PastureId: pastureId,
  457. GroupVersion: req.Version,
  458. Belong: req.Belong,
  459. CreatedAt: time.Now().Unix(),
  460. UpdatedAt: time.Now().Unix(),
  461. }
  462. if _, err := DbSession.Insert(feedDetailVersion); err != nil {
  463. DbSession.Rollback()
  464. return err
  465. }
  466. // FeedDetailVersionLog 更新
  467. versionLogs := make([]*models.FeedDetailVersionLog, 0)
  468. for _, v := range req.Data {
  469. versionLogs = append(versionLogs, &models.FeedDetailVersionLog{
  470. VersionId: feedDetailVersion.Id,
  471. PastureId: pastureId,
  472. FeedTemplateId: req.FeedTemplateId,
  473. ForageId: int64(v.ForageId),
  474. ForageName: v.ForageName,
  475. ForageGroupName: v.ForageGroupName,
  476. Weight: int32(v.Weight * 100),
  477. StirDelay: v.StirDelay,
  478. AllowError: v.AllowError,
  479. IsModify: v.IsModify,
  480. IsLockCowCountRatio: operationPb.IsShow_Kind(v.IsLockCowCountRatio),
  481. Sort: v.Sort,
  482. })
  483. }
  484. if _, err := DbSession.Table(new(models.FeedDetailVersionLog).TableName()).Insert(versionLogs); err != nil {
  485. DbSession.Rollback()
  486. return err
  487. }
  488. return DbSession.Commit()
  489. }
  490. func NewSearchFeedTemplateList(ctx context.Context, req *pasturePb.SearchFeedTemplateRequest) ([]*models.FeedTemplate, int64, error) {
  491. DBSession := restful.Engine.NewSession()
  492. defer DBSession.Close()
  493. res := make([]*models.FeedTemplate, 0)
  494. if req.PastureId > 0 {
  495. DBSession.And("pastureid = ?", req.PastureId)
  496. }
  497. if req.Name != "" {
  498. DBSession.And("tname like ?", "%"+req.Name+"%")
  499. }
  500. if req.CattleCategoryId > 0 {
  501. DBSession.And("ccid = ?", req.CattleCategoryId)
  502. }
  503. if req.FormulaTypeId > 0 {
  504. DBSession.And("fttypeid = ?", req.FormulaTypeId)
  505. }
  506. switch req.SourceId {
  507. case 0:
  508. DBSession.And("source = '自定义'")
  509. case 1:
  510. DBSession.And("source = '集团下发未调整'")
  511. case 2:
  512. DBSession.And("source = '集团下发有调整'")
  513. case 3:
  514. DBSession.And("source = '导入'")
  515. }
  516. if req.Enable > 0 {
  517. DBSession.And("enable = ?", req.Enable)
  518. }
  519. if req.Remark != "" {
  520. DBSession.And("remark = ?", req.Remark)
  521. }
  522. if err := DBSession.Desc("id").Find(&res); err != nil {
  523. return nil, 0, err
  524. } else {
  525. return res, int64(len(res)), nil
  526. }
  527. }
  528. func FeedDetailVersionLogList(ctx context.Context) ([]*models.FeedDetailVersion, error) {
  529. res := make([]*models.FeedDetailVersion, 0)
  530. if err := restful.Engine.NewSession().Find(&res); err != nil {
  531. if !errors.Is(err, xorm.ErrNotExist) {
  532. return nil, err
  533. }
  534. }
  535. return res, nil
  536. }
  537. // SearchFeedTemplateDetailListByFeedTemplateId 获取配方当前饲料列表详情
  538. func SearchFeedTemplateDetailListByFeedTemplateId(ctx context.Context, pastureId, feedTemplateId int64) ([]*models.FeedTemplateDetail, error) {
  539. res := make([]*models.FeedTemplateDetail, 0)
  540. if err := restful.Engine.Table(new(models.FeedTemplateDetail).TableName()).Where("pastureid = ?", pastureId).And("ftid = ?", feedTemplateId).Find(&res); err != nil {
  541. return nil, err
  542. }
  543. return res, nil
  544. }
  545. // GetFeedDetailVersionByDesc 获取配方最新版本数据
  546. func GetFeedDetailVersionByDesc(ctx context.Context, pastureId, feedTemplateId int64) (*models.FeedDetailVersion, error) {
  547. res := &models.FeedDetailVersion{}
  548. if _, err := restful.Engine.Table(new(models.FeedDetailVersion).TableName()).
  549. Where("pasture_id = ?", pastureId).
  550. And("feed_template_id = ?", feedTemplateId).OrderBy("id desc").Get(res); err != nil {
  551. return nil, err
  552. }
  553. return res, nil
  554. }
  555. // SearchFeedDetailVersionLogById 获取配方关联最新饲料信息
  556. func SearchFeedDetailVersionLogById(ctx context.Context, pastureId, feedTemplateId, versionId int64) ([]*models.FeedDetailVersionLog, error) {
  557. res := make([]*models.FeedDetailVersionLog, 0)
  558. if err := restful.Engine.NewSession().Table(new(models.FeedDetailVersionLog).TableName()).Where("pasture_id = ?", pastureId).
  559. And("feed_template_id = ?", feedTemplateId).And("version_id = ?", versionId).Find(&res); err != nil {
  560. return nil, err
  561. }
  562. return res, nil
  563. }
  564. // FeetTemplateUpgradeNewVersion 配方更新至最新版本
  565. func FeetTemplateUpgradeNewVersion(ctx context.Context, pastureId, feedTemplateId int64) error {
  566. newFeedDetailVersion, err := GetFeedDetailVersionByDesc(ctx, pastureId, feedTemplateId)
  567. if err != nil {
  568. return err
  569. }
  570. DBSession := restful.Engine.NewSession()
  571. defer DBSession.Close()
  572. if err = DBSession.Begin(); err != nil {
  573. return err
  574. }
  575. if _, err = DBSession.Table(new(models.FeedTemplateDetail).TableName()).
  576. Where("pasture_id = ?", pastureId).
  577. And("feed_template_id = ?", feedTemplateId).Update("is_show", operationPb.IsShow_NO); err != nil {
  578. DBSession.Rollback()
  579. return err
  580. }
  581. res, err := SearchFeedDetailVersionLogById(ctx, pastureId, feedTemplateId, newFeedDetailVersion.Id)
  582. if err != nil {
  583. DBSession.Rollback()
  584. return err
  585. }
  586. if len(res) <= 0 {
  587. return DBSession.Commit()
  588. }
  589. newFtDetailList := make([]*models.FeedTemplateDetail, 0)
  590. for _, v := range res {
  591. newFtDetailList = append(newFtDetailList, &models.FeedTemplateDetail{
  592. PastureId: pastureId,
  593. FtId: feedTemplateId,
  594. FId: v.ForageId,
  595. FName: v.ForageName,
  596. FWeight: float64(v.Weight / 100),
  597. IsLockCount: int32(v.IsLockCowCountRatio),
  598. IsFg: 0,
  599. Sort: v.Sort,
  600. FeedGroup: v.ForageGroupName,
  601. PreFtId: 0,
  602. AutoSecond: v.StirDelay,
  603. AutoSecondName: "",
  604. SplitFtPreId: 0,
  605. Deviation: v.AllowError,
  606. IsModify: int32(v.IsModify),
  607. IsShow: int32(operationPb.IsShow_OK),
  608. })
  609. }
  610. if _, err = DBSession.Table(new(models.FeedTemplateDetail).TableName()).Insert(newFtDetailList); err != nil {
  611. DBSession.Rollback()
  612. return err
  613. }
  614. return DBSession.Commit()
  615. }