milk_original.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. package crontab
  2. import (
  3. "fmt"
  4. "kpt-pasture/model"
  5. "kpt-pasture/util"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  10. "go.uber.org/zap"
  11. )
  12. func (e *Entry) UpdateMilkOriginal() error {
  13. pastureList := e.FindPastureList()
  14. if pastureList == nil || len(pastureList) == 0 {
  15. return nil
  16. }
  17. for _, pasture := range pastureList {
  18. e.ProcessMilkOriginal(pasture.Id)
  19. }
  20. return nil
  21. }
  22. func (e *Entry) ProcessMilkOriginal(pastureId int64) {
  23. milkConfigList, err := e.FindMilkConfigure(pastureId)
  24. if err != nil {
  25. zaplog.Error("MilkOriginal", zap.Any("pastureId", pastureId), zap.Any("err", err))
  26. return
  27. }
  28. milkClassConfig := &MilkClassConfig{}
  29. for _, v := range milkConfigList {
  30. switch v.Name {
  31. case model.FirstClassMilkTime:
  32. milkClassConfig.FirstClassMilkTime = v.Value
  33. case model.SecondClassMilkTime:
  34. milkClassConfig.SecondClassMilkTime = v.Value
  35. case model.ThirdClassMilkTime:
  36. milkClassConfig.ThirdClassMilkTime = v.Value
  37. case model.FourthClassMilkTime:
  38. milkClassConfig.FourthClassMilkTime = v.Value
  39. case model.UpdateMilkOriginalMaxId:
  40. maxId, _ := strconv.ParseInt(v.Value, 10, 64)
  41. milkClassConfig.OldUpdateMaxId = maxId
  42. }
  43. }
  44. xDBeg, xBeg1, xBeg2, xBeg3, xBeg4 := parseXBeg(milkClassConfig)
  45. e.UpdateShifts(pastureId, xBeg1, xBeg2, xBeg3, xBeg4)
  46. e.UpdateMilkDate(pastureId, xDBeg)
  47. // 获取当前最大Id
  48. var currentMaxId int64
  49. if err = e.DB.Model(new(model.MilkOriginal)).
  50. Select("MAX(id)").
  51. Where("pasture_id = ?", pastureId).
  52. Where("id > ?", milkClassConfig.OldUpdateMaxId).
  53. Scan(&currentMaxId).Error; err != nil {
  54. zaplog.Error("DeleteRepeatMilkData GetOriWid", zap.Any("pastureId", pastureId), zap.Any("err", err))
  55. return
  56. }
  57. milkClassConfig.CurrentMaxId = currentMaxId
  58. // 获取时间范围和ID范围
  59. deleteModel := &DeleteMilkOriginal{}
  60. selectSql := fmt.Sprintf(`MIN(DATE(TIMESTAMPADD(HOUR, -%d, attach_time))) as x_mind,
  61. MAX(DATE(TIMESTAMPADD(HOUR, -%d, attach_time))) as x_max_d2, MIN(id) as x_min_wid, MAX(id) as x_max_wid`, xDBeg, xDBeg)
  62. if err = e.DB.Model(new(model.MilkOriginal)).
  63. Select(selectSql).
  64. Where("pasture_id = ?", pastureId).
  65. Where("id > ?", milkClassConfig.OldUpdateMaxId).
  66. First(deleteModel).Error; err != nil {
  67. zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
  68. return
  69. }
  70. e.DeleteRepeatMilkData(pastureId, deleteModel, milkClassConfig)
  71. }
  72. // UpdateShifts 更新班次
  73. func (e *Entry) UpdateShifts(pastureId int64, xBeg1, xBeg2, xBeg3, xBeg4 int) {
  74. milkOriginalList := make([]*model.MilkOriginal, 0)
  75. if err := e.DB.Model(new(model.MilkOriginal)).
  76. Where("pasture_id = ?", pastureId).
  77. Where("shifts = ?", 0).
  78. Find(&milkOriginalList).Error; err != nil {
  79. zaplog.Error("UpdateShifts", zap.Any("pastureId", pastureId), zap.Any("err", err))
  80. }
  81. for _, v := range milkOriginalList {
  82. subDetachTime1 := util.Substr(v.DetacherTime, 11, 2)
  83. subDetachTime2 := util.Substr(v.DetacherTime, 14, 2)
  84. subDetachTime1Int, _ := strconv.ParseInt(subDetachTime1, 10, 64)
  85. subDetachTime2Int, _ := strconv.ParseInt(subDetachTime2, 10, 64)
  86. allDetachTime := int(subDetachTime1Int*100 + subDetachTime2Int)
  87. // 更新第一班
  88. if xBeg2 > xBeg1 {
  89. if allDetachTime >= xBeg1 && allDetachTime <= xBeg2 {
  90. v.Shifts = 1
  91. }
  92. } else {
  93. if allDetachTime >= xBeg1 || allDetachTime <= xBeg2 {
  94. v.Shifts = 1
  95. }
  96. }
  97. // 更新第二班
  98. if xBeg3 > xBeg2 {
  99. if allDetachTime >= xBeg2 && allDetachTime <= xBeg3 {
  100. v.Shifts = 2
  101. }
  102. } else {
  103. if allDetachTime >= xBeg2 || allDetachTime <= xBeg3 {
  104. v.Shifts = 2
  105. }
  106. }
  107. // 更新第四班(如果有)
  108. if xBeg4 > 0 && xBeg4 != xBeg1 {
  109. if xBeg1 > xBeg4 {
  110. if allDetachTime >= xBeg4 && allDetachTime <= xBeg1 {
  111. v.Shifts = 4
  112. }
  113. } else {
  114. if allDetachTime >= xBeg4 || allDetachTime <= xBeg1 {
  115. v.Shifts = 4
  116. }
  117. }
  118. }
  119. // 如果还没有分配班次,则分配到第三班
  120. if v.Shifts == 0 {
  121. v.Shifts = 3
  122. }
  123. // 批量更新数据库
  124. if err := e.DB.Model(new(model.MilkOriginal)).
  125. Select("shifts").
  126. Where("id = ?", v.Id).
  127. Updates(v).Error; err != nil {
  128. zaplog.Error("UpdateShifts Save", zap.Any("pastureId", pastureId), zap.Any("err", err))
  129. }
  130. }
  131. }
  132. // UpdateMilkDate 更换挤奶时间
  133. func (e *Entry) UpdateMilkDate(pastureId int64, xDBeg int) {
  134. milkOriginalList := make([]*model.MilkOriginal, 0)
  135. if err := e.DB.Model(new(model.MilkOriginal)).
  136. Where("pasture_id = ?", pastureId).
  137. Where("milk_date = ?", "").
  138. Find(&milkOriginalList).Error; err != nil {
  139. zaplog.Error("UpdateMilkDate", zap.Any("pastureId", pastureId), zap.Any("err", err))
  140. return
  141. }
  142. for _, v := range milkOriginalList {
  143. // 获取结束时间,如果为空则使用默认时间
  144. var endTime time.Time
  145. if v.EndTime == "" {
  146. endTime = time.Date(1999, 12, 31, 23, 0, 0, 0, time.Local)
  147. }
  148. // 比较挤奶时间和结束时间,取较晚的时间
  149. detacherTime, _ := util.TimeParseLocal(model.LayoutTime, v.DetacherTime)
  150. latestTime := detacherTime
  151. if endTime.After(detacherTime) {
  152. latestTime = endTime
  153. }
  154. // 减去xDBeg小时并获取日期
  155. milkDate := latestTime.Add(time.Duration(-xDBeg) * time.Hour).Format(model.LayoutDate2)
  156. // 更新数据库
  157. if err := e.DB.Model(new(model.MilkOriginal)).
  158. Select("milk_date").
  159. Where("id = ?", v.Id).
  160. Update("milk_date", milkDate).Error; err != nil {
  161. zaplog.Error("UpdateMilkDate", zap.Any("err", err), zap.Any("milkDate", milkDate))
  162. }
  163. }
  164. }
  165. // DeleteRepeatMilkData 删除重复数据
  166. func (e *Entry) DeleteRepeatMilkData(pastureId int64, deleteModel *DeleteMilkOriginal, cfg *MilkClassConfig) {
  167. // 获取最小日期对应的最小wid
  168. var oriWid int64
  169. if err := e.DB.Model(new(model.MilkOriginal)).
  170. Select("MIN(id)").
  171. Where("pasture_id = ?", pastureId).
  172. Where("milk_date = ?", deleteModel.XMind).
  173. Scan(&oriWid).Error; err != nil {
  174. zaplog.Error("DeleteRepeatMilkData GetOriWid", zap.Any("pastureId", pastureId), zap.Any("err", err))
  175. return
  176. }
  177. milkOriginalList := make([]*model.MilkOriginal, 0)
  178. if err := e.DB.Model(new(model.MilkOriginal)).
  179. Where("pasture_id = ?", pastureId).
  180. Where("id BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  181. Find(&milkOriginalList).Error; err != nil {
  182. zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
  183. }
  184. for _, v := range milkOriginalList {
  185. e.Delete1(v, deleteModel.XMind, cfg)
  186. }
  187. /*// 2. 删除重复记录(除第一条外)
  188. if err := e.DB.Exec(`
  189. DELETE FROM milk_original
  190. WHERE wid IN (
  191. SELECT m.wid FROM (
  192. SELECT m1.wid, m1.milk_date, m1.shifts, m1.detacher_address, m1.attach_time, m1.milk_weight, m1.pasture_id
  193. FROM milk_original m1
  194. WHERE m1.wid BETWEEN ? AND ?
  195. AND m1.milk_date >= ?
  196. AND EXISTS (
  197. SELECT 1 FROM milk_original m2
  198. WHERE m2.wid BETWEEN ? AND ?
  199. AND m2.milk_date = m1.milk_date
  200. AND m2.shifts = m1.shifts
  201. AND m2.detacher_address = m1.detacher_address
  202. AND m2.attach_time = m1.attach_time
  203. AND m2.milk_weight = m1.milk_weight
  204. AND m2.pasture_id = m1.pasture_id
  205. AND m2.wid < m1.wid
  206. )
  207. ) m
  208. )`,
  209. oriWid, maxWid, minDate, oriWid, maxWid).Error; err != nil {
  210. zaplog.Error("DeleteRepeatMilkData DeleteDuplicates", zap.Any("err", err))
  211. }
  212. // 4. 删除各班次开始前无奶量记录
  213. if err := e.DB.Exec(`
  214. DELETE FROM milk_original
  215. WHERE wid IN (
  216. SELECT m.wid FROM (
  217. SELECT m1.wid, m1.milk_date, m1.shifts, m1.milk_weight,
  218. @tot := IF(@tot + m1.milk_weight > 100, 100,
  219. IF(m1.shifts = @shifts, @tot, 0) + m1.milk_weight) m_tot,
  220. @shifts := m1.shifts
  221. FROM milk_original m1, (SELECT @tot := 0, @shifts := 0) aa
  222. WHERE m1.wid BETWEEN ? AND ?
  223. AND m1.milk_date >= ?
  224. AND m1.pasture_id = ?
  225. ORDER BY m1.milk_date, m1.shifts, STR_TO_DATE(m1.attach_time, '%Y-%m-%d %H:%i:%s')
  226. ) m
  227. WHERE m.m_tot = 0
  228. )`,
  229. minWid, maxWid, minDate, pastureId).Error; err != nil {
  230. zaplog.Error("DeleteRepeatMilkData DeleteNoMilkAtShift", zap.Any("err", err))
  231. }
  232. // 5. 删除时间异常数据
  233. if err := e.DB.Exec(`
  234. DELETE FROM milk_original
  235. WHERE wid BETWEEN ? AND ?
  236. AND milk_date >= '2020-10-01'
  237. AND STR_TO_DATE(milk_date_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
  238. AND STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
  239. AND HOUR(STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s')) = 23
  240. AND pasture_id = ?`,
  241. minWid, maxWid, pastureId).Error; err != nil {
  242. zaplog.Error("DeleteRepeatMilkData DeleteAbnormalTime", zap.Any("err", err))
  243. }*/
  244. }
  245. func (e *Entry) Delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  246. // 1. 删除attach_time为00:00:00的记录
  247. acctchStr := util.Substr(data.AttachTime, -1, 8)
  248. if data.MilkDate < xMinD || acctchStr != "00:00:00" {
  249. return
  250. }
  251. // 2. 检查是否存在符合条件的m2记录
  252. var count int64
  253. if err := e.DB.Model(new(model.MilkOriginal)).
  254. Where("wid BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  255. Where("milk_date = ?", data.MilkDate).
  256. Where("detacher_address = ?", data.DetacherAddress).
  257. Where("ABS(TIMESTAMPDIFF(SECOND, detach_time, ?)) < 10", data.DetacherTime).
  258. Where("milk_weight = ?", data.MilkWeight).
  259. Where("pasture_id = ?", data.PastureId).
  260. Where("RIGHT(attach_time, 8) != '00:00:00'").
  261. Count(&count).Error; err != nil {
  262. zaplog.Error("Delete1", zap.Any("err", err))
  263. return
  264. }
  265. if count > 0 {
  266. if err := e.DB.Model(new(model.MilkOriginal)).
  267. Where("id = ?", data.Id).
  268. Delete(data).Error; err != nil {
  269. zaplog.Error("Delete1", zap.Any("err", err), zap.Any("data", data))
  270. }
  271. }
  272. }
  273. func parseXBeg(cfg *MilkClassConfig) (xBeg, xBeg1, xBeg2, xBeg3, xBeg4 int) {
  274. xBeg1Parts := strings.Split(cfg.FirstClassMilkTime, ":")
  275. if len(xBeg1Parts) < 2 {
  276. return
  277. }
  278. // 提取最后一部分
  279. xBeg1LastPart, _ := strconv.Atoi(xBeg1Parts[len(xBeg1Parts)-1])
  280. xBeg, _ = strconv.Atoi(xBeg1Parts[0])
  281. xBeg1, _ = strconv.Atoi(xBeg1Parts[1])
  282. xBeg1 = xBeg1*100 + xBeg1LastPart
  283. xBeg2Parts := strings.Split(cfg.SecondClassMilkTime, ":")
  284. if len(xBeg2Parts) < 2 {
  285. return
  286. }
  287. xBeg2LastPart, _ := strconv.Atoi(xBeg2Parts[len(xBeg2Parts)-1])
  288. xBeg2, _ = strconv.Atoi(xBeg2Parts[0])
  289. xBeg2 = xBeg2*100 + xBeg2LastPart
  290. xBeg3Parts := strings.Split(cfg.ThirdClassMilkTime, ":")
  291. if len(xBeg3Parts) < 2 {
  292. return
  293. }
  294. xBeg3LastPart, _ := strconv.Atoi(xBeg3Parts[len(xBeg3Parts)-1])
  295. xBeg3, _ = strconv.Atoi(xBeg3Parts[0])
  296. xBeg3 = xBeg3*100 + xBeg3LastPart
  297. xBeg4Parts := strings.Split(cfg.FourthClassMilkTime, ":")
  298. if len(xBeg4Parts) < 2 {
  299. return
  300. }
  301. xBeg4LastPart, _ := strconv.Atoi(xBeg4Parts[len(xBeg4Parts)-1])
  302. xBeg4, _ = strconv.Atoi(xBeg4Parts[0])
  303. xBeg4 = xBeg4*100 + xBeg4LastPart
  304. return
  305. }