event_breed.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. package backend
  2. import (
  3. "context"
  4. "fmt"
  5. "kpt-pasture/model"
  6. "kpt-pasture/util"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  12. "go.uber.org/zap"
  13. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  14. "gitee.com/xuyiping_admin/pkg/xerr"
  15. "gorm.io/gorm"
  16. )
  17. func (s *StoreEntry) CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error) {
  18. lavingList := make([]*model.EventCalvingList, 0)
  19. var count int64 = 0
  20. pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())).
  21. Select(`a.*,b.name as pen_name,c.name as staff_member_name`).
  22. Joins(fmt.Sprintf("JOIN %s AS b on a.pen_id = b.id", new(model.Pen).TableName())).
  23. Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName()))
  24. if len(req.CowId) > 0 {
  25. cowIds := strings.Split(req.CowId, ",")
  26. pref.Where("a.cow_id IN ?", cowIds)
  27. }
  28. if err := pref.Order("a.id desc").
  29. Count(&count).Limit(int(pagination.PageSize)).
  30. Offset(int(pagination.PageOffset)).
  31. Find(&lavingList).Error; err != nil {
  32. return nil, xerr.WithStack(err)
  33. }
  34. calvingIds := make([]int64, 0)
  35. for _, v := range lavingList {
  36. calvingIds = append(calvingIds, v.Id)
  37. }
  38. calvingCalfList := make([]*model.CalvingCalf, 0)
  39. if err := s.DB.Model(new(model.CalvingCalf)).
  40. Where("calving_id IN ?", calvingIds).
  41. Find(&calvingCalfList).Error; err != nil {
  42. return nil, xerr.WithStack(err)
  43. }
  44. return &pasturePb.SearchLavingEventResponse{
  45. Code: http.StatusOK,
  46. Message: "ok",
  47. Data: &pasturePb.SearchLavingData{
  48. List: model.EventCalvingListSlice(lavingList).ToPB(calvingCalfList),
  49. Total: int32(count),
  50. PageSize: pagination.PageSize,
  51. Page: pagination.Page,
  52. },
  53. }, nil
  54. }
  55. func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalving) (err error) {
  56. cow, err := s.GetCowInfoByCowId(ctx, int64(req.CowId))
  57. if err != nil {
  58. zaplog.Error("CalvingCreate", zap.Any("cow_id", req.CowId), zap.Any("err", err))
  59. return xerr.Custom("请选择相关牛只")
  60. }
  61. operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
  62. if err != nil {
  63. return xerr.Customf("获取操作人员信息失败: %s", err.Error())
  64. }
  65. req.OperationName = operationUser.Name
  66. // 记录牛只事件日志
  67. defer func() {
  68. if err == nil {
  69. // 母牛事件日志
  70. cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Calving, pasturePb.ExposeEstrusType_Invalid, req)
  71. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  72. // 犊牛事件日志
  73. for _, v := range req.CalfItemList {
  74. if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No {
  75. continue
  76. }
  77. cow, _ = s.GetCowInfoByCowId(ctx, int64(v.CowId))
  78. cowLogs = s.SubmitEventLog(ctx, cow, pasturePb.EventType_Birth, pasturePb.ExposeEstrusType_Invalid, v)
  79. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  80. }
  81. }
  82. }()
  83. newEventCalving := &model.EventCalving{}
  84. if err = s.DB.Model(new(model.EventCalving)).
  85. Where("cow_id = ?", cow.Id).
  86. Where("lact = ?", cow.Lact).
  87. First(newEventCalving).Error; err != nil {
  88. return xerr.Custom("该母牛信息不存在")
  89. }
  90. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  91. // 更新产犊事件表
  92. newEventCalving.Update(operationUser, req, cow)
  93. if err = tx.Model(new(model.EventCalving)).
  94. Where("id = ?", newEventCalving.Id).
  95. Updates(newEventCalving).Error; err != nil {
  96. return xerr.WithStack(err)
  97. }
  98. for _, v := range req.CalfItemList {
  99. if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No {
  100. continue
  101. }
  102. // 犊牛信息
  103. newCalvingCalf := model.NewEventCalvingCalf(int64(req.CowId), newEventCalving.Id, int64(req.CalvingAt), v)
  104. // 留养犊牛
  105. newCow := model.NewCalfCow(cow.Id, cow.LastBullNumber, newCalvingCalf)
  106. if err = tx.Create(newCow).Error; err != nil {
  107. return xerr.WithStack(err)
  108. }
  109. v.CowId = int32(newCow.Id)
  110. if err = tx.Create(newCalvingCalf).Error; err != nil {
  111. return xerr.WithStack(err)
  112. }
  113. }
  114. // 更新母牛信息
  115. cow.EventCalvingUpdate(int64(req.CalvingAt))
  116. if err = tx.Model(cow).
  117. Select("calving_age,mating_times,pregnancy_age,lact,breed_status,is_pregnant,last_calving_at").
  118. Where("id = ?", cow.Id).
  119. Updates(cow).Error; err != nil {
  120. return xerr.WithStack(err)
  121. }
  122. return nil
  123. }); err != nil {
  124. return xerr.WithStack(err)
  125. }
  126. return nil
  127. }
  128. func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusItemsResponse, error) {
  129. estrusList := make([]*model.EventEstrus, 0)
  130. var count int64 = 0
  131. pref := s.DB.Table(new(model.EventEstrus).TableName()).
  132. Where("is_show = ?", pasturePb.IsShow_Ok)
  133. if len(req.CowIds) > 0 {
  134. cowIds := strings.Split(util.ArrayInt32ToStrings(req.CowIds, ","), ",")
  135. pref.Where("cow_id IN ?", cowIds)
  136. }
  137. if req.Level > 0 {
  138. pref.Where("level = ?", req.Level)
  139. }
  140. if len(req.PenIds) > 0 {
  141. penIds := strings.Split(util.ArrayInt32ToStrings(req.PenIds, ","), ",")
  142. pref.Where("pen_id IN ?", penIds)
  143. }
  144. if err := pref.Order("id desc").
  145. Count(&count).Limit(int(pagination.PageSize)).
  146. Offset(int(pagination.PageOffset)).
  147. Find(&estrusList).Error; err != nil {
  148. return nil, xerr.WithStack(err)
  149. }
  150. getCowInfoByCowId := GetCowInfoByCowId
  151. getCowLastEvent := GetCowLastEvent
  152. return &pasturePb.EstrusItemsResponse{
  153. Code: http.StatusOK,
  154. Message: "ok",
  155. Data: &pasturePb.EstrusItemsData{
  156. List: model.EstrusSlice(estrusList).ToPB(s.DB, getCowInfoByCowId, getCowLastEvent),
  157. Total: int32(count),
  158. PageSize: pagination.PageSize,
  159. Page: pagination.Page,
  160. },
  161. }, nil
  162. }
  163. func (s *StoreEntry) EstrusBatch(ctx context.Context, req *pasturePb.EventEstrus) (err error) {
  164. currentUser, err := s.GetCurrentSystemUser(ctx)
  165. if err != nil {
  166. return xerr.Custom("当前用户信息错误")
  167. }
  168. operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
  169. if err != nil {
  170. return xerr.Customf("该用户不存在: %d", req.OperationId)
  171. }
  172. req.OperationName = operationUser.Name
  173. eventEstrusIds := make([]string, 0)
  174. eventMatingList := make([]*model.EventMating, 0)
  175. for _, cowId := range req.CowIds {
  176. cowInfo := GetCowInfoByCowId(s.DB, int64(cowId))
  177. if cowInfo == nil {
  178. return xerr.Custom("牛只信息不存在")
  179. }
  180. newEventMating := model.NewEventMating(cowInfo, time.Now().Unix(), pasturePb.ExposeEstrusType_Neck_Ring)
  181. eventEstrus, ok := s.EventEstrusIsExist(ctx, int64(cowId))
  182. if ok {
  183. newEventMating.EventEstrusId = eventEstrus.Id
  184. newEventMating.MatingTimes = cowInfo.MatingTimes + 1
  185. newEventMating.Status = pasturePb.IsShow_Ok
  186. newEventMating.RealityDay = int64(req.MatingAt)
  187. newEventMating.OperationId = operationUser.Id
  188. newEventMating.OperationName = operationUser.Name
  189. newEventMating.FrozenSemenNumber = req.BullNumber
  190. newEventMating.Remarks = req.Remarks
  191. newEventMating.MessageId = currentUser.Id
  192. newEventMating.MessageName = currentUser.Name
  193. eventEstrusIds = append(eventEstrusIds, strconv.FormatInt(eventEstrus.Id, 10))
  194. }
  195. eventMatingList = append(eventMatingList, newEventMating)
  196. }
  197. if len(eventMatingList) <= 0 {
  198. return nil
  199. }
  200. defer func() {
  201. // 记录牛只事件日志
  202. if err == nil {
  203. for _, v := range eventMatingList {
  204. cow, _ := s.GetCowInfoByCowId(ctx, v.CowId)
  205. cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Mating, pasturePb.ExposeEstrusType_Neck_Ring, req)
  206. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  207. }
  208. }
  209. }()
  210. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  211. if len(eventEstrusIds) > 0 {
  212. if err = tx.Model(new(model.EventEstrus)).
  213. Where("id IN ?", eventEstrusIds).
  214. Updates(map[string]interface{}{
  215. "is_show": pasturePb.IsShow_No,
  216. "result": pasturePb.EstrusResult_Correct,
  217. }).Error; err != nil {
  218. return xerr.WithStack(err)
  219. }
  220. }
  221. if len(eventMatingList) > 0 {
  222. if err = tx.Create(eventMatingList).Error; err != nil {
  223. return xerr.WithStack(err)
  224. }
  225. }
  226. return nil
  227. }); err != nil {
  228. return xerr.WithStack(err)
  229. }
  230. return nil
  231. }
  232. func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) (err error) {
  233. eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, int64(req.CowId))
  234. if err != nil {
  235. zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req))
  236. return xerr.Customf("异常数据")
  237. }
  238. drugs := &model.Drugs{}
  239. if drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId)); err != nil {
  240. zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req))
  241. return xerr.Customf("该药品不存在: %d", req.DrugsId)
  242. }
  243. req.DrugsName = drugs.Name
  244. operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
  245. if err != nil {
  246. return xerr.WithStack(err)
  247. }
  248. currentUser, err := s.GetCurrentSystemUser(ctx)
  249. if err != nil {
  250. return xerr.Custom("当前用户信息错误")
  251. }
  252. eventCowSameTime.Update(drugs, req.Usage, req.Remarks, operationUser, currentUser)
  253. defer func() {
  254. if err == nil {
  255. // 记录牛只事件日志
  256. cow, _ := s.GetCowInfoByCowId(ctx, eventCowSameTime.CowId)
  257. cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Seme_Time, pasturePb.ExposeEstrusType_Same_Time, req)
  258. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  259. if err = s.DB.Model(new(model.CowSameTime)).
  260. Where("cow_id = ?", eventCowSameTime.CowId).
  261. Where("same_time_id = ?", eventCowSameTime.Id).
  262. Where("same_time_status = ?", pasturePb.SameTimeStatus_No_Start).
  263. Update("same_time_status", pasturePb.SameTimeStatus_In_Progress).Error; err != nil {
  264. zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req))
  265. }
  266. }
  267. }()
  268. if err = s.DB.Model(new(model.EventCowSameTime)).
  269. Select("status,drugs_id,unit,usage,remarks,operation_id,operation_name").
  270. Where("id = ?", eventCowSameTime.Id).
  271. Updates(eventCowSameTime).Error; err != nil {
  272. return xerr.WithStack(err)
  273. }
  274. return nil
  275. }
  276. func (s *StoreEntry) SameTimeBatch(ctx context.Context, req *pasturePb.EventSameTimeBatch) (err error) {
  277. operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
  278. if err != nil {
  279. return xerr.Customf("异常数据")
  280. }
  281. req.OperationName = operationUser.Name
  282. currentUser, err := s.GetCurrentSystemUser(ctx)
  283. if err != nil {
  284. return xerr.Customf("异常数据")
  285. }
  286. drugs := &model.Drugs{}
  287. if drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId)); err != nil {
  288. zaplog.Error("SameTimeBatch", zap.Any("err", err), zap.Any("req", req))
  289. return xerr.Customf("该药物不存在: %d", req.DrugsId)
  290. }
  291. req.DrugsName = drugs.Name
  292. eventCowSameTimeList := make([]*model.EventCowSameTime, 0)
  293. for _, v := range req.CowIds {
  294. eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, int64(v))
  295. if err != nil {
  296. zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req))
  297. return xerr.WithStack(err)
  298. }
  299. eventCowSameTimeList = append(eventCowSameTimeList, eventCowSameTime)
  300. }
  301. defer func() {
  302. // 记录牛只事件日志
  303. if err == nil {
  304. for _, v := range eventCowSameTimeList {
  305. cow, _ := s.GetCowInfoByCowId(ctx, v.CowId)
  306. cowLogs := s.SubmitEventLog(
  307. ctx,
  308. cow,
  309. pasturePb.EventType_Seme_Time,
  310. pasturePb.ExposeEstrusType_Same_Time,
  311. &pasturePb.EventSameTime{
  312. Id: int32(v.Id),
  313. CowId: int32(v.CowId),
  314. SameTimeId: int32(v.SameTimeId),
  315. SameTimeType: v.SameTimeType,
  316. SameTimeTypeName: v.SameTimeName,
  317. DrugsId: int32(v.DrugsId),
  318. DrugsName: drugs.Name,
  319. Usage: req.Usage,
  320. OperationId: int32(operationUser.Id),
  321. OperationName: operationUser.Name,
  322. SameTimeAt: req.SameTimeAt,
  323. })
  324. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  325. }
  326. }
  327. }()
  328. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  329. for _, v := range eventCowSameTimeList {
  330. if err = tx.Model(new(model.CowSameTime)).
  331. Where("cow_id = ?", v.CowId).
  332. Where("same_time_id = ?", v.Id).
  333. Where("same_time_status = ?", pasturePb.SameTimeStatus_No_Start).
  334. Update("same_time_status", pasturePb.SameTimeStatus_In_Progress).Error; err != nil {
  335. zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req))
  336. }
  337. // 更新SameTime
  338. v.Update(drugs, req.Usage, req.Remarks, currentUser, operationUser)
  339. if err = tx.Model(new(model.EventCowSameTime)).
  340. Select("status,drugs_id,unit,usage,remarks,operation_id,operation_name").
  341. Where("id = ?", v.Id).
  342. Updates(v).Error; err != nil {
  343. return xerr.WithStack(err)
  344. }
  345. }
  346. return nil
  347. }); err != nil {
  348. return xerr.WithStack(err)
  349. }
  350. return nil
  351. }
  352. func (s *StoreEntry) SameTimeList(
  353. ctx context.Context,
  354. req *pasturePb.SearchEventRequest,
  355. pagination *pasturePb.PaginationModel,
  356. ) (*pasturePb.SearchSameTimeResponse, error) {
  357. cowSameTimeList := make([]*model.EventCowSameTime, 0)
  358. var count int64 = 0
  359. pref := s.DB.Table(new(model.EventCowSameTime).TableName())
  360. if req.CowId != "" {
  361. cowIds := strings.Split(req.CowId, ",")
  362. pref.Where("cow_id IN ?", cowIds)
  363. }
  364. if err := pref.Count(&count).
  365. Limit(int(pagination.PageSize)).
  366. Offset(int(pagination.PageOffset)).
  367. Find(&cowSameTimeList).Error; err != nil {
  368. return nil, xerr.WithStack(err)
  369. }
  370. sameTimeTypeMap := s.SameTimeTypeMap()
  371. return &pasturePb.SearchSameTimeResponse{
  372. Code: http.StatusOK,
  373. Message: "ok",
  374. Data: &pasturePb.SameTimeData{
  375. List: model.EventCowSameTimeSlice(cowSameTimeList).ToPB(sameTimeTypeMap),
  376. Total: int32(count),
  377. PageSize: pagination.PageSize,
  378. Page: pagination.Page,
  379. },
  380. }, nil
  381. }
  382. func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) {
  383. matingList := make([]*model.EventMating, 0)
  384. var count int64 = 0
  385. pref := s.DB.Model(new(model.EventMating)).
  386. Where("mating_result > ?", pasturePb.MatingResult_Invalid).
  387. Where("status = ?", pasturePb.IsShow_No)
  388. if len(req.CowId) > 0 {
  389. cowIds := strings.Split(req.CowId, ",")
  390. pref.Where("cow_id IN ?", cowIds)
  391. }
  392. if err := pref.Order("id desc").
  393. Count(&count).Limit(int(pagination.PageSize)).
  394. Offset(int(pagination.PageOffset)).
  395. Find(&matingList).Error; err != nil {
  396. return nil, xerr.WithStack(err)
  397. }
  398. exposeEstrusTypeMap := s.ExposeEstrusTypeMap()
  399. return &pasturePb.MatingEventResponse{
  400. Code: http.StatusOK,
  401. Message: "ok",
  402. Data: &pasturePb.SearchMatingData{
  403. List: model.EventMatingSlice(matingList).ToPB(exposeEstrusTypeMap),
  404. Total: int32(count),
  405. PageSize: pagination.PageSize,
  406. Page: pagination.Page,
  407. },
  408. }, nil
  409. }
  410. // MatingCreate 牛只配种
  411. func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMating) (err error) {
  412. eventCheckModel, err := s.MatingCreateCheck(ctx, req)
  413. if err != nil {
  414. return xerr.WithStack(err)
  415. }
  416. frozenSemen := &model.FrozenSemen{}
  417. if err = s.DB.Where("bull_id = ?", req.FrozenSemenNumber).
  418. First(frozenSemen).Error; err != nil {
  419. return xerr.Custom("未找到冻精信息")
  420. }
  421. if frozenSemen.Quantity < req.FrozenSemenCount {
  422. return xerr.Custom("冻精数量不足")
  423. }
  424. // 更新复配的牛只
  425. matingReMatchIds := make([]int64, 0)
  426. // 新建配种信息的牛只
  427. newMatingList := make([]*model.EventMating, 0)
  428. // 更新配种信息牛只
  429. updateMatingList := make([]int64, 0)
  430. // 所有牛只
  431. cowIds := make([]int64, 0)
  432. // 需要更新配次的牛只
  433. matingTimes := make([]*MatingTimes, 0)
  434. // 需要更新空怀的牛只
  435. emptyCowIds := make([]int64, 0)
  436. for _, cow := range eventCheckModel.CowList {
  437. // 1. 第一次配种,创建配种信息(自然发情牛只,未经过同期的牛只)
  438. if cow.LastMatingAt <= 0 {
  439. newMatingList = append(newMatingList, model.NewEventMating2(cow, req, eventCheckModel.CurrentUser))
  440. continue
  441. }
  442. eventMatingHistory, err := s.GetEventMatingIsExIstByCowId(ctx, cow)
  443. if err != nil {
  444. return xerr.WithStack(err)
  445. }
  446. // 2. 同期更新配种信息 牛号&& 胎次 && 未配 && 配种结果未知 ==> 同期初配
  447. if eventMatingHistory.Status == pasturePb.IsShow_No &&
  448. eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown {
  449. updateMatingList = append(updateMatingList, eventMatingHistory.Id)
  450. continue
  451. }
  452. lastMatingAt := time.Unix(cow.LastMatingAt, 0)
  453. currentMatingAt := time.Unix(int64(req.MatingAt), 0)
  454. daysBetween := util.DaysBetween(currentMatingAt.Unix(), lastMatingAt.Unix())
  455. // 3. 如何两次配种时间为连续两天之内&&有过一次配种记录,则更新为复配状态 牛号&& 胎次 && 已配 && 配种结果未知 ==> 复配
  456. if (currentMatingAt.Format(model.LayoutDate2) == lastMatingAt.Format(model.LayoutDate2) || daysBetween == 1) &&
  457. eventMatingHistory.Status == pasturePb.IsShow_Ok &&
  458. eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown {
  459. matingReMatchIds = append(matingReMatchIds, eventMatingHistory.Id)
  460. } else {
  461. matingTimes = append(matingTimes, &MatingTimes{
  462. Mt: cow.MatingTimes + 1,
  463. CowId: cow.Id,
  464. EventMatingId: eventMatingHistory.Id,
  465. })
  466. }
  467. // 4. 提交的配种数据中,如何定位出空怀的牛只,
  468. if (eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown || eventMatingHistory.MatingResult == pasturePb.MatingResult_ReMatch) &&
  469. daysBetween >= 2 {
  470. emptyCowIds = append(emptyCowIds, eventMatingHistory.Id)
  471. newMatingList = append(newMatingList, model.NewEventMating2(cow, req, eventCheckModel.CurrentUser))
  472. }
  473. cowIds = append(cowIds, cow.Id)
  474. }
  475. if len(cowIds) != len(updateMatingList)+len(matingReMatchIds)+len(newMatingList) {
  476. zaplog.Error("MatingCreate",
  477. zap.Any("cowIds", cowIds),
  478. zap.Any("updateMatingList", updateMatingList),
  479. zap.Any("newMatingList", newMatingList),
  480. zap.Any("matingReMatchIds", matingReMatchIds),
  481. zap.Any("req", req),
  482. )
  483. return xerr.Custom("配种信息有误")
  484. }
  485. defer func() {
  486. if err != nil {
  487. // 记录事件日志
  488. for _, cowId := range cowIds {
  489. cow, _ := s.GetCowInfoByCowId(ctx, cowId)
  490. cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Mating, req.ExposeEstrusType, req)
  491. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  492. }
  493. }
  494. }()
  495. itemFrozenSemenLog := model.NewEventFrozenSemenLog(req)
  496. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  497. // 更新配种事件数据(初配)
  498. if len(updateMatingList) > 0 {
  499. if err = tx.Model(new(model.EventMating)).
  500. Where("id IN ?", updateMatingList).
  501. Where("status = ?", pasturePb.IsShow_No).
  502. Updates(
  503. model.EventMatingUpdateMap(int64(req.MatingAt), req.FrozenSemenNumber, eventCheckModel.OperationUser, eventCheckModel.CurrentUser),
  504. ).Error; err != nil {
  505. return xerr.WithStack(err)
  506. }
  507. }
  508. // 更新已配种的牛只为复配状态
  509. if len(matingReMatchIds) > 0 {
  510. if err = tx.Model(new(model.EventMating)).
  511. Where("id IN ?", matingReMatchIds).
  512. Where("mating_result = ?", pasturePb.MatingResult_Unknown).
  513. Where("status = ?", pasturePb.IsShow_Ok).
  514. Update("mating_result", pasturePb.MatingResult_ReMatch).
  515. Error; err != nil {
  516. return xerr.WithStack(err)
  517. }
  518. }
  519. // 更新上次已配种的牛只为空怀
  520. if len(emptyCowIds) > 0 {
  521. if err = tx.Model(new(model.EventMating)).
  522. Where("id IN ?", emptyCowIds).
  523. Update("mating_result", pasturePb.BreedStatus_Empty).
  524. Error; err != nil {
  525. return xerr.WithStack(err)
  526. }
  527. }
  528. // 创建配种事件数据
  529. if len(newMatingList) > 0 {
  530. if err = tx.Create(newMatingList).Error; err != nil {
  531. return xerr.WithStack(err)
  532. }
  533. }
  534. // 创建冻精使用记录日志
  535. if err = tx.Create(itemFrozenSemenLog).Error; err != nil {
  536. return xerr.WithStack(err)
  537. }
  538. // 如果有同期牛只,则修改为已结束状态
  539. if err = tx.Model(new(model.CowSameTime)).
  540. Where("cow_id IN ?", cowIds).
  541. UpdateColumn("same_time_status", pasturePb.SameTimeStatus_End).Error; err != nil {
  542. return xerr.WithStack(err)
  543. }
  544. // 更新牛只的繁殖状态为配种
  545. if err = tx.Model(new(model.Cow)).
  546. Where("id IN ?", cowIds).
  547. Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
  548. Updates(map[string]interface{}{
  549. "breed_status": pasturePb.BreedStatus_Breeding,
  550. "last_bull_number": req.FrozenSemenNumber,
  551. "last_mating_at": int64(req.MatingAt),
  552. }).Error; err != nil {
  553. return xerr.WithStack(err)
  554. }
  555. // 减去精液的数量
  556. if err = tx.Model(frozenSemen).
  557. Where("id = ?", frozenSemen.Id).
  558. Where("quantity > 0").
  559. UpdateColumn("quantity",
  560. gorm.Expr("quantity - ?", req.FrozenSemenCount),
  561. ).Error; err != nil {
  562. return xerr.WithStack(err)
  563. }
  564. // 更新配次
  565. if len(matingTimes) > 0 {
  566. for _, mt := range matingTimes {
  567. if err = tx.Model(new(model.EventMating)).
  568. Where("id = ?", mt.EventMatingId).
  569. Update("mating_times", mt.Mt).Error; err != nil {
  570. return xerr.WithStack(err)
  571. }
  572. if err = tx.Model(new(model.Cow)).
  573. Where("id = ?", mt.CowId).
  574. Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
  575. Where("breed_status = ?", pasturePb.BreedStatus_Breeding).
  576. Update("mating_times", mt.Mt).Error; err != nil {
  577. return xerr.WithStack(err)
  578. }
  579. }
  580. }
  581. return nil
  582. }); err != nil {
  583. return xerr.WithStack(err)
  584. }
  585. return nil
  586. }
  587. func (s *StoreEntry) WeaningBatch(ctx context.Context, req *pasturePb.EventWeaningBatchRequest) (err error) {
  588. if len(req.Item) <= 0 {
  589. return nil
  590. }
  591. cowIds := make([]int64, 0)
  592. cowWeightMap := make(map[int64]float64)
  593. for _, item := range req.Item {
  594. cowIds = append(cowIds, int64(item.CowId))
  595. cowWeightMap[int64(item.CowId)] = float64(item.Weight)
  596. }
  597. eventWeaningList := make([]*model.EventWeaning, 0)
  598. if err = s.DB.Model(new(model.EventWeaning)).
  599. Where("cow_id IN ?", cowIds).
  600. Where("status = ?", pasturePb.IsShow_No).
  601. Find(&eventWeaningList).Error; err != nil {
  602. return xerr.WithStack(err)
  603. }
  604. operation, err := s.GetSystemUserById(ctx, int64(req.OperationId))
  605. if err != nil {
  606. return xerr.WithStack(err)
  607. }
  608. currentUser, err := s.GetCurrentSystemUser(ctx)
  609. if err != nil {
  610. return xerr.WithStack(err)
  611. }
  612. defer func() {
  613. if err != nil {
  614. for _, cowId := range cowIds {
  615. cow, _ := s.GetCowInfoByCowId(ctx, cowId)
  616. cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Weaning, pasturePb.ExposeEstrusType_Invalid, req)
  617. s.DB.Table(cowLogs.TableName()).Create(cowLogs)
  618. }
  619. }
  620. }()
  621. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  622. cowInfo := &model.Cow{}
  623. for _, v := range eventWeaningList {
  624. v.EventUpdate(int64(req.WeaningAt), req.Remarks, req.PenId, operation, currentUser)
  625. if err = tx.Model(new(model.EventWeaning)).
  626. Select("status,reality_day,operation_id,operation_name,message_id,message_name,remarks,after_pen_id").
  627. Where("id = ?", v.Id).
  628. Updates(v).Error; err != nil {
  629. return xerr.WithStack(err)
  630. }
  631. cowInfo, err = s.GetCowInfoByCowId(ctx, v.CowId)
  632. if err != nil {
  633. return xerr.WithStack(err)
  634. }
  635. cowInfo.EventWeaningUpdate(int64(req.WeaningAt), req.PenId, int64(cowWeightMap[cowInfo.Id]*1000))
  636. if err = tx.Model(new(model.Cow)).
  637. Select("pen_id,current_weight,weaning_at,last_weight_at").
  638. Where("id = ?", v.CowId).
  639. Updates(cowInfo).Error; err != nil {
  640. return xerr.WithStack(err)
  641. }
  642. // 创建牛只的体重记录
  643. newEventWeight := model.NewEventWeight(
  644. cowInfo,
  645. currentUser,
  646. int32(cowWeightMap[v.CowId]*1000),
  647. 0,
  648. &pasturePb.EventWeight{
  649. WeightAt: req.WeaningAt,
  650. OperationId: req.OperationId,
  651. OperationName: req.OperationName,
  652. Remarks: req.Remarks,
  653. })
  654. if err = tx.Create(newEventWeight).Error; err != nil {
  655. return xerr.WithStack(err)
  656. }
  657. }
  658. return nil
  659. }); err != nil {
  660. return xerr.WithStack(err)
  661. }
  662. return nil
  663. }