package backend import ( "context" "fmt" "kpt-pasture/model" "net/http" "strconv" "strings" "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) ParseCowIds(ctx context.Context, pastureId int64, cowIds string) ([]*model.Cow, error) { if len(cowIds) == 0 { return nil, xerr.Custom("cow id is required") } cowIdStr := strings.Split(cowIds, ",") var cowIdInts = make([]int64, 0) for _, v := range cowIdStr { cowId, err := strconv.ParseInt(v, 10, 64) if err != nil { return nil, xerr.Customf("错误的牛号: %s", v) } cowIdInts = append(cowIdInts, cowId) } cowList, err := s.GetCowInfoByCowIds(ctx, pastureId, cowIdInts) if err != nil { return nil, xerr.WithStack(err) } return cowList, nil } func (s *StoreEntry) EnterList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchEnterEventResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } eventEnterList := make([]*model.EventEnter, 0) var count int64 = 0 pref := s.DB.Model(new(model.EventEnter)). Where("pasture_id = ?", userModel.AppPasture.Id) 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(&eventEnterList).Error; err != nil { return nil, xerr.WithStack(err) } penMap := s.PenMap(ctx, userModel.AppPasture.Id) breedStatusMap := s.CowBreedStatusMap() cowSourceMap := s.CowSourceMap() cowTypeMap := s.CowTypeMap() cowKindMap := s.CowKindMap() return &pasturePb.SearchEnterEventResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchEnterEventData{ List: model.EventEnterSlice(eventEnterList).ToPB(penMap, breedStatusMap, cowSourceMap, cowTypeMap, cowKindMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) CreateEnter(ctx context.Context, req *pasturePb.EventEnterRequest) (err error) { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } if err = s.EnterCheck(ctx, req); err != nil { return xerr.WithStack(err) } req.MessengerId = int32(userModel.SystemUser.Id) req.MessengerName = userModel.SystemUser.Name if req.OperationId > 0 { systemUser, _ := s.GetSystemUserById(ctx, int64(req.OperationId)) req.OperationName = systemUser.Name } penMap := s.PenMap(ctx, userModel.AppPasture.Id) newCow := model.NewCow(userModel.AppPasture.Id, req, penMap) defer func() { if err == nil { cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, newCow, pasturePb.EventType_Enter, pasturePb.ExposeEstrusType_Invalid, req) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } }() if err = s.DB.Transaction(func(tx *gorm.DB) error { if err = tx.Create(newCow).Error; err != nil { return xerr.WithStack(err) } newEventEnter := model.NewEventEnter(userModel.AppPasture.Id, newCow.Id, req) if err = tx.Create(newEventEnter).Error; err != nil { return xerr.WithStack(err) } eventWeight := model.NewEventWeight( userModel.AppPasture.Id, newCow, userModel.SystemUser, &pasturePb.EventWeight{ WeightAt: req.EnterAt, Remarks: "入场体重", OperationId: req.OperationId, OperationName: req.OperationName, Weight: req.Weight, }) if err = tx.Create(eventWeight).Error; err != nil { return xerr.WithStack(err) } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) GroupTransferList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchTransferGroupEventResponse, error) { eventGroupTransferList := make([]*pasturePb.EventTransferGroupData, 0) var count int64 = 0 pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventTransferGroup).TableName())). Select(`a.id,a.cow_id,a.pen_in_id as transfer_in_pen_id,a.pen_out_id as transfer_out_pen_id,a.lact,a.remarks, a.transfer_reason_id,a.transfer_reason_name,a.transfer_date,a.created_at,a.operation_id,a.operation_name, b.name as transfer_in_pen_name,c.name as transfer_out_pen_name,f.lact,f.ear_number`). Joins(fmt.Sprintf("JOIN %s AS b ON a.pen_in_id = b.id", new(model.Pen).TableName())). Joins(fmt.Sprintf("JOIN %s AS c on a.pen_out_id = c.id", new(model.Pen).TableName())). Joins(fmt.Sprintf("JOIN %s AS f ON a.cow_id = f.id", new(model.Cow).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").Group("a.id"). Count(&count).Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&eventGroupTransferList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.SearchTransferGroupEventResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchTransferGroupEventData{ List: eventGroupTransferList, Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) CreateGroupTransfer(ctx context.Context, req *pasturePb.TransferGroupEventRequest) (err error) { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } newEventTransferGroupModelList := make([]*model.EventTransferGroupModel, 0) transferPenMap := s.TransferPenMap() for _, v := range req.Body { cow, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(v.CowId)) if err != nil { return xerr.WithStack(err) } // 转去栏舍和当前栏舍相同,则不处理 if cow.PenId == v.TransferInPenId { return xerr.Custom("转入栏舍和牛只当前栏舍不能一致") } operationUser, err := s.GetSystemUserById(ctx, int64(v.OperationId)) if err != nil { return xerr.WithStack(err) } newEventTransferGroup := model.NewEventTransferGroup(userModel.AppPasture.Id, cow, v, transferPenMap, userModel.SystemUser, operationUser) newEventTransferGroupModelList = append(newEventTransferGroupModelList, &model.EventTransferGroupModel{ Cow: cow, EventTransferGroup: newEventTransferGroup, }) } if len(newEventTransferGroupModelList) <= 0 { return nil } if err = s.DB.Transaction(func(tx *gorm.DB) error { for _, etg := range newEventTransferGroupModelList { if err = tx.Create(etg.EventTransferGroup).Error; err != nil { return xerr.WithStack(err) } if err = tx.Model(etg.Cow).Update("pen_id", etg.EventTransferGroup.PenInId).Error; err != nil { return xerr.WithStack(err) } // 事件日志 cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, etg.Cow, pasturePb.EventType_Transfer_Ben, pasturePb.ExposeEstrusType_Invalid, etg.EventTransferGroup) if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) BodyScoreList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBodyScoreEventResponse, error) { bodyScoreList := make([]*pasturePb.BodyScoreList, 0) var count int64 = 0 pref := s.DB.Model(new(model.EventBodyScore)).Select("*,score as body_score") 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(&bodyScoreList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.SearchBodyScoreEventResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchBodyScoreData{ List: bodyScoreList, Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) CreateBodyScore(ctx context.Context, req *pasturePb.BodyScoreEventRequest) error { if len(req.CowId) <= 0 { return xerr.Custom("请选择相关牛只") } userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId)) if err != nil { return xerr.WithStack(err) } req.OperationName = operationUser.Name bodyScourEvent := make([]*model.EventBodyScore, 0) cowList, err := s.ParseCowIds(ctx, userModel.AppPasture.Id, req.CowId) if err != nil { return xerr.WithStack(err) } for _, cow := range cowList { bodyScourEvent = append(bodyScourEvent, model.NewEventBodyScore(cow, userModel.AppPasture.Id, userModel.SystemUser, req)) } if len(bodyScourEvent) <= 0 { return nil } return s.DB.Create(bodyScourEvent).Error } func (s *StoreEntry) WeightList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWeightEventResponse, error) { weightList := make([]*pasturePb.SearchWeightList, 0) var count int64 = 0 pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventWeight).TableName())). Select(`a.id,a.cow_id,a.ear_number,ROUND(a.weight/1000, 2) as weight,a.height,a.lact,a.day_age,a.weight_at,a.remarks,a.created_at, a.updated_at,a.message_id,a.operation_id,a.message_name,a.operation_name`) 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(&weightList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.SearchWeightEventResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchWeightData{ List: weightList, Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) WeightBatch(ctx context.Context, req *pasturePb.BatchEventWeight) (err error) { if len(req.Items) <= 0 { return xerr.Custom("称重数据不能为空") } userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } defer func() { if err == nil { // 记录事件日志 for _, item := range req.Items { cow, _ := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(item.CowId)) cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Weight, pasturePb.ExposeEstrusType_Invalid, item) s.DB.Table(cowLogs.TableName()).Create(cowLogs) } } }() cow := &model.Cow{} for _, item := range req.Items { cow, err = s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(item.CowId)) if err != nil { return xerr.WithStack(err) } // 更新牛只信息 cow.EventWeightUpdate(int64(item.Weight*1000), int64(item.WeightAt)) if err = s.DB.Model(new(model.Cow)). Select("last_second_weight_at", "last_second_weight", "last_weight_at", "current_weight"). Where("id = ?", cow.Id). Where("admission_status = ?", pasturePb.AdmissionStatus_Admission). Updates(cow).Error; err != nil { return xerr.WithStack(err) } operationUser, _ := s.GetSystemUserById(ctx, int64(item.OperationId)) item.OperationName = operationUser.Name // 创建牛只的体重记录 eventWeight := model.NewEventWeight(userModel.AppPasture.Id, cow, userModel.SystemUser, item) if err = s.DB.Create(eventWeight).Error; err != nil { return xerr.WithStack(err) } } return err } func (s *StoreEntry) DepartureBatch(ctx context.Context, req *pasturePb.EventDepartureBatch) (err error) { if len(req.Item) <= 0 { return xerr.Custom("请选择相关牛只") } userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } newEventDepartureModelList := make([]*model.EventDepartureModel, 0) cow := &model.Cow{} for _, item := range req.Item { cow, err = s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(item.CowId)) if err != nil { zaplog.Error("DepartureBatch", zap.Any("item", item), zap.Any("err", err)) return xerr.Customf("获取牛只信息失败: %d", item.CowId) } operationUser, err := s.GetSystemUserById(ctx, int64(item.OperationId)) if err != nil { zaplog.Error("DepartureBatch", zap.Any("item", item), zap.Any("err", err)) return xerr.Customf("获取操作人员信息失败: %d", item.OperationId) } reasonName := "" switch item.DepartureType { case pasturePb.DepartureType_Death: reasonName = s.DeadReasonMap()[pasturePb.DeadReason_Kind(item.DepartureReasonKind)] case pasturePb.DepartureType_Out: reasonName = s.OutReasonMap()[pasturePb.OutReason_Kind(item.DepartureReasonKind)] default: return xerr.Custom("未知的离场类型") } newEventDeparture := model.NewEventDeparture(userModel.AppPasture.Id, cow, item, reasonName, userModel.SystemUser, operationUser) newEventDepartureModelList = append(newEventDepartureModelList, &model.EventDepartureModel{ EventDeparture: newEventDeparture, Cow: cow, DepartureAt: int64(item.DepartureAt), }) } if len(newEventDepartureModelList) <= 0 { return nil } if err = s.DB.Transaction(func(tx *gorm.DB) error { // 记录事件日志 for _, item := range newEventDepartureModelList { eventType := pasturePb.EventType_Death if item.EventDeparture.DepartureType == pasturePb.DepartureType_Out { eventType = pasturePb.EventType_Out } if err = tx.Create(item.EventDeparture).Error; err != nil { return xerr.WithStack(err) } cow.EventDepartureUpdate(item.DepartureAt, item.EventDeparture.DepartureType) if err = tx.Model(cow). Select("admission_status", "health_status", "departure_at"). Where("id = ?", cow.Id). Updates(cow).Error; err != nil { return xerr.WithStack(err) } // 记录事件日志 cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, eventType, pasturePb.ExposeEstrusType_Invalid, item) if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) CowEarNumberUpdate(ctx context.Context, req *pasturePb.EventReplaceEarNumber) (err error) { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } cow, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId)) if err != nil { return xerr.Custom("未找到该牛只信息") } cow.EventEarNumberUpdate(req.EarNumber) if err = s.DB.Model(cow). Select("ear_number", "ear_old_number"). Where("id = ?", cow.Id). Updates(cow).Error; err != nil { return xerr.WithStack(err) } return nil }