milk_original.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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. e.Delete2(v, deleteModel.XMind, cfg)
  187. e.Delete3(v, deleteModel.XMind, cfg)
  188. e.Delete4(v, deleteModel.XMind, cfg)
  189. }
  190. /*// 2. 删除重复记录(除第一条外)
  191. if err := e.DB.Exec(`
  192. DELETE FROM milk_original
  193. WHERE wid IN (
  194. SELECT m.wid FROM (
  195. SELECT m1.wid, m1.milk_date, m1.shifts, m1.detacher_address, m1.attach_time, m1.milk_weight, m1.pasture_id
  196. FROM milk_original m1
  197. WHERE m1.wid BETWEEN ? AND ?
  198. AND m1.milk_date >= ?
  199. AND EXISTS (
  200. SELECT 1 FROM milk_original m2
  201. WHERE m2.wid BETWEEN ? AND ?
  202. AND m2.milk_date = m1.milk_date
  203. AND m2.shifts = m1.shifts
  204. AND m2.detacher_address = m1.detacher_address
  205. AND m2.attach_time = m1.attach_time
  206. AND m2.milk_weight = m1.milk_weight
  207. AND m2.pasture_id = m1.pasture_id
  208. AND m2.wid < m1.wid
  209. )
  210. ) m
  211. )`,
  212. oriWid, maxWid, minDate, oriWid, maxWid).Error; err != nil {
  213. zaplog.Error("DeleteRepeatMilkData DeleteDuplicates", zap.Any("err", err))
  214. }
  215. // 4. 删除各班次开始前无奶量记录
  216. if err := e.DB.Exec(`
  217. DELETE FROM milk_original
  218. WHERE wid IN (
  219. SELECT m.wid FROM (
  220. SELECT m1.wid, m1.milk_date, m1.shifts, m1.milk_weight,
  221. @tot := IF(@tot + m1.milk_weight > 100, 100,
  222. IF(m1.shifts = @shifts, @tot, 0) + m1.milk_weight) m_tot,
  223. @shifts := m1.shifts
  224. FROM milk_original m1, (SELECT @tot := 0, @shifts := 0) aa
  225. WHERE m1.wid BETWEEN ? AND ?
  226. AND m1.milk_date >= ?
  227. AND m1.pasture_id = ?
  228. ORDER BY m1.milk_date, m1.shifts, STR_TO_DATE(m1.attach_time, '%Y-%m-%d %H:%i:%s')
  229. ) m
  230. WHERE m.m_tot = 0
  231. )`,
  232. minWid, maxWid, minDate, pastureId).Error; err != nil {
  233. zaplog.Error("DeleteRepeatMilkData DeleteNoMilkAtShift", zap.Any("err", err))
  234. }
  235. // 5. 删除时间异常数据
  236. if err := e.DB.Exec(`
  237. DELETE FROM milk_original
  238. WHERE wid BETWEEN ? AND ?
  239. AND milk_date >= '2020-10-01'
  240. AND STR_TO_DATE(milk_date_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
  241. AND STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
  242. AND HOUR(STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s')) = 23
  243. AND pasture_id = ?`,
  244. minWid, maxWid, pastureId).Error; err != nil {
  245. zaplog.Error("DeleteRepeatMilkData DeleteAbnormalTime", zap.Any("err", err))
  246. }*/
  247. }
  248. func (e *Entry) Delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  249. // 1. 删除attach_time为00:00:00的记录
  250. acctchStr := util.Substr(data.AttachTime, -1, 8)
  251. if data.MilkDate < xMinD || acctchStr != "00:00:00" {
  252. return
  253. }
  254. // 2. 检查是否存在符合条件的m2记录
  255. var count int64
  256. if err := e.DB.Model(new(model.MilkOriginal)).
  257. Where("wid BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  258. Where("milk_date = ?", data.MilkDate).
  259. Where("detacher_address = ?", data.DetacherAddress).
  260. Where("ABS(TIMESTAMPDIFF(SECOND, detach_time, ?)) < 10", data.DetacherTime).
  261. Where("milk_weight = ?", data.MilkWeight).
  262. Where("pasture_id = ?", data.PastureId).
  263. Where("RIGHT(attach_time, 8) != '00:00:00'").
  264. Count(&count).Error; err != nil {
  265. zaplog.Error("Delete1", zap.Any("err", err))
  266. return
  267. }
  268. if count > 0 {
  269. if err := e.DB.Model(new(model.MilkOriginal)).
  270. Where("id = ?", data.Id).
  271. Delete(data).Error; err != nil {
  272. zaplog.Error("Delete1", zap.Any("err", err), zap.Any("data", data))
  273. }
  274. }
  275. }
  276. func (e *Entry) Delete2(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  277. // 1. 检查记录是否在时间范围内
  278. if data.MilkDate < xMinD {
  279. return
  280. }
  281. // 2. 检查是否存在重复记录(除第一条外)
  282. var count int64
  283. if err := e.DB.Model(new(model.MilkOriginal)).
  284. Where("id BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  285. Where("milk_date = ?", data.MilkDate).
  286. Where("shifts = ?", data.Shifts).
  287. Where("detacher_address = ?", data.DetacherAddress).
  288. Where("attach_time = ?", data.AttachTime).
  289. Where("milk_weight = ?", data.MilkWeight).
  290. Where("pasture_id = ?", data.PastureId).
  291. Where("id < ?", data.Id). // 只查找比当前记录更早的记录
  292. Count(&count).Error; err != nil {
  293. zaplog.Error("Delete2", zap.Any("err", err))
  294. return
  295. }
  296. // 3. 如果存在重复记录,则删除当前记录
  297. if count > 0 {
  298. if err := e.DB.Model(new(model.MilkOriginal)).
  299. Where("id = ?", data.Id).
  300. Delete(data).Error; err != nil {
  301. zaplog.Error("Delete2", zap.Any("err", err), zap.Any("data", data))
  302. }
  303. }
  304. }
  305. func (e *Entry) Delete3(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  306. // 1. 检查记录是否在时间范围内
  307. if data.MilkDate < xMinD {
  308. return
  309. }
  310. // 2. 检查是否为班次开始且无奶量记录
  311. var isFirstInShift bool
  312. if err := e.DB.Raw(`
  313. SELECT 1 FROM (
  314. SELECT m.id, m.milk_date, m.shifts, m.milk_weight,
  315. @tot := IF(@tot + m.milk_weight > 100, 100,
  316. IF(m.shifts = @shifts, @tot, 0) + m.milk_weight) m_tot,
  317. @shifts := m.shifts
  318. FROM milk_original m, (SELECT @tot := 0, @shifts := 0) vars
  319. WHERE m.id BETWEEN ? AND ?
  320. AND m.milk_date >= ?
  321. AND m.pasture_id = ?
  322. ORDER BY m.milk_date, m.shifts, m.attach_time
  323. ) t
  324. WHERE t.id = ? AND t.m_tot = 0`,
  325. cfg.OldUpdateMaxId+1, cfg.CurrentMaxId, xMinD, data.PastureId, data.Id).
  326. Scan(&isFirstInShift).Error; err != nil {
  327. zaplog.Error("Delete3", zap.Any("err", err))
  328. return
  329. }
  330. // 3. 如果是班次开始且无奶量记录,则删除
  331. if isFirstInShift {
  332. if err := e.DB.Model(new(model.MilkOriginal)).
  333. Where("id = ?", data.Id).
  334. Delete(data).Error; err != nil {
  335. zaplog.Error("Delete3", zap.Any("err", err), zap.Any("data", data))
  336. }
  337. }
  338. }
  339. func (e *Entry) Delete4(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  340. // 1. 检查记录是否在时间范围内
  341. if data.MilkDate < "2020-10-01" {
  342. return
  343. }
  344. // 2. 检查是否为时间异常记录
  345. var isAbnormal bool
  346. if err := e.DB.Model(new(model.MilkOriginal)).
  347. Where("id = ?", data.Id).
  348. Where("milk_date >= ?", "2020-10-01").
  349. Where("recognition_time > detacher_time").
  350. Where("attach_time > detacher_time").
  351. Where("SUBSTRING(attach_time, 12, 2) = ?", "23").
  352. Where("pasture_id = ?", data.PastureId).
  353. Select("1").
  354. Scan(&isAbnormal).Error; err != nil {
  355. zaplog.Error("Delete4", zap.Any("err", err))
  356. return
  357. }
  358. // 3. 如果是时间异常记录,则删除
  359. if isAbnormal {
  360. if err := e.DB.Model(new(model.MilkOriginal)).
  361. Where("id = ?", data.Id).
  362. Delete(data).Error; err != nil {
  363. zaplog.Error("Delete4", zap.Any("err", err), zap.Any("data", data))
  364. }
  365. }
  366. }
  367. func parseXBeg(cfg *MilkClassConfig) (xBeg, xBeg1, xBeg2, xBeg3, xBeg4 int) {
  368. xBeg1Parts := strings.Split(cfg.FirstClassMilkTime, ":")
  369. if len(xBeg1Parts) < 2 {
  370. return
  371. }
  372. // 提取最后一部分
  373. xBeg1LastPart, _ := strconv.Atoi(xBeg1Parts[len(xBeg1Parts)-1])
  374. xBeg, _ = strconv.Atoi(xBeg1Parts[0])
  375. xBeg1, _ = strconv.Atoi(xBeg1Parts[1])
  376. xBeg1 = xBeg1*100 + xBeg1LastPart
  377. xBeg2Parts := strings.Split(cfg.SecondClassMilkTime, ":")
  378. if len(xBeg2Parts) < 2 {
  379. return
  380. }
  381. xBeg2LastPart, _ := strconv.Atoi(xBeg2Parts[len(xBeg2Parts)-1])
  382. xBeg2, _ = strconv.Atoi(xBeg2Parts[0])
  383. xBeg2 = xBeg2*100 + xBeg2LastPart
  384. xBeg3Parts := strings.Split(cfg.ThirdClassMilkTime, ":")
  385. if len(xBeg3Parts) < 2 {
  386. return
  387. }
  388. xBeg3LastPart, _ := strconv.Atoi(xBeg3Parts[len(xBeg3Parts)-1])
  389. xBeg3, _ = strconv.Atoi(xBeg3Parts[0])
  390. xBeg3 = xBeg3*100 + xBeg3LastPart
  391. xBeg4Parts := strings.Split(cfg.FourthClassMilkTime, ":")
  392. if len(xBeg4Parts) < 2 {
  393. return
  394. }
  395. xBeg4LastPart, _ := strconv.Atoi(xBeg4Parts[len(xBeg4Parts)-1])
  396. xBeg4, _ = strconv.Atoi(xBeg4Parts[0])
  397. xBeg4 = xBeg4*100 + xBeg4LastPart
  398. return
  399. }