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) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return nil, xerr.Custom("用户信息错误,请退出重新登录") } 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())). Where("pasture_id = ?", currentUser.PastureId) 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) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("用户信息错误,请退出重新登录") } cow, err := s.GetCowInfoByCowId(ctx, currentUser.PastureId, 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, currentUser.PastureId, 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, currentUser, 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, currentUser.PastureId, int64(v.CowId)) cowLogs = s.SubmitEventLog(ctx, currentUser, 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.EventUpdate(operationUser, req, cow) if err = tx.Model(new(model.EventCalving)). Select("operation_id", "operation_name", "reality_day", "day_age", "pregnancy_age", "bull_number", "calving_level", "child_number", "status", "is_inducing_childbirth", "pen_id", "dystocia_reason", "remarks"). 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(currentUser.PastureId, 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) SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) (err error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误,请退出重新登录") } operationUser, err := s.GetSystemUserById(ctx, currentUser.PastureId, int64(req.OperationId)) if err != nil { return xerr.WithStack(err) } eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, currentUser.PastureId, 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, currentUser.PastureId, 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 eventCowSameTime.EventUpdate(drugs, req.Usage, req.Remarks, operationUser, currentUser) defer func() { if err == nil { // 记录牛只事件日志 cow, _ := s.GetCowInfoByCowId(ctx, currentUser.PastureId, eventCowSameTime.CowId) cowLogs := s.SubmitEventLog(ctx, currentUser, cow, pasturePb.EventType_Seme_Time, pasturePb.ExposeEstrusType_Same_Time, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } }() 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) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误,请退出重新登录") } operationUser, err := s.GetSystemUserById(ctx, currentUser.PastureId, int64(req.OperationId)) if err != nil { return xerr.Customf("异常数据") } req.OperationName = operationUser.Name drugs := &model.Drugs{} if drugs, err = s.GetDrugsById(ctx, currentUser.PastureId, 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, currentUser.PastureId, 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, currentUser.PastureId, v.CowId) cowLogs := s.SubmitEventLog( ctx, currentUser, 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 { // 更新SameTime v.EventUpdate(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) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return nil, xerr.Custom("当前用户信息错误,请退出重新登录") } cowSameTimeList := make([]*model.EventCowSameTime, 0) var count int64 = 0 pref := s.DB.Table(new(model.EventCowSameTime).TableName()).Where("pasture_id = ?", currentUser.PastureId) 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) EstrusList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusItemsResponse, error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return nil, xerr.Custom("用户信息错误,请退出重新登录") } estrusList := make([]*model.EventEstrus, 0) var count int64 = 0 pref := s.DB.Table(new(model.EventEstrus).TableName()). Where("is_show = ?", pasturePb.IsShow_Ok). Where("pasture_id = ?", currentUser.PastureId) 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) EstrusBatchMating(ctx context.Context, req *pasturePb.EventEstrus) (err error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误,请退出重新登录") } operationUser, err := s.GetSystemUserById(ctx, currentUser.PastureId, 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) cowIds := make([]int32, 0) for _, cowId := range req.CowIds { cowInfo := GetCowInfoByCowId(s.DB, int64(cowId)) if cowInfo == nil { return xerr.Custom("牛只信息不存在") } newEventMating := model.NewEventMating(currentUser.PastureId, cowInfo, time.Now().Unix(), pasturePb.ExposeEstrusType_Neck_Ring) eventEstrus, ok, err := s.FindEventEstrusByCowId(ctx, currentUser.PastureId, int64(cowId)) if err != nil { return xerr.WithStack(err) } if !ok { continue } newEventMating.EventEstrusId = eventEstrus.Id eventEstrusIds = append(eventEstrusIds, strconv.FormatInt(eventEstrus.Id, 10)) eventMatingList = append(eventMatingList, newEventMating) cowIds = append(cowIds, cowId) } if len(eventMatingList) <= 0 { return nil } 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) } // 配种信息 eventMating := &pasturePb.EventMating{ CowIds: cowIds, FrozenSemenNumber: req.BullNumber, FrozenSemenCount: req.Quantity, OperationId: req.OperationId, Remarks: req.Remarks, MatingAt: req.MatingAt, ExposeEstrusType: pasturePb.ExposeEstrusType_Neck_Ring, } if err = s.MatingCreate(ctx, eventMating); err != nil { zaplog.Error("EstrusBatchMating", zap.Any("MatingCreate", err), zap.Any("eventMating", eventMating)) return xerr.WithStack(err) } return nil } func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return nil, xerr.Custom("当前用户信息错误,请退出重新登录") } 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). Where("pasture_id = ?", currentUser.PastureId) 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) } req.OperationName = eventCheckModel.OperationUser.Name if err = s.DB.Transaction(func(tx *gorm.DB) error { for _, cow := range eventCheckModel.CowList { // 获取牛只最近一次配种信息 lastEventMating, ok, err := s.FindLastEventMatingByCowId(ctx, eventCheckModel.CurrentUser.PastureId, cow.Id) if err != nil { return xerr.WithStack(err) } // 1. 没有配种信息,(第一次参加配种的牛只,并且没有参与同期的牛只 ) if !ok { newMating := model.NewEventMatingNaturalEstrus(cow, req, eventCheckModel.CurrentUser) if err = tx.Create(newMating).Error; err != nil { return xerr.WithStack(err) } if err = s.MatingCowUpdate(ctx, cow, eventCheckModel.CurrentUser, req, false); err != nil { return xerr.WithStack(err) } continue } // 2. 所有有配种数据的牛只 if lastEventMating == nil || lastEventMating.Id <= 0 { zaplog.Error("MatingCreate", zap.Any("cow", cow), zap.Any("CurrentUser", eventCheckModel.CurrentUser)) return xerr.Customf("异常牛数据: %d", cow.Id) } // 2.1 复配 => 本胎次配次不加1 isReMating := lastEventMating.IsReMating(cow, int64(req.MatingAt)) if isReMating { lastEventMating.EventReMatingUpdate(int64(req.MatingAt)) if err = tx.Model(lastEventMating). Select("mating_result", "mating_result_at", "status"). Where("id = ?", lastEventMating.Id). Updates(lastEventMating).Error; err != nil { } } // 2.2. 同期初配 IsMatingUpdate := lastEventMating.IsMatingUpdate() if IsMatingUpdate { lastEventMating.EventUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating, eventCheckModel.OperationUser, eventCheckModel.CurrentUser) if err = tx.Model(lastEventMating). Select("mating_at", "status", "reality_day", "frozen_semen_number", "operation_id", "operation_name", "message_id", "message_name"). Where("id = ?", lastEventMating.Id). Updates(lastEventMating).Error; err != nil { return xerr.WithStack(err) } } // 2.3. 提交的配种数据中,定位出空怀的牛只, isEmptyMating := lastEventMating.IsEmptyMating(cow, int64(req.MatingAt)) if isEmptyMating { // 把上次配种结果信息更新成空怀 lastEventMating.EventMatingResultUpdate(pasturePb.MatingResult_Empty, int64(req.MatingAt)) if err = tx.Model(lastEventMating). Select("mating_result", "mating_result_at"). Where("id = ?", lastEventMating.Id). Updates(lastEventMating).Error; err != nil { return xerr.WithStack(err) } // 先创建一条新的配种数据 newMating := model.NewEventMating(eventCheckModel.CurrentUser.PastureId, cow, int64(req.MatingAt), req.ExposeEstrusType) newMating.EventUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating, eventCheckModel.OperationUser, eventCheckModel.CurrentUser) if err = tx.Model(newMating).Create(newMating).Error; err != nil { return xerr.WithStack(err) } // 更新牛只配种结果日志 if err = s.UpdateMatingResultEventCowLogByCowId(ctx, cow.Id, s.MatingResultMap()[pasturePb.MatingResult_Empty]); err != nil { zaplog.Error("MatingCreate", zap.Any("UpdateEventCowLogByCowId", err), zap.Any("cow", cow)) } } // 牛只基本中配种信息更新 if err = s.MatingCowUpdate(ctx, cow, eventCheckModel.CurrentUser, req, isReMating); err != nil { return xerr.WithStack(err) } } // 创建冻精使用记录日志 itemFrozenSemenLog := model.NewEventFrozenSemenLog(eventCheckModel.FrozenSemen.PastureId, req) if err = tx.Create(itemFrozenSemenLog).Error; err != nil { return xerr.WithStack(err) } // 减去精液的数量 eventCheckModel.FrozenSemen.EventQuantityUpdate(req.FrozenSemenCount) if err = tx.Model(eventCheckModel.FrozenSemen). Select("quantity"). Where("id = ?", eventCheckModel.FrozenSemen.Id). Updates(eventCheckModel.FrozenSemen).Error; err != nil { return xerr.WithStack(err) } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) MatingCowUpdate(ctx context.Context, cow *model.Cow, currentUser *model.SystemUser, req *pasturePb.EventMating, isReMating bool) error { // 牛只基本中配种信息更新 cow.EventMatingUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating) if err := s.DB.Model(cow). Select("last_mating_at", "mating_times", "last_bull_number", "first_mating_at", "is_pregnant", "breed_status"). Where("id = ?", cow.Id). Updates(cow).Error; err != nil { return xerr.WithStack(err) } // 记录日志 cowLogs := s.SubmitEventLog(ctx, currentUser, cow, pasturePb.EventType_Mating, req.ExposeEstrusType, req) if err := s.DB.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) WeaningBatch(ctx context.Context, req *pasturePb.EventWeaningBatchRequest) (err error) { currentUser, err := s.GetCurrentSystemUser(ctx) if err != nil { return xerr.Custom("当前用户信息错误,请退出重新登录") } 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, currentUser.PastureId, int64(req.OperationId)) if err != nil { return xerr.WithStack(err) } defer func() { if err != nil { for _, cowId := range cowIds { cow, _ := s.GetCowInfoByCowId(ctx, currentUser.PastureId, cowId) cowLogs := s.SubmitEventLog(ctx, currentUser, 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, currentUser.PastureId, 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 }