Procházet zdrojové kódy

indicators: update

Yi před 1 měsícem
rodič
revize
6b8e342d3a

+ 40 - 0
model/indicators_cow.go

@@ -0,0 +1,40 @@
+package model
+
+type IndicatorsCow struct {
+	Id           int64  `json:"id"`
+	PastureId    int64  `json:"pastureId"`
+	IndicatorsId int64  `json:"indicatorsId"`
+	DateTime     string `json:"dateTime"`
+	CowId        int64  `json:"cowId"`
+	EarNumber    string `json:"earNumber"`
+	Lact         int32  `json:"lact"`
+	AdmissionAge int32  `json:"admissionAge"`
+	CalvingAge   int32  `json:"calvingAge"`
+	CreatedAt    int64  `json:"createdAt"`
+	UpdatedAt    int64  `json:"updatedAt"`
+}
+
+func (i *IndicatorsCow) TableName() string {
+	return "indicator_cow"
+}
+
+func NewIndicatorsCow(pastureId int64, indicatorsId int64, dateTime string, cowInfo *Cow) *IndicatorsCow {
+	return &IndicatorsCow{
+		PastureId:    pastureId,
+		IndicatorsId: indicatorsId,
+		DateTime:     dateTime,
+		CowId:        cowInfo.Id,
+		EarNumber:    cowInfo.EarNumber,
+		Lact:         cowInfo.Lact,
+		AdmissionAge: cowInfo.AdmissionAge,
+		CalvingAge:   cowInfo.CalvingAge,
+	}
+}
+
+func NewIndicatorsCowList(pastureId int64, indicatorsId int64, dataTime string, cowList []*Cow) []*IndicatorsCow {
+	res := make([]*IndicatorsCow, 0)
+	for _, cow := range cowList {
+		res = append(res, NewIndicatorsCow(pastureId, indicatorsId, dataTime, cow))
+	}
+	return res
+}

+ 5 - 0
model/indicators_data.go

