event_breed.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. package backend
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "kpt-pasture/model"
  7. "net/http"
  8. "strings"
  9. "time"
  10. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  11. "go.uber.org/zap"
  12. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  13. "gitee.com/xuyiping_admin/pkg/xerr"
  14. "gorm.io/gorm"
  15. )
  16. func (s *StoreEntry) CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error) {
  17. lavingList := make([]*model.EventCalvingList, 0)
  18. var count int64 = 0
  19. pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())).
  20. Select(`a.*,b.name as pen_name,c.name as staff_member_name`).
  21. Joins(fmt.Sprintf("JOIN %s AS b on a.pen_id = b.id", new(model.Pen).TableName())).
  22. Joins(fmt.Sprintf("JOIN %s AS c on a.staff_member_id = c.id", new(model.SystemUser).TableName()))
  23. if len(req.CowId) > 0 {
  24. cowIds := strings.Split(req.CowId, ",")
  25. pref.Where("a.cow_id IN ?", cowIds)
  26. }
  27. if err := pref.Order("a.id desc").
  28. Count(&count).Limit(int(pagination.PageSize)).
  29. Offset(int(pagination.PageOffset)).
  30. Find(&lavingList).Error; err != nil {
  31. return nil, xerr.WithStack(err)
  32. }
  33. calvingIds := make([]int64, 0)
  34. for _, v := range lavingList {
  35. calvingIds = append(calvingIds, v.Id)
  36. }
  37. calvingCalfList := make([]*model.CalvingCalf, 0)
  38. if err := s.DB.Model(new(model.CalvingCalf)).
  39. Where("calving_id IN ?", calvingIds).
  40. Find(&calvingCalfList).Error; err != nil {
  41. return nil, xerr.WithStack(err)
  42. }
  43. return &pasturePb.SearchLavingEventResponse{
  44. Code: http.StatusOK,
  45. Message: "ok",
  46. Data: &pasturePb.SearchLavingData{
  47. List: model.EventCalvingListSlice(lavingList).ToPB(calvingCalfList),
  48. Total: int32(count),
  49. PageSize: pagination.PageSize,
  50. Page: pagination.Page,
  51. },
  52. }, nil
  53. }
  54. func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalving) error {
  55. if len(req.CowId) <= 0 {
  56. return xerr.Custom("请选择相关牛只")
  57. }
  58. cowList, err := s.ParseCowIds(ctx, req.CowId)
  59. if err != nil {
  60. return xerr.WithStack(err)
  61. }
  62. if len(cowList) <= 0 {
  63. return xerr.Custom("请选择相关牛只")
  64. }
  65. cow := cowList[0]
  66. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  67. // 母牛信息
  68. newCalving := model.NewEventCalving(cow, req)
  69. if err = tx.Create(newCalving).Error; err != nil {
  70. return xerr.WithStack(err)
  71. }
  72. // 犊牛信息
  73. newCalvingCalfList := model.NewEventCalvingCalf(cow.Id, newCalving.Id, req)
  74. for _, v := range newCalvingCalfList {
  75. if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No {
  76. continue
  77. }
  78. // 留养犊牛
  79. newCow := model.NewCalfCow(cow.Id, cow.LastBullId, v)
  80. if err = tx.Create(newCow).Error; err != nil {
  81. return xerr.WithStack(err)
  82. }
  83. v.CowId = newCow.Id
  84. }
  85. if err = tx.Create(newCalvingCalfList).Error; err != nil {
  86. return xerr.WithStack(err)
  87. }
  88. if err = tx.Model(new(model.Cow)).Where("id = ?", cow.Id).Updates(map[string]interface{}{
  89. "calving_age": 0,
  90. "lact": cow.Lact + 1,
  91. "breed_status": pasturePb.BreedStatus_Calving,
  92. "is_pregnant": pasturePb.IsShow_No,
  93. "calving_at": time.Now().Unix(),
  94. "last_calving_at": time.Now().Unix(),
  95. }).Error; err != nil {
  96. return xerr.WithStack(err)
  97. }
  98. return nil
  99. }); err != nil {
  100. return xerr.WithStack(err)
  101. }
  102. return nil
  103. }
  104. func (s *StoreEntry) PregnantCheckList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnantCheckEventResponse, error) {
  105. pregnantCheckList := make([]*model.EventPregnantCheck, 0)
  106. var count int64 = 0
  107. pref := s.DB.Table(new(model.EventPregnantCheck).TableName())
  108. if len(req.CowId) > 0 {
  109. cowIds := strings.Split(req.CowId, ",")
  110. pref.Where("cow_id IN ?", cowIds)
  111. }
  112. if err := pref.Order("id desc").
  113. Count(&count).Limit(int(pagination.PageSize)).
  114. Offset(int(pagination.PageOffset)).
  115. Find(&pregnantCheckList).Error; err != nil {
  116. return nil, xerr.WithStack(err)
  117. }
  118. systemUserList, _ := s.SystemUserList(ctx)
  119. pregnantCheckResult := s.PregnantCheckResultEnumList()
  120. pregnantCheckMethod := s.PregnantCheckMethodEnumList()
  121. return &pasturePb.PregnantCheckEventResponse{
  122. Code: http.StatusOK,
  123. Message: "ok",
  124. Data: &pasturePb.SearchPregnantCheckData{
  125. List: model.EventPregnantCheckSlice(pregnantCheckList).ToPB(systemUserList, pregnantCheckResult, pregnantCheckMethod),
  126. Total: int32(count),
  127. PageSize: pagination.PageSize,
  128. Page: pagination.Page,
  129. },
  130. }, nil
  131. }
  132. func (s *StoreEntry) PregnantCheckCreate(ctx context.Context, req *pasturePb.EventPregnantCheck) error {
  133. if len(req.CowId) <= 0 {
  134. return xerr.Custom("请选择相关牛只")
  135. }
  136. cowList, err := s.ParseCowIds(ctx, req.CowId)
  137. if err != nil {
  138. return xerr.WithStack(err)
  139. }
  140. eventPregnantCheckList := make([]*model.EventPregnantCheck, 0)
  141. currentUser, _ := s.GetCurrentSystemUser(ctx)
  142. // 更新怀孕牛只
  143. updatePregnantCowIds := make([]int64, 0)
  144. // 更新流产牛只
  145. updateAbortCowIds := make([]int64, 0)
  146. // 更新空怀牛只
  147. updateEmptyCowIds := make([]int64, 0)
  148. for _, cow := range cowList {
  149. // 过滤掉没有配种状态的牛只 todo 是否需要返回前端提示用户
  150. if cow.BreedStatus != pasturePb.BreedStatus_Breeding {
  151. continue
  152. }
  153. var count int64 = 0
  154. if err = s.DB.Model(new(model.EventPregnantCheck)).
  155. Where("lact = ?", cow.Lact).
  156. Where("cow_id = ?", cow.Id).
  157. Order("id desc").Limit(1).Count(&count).Error; err != nil {
  158. return xerr.WithStack(err)
  159. }
  160. pregnantCheckResult := req.PregnantCheckResult
  161. if req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant {
  162. if count > 0 {
  163. pregnantCheckResult = pasturePb.PregnantCheckResult_Recheck_Pregnant
  164. } else {
  165. pregnantCheckResult = pasturePb.PregnantCheckResult_InCheck_Pregnant
  166. }
  167. updatePregnantCowIds = append(updatePregnantCowIds, cow.Id)
  168. }
  169. if req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant {
  170. if count > 0 {
  171. pregnantCheckResult = pasturePb.PregnantCheckResult_Recheck_UnPregnant
  172. updateAbortCowIds = append(updateAbortCowIds, cow.Id)
  173. } else {
  174. pregnantCheckResult = pasturePb.PregnantCheckResult_InCheck_UnPregnant
  175. updateEmptyCowIds = append(updateEmptyCowIds, cow.Id)
  176. }
  177. }
  178. eventPregnantCheckList = append(eventPregnantCheckList, model.NewEventPregnantCheck(cow, currentUser, req, pregnantCheckResult))
  179. }
  180. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  181. if err = tx.Create(eventPregnantCheckList).Error; err != nil {
  182. return xerr.WithStack(err)
  183. }
  184. // 抽象公共方法来更新牛只状态
  185. err = s.updateCowStatus(tx, updatePregnantCowIds, pasturePb.BreedStatus_Pregnant, pasturePb.MatingResult_Pregnant)
  186. if err != nil {
  187. return err
  188. }
  189. err = s.updateCowStatus(tx, updateAbortCowIds, pasturePb.BreedStatus_Abort, pasturePb.MatingResult_Abort)
  190. if err != nil {
  191. return err
  192. }
  193. err = s.updateCowStatus(tx, updateEmptyCowIds, pasturePb.BreedStatus_Empty, pasturePb.MatingResult_Empty)
  194. if err != nil {
  195. return err
  196. }
  197. return nil
  198. }); err != nil {
  199. return xerr.WithStack(err)
  200. }
  201. return nil
  202. }
  203. // 抽象公共方法来更新牛只状态
  204. func (s *StoreEntry) updateCowStatus(tx *gorm.DB, cowIds []int64, breedStatus pasturePb.BreedStatus_Kind, matingResult pasturePb.MatingResult_Kind) error {
  205. if len(cowIds) > 0 {
  206. if err := tx.Model(&model.Cow{}).Where("cow_id IN ?", cowIds).
  207. Updates(map[string]interface{}{"breed_status": breedStatus}).Error; err != nil {
  208. return xerr.WithStack(err)
  209. }
  210. if err := tx.Model(&model.EventMating{}).Where("cow_id IN ?", cowIds).
  211. Group("cow_id").Select("MAX(id) as id").
  212. Updates(map[string]interface{}{"mating_result": matingResult}).Error; err != nil {
  213. return xerr.WithStack(err)
  214. }
  215. }
  216. return nil
  217. }
  218. func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) {
  219. matingList := make([]*model.EventMating, 0)
  220. var count int64 = 0
  221. pref := s.DB.Table(new(model.EventMating).TableName())
  222. if len(req.CowId) > 0 {
  223. cowIds := strings.Split(req.CowId, ",")
  224. pref.Where("cow_id IN ?", cowIds)
  225. }
  226. if err := pref.Order("id desc").
  227. Count(&count).Limit(int(pagination.PageSize)).
  228. Offset(int(pagination.PageOffset)).
  229. Find(&matingList).Error; err != nil {
  230. return nil, xerr.WithStack(err)
  231. }
  232. systemUserList, _ := s.SystemUserList(ctx)
  233. exposeEstrusTypeMap := s.ExposeEstrusTypeMap()
  234. return &pasturePb.MatingEventResponse{
  235. Code: http.StatusOK,
  236. Message: "ok",
  237. Data: &pasturePb.SearchMatingData{
  238. List: model.EventMatingSlice(matingList).ToPB(systemUserList, exposeEstrusTypeMap),
  239. Total: int32(count),
  240. PageSize: pagination.PageSize,
  241. Page: pagination.Page,
  242. },
  243. }, nil
  244. }
  245. func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMating) error {
  246. if len(req.CowId) <= 0 {
  247. return xerr.Custom("请选择相关牛只")
  248. }
  249. cowList, err := s.ParseCowIds(ctx, req.CowId)
  250. if err != nil {
  251. return xerr.WithStack(err)
  252. }
  253. eventFrozenSemenLogList := make([]*model.FrozenSemenLog, 0)
  254. currentUser, _ := s.GetCurrentSystemUser(ctx)
  255. frozenSemen := &model.FrozenSemen{}
  256. if err = s.DB.Where("bull_id = ?", req.BullId).First(frozenSemen).Error; err != nil {
  257. return xerr.WithStack(err)
  258. }
  259. sameTimeCowIds := make([]int64, 0)
  260. matingInsertList := make([]*model.EventMating, 0)
  261. matingUpdateIds := make([]int64, 0)
  262. cowIds := make([]int64, 0)
  263. nowTime := time.Now()
  264. for _, cow := range cowList {
  265. var count int64 = 0
  266. itemEventMating := &model.EventMating{}
  267. if err = s.DB.Where("lact = ?", cow.Lact).
  268. Where("cow_id = ?", cow.Id).
  269. Order("id desc").
  270. First(itemEventMating).Count(&count).Error; err != nil {
  271. return xerr.WithStack(err)
  272. }
  273. // 判断当前输精时间距离上次输精时间是否超过2天,如果超过则更新为复配状态
  274. itemBeforeTwoDays := nowTime.Sub(time.Unix(itemEventMating.MatingAt, 0)).Hours()
  275. if count > 0 && itemBeforeTwoDays > 48 {
  276. matingUpdateIds = append(matingUpdateIds, itemEventMating.Id)
  277. } else {
  278. matingInsertList = append(matingInsertList, model.NewEventMating(cow, currentUser, req))
  279. }
  280. eventFrozenSemenLogList = append(
  281. eventFrozenSemenLogList,
  282. model.NewEventFrozenSemenLog(req.BullId, cow, int64(req.StaffMemberId)),
  283. )
  284. sameTimeCow := &model.SameTimeCow{}
  285. if err = s.DB.Where("lact = ?", cow.Lact).
  286. Where("cow_id = ?", cow.Id).
  287. Where("status = ?", pasturePb.SameTimeStatus_In_Progress).
  288. First(sameTimeCow).Error; err != nil {
  289. if !errors.Is(err, gorm.ErrRecordNotFound) {
  290. return xerr.WithStack(err)
  291. }
  292. }
  293. if sameTimeCow.Id > 0 {
  294. sameTimeCowIds = append(sameTimeCowIds, sameTimeCow.Id)
  295. }
  296. cowIds = append(cowIds, cow.Id)
  297. }
  298. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  299. // 创建配种事件数据
  300. if len(matingInsertList) > 0 {
  301. if err = tx.Create(matingInsertList).Error; err != nil {
  302. return xerr.WithStack(err)
  303. }
  304. }
  305. // 更新已配种的牛只为复配状态
  306. if len(matingUpdateIds) > 0 {
  307. if err = tx.Model(new(model.EventMating)).
  308. Where("id IN ?", matingUpdateIds).
  309. Where("mating_result = ?", pasturePb.MatingResult_Unknown).
  310. Update("mating_result", pasturePb.MatingResult_ReMatch).
  311. Error; err != nil {
  312. return xerr.WithStack(err)
  313. }
  314. }
  315. // 创建冻精使用记录日志
  316. if err = tx.Create(eventFrozenSemenLogList).Error; err != nil {
  317. return xerr.WithStack(err)
  318. }
  319. // 如果有同期牛只,则修改为已结束状态
  320. if len(sameTimeCowIds) > 0 {
  321. if err = tx.Table(new(model.SameTimeCow).TableName()).
  322. Where("id IN ?", sameTimeCowIds).
  323. UpdateColumn("status", pasturePb.SameTimeStatus_End).Error; err != nil {
  324. }
  325. }
  326. // 减去精液的数量
  327. if err = tx.Table(new(model.FrozenSemen).TableName()).
  328. Where("bull_id = ?", req.BullId).
  329. Where("quantity > 0").
  330. UpdateColumn("quantity",
  331. gorm.Expr("quantity - ?", len(matingUpdateIds)+len(matingInsertList)),
  332. ).Error; err != nil {
  333. return xerr.WithStack(err)
  334. }
  335. if err = tx.Table(new(model.Cow).TableName()).
  336. Where("id IN ?", cowIds).
  337. UpdateColumn("breed_status", pasturePb.BreedStatus_Breeding).Error; err != nil {
  338. return xerr.WithStack(err)
  339. }
  340. return nil
  341. }); err != nil {
  342. return xerr.WithStack(err)
  343. }
  344. return nil
  345. }
  346. func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusEventResponse, error) {
  347. estrusList := make([]*model.EventEstrus, 0)
  348. var count int64 = 0
  349. pref := s.DB.Table(new(model.EventEstrus).TableName())
  350. if len(req.CowId) > 0 {
  351. cowIds := strings.Split(req.CowId, ",")
  352. pref.Where("cow_id IN ?", cowIds)
  353. }
  354. if err := pref.Order("id desc").
  355. Count(&count).Limit(int(pagination.PageSize)).
  356. Offset(int(pagination.PageOffset)).
  357. Find(&estrusList).Error; err != nil {
  358. return nil, xerr.WithStack(err)
  359. }
  360. systemUserList, _ := s.SystemUserList(ctx)
  361. return &pasturePb.EstrusEventResponse{
  362. Code: http.StatusOK,
  363. Message: "ok",
  364. Data: &pasturePb.SearchEstrusData{
  365. List: model.EstrusSlice(estrusList).ToPB(systemUserList),
  366. Total: int32(count),
  367. PageSize: pagination.PageSize,
  368. Page: pagination.Page,
  369. },
  370. }, nil
  371. }
  372. func (s *StoreEntry) EstrusCreate(ctx context.Context, req *pasturePb.EventEstrus) error {
  373. if len(req.CowId) <= 0 {
  374. return xerr.Custom("请选择相关牛只")
  375. }
  376. cowList, err := s.ParseCowIds(ctx, req.CowId)
  377. if err != nil {
  378. return xerr.WithStack(err)
  379. }
  380. estrusList := make([]*model.EventEstrus, 0)
  381. currentUser, _ := s.GetCurrentSystemUser(ctx)
  382. for _, cow := range cowList {
  383. estrusList = append(estrusList, model.NewEventEstrus(cow, currentUser, req))
  384. }
  385. if err := s.DB.Create(estrusList).Error; err != nil {
  386. return xerr.WithStack(err)
  387. }
  388. return nil
  389. }
  390. func (s *StoreEntry) FrozenSemenList(ctx context.Context, req *pasturePb.FrozenSemenRequest, pagination *pasturePb.PaginationModel) (*pasturePb.FrozenSemenResponse, error) {
  391. frozenSemenList := make([]*model.FrozenSemen, 0)
  392. var count int64 = 0
  393. pref := s.DB.Table(new(model.FrozenSemen).TableName())
  394. if req.BullId != "" {
  395. pref.Where("bull_id = ?", req.BullId)
  396. }
  397. if req.Producer != "" {
  398. pref.Where("producer = ?", req.Producer)
  399. }
  400. if err := pref.Order("id desc").
  401. Count(&count).Limit(int(pagination.PageSize)).
  402. Offset(int(pagination.PageOffset)).
  403. Find(&frozenSemenList).Error; err != nil {
  404. return nil, xerr.WithStack(err)
  405. }
  406. frozenSemenTypeMap := s.FrozenSemenTypeMap()
  407. unitMap := s.UnitMap()
  408. return &pasturePb.FrozenSemenResponse{
  409. Code: http.StatusOK,
  410. Message: "ok",
  411. Data: &pasturePb.SearchFrozenSemenData{
  412. List: model.FrozenSemenSlice(frozenSemenList).ToPB(frozenSemenTypeMap, unitMap),
  413. Total: int32(count),
  414. PageSize: pagination.PageSize,
  415. Page: pagination.Page,
  416. },
  417. }, nil
  418. }
  419. func (s *StoreEntry) FrozenSemenCreate(ctx context.Context, req *pasturePb.SearchFrozenSemenList) error {
  420. currentUser, _ := s.GetCurrentSystemUser(ctx)
  421. req.CowKindName = s.CowKindMap()[req.CowKind]
  422. newFrozenSemen := model.NewFrozenSemen(req, currentUser)
  423. if err := s.DB.Create(newFrozenSemen).Error; err != nil {
  424. return xerr.WithStack(err)
  425. }
  426. return nil
  427. }
  428. func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) error {
  429. sameTime, err := s.GetSameTimeById(ctx, int64(req.SameTimeId))
  430. if err != nil {
  431. return xerr.WithStack(err)
  432. }
  433. zaplog.Info("SameTimeCreate", zap.Any("sameTime", sameTime), zap.Any("req", req))
  434. cowList, err := s.ParseCowIds(ctx, req.CowId)
  435. if err != nil {
  436. return xerr.WithStack(err)
  437. }
  438. drugs := &model.Drugs{}
  439. if req.DrugsId > 0 {
  440. drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId))
  441. if err != nil {
  442. zaplog.Error("SameTimeCreate", zap.Any("GetDrugsById", err), zap.Any("req", req))
  443. }
  444. }
  445. if err = s.DB.Transaction(func(tx *gorm.DB) error {
  446. eventSameTimeList := make([]*model.EventSameTime, 0)
  447. for _, cow := range cowList {
  448. eventSameTimeList = append(eventSameTimeList, model.NewEventSameTime(cow, req, drugs))
  449. // sameTimeCow 不存在时创建
  450. if err = tx.Where("same_time_id = ? ", sameTime.Id).
  451. Where("cow_id = ?", cow.Id).
  452. Where("lact = ?", cow.Lact).
  453. First(new(model.SameTimeCow)).Error; err != nil {
  454. if errors.Is(err, gorm.ErrRecordNotFound) {
  455. if err = tx.Create(model.NewSameTimeCow(cow.Id, sameTime.Id)).Error; err != nil {
  456. return xerr.WithStack(err)
  457. }
  458. }
  459. }
  460. }
  461. if err = tx.Create(eventSameTimeList).Error; err != nil {
  462. return xerr.WithStack(err)
  463. }
  464. return nil
  465. }); err != nil {
  466. return xerr.WithStack(err)
  467. }
  468. return nil
  469. }