milk_original_update.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. shifts := make([]int32, 0)
  29. milkClassConfig := &MilkClassConfig{}
  30. for _, v := range milkConfigList {
  31. switch v.Name {
  32. case model.FirstClassMilkTime:
  33. milkClassConfig.FirstClassMilkTime = v.Value
  34. shifts = append(shifts, 1)
  35. case model.SecondClassMilkTime:
  36. milkClassConfig.SecondClassMilkTime = v.Value
  37. shifts = append(shifts, 2)
  38. case model.ThirdClassMilkTime:
  39. milkClassConfig.ThirdClassMilkTime = v.Value
  40. shifts = append(shifts, 3)
  41. case model.FourthClassMilkTime:
  42. milkClassConfig.FourthClassMilkTime = v.Value
  43. shifts = append(shifts, 4)
  44. case model.UpdateMilkOriginalMaxId:
  45. maxId, _ := strconv.ParseInt(v.Value, 10, 64)
  46. milkClassConfig.OldUpdateMaxId = maxId
  47. }
  48. }
  49. xDBeg, xBeg1, xBeg2, xBeg3, xBeg4 := parseXBeg(milkClassConfig)
  50. e.UpdateShifts(pastureId, xBeg1, xBeg2, xBeg3, xBeg4)
  51. e.UpdateMilkDate(pastureId, xDBeg)
  52. // 获取当前最大Id
  53. var currentMaxId int64
  54. if err = e.DB.Model(new(model.MilkOriginal)).
  55. Select("MAX(id)").
  56. Where("pasture_id = ?", pastureId).
  57. Where("id > ?", milkClassConfig.OldUpdateMaxId).
  58. Scan(&currentMaxId).Error; err != nil {
  59. zaplog.Error("DeleteRepeatMilkData GetOriWid", zap.Any("pastureId", pastureId), zap.Any("err", err))
  60. return
  61. }
  62. milkClassConfig.CurrentMaxId = currentMaxId
  63. // 获取时间范围和ID范围
  64. deleteModel := &DeleteMilkOriginal{}
  65. selectSql := fmt.Sprintf(`MIN(DATE(TIMESTAMPADD(HOUR, -%d, attach_time))) as x_mind,
  66. 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)
  67. if err = e.DB.Model(new(model.MilkOriginal)).
  68. Select(selectSql).
  69. Where("pasture_id = ?", pastureId).
  70. Where("id > ?", milkClassConfig.OldUpdateMaxId).
  71. First(deleteModel).Error; err != nil {
  72. zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
  73. return
  74. }
  75. milkOriginalList := make([]*model.MilkOriginal, 0)
  76. if err = e.DB.Model(new(model.MilkOriginal)).
  77. Where("pasture_id = ?", pastureId).
  78. Where("id BETWEEN ? AND ?", milkClassConfig.OldUpdateMaxId+1, milkClassConfig.CurrentMaxId).
  79. Find(&milkOriginalList).Error; err != nil {
  80. zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
  81. return
  82. }
  83. e.DeleteRepeatMilkData(pastureId, deleteModel, milkClassConfig, milkOriginalList)
  84. milkHallList := e.FindMilkHallList(pastureId)
  85. for _, hall := range milkHallList {
  86. e.UpdateRecognitionTime(pastureId, hall)
  87. e.UpdateRepeatCupSet1(milkOriginalList)
  88. e.UpdateMilkOriginCowInfo(milkOriginalList, hall)
  89. e.UpdateRepeatCupSet2(milkOriginalList)
  90. e.UpdateMilkOriginalInitialTimesAndAttachAdjustTime(shifts, milkOriginalList)
  91. e.UpdateMilkNattach(pastureId, milkClassConfig, hall)
  92. e.UpdateMilkNoCowId(pastureId, milkClassConfig, hall)
  93. e.UpdateMilkLoad(pastureId, milkClassConfig, hall)
  94. e.UpdateMilkLoad2(pastureId, milkClassConfig, hall)
  95. }
  96. }
  97. // UpdateShifts 更新班次
  98. func (e *Entry) UpdateShifts(pastureId int64, xBeg1, xBeg2, xBeg3, xBeg4 int) {
  99. milkOriginalList := make([]*model.MilkOriginal, 0)
  100. if err := e.DB.Model(new(model.MilkOriginal)).
  101. Where("pasture_id = ?", pastureId).
  102. Where("shifts = ?", 0).
  103. Find(&milkOriginalList).Error; err != nil {
  104. zaplog.Error("UpdateShifts", zap.Any("pastureId", pastureId), zap.Any("err", err))
  105. }
  106. for _, v := range milkOriginalList {
  107. subDetachTime1 := util.Substr(v.DetachedTime, 11, 2)
  108. subDetachTime2 := util.Substr(v.DetachedTime, 14, 2)
  109. subDetachTime1Int, _ := strconv.ParseInt(subDetachTime1, 10, 64)
  110. subDetachTime2Int, _ := strconv.ParseInt(subDetachTime2, 10, 64)
  111. allDetachTime := int(subDetachTime1Int*100 + subDetachTime2Int)
  112. // 更新第一班
  113. if xBeg2 > xBeg1 {
  114. if allDetachTime >= xBeg1 && allDetachTime <= xBeg2 {
  115. v.Shifts = 1
  116. }
  117. } else {
  118. if allDetachTime >= xBeg1 || allDetachTime <= xBeg2 {
  119. v.Shifts = 1
  120. }
  121. }
  122. // 更新第二班
  123. if xBeg3 > xBeg2 {
  124. if allDetachTime >= xBeg2 && allDetachTime <= xBeg3 {
  125. v.Shifts = 2
  126. }
  127. } else {
  128. if allDetachTime >= xBeg2 || allDetachTime <= xBeg3 {
  129. v.Shifts = 2
  130. }
  131. }
  132. // 更新第四班(如果有)
  133. if xBeg4 > 0 && xBeg4 != xBeg1 {
  134. if xBeg1 > xBeg4 {
  135. if allDetachTime >= xBeg4 && allDetachTime <= xBeg1 {
  136. v.Shifts = 4
  137. }
  138. } else {
  139. if allDetachTime >= xBeg4 || allDetachTime <= xBeg1 {
  140. v.Shifts = 4
  141. }
  142. }
  143. }
  144. // 如果还没有分配班次,则分配到第三班
  145. if v.Shifts == 0 {
  146. v.Shifts = 3
  147. }
  148. // 批量更新数据库
  149. if err := e.DB.Model(new(model.MilkOriginal)).
  150. Select("shifts").
  151. Where("id = ?", v.Id).
  152. Updates(v).Error; err != nil {
  153. zaplog.Error("UpdateShifts Save", zap.Any("pastureId", pastureId), zap.Any("err", err))
  154. }
  155. }
  156. }
  157. // UpdateMilkDate 更换挤奶时间
  158. func (e *Entry) UpdateMilkDate(pastureId int64, xDBeg int) {
  159. milkOriginalList := make([]*model.MilkOriginal, 0)
  160. if err := e.DB.Model(new(model.MilkOriginal)).
  161. Where("pasture_id = ?", pastureId).
  162. Where("milk_date = ?", "").
  163. Find(&milkOriginalList).Error; err != nil {
  164. zaplog.Error("UpdateMilkDate", zap.Any("pastureId", pastureId), zap.Any("err", err))
  165. return
  166. }
  167. for _, v := range milkOriginalList {
  168. // 获取结束时间,如果为空则使用默认时间
  169. var endTime time.Time
  170. if v.EndTime == "" {
  171. endTime = time.Date(1999, 12, 31, 23, 0, 0, 0, time.Local)
  172. }
  173. // 比较挤奶时间和结束时间,取较晚的时间
  174. detachedTime, _ := util.TimeParseLocal(model.LayoutTime, v.DetachedTime)
  175. latestTime := detachedTime
  176. if endTime.After(detachedTime) {
  177. latestTime = endTime
  178. }
  179. // 减去xDBeg小时并获取日期
  180. milkDate := latestTime.Add(time.Duration(-xDBeg) * time.Hour).Format(model.LayoutDate2)
  181. // 更新数据库
  182. if err := e.DB.Model(new(model.MilkOriginal)).
  183. Select("milk_date").
  184. Where("id = ?", v.Id).
  185. Update("milk_date", milkDate).Error; err != nil {
  186. zaplog.Error("UpdateMilkDate", zap.Any("err", err), zap.Any("milkDate", milkDate))
  187. }
  188. }
  189. }
  190. // DeleteRepeatMilkData 删除重复数据
  191. func (e *Entry) DeleteRepeatMilkData(pastureId int64, deleteModel *DeleteMilkOriginal, cfg *MilkClassConfig, milkOriginalList []*model.MilkOriginal) {
  192. // 获取最小日期对应的最小wid
  193. var oriWid int64
  194. if err := e.DB.Model(new(model.MilkOriginal)).
  195. Select("MIN(id)").
  196. Where("pasture_id = ?", pastureId).
  197. Where("milk_date = ?", deleteModel.XMind).
  198. Scan(&oriWid).Error; err != nil {
  199. zaplog.Error("DeleteRepeatMilkData GetOriWid", zap.Any("pastureId", pastureId), zap.Any("err", err))
  200. return
  201. }
  202. for _, v := range milkOriginalList {
  203. e.delete1(v, deleteModel.XMind, cfg)
  204. e.delete2(v, deleteModel.XMind, cfg)
  205. e.delete3(v, deleteModel.XMind, cfg)
  206. e.delete4(v)
  207. }
  208. }
  209. func (e *Entry) delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  210. // 1. 删除attach_time为00:00:00的记录
  211. actchStr := util.Substr(data.AttachTime, -1, 8)
  212. if data.MilkDate < xMinD || actchStr != "00:00:00" {
  213. return
  214. }
  215. // 2. 检查是否存在符合条件的m2记录
  216. var count int64
  217. if err := e.DB.Model(new(model.MilkOriginal)).
  218. Where("id BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  219. Where("milk_date = ?", data.MilkDate).
  220. Where("detached_address = ?", data.DetachedAddress).
  221. Where("ABS(TIMESTAMPDIFF(SECOND, detach_time, ?)) < 10", data.DetachedTime).
  222. Where("milk_weight = ?", data.MilkWeight).
  223. Where("pasture_id = ?", data.PastureId).
  224. Where("RIGHT(attach_time, 8) != '00:00:00'").
  225. Count(&count).Error; err != nil {
  226. zaplog.Error("Delete1", zap.Any("err", err))
  227. return
  228. }
  229. if count > 0 {
  230. if err := e.DB.Model(new(model.MilkOriginal)).
  231. Where("id = ?", data.Id).
  232. Delete(data).Error; err != nil {
  233. zaplog.Error("Delete1", zap.Any("err", err), zap.Any("data", data))
  234. }
  235. }
  236. }
  237. func (e *Entry) delete2(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  238. // 1. 检查记录是否在时间范围内
  239. if data.MilkDate < xMinD {
  240. return
  241. }
  242. // 2. 检查是否存在重复记录(除第一条外)
  243. var count int64
  244. if err := e.DB.Model(new(model.MilkOriginal)).
  245. Where("id BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
  246. Where("milk_date = ?", data.MilkDate).
  247. Where("shifts = ?", data.Shifts).
  248. Where("detached_address = ?", data.DetachedAddress).
  249. Where("attach_time = ?", data.AttachTime).
  250. Where("milk_weight = ?", data.MilkWeight).
  251. Where("pasture_id = ?", data.PastureId).
  252. Where("id < ?", data.Id). // 只查找比当前记录更早的记录
  253. Count(&count).Error; err != nil {
  254. zaplog.Error("Delete2", zap.Any("err", err))
  255. return
  256. }
  257. // 3. 如果存在重复记录,则删除当前记录
  258. if count > 0 {
  259. if err := e.DB.Model(new(model.MilkOriginal)).
  260. Where("id = ?", data.Id).
  261. Delete(data).Error; err != nil {
  262. zaplog.Error("Delete2", zap.Any("err", err), zap.Any("data", data))
  263. }
  264. }
  265. }
  266. func (e *Entry) delete3(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
  267. // 1. 检查记录是否在时间范围内
  268. if data.MilkDate < xMinD {
  269. return
  270. }
  271. // 2. 检查是否为班次开始且无奶量记录
  272. var isFirstInShift bool
  273. if err := e.DB.Raw(`
  274. SELECT 1 FROM (
  275. SELECT m.id, m.milk_date, m.shifts, m.milk_weight,
  276. @tot := IF(@tot + m.milk_weight > 100, 100,
  277. IF(m.shifts = @shifts, @tot, 0) + m.milk_weight) m_tot,
  278. @shifts := m.shifts
  279. FROM milk_original m, (SELECT @tot := 0, @shifts := 0) vars
  280. WHERE m.id BETWEEN ? AND ?
  281. AND m.milk_date >= ?
  282. AND m.pasture_id = ?
  283. ORDER BY m.milk_date, m.shifts, m.attach_time
  284. ) t
  285. WHERE t.id = ? AND t.m_tot = 0`,
  286. cfg.OldUpdateMaxId+1, cfg.CurrentMaxId, xMinD, data.PastureId, data.Id).
  287. Scan(&isFirstInShift).Error; err != nil {
  288. zaplog.Error("Delete3", zap.Any("err", err))
  289. return
  290. }
  291. // 3. 如果是班次开始且无奶量记录,则删除
  292. if isFirstInShift {
  293. if err := e.DB.Model(new(model.MilkOriginal)).
  294. Where("id = ?", data.Id).
  295. Delete(data).Error; err != nil {
  296. zaplog.Error("Delete3", zap.Any("err", err), zap.Any("data", data))
  297. }
  298. }
  299. }
  300. func (e *Entry) delete4(data *model.MilkOriginal) {
  301. // 1. 检查记录是否在时间范围内
  302. if data.MilkDate < "2020-10-01" {
  303. return
  304. }
  305. // 2. 检查是否为时间异常记录
  306. var isAbnormal bool
  307. if err := e.DB.Model(new(model.MilkOriginal)).
  308. Where("id = ?", data.Id).
  309. Where("milk_date >= ?", "2020-10-01").
  310. Where("recognition_time > detached_time").
  311. Where("attach_time > detached_time").
  312. Where("SUBSTRING(attach_time, 12, 2) = ?", "23").
  313. Where("pasture_id = ?", data.PastureId).
  314. Select("1").
  315. Scan(&isAbnormal).Error; err != nil {
  316. zaplog.Error("Delete4", zap.Any("err", err))
  317. return
  318. }
  319. // 3. 如果是时间异常记录,则删除
  320. if isAbnormal {
  321. if err := e.DB.Model(new(model.MilkOriginal)).
  322. Where("id = ?", data.Id).
  323. Delete(data).Error; err != nil {
  324. zaplog.Error("Delete4", zap.Any("err", err), zap.Any("data", data))
  325. }
  326. }
  327. }
  328. func parseXBeg(cfg *MilkClassConfig) (xBeg, xBeg1, xBeg2, xBeg3, xBeg4 int) {
  329. xBeg1Parts := strings.Split(cfg.FirstClassMilkTime, ":")
  330. if len(xBeg1Parts) < 2 {
  331. return
  332. }
  333. // 提取最后一部分
  334. xBeg1LastPart, _ := strconv.Atoi(xBeg1Parts[len(xBeg1Parts)-1])
  335. xBeg, _ = strconv.Atoi(xBeg1Parts[0])
  336. xBeg1, _ = strconv.Atoi(xBeg1Parts[1])
  337. xBeg1 = xBeg1*100 + xBeg1LastPart
  338. xBeg2Parts := strings.Split(cfg.SecondClassMilkTime, ":")
  339. if len(xBeg2Parts) < 2 {
  340. return
  341. }
  342. xBeg2LastPart, _ := strconv.Atoi(xBeg2Parts[len(xBeg2Parts)-1])
  343. xBeg2, _ = strconv.Atoi(xBeg2Parts[0])
  344. xBeg2 = xBeg2*100 + xBeg2LastPart
  345. xBeg3Parts := strings.Split(cfg.ThirdClassMilkTime, ":")
  346. if len(xBeg3Parts) < 2 {
  347. return
  348. }
  349. xBeg3LastPart, _ := strconv.Atoi(xBeg3Parts[len(xBeg3Parts)-1])
  350. xBeg3, _ = strconv.Atoi(xBeg3Parts[0])
  351. xBeg3 = xBeg3*100 + xBeg3LastPart
  352. xBeg4Parts := strings.Split(cfg.FourthClassMilkTime, ":")
  353. if len(xBeg4Parts) < 2 {
  354. return
  355. }
  356. xBeg4LastPart, _ := strconv.Atoi(xBeg4Parts[len(xBeg4Parts)-1])
  357. xBeg4, _ = strconv.Atoi(xBeg4Parts[0])
  358. xBeg4 = xBeg4*100 + xBeg4LastPart
  359. return
  360. }