|  | @@ -0,0 +1,289 @@
 | 
	
		
			
				|  |  | +package backend
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import (
 | 
	
		
			
				|  |  | +	"context"
 | 
	
		
			
				|  |  | +	"fmt"
 | 
	
		
			
				|  |  | +	"kpt-pasture/model"
 | 
	
		
			
				|  |  | +	"kpt-pasture/util"
 | 
	
		
			
				|  |  | +	"net/http"
 | 
	
		
			
				|  |  | +	"regexp"
 | 
	
		
			
				|  |  | +	"strconv"
 | 
	
		
			
				|  |  | +	"time"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 | 
	
		
			
				|  |  | +	"gitee.com/xuyiping_admin/pkg/xerr"
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *StoreEntry) CalvingCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.CalvingItemsResponse, error) {
 | 
	
		
			
				|  |  | +	userModel, err := s.GetUserModel(ctx)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	calvingItems := make([]*pasturePb.CalvingItems, 0)
 | 
	
		
			
				|  |  | +	count := int64(0)
 | 
	
		
			
				|  |  | +	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())).
 | 
	
		
			
				|  |  | +		Select(`a.id,a.cow_id,a.ear_number,a.status,b.breed_status,b.pen_id,ROUND(b.current_weight/100,2) as current_weight,DATE_FORMAT(FROM_UNIXTIME(last_mating_at), '%Y-%m-%d') AS mating_at_format,
 | 
	
		
			
				|  |  | +		b.day_age,b.last_bull_number as bull_id,b.pen_name,DATEDIFF(NOW(),FROM_UNIXTIME(last_mating_at)) AS mating_age,DATE_FORMAT(FROM_UNIXTIME(a.plan_day), '%Y-%m-%d') AS plan_day`).
 | 
	
		
			
				|  |  | +		Joins("left join cow as b on a.cow_id = b.id").
 | 
	
		
			
				|  |  | +		Where("a.status = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  | +		Where("b.admission_status = ?", pasturePb.AdmissionStatus_Admission).
 | 
	
		
			
				|  |  | +		Where("a.pasture_id = ?", userModel.AppPasture.Id)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.EndDay != "" {
 | 
	
		
			
				|  |  | +		dateTime := util.TimeParseLocalEndUnix(req.EndDay)
 | 
	
		
			
				|  |  | +		pref.Where("a.plan_day <= ?", dateTime)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.PenId > 0 {
 | 
	
		
			
				|  |  | +		pref.Where("b.pen_id = ?", req.PenId)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = pref.Order("a.plan_day DESC").
 | 
	
		
			
				|  |  | +		Count(&count).
 | 
	
		
			
				|  |  | +		Limit(int(pagination.PageSize)).
 | 
	
		
			
				|  |  | +		Offset(int(pagination.PageOffset)).
 | 
	
		
			
				|  |  | +		Find(&calvingItems).Error; err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	breedStatusMap := s.CowBreedStatusMap()
 | 
	
		
			
				|  |  | +	for _, v := range calvingItems {
 | 
	
		
			
				|  |  | +		breedStatusName := ""
 | 
	
		
			
				|  |  | +		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
 | 
	
		
			
				|  |  | +			breedStatusName = breedStatus
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		v.BreedStatusName = breedStatusName
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return &pasturePb.CalvingItemsResponse{
 | 
	
		
			
				|  |  | +		Code: http.StatusOK,
 | 
	
		
			
				|  |  | +		Msg:  "ok",
 | 
	
		
			
				|  |  | +		Data: &pasturePb.CalvingItemsData{
 | 
	
		
			
				|  |  | +			Total:    int32(count),
 | 
	
		
			
				|  |  | +			Page:     pagination.Page,
 | 
	
		
			
				|  |  | +			PageSize: pagination.PageSize,
 | 
	
		
			
				|  |  | +			Header: map[string]string{
 | 
	
		
			
				|  |  | +				"id":              "编号",
 | 
	
		
			
				|  |  | +				"cowId":           "牛号",
 | 
	
		
			
				|  |  | +				"earNumber":       "耳标号",
 | 
	
		
			
				|  |  | +				"breedStatusName": "繁殖状态",
 | 
	
		
			
				|  |  | +				"penName":         "栏舍",
 | 
	
		
			
				|  |  | +				"lact":            "胎次",
 | 
	
		
			
				|  |  | +				"matingAge":       "配后天数",
 | 
	
		
			
				|  |  | +				"dayAge":          "日龄",
 | 
	
		
			
				|  |  | +				"status":          "是否完成",
 | 
	
		
			
				|  |  | +				"bullId":          "配种公牛号",
 | 
	
		
			
				|  |  | +				"planDay":         "预产时间",
 | 
	
		
			
				|  |  | +				"matingAtFormat":  "配种时间",
 | 
	
		
			
				|  |  | +				"currentWeight":   "体重",
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +			List: calvingItems,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +	}, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *StoreEntry) DryMilkCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.DruMilkItemsResponse, error) {
 | 
	
		
			
				|  |  | +	userModel, err := s.GetUserModel(ctx)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	dryMilkItems := make([]*pasturePb.DruMilkItems, 0)
 | 
	
		
			
				|  |  | +	count := int64(0)
 | 
	
		
			
				|  |  | +	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventDryMilk).TableName())).
 | 
	
		
			
				|  |  | +		Select(`a.id,a.cow_id,a.ear_number,a.status,b.breed_status,b.pen_id,b.day_age,b.last_bull_number as bull_number,
 | 
	
		
			
				|  |  | +b.pen_name,DATEDIFF(NOW(),FROM_UNIXTIME(last_mating_at)) AS mating_age,DATE_FORMAT(FROM_UNIXTIME(a.plan_day), '%Y-%m-%d') AS plan_day`).
 | 
	
		
			
				|  |  | +		Joins("left join cow as b on a.cow_id = b.id").
 | 
	
		
			
				|  |  | +		Where("a.status = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  | +		Where("b.admission_status = ?", pasturePb.AdmissionStatus_Admission).
 | 
	
		
			
				|  |  | +		Where("a.pasture_id = ?", userModel.AppPasture.Id)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.EndDay != "" {
 | 
	
		
			
				|  |  | +		dateTime := util.TimeParseLocalEndUnix(req.EndDay)
 | 
	
		
			
				|  |  | +		pref.Where("a.plan_day <= ?", dateTime)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.PenId > 0 {
 | 
	
		
			
				|  |  | +		pref.Where("b.pen_id = ?", req.PenId)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = pref.Order("a.plan_day DESC").
 | 
	
		
			
				|  |  | +		Count(&count).
 | 
	
		
			
				|  |  | +		Limit(int(pagination.PageSize)).
 | 
	
		
			
				|  |  | +		Offset(int(pagination.PageOffset)).
 | 
	
		
			
				|  |  | +		Find(&dryMilkItems).Error; err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	breedStatusMap := s.CowBreedStatusMap()
 | 
	
		
			
				|  |  | +	for _, v := range dryMilkItems {
 | 
	
		
			
				|  |  | +		breedStatusName := ""
 | 
	
		
			
				|  |  | +		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
 | 
	
		
			
				|  |  | +			breedStatusName = breedStatus
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		v.BreedStatusName = breedStatusName
 | 
	
		
			
				|  |  | +		v.CalvingAtFormat = time.Now().AddDate(0, 0, int(systemBasic.MinValue-v.PregnancyAge)).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return &pasturePb.DruMilkItemsResponse{
 | 
	
		
			
				|  |  | +		Code: http.StatusOK,
 | 
	
		
			
				|  |  | +		Msg:  "ok",
 | 
	
		
			
				|  |  | +		Data: &pasturePb.DruMilkItemsData{
 | 
	
		
			
				|  |  | +			Total:    int32(count),
 | 
	
		
			
				|  |  | +			Page:     pagination.Page,
 | 
	
		
			
				|  |  | +			PageSize: pagination.PageSize,
 | 
	
		
			
				|  |  | +			Header: map[string]string{
 | 
	
		
			
				|  |  | +				"id":              "编号",
 | 
	
		
			
				|  |  | +				"cowId":           "牛号",
 | 
	
		
			
				|  |  | +				"earNumber":       "耳标号",
 | 
	
		
			
				|  |  | +				"breedStatusName": "繁殖状态",
 | 
	
		
			
				|  |  | +				"penName":         "栏舍",
 | 
	
		
			
				|  |  | +				"lact":            "胎次",
 | 
	
		
			
				|  |  | +				"pregnancyAge":    "怀孕天数",
 | 
	
		
			
				|  |  | +				"dayAge":          "日龄",
 | 
	
		
			
				|  |  | +				"status":          "是否完成",
 | 
	
		
			
				|  |  | +				"bullNumber":      "配种公牛号",
 | 
	
		
			
				|  |  | +				"planDay":         "干奶时间",
 | 
	
		
			
				|  |  | +				"calvingAtFormat": "预产日期",
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +			List: dryMilkItems,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +	}, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// TreatmentCowList 治疗清单
 | 
	
		
			
				|  |  | +func (s *StoreEntry) TreatmentCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (interface{}, error) {
 | 
	
		
			
				|  |  | +	userModel, err := s.GetUserModel(ctx)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	diseaseItems := make([]*model.EventCowDisease, 0)
 | 
	
		
			
				|  |  | +	count := int64(0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCowDisease).TableName())).
 | 
	
		
			
				|  |  | +		Joins(fmt.Sprintf("JOIN %s AS b on a.cow_id = b.id", new(model.Cow).TableName())).
 | 
	
		
			
				|  |  | +		Where("a.pasture_id = ?", userModel.AppPasture.Id).
 | 
	
		
			
				|  |  | +		Where("a.health_status IN (?)", []pasturePb.HealthStatus_Kind{pasturePb.HealthStatus_Disease, pasturePb.HealthStatus_Treatment})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.PenId > 0 {
 | 
	
		
			
				|  |  | +		pref.Where("b.pen_id = ?", req.PenId)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = pref.Order("a.disease_at DESC").
 | 
	
		
			
				|  |  | +		Count(&count).
 | 
	
		
			
				|  |  | +		Limit(int(pagination.PageSize)).
 | 
	
		
			
				|  |  | +		Offset(int(pagination.PageOffset)).
 | 
	
		
			
				|  |  | +		Find(&diseaseItems).Error; err != nil {
 | 
	
		
			
				|  |  | +		return nil, xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return &pasturePb.EventCowDiseaseResponse{
 | 
	
		
			
				|  |  | +		Code: http.StatusOK,
 | 
	
		
			
				|  |  | +		Msg:  "ok",
 | 
	
		
			
				|  |  | +		Data: &pasturePb.EventCowDiseaseData{
 | 
	
		
			
				|  |  | +			List:     model.EventCowDiseaseSlice(diseaseItems).ToPB(s.HealthStatusMap()),
 | 
	
		
			
				|  |  | +			Total:    int32(count),
 | 
	
		
			
				|  |  | +			PageSize: pagination.PageSize,
 | 
	
		
			
				|  |  | +			Page:     pagination.Page,
 | 
	
		
			
				|  |  | +			Header: map[string]string{
 | 
	
		
			
				|  |  | +				"id":                   "编号",
 | 
	
		
			
				|  |  | +				"cowId":                "牛号",
 | 
	
		
			
				|  |  | +				"earNumber":            "耳标",
 | 
	
		
			
				|  |  | +				"diagnoseName":         "疾病名称",
 | 
	
		
			
				|  |  | +				"healthStatus":         "健康状态",
 | 
	
		
			
				|  |  | +				"lastPrescriptionName": "处方名称",
 | 
	
		
			
				|  |  | +				"treatmentDays":        "治疗天数",
 | 
	
		
			
				|  |  | +				"onsetDays":            "发病天数",
 | 
	
		
			
				|  |  | +				"penName":              "栏舍名称",
 | 
	
		
			
				|  |  | +			},
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +	}, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// WorkOrderCowList 暂时不处理工单业务
 | 
	
		
			
				|  |  | +func (s *StoreEntry) WorkOrderCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (interface{}, error) {
 | 
	
		
			
				|  |  | +	return nil, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Paginate 函数用于对切片进行分页
 | 
	
		
			
				|  |  | +func Paginate(slice []*pasturePb.CalendarToDoList, req *pasturePb.CalendarToDoRequest, pagination *pasturePb.PaginationModel) ([]*pasturePb.CalendarToDoList, int32) {
 | 
	
		
			
				|  |  | +	newSlice := make([]*pasturePb.CalendarToDoList, 0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.CalendarType > 0 {
 | 
	
		
			
				|  |  | +		calendarTypeName := CalendarTypeMap()[req.CalendarType]
 | 
	
		
			
				|  |  | +		if len(calendarTypeName) > 0 {
 | 
	
		
			
				|  |  | +			re := regexp.MustCompile(`[a-zA-Z]`) // 使用正则表达式替换匹配的字母为空字符串
 | 
	
		
			
				|  |  | +			calendarTypeName = re.ReplaceAllString(calendarTypeName, "")
 | 
	
		
			
				|  |  | +			for _, v := range slice {
 | 
	
		
			
				|  |  | +				if v.CalendarTypeName != calendarTypeName {
 | 
	
		
			
				|  |  | +					continue
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				newSlice = append(newSlice, v)
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		newSlice = append(newSlice, slice...)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if req.CowId > 0 {
 | 
	
		
			
				|  |  | +		filteredSlice := make([]*pasturePb.CalendarToDoList, 0)
 | 
	
		
			
				|  |  | +		for _, v := range newSlice {
 | 
	
		
			
				|  |  | +			if v.CowId != req.CowId {
 | 
	
		
			
				|  |  | +				continue
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			filteredSlice = append(filteredSlice, v)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		newSlice = filteredSlice
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	total := int32(len(newSlice))
 | 
	
		
			
				|  |  | +	// 计算起始索引
 | 
	
		
			
				|  |  | +	start := (pagination.Page - 1) * pagination.PageSize
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 如果起始索引超出切片长度,返回空切片
 | 
	
		
			
				|  |  | +	if start >= int32(len(newSlice)) {
 | 
	
		
			
				|  |  | +		return []*pasturePb.CalendarToDoList{}, total
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 计算结束索引
 | 
	
		
			
				|  |  | +	end := start + pagination.PageSize
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 如果结束索引超出切片长度,调整到切片末尾
 | 
	
		
			
				|  |  | +	if end > int32(len(newSlice)) {
 | 
	
		
			
				|  |  | +		end = int32(len(newSlice))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 返回分页后的切片
 | 
	
		
			
				|  |  | +	return newSlice[start:end], total
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func ProgressList(dataList []*pasturePb.CalendarToDoList, toDayCompletedCountMap map[string]int32) map[string]*pasturePb.ProgressList {
 | 
	
		
			
				|  |  | +	res := make(map[string]*pasturePb.ProgressList)
 | 
	
		
			
				|  |  | +	for cn, cc := range toDayCompletedCountMap {
 | 
	
		
			
				|  |  | +		res[cn] = &pasturePb.ProgressList{
 | 
	
		
			
				|  |  | +			CalendarName:   cn,
 | 
	
		
			
				|  |  | +			CompletedCount: cc,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		for _, d := range dataList {
 | 
	
		
			
				|  |  | +			calendarName := CalendarTypeMap()[d.CalendarType]
 | 
	
		
			
				|  |  | +			if calendarName != cn {
 | 
	
		
			
				|  |  | +				continue
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			res[cn].CalendarTypeKind = d.CalendarType
 | 
	
		
			
				|  |  | +			res[cn].IncompleteTotal += 1
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if res[cn].IncompleteTotal > 0 && res[cn].CompletedCount > 0 {
 | 
	
		
			
				|  |  | +			res[cn].Progress = strconv.FormatFloat(float64(res[cn].CompletedCount)/float64(res[cn].IncompleteTotal)*100, 'f', 2, 64)
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			res[cn].Progress = "0%"
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return res
 | 
	
		
			
				|  |  | +}
 |