Эх сурвалжийг харах

neckRing: 脖环绑定或解绑

Yi 4 сар өмнө
parent
commit
77e005c673

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20241217065218-21d2be069b22
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20241218092251-fc63330bc909
 	gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3

+ 5 - 0
go.sum

@@ -59,6 +59,11 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20241217030755-242924b1d633 h1:tj3mbsCd
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241217030755-242924b1d633/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241217065218-21d2be069b22 h1:4qNwmfsRxhbWGst94GHgibyfTt5LAtu0oBwzpQjWyQI=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241217065218-21d2be069b22/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241218075304-cbb87679a2f1 h1:0oozXkfpp5WIZZoBadC/1au+rHgw8m92eXIhb/3/AV0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241218075304-cbb87679a2f1/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241218075333-5e665935b341/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241218092251-fc63330bc909 h1:vxUvJnVW0fMgbWwLBTHLU0cNYyl3nBm/8RO86TmulIs=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241218092251-fc63330bc909/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b h1:w05MxH7yqveRlaRbxHhbif5YjPrJFodRPfOjYhXn7Zk=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 16 - 3
http/handler/goods/drugs.go

@@ -133,7 +133,7 @@ func NeckRingList(c *gin.Context) {
 		PageOffset: int32(c.GetInt(middleware.PageOffset)),
 	}
 
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.NeckRingLogList(c, &req, pagination)
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.NeckRingList(c, &req, pagination)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
@@ -149,13 +149,26 @@ func NeckRingCreateOrUpdate(c *gin.Context) {
 	}
 
 	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.Items, valid.Required),
