Преглед на файлове

analysis: 治愈率报告

Yi преди 5 месеца
родител
ревизия
001313bb9f

+ 3 - 1
README.md

@@ -38,4 +38,6 @@ todo列表:
 - [ ] 后备牛到达主动停配期后的牛只放在哪个模块(配种清单,发情清单)
 - [ ] 后备牛到达主动停配期后的牛只放在哪个模块(配种清单,发情清单)
 - [ ] 发情清单和配种清单更新机制
 - [ ] 发情清单和配种清单更新机制
 - [ ] 前后端部署架构【k8s,docker-compose,docker-swarm】namespace隔离,需要考虑的问题【1.一次性任务,2. 定时任务 3. 数据收集,4. 日志收集 5. 报警介入】
 - [ ] 前后端部署架构【k8s,docker-compose,docker-swarm】namespace隔离,需要考虑的问题【1.一次性任务,2. 定时任务 3. 数据收集,4. 日志收集 5. 报警介入】
-- [ ] 所有事件录入梳理【批量录入,excel导入,信息人员与操作人员统一规范】
+- [ ] 所有事件录入梳理【批量录入,excel导入,信息人员与操作人员统一规范】
+- [ ] 药品优化成药品名称关联生产商
+- [ ] 框架logrus日志优化【未安装指定天数的日志自动删除】

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 go 1.17
 
 
 require (
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20241029012622-50585ae73c7d
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20241029090643-f4a03baaf55f
 	gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011
 	gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eko/gocache v1.1.0
 	github.com/eko/gocache v1.1.0

+ 8 - 0
go.sum

@@ -42,6 +42,14 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20241028072205-d586542d9487 h1:xeD7qGaA
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241028072205-d586542d9487/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241028072205-d586542d9487/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241029012622-50585ae73c7d h1:VoZSuWA2Q21maenUATF3fBiKIqigkJ31vV+kRrzjjGA=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241029012622-50585ae73c7d h1:VoZSuWA2Q21maenUATF3fBiKIqigkJ31vV+kRrzjjGA=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241029012622-50585ae73c7d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20241029012622-50585ae73c7d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029025035-79916b8f115e h1:PuXEMHLoZH9hG6I6+xS0d/rt0qAmQTlRG6dinjey/sE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029025035-79916b8f115e/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029080158-a9b4822a03ba h1:vsO5PPo/r4lglFPLsrqQ0Vrxp+v6hs8gcK5kpDeI16c=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029080158-a9b4822a03ba/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029081257-b24ca2303d54 h1:M5OBYsBwQuzanqvr19jd2OdS0HPsGUdyymxqBVACtKE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029081257-b24ca2303d54/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029090643-f4a03baaf55f h1:TUKiPo/cMn3pbGcPXGs1UOjc7Ut8B8flRZn5XGW4A7Q=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20241029090643-f4a03baaf55f/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011 h1:jiabQDYcT5PjqyLh57xecf7FpADdWR88+JCrdvBpqfM=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011 h1:jiabQDYcT5PjqyLh57xecf7FpADdWR88+JCrdvBpqfM=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011/go.mod h1:Fk4GYI/v0IK3XFrm1Gn+VkgCz5Y7mfswD5hsTJYOG6A=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241028073848-407d15a8f011/go.mod h1:Fk4GYI/v0IK3XFrm1Gn+VkgCz5Y7mfswD5hsTJYOG6A=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 24 - 0
http/handler/analysis/analysis.go

@@ -200,3 +200,27 @@ func CalvingReport(c *gin.Context) {
 	}
 	}
 	ginutil.JSONResp(c, res)
 	ginutil.JSONResp(c, res)
 }
 }
+
+func DiseaseCureReport(c *gin.Context) {
+	var req pasturePb.DiseaseCureRateRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.StartDayTime, valid.Required),
+		valid.Field(&req.EndDayTime, valid.Required),
+		valid.Field(&req.AnalysisMethod, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.DiseaseCureReport(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}

+ 2 - 2
http/route/analysis_api.go

@@ -18,9 +18,9 @@ func AnalysisAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		pastureRoute.POST("/mating/timely", analysis.MatingTimeLy)
 		pastureRoute.POST("/mating/timely", analysis.MatingTimeLy)
 		pastureRoute.POST("/pen/weight", analysis.PenWeight)
 		pastureRoute.POST("/pen/weight", analysis.PenWeight)
 		pastureRoute.POST("/abortion/rate", analysis.AbortionRate)
 		pastureRoute.POST("/abortion/rate", analysis.AbortionRate)
-
+		pastureRoute.POST("/twenty/one/pregnant/rate", analysis.TwentyOnePregnantRate)
 		pastureRoute.POST("/pregnancy/report", analysis.PregnancyReport)
 		pastureRoute.POST("/pregnancy/report", analysis.PregnancyReport)
 		pastureRoute.POST("/calving/report", analysis.CalvingReport)
 		pastureRoute.POST("/calving/report", analysis.CalvingReport)
-		pastureRoute.POST("/twenty/one/pregnant/rate", analysis.TwentyOnePregnantRate)
+		pastureRoute.POST("/disease/cure/report", analysis.DiseaseCureReport)
 	}
 	}
 }
 }

