feed_service.go 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. package backend
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "kpt-tmr-group/model"
  10. "net/http"
  11. "strconv"
  12. "sync"
  13. "time"
  14. operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
  15. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  16. "gitee.com/xuyiping_admin/pkg/xerr"
  17. "go.uber.org/multierr"
  18. "github.com/xuri/excelize/v2"
  19. "go.uber.org/zap"
  20. "gorm.io/gorm"
  21. )
  22. const EncodeNumberPrefix = "encode_number"
  23. var PastureDataLogType = map[string]int32{
  24. "FeedFormula_Distribute": 1,
  25. "FeedFormula_IsModify": 2,
  26. "FeedFormula_Cancel_Distribute": 3,
  27. }
  28. var EditRecodeMap = map[string]string{
  29. "forage_name": "饲料名称",
  30. "weight": "重量",
  31. "stir_delay": "搅拌延迟",
  32. "allow_error": "允许误差",
  33. "sort": "排序",
  34. }
  35. // CreateFeedFormula 添加数据
  36. func (s *StoreEntry) CreateFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error {
  37. forage := model.NewFeedFormula(req)
  38. if err := s.DB.Create(forage).Error; err != nil {
  39. return xerr.WithStack(err)
  40. }
  41. return nil
  42. }
  43. // EditFeedFormula 编辑数据
  44. func (s *StoreEntry) EditFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error {
  45. feedFormula := &model.FeedFormula{Id: int64(req.Id)}
  46. if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(feedFormula).Error; err != nil {
  47. if errors.Is(err, gorm.ErrRecordNotFound) {
  48. return xerr.Custom("该数据不存在")
  49. }
  50. return xerr.WithStack(err)
  51. }
  52. // 更新版本号
  53. defer s.UpdateFeedFormalVersion(ctx, feedFormula)
  54. updateData := &model.FeedFormula{
  55. Name: req.Name,
  56. Colour: req.Colour,
  57. CattleCategoryId: req.CattleCategoryId,
  58. CattleCategoryName: req.CattleCategoryName,
  59. FormulaTypeId: req.FormulaTypeId,
  60. FormulaTypeName: req.FormulaTypeName,
  61. DataSourceId: req.DataSourceId,
  62. DataSourceName: req.DataSourceName,
  63. Remarks: req.Remarks,
  64. IsShow: req.IsShow,
  65. }
  66. if err := s.DB.Model(new(model.FeedFormula)).
  67. Omit("is_show", "is_delete", "encode_number", "formula_type_id",
  68. "formula_type_name", "data_source", "is_modify").
  69. Where("id = ?", req.Id).
  70. Updates(updateData).Error; err != nil {
  71. return xerr.WithStack(err)
  72. }
  73. return nil
  74. }
  75. // AddFeedByFeedFormula 配方添加饲料
  76. func (s *StoreEntry) AddFeedByFeedFormula(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
  77. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  78. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  79. return xerr.WithStack(err)
  80. }
  81. // 更新修改记录
  82. defer s.addFeedFormulaDetailAddRecode(ctx, req)
  83. // 更新版本号
  84. defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
  85. insertData := make([]*model.FeedFormulaDetail, 0)
  86. for _, v := range req.List {
  87. feedData := &model.Forage{Id: int64(v.ForageId)}
  88. if err := s.DB.Model(new(model.Forage)).First(feedData).Error; err != nil {
  89. return xerr.WithStack(err)
  90. }
  91. if v.AllowError > v.StirDelay {
  92. return xerr.Customf("允许误差不能大于搅拌延迟")
  93. }
  94. insertData = append(insertData, &model.FeedFormulaDetail{
  95. PastureName: "集团",
  96. FeedFormulaId: int64(req.FeedFormulaId),
  97. ForageId: int64(v.ForageId),
  98. ForageName: v.ForageName,
  99. ForageGroupName: v.ForageGroupName,
  100. Weight: int32(v.Weight * 100),
  101. StirDelay: v.StirDelay,
  102. AllowError: v.AllowError,
  103. IsShow: operationPb.IsShow_OK,
  104. IsModify: v.IsModify,
  105. Sort: v.Sort,
  106. })
  107. }
  108. if err := s.DB.Model(new(model.FeedFormulaDetail)).Save(insertData).Error; err != nil {
  109. return xerr.WithStack(err)
  110. }
  111. return nil
  112. }
  113. // addFeedFormulaDetailAddRecode 添加配方记录
  114. func (s *StoreEntry) addFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) {
  115. editRecord, _ := s.GetEditRecordLastGroupId(ctx)
  116. editRecordList := make([]*model.FeedFormulaEditRecord, 0)
  117. for _, v := range req.List {
  118. editRecordList = append(editRecordList, &model.FeedFormulaEditRecord{
  119. FeedFormulaId: int64(req.FeedFormulaId),
  120. PastureName: "集团",
  121. ForageName: v.ForageName,
  122. Status: operationPb.FeedFormulaEditRecordType_INSERT,
  123. GroupId: editRecord.GroupId + 1,
  124. })
  125. }
  126. if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
  127. zaplog.Error("deleteFeedFormulaDetailAddRecode", zap.Any("CreateFeedFormulaEditRecord", err))
  128. }
  129. }
  130. // EditFeedByFeedFormula 配方饲料编辑
  131. func (s *StoreEntry) EditFeedByFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error {
  132. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  133. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  134. return xerr.WithStack(err)
  135. }
  136. feedFormulaDetail := &model.FeedFormulaDetail{Id: int64(req.Id)}
  137. if err := s.DB.Model(new(model.FeedFormulaDetail)).
  138. Where("is_show = ?", operationPb.IsShow_OK).
  139. First(feedFormulaDetail).Error; err != nil {
  140. return xerr.WithStack(err)
  141. }
  142. // 添加修改记录
  143. defer s.editFeedFormulaDetailAddRecode(ctx, req, feedFormulaDetail)
  144. // 更新版本号
  145. defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
  146. // 更新数据
  147. updateData := &model.FeedFormulaDetail{
  148. ForageId: int64(req.ForageId),
  149. ForageName: req.ForageName,
  150. ForageGroupName: req.ForageGroupName,
  151. Weight: int32(req.Weight * 100),
  152. StirDelay: req.StirDelay,
  153. AllowError: req.AllowError,
  154. Sort: req.Sort,
  155. }
  156. if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("id = ?", req.Id).Updates(updateData).Error; err != nil {
  157. return xerr.WithStack(err)
  158. }
  159. return nil
  160. }
  161. // EditFeedFormulaDetailAddRecode 更新饲料配方修改记录
  162. func (s *StoreEntry) editFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.AddFeedFormulaDetail, feedFormulaDetail *model.FeedFormulaDetail) {
  163. editRecordList := make([]*model.FeedFormulaEditRecord, 0)
  164. editRecordData := &model.FeedFormulaEditRecord{
  165. FeedFormulaId: int64(req.FeedFormulaId),
  166. PastureName: "集团",
  167. ForageName: req.ForageName,
  168. Status: operationPb.FeedFormulaEditRecordType_UPDATE,
  169. }
  170. if operationName, err := s.GetCurrentUserName(ctx); err != nil {
  171. zaplog.Error("EditFeedByFeedFormula", zap.Any("GetCurrentUserName", err))
  172. } else {
  173. editRecordData.OperationName = operationName
  174. }
  175. lastGroupIdData := &model.FeedFormulaEditRecord{}
  176. if err := s.DB.Model(new(model.FeedFormulaEditRecord)).
  177. Where("is_show = ?", operationPb.IsShow_OK).
  178. Order("group_id desc").
  179. First(&lastGroupIdData).Error; err != nil {
  180. zaplog.Error("EditFeedByFeedFormula", zap.Any("lastGroupIdData", err))
  181. } else {
  182. editRecordData.GroupId = lastGroupIdData.GroupId + 1
  183. editRecordData.BeforeValue = lastGroupIdData.BeforeValue
  184. }
  185. if feedFormulaDetail.ForageName != req.ForageName {
  186. editRecordData.FieldName = EditRecodeMap["forage_name"]
  187. editRecordData.BeforeValue = lastGroupIdData.ForageName
  188. editRecordData.AfterValue = req.ForageName
  189. editRecordList = append(editRecordList, editRecordData)
  190. }
  191. if feedFormulaDetail.Weight != int32(req.Weight*100) {
  192. editRecordData.FieldName = EditRecodeMap["weight"]
  193. editRecordData.AfterValue = fmt.Sprintf("%d", int32(req.Weight*100))
  194. editRecordList = append(editRecordList, editRecordData)
  195. }
  196. if feedFormulaDetail.AllowError != req.AllowError {
  197. editRecordData.FieldName = EditRecodeMap["allow_error"]
  198. editRecordData.AfterValue = fmt.Sprintf("%d", req.AllowError)
  199. editRecordList = append(editRecordList, editRecordData)
  200. }
  201. if feedFormulaDetail.StirDelay != req.StirDelay {
  202. editRecordData.FieldName = EditRecodeMap["stir_delay"]
  203. editRecordData.AfterValue = fmt.Sprintf("%d", req.StirDelay)
  204. editRecordList = append(editRecordList, editRecordData)
  205. }
  206. if feedFormulaDetail.Sort != req.Sort {
  207. editRecordData.FieldName = EditRecodeMap["sort"]
  208. editRecordData.AfterValue = fmt.Sprintf("%d", req.Sort)
  209. editRecordList = append(editRecordList, editRecordData)
  210. }
  211. if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
  212. zaplog.Error("EditFeedByFeedFormula", zap.Any("CreateFeedFormulaEditRecord", err))
  213. }
  214. }
  215. // CreateFeedFormulaEditRecord 创建配方修改记录
  216. func (s *StoreEntry) CreateFeedFormulaEditRecord(ctx context.Context, req []*model.FeedFormulaEditRecord) error {
  217. if req == nil {
  218. return nil
  219. }
  220. if err := s.DB.Model(new(model.FeedFormulaEditRecord)).Save(req).Error; err != nil {
  221. return xerr.WithStack(err)
  222. }
  223. return nil
  224. }
  225. // FeedFormulaDetailBySort 配方饲料排序
  226. func (s *StoreEntry) FeedFormulaDetailBySort(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
  227. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  228. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  229. return xerr.WithStack(err)
  230. }
  231. // 更新版本号
  232. defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
  233. tx := s.DB.Transaction(func(tx *gorm.DB) error {
  234. for _, v := range req.List {
  235. if err := tx.Model(new(model.FeedFormulaDetail)).
  236. Where("id = ?", v.Id).
  237. Updates(map[string]interface{}{
  238. "sort": v.Sort,
  239. }).Error; err != nil {
  240. return xerr.WithStack(err)
  241. }
  242. }
  243. return nil
  244. })
  245. return tx
  246. }
  247. // FeedFormulaDetailIsModify 配方饲料是否可修改
  248. func (s *StoreEntry) FeedFormulaDetailIsModify(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error {
  249. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  250. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  251. return xerr.WithStack(err)
  252. }
  253. // 更新版本号
  254. defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
  255. return s.DB.Model(new(model.FeedFormulaDetail)).
  256. Where("id = ?", req.Id).
  257. Where("feed_formula_id = ?", req.FeedFormulaId).
  258. Updates(map[string]interface{}{
  259. "is_modify": req.IsModify,
  260. }).Error
  261. }
  262. // DeleteFeedFormulaDetail 配方删除饲料
  263. func (s *StoreEntry) DeleteFeedFormulaDetail(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
  264. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  265. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  266. return xerr.WithStack(err)
  267. }
  268. // 增加配方记录
  269. defer s.deleteFeedFormulaDetailAddRecode(ctx, req)
  270. tr := s.DB.Transaction(func(tx *gorm.DB) error {
  271. for _, v := range req.List {
  272. if err := tx.Model(new(model.FeedFormulaDetail)).
  273. Where("id = ?", v.Id).
  274. Updates(map[string]interface{}{
  275. "is_show": operationPb.IsShow_NO,
  276. }).Error; err != nil {
  277. return xerr.WithStack(err)
  278. }
  279. }
  280. return nil
  281. })
  282. return tr
  283. }
  284. // deleteFeedFormulaDetailAddRecode 删除配方增加修改记录
  285. func (s *StoreEntry) deleteFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) {
  286. editRecordList := make([]*model.FeedFormulaEditRecord, 0)
  287. for _, v := range req.List {
  288. editRecordList = append(editRecordList, &model.FeedFormulaEditRecord{
  289. FeedFormulaId: int64(req.FeedFormulaId),
  290. PastureName: "集团",
  291. ForageName: v.ForageName,
  292. Status: operationPb.FeedFormulaEditRecordType_DELETE,
  293. })
  294. }
  295. if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
  296. zaplog.Error("deleteFeedFormulaDetailAddRecode", zap.Any("CreateFeedFormulaEditRecord", err))
  297. }
  298. }
  299. // SearchFeedFormulaDetail 查询配方饲料详情
  300. func (s *StoreEntry) SearchFeedFormulaDetail(ctx context.Context, req *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error) {
  301. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  302. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Debug().Error; err != nil {
  303. return nil, xerr.WithStack(err)
  304. }
  305. var count int64
  306. feedFormulaDetailList := make([]*model.FeedFormulaDetail, 0)
  307. pref := s.DB.Model(new(model.FeedFormulaDetail)).
  308. Where("is_show = ?", operationPb.IsShow_OK).
  309. Where("feed_formula_id = ?", req.FeedFormulaId)
  310. if req.ForageName != "" {
  311. pref.Where("forage_name = ?", req.ForageName)
  312. }
  313. if req.ForageGroupName != "" {
  314. pref.Where("forage_group_name = ?", req.ForageGroupName)
  315. }
  316. if req.Weight > 0 {
  317. pref.Where("weight = ?", int64(req.Weight*100))
  318. }
  319. if req.IsLockCowCountRatio > 0 {
  320. pref.Where("is_lock_cow_count_ratio = ?", req.IsLockCowCountRatio)
  321. }
  322. if req.StirDelay > 0 {
  323. pref.Where("stir_delay = ?", req.StirDelay)
  324. }
  325. if req.Sort > 0 {
  326. pref.Where("sort = ?", req.Sort)
  327. }
  328. if err := pref.Order("sort").Count(&count).Limit(int(req.Pagination.PageSize)).
  329. Offset(int(req.Pagination.PageOffset)).Find(&feedFormulaDetailList).Debug().Error; err != nil {
  330. return nil, xerr.WithStack(err)
  331. }
  332. return &operationPb.FeedFormulaDetailResponse{
  333. Code: http.StatusOK,
  334. Msg: "ok",
  335. Data: model.FeedFormulaDetailSlice(feedFormulaDetailList).ToPB(),
  336. }, nil
  337. }
  338. // MixedFeedFormula 合成预混料
  339. func (s *StoreEntry) MixedFeedFormula(ctx context.Context, req *operationPb.MixedFeedFormulaRequest) error {
  340. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  341. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  342. return xerr.WithStack(err)
  343. }
  344. if feedFormulaData.FormulaTypeId == operationPb.FormulaType_PREMIXED_FORMULA {
  345. return xerr.Customf("预混料配方不能合成预混料")
  346. }
  347. tr := s.DB.Transaction(func(tx *gorm.DB) error {
  348. newFeedFormulaData := model.NewNewFeedFormulaByMixed(req)
  349. newFeedFormulaData.EncodeNumber = s.EncodeNumber(ctx)
  350. if err := s.DB.Model(new(model.FeedFormula)).Create(newFeedFormulaData).Error; err != nil {
  351. return xerr.WithStack(err)
  352. }
  353. feedFormulaDetailList := make([]*model.FeedFormulaDetail, 0)
  354. for _, v := range req.FeedList {
  355. feedFormulaDetailList = append(feedFormulaDetailList, &model.FeedFormulaDetail{
  356. PastureName: "集团",
  357. FeedFormulaId: newFeedFormulaData.Id,
  358. ForageId: int64(v.ForageId),
  359. ForageName: v.ForageName,
  360. ForageGroupName: v.ForageGroupName,
  361. Weight: int32(v.Weight * 100),
  362. StirDelay: v.StirDelay,
  363. AllowError: v.AllowError,
  364. IsShow: operationPb.IsShow_OK,
  365. Sort: v.Sort,
  366. })
  367. }
  368. if err := s.DB.Model(new(model.FeedFormulaDetail)).Save(feedFormulaDetailList).Error; err != nil {
  369. return xerr.WithStack(err)
  370. }
  371. return nil
  372. })
  373. return tr
  374. }
  375. // SearchFeedFormulaList 查询数据列表
  376. func (s *StoreEntry) SearchFeedFormulaList(ctx context.Context, req *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error) {
  377. feedFormula := make([]*model.FeedFormula, 0)
  378. var count int64 = 0
  379. pref := s.DB.Model(new(model.FeedFormula)).Where("is_delete = ?", operationPb.IsShow_OK)
  380. if req.Name != "" {
  381. pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
  382. }
  383. if req.CattleCategoryId > 0 {
  384. pref.Where("cattle_category_id = ?", req.CattleCategoryId)
  385. }
  386. if req.FormulaTypeId > 0 {
  387. pref.Where("formula_type_id = ?", req.FormulaTypeId)
  388. }
  389. if req.IsShow > 0 {
  390. pref.Where("is_show = ?", req.IsShow)
  391. }
  392. if req.DataSource > 0 {
  393. pref.Where("data_source = ?", req.DataSource)
  394. }
  395. if req.Remarks != "" {
  396. pref.Where("remarks = ?", req.Remarks)
  397. }
  398. if err := pref.Order("id desc").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)).
  399. Find(&feedFormula).Error; err != nil {
  400. return nil, xerr.WithStack(err)
  401. }
  402. return &operationPb.SearchFeedFormulaListResponse{
  403. Code: http.StatusOK,
  404. Msg: "ok",
  405. Data: &operationPb.SearchFeedFormulaListData{
  406. Page: req.Pagination.Page,
  407. PageSize: req.Pagination.PageSize,
  408. Total: int32(count),
  409. List: model.FeedFormulaSlice(feedFormula).ToPB(),
  410. },
  411. }, nil
  412. }
  413. // SearchFeedFormulaById 查询指定数据
  414. func (s *StoreEntry) SearchFeedFormulaById(ctx context.Context, foodFormulaId int64) (*model.FeedFormula, error) {
  415. feedFormula := &model.FeedFormula{}
  416. if err := s.DB.Model(new(model.FeedFormula)).
  417. Where("is_delete = ?", operationPb.IsShow_OK).
  418. Where("id = ?", foodFormulaId).
  419. First(feedFormula).Error; err != nil {
  420. return nil, xerr.WithStack(err)
  421. }
  422. return feedFormula, nil
  423. }
  424. // IsShowFeedFormula 是否启用和是否可修改
  425. func (s *StoreEntry) IsShowFeedFormula(ctx context.Context, req *operationPb.IsShowModifyFeedFormula) error {
  426. feedFormula := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  427. if err := s.DB.First(feedFormula).Error; err != nil {
  428. if errors.Is(err, gorm.ErrRecordNotFound) {
  429. return xerr.Custom("该数据不存在")
  430. }
  431. return xerr.WithStack(err)
  432. }
  433. if req.EditType == 1 {
  434. if err := s.DB.Model(new(model.FeedFormula)).Where("id = ?", req.FeedFormulaId).Update("is_show", req.IsShow).Error; err != nil {
  435. return xerr.WithStack(err)
  436. }
  437. }
  438. if req.EditType == 2 {
  439. if err := s.DB.Model(new(model.FeedFormula)).Where("id = ?", req.FeedFormulaId).Update("is_modify", req.IsShow).Error; err != nil {
  440. return xerr.WithStack(err)
  441. } else {
  442. s.PastureFeedFormulaIsModify(ctx, req.FeedFormulaId, req.IsShow)
  443. }
  444. }
  445. return nil
  446. }
  447. // DeleteFeedFormula 是否删除
  448. func (s *StoreEntry) DeleteFeedFormula(ctx context.Context, feedFormulaId int64) error {
  449. feedFormula := &model.FeedFormula{Id: feedFormulaId}
  450. if err := s.DB.First(feedFormula).Error; err != nil {
  451. if errors.Is(err, gorm.ErrRecordNotFound) {
  452. return xerr.Custom("该数据不存在")
  453. }
  454. return xerr.WithStack(err)
  455. }
  456. if err := s.DB.Model(new(model.FeedFormula)).Where("id = ?", feedFormula.Id).Update("is_delete", operationPb.IsShow_NO).Error; err != nil {
  457. return xerr.WithStack(err)
  458. }
  459. return nil
  460. }
  461. // ExcelImportFeedFormula 导入excel
  462. func (s *StoreEntry) ExcelImportFeedFormula(ctx context.Context, req io.Reader) error {
  463. xlsx, err := excelize.OpenReader(req)
  464. if err != nil {
  465. return xerr.WithStack(err)
  466. }
  467. defer xlsx.Close()
  468. rows, err := xlsx.GetRows(xlsx.GetSheetName(xlsx.GetActiveSheetIndex()))
  469. if err != nil {
  470. return xerr.WithStack(err)
  471. }
  472. if len(rows) > 10000 {
  473. rows = rows[:10000]
  474. }
  475. feedFormulaList := make([]*model.FeedFormula, 0)
  476. for i, row := range rows {
  477. if i == 0 {
  478. continue
  479. }
  480. var (
  481. name, encodeNumber, cattleCategoryName, formulaTypeName, dataSourceName, remarks, isShowStr string
  482. isShow operationPb.IsShow_Kind
  483. )
  484. for k, v := range row {
  485. if k == 0 {
  486. name = v
  487. }
  488. if k == 1 {
  489. encodeNumber = v
  490. }
  491. if k == 2 {
  492. cattleCategoryName = v
  493. }
  494. if k == 3 {
  495. formulaTypeName = v
  496. }
  497. if k == 4 {
  498. dataSourceName = v
  499. }
  500. if k == 5 {
  501. remarks = v
  502. }
  503. if k == 6 {
  504. isShowStr = v
  505. }
  506. }
  507. if isShowStr == "是" {
  508. isShow = operationPb.IsShow_OK
  509. } else {
  510. isShow = operationPb.IsShow_NO
  511. }
  512. feedFormulaItem := &model.FeedFormula{
  513. Name: name,
  514. EncodeNumber: encodeNumber,
  515. CattleCategoryName: cattleCategoryName,
  516. FormulaTypeName: formulaTypeName,
  517. Remarks: remarks,
  518. IsShow: isShow,
  519. IsDelete: operationPb.IsShow_OK,
  520. DataSourceId: operationPb.DataSource_EXCEL_IMPORT,
  521. DataSourceName: dataSourceName,
  522. }
  523. feedFormulaList = append(feedFormulaList, feedFormulaItem)
  524. }
  525. if len(feedFormulaList) > 0 {
  526. if err = s.DB.Create(feedFormulaList).Error; err != nil {
  527. return xerr.WithStack(err)
  528. }
  529. }
  530. return nil
  531. }
  532. // ExcelExportFeedFormula 流式导出excel
  533. func (s *StoreEntry) ExcelExportFeedFormula(ctx context.Context, req *operationPb.SearchFeedFormulaRequest) (*bytes.Buffer, error) {
  534. res, err := s.SearchFeedFormulaList(ctx, req)
  535. if err != nil {
  536. return nil, xerr.WithStack(err)
  537. }
  538. if len(res.Data.List) <= 0 {
  539. return nil, xerr.Custom("数据为空")
  540. }
  541. file := excelize.NewFile()
  542. defer file.Close()
  543. streamWriter, err := file.NewStreamWriter("Sheet1")
  544. if err != nil {
  545. return nil, xerr.WithStack(err)
  546. }
  547. titles := []interface{}{"配方名称", "配方编码", "畜牧类别", "配方类别", "来源", "备注", "是否启用",
  548. "饲料组", "饲料名称", "重量(kg)", "搅拌延迟(min)", "是否锁定牛头数比例", "顺序"}
  549. if err = streamWriter.SetRow("A1", titles); err != nil {
  550. return nil, xerr.WithStack(err)
  551. }
  552. for i, item := range res.Data.List {
  553. cell, err := excelize.CoordinatesToCellName(1, i+2)
  554. if err != nil {
  555. zaplog.Error("exclude CoordinatesToCellName", zap.Any("Err", err))
  556. continue
  557. }
  558. row := make([]interface{}, 0)
  559. row = append(row, item.Name, item.EncodeNumber, item.CattleCategoryName, item.FormulaTypeName, item.DataSourceName,
  560. item.Remarks, item.IsShow)
  561. if err = streamWriter.SetRow(cell, row); err != nil {
  562. return nil, xerr.WithStack(err)
  563. }
  564. }
  565. if err = streamWriter.Flush(); err != nil {
  566. return nil, xerr.WithStack(err)
  567. }
  568. return file.WriteToBuffer()
  569. }
  570. // ExcelTemplateFeedFormula 导出模板
  571. func (s *StoreEntry) ExcelTemplateFeedFormula(ctx context.Context) (*bytes.Buffer, error) {
  572. file := excelize.NewFile()
  573. defer file.Close()
  574. streamWriter, err := file.NewStreamWriter("Sheet1")
  575. if err != nil {
  576. return nil, xerr.WithStack(err)
  577. }
  578. titles := []interface{}{"配方名称", "配方编码", "畜牧类别", "配方类别", "来源", "备注", "是否启用",
  579. "饲料组", "饲料名称", "重量(kg)", "搅拌延迟(min)", "是否锁定牛头数比例", "顺序"}
  580. if err = streamWriter.SetRow("A1", titles); err != nil {
  581. return nil, xerr.WithStack(err)
  582. }
  583. if err = streamWriter.Flush(); err != nil {
  584. return nil, xerr.WithStack(err)
  585. }
  586. return file.WriteToBuffer()
  587. }
  588. // EncodeNumber 配方编码
  589. func (s *StoreEntry) EncodeNumber(ctx context.Context) string {
  590. currTime := time.Now().Format(model.LayoutDate)
  591. prefix := fmt.Sprintf("%s_%s", EncodeNumberPrefix, currTime)
  592. data := &model.UniqueData{}
  593. if err := s.DB.Order("id desc").Where("prefix = ?", prefix).First(data).Error; err != nil {
  594. if !errors.Is(err, gorm.ErrRecordNotFound) {
  595. return ""
  596. }
  597. ud, _ := strconv.Atoi(currTime)
  598. result := ud*100 + 1
  599. newData := &model.UniqueData{
  600. Prefix: prefix,
  601. Data: int64(result),
  602. }
  603. if err = s.DB.Create(newData).Error; err != nil {
  604. zaplog.Error("EncodeNumber Create", zap.Any("data", newData), zap.Any("Err", err))
  605. return ""
  606. }
  607. return fmt.Sprintf("%d", newData.Data)
  608. }
  609. data.Data += 1
  610. if err := s.DB.Model(new(model.UniqueData)).Where("prefix = ?", prefix).Update("data", data.Data).Error; err != nil {
  611. return ""
  612. } else {
  613. return fmt.Sprintf("%d", data.Data)
  614. }
  615. }
  616. // DistributeFeedFormula 配方下发牧场
  617. func (s *StoreEntry) DistributeFeedFormula(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) error {
  618. distributeData, err := s.checkoutDistributeData(ctx, req)
  619. if err != nil {
  620. return xerr.WithStack(err)
  621. }
  622. wg := sync.WaitGroup{}
  623. wg.Add(len(distributeData.PastureList))
  624. var muError error
  625. for _, pasture := range distributeData.PastureList {
  626. go func(p *operationPb.AddPastureRequest) {
  627. defer wg.Done()
  628. // 过滤掉自己本牧场上报的配方数据
  629. newDistributeFeedRequest := make([]*operationPb.DistributeFeedRequest, 0)
  630. for _, v := range distributeData.FeedFormulaList {
  631. if v.PastureId != p.Id {
  632. newDistributeFeedRequest = append(newDistributeFeedRequest, v)
  633. }
  634. }
  635. if len(newDistributeFeedRequest) <= 0 {
  636. return
  637. }
  638. // 过滤掉已经下发过配方
  639. putDistributeFeedRequest := make([]*operationPb.DistributeFeedRequest, 0)
  640. for _, v := range newDistributeFeedRequest {
  641. if !s.CheckFeedFormulaDistribute(ctx, int64(p.Id), int64(v.Id)) {
  642. putDistributeFeedRequest = append(putDistributeFeedRequest, v)
  643. }
  644. }
  645. if len(putDistributeFeedRequest) <= 0 {
  646. return
  647. }
  648. // 请求参数
  649. request, response := &operationPb.DistributeDataRequest{
  650. PastureId: p.PastureId,
  651. FeedFormulaList: newDistributeFeedRequest,
  652. }, &model.PastureResponse{
  653. Code: 0,
  654. Msg: "",
  655. Data: &model.PastureSuccess{Success: false},
  656. }
  657. defer func() {
  658. if response.Code == http.StatusOK {
  659. feedFormulaDistributeLog := model.NewFeedFormulaDistributeLogList(distributeData.FeedFormulaList, int64(p.Id), p.Name, operationPb.IsShow_OK)
  660. if err = s.DB.Create(feedFormulaDistributeLog).Error; err != nil {
  661. zaplog.Error("DistributeFeedFormula", zap.Any("feedFormulaDistributeLog", feedFormulaDistributeLog), zap.Any("err", err))
  662. }
  663. } else {
  664. muError = multierr.Append(muError, err)
  665. }
  666. }()
  667. if err = s.PastureHttpClient(ctx, model.FeedFormulaDistributeUrl, int64(p.Id), request, response); err != nil {
  668. muError = multierr.Append(muError, err)
  669. zaplog.Error("DistributeFeedFormula",
  670. zap.Any("pasture", p),
  671. zap.Any("body", distributeData.FeedFormulaList),
  672. zap.Any("err", err),
  673. zap.Any("response", response),
  674. )
  675. b, _ := json.Marshal(request)
  676. res, _ := json.Marshal(response)
  677. pastureDataLog := model.NewPastureDataLog(int64(p.Id), PastureDataLogType["FeedFormula_Distribute"], model.FeedFormulaDistributeUrl, string(b), string(res))
  678. if err = s.DB.Create(pastureDataLog).Error; err != nil {
  679. zaplog.Error("DistributeFeedFormula", zap.Any("pastureDataLog", pastureDataLog), zap.Any("err", err))
  680. }
  681. }
  682. }(pasture)
  683. }
  684. wg.Wait()
  685. return xerr.WithStack(muError)
  686. }
  687. // CancelDistributeFeedFormula 取消配方下发牧场
  688. func (s *StoreEntry) CancelDistributeFeedFormula(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) error {
  689. distributeData, err := s.checkoutDistributeData(ctx, req)
  690. if err != nil {
  691. return xerr.WithStack(err)
  692. }
  693. wg := sync.WaitGroup{}
  694. wg.Add(len(distributeData.PastureList))
  695. var muError error
  696. for _, pasture := range distributeData.PastureList {
  697. go func(p *operationPb.AddPastureRequest) {
  698. defer wg.Done()
  699. pastureDataId := make([]int64, 0)
  700. for _, v := range distributeData.FeedFormulaList {
  701. if v.PastureId == p.Id {
  702. pastureDataId = append(pastureDataId, int64(v.PastureDataId))
  703. }
  704. }
  705. if len(pastureDataId) <= 0 {
  706. return
  707. }
  708. request := &model.CancelDistributeFeedFormulaRequest{
  709. PastureId: int64(p.Id),
  710. PastureDataId: pastureDataId,
  711. }
  712. response := &model.PastureResponse{}
  713. if err = s.PastureHttpClient(ctx, model.FeedFormulaCancelDistributeUrl, int64(p.Id), request, response); err != nil {
  714. zaplog.Error("DistributeFeedFormula",
  715. zap.String("url", model.FeedFormulaCancelDistributeUrl),
  716. zap.Any("pasture", p),
  717. zap.Any("body", distributeData.FeedFormulaList),
  718. zap.Any("err", err),
  719. zap.Any("response", response))
  720. b, _ := json.Marshal(request)
  721. res, _ := json.Marshal(response)
  722. pastureDataLog := model.NewPastureDataLog(int64(p.Id), PastureDataLogType["FeedFormula_Cancel_Distribute"], model.FeedFormulaCancelDistributeUrl, string(b), string(res))
  723. s.DB.Create(pastureDataLog)
  724. }
  725. }(pasture)
  726. }
  727. wg.Wait()
  728. return muError
  729. }
  730. // EditRecodeFeedFormula 配方修改记录
  731. func (s *StoreEntry) EditRecodeFeedFormula(ctx context.Context, req *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error) {
  732. feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
  733. if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
  734. return nil, xerr.WithStack(err)
  735. }
  736. res := &operationPb.EditRecodeFeedFormulaResponse{
  737. Code: http.StatusOK,
  738. Msg: "ok",
  739. Data: make([]*operationPb.EditRecodeFeedFormulaData, 0),
  740. }
  741. feedFormulaEditRecordList := make([]*model.FeedFormulaEditRecord, 0)
  742. pref := s.DB.Model(new(model.FeedFormulaEditRecord)).Where("status > 0").Where("feed_formula_id = ?", req.FeedFormulaId)
  743. if req.PastureId > 0 {
  744. pref.Where("pasture_id = ?", req.PastureId)
  745. }
  746. if req.StartTime > 0 && req.EndTime > 0 && req.EndTime >= req.StartTime {
  747. pref.Where("created_at >= ?", req.StartTime).Where("created_at <= ?", req.EndTime)
  748. }
  749. if err := pref.Order("group_id").Find(&feedFormulaEditRecordList).Error; err != nil {
  750. return res, xerr.WithStack(err)
  751. }
  752. groupByFeedFormulaEditRecordList := make(map[int64][]*model.FeedFormulaEditRecord)
  753. for _, v := range feedFormulaEditRecordList {
  754. if groupByFeedFormulaEditRecordList[v.GroupId] == nil {
  755. groupByFeedFormulaEditRecordList[v.GroupId] = make([]*model.FeedFormulaEditRecord, 0)
  756. }
  757. groupByFeedFormulaEditRecordList[v.GroupId] = append(groupByFeedFormulaEditRecordList[v.GroupId], v)
  758. }
  759. editRecodeFeedFormulaDataList := make([]*operationPb.EditRecodeFeedFormulaData, 0)
  760. for _, data := range groupByFeedFormulaEditRecordList {
  761. var modifyDetail = ""
  762. var pastureId int32 = 0
  763. var pastureName = ""
  764. var createTime int64 = 0
  765. for i, v := range data {
  766. if i == 0 {
  767. modifyDetail += fmt.Sprintf("%s\n ", v.PastureName)
  768. pastureId = int32(v.PastureId)
  769. pastureName = v.PastureName
  770. createTime = v.CreatedAt
  771. }
  772. switch v.Status {
  773. case operationPb.FeedFormulaEditRecordType_INSERT:
  774. modifyDetail += fmt.Sprintf(`%s新增了饲料%s\n `, v.OperationName, v.ForageName)
  775. case operationPb.FeedFormulaEditRecordType_UPDATE:
  776. modifyDetail += fmt.Sprintf(`%s将%s的%s"%s"更新为"%s"\n `, v.OperationName, v.ForageName, v.FieldName, v.BeforeValue, v.AfterValue)
  777. case operationPb.FeedFormulaEditRecordType_DELETE:
  778. modifyDetail += fmt.Sprintf(`%s删除了%s\n `, v.OperationName, v.ForageName)
  779. }
  780. }
  781. editRecodeFeedFormulaDataList = append(editRecodeFeedFormulaDataList, &operationPb.EditRecodeFeedFormulaData{
  782. PastureId: pastureId,
  783. PastureName: pastureName,
  784. ModifyTime: time.Unix(createTime, 0).Format(model.LayoutTime),
  785. ModifyDetail: modifyDetail,
  786. })
  787. }
  788. res.Data = editRecodeFeedFormulaDataList
  789. return res, nil
  790. }
  791. func (s *StoreEntry) FeedFormulaDetailList(ctx context.Context, req *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
  792. res := &operationPb.FeedFormulaDetailResponse{
  793. Code: http.StatusOK,
  794. Msg: "ok",
  795. Data: make([]*operationPb.AddFeedFormulaDetail, 0),
  796. }
  797. feedFormula, err := s.SearchFeedFormulaById(ctx, int64(req.FeedFormulaId))
  798. if err != nil {
  799. return nil, xerr.WithStack(err)
  800. }
  801. feedFormulaId := feedFormula.Id
  802. if feedFormula.PastureDataId > 0 {
  803. feedFormulaId = feedFormula.PastureDataId
  804. }
  805. list, err := s.SearchFeedFormalDetailById(ctx, feedFormulaId, feedFormula.PastureId)
  806. if err != nil {
  807. return nil, xerr.WithStack(err)
  808. }
  809. if len(list) <= 0 {
  810. list, err = s.SearchFeedFormalDetailById(ctx, feedFormula.Id, 0)
  811. if err != nil {
  812. return nil, xerr.WithStack(err)
  813. }
  814. }
  815. res.Data = model.FeedFormulaDetailSlice(list).ToPB()
  816. return res, nil
  817. }
  818. // FeedFormulaUsage 配方使用概况
  819. func (s *StoreEntry) FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error) {
  820. feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
  821. if err := s.DB.Model(new(model.FeedFormulaDistributeLog)).
  822. Where("feed_formula_id = ?", req.FeedFormulaId).
  823. Where("is_show = ?", operationPb.IsShow_OK).Group("pasture_id").
  824. Find(&feedFormulaDistributeLogList).Error; err != nil {
  825. return nil, xerr.WithStack(err)
  826. }
  827. res := &operationPb.FeedFormulaUsageResponse{
  828. Code: http.StatusOK,
  829. Msg: "ok",
  830. Data: make([]*operationPb.FeedFormulaUsageList, 0),
  831. }
  832. wg := sync.WaitGroup{}
  833. wg.Add(len(feedFormulaDistributeLogList))
  834. for _, list := range feedFormulaDistributeLogList {
  835. go func(l *model.FeedFormulaDistributeLog) {
  836. defer wg.Done()
  837. groupDetail, err := s.PastureDetailById(ctx, l.PastureId)
  838. if err != nil {
  839. zaplog.Error("FeedFormulaUsage", zap.Any("PastureDetailById", err))
  840. return
  841. }
  842. req.PastureId = int32(groupDetail.PastureId)
  843. response := &operationPb.PastureFeedFormulaUsageResponse{}
  844. if err = s.PastureHttpClient(ctx, model.FeedUsageURl, groupDetail.Id, req, response); err != nil {
  845. zaplog.Error("FeedFormulaUsage", zap.Any("PastureDetailById", err))
  846. return
  847. }
  848. if response.Code == http.StatusOK {
  849. data := &operationPb.FeedFormulaUsageList{
  850. PastureId: int32(groupDetail.Id),
  851. PastureName: groupDetail.Name,
  852. MixedFodderAccurateRatio: response.Data.MixedFodderAccurateRatio,
  853. MixedFodderCorrectRatio: response.Data.MixedFodderCorrectRatio,
  854. SprinkleFodderAccurateRatio: response.Data.SprinkleFodderAccurateRatio,
  855. SprinkleFodderCorrectRatio: response.Data.SprinkleFodderCorrectRatio,
  856. AddFeedTime: response.Data.AddFeedTime,
  857. SprinkleTime: response.Data.SprinkleTime,
  858. StirTime: response.Data.StirTime,
  859. LastEditTime: response.Data.LastEditTime,
  860. }
  861. res.Data = append(res.Data, data)
  862. } else {
  863. zaplog.Error("FeedFormulaUsage-http", zap.Any("response", response))
  864. return
  865. }
  866. }(list)
  867. }
  868. wg.Wait()
  869. return res, nil
  870. }
  871. func (s *StoreEntry) PastureFeedFormulaIsModify(ctx context.Context, feedFormulaId int32, isModify operationPb.IsShow_Kind) {
  872. feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
  873. if err := s.DB.Where("is_show = ?", operationPb.IsShow_OK).
  874. Where("feed_formula_id = ?", feedFormulaId).
  875. Group("pasture_id").Find(&feedFormulaDistributeLogList).Error; err != nil {
  876. zaplog.Error("PastureFeedFormulaIsModify", zap.Any("err", err), zap.Any("feed_formula_id", feedFormulaId))
  877. return
  878. }
  879. for _, v := range feedFormulaDistributeLogList {
  880. response := &model.PastureResponse{}
  881. request := &model.FeedFormulaIsModifyRequest{
  882. PastureId: v.PastureId,
  883. FeedFormulaId: v.FeedFormulaId,
  884. IsModify: int32(isModify),
  885. }
  886. if err := s.PastureHttpClient(ctx, model.FeedFormulaIsModifyUrl, v.Id, request, response); err != nil {
  887. zaplog.Error("PastureFeedFormulaIsModify", zap.Any("request", request), zap.Any("err", err), zap.Any("response", response))
  888. b, _ := json.Marshal(request)
  889. res, _ := json.Marshal(response)
  890. pastureDataLog := model.NewPastureDataLog(v.PastureId, PastureDataLogType["FeedFormula_IsModify"], model.FeedFormulaIsModifyUrl, string(b), string(res))
  891. s.DB.Create(pastureDataLog)
  892. }
  893. }
  894. }
  895. func (s *StoreEntry) checkoutDistributeData(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) (*operationPb.CheckDistributeData, error) {
  896. result := &operationPb.CheckDistributeData{
  897. PastureList: make([]*operationPb.AddPastureRequest, 0),
  898. FeedFormulaList: make([]*operationPb.DistributeFeedRequest, 0),
  899. }
  900. newGroupPastureList := make([]*model.GroupPasture, 0)
  901. if err := s.DB.Model(new(model.GroupPasture)).Where("id IN ?", req.PastureIds).Where("is_delete = ?", operationPb.IsShow_OK).Find(&newGroupPastureList).Error; err != nil {
  902. return result, xerr.WithStack(err)
  903. }
  904. result.PastureList = model.GroupPastureSlice(newGroupPastureList).ToPB()
  905. newFeedFormulaList := make([]*model.FeedFormula, 0)
  906. if err := s.DB.Model(new(model.FeedFormula)).Where("id IN ?", req.FeedFormulaIds).Find(&newFeedFormulaList).Error; err != nil {
  907. return result, xerr.WithStack(err)
  908. }
  909. result.FeedFormulaList = model.FeedFormulaSlice(newFeedFormulaList).ToDistributePB()
  910. if len(result.FeedFormulaList) != len(req.FeedFormulaIds) {
  911. return result, xerr.Customf("数据错误:%v", req.FeedFormulaIds)
  912. }
  913. for _, v := range result.FeedFormulaList {
  914. feedFormulaDetail := make([]*model.FeedFormulaDetail, 0)
  915. if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("feed_formula_id = ?", v.Id).Find(&feedFormulaDetail).Error; err != nil {
  916. zaplog.Error("checkoutDistributeData", zap.Any("feed_formula_id", v.Id), zap.Any("err", err))
  917. return result, xerr.Customf("%v", err)
  918. }
  919. if len(feedFormulaDetail) <= 0 {
  920. return result, xerr.Customf("请先添加配方饲料信息: %s", v.Name)
  921. }
  922. v.FeedFormulaDetail = model.FeedFormulaDetailSlice(feedFormulaDetail).ToPB()
  923. }
  924. if len(result.PastureList) <= 0 || len(result.FeedFormulaList) <= 0 {
  925. return result, xerr.Customf("数据错误")
  926. }
  927. return result, nil
  928. }
  929. func (s *StoreEntry) checkoutDistributeLog(ctx context.Context, pastureId, feedFormulaId int64) bool {
  930. res := &model.FeedFormulaDistributeLog{}
  931. if err := s.DB.Model(new(model.FeedFormulaDistributeLog)).Where("feed_formula_id = ?", feedFormulaId).
  932. Where("pasture_id = ?", pastureId).Where("is_show = ?", operationPb.IsShow_OK).First(res).Error; err != nil {
  933. return false
  934. }
  935. if res.IsShow == operationPb.IsShow_OK {
  936. return true
  937. }
  938. return false
  939. }
  940. func (s *StoreEntry) SearchFeedFormalDetailById(ctx context.Context, feedFormulaId, pastureId int64) ([]*model.FeedFormulaDetail, error) {
  941. res := make([]*model.FeedFormulaDetail, 0)
  942. if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("pasture_id = ?", pastureId).
  943. Where("feed_formula_id = ?", feedFormulaId).
  944. Where("is_show = ?", operationPb.IsShow_OK).
  945. Order("id desc").Find(&res).Error; err != nil {
  946. return nil, xerr.WithStack(err)
  947. }
  948. return res, nil
  949. }
  950. // UpdateFeedFormalVersion 更新版本库并通知牧场端
  951. func (s *StoreEntry) UpdateFeedFormalVersion(ctx context.Context, req *model.FeedFormula) {
  952. if err := s.DB.Model(req).UpdateColumn("version", gorm.Expr("version + ?", 1)).Error; err != nil {
  953. zaplog.Error("UpdateFeedFormalVersion-UpdateColumn", zap.Any("err", err))
  954. }
  955. // 获取该配方下发记录表
  956. feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
  957. if err := s.DB.Table(new(model.FeedFormulaDistributeLog).TableName()).
  958. Where("feed_formula_id = ?", req.Id).
  959. Where("is_show = ?", operationPb.IsShow_OK).
  960. Group("pasture_id").
  961. Find(&feedFormulaDistributeLogList).Error; err != nil {
  962. if !errors.Is(err, gorm.ErrRecordNotFound) {
  963. zaplog.Error("UpdateFeedFormalVersion-feedFormulaDistributeLog", zap.Any("err", err))
  964. }
  965. return
  966. }
  967. if len(feedFormulaDistributeLogList) > 0 {
  968. wg := sync.WaitGroup{}
  969. wg.Add(len(feedFormulaDistributeLogList))
  970. for _, v := range feedFormulaDistributeLogList {
  971. go func(feedFormulaDistributeLog *model.FeedFormulaDistributeLog) {
  972. defer wg.Done()
  973. // 更新牧场端配方版本
  974. s.UpdatePastureFeedDetailVersionLog(ctx, feedFormulaDistributeLog, req)
  975. }(v)
  976. }
  977. wg.Wait()
  978. }
  979. }
  980. func (s *StoreEntry) UpdatePastureFeedDetailVersionLog(ctx context.Context, distributeLog *model.FeedFormulaDistributeLog, req *model.FeedFormula) {
  981. pastureId := distributeLog.PastureId
  982. groupPasture, err := s.GetGroupPastureById(ctx, pastureId)
  983. if err != nil {
  984. zaplog.Error("UpdateFeedFormalVersion", zap.Any("GetGroupPastureById", pastureId), zap.Any("err", err))
  985. return
  986. }
  987. if groupPasture.IsDistribution != operationPb.IsShow_OK {
  988. return
  989. }
  990. var (
  991. belong int32 = 1
  992. feedTemplateId = req.Id
  993. )
  994. if req.PastureDataId > 0 {
  995. belong = 2
  996. feedTemplateId = req.PastureDataId
  997. }
  998. list := make([]*operationPb.AddFeedFormulaDetail, 0)
  999. if err = s.DB.Model(new(model.FeedFormulaDetail)).Where("feed_formula_id = ?", req.Id).Find(&list).Error; err != nil {
  1000. zaplog.Error("UpdatePastureFeedDetailVersionLog-getFeedFormulaDetail",
  1001. zap.Any("err", err),
  1002. zap.Any("feed_formula_id", req.Id))
  1003. return
  1004. }
  1005. response := &model.FeedFormulaUpdateVersionResponse{}
  1006. body := &model.FeedFormulaUpdateVersionRequest{
  1007. FeedTemplateId: feedTemplateId,
  1008. Version: req.Version,
  1009. Belong: belong,
  1010. Data: make([]*operationPb.AddFeedFormulaDetail, 0),
  1011. }
  1012. zaplog.Info("UpdateFeedFormalVersion", zap.Any("body", body))
  1013. if err = s.PastureHttpClient(ctx, model.FeedFormulaVersionUpdateUrl, pastureId, body, response); err != nil {
  1014. zaplog.Error("UpdateFeedFormalVersion-http",
  1015. zap.String("url", model.FeedFormulaVersionUpdateUrl),
  1016. zap.Any("pasture", groupPasture), zap.Any("body", body),
  1017. zap.Any("err", err), zap.Any("response", response))
  1018. return
  1019. }
  1020. if response.Code != http.StatusOK {
  1021. zaplog.Error("UpdateFeedFormalVersion-response",
  1022. zap.String("url", model.DashboardExecTimeUrl),
  1023. zap.Any("pasture", groupPasture), zap.Any("body", body),
  1024. zap.Any("err", err), zap.Any("response", response))
  1025. return
  1026. }
  1027. }
  1028. // CheckFeedFormulaDistribute 检查该配方是否下发牧场端
  1029. func (s *StoreEntry) CheckFeedFormulaDistribute(ctx context.Context, pastureId, feedFormulaId int64) bool {
  1030. res := &model.FeedFormulaDistributeLog{}
  1031. if err := s.DB.Where("feed_formula_id = ?", feedFormulaId).Where("pasture_id = ?", pastureId).First(res).Error; err != nil {
  1032. return false
  1033. }
  1034. if res.IsShow == operationPb.IsShow_OK {
  1035. return true
  1036. }
  1037. return false
  1038. }
  1039. // ForageListByGroup 查询集团端饲料的列表数据
  1040. func (s *StoreEntry) ForageListByGroup(ctx context.Context) (*operationPb.SearchForageListResponse, error) {
  1041. forage := make([]*model.Forage, 0)
  1042. var count int64 = 0
  1043. if err := s.DB.Model(new(model.Forage)).Where("is_delete = ?", operationPb.IsShow_OK).
  1044. Where("pasture_id = 0").Where("is_show = ?", operationPb.IsShow_OK).
  1045. Order("id DESC").Count(&count).Find(&forage).Error; err != nil {
  1046. return nil, xerr.WithStack(err)
  1047. }
  1048. return &operationPb.SearchForageListResponse{
  1049. Code: http.StatusOK,
  1050. Msg: "ok",
  1051. Data: &operationPb.SearchForageList{
  1052. Total: int32(count),
  1053. List: model.ForageSlice(forage).ToPB(),
  1054. },
  1055. }, nil
  1056. }