package backend import ( "context" "fmt" "kpt-pasture/model" "kpt-pasture/util" "net/http" "strconv" "strings" "time" "gitee.com/xuyiping_admin/pkg/logger/zaplog" "go.uber.org/zap" pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow" "gitee.com/xuyiping_admin/pkg/xerr" "gorm.io/gorm" ) func (s *StoreEntry) CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error) { lavingList := make([]*model.EventCalvingList, 0) var count int64 = 0 pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())). Select(`a.*,b.name as pen_name,c.name as staff_member_name`). Joins(fmt.Sprintf("JOIN %s AS b on a.pen_id = b.id", new(model.Pen).TableName())). Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName())) if len(req.CowId) > 0 { cowIds := strings.Split(req.CowId, ",") pref.Where("a.cow_id IN ?", cowIds) } if err := pref.Order("a.id desc"). Count(&count).Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&lavingList).Error; err != nil { return nil, xerr.WithStack(err) } calvingIds := make([]int64, 0) for _, v := range lavingList { calvingIds = append(calvingIds, v.Id) } calvingCalfList := make([]*model.CalvingCalf, 0) if err := s.DB.Model(new(model.CalvingCalf)). Where("calving_id IN ?", calvingIds). Find(&calvingCalfList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.SearchLavingEventResponse{ Code: http.StatusOK, Message: "ok", Data: &pasturePb.SearchLavingData{ List: model.EventCalvingListSlice(lavingList).ToPB(calvingCalfList), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalving) (err error) { cow, err := s.GetCowInfoByCowId(ctx, int64(req.CowId)) if err != nil { zaplog.Error("CalvingCreate", zap.Any("cow_id", req.CowId), zap.Any("err", err)) return xerr.Custom("请选择相关牛只") } operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.Customf("获取操作人员信息失败: %s", err.Error()) } req.OperationName = operationUser.Name // 记录牛只事件日志 defer func() { if err == nil { // 母牛事件日志 cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Calving, pasturePb.ExposeEstrusType_Invalid, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) // 犊牛事件日志 for _, v := range req.CalfItemList { if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No { continue } cow, _ = s.GetCowInfoByCowId(ctx, int64(v.CowId)) cowLogs = s.SubmitEventLog(ctx, cow, pasturePb.EventType_Birth, pasturePb.ExposeEstrusType_Invalid, v) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() newEventCalving := &model.EventCalving{} if err = s.DB.Model(new(model.EventCalving)). Where("cow_id = ?", cow.Id). Where("lact = ?", cow.Lact). First(newEventCalving).Error; err != nil { return xerr.Custom("该母牛信息不存在") } if err = s.DB.Transaction(func(tx *gorm.DB) error { // 更新产犊事件表 newEventCalving.Update(operationUser, req, cow) if err = tx.Model(new(model.EventCalving)). Where("id = ?", newEventCalving.Id). Updates(newEventCalving).Error; err != nil { return xerr.WithStack(err) } for _, v := range req.CalfItemList { if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No { continue } // 犊牛信息 newCalvingCalf := model.NewEventCalvingCalf(int64(req.CowId), newEventCalving.Id, int64(req.CalvingAt), v) // 留养犊牛 newCow := model.NewCalfCow(cow.Id, cow.LastBullNumber, newCalvingCalf) if err = tx.Create(newCow).Error; err != nil { return xerr.WithStack(err) } v.CowId = int32(newCow.Id) if err = tx.Create(newCalvingCalf).Error; err != nil { return xerr.WithStack(err) } } // 更新母牛信息 cow.EventCalvingUpdate(int64(req.CalvingAt)) if err = tx.Model(cow). Select("calving_age,mating_times,pregnancy_age,lact,breed_status,is_pregnant,last_calving_at"). Where("id = ?", cow.Id). Updates(cow).Error; err != nil { return xerr.WithStack(err) } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusItemsResponse, error) { estrusList := make([]*model.EventEstrus, 0) var count int64 = 0 pref := s.DB.Table(new(model.EventEstrus).TableName()). Where("is_show = ?", pasturePb.IsShow_Ok) if len(req.CowIds) > 0 { cowIds := strings.Split(util.ArrayInt32ToStrings(req.CowIds, ","), ",") pref.Where("cow_id IN ?", cowIds) } if req.Level > 0 { pref.Where("level = ?", req.Level) } if len(req.PenIds) > 0 { penIds := strings.Split(util.ArrayInt32ToStrings(req.PenIds, ","), ",") pref.Where("pen_id IN ?", penIds) } if err := pref.Order("id desc"). Count(&count).Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&estrusList).Error; err != nil { return nil, xerr.WithStack(err) } getCowInfoByCowId := GetCowInfoByCowId getCowLastEvent := GetCowLastEvent return &pasturePb.EstrusItemsResponse{ Code: http.StatusOK, Message: "ok", Data: &pasturePb.EstrusItemsData{ List: model.EstrusSlice(estrusList).ToPB(s.DB, getCowInfoByCowId, getCowLastEvent), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) EstrusBatch(ctx context.Context, req *pasturePb.EventEstrus) (err error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误") } operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.Customf("该用户不存在: %d", req.OperationId) } req.OperationName = operationUser.Name eventEstrusIds := make([]string, 0) eventMatingList := make([]*model.EventMating, 0) for _, cowId := range req.CowIds { cowInfo := GetCowInfoByCowId(s.DB, int64(cowId)) if cowInfo == nil { return xerr.Custom("牛只信息不存在") } newEventMating := model.NewEventMating(cowInfo, time.Now().Unix(), pasturePb.ExposeEstrusType_Neck_Ring) eventEstrus, ok := s.EventEstrusIsExist(ctx, int64(cowId)) if ok { newEventMating.EventEstrusId = eventEstrus.Id newEventMating.MatingTimes = cowInfo.MatingTimes + 1 newEventMating.Status = pasturePb.IsShow_Ok newEventMating.RealityDay = int64(req.MatingAt) newEventMating.OperationId = operationUser.Id newEventMating.OperationName = operationUser.Name newEventMating.FrozenSemenNumber = req.BullNumber newEventMating.Remarks = req.Remarks newEventMating.MessageId = currentUser.Id newEventMating.MessageName = currentUser.Name eventEstrusIds = append(eventEstrusIds, strconv.FormatInt(eventEstrus.Id, 10)) } eventMatingList = append(eventMatingList, newEventMating) } if len(eventMatingList) <= 0 { return nil } defer func() { // 记录牛只事件日志 if err == nil { for _, v := range eventMatingList { cow, _ := s.GetCowInfoByCowId(ctx, v.CowId) cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Mating, pasturePb.ExposeEstrusType_Neck_Ring, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() if err = s.DB.Transaction(func(tx *gorm.DB) error { if len(eventEstrusIds) > 0 { if err = tx.Model(new(model.EventEstrus)). Where("id IN ?", eventEstrusIds). Updates(map[string]interface{}{ "is_show": pasturePb.IsShow_No, "result": pasturePb.EstrusResult_Correct, }).Error; err != nil { return xerr.WithStack(err) } } if len(eventMatingList) > 0 { if err = tx.Create(eventMatingList).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) (err error) { eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, int64(req.CowId)) if err != nil { zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req)) return xerr.Customf("异常数据") } drugs := &model.Drugs{} if drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId)); err != nil { zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req)) return xerr.Customf("该药品不存在: %d", req.DrugsId) } req.DrugsName = drugs.Name operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.WithStack(err) } currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误") } eventCowSameTime.Update(drugs, req.Usage, req.Remarks, operationUser, currentUser) defer func() { if err == nil { // 记录牛只事件日志 cow, _ := s.GetCowInfoByCowId(ctx, eventCowSameTime.CowId) cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Seme_Time, pasturePb.ExposeEstrusType_Same_Time, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) if err = s.DB.Model(new(model.CowSameTime)). Where("cow_id = ?", eventCowSameTime.CowId). Where("same_time_id = ?", eventCowSameTime.Id). Where("same_time_status = ?", pasturePb.SameTimeStatus_No_Start). Update("same_time_status", pasturePb.SameTimeStatus_In_Progress).Error; err != nil { zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req)) } } }() if err = s.DB.Model(new(model.EventCowSameTime)). Select("status,drugs_id,unit,usage,remarks,operation_id,operation_name"). Where("id = ?", eventCowSameTime.Id). Updates(eventCowSameTime).Error; err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) SameTimeBatch(ctx context.Context, req *pasturePb.EventSameTimeBatch) (err error) { operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.Customf("异常数据") } req.OperationName = operationUser.Name currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Customf("异常数据") } drugs := &model.Drugs{} if drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId)); err != nil { zaplog.Error("SameTimeBatch", zap.Any("err", err), zap.Any("req", req)) return xerr.Customf("该药物不存在: %d", req.DrugsId) } req.DrugsName = drugs.Name eventCowSameTimeList := make([]*model.EventCowSameTime, 0) for _, v := range req.CowIds { eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, int64(v)) if err != nil { zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req)) return xerr.WithStack(err) } eventCowSameTimeList = append(eventCowSameTimeList, eventCowSameTime) } defer func() { // 记录牛只事件日志 if err == nil { for _, v := range eventCowSameTimeList { cow, _ := s.GetCowInfoByCowId(ctx, v.CowId) cowLogs := s.SubmitEventLog( ctx, cow, pasturePb.EventType_Seme_Time, pasturePb.ExposeEstrusType_Same_Time, &pasturePb.EventSameTime{ Id: int32(v.Id), CowId: int32(v.CowId), SameTimeId: int32(v.SameTimeId), SameTimeType: v.SameTimeType, SameTimeTypeName: v.SameTimeName, DrugsId: int32(v.DrugsId), DrugsName: drugs.Name, Usage: req.Usage, OperationId: int32(operationUser.Id), OperationName: operationUser.Name, SameTimeAt: req.SameTimeAt, }) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() if err = s.DB.Transaction(func(tx *gorm.DB) error { for _, v := range eventCowSameTimeList { if err = tx.Model(new(model.CowSameTime)). Where("cow_id = ?", v.CowId). Where("same_time_id = ?", v.Id). Where("same_time_status = ?", pasturePb.SameTimeStatus_No_Start). Update("same_time_status", pasturePb.SameTimeStatus_In_Progress).Error; err != nil { zaplog.Error("SameTimeCreate", zap.Any("err", err), zap.Any("req", req)) } // 更新SameTime v.Update(drugs, req.Usage, req.Remarks, currentUser, operationUser) if err = tx.Model(new(model.EventCowSameTime)). Select("status,drugs_id,unit,usage,remarks,operation_id,operation_name"). Where("id = ?", v.Id). Updates(v).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) SameTimeList( ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel, ) (*pasturePb.SearchSameTimeResponse, error) { cowSameTimeList := make([]*model.EventCowSameTime, 0) var count int64 = 0 pref := s.DB.Table(new(model.EventCowSameTime).TableName()) if req.CowId != "" { cowIds := strings.Split(req.CowId, ",") pref.Where("cow_id IN ?", cowIds) } if err := pref.Count(&count). Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&cowSameTimeList).Error; err != nil { return nil, xerr.WithStack(err) } sameTimeTypeMap := s.SameTimeTypeMap() return &pasturePb.SearchSameTimeResponse{ Code: http.StatusOK, Message: "ok", Data: &pasturePb.SameTimeData{ List: model.EventCowSameTimeSlice(cowSameTimeList).ToPB(sameTimeTypeMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) { matingList := make([]*model.EventMating, 0) var count int64 = 0 pref := s.DB.Model(new(model.EventMating)). Where("mating_result > ?", pasturePb.MatingResult_Invalid). Where("status = ?", pasturePb.IsShow_No) if len(req.CowId) > 0 { cowIds := strings.Split(req.CowId, ",") pref.Where("cow_id IN ?", cowIds) } if err := pref.Order("id desc"). Count(&count).Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&matingList).Error; err != nil { return nil, xerr.WithStack(err) } exposeEstrusTypeMap := s.ExposeEstrusTypeMap() return &pasturePb.MatingEventResponse{ Code: http.StatusOK, Message: "ok", Data: &pasturePb.SearchMatingData{ List: model.EventMatingSlice(matingList).ToPB(exposeEstrusTypeMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } // MatingCreate 牛只配种 func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMating) (err error) { eventCheckModel, err := s.MatingCreateCheck(ctx, req) if err != nil { return xerr.WithStack(err) } frozenSemen := &model.FrozenSemen{} if err = s.DB.Where("bull_id = ?", req.FrozenSemenNumber). First(frozenSemen).Error; err != nil { return xerr.Custom("未找到冻精信息") } if frozenSemen.Quantity < req.FrozenSemenCount { return xerr.Custom("冻精数量不足") } // 更新复配的牛只 matingReMatchIds := make([]int64, 0) // 新建配种信息的牛只 newMatingList := make([]*model.EventMating, 0) // 更新配种信息牛只 updateMatingList := make([]int64, 0) // 所有牛只 cowIds := make([]int64, 0) // 需要更新配次的牛只 matingTimes := make([]*MatingTimes, 0) // 需要更新空怀的牛只 emptyCowIds := make([]int64, 0) for _, cow := range eventCheckModel.CowList { // 1. 第一次配种,创建配种信息(自然发情牛只,未经过同期的牛只) if cow.LastMatingAt <= 0 { newMatingList = append(newMatingList, model.NewEventMating2(cow, req, eventCheckModel.CurrentUser)) continue } eventMatingHistory, err := s.GetEventMatingIsExIstByCowId(ctx, cow) if err != nil { return xerr.WithStack(err) } // 2. 同期更新配种信息 牛号&& 胎次 && 未配 && 配种结果未知 ==> 同期初配 if eventMatingHistory.Status == pasturePb.IsShow_No && eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown { updateMatingList = append(updateMatingList, eventMatingHistory.Id) continue } lastMatingAt := time.Unix(cow.LastMatingAt, 0) currentMatingAt := time.Unix(int64(req.MatingAt), 0) daysBetween := util.DaysBetween(currentMatingAt.Unix(), lastMatingAt.Unix()) // 3. 如何两次配种时间为连续两天之内&&有过一次配种记录,则更新为复配状态 牛号&& 胎次 && 已配 && 配种结果未知 ==> 复配 if (currentMatingAt.Format(model.LayoutDate2) == lastMatingAt.Format(model.LayoutDate2) || daysBetween == 1) && eventMatingHistory.Status == pasturePb.IsShow_Ok && eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown { matingReMatchIds = append(matingReMatchIds, eventMatingHistory.Id) } else { matingTimes = append(matingTimes, &MatingTimes{ Mt: cow.MatingTimes + 1, CowId: cow.Id, EventMatingId: eventMatingHistory.Id, }) } // 4. 提交的配种数据中,如何定位出空怀的牛只, if (eventMatingHistory.MatingResult == pasturePb.MatingResult_Unknown || eventMatingHistory.MatingResult == pasturePb.MatingResult_ReMatch) && daysBetween >= 2 { emptyCowIds = append(emptyCowIds, eventMatingHistory.Id) newMatingList = append(newMatingList, model.NewEventMating2(cow, req, eventCheckModel.CurrentUser)) } cowIds = append(cowIds, cow.Id) } if len(cowIds) != len(updateMatingList)+len(matingReMatchIds)+len(newMatingList) { zaplog.Error("MatingCreate", zap.Any("cowIds", cowIds), zap.Any("updateMatingList", updateMatingList), zap.Any("newMatingList", newMatingList), zap.Any("matingReMatchIds", matingReMatchIds), zap.Any("req", req), ) return xerr.Custom("配种信息有误") } defer func() { if err != nil { // 记录事件日志 for _, cowId := range cowIds { cow, _ := s.GetCowInfoByCowId(ctx, cowId) cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Mating, req.ExposeEstrusType, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() itemFrozenSemenLog := model.NewEventFrozenSemenLog(req) if err = s.DB.Transaction(func(tx *gorm.DB) error { // 更新配种事件数据(初配) if len(updateMatingList) > 0 { if err = tx.Model(new(model.EventMating)). Where("id IN ?", updateMatingList). Where("status = ?", pasturePb.IsShow_No). Updates( model.EventMatingUpdateMap(int64(req.MatingAt), req.FrozenSemenNumber, eventCheckModel.OperationUser, eventCheckModel.CurrentUser), ).Error; err != nil { return xerr.WithStack(err) } } // 更新已配种的牛只为复配状态 if len(matingReMatchIds) > 0 { if err = tx.Model(new(model.EventMating)). Where("id IN ?", matingReMatchIds). Where("mating_result = ?", pasturePb.MatingResult_Unknown). Where("status = ?", pasturePb.IsShow_Ok). Update("mating_result", pasturePb.MatingResult_ReMatch). Error; err != nil { return xerr.WithStack(err) } } // 更新上次已配种的牛只为空怀 if len(emptyCowIds) > 0 { if err = tx.Model(new(model.EventMating)). Where("id IN ?", emptyCowIds). Update("mating_result", pasturePb.BreedStatus_Empty). Error; err != nil { return xerr.WithStack(err) } } // 创建配种事件数据 if len(newMatingList) > 0 { if err = tx.Create(newMatingList).Error; err != nil { return xerr.WithStack(err) } } // 创建冻精使用记录日志 if err = tx.Create(itemFrozenSemenLog).Error; err != nil { return xerr.WithStack(err) } // 如果有同期牛只,则修改为已结束状态 if err = tx.Model(new(model.CowSameTime)). Where("cow_id IN ?", cowIds). UpdateColumn("same_time_status", pasturePb.SameTimeStatus_End).Error; err != nil { return xerr.WithStack(err) } // 更新牛只的繁殖状态为配种 if err = tx.Model(new(model.Cow)). Where("id IN ?", cowIds). Where("admission_status = ?", pasturePb.AdmissionStatus_Admission). Updates(map[string]interface{}{ "breed_status": pasturePb.BreedStatus_Breeding, "last_bull_number": req.FrozenSemenNumber, "last_mating_at": int64(req.MatingAt), }).Error; err != nil { return xerr.WithStack(err) } // 减去精液的数量 if err = tx.Model(frozenSemen). Where("id = ?", frozenSemen.Id). Where("quantity > 0"). UpdateColumn("quantity", gorm.Expr("quantity - ?", req.FrozenSemenCount), ).Error; err != nil { return xerr.WithStack(err) } // 更新配次 if len(matingTimes) > 0 { for _, mt := range matingTimes { if err = tx.Model(new(model.EventMating)). Where("id = ?", mt.EventMatingId). Update("mating_times", mt.Mt).Error; err != nil { return xerr.WithStack(err) } if err = tx.Model(new(model.Cow)). Where("id = ?", mt.CowId). Where("admission_status = ?", pasturePb.AdmissionStatus_Admission). Where("breed_status = ?", pasturePb.BreedStatus_Breeding). Update("mating_times", mt.Mt).Error; err != nil { return xerr.WithStack(err) } } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) WeaningBatch(ctx context.Context, req *pasturePb.EventWeaningBatchRequest) (err error) { if len(req.Item) <= 0 { return nil } cowIds := make([]int64, 0) cowWeightMap := make(map[int64]float64) for _, item := range req.Item { cowIds = append(cowIds, int64(item.CowId)) cowWeightMap[int64(item.CowId)] = float64(item.Weight) } eventWeaningList := make([]*model.EventWeaning, 0) if err = s.DB.Model(new(model.EventWeaning)). Where("cow_id IN ?", cowIds). Where("status = ?", pasturePb.IsShow_No). Find(&eventWeaningList).Error; err != nil { return xerr.WithStack(err) } operation, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.WithStack(err) } currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.WithStack(err) } defer func() { if err != nil { for _, cowId := range cowIds { cow, _ := s.GetCowInfoByCowId(ctx, cowId) cowLogs := s.SubmitEventLog(ctx, cow, pasturePb.EventType_Weaning, pasturePb.ExposeEstrusType_Invalid, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() if err = s.DB.Transaction(func(tx *gorm.DB) error { cowInfo := &model.Cow{} for _, v := range eventWeaningList { v.EventUpdate(int64(req.WeaningAt), req.Remarks, req.PenId, operation, currentUser) if err = tx.Model(new(model.EventWeaning)). Select("status,reality_day,operation_id,operation_name,message_id,message_name,remarks,after_pen_id"). Where("id = ?", v.Id). Updates(v).Error; err != nil { return xerr.WithStack(err) } cowInfo, err = s.GetCowInfoByCowId(ctx, v.CowId) if err != nil { return xerr.WithStack(err) } cowInfo.EventWeaningUpdate(int64(req.WeaningAt), req.PenId, int64(cowWeightMap[cowInfo.Id]*1000)) if err = tx.Model(new(model.Cow)). Select("pen_id,current_weight,weaning_at,last_weight_at"). Where("id = ?", v.CowId). Updates(cowInfo).Error; err != nil { return xerr.WithStack(err) } // 创建牛只的体重记录 newEventWeight := model.NewEventWeight( cowInfo, currentUser, int32(cowWeightMap[v.CowId]*1000), 0, &pasturePb.EventWeight{ WeightAt: req.WeaningAt, OperationId: req.OperationId, OperationName: req.OperationName, Remarks: req.Remarks, }) if err = tx.Create(newEventWeight).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil }