analysis_breed.go 34 KB

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