analysis_breed.go 32 KB

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