@@ -64,6 +64,11 @@ const (
 	Lact1PregnancyRate               = "lact1_pregnancy_rate"                  // 1胎受胎率
 	Lact2PregnancyRate               = "lact2_pregnancy_rate"                  // 2胎受孕率
 	Lact3PregnancyRate               = "lact3_pregnancy_rate"                  // >=3胎受孕率
+	FirstMatingPregnancyRate         = "first_mating_pregnancy_rate"           // 第1次配种受胎率
+	SecondMatingPregnancyRate        = "second_mating_pregnancy_rate"          // 第2次配种受胎率
+	Day75DayMatingRate               = "day75_day_mating_rate"                 // 75天配种率(在群)
+	Day75DMonthMatingRate            = "day75_month_mating_rate"               // 75天配种率(月度)
+	AvgAdultCowEmptyNumber           = "avg_adult_cow_empty_number"            // 成母牛平均空怀天数
 )
 
 type IndicatorsData struct {

+ 1 - 1
model/indicators_details.go

@@ -5,7 +5,7 @@ import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 const DefaultFocusIndicators = "all_cow,output_number,input_number,fatten_cattle_number,sales_volume"
 
 type IndicatorsDetails struct {
-	Id           int                          `json:"id"`
+	Id           int64                        `json:"id"`
 	Kind         string                       `json:"kind"`
 	Name         string                       `json:"name"`
 	CategoryType pasturePb.IndicatorType_Kind `json:"categoryType"`

+ 11 - 1
module/crontab/cow_cron.go

@@ -187,6 +187,16 @@ func (e *Entry) Indicators() error {
 			pastureIndicatorList = e.LactPregnancyRate(pastureList, "lact = 2", startTime, endTime)
 		case model.Lact3PregnancyRate:
 			pastureIndicatorList = e.LactPregnancyRate(pastureList, "lact >= 3", startTime, endTime)
+		case model.FirstMatingPregnancyRate:
+			pastureIndicatorList = e.MatingPregnancyRate(pastureList, model.FirstMatingPregnancyRate, startTime, endTime)
+		case model.SecondMatingPregnancyRate:
+			pastureIndicatorList = e.MatingPregnancyRate(pastureList, model.SecondMatingPregnancyRate, startTime, endTime)
+		case model.Day75DayMatingRate:
+			pastureIndicatorList = e.Day75DayMatingRate(pastureList)
+		case model.Day75DMonthMatingRate:
+			pastureIndicatorList = e.Day75MonthMatingRate(pastureList, indicatorsDetail.Id)
+		case model.AvgAdultCowEmptyNumber:
+			pastureIndicatorList = e.AvgAdultCowEmptyNumber(pastureList, startTime, endTime)
 		}
 
 		for pastureId, value := range pastureIndicatorList {
@@ -244,7 +254,7 @@ func (e *Entry) UpdateCowInfoByPasture(pastureId int64) {
 			if err := e.DB.Model(new(model.CowPregnant)).
 				Where("pasture_id = ?", pastureId).
 				Where("date_time = ?", dateTime).
-				Delete(&model.CowPregnant{}).Error; err != nil {
+				Delete(new(model.CowPregnant)).Error; err != nil {
 				zaplog.Error("Crontab", zap.Any("UpdateCowPregnant", err))
 			}
 			if err := e.DB.Model(new(model.CowPregnant)).

+ 228 - 0
module/crontab/cow_indicators_breed_more.go

@@ -3,6 +3,8 @@ package crontab
 import (
 	"fmt"
 	"kpt-pasture/model"
+	"kpt-pasture/util"
+	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
@@ -80,3 +82,229 @@ func (e *Entry) LactPregnancyRate(pastureList []*model.AppPastureList, condition
 	}
 	return res
 }
+
+// MatingPregnancyRate 第1次配种受胎率/第2次配种受胎率
+func (e *Entry) MatingPregnancyRate(pastureList []*model.AppPastureList, kind string, startTime, endTime int64) map[int64]string {
+	res := make(map[int64]string)
+	for _, pasture := range pastureList {
+		if kind != model.FirstMatingPregnancyRate && kind != model.SecondMatingPregnancyRate {
+			res[pasture.Id] = "0"
+			continue
+		}
+
+		var (
+			pregnantCount     int64 // 确认怀孕的
+			realityBreedCount int64 // 参与配种的
+		)
+		pref1 := e.DB.Model(new(model.EventMating)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("status = ?", pasturePb.IsShow_Ok).
+			Where("mating_result = ?", pasturePb.MatingResult_Pregnant).
+			Where("mating_result_at BETWEEN ? AND ?", startTime, endTime)
+
+		if kind == model.FirstMatingPregnancyRate {
+			pref1 = pref1.Where("remating_at = ?", 0)
+		}
+
+		if kind == model.SecondMatingPregnancyRate {
+			pref1 = pref1.Where("remating_at > ?", 0)
+		}
+
+		if err := pref1.Count(&pregnantCount).Error; err != nil {
+			zaplog.Error("pregnantCount", zap.Any("err", err))
+		}
+
+		pref2 := e.DB.Model(new(model.EventMating)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("status = ?", pasturePb.IsShow_Ok).
+			Where("reality_day BETWEEN ? AND ?", startTime, endTime)
+
+		if kind == model.FirstMatingPregnancyRate {
+			pref2 = pref2.Where("remating_at = ?", 0)
+		}
+
+		if kind == model.SecondMatingPregnancyRate {
+			pref2 = pref2.Where("remating_at > ?", 0)
+		}
+
+		if err := pref2.Count(&realityBreedCount).Error; err != nil {
+			zaplog.Error("realityBreedCount", zap.Any("err", err))
+		}
+
+		if realityBreedCount > 0 && pregnantCount > 0 {
+			res[pasture.Id] = fmt.Sprintf("%.2f", float64(pregnantCount)/float64(realityBreedCount))
+		} else {
+			res[pasture.Id] = "0"
+		}
+	}
+	return res
+}
+
+// Day75DayMatingRate 75天配种率(在群)
+func (e *Entry) Day75DayMatingRate(pastureList []*model.AppPastureList) map[int64]string {
+	res := make(map[int64]string)
+	for _, pasture := range pastureList {
+		cowList := make([]*model.Cow, 0)
+		if err := e.DB.Model(new(model.Cow)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("calving_age >= ?", 75).
+			Find(&cowList).Error; err != nil {
+			zaplog.Error("matingCount", zap.Any("err", err))
+		}
+		cowIds := make([]int64, 0)
+		for _, cow := range cowList {
+			cowIds = append(cowIds, cow.Id)
+		}
+
+		var matingCowCount int64
+		if err := e.DB.Model(new(model.EventMating)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("status = ?", pasturePb.IsShow_Ok).
+			Where("cow_id IN ?", cowIds).
+			Where("calving_age < ?", 75).
+			Count(&matingCowCount).Error; err != nil {
+			zaplog.Error("matingCount", zap.Any("err", err))
+		}
+		if len(cowIds) > 0 && matingCowCount > 0 {
+			res[pasture.Id] = fmt.Sprintf("%.2f", float64(matingCowCount)/float64(len(cowIds)))
+		} else {
+			res[pasture.Id] = "0"
+		}
+	}
+	return res
+}
+
+// Day75MonthMatingRate 75天配种率(月度)
+func (e *Entry) Day75MonthMatingRate(pastureList []*model.AppPastureList, indicatorsId int64) map[int64]string {
+	res := make(map[int64]string)
+	nowTime := time.Now().Local()
+	monthStartAt, monthEndAt := util.GetMonthStartAndEndTimestamp()
+
+	nowTimeFormat := nowTime.Format(model.LayoutDate2)
+	monthStartAtFormat := time.Unix(monthStartAt, 0).Local().Format(model.LayoutDate2)
+	monthEndAtFormat := time.Unix(monthEndAt, 0).Local().Format(model.LayoutDate2)
+
+	if nowTimeFormat != monthStartAtFormat || nowTimeFormat != monthEndAtFormat {
+		for _, pasture := range pastureList {
+			res[pasture.Id] = "0"
+		}
+		return res
+	}
+
+	if nowTimeFormat == monthStartAtFormat {
+		for _, pasture := range pastureList {
+			cowList := make([]*model.Cow, 0)
+			if err := e.DB.Model(new(model.Cow)).Where("pasture_id = ?", pasture.Id).
+				Where("calving_age < ?", 75).
+				Where("sex = ?", pasturePb.Genders_Female).
+				Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+				Find(&cowList).Error; err != nil {
+				zaplog.Error("Day75MonthMatingRate", zap.Any("err", err))
+			}
+			if len(cowList) > 0 {
+				newIndicatorsCowList := model.NewIndicatorsCowList(pasture.Id, indicatorsId, nowTimeFormat, cowList)
+				if err := e.DB.Model(new(model.IndicatorsCow)).
+					Create(newIndicatorsCowList).Error; err != nil {
+					zaplog.Error("Day75MonthMatingRate", zap.Any("err", err))
+				}
+			}
+			res[pasture.Id] = "0"
+		}
+		return res
+	}
+
+	if nowTimeFormat == monthEndAtFormat {
+		for _, pasture := range pastureList {
+			indicatorsCowList := make([]*model.IndicatorsCow, 0)
+			if err := e.DB.Model(new(model.IndicatorsCow)).
+				Where("pasture_id = ?", pasture.Id).
+				Where("indicators_id = ?", indicatorsId).
+				Where("date_time = ?", monthStartAtFormat).
+				Find(&indicatorsCowList).Error; err != nil {
+				zaplog.Error("Day75MonthMatingRate", zap.Any("err", err))
+			}
+			cowIds := make([]int64, 0)
+			for _, indicatorsCow := range indicatorsCowList {
+				cowIds = append(cowIds, indicatorsCow.CowId)
+			}
+
+			var historyCowCount int64
+			if err := e.DB.Table(fmt.Sprintf("%s as cow as a", new(model.Cow).TableName())).
+				Joins("LEFT JOIN %s as b on a.id = b.cow_id", new(model.EventMating).TableName()).
+				Where("a.pasture_id = ?", pasture.Id).
+				Where("a.id IN ?", cowIds).
+				Where("b.status = ?", pasturePb.IsShow_Ok).
+				Where("b.calving_age < ?", 75).
+				Where("a.calving_age >= ?", 75).
+				Count(&historyCowCount).Error; err != nil {
+				zaplog.Error("Day75MonthMatingRate", zap.Any("err", err))
+			}
+
+			var currentCowCount int64
+			if err := e.DB.Model(new(model.Cow)).
+				Where("pasture_id = ?", pasture.Id).
+				Where("calving_age >= ?", 75).
+				Where("sex = ?", pasturePb.Genders_Female).
+				Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+				Count(&currentCowCount).Error; err != nil {
+				zaplog.Error("Day75MonthMatingRate", zap.Any("err", err))
+			}
+
+			if currentCowCount > 0 && historyCowCount > 0 {
+				res[pasture.Id] = fmt.Sprintf("%.2f", float64(historyCowCount)/float64(currentCowCount))
+			} else {
+				res[pasture.Id] = "0"
+			}
+		}
+	}
+
+	return res
+}
+
+// AvgAdultCowEmptyNumber 成母牛平均空怀天数
+func (e *Entry) AvgAdultCowEmptyNumber(pastureList []*model.AppPastureList, startTime, endTime int64) map[int64]string {
+	res := make(map[int64]string)
+	for _, pasture := range pastureList {
+		var v = struct {
+			EmptyDays int64
+			CowCount  int64
+		}{
+			EmptyDays: 0,
+			CowCount:  0,
+		}
+
+		if err := e.DB.Model(new(model.Cow)).
+			Select(`
+			SUM(
+				CASE 
+					-- 未孕牛只:空怀天数 = 当前日期 - 产犊日期
+					WHEN is_pregnant = 2 AND last_calving_at > 0 THEN 
+						DATEDIFF(
+							FROM_UNIXTIME(UNIX_TIMESTAMP()), 
+							FROM_UNIXTIME(last_calving_at)
+						)
+					-- 已孕牛只:空怀天数 = 配种结果为怀孕的配种日期 - 产犊日期
+					WHEN is_pregnant = 1 AND last_mating_at > 0 AND last_calving_at > 0 THEN 
+						DATEDIFF(
+							FROM_UNIXTIME(last_mating_at), 
+							FROM_UNIXTIME(last_calving_at)
+						)
+					ELSE 0
+				END
+			) AS empty_days,count(*) AS cow_count`).
+			Where("pasture_id = ?", pasture.Id).
+			Where("sex = ?", pasturePb.Genders_Female).
+			Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+			Where("lact >= ?", 1).
+			First(&v).
+			Error; err != nil {
+			zaplog.Error("AvgAdultCowEmptyNumber", zap.Any("err", err))
+		}
+		if v.CowCount > 0 && v.EmptyDays > 0 {
+			res[pasture.Id] = fmt.Sprintf("%.2f", float64(v.EmptyDays)/float64(v.CowCount))
+		} else {
+			res[pasture.Id] = "0"
+		}
+	}
+	return res
+}