+		valid.Field(&req.Items, valid.Required, valid.Each(valid.By(func(value interface{}) error {
+			item := value.(pasturePb.NeckRingCreateItem)
+			if req.Status == pasturePb.NeckRingOperationStatus_Bind {
+				return valid.ValidateStruct(&item,
+					valid.Field(&item.Number, valid.Required),
+					valid.Field(&item.CowId, valid.Required),
+				)
+			} else {
+				return valid.ValidateStruct(&item,
+					valid.Field(&item.Number, valid.Required),
+				)
+			}
+		}))),
+		valid.Field(&req.Status, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.NeckRingLogCreateOrUpdate(c, &req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.NeckRingCreateOrUpdate(c, &req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}

+ 39 - 20
model/neck_ring_log.go → model/neck_ring.go

@@ -1,17 +1,17 @@
 package model
 
 import (
+	"kpt-pasture/store/kptstore"
 	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
-type NeckRingLog struct {
+type NeckRing struct {
 	Id            int64                         `json:"id"`
 	Number        string                        `json:"number"`
 	CowId         int64                         `json:"cowId"`
 	WearAt        int64                         `json:"wearAt"`
-	UnbindAt      int64                         `json:"unbindAt"`
 	Status        pasturePb.NeckRingStatus_Kind `json:"status"`
 	ErrorReason   string                        `json:"errorReason"`
 	OperationId   int32                         `json:"operationId"`
@@ -20,40 +20,59 @@ type NeckRingLog struct {
 	UpdatedAt     int64                         `json:"updatedAt"`
 }
 
-func (n *NeckRingLog) TableName() string {
-	return "neck_ring_log"
+func (n *NeckRing) TableName() string {
+	return "neck_ring"
 }
 
-func NewNeckRingLog(number string, cowId int64, currentUser *SystemUser) *NeckRingLog {
-	return &NeckRingLog{
+func (n *NeckRing) Update(cowId int64) {
+	n.CowId = cowId
+	n.WearAt = time.Now().Unix()
+}
+
+func NewNeckRing(number string, cowId int64, operationUser *SystemUser) *NeckRing {
+	return &NeckRing{
 		Number:        number,
 		CowId:         cowId,
 		WearAt:        time.Now().Unix(),
 		Status:        pasturePb.NeckRingStatus_Bind,
-		OperationId:   int32(currentUser.Id),
-		OperationName: currentUser.Name,
+		OperationId:   int32(operationUser.Id),
+		OperationName: operationUser.Name,
 	}
 }
 
-func NewNeckRingLogList(req []*pasturePb.NeckRingCreateItem, currentUser *SystemUser) []*NeckRingLog {
-	res := make([]*NeckRingLog, len(req))
-	for i, v := range req {
-		res[i] = NewNeckRingLog(v.Number, int64(v.CowId), currentUser)
-	}
-	return res
-}
+type NeckRingSlice []*NeckRing
 
-type NeckRingLogSlice []*NeckRingLog
-
-func (n NeckRingLogSlice) ToPB(neckRingStatus map[pasturePb.NeckRingStatus_Kind]string) []*pasturePb.SearchNeckRingList {
+func (n NeckRingSlice) ToPB(
+	neckRingStatus map[pasturePb.NeckRingStatus_Kind]string,
+	db *kptstore.DB,
+	getCowPenInfoByCowId func(DB *kptstore.DB, cowId int64) *Pen,
+) []*pasturePb.SearchNeckRingList {
 	res := make([]*pasturePb.SearchNeckRingList, len(n))
 	for i, v := range n {
+		penId := int32(0)
+		penName := ""
+		if v.CowId > 0 {
+			penInfo := getCowPenInfoByCowId(db, v.CowId)
+			if penInfo != nil {
+				penId = penInfo.Id
+				penName = penInfo.Name
+			}
+		}
+
+		wearAtFormat := ""
+		wearDays := int32(0)
+		if v.WearAt > 0 {
+			wearAtFormat = time.Unix(v.WearAt, 0).Format(LayoutDate2)
+			wearDays = int32(time.Now().Sub(time.Unix(v.WearAt, 0)).Hours() / 24)
+		}
 		res[i] = &pasturePb.SearchNeckRingList{
 			Id:           int32(v.Id),
 			Number:       v.Number,
+			PenId:        penId,
+			PenName:      penName,
 			CowId:        int32(v.CowId),
-			WearAtFormat: time.Unix(v.WearAt, 0).Format(LayoutDate2),
-			WearDays:     int32(time.Now().Sub(time.Unix(v.WearAt, 0)).Hours() / 24),
+			WearAtFormat: wearAtFormat,
+			WearDays:     wearDays,
 			Status:       v.Status,
 			StatusName:   neckRingStatus[v.Status],
 			ErrorReason:  v.ErrorReason,

+ 33 - 0
model/neck_ring_bind_log.go

@@ -0,0 +1,33 @@
+package model
+
+import "time"
+
+type NeckRingBindLog struct {
+	Id            int64  `json:"id"`
+	Number        string `json:"number"`
+	CowId         int64  `json:"cowId"`
+	BindAt        int64  `json:"bindAt"`
+	UnBindAt      int64  `json:"unBindAt"`
+	OperationId   int64  `json:"operationId"`
+	OperationName string `json:"operationName"`
+	CreatedAt     int64  `json:"createdAt"`
+	UpdatedAt     int64  `json:"updatedAt"`
+}
+
+func (n *NeckRingBindLog) TableName() string {
+	return "neck_ring_bind_log"
+}
+
+func NewNeckRingBindLog(number string, cowId int64, operationUser *SystemUser) *NeckRingBindLog {
+	return &NeckRingBindLog{
+		Number:        number,
+		BindAt:        time.Now().Unix(),
+		CowId:         cowId,
+		OperationId:   operationUser.Id,
+		OperationName: operationUser.Name,
+	}
+}
+
+func (n *NeckRingBindLog) UnBind() {
+	n.UnBindAt = time.Now().Unix()
+}

+ 1 - 5
module/backend/calendar.go

@@ -95,7 +95,7 @@ func (s *StoreEntry) CalendarTableDetail(
 ) (interface{}, error) {
 
 	if req.Start != time.Now().Format(model.LayoutDate2) {
-		return nil, xerr.New("参数错误")
+		return nil, xerr.Custom("只能获取当天的数据")
 	}
 
 	newCalendar := &model.Calendar{}
@@ -164,10 +164,6 @@ func (s *StoreEntry) ImmunisationCowList(ctx context.Context, req *pasturePb.Ite
 		pref.Where("plan_id = ?", req.ImmunizationId)
 	}
 
-	if req.Lact >= 0 {
-		pref.Where("lact = ?", req.Lact)
-	}
-
 	if req.PenId > 0 {
 		pref.Where("pen_id = ?", req.PenId)
 	}

+ 4 - 0
module/backend/config_data_breed.go

@@ -238,6 +238,10 @@ func (s *StoreEntry) NeckRingStatusEnumList(isAll string) []*pasturePb.ConfigOpt
 			})
 	}
 	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.NeckRingStatus_Unbind),
+		Label:    "未绑定",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.NeckRingStatus_Bind),
 		Label:    "绑定",
 		Disabled: true,

+ 75 - 31
module/backend/goods.go

@@ -117,7 +117,7 @@ func (s *StoreEntry) MedicalEquipmentCreateOrUpdate(ctx context.Context, req *pa
 	return nil
 }
 
-func (s *StoreEntry) NeckRingLogCreateOrUpdate(ctx context.Context, req *pasturePb.NeckRingCreateRequest) error {
+func (s *StoreEntry) NeckRingCreateOrUpdate(ctx context.Context, req *pasturePb.NeckRingCreateRequest) error {
 	currentUser, err := s.GetCurrentSystemUser(ctx)
 	if err != nil {
 		return xerr.Custom("登录人信息失效")
@@ -127,54 +127,98 @@ func (s *StoreEntry) NeckRingLogCreateOrUpdate(ctx context.Context, req *pasture
 		return xerr.Custom("请选择要脖环数据")
 	}
 
-	newNeckRingLogList := model.NewNeckRingLogList(req.Items, currentUser)
-	cowIds := make([]int64, 0)
-	for _, v := range newNeckRingLogList {
-		cowIds = append(cowIds, v.CowId)
-	}
-
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
-		// 解绑脖环号
-		if err = tx.Model(new(model.NeckRingLog)).
-			Where("cow_id IN ?", cowIds).
-			Updates(map[string]interface{}{
-				"unbind_at":      time.Now().Unix(),
-				"status":         pasturePb.NeckRingStatus_Unbind,
-				"operation_id":   currentUser.Id,
-				"operation_name": currentUser.Name,
-			}).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		// 绑定新脖环
-		if err = tx.Create(newNeckRingLogList).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
 		for _, v := range req.Items {
-			if v.CowId > 0 {
+			switch req.Status {
+			// 绑定
+			case pasturePb.NeckRingOperationStatus_Bind:
+				_, err = s.GetCowInfoByCowId(ctx, int64(v.CowId))
+				if err != nil {
+					return xerr.Customf("该牛不存在")
+				}
+				neckRing, ok := s.NeckRingIsExist(ctx, v.Number)
+				if !ok {
+					newNeckRing := model.NewNeckRing(v.Number, int64(v.CowId), currentUser)
+					if err = tx.Create(newNeckRing).Error; err != nil {
+						return xerr.WithStack(err)
+					}
+				}
+
+				if ok {
+					neckRing.Update(int64(v.CowId))
+					if err = tx.Model(new(model.NeckRing)).
+						Select("cow_id,wear_at").
+						Where("id = ?", neckRing.Id).
+						Updates(neckRing).Error; err != nil {
+						return xerr.WithStack(err)
+					}
+				}
+
+				newNeckRingLog := model.NewNeckRingBindLog(v.Number, int64(v.CowId), currentUser)
+				if err = tx.Create(newNeckRingLog).Error; err != nil {
+					return xerr.WithStack(err)
+				}
 				if err = tx.Model(new(model.Cow)).
 					Where("id = ?", v.CowId).
-					Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+					Update("neck_ring_number", v.Number).
+					Error; err != nil {
+					return xerr.WithStack(err)
+				}
+				// 解绑
+			case pasturePb.NeckRingOperationStatus_UnBind:
+				if err = tx.Model(new(model.NeckRing)).
+					Where("number = ?", v.Number).
 					Updates(map[string]interface{}{
-						"neck_ring_number": v.Number,
+						"wear_at": 0,
+						"cow_id":  0,
+						"status":  pasturePb.NeckRingStatus_Unbind,
 					}).Error; err != nil {
 					return xerr.WithStack(err)
 				}
+
+				if err = tx.Model(new(model.Cow)).
+					Where("neck_ring_number = ?", v.Number).
+					Updates(map[string]interface{}{
+						"neck_ring_number": "",
+					}).Error; err != nil {
+					return xerr.WithStack(err)
+				}
+
+				if err = tx.Model(new(model.NeckRingBindLog)).
+					Where("number = ?", v.Number).
+					Update("un_bind_at", time.Now().Unix()).Error; err != nil {
+					return xerr.WithStack(err)
+				}
+				// 编辑
+			case pasturePb.NeckRingOperationStatus_Edit:
+				if err = tx.Model(new(model.NeckRing)).
+					Where("cow_id = ?", v.CowId).
+					Update("number", v.Number).Error; err != nil {
+					return xerr.WithStack(err)
+				}
+
+				if err = tx.Model(new(model.Cow)).
+					Where("id = ?", v.CowId).
+					Update("neck_ring_number", v.Number).Error; err != nil {
+					return xerr.WithStack(err)
+				}
 			}
 		}
-
 		return nil
 	}); err != nil {
 		return xerr.WithStack(err)
 	}
+
 	return nil
 }
 
-func (s *StoreEntry) NeckRingLogList(ctx context.Context, req *pasturePb.SearchNeckRingRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchNeckRingResponse, error) {
-	neckRingLogList := make([]*model.NeckRingLog, 0)
+func (s *StoreEntry) NeckRingList(ctx context.Context, req *pasturePb.SearchNeckRingRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchNeckRingResponse, error) {
+	neckRingLogList := make([]*model.NeckRing, 0)
 	var count int64 = 0
 
-	pref := s.DB.Model(new(model.NeckRingLog)).Where("status > ?", pasturePb.NeckRingStatus_Unbind)
+	pref := s.DB.Model(new(model.NeckRing)).
+		Where("status >= ?", pasturePb.NeckRingStatus_Unbind).
+		Where("number != ''")
 	if req.Status > 0 {
 		pref.Where("status = ?", req.Status)
 	}
@@ -200,7 +244,7 @@ func (s *StoreEntry) NeckRingLogList(ctx context.Context, req *pasturePb.SearchN
 		Code:    http.StatusOK,
 		Message: "ok",
 		Data: &pasturePb.SearchNeckRingData{
-			List:     model.NeckRingLogSlice(neckRingLogList).ToPB(neckRingStatusMap),
+			List:     model.NeckRingSlice(neckRingLogList).ToPB(neckRingStatusMap, s.DB, GetCowPenInfoByCowId),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,

+ 3 - 3
module/backend/interface.go

@@ -215,9 +215,9 @@ type GoodsService interface {
 	// MedicalEquipmentList 医疗设备
 	MedicalEquipmentList(ctx context.Context, req *pasturePb.SearchMedicalEquipmentRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchMedicalEquipmentResponse, error)
 	MedicalEquipmentCreateOrUpdate(ctx context.Context, req *pasturePb.SearchMedicalEquipmentList) error
-	// NeckRingLogList 脖环相关
-	NeckRingLogList(ctx context.Context, req *pasturePb.SearchNeckRingRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchNeckRingResponse, error)
-	NeckRingLogCreateOrUpdate(ctx context.Context, req *pasturePb.NeckRingCreateRequest) error
+	// NeckRingList 脖环相关
+	NeckRingList(ctx context.Context, req *pasturePb.SearchNeckRingRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchNeckRingResponse, error)
+	NeckRingCreateOrUpdate(ctx context.Context, req *pasturePb.NeckRingCreateRequest) error
 	// OutboundApply 出库申请
 	OutboundApply(ctx context.Context, req *pasturePb.OutboundApplyItem) error
 	OutboundList(ctx context.Context, req *pasturePb.SearchOutboundApplyRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchOutboundApplyResponse, error)

+ 29 - 2
module/backend/sql.go

@@ -3,13 +3,14 @@ package backend
 import (
 	"context"
 	"errors"
+	"fmt"
 	"kpt-pasture/model"
+	"kpt-pasture/store/kptstore"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 	"go.uber.org/zap"
 
-	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
-
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/xerr"
 	"gorm.io/gorm"
@@ -362,3 +363,29 @@ func (s *StoreEntry) DiseaseMaps(ctx context.Context) (map[int64]*model.Disease,
 	}
 	return res, nil
 }
+
+func (s *StoreEntry) NeckRingIsExist(ctx context.Context, number string) (*model.NeckRing, bool) {
+	neckRing := &model.NeckRing{}
+	if err := s.DB.Model(new(model.NeckRing)).
+		Where("number = ?", number).
+		First(neckRing).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, false
+		}
+	}
+	return neckRing, true
+}
+
+func GetCowPenInfoByCowId(DB *kptstore.DB, cowId int64) *model.Pen {
+	penData := &model.Pen{}
+	if err := DB.Model(new(model.Cow)).
+		Select("b.*").
+		Table(fmt.Sprintf("%s as a", new(model.Cow).TableName())).
+		Joins(fmt.Sprintf("left join %s as b on a.pen_id = b.id", new(model.Pen).TableName())).
+		Where("a.id = ?", cowId).
+		Where("a.pen_id > ?", 0).
+		First(penData).Error; err != nil {
+		return nil
+	}
+	return penData
+}