+ 10 - 9
model/disease.go

@@ -7,15 +7,16 @@ import (
 )
 )
 
 
 type Disease struct {
 type Disease struct {
-	Id          int64                 `json:"id"`
-	Name        string                `json:"name"`
-	Symptoms    string                `json:"symptoms"`
-	DiseaseType int32                 `json:"disease_type"`
-	IsShow      pasturePb.IsShow_Kind `json:"is_show"`
-	Remarks     string                `json:"remarks"`
-	OperationId int64                 `json:"operation_id"`
-	CreatedAt   int64                 `json:"created_at"`
-	UpdatedAt   int64                 `json:"updated_at"`
+	Id              int64                 `json:"id"`
+	Name            string                `json:"name"`
+	Symptoms        string                `json:"symptoms"`
+	DiseaseType     int32                 `json:"disease_type"`
+	DiseaseTypeName string                `json:"disease_type_name"`
+	IsShow          pasturePb.IsShow_Kind `json:"is_show"`
+	Remarks         string                `json:"remarks"`
+	OperationId     int64                 `json:"operation_id"`
+	CreatedAt       int64                 `json:"created_at"`
+	UpdatedAt       int64                 `json:"updated_at"`
 }
 }
 
 
 func (d *Disease) TableName() string {
 func (d *Disease) TableName() string {

+ 19 - 12
model/event_cow_disease.go

@@ -5,15 +5,19 @@ import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 type EventCowDisease struct {
 type EventCowDisease struct {
 	Id                    int64                       `json:"id"`
 	Id                    int64                       `json:"id"`
 	CowId                 int64                       `json:"cowId"`
 	CowId                 int64                       `json:"cowId"`
+	CowType               pasturePb.CowType_Kind      `json:"cowType"`
 	Lact                  int32                       `json:"lact"`
 	Lact                  int32                       `json:"lact"`
 	DayAge                int32                       `json:"dayAge"`
 	DayAge                int32                       `json:"dayAge"`
 	DiseaseId             int32                       `json:"diseaseId"`
 	DiseaseId             int32                       `json:"diseaseId"`
 	DiseaseName           string                      `json:"diseaseName"`
 	DiseaseName           string                      `json:"diseaseName"`
+	DiseaseType           int32                       `json:"diseaseType"`
+	DiseaseTypeName       string                      `json:"diseaseTypeName"`
 	DiagnoseId            int32                       `json:"diagnoseId"`
 	DiagnoseId            int32                       `json:"diagnoseId"`
 	DiagnoseName          string                      `json:"diagnoseName"`
 	DiagnoseName          string                      `json:"diagnoseName"`
 	PenId                 int32                       `json:"penId"`
 	PenId                 int32                       `json:"penId"`
 	HealthStatus          pasturePb.HealthStatus_Kind `json:"healthStatus"`
 	HealthStatus          pasturePb.HealthStatus_Kind `json:"healthStatus"`
 	DiagnosedResult       pasturePb.IsShow_Kind       `json:"diagnosedResult"`
 	DiagnosedResult       pasturePb.IsShow_Kind       `json:"diagnosedResult"`
+	DiagnosedAt           int64                       `json:"diagnosedAt"`
 	DiseaseAt             int64                       `json:"diseaseAt"`
 	DiseaseAt             int64                       `json:"diseaseAt"`
 	Temperature           int32                       `json:"temperature"`
 	Temperature           int32                       `json:"temperature"`
 	Remarks               string                      `json:"remarks"`
 	Remarks               string                      `json:"remarks"`
@@ -32,18 +36,21 @@ func (e *EventCowDisease) TableName() string {
 
 
 func NewEventCowDisease(cow *Cow, disease *Disease, req *pasturePb.EventCowDiseaseRequest, operation *SystemUser) *EventCowDisease {
 func NewEventCowDisease(cow *Cow, disease *Disease, req *pasturePb.EventCowDiseaseRequest, operation *SystemUser) *EventCowDisease {
 	return &EventCowDisease{
 	return &EventCowDisease{
-		CowId:         cow.Id,
-		Lact:          cow.Lact,
-		DayAge:        cow.DayAge,
-		DiseaseId:     int32(disease.Id),
-		DiseaseName:   disease.Name,
-		PenId:         req.PenId,
-		HealthStatus:  pasturePb.HealthStatus_Health,
-		DiseaseAt:     int64(req.DiseaseAt),
-		Temperature:   int32(req.Temperature * 10),
-		OperationId:   int32(operation.Id),
-		OperationName: operation.Name,
-		Remarks:       req.Remarks,
+		CowId:           cow.Id,
+		CowType:         cow.CowType,
+		Lact:            cow.Lact,
+		DayAge:          cow.DayAge,
+		DiseaseId:       int32(disease.Id),
+		DiseaseName:     disease.Name,
+		DiseaseType:     disease.DiseaseType,
+		DiseaseTypeName: disease.DiseaseTypeName,
+		PenId:           req.PenId,
+		HealthStatus:    pasturePb.HealthStatus_Health,
+		DiseaseAt:       int64(req.DiseaseAt),
+		Temperature:     int32(req.Temperature * 10),
+		OperationId:     int32(operation.Id),
+		OperationName:   operation.Name,
+		Remarks:         req.Remarks,
 	}
 	}
 }
 }
 
 

+ 5 - 1
model/event_cow_treatment.go

@@ -15,6 +15,8 @@ type EventCowTreatment struct {
 	CowDiseaseId       int64                          `json:"cowDiseaseId"`
 	CowDiseaseId       int64                          `json:"cowDiseaseId"`
 	DiseaseId          int64                          `json:"diseaseId"`
 	DiseaseId          int64                          `json:"diseaseId"`
 	DiseaseName        string                         `json:"diseaseName"`
 	DiseaseName        string                         `json:"diseaseName"`
+	DiseaseType        int32                          `json:"diseaseType"`
+	DiseaseTypeName    string                         `json:"diseaseTypeName"`
 	PrescriptionId     int32                          `json:"prescriptionId"`
 	PrescriptionId     int32                          `json:"prescriptionId"`
 	PrescriptionName   string                         `json:"prescriptionName"`
 	PrescriptionName   string                         `json:"prescriptionName"`
 	PrescriptionDetail string                         `json:"prescriptionDetail"`
 	PrescriptionDetail string                         `json:"prescriptionDetail"`
@@ -31,13 +33,15 @@ func (e *EventCowTreatment) TableName() string {
 	return "event_cow_treatment"
 	return "event_cow_treatment"
 }
 }
 
 
-func NewEventCowTreatment(prescription *Prescription, req *pasturePb.CowTreatmentRequest, operation *SystemUser) *EventCowTreatment {
+func NewEventCowTreatment(prescription *Prescription, req *pasturePb.CowTreatmentRequest, diseaseTypeMap map[int32]string, operation *SystemUser) *EventCowTreatment {
 	b, _ := json.Marshal(req.PrescriptionDetail)
 	b, _ := json.Marshal(req.PrescriptionDetail)
 	return &EventCowTreatment{
 	return &EventCowTreatment{
 		CowId:              int64(req.CowId),
 		CowId:              int64(req.CowId),
 		CowDiseaseId:       int64(req.Id),
 		CowDiseaseId:       int64(req.Id),
 		DiseaseId:          int64(req.DiseaseId),
 		DiseaseId:          int64(req.DiseaseId),
 		DiseaseName:        req.DiseaseName,
 		DiseaseName:        req.DiseaseName,
+		DiseaseType:        req.DiseaseType,
+		DiseaseTypeName:    diseaseTypeMap[req.DiseaseType],
 		PrescriptionId:     req.PrescriptionId,
 		PrescriptionId:     req.PrescriptionId,
 		PrescriptionName:   prescription.Name,
 		PrescriptionName:   prescription.Name,
 		PrescriptionDetail: string(b),
 		PrescriptionDetail: string(b),

+ 162 - 0
module/backend/analysis_other.go

@@ -164,3 +164,165 @@ func (s *StoreEntry) CalvingReport(ctx context.Context, req *pasturePb.CalvingRe
 		},
 		},
 	}, nil
 	}, nil
 }
 }
+
+func (s *StoreEntry) DiseaseCureReport(ctx context.Context, req *pasturePb.DiseaseCureRateRequest) (*pasturePb.DiseaseCureRateResponse, error) {
+	lastDayOfMonth, err := util.GetLastDayOfMonth(req.EndDayTime)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	endDayTimeUnix := util.TimeParseLocalEndUnix(lastDayOfMonth)
+	startDayTimeUnix := util.TimeParseLocalUnix(fmt.Sprintf("%s-01", req.StartDayTime))
+	if startDayTimeUnix == 0 || endDayTimeUnix == 0 || endDayTimeUnix <= startDayTimeUnix {
+		return nil, xerr.Custom("开始时间不能大于结束时间")
+	}
+
+	diseaseCureRateList1 := make([]*pasturePb.DiseaseCureRateList, 0)
+	diseaseCureRateList2 := make([]*pasturePb.DiseaseCureRateList, 0)
+	pref1 := s.DB.Model(new(model.EventCowDisease)).
+		Select(
+			fmt.Sprint(`DATE_FORMAT(FROM_UNIXTIME(diagnosed_at), '%Y-%m') AS months,`)+
+				fmt.Sprintf(`
+				diagnose_id as disease_id,
+				diagnose_name as disease_name,
+				diagnose_operation_id as operation_id,
+				diagnose_operation_name as operation_name,
+				disease_type,
+				COUNT(DISTINCT CASE WHEN health_status = %d THEN cow_id END) AS disease_treatment_count, -- 治疗头数  
+				COUNT(DISTINCT CASE WHEN health_status = %d AND curable_at > 0 THEN cow_id END) AS disease_cure_count, -- 治愈头数  
+				COUNT(DISTINCT CASE WHEN diagnosed_result = %d THEN cow_id END) AS disease_count, -- 发病数  
+				COUNT(DISTINCT CASE WHEN health_status IN (%d, %d) THEN cow_id END) AS die_out_count, -- 死淘数  
+				COUNT(DISTINCT CASE   
+						   WHEN health_status = %d  
+						   AND TIMESTAMPDIFF(DAY, FROM_UNIXTIME(disease_at), FROM_UNIXTIME(curable_at)) <= 7   
+						   THEN cow_id   
+					   END) AS seven_cure_count, -- 7天内治愈头数  
+				COUNT(DISTINCT CASE   
+						   WHEN health_status = %d  
+						   AND TIMESTAMPDIFF(DAY, FROM_UNIXTIME(disease_at), FROM_UNIXTIME(curable_at)) <= 14   
+						   THEN cow_id   
+					   END) AS seventeen_cure_count, -- 14天内治愈头数 
+				COUNT(DISTINCT CASE   
+						   WHEN health_status = %d  
+						   AND TIMESTAMPDIFF(DAY, FROM_UNIXTIME(disease_at), FROM_UNIXTIME(curable_at)) <= 30  
+						   THEN cow_id   
+					   END) AS thirty_cure_count -- 30天内治愈头数         
+				`, pasturePb.HealthStatus_Treatment, pasturePb.HealthStatus_Curable, pasturePb.IsShow_Ok, pasturePb.HealthStatus_Out,
+					pasturePb.HealthStatus_Dead, pasturePb.HealthStatus_Curable, pasturePb.HealthStatus_Curable, pasturePb.HealthStatus_Curable,
+				)).
+		Where("diagnosed_result = ?", pasturePb.IsShow_Ok).
+		Where("diagnosed_at BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix)
+	if req.CowType > 0 {
+		pref1.Where("cow_type = ?", req.CowType)
+	}
+
+	pref2 := s.DB.Model(new(model.EventCowTreatment)).
+		Select(`
+		DATE_FORMAT(FROM_UNIXTIME(treatment_at), '%Y-%m') AS months,
+		disease_id,
+		disease_name,
+		disease_type,
+		prescription_id,
+		prescription_name,
+		operation_id,
+		operation_name,
+		COUNT(DISTINCT cow_id) AS disease_treatment_count`,
+		).Where("treatment_at BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix)
+
+	switch req.AnalysisMethod {
+	case pasturePb.DiseaseAnalysisMethod_Months:
+		pref1.Where("diagnosed_at > 0").Group("months").Order("months")
+		pref2.Where("treatment_at > 0").Group("months").Order("months")
+	case pasturePb.DiseaseAnalysisMethod_Disease_Category:
+		pref1.Where("disease_type > 0").Group("disease_type").Order("disease_type")
+		pref2.Where("disease_type > 0").Group("disease_type").Order("disease_type")
+	case pasturePb.DiseaseAnalysisMethod_Disease:
+		pref1.Where("diagnose_id > 0").Group("diagnose_id").Order("diagnose_id")
+		pref2.Where("disease_id > 0").Group("disease_id").Order("disease_id")
+	case pasturePb.DiseaseAnalysisMethod_Operator:
+		pref1.Where("diagnose_operation_id > 0").Group("diagnose_operation_id").Order("diagnose_operation_id")
+		pref2.Where("operation_id > 0").Group("operation_id").Order("operation_id")
+	default:
+		return nil, xerr.Custom("请选择统计方式")
+	}
+
+	if err = pref1.Find(&diseaseCureRateList1).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if err = pref2.Find(&diseaseCureRateList2).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	for _, v1 := range diseaseCureRateList1 {
+		for _, v2 := range diseaseCureRateList2 {
+			switch req.AnalysisMethod {
+			case pasturePb.DiseaseAnalysisMethod_Months:
+				if v1.Months != v2.Months {
+					continue
+				}
+				v1.DiseaseTreatmentCount = v2.DiseaseTreatmentCount
+			case pasturePb.DiseaseAnalysisMethod_Disease_Category:
+				if v1.DiseaseType != v2.DiseaseType {
+					continue
+				}
+				v1.DiseaseTreatmentCount = v2.DiseaseTreatmentCount
+			case pasturePb.DiseaseAnalysisMethod_Disease:
+				if v1.DiseaseId != v2.DiseaseId {
+					continue
+				}
+				v1.DiseaseTreatmentCount = v2.DiseaseTreatmentCount
+			case pasturePb.DiseaseAnalysisMethod_Operator:
+				if v1.OperationId != v2.OperationId {
+					continue
+				}
+				v1.DiseaseTreatmentCount = v2.DiseaseTreatmentCount
+			case pasturePb.DiseaseAnalysisMethod_Prescription:
+				if v1.PrescriptionId != v2.PrescriptionId {
+					continue
+				}
+				v1.DiseaseTreatmentCount = v2.DiseaseTreatmentCount
+			}
+		}
+	}
+	chart := &pasturePb.DiseaseCureRateChart{
+		Headers:          make([]string, 0),
+		DiseaseCureCount: make([]int32, 0),
+		DiseaseCureRate:  make([]float32, 0),
+		DiseaseCount:     make([]int32, 0),
+	}
+
+	for _, v := range diseaseCureRateList1 {
+		switch req.AnalysisMethod {
+		case pasturePb.DiseaseAnalysisMethod_Months:
+			v.StatisticMethod = v.Months
+		case pasturePb.DiseaseAnalysisMethod_Disease_Category:
+			diseaseTypeMap := s.DiseaseTypeMap()
+			v.StatisticMethod = diseaseTypeMap[v.DiseaseType]
+		case pasturePb.DiseaseAnalysisMethod_Disease:
+			v.StatisticMethod = v.DiseaseName
+		case pasturePb.DiseaseAnalysisMethod_Operator:
+			v.StatisticMethod = v.OperationName
+		case pasturePb.DiseaseAnalysisMethod_Prescription:
+			v.StatisticMethod = v.PrescriptionName
+		}
+
+		chart.Headers = append(chart.Headers, v.StatisticMethod)
+		chart.DiseaseCureCount = append(chart.DiseaseCureCount, v.DiseaseTreatmentCount)
+		diseaseCureRate := float32(0)
+		if v.DiseaseTreatmentCount > 0 {
+			diseaseCureRate = float32(util.RoundToTwoDecimals(float64(v.DiseaseCureCount) / float64(v.DiseaseCount) * 100))
+		}
+		chart.DiseaseCureRate = append(chart.DiseaseCureRate, diseaseCureRate)
+		chart.DiseaseCount = append(chart.DiseaseCount, v.DiseaseCount)
+	}
+
+	return &pasturePb.DiseaseCureRateResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.DiseaseCureRateData{
+			List:  diseaseCureRateList1,
+			Chart: chart,
+		},
+	}, nil
+}

+ 17 - 0
module/backend/config_data_other.go

@@ -598,3 +598,20 @@ func (s *StoreEntry) DiseaseAnalysisMethodEnumList(isAll string) []*pasturePb.Co
 	})
 	})
 	return configOptions
 	return configOptions
 }
 }
+
+func (s *StoreEntry) diseaseTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configDiseaseTypeList := make([]*model.ConfigDiseaseType, 0)
+	configOptionsList := make([]*pasturePb.ConfigOptionsList, 0)
+	if err := s.DB.Where("is_show = ?", pasturePb.IsShow_Ok).Find(&configDiseaseTypeList).Error; err != nil {
+		zaplog.Error("diseaseTypeEnumList", zap.Any("Find", err))
+	}
+
+	for _, v := range configDiseaseTypeList {
+		configOptionsList = append(configOptionsList, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Id),
+			Label:    v.Name,
+			Disabled: true,
+		})
+	}
+	return configOptionsList
+}

+ 8 - 0
module/backend/enum_map.go

@@ -170,3 +170,11 @@ func (s *StoreEntry) HealthStatusMap() map[pasturePb.HealthStatus_Kind]string {
 	}
 	}
 	return res
 	return res
 }
 }
+
+func (s *StoreEntry) DiseaseTypeMap() map[int32]string {
+	res := make(map[int32]string)
+	for _, v := range s.diseaseTypeEnumList("") {
+		res[v.Value] = v.Label
+	}
+	return res
+}

+ 42 - 50
module/backend/event_health.go

@@ -4,9 +4,7 @@ import (
 	"context"
 	"context"
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"net/http"
 	"net/http"
-
-	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
-	"go.uber.org/zap"
+	"time"
 
 
 	"gorm.io/gorm"
 	"gorm.io/gorm"
 
 
@@ -38,61 +36,58 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 		}
 		}
 	}
 	}
 
 
+	defer func() {
+		s.UpdateCowPenId(ctx, int64(req.CowId), int64(req.PenId))
+	}()
+
 	newEventCowDisease := model.NewEventCowDisease(cow, disease, req, systemUser)
 	newEventCowDisease := model.NewEventCowDisease(cow, disease, req, systemUser)
 	if prescription.Id > 0 {
 	if prescription.Id > 0 {
 		newEventCowDisease.HealthStatus = pasturePb.HealthStatus_Treatment
 		newEventCowDisease.HealthStatus = pasturePb.HealthStatus_Treatment
 	}
 	}
 
 
-	unitMap := s.UnitMap()
-
-	if err = s.DB.Transaction(func(tx *gorm.DB) error {
-		if err = tx.Model(new(model.EventCowDisease)).Create(newEventCowDisease).Error; err != nil {
+	var newEventCowTreatment *model.EventCowTreatment
+	if prescription.Id > 0 {
+		prescriptionDrugs, err := s.PrescriptionDrugsByPrescriptionId(ctx, prescription.Id)
+		if err != nil {
 			return xerr.WithStack(err)
 			return xerr.WithStack(err)
 		}
 		}
-		// 更新牛舍
-		if req.PenId > 0 {
-			if err = tx.Model(new(model.Cow)).
-				Where("id = ?", req.CowId).
-				Updates(map[string]interface{}{
-					"pen_id": req.PenId,
-				}).Error; err != nil {
-				zaplog.Error("CowDiseaseCreate", zap.Any("UpdatePen", err), zap.Any("req", req))
+		unitMap := s.UnitMap()
+		prescriptionDetail := make([]*pasturePb.TreatmentDrugs, len(prescriptionDrugs))
+		for i, v := range prescriptionDrugs {
+			prescriptionDetail[i] = &pasturePb.TreatmentDrugs{
+				DrugsId:   int32(v.DrugsId),
+				DrugsName: v.DrugsName,
+				Unit:      v.Unit,
+				UnitName:  unitMap[v.Unit],
+				UseNum:    float32(v.Dosages),
 			}
 			}
 		}
 		}
 
 
+		newCowTreatmentRequest := &pasturePb.CowTreatmentRequest{
+			CowId:              req.CowId,
+			PrescriptionId:     prescription.Id,
+			DiseaseId:          req.DiseaseId,
+			DiseaseName:        disease.Name,
+			PrescriptionDetail: prescriptionDetail,
+			TreatmentResult:    pasturePb.TreatmentResult_GoOn,
+			Remarks:            "",
+			TreatmentAt:        req.DiseaseAt,
+		}
+		diseaseTypeMap := s.DiseaseTypeMap()
+		newEventCowTreatment = model.NewEventCowTreatment(prescription, newCowTreatmentRequest, diseaseTypeMap, systemUser)
+		newEventCowDisease.DiagnosedAt = int64(req.DiseaseAt)
+	}
+
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		if err = tx.Model(new(model.EventCowDisease)).Create(newEventCowDisease).Error; err != nil {
+			return xerr.WithStack(err)
+		}
 		// 如果有处方Id,则创建治疗记录
 		// 如果有处方Id,则创建治疗记录
 		if prescription.Id > 0 {
 		if prescription.Id > 0 {
-			prescriptionDrugs, err := s.PrescriptionDrugsByPrescriptionId(ctx, prescription.Id)
-			if err != nil {
-				return xerr.WithStack(err)
-			}
-
-			prescriptionDetail := make([]*pasturePb.TreatmentDrugs, len(prescriptionDrugs))
-			for i, v := range prescriptionDrugs {
-				prescriptionDetail[i] = &pasturePb.TreatmentDrugs{
-					DrugsId:   int32(v.DrugsId),
-					DrugsName: v.DrugsName,
-					Unit:      v.Unit,
-					UnitName:  unitMap[v.Unit],
-					UseNum:    float32(v.Dosages),
-				}
-			}
-
-			newEventCowTreatment := model.NewEventCowTreatment(prescription, &pasturePb.CowTreatmentRequest{
-				CowId:              req.CowId,
-				PrescriptionId:     prescription.Id,
-				DiseaseId:          req.DiseaseId,
-				DiseaseName:        disease.Name,
-				PrescriptionDetail: prescriptionDetail,
-				TreatmentResult:    pasturePb.TreatmentResult_GoOn,
-				Remarks:            "",
-				TreatmentAt:        req.DiseaseAt,
-			}, systemUser)
 			// 创建治疗记录
 			// 创建治疗记录
 			if err = tx.Model(new(model.EventCowTreatment)).Create(newEventCowTreatment).Error; err != nil {
 			if err = tx.Model(new(model.EventCowTreatment)).Create(newEventCowTreatment).Error; err != nil {
 				return xerr.WithStack(err)
 				return xerr.WithStack(err)
 			}
 			}
-
 			if err = tx.Model(new(model.Cow)).
 			if err = tx.Model(new(model.Cow)).
 				Where("id = ?", req.CowId).
 				Where("id = ?", req.CowId).
 				Updates(map[string]interface{}{
 				Updates(map[string]interface{}{
@@ -100,14 +95,12 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 				}).Error; err != nil {
 				}).Error; err != nil {
 				return xerr.WithStack(err)
 				return xerr.WithStack(err)
 			}
 			}
-
 		}
 		}
 
 
 		return nil
 		return nil
 	}); err != nil {
 	}); err != nil {
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
@@ -215,10 +208,10 @@ func (s *StoreEntry) CowDiseaseDiagnose(ctx context.Context, req *pasturePb.CowD
 				"diagnosed_result":        pasturePb.IsShow_Ok,
 				"diagnosed_result":        pasturePb.IsShow_Ok,
 				"diagnose_id":             req.DiseaseId,
 				"diagnose_id":             req.DiseaseId,
 				"diagnose_name":           disease.Name,
 				"diagnose_name":           disease.Name,
-				"temperature":             int32(req.Temperature * 10),
+				"temperature":             int32(req.Temperature * 100),
 				"diagnose_operation_id":   req.OperationId,
 				"diagnose_operation_id":   req.OperationId,
 				"diagnose_operation_name": systemUser.Name,
 				"diagnose_operation_name": systemUser.Name,
-				"remarks":                 req.Remarks,
+				"diagnosed_at":            time.Now().Unix(),
 			}).Error; err != nil {
 			}).Error; err != nil {
 			return xerr.WithStack(err)
 			return xerr.WithStack(err)
 		}
 		}
@@ -263,13 +256,13 @@ func (s *StoreEntry) CowDiseaseTreatment(ctx context.Context, req *pasturePb.Cow
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 	req.DiseaseName = disease.Name
 	req.DiseaseName = disease.Name
+	req.DiseaseType = disease.DiseaseType
 	prescriptionDrugs, err := s.PrescriptionDrugsByPrescriptionId(ctx, prescription.Id)
 	prescriptionDrugs, err := s.PrescriptionDrugsByPrescriptionId(ctx, prescription.Id)
 	if err != nil {
 	if err != nil {
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 
 
 	unitMap := s.UnitMap()
 	unitMap := s.UnitMap()
-
 	prescriptionDetail := make([]*pasturePb.TreatmentDrugs, len(prescriptionDrugs))
 	prescriptionDetail := make([]*pasturePb.TreatmentDrugs, len(prescriptionDrugs))
 	for i, v := range prescriptionDrugs {
 	for i, v := range prescriptionDrugs {
 		prescriptionDetail[i] = &pasturePb.TreatmentDrugs{
 		prescriptionDetail[i] = &pasturePb.TreatmentDrugs{
@@ -281,7 +274,6 @@ func (s *StoreEntry) CowDiseaseTreatment(ctx context.Context, req *pasturePb.Cow
 		}
 		}
 	}
 	}
 	req.PrescriptionDetail = prescriptionDetail
 	req.PrescriptionDetail = prescriptionDetail
-
 	healthStatus := pasturePb.HealthStatus_Treatment
 	healthStatus := pasturePb.HealthStatus_Treatment
 	if req.TreatmentResult == pasturePb.TreatmentResult_Curable {
 	if req.TreatmentResult == pasturePb.TreatmentResult_Curable {
 		healthStatus = pasturePb.HealthStatus_Curable
 		healthStatus = pasturePb.HealthStatus_Curable
@@ -294,8 +286,8 @@ func (s *StoreEntry) CowDiseaseTreatment(ctx context.Context, req *pasturePb.Cow
 	if req.TreatmentResult == pasturePb.TreatmentResult_Dead {
 	if req.TreatmentResult == pasturePb.TreatmentResult_Dead {
 		healthStatus = pasturePb.HealthStatus_Dead
 		healthStatus = pasturePb.HealthStatus_Dead
 	}
 	}
-
-	newEventCowTreatment := model.NewEventCowTreatment(prescription, req, systemUser)
+	diseaseTypeMap := s.DiseaseTypeMap()
+	newEventCowTreatment := model.NewEventCowTreatment(prescription, req, diseaseTypeMap, systemUser)
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
 		if err = tx.Create(newEventCowTreatment).Error; err != nil {
 		if err = tx.Create(newEventCowTreatment).Error; err != nil {
 			return xerr.WithStack(err)
 			return xerr.WithStack(err)

+ 1 - 0
module/backend/interface.go

@@ -215,6 +215,7 @@ type AnalyseService interface {
 	TwentyOnePregnantRate(ctx context.Context, req *pasturePb.TwentyOnePregnantRateRequest) (*pasturePb.TwentyOnePregnantRateResponse, error)
 	TwentyOnePregnantRate(ctx context.Context, req *pasturePb.TwentyOnePregnantRateRequest) (*pasturePb.TwentyOnePregnantRateResponse, error)
 	PregnancyReport(ctx context.Context, req *pasturePb.PregnancyReportRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnancyReportResponse, error)
 	PregnancyReport(ctx context.Context, req *pasturePb.PregnancyReportRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnancyReportResponse, error)
 	CalvingReport(ctx context.Context, req *pasturePb.CalvingReportRequest) (*pasturePb.CalvingReportResponse, error)
 	CalvingReport(ctx context.Context, req *pasturePb.CalvingReportRequest) (*pasturePb.CalvingReportResponse, error)
+	DiseaseCureReport(ctx context.Context, req *pasturePb.DiseaseCureRateRequest) (*pasturePb.DiseaseCureRateResponse, error)
 }
 }
 
 
 //go:generate mockgen -destination mock/DashboardService.go -package kptservicemock kpt-pasture/module/backend DashboardService
 //go:generate mockgen -destination mock/DashboardService.go -package kptservicemock kpt-pasture/module/backend DashboardService

+ 18 - 0
module/backend/sql.go

@@ -5,6 +5,9 @@ import (
 	"errors"
 	"errors"
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 
 
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"go.uber.org/zap"
+
 	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
@@ -257,3 +260,18 @@ func (s *StoreEntry) GetSystemBasicByName(ctx context.Context, name string) (*mo
 	}
 	}
 	return systemBasic, nil
 	return systemBasic, nil
 }
 }
+
+// UpdateCowPenId 更新牛舍Id
+func (s *StoreEntry) UpdateCowPenId(ctx context.Context, cowId, penId int64) {
+	if penId == 0 || cowId == 0 {
+		return
+	}
+	cow, err := s.GetCowInfoByCowId(ctx, cowId)
+	if err != nil {
+		zaplog.Error("UpdateCowPenId", zap.Any("cowId", err))
+		return
+	}
+	if err = s.DB.Model(new(model.Cow)).Where("id = ?", cow.Id).Update("pen_id", penId).Error; err != nil {
+		zaplog.Error("UpdateCowPenId", zap.Any("cow_id", cowId), zap.Any("pen_id", penId), zap.Any("err", err))
+	}
+}