Prechádzať zdrojové kódy

crontab: neckRingHealth update

Yi 4 dní pred
rodič
commit
43dd721973

+ 10 - 2
http/handler/warning/warning.go

@@ -118,6 +118,14 @@ func DataNoticeDetail(c *gin.Context) {
 func DataNoticeKnown(c *gin.Context) {
 	idStr := c.Param("id")
 	dataNoticeId, _ := strconv.Atoi(idStr)
-	res := middleware.BackendOperation(c).OpsService.DataNoticeKnown(c, int64(dataNoticeId))
-	c.JSON(http.StatusOK, res)
+	if err := middleware.BackendOperation(c).OpsService.DataNoticeKnown(c, int64(dataNoticeId)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
 }

+ 9 - 1
model/data_notice.go

@@ -9,7 +9,10 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
-const DefaultDataLatencyMinutes = 40
+const (
+	DefaultDataLatencyMinutes = 40
+	DataLatencyTitle          = "脖环数据延迟"
+)
 
 type DataNotice struct {
 	Id         int64                     `json:"id"`
@@ -41,6 +44,11 @@ func (d *DataNotice) GetUserIds() []int64 {
 	return userIds
 }
 
+func (d *DataNotice) UpdateNotice(content string) {
+	d.Content = content
+	d.KnownUsers = ""
+}
+
 func NewDataNotice(pastureId int64, title, content string, noticeKind pasturePb.NoticeType_Kind) *DataNotice {
 	nowTime := time.Now().Local()
 	return &DataNotice{

+ 0 - 1
model/system_menu.go

@@ -156,7 +156,6 @@ func (s SystemMenuSlice) ToTree() []*pasturePb.MenuTree {
 	if len(s) == 0 {
 		return make([]*pasturePb.MenuTree, 0)
 	}
-
 	// 1. 一次性创建所有节点并建立ID映射
 	nodeMap := make(map[int32]*pasturePb.MenuTree, len(s))
 	allNodes := make([]*pasturePb.MenuTree, len(s))

+ 12 - 13
module/backend/system_service.go

@@ -28,9 +28,14 @@ const (
 // Login 用户登录
 func (s *StoreEntry) Login(ctx context.Context, req *pasturePb.SearchUserRequest) (*pasturePb.SystemUserResponse, error) {
 	systemUser := &model.SystemUser{}
-	if err := s.DB.Where("name = ?", req.Name).
+	if err := s.DB.Model(new(model.SystemUser)).
+		Where("name = ?", req.Name).
 		First(systemUser).Error; err != nil {
-		return nil, xerr.WithStack(err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, xerr.Customf("用户不存在: %s", req.Name)
+		} else {
+			return nil, xerr.WithStack(err)
+		}
 	}
 
 	if systemUser.Password != req.Password {
@@ -550,19 +555,13 @@ func (s *StoreEntry) GetMenusWithParents(ctx context.Context, pastureId int64, m
 	if err := s.DB.Table(fmt.Sprintf("%s as a", new(model.SystemMenu).TableName())).
 		Select("a.*").
 		Joins("LEFT JOIN system_role_menu as b ON a.id = b.menu_id").
-		Where("b.id IN ?", menuIds).
+		Joins("LEFT JOIN system_pasture_menu as c ON a.id = c.menu_id").
+		Where("a.id IN ?", menuIds).
+		Where("c.pasture_id = ?", pastureId).
+		Group("a.id").
 		Find(&userMenuList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 
-	allSystemMenuList := make([]*model.SystemMenu, 0)
-	if err := s.DB.Model(new(model.SystemMenu)).
-		Where("id IN (?) AND is_delete = ?", menuIds, pasturePb.IsShow_Ok).
-		Order("parent_id ASC,id ASC").
-		Group("id").
-		Find(&allSystemMenuList).Error; err != nil {
-		return nil, fmt.Errorf("failed to query menus: %v", err)
-	}
-
-	return allSystemMenuList, nil
+	return userMenuList, nil
 }

+ 32 - 7
module/crontab/cow_neck_ring_error.go

@@ -1,11 +1,14 @@
 package crontab
 
 import (
+	"errors"
 	"fmt"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"time"
 
+	"gorm.io/gorm"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 	"go.uber.org/zap"
@@ -298,14 +301,36 @@ func (e *Entry) NeckRingLastDate(pastureId int64) {
 	}
 	nowTime := time.Now().Local()
 	subMinutes := nowTime.Sub(time.Unix(lastOriginalData.CreatedAt, 0)).Minutes()
-	if subMinutes >= model.DefaultDataLatencyMinutes {
+	if subMinutes < model.DefaultDataLatencyMinutes {
+		return
+	}
+
+	hours := int(subMinutes) / 60
+	minutes := int(subMinutes) % 60
+	content := fmt.Sprintf("距离目前已经%d小时%d分钟未接收到脖环数据,核实是否有电,如有电请及时联系服务工程师", hours, minutes)
+
+	historyData := &model.DataNotice{}
+	if err := e.DB.Model(new(model.DataNotice)).
+		Where("pasture_id = ?", pastureId).
+		Where("notice_kind = ?", pasturePb.NoticeType_Neck_Ring_Data_Latency).
+		First(&historyData).Error; err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			return
+		}
+	}
 
-		hours := int(subMinutes) / 60
-		minutes := int(subMinutes) % 60
-		title := "脖环数据延迟"
-		content := fmt.Sprintf("距离目前已经%d小时%d分钟未接收到脖环数据,核实是否有电,如有电请及时联系服务工程师", hours, minutes)
-		newDataNotice := model.NewDataNotice(pastureId, title, content, pasturePb.NoticeType_Neck_Ring_Data_Latency)
-		if err := e.DB.Model(new(model.DataNotice)).Create(newDataNotice).Error; err != nil {
+	if historyData.Id > 0 {
+		historyData.UpdateNotice(content)
+		if err := e.DB.Model(new(model.DataNotice)).
+			Select("content", "known_users").
+			Where("id = ?", historyData.Id).
+			Updates(historyData).Error; err != nil {
+			zaplog.Error("NeckRingLastDate", zap.Any("err", err), zap.Any("pastureId", pastureId))
+		}
+	} else {
+		newDataNotice := model.NewDataNotice(pastureId, model.DataLatencyTitle, content, pasturePb.NoticeType_Neck_Ring_Data_Latency)
+		if err := e.DB.Model(new(model.DataNotice)).
+			Create(newDataNotice).Error; err != nil {
 			zaplog.Error("NeckRingLastDate", zap.Any("err", err), zap.Any("pastureId", pastureId))
 		}
 	}

+ 23 - 53
module/crontab/neck_ring_health.go

@@ -13,62 +13,32 @@ import (
 
 // HealthWarning 健康预警 create_jbq_update_2024
 func (e *Entry) HealthWarning(pastureId int64, processIds []int64) {
-	newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
-	if err := e.DB.Model(new(model.NeckActiveHabit)).
-		Where("pasture_id = ?", pastureId).
-		Where("id IN (?)", processIds).
-		Where("score BETWEEN ? AND ?", model.MinScore, model.MaxScore).
-		Order("neck_ring_number,heat_date,frameid").
-		Find(&newNeckActiveHabitList).Error; err != nil {
+	healthWarningList := make([]*model.NeckRingHealth, 0)
+	sqlQuery := `SELECT aa.pasture_id,aa.cow_id,aa.ear_number,aa.neck_ring_number,aa.lact,aa.calving_age,aa.heat_date,aa.frameid,aa.active_time,
+		aa.change_filter,aa.chew_filter,aa.sum_chew,aa.sum_inactive,aa.before_three_sum_chew,aa.min_high,aa.max_high,aa.min_chew,aa.score
+	FROM (
+		SELECT	h.id,h.cow_id,h.pasture_id,h.ear_number,h.neck_ring_number,h.calving_age,h.heat_date,h.frameid,h.lact,
+		IF(h.change_filter>-99, h.change_filter, 0) AS change_filter,
+		IF(h.filter_chew>-99, h.filter_chew, 0) AS chew_filter,
+		(h.sum_rumina +h.sum_intake) AS sum_chew,
+		h.sum_inactive,
+		(h.before_three_sum_rumina +h.before_three_sum_intake) AS before_three_sum_chew,
+		IF(h.sum_min_high>-99, h.sum_min_high, 0) AS min_high,
+		IF(h.sum_max_high>-99, h.sum_max_high, 0) AS max_high,
+		IF(h.sum_min_chew>-99, h.sum_min_chew, 0) AS min_chew,
+		h.score,h.active_time,
+		IF(h.cow_id=@cow AND h.heat_date=@date AND h.score>=@score, 0, 1) is_worse, @cow:=h.cow_id, @date:=h.heat_date, @score:=h.score
+		FROM neck_active_habit h, (SELECT @cow:=0, @date:='2001-01-01', @score:=100) aaa
+		WHERE h.id IN ? 
+		AND h.score BETWEEN ? AND ? 
+		AND  h.pasture_id = ?
+	) aa WHERE aa.is_worse = ? 
+	ORDER BY aa.id;`
+	if err := e.DB.Raw(sqlQuery, processIds, model.MinScore, model.MaxScore, pastureId, pasturePb.IsShow_Ok).
+		Find(&healthWarningList).Error; err != nil {
 		zaplog.Error("HealthWarning", zap.Any("error", err), zap.Any("processIds", processIds))
 	}
 
-	var (
-		lastCowID         int64  = 0
-		lastHeatDate      string = "2001-01-01"
-		lastScore         int32  = 100
-		healthWarningList []*model.NeckRingHealth
-	)
-
-	for _, habit := range newNeckActiveHabitList {
-		if habit.ChangeFilter <= -99 {
-			habit.ChangeFilter = 0
-		}
-
-		if habit.ChewFilter <= -99 {
-			habit.ChewFilter = 0
-		}
-
-		if habit.SumMinHigh <= -99 {
-			habit.SumMinHigh = 0
-		}
-
-		if habit.SumMaxHigh <= -99 {
-			habit.SumMaxHigh = 0
-		}
-
-		if habit.SumMinChew <= -99 {
-			habit.SumMinChew = 0
-		}
-
-		sumChew := habit.SumRumina + habit.SumIntake
-		chew3dago := habit.BeforeThreeSumRumina + habit.BeforeThreeSumIntake
-
-		isWorse := 1
-		if habit.CowId == lastCowID && habit.HeatDate == lastHeatDate && habit.Score >= lastScore {
-			isWorse = 0
-		}
-
-		lastCowID = habit.CowId
-		lastHeatDate = habit.HeatDate
-		lastScore = habit.Score
-
-		if isWorse != 1 {
-			continue
-		}
-		newHealthWarning := model.NewNeckRingHealth(habit, sumChew, chew3dago)
-		healthWarningList = append(healthWarningList, newHealthWarning)
-	}
 	if len(healthWarningList) > 0 {
 		e.updateNeckRingHealth(pastureId, healthWarningList)
 	}