analysis_breed.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. package backend
  2. import (
  3. "context"
  4. "fmt"
  5. "kpt-pasture/model"
  6. "kpt-pasture/util"
  7. "net/http"
  8. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  9. "gitee.com/xuyiping_admin/pkg/xerr"
  10. )
  11. // SingleFactorInfantSurvivalRateAnalysis 单因素受胎率分析
  12. func (s *StoreEntry) SingleFactorInfantSurvivalRateAnalysis(ctx context.Context, req *pasturePb.SingleFactorPregnancyRateRequest) (*pasturePb.SingleFactorPregnancyRateResponse, error) {
  13. userModel, err := s.GetUserModel(ctx)
  14. if err != nil {
  15. return nil, xerr.WithStack(err)
  16. }
  17. startTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  18. endTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  19. if startTimeUnix == 0 || endTimeUnix == 0 || endTimeUnix <= startTimeUnix {
  20. return nil, xerr.Custom("开始时间不能大于结束时间")
  21. }
  22. list := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  23. chart := &pasturePb.SingleFactorPregnancyRateChart{
  24. Headers: make([]string, 0),
  25. PregnantRate: make([]float32, 0),
  26. MaxValue: make([]int32, 0),
  27. MinValue: make([]int32, 0),
  28. AveragePregnantRate: 0,
  29. }
  30. switch req.AnalysisMethod {
  31. case pasturePb.SingleFactorAnalysisMethod_Cycle:
  32. list, err = s.SingleFactorAnalysisMethodCycle(userModel.AppPasture.Id, req)
  33. case pasturePb.SingleFactorAnalysisMethod_Months:
  34. list, err = s.SingleFactorAnalysisMethodMonths(userModel.AppPasture.Id, req)
  35. case pasturePb.SingleFactorAnalysisMethod_Mating_Times:
  36. list, err = s.SingleFactorAnalysisMethodMatingTimes(userModel.AppPasture.Id, req)
  37. case pasturePb.SingleFactorAnalysisMethod_Breeding_Method:
  38. list, err = s.SingleFactorAnalysisMethodBreeding(userModel.AppPasture.Id, req)
  39. case pasturePb.SingleFactorAnalysisMethod_Breeding_Company:
  40. list, err = s.SingleFactorAnalysisMethodBreedingCompany(userModel.AppPasture.Id, req)
  41. case pasturePb.SingleFactorAnalysisMethod_Operation:
  42. list, err = s.SingleFactorAnalysisMethodOperation(userModel.AppPasture.Id, req)
  43. case pasturePb.SingleFactorAnalysisMethod_Mating_Interval:
  44. list, err = s.SingleFactorAnalysisMethodMatingInterval(userModel.AppPasture.Id, req)
  45. case pasturePb.SingleFactorAnalysisMethod_Bull:
  46. list, err = s.SingleFactorAnalysisMethodBull(userModel.AppPasture.Id, req)
  47. case pasturePb.SingleFactorAnalysisMethod_Breeding_Cycle:
  48. list, err = s.SingleFactorAnalysisMethodBreedingCycle(userModel.AppPasture.Id, req)
  49. case pasturePb.SingleFactorAnalysisMethod_Week:
  50. list, err = s.SingleFactorAnalysisMethodWeek(userModel.AppPasture.Id, req)
  51. case pasturePb.SingleFactorAnalysisMethod_Lact:
  52. list, err = s.SingleFactorAnalysisMethodLact(userModel.AppPasture.Id, req)
  53. default:
  54. return nil, xerr.Custom("错误的统计方式")
  55. }
  56. if err != nil {
  57. return nil, xerr.WithStack(err)
  58. }
  59. totalCountMap := make(map[int]int32, len(list))
  60. allTotalCount := int32(0) // 总头数
  61. allPregnantRate := float64(0) // 总受胎率
  62. for i, v := range list {
  63. chart.Headers = append(chart.Headers, v.StatisticMethod)
  64. pregnantRate := float64(0)
  65. if v.EmptyPregnantCount+v.PregnantCount > 0 {
  66. pregnantRate = float64(v.PregnantCount) / float64(v.EmptyPregnantCount+v.PregnantCount)
  67. }
  68. chart.PregnantRate = append(chart.PregnantRate, float32(util.RoundToTwoDecimals(pregnantRate*100)))
  69. v.TotalCount = v.PregnantCount + v.EmptyPregnantCount + v.OtherCount
  70. v.PregnantRate = float32(util.RoundToTwoDecimals(pregnantRate * 100))
  71. spcRate := float32(0)
  72. if v.PregnantRate > 0 {
  73. spcRate = float32(util.RoundToTwoDecimals((float64(v.PregnantCount) / float64(v.TotalCount)) * 100))
  74. }
  75. v.SpceRate = spcRate
  76. ci95Min, ci95Max := util.ConfidenceInterval2(pregnantRate, float64(v.TotalCount))
  77. v.Ci95 = fmt.Sprintf("%d ~ %d", int32(ci95Min), int32(ci95Max))
  78. chart.MaxValue = append(chart.MaxValue, int32(ci95Max))
  79. chart.MinValue = append(chart.MinValue, int32(ci95Min))
  80. totalCountMap[i] = v.TotalCount
  81. allTotalCount += v.TotalCount
  82. allPregnantRate += pregnantRate
  83. }
  84. for i, v := range totalCountMap {
  85. if allTotalCount <= 0 || list[i].TotalCount <= 0 {
  86. continue
  87. }
  88. list[i].TotalRate = float32(util.RoundToTwoDecimals(float64(v) / float64(allTotalCount) * 100))
  89. }
  90. if len(list) > 0 && allPregnantRate > 0 {
  91. chart.AveragePregnantRate = float32(util.RoundToTwoDecimals(allPregnantRate/float64(len(list))) * 100)
  92. }
  93. return &pasturePb.SingleFactorPregnancyRateResponse{
  94. Code: http.StatusOK,
  95. Msg: "ok",
  96. Data: &pasturePb.SingleFactorPregnancyRateData{
  97. Total: int32(len(list)),
  98. List: list,
  99. Chart: chart,
  100. },
  101. }, nil
  102. }
  103. func (s *StoreEntry) SingleFactorAnalysisMethodCycle(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  104. dateTimeRange, err := util.GetRangeDayByDays(req.StartDayTime, req.EndDayTime, req.Value)
  105. if err != nil {
  106. return nil, xerr.WithStack(err)
  107. }
  108. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  109. selectSql := ""
  110. for _, v := range dateTimeRange {
  111. if len(v) != 2 {
  112. continue
  113. }
  114. startDayTimeUnix := util.TimeParseLocalUnix(v[0])
  115. endDayTimeUnix := util.TimeParseLocalEndUnix(v[1])
  116. selectSql += fmt.Sprintf(`
  117. SELECT
  118. '%s ~ %s' as statistic_method,
  119. COUNT(DISTINCT CASE WHEN mating_result = %d AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  120. COUNT(DISTINCT CASE WHEN mating_result = %d AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  121. COUNT(DISTINCT CASE WHEN mating_result = %d AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  122. COUNT(DISTINCT CASE WHEN mating_result IN (%d, %d) THEN cow_id END) AS other_count, -- 其他数
  123. (
  124. COUNT(DISTINCT CASE WHEN mating_result = %d AND mating_result_at > 0 THEN cow_id END) +
  125. COUNT(DISTINCT CASE WHEN mating_result = %d AND mating_result_at > 0 THEN cow_id END) +
  126. COUNT(DISTINCT CASE WHEN mating_result IN (%d, %d) THEN cow_id END)
  127. ) AS total_count -- 总数
  128. FROM event_mating WHERE pasture_id = %d AND status = %d AND reality_day BETWEEN %d AND %d
  129. UNION ALL `, v[0], v[1], pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  130. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  131. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch,
  132. pastureId, pasturePb.IsShow_Ok, startDayTimeUnix, endDayTimeUnix)
  133. }
  134. if len(selectSql) > 0 {
  135. selectSql = selectSql[:len(selectSql)-len("UNION ALL")-3] + ";"
  136. }
  137. if err = s.DB.Raw(selectSql).Scan(&res).Error; err != nil {
  138. return nil, xerr.WithStack(err)
  139. }
  140. return res, nil
  141. }
  142. func (s *StoreEntry) SingleFactorAnalysisMethodMonths(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  143. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  144. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  145. if startDayTimeUnix == 0 || endDayTimeUnix == 0 || endDayTimeUnix <= startDayTimeUnix {
  146. return nil, xerr.Custom("开始时间不能大于结束时间")
  147. }
  148. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  149. pref := s.DB.Model(new(model.EventMating)).
  150. Select(`
  151. DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m') AS months,
  152. DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m') AS statistic_method,
  153. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  154. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  155. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  156. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  157. (
  158. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  159. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  160. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  161. ) AS total_count -- 总数
  162. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  163. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  164. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch).
  165. Where("status = ?", pasturePb.IsShow_Ok).
  166. Where("pasture_id = ?", pastureId).
  167. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix)
  168. if req.CowType > 0 {
  169. pref.Where("cow_type = ?", req.CowType)
  170. }
  171. if req.CowKind > 0 {
  172. pref.Where("cow_kind = ?", req.CowKind)
  173. }
  174. if req.LactInterval > 0 {
  175. switch req.LactInterval {
  176. case pasturePb.CompareSymbol_Less_Than:
  177. pref.Where("lact < ?", req.LactIntervalStartValue)
  178. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  179. pref.Where("lact <= ?", req.LactIntervalStartValue)
  180. case pasturePb.CompareSymbol_Greater_Than:
  181. pref.Where("lact > ?", req.LactIntervalStartValue)
  182. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  183. pref.Where("lact >= ?", req.LactIntervalStartValue)
  184. case pasturePb.CompareSymbol_Equal_To:
  185. pref.Where("lact = ?", req.LactIntervalStartValue)
  186. case pasturePb.CompareSymbol_Not_Equal_To:
  187. pref.Where("lact != ?", req.LactIntervalStartValue)
  188. case pasturePb.CompareSymbol_Between:
  189. pref.Where("lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  190. default:
  191. return nil, xerr.Custom("错误的胎次区间符号")
  192. }
  193. }
  194. if err := pref.Group("months").Order("months").Find(&res).Error; err != nil {
  195. return nil, xerr.WithStack(err)
  196. }
  197. return res, nil
  198. }
  199. func (s *StoreEntry) SingleFactorAnalysisMethodMatingTimes(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  200. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  201. return res, nil
  202. }
  203. func (s *StoreEntry) SingleFactorAnalysisMethodBreeding(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  204. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  205. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  206. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  207. if err := s.DB.Model(new(model.EventMating)).
  208. Select(`
  209. CASE
  210. WHEN expose_estrus_type = ? THEN '脖环揭发'
  211. WHEN expose_estrus_type = ? THEN '脚环/计步器'
  212. WHEN expose_estrus_type = ? THEN '自然发情'
  213. WHEN expose_estrus_type = ? THEN '同期'
  214. ELSE '未知'
  215. END AS statistic_method,
  216. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  217. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  218. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  219. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  220. (
  221. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  222. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  223. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  224. ) AS total_count -- 总数
  225. `, pasturePb.ExposeEstrusType_Neck_Ring, pasturePb.ExposeEstrusType_Foot_Ring,
  226. pasturePb.ExposeEstrusType_Natural_Estrus, pasturePb.ExposeEstrusType_Same_Time,
  227. pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  228. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  229. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch,
  230. ).Where("status = ?", pasturePb.IsShow_Ok).
  231. Where("pasture_id = ?", pastureId).
  232. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  233. Where("cow_type = ?", req.CowType).
  234. Group("expose_estrus_type").
  235. Order("expose_estrus_type").
  236. Find(&res).Error; err != nil {
  237. return nil, xerr.WithStack(err)
  238. }
  239. return res, nil
  240. }
  241. func (s *StoreEntry) SingleFactorAnalysisMethodBreedingCompany(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  242. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  243. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  244. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  245. pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventMating).TableName())).
  246. Select(`
  247. b.producer AS statistic_method,
  248. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  249. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  250. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  251. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  252. (
  253. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  254. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  255. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  256. ) AS total_count -- 总数
  257. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  258. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  259. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch).
  260. Joins(fmt.Sprintf("left join %s as b on a.frozen_semen_number = b.bull_id ", new(model.FrozenSemen).TableName()))
  261. if req.CowType > 0 {
  262. pref.Where("a.cow_type = ?", req.CowType)
  263. }
  264. if req.CowKind > 0 {
  265. pref.Where("a.cow_kind = ?", req.CowKind)
  266. }
  267. if req.LactInterval > 0 {
  268. switch req.LactInterval {
  269. case pasturePb.CompareSymbol_Less_Than:
  270. pref.Where("a.lact < ?", req.LactIntervalStartValue)
  271. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  272. pref.Where("a.lact <= ?", req.LactIntervalStartValue)
  273. case pasturePb.CompareSymbol_Greater_Than:
  274. pref.Where("a.lact > ?", req.LactIntervalStartValue)
  275. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  276. pref.Where("a.lact >= ?", req.LactIntervalStartValue)
  277. case pasturePb.CompareSymbol_Equal_To:
  278. pref.Where("a.lact = ?", req.LactIntervalStartValue)
  279. case pasturePb.CompareSymbol_Not_Equal_To:
  280. pref.Where("a.lact != ?", req.LactIntervalStartValue)
  281. case pasturePb.CompareSymbol_Between:
  282. pref.Where("a.lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  283. default:
  284. return nil, xerr.Custom("错误的胎次区间符号")
  285. }
  286. }
  287. if err := pref.Where("a.status = ?", pasturePb.IsShow_Ok).Where("pasture_id = ?", pastureId).
  288. Where("a.reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  289. Group("b.producer").
  290. Find(&res).Error; err != nil {
  291. return nil, xerr.WithStack(err)
  292. }
  293. return res, nil
  294. }
  295. func (s *StoreEntry) SingleFactorAnalysisMethodOperation(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  296. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  297. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  298. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  299. pref := s.DB.Model(new(model.EventMating)).Select(`
  300. operation_name AS statistic_method,
  301. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  302. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  303. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  304. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  305. (
  306. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  307. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  308. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  309. ) AS total_count -- 总数
  310. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  311. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  312. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch)
  313. if req.CowType > 0 {
  314. pref.Where("cow_type = ?", req.CowType)
  315. }
  316. if req.CowKind > 0 {
  317. pref.Where("cow_kind = ?", req.CowKind)
  318. }
  319. if req.LactInterval > 0 {
  320. switch req.LactInterval {
  321. case pasturePb.CompareSymbol_Less_Than:
  322. pref.Where("lact < ?", req.LactIntervalStartValue)
  323. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  324. pref.Where("lact <= ?", req.LactIntervalStartValue)
  325. case pasturePb.CompareSymbol_Greater_Than:
  326. pref.Where("lact > ?", req.LactIntervalStartValue)
  327. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  328. pref.Where("lact >= ?", req.LactIntervalStartValue)
  329. case pasturePb.CompareSymbol_Equal_To:
  330. pref.Where("lact = ?", req.LactIntervalStartValue)
  331. case pasturePb.CompareSymbol_Not_Equal_To:
  332. pref.Where("lact != ?", req.LactIntervalStartValue)
  333. case pasturePb.CompareSymbol_Between:
  334. pref.Where("lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  335. default:
  336. return nil, xerr.Custom("错误的胎次区间符号")
  337. }
  338. }
  339. if err := pref.Where("status = ?", pasturePb.IsShow_Ok).
  340. Where("pasture_id = ?", pastureId).
  341. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  342. Group("operation_id").
  343. Find(&res).Error; err != nil {
  344. return nil, xerr.WithStack(err)
  345. }
  346. return res, nil
  347. }
  348. func (s *StoreEntry) SingleFactorAnalysisMethodMatingInterval(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  349. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  350. return res, nil
  351. }
  352. func (s *StoreEntry) SingleFactorAnalysisMethodBull(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  353. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  354. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  355. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  356. pref := s.DB.Model(new(model.EventMating)).
  357. Select(`
  358. frozen_semen_number AS statistic_method,
  359. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  360. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  361. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  362. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  363. (
  364. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  365. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  366. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  367. ) AS total_count -- 总数
  368. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  369. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  370. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch)
  371. if req.CowType > 0 {
  372. pref.Where("cow_type = ?", req.CowType)
  373. }
  374. if req.CowKind > 0 {
  375. pref.Where("cow_kind = ?", req.CowKind)
  376. }
  377. if req.LactInterval > 0 {
  378. switch req.LactInterval {
  379. case pasturePb.CompareSymbol_Less_Than:
  380. pref.Where("lact < ?", req.LactIntervalStartValue)
  381. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  382. pref.Where("lact <= ?", req.LactIntervalStartValue)
  383. case pasturePb.CompareSymbol_Greater_Than:
  384. pref.Where("lact > ?", req.LactIntervalStartValue)
  385. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  386. pref.Where("lact >= ?", req.LactIntervalStartValue)
  387. case pasturePb.CompareSymbol_Equal_To:
  388. pref.Where("lact = ?", req.LactIntervalStartValue)
  389. case pasturePb.CompareSymbol_Not_Equal_To:
  390. pref.Where("lact != ?", req.LactIntervalStartValue)
  391. case pasturePb.CompareSymbol_Between:
  392. pref.Where("lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  393. default:
  394. return nil, xerr.Custom("错误的胎次区间符号")
  395. }
  396. }
  397. if err := pref.Where("status = ?", pasturePb.IsShow_Ok).
  398. Where("pasture_id = ?").
  399. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  400. Group("frozen_semen_number").
  401. Find(&res).Error; err != nil {
  402. return nil, xerr.WithStack(err)
  403. }
  404. return res, nil
  405. }
  406. func (s *StoreEntry) SingleFactorAnalysisMethodBreedingCycle(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  407. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  408. return res, nil
  409. }
  410. func (s *StoreEntry) SingleFactorAnalysisMethodWeek(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  411. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  412. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  413. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  414. pref := s.DB.Model(new(model.EventMating)).
  415. Select(`
  416. CASE
  417. DAYOFWEEK(DATE(FROM_UNIXTIME(reality_day)))
  418. WHEN 2 THEN '星期一'
  419. WHEN 3 THEN '星期二'
  420. WHEN 4 THEN '星期三'
  421. WHEN 5 THEN '星期四'
  422. WHEN 6 THEN '星期五'
  423. WHEN 7 THEN '星期六'
  424. WHEN 1 THEN '星期日'
  425. ELSE '未知'
  426. END AS statistic_method,
  427. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  428. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  429. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  430. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  431. (
  432. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  433. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  434. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  435. ) AS total_count -- 总数
  436. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  437. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  438. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch)
  439. if req.CowType > 0 {
  440. pref.Where("cow_type = ?", req.CowType)
  441. }
  442. if req.CowKind > 0 {
  443. pref.Where("cow_kind = ?", req.CowKind)
  444. }
  445. if req.LactInterval > 0 {
  446. switch req.LactInterval {
  447. case pasturePb.CompareSymbol_Less_Than:
  448. pref.Where("lact < ?", req.LactIntervalStartValue)
  449. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  450. pref.Where("lact <= ?", req.LactIntervalStartValue)
  451. case pasturePb.CompareSymbol_Greater_Than:
  452. pref.Where("lact > ?", req.LactIntervalStartValue)
  453. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  454. pref.Where("lact >= ?", req.LactIntervalStartValue)
  455. case pasturePb.CompareSymbol_Equal_To:
  456. pref.Where("lact = ?", req.LactIntervalStartValue)
  457. case pasturePb.CompareSymbol_Not_Equal_To:
  458. pref.Where("lact != ?", req.LactIntervalStartValue)
  459. case pasturePb.CompareSymbol_Between:
  460. pref.Where("lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  461. default:
  462. return nil, xerr.Custom("错误的胎次区间符号")
  463. }
  464. }
  465. if err := pref.Where("status = ?", pasturePb.IsShow_Ok).
  466. Where("pasture_id = ?", pastureId).
  467. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  468. Group("statistic_method").
  469. Find(&res).Error; err != nil {
  470. return nil, xerr.WithStack(err)
  471. }
  472. return res, nil
  473. }
  474. func (s *StoreEntry) SingleFactorAnalysisMethodLact(pastureId int64, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  475. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  476. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  477. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  478. pref := s.DB.Model(new(model.EventMating)).
  479. Select(`
  480. lact AS statistic_method,
  481. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  482. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  483. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  484. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  485. (
  486. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  487. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  488. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  489. ) AS total_count -- 总数
  490. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  491. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  492. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch)
  493. if req.CowType > 0 {
  494. pref.Where("cow_type = ?", req.CowType)
  495. }
  496. if req.CowKind > 0 {
  497. pref.Where("cow_kind = ?", req.CowKind)
  498. }
  499. if err := pref.Where("status = ?", pasturePb.IsShow_Ok).
  500. Where("pasture_id = ?", pastureId).
  501. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  502. Group("lact").
  503. Find(&res).Error; err != nil {
  504. return nil, xerr.WithStack(err)
  505. }
  506. return res, nil
  507. }
  508. func (s *StoreEntry) MultipleFactorAnalysis(ctx context.Context, req *pasturePb.MultiFactorPregnancyRateRequest) (*model.MultiFactorPregnancyRateResponse, error) {
  509. userModel, err := s.GetUserModel(ctx)
  510. if err != nil {
  511. return nil, err
  512. }
  513. startTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  514. endTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  515. if startTimeUnix == 0 || endTimeUnix == 0 || endTimeUnix <= startTimeUnix {
  516. return nil, xerr.Custom("开始时间不能大于结束时间")
  517. }
  518. if req.XAxle == req.YAxle {
  519. return nil, xerr.Custom("X轴和Y轴不能相同")
  520. }
  521. if req.XAxle == 0 || req.YAxle == 0 {
  522. return nil, xerr.Custom("错误的XY轴数据")
  523. }
  524. pref := s.DB.Model(new(model.EventMating)).
  525. Select(`
  526. DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m') AS months,
  527. operation_name,frozen_semen_number as bull,lact,mating_times,
  528. CASE expose_estrus_type
  529. WHEN 1 THEN '脖环揭发'
  530. WHEN 2 THEN '脚环/计步器'
  531. WHEN 3 THEN '自然发情'
  532. WHEN 4 THEN '同期'
  533. ELSE '未知'
  534. END AS expose_estrus_type,
  535. CASE DAYOFWEEK(DATE(FROM_UNIXTIME(reality_day)))
  536. WHEN 2 THEN '星期一'
  537. WHEN 3 THEN '星期二'
  538. WHEN 4 THEN '星期三'
  539. WHEN 5 THEN '星期四'
  540. WHEN 6 THEN '星期五'
  541. WHEN 7 THEN '星期六'
  542. WHEN 1 THEN '星期日'
  543. ELSE '未知'
  544. END AS week,
  545. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  546. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  547. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  548. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  549. (
  550. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  551. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) +
  552. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END)
  553. ) AS total_count -- 总数
  554. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  555. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch, pasturePb.MatingResult_Pregnant,
  556. pasturePb.MatingResult_Empty, pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch).
  557. Where("pasture_id = ?", userModel.AppPasture.Id).
  558. Where("status = ?", pasturePb.IsShow_Ok).
  559. Where("cow_type = ?", req.CowType).
  560. Where("reality_day BETWEEN ? AND ?", startTimeUnix, endTimeUnix)
  561. if req.LactCompareSymbol > 0 {
  562. switch req.LactCompareSymbol {
  563. case pasturePb.CompareSymbol_Less_Than:
  564. pref.Where("lact < ?", req.LactStartValue)
  565. case pasturePb.CompareSymbol_Less_Than_Or_Equal_To:
  566. pref.Where("lact <= ?", req.LactStartValue)
  567. case pasturePb.CompareSymbol_Greater_Than:
  568. pref.Where("lact > ?", req.LactStartValue)
  569. case pasturePb.CompareSymbol_Greater_Than_Or_Equal_To:
  570. pref.Where("lact >= ?", req.LactStartValue)
  571. case pasturePb.CompareSymbol_Equal_To:
  572. pref.Where("lact = ?", req.LactStartValue)
  573. case pasturePb.CompareSymbol_Not_Equal_To:
  574. pref.Where("lact != ?", req.LactStartValue)
  575. case pasturePb.CompareSymbol_Between:
  576. pref.Where("lact BETWEEN ? AND ? ", req.LactStartValue, req.LactEndValue)
  577. }
  578. }
  579. multiFactorAnalysisMethod := s.MultiFactorAnalysisMethodMap()
  580. groupMap := make(map[string]string)
  581. for k1, v1 := range multiFactorAnalysisMethod {
  582. for k2, v2 := range multiFactorAnalysisMethod {
  583. groupMap[fmt.Sprintf("%d%d", k1, k2)] = fmt.Sprintf("%s,%s", v1, v2)
  584. }
  585. }
  586. list := make([]*model.MultiFactorPregnancyRateList, 0)
  587. if err = pref.Group(groupMap[fmt.Sprintf("%d%d", req.XAxle, req.YAxle)]).
  588. Order(fmt.Sprintf("%s", multiFactorAnalysisMethod[req.XAxle])).Find(&list).Error; err != nil {
  589. return nil, xerr.WithStack(err)
  590. }
  591. chart := &model.MultiFactorPregnancyRateChart{
  592. Header: make([]string, 0),
  593. PregnantRateMap: make(map[string]map[string]string),
  594. }
  595. for _, v := range list {
  596. switch req.XAxle {
  597. case pasturePb.MultiFactorAnalysisMethod_Months:
  598. chart.Header = append(chart.Header, v.Months)
  599. v.StatisticMethod1 = v.Months
  600. case pasturePb.MultiFactorAnalysisMethod_Week:
  601. chart.Header = append(chart.Header, v.Week)
  602. v.StatisticMethod1 = v.Week
  603. case pasturePb.MultiFactorAnalysisMethod_Operation:
  604. chart.Header = append(chart.Header, v.OperationName)
  605. v.StatisticMethod1 = v.OperationName
  606. case pasturePb.MultiFactorAnalysisMethod_Bull:
  607. chart.Header = append(chart.Header, v.Bull)
  608. v.StatisticMethod1 = v.Bull
  609. case pasturePb.MultiFactorAnalysisMethod_Lact:
  610. chart.Header = append(chart.Header, v.Lact)
  611. v.StatisticMethod1 = v.Lact
  612. case pasturePb.MultiFactorAnalysisMethod_Mating_Times:
  613. chart.Header = append(chart.Header, v.MatingTimes)
  614. v.StatisticMethod1 = v.MatingTimes
  615. case pasturePb.MultiFactorAnalysisMethod_Breeding_Method:
  616. chart.Header = append(chart.Header, v.ExposeEstrusType)
  617. v.StatisticMethod1 = v.ExposeEstrusType
  618. }
  619. switch req.YAxle {
  620. case pasturePb.MultiFactorAnalysisMethod_Months:
  621. v.StatisticMethod2 = v.Months
  622. case pasturePb.MultiFactorAnalysisMethod_Week:
  623. v.StatisticMethod2 = v.Week
  624. case pasturePb.MultiFactorAnalysisMethod_Operation:
  625. v.StatisticMethod2 = v.OperationName
  626. case pasturePb.MultiFactorAnalysisMethod_Bull:
  627. v.StatisticMethod2 = v.Bull
  628. case pasturePb.MultiFactorAnalysisMethod_Lact:
  629. v.StatisticMethod2 = v.Lact
  630. case pasturePb.MultiFactorAnalysisMethod_Mating_Times:
  631. v.StatisticMethod2 = v.MatingTimes
  632. case pasturePb.MultiFactorAnalysisMethod_Breeding_Method:
  633. v.StatisticMethod2 = v.ExposeEstrusType
  634. }
  635. if chart.PregnantRateMap[v.StatisticMethod1] == nil {
  636. chart.PregnantRateMap[v.StatisticMethod1] = make(map[string]string)
  637. }
  638. if chart.KepMap == nil {
  639. chart.KepMap = make([]string, 0)
  640. }
  641. pregnantRate := float64(0)
  642. if v.EmptyPregnantCount+v.PregnantCount > 0 {
  643. pregnantRate = float64(v.PregnantCount) / float64(v.EmptyPregnantCount+v.PregnantCount)
  644. }
  645. v.PregnantRate = float32(util.RoundToTwoDecimals(pregnantRate * 100))
  646. spcRate := float32(0)
  647. if v.PregnantRate > 0 {
  648. spcRate = float32(util.RoundToTwoDecimals((float64(v.PregnantCount) / float64(v.TotalCount)) * 100))
  649. }
  650. v.SpcRate = spcRate
  651. chart.PregnantRateMap[v.StatisticMethod1][v.StatisticMethod2] = fmt.Sprintf("%.0f", v.PregnantRate)
  652. chart.KepMap = append(chart.KepMap, v.StatisticMethod2)
  653. }
  654. chart.Header = util.RemoveDuplicates(chart.Header)
  655. chart.KepMap = util.RemoveDuplicates(chart.KepMap)
  656. return &model.MultiFactorPregnancyRateResponse{
  657. Code: http.StatusOK,
  658. Msg: "ok",
  659. Data: &model.MultiFactorPregnancyRateData{
  660. Total: int32(len(list)),
  661. List: list,
  662. Chart: chart,
  663. },
  664. }, nil
  665. }