work.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package backend
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "kpt-pasture/model"
  7. "kpt-pasture/util"
  8. "net/http"
  9. "strings"
  10. "time"
  11. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  12. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  13. "gitee.com/xuyiping_admin/pkg/xerr"
  14. "go.uber.org/zap"
  15. "gorm.io/gorm"
  16. )
  17. func (s *StoreEntry) OrderList(ctx context.Context, req *pasturePb.SearchWorkOrderRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWorkOrderResponse, error) {
  18. workOrderList := make([]*model.WorkOrderMaster, 0)
  19. var count int64 = 0
  20. pref := s.DB.Model(new(model.WorkOrderMaster))
  21. if req.Name != "" {
  22. pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
  23. }
  24. if req.Frequency > 0 {
  25. pref.Where("frequency = ?", req.Frequency)
  26. }
  27. if req.Priority > 0 {
  28. pref.Where("priority = ?", req.Priority)
  29. }
  30. if req.IsShow > 0 {
  31. pref.Where("is_show = ?", req.IsShow)
  32. }
  33. if req.SubscribeUnit > 0 {
  34. pref.Where("subscribe_unit = ?", req.SubscribeUnit)
  35. }
  36. if req.CategoryId > 0 {
  37. pref.Where("category_id = ?", req.CategoryId)
  38. }
  39. if err := pref.Order("id desc").Count(&count).Limit(int(pagination.PageSize)).Offset(int(pagination.PageOffset)).
  40. Find(&workOrderList).Error; err != nil {
  41. return nil, xerr.WithStack(err)
  42. }
  43. priorityMap := s.WorkOrderPriorityMap()
  44. frequencyMap := s.WorkOrderFrequencyMap()
  45. subscribeUnitMap := s.WorkOrderSubUnitMap()
  46. weekMap := s.WeekMap()
  47. monthMap := s.MonthMap()
  48. return &pasturePb.SearchWorkOrderResponse{
  49. Code: http.StatusOK,
  50. Msg: "ok",
  51. Data: &pasturePb.SearchWorkOrderData{
  52. List: model.WorkOrderMasterSlice(workOrderList).ToPB(priorityMap, frequencyMap, subscribeUnitMap, weekMap, monthMap),
  53. Total: int32(count),
  54. PageSize: pagination.PageSize,
  55. Page: pagination.Page,
  56. },
  57. }, nil
  58. }
  59. // OrderCreateOrUpdate 创建和更新工单
  60. // 周期性工单【包括每天,每周,每月】一次性生成符合本月日期所有工单
  61. // 更新工单的时候需要重新维护子工单
  62. func (s *StoreEntry) OrderCreateOrUpdate(ctx context.Context, req *pasturePb.WorkOrderList) error {
  63. userModel, err := s.GetUserModel(ctx)
  64. if err != nil {
  65. return xerr.WithStack(err)
  66. }
  67. workOrderCategoryMap := s.WorkOrderCategoryMap()
  68. systemUserList, _ := s.SystemUserList(ctx)
  69. newWorkOrderMaster := model.NewWorkOrderMaster(userModel.AppPasture.Id, req, userModel.SystemUser, systemUserList, workOrderCategoryMap)
  70. if req.Id <= 0 {
  71. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  72. if err := tx.Create(newWorkOrderMaster).Error; err != nil {
  73. return xerr.WithStack(err)
  74. }
  75. newWorkOrderSubList := model.NewWorkOrderSub(newWorkOrderMaster)
  76. if len(newWorkOrderSubList) > 0 {
  77. if err := tx.Create(&newWorkOrderSubList).Error; err != nil {
  78. return xerr.WithStack(err)
  79. }
  80. }
  81. return nil
  82. }); err != nil {
  83. return xerr.WithStack(err)
  84. }
  85. } else {
  86. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  87. if err := tx.Model(newWorkOrderMaster).Where("id = ?", req.Id).Updates(map[string]interface{}{
  88. "name": newWorkOrderMaster.Name,
  89. "frequency": newWorkOrderMaster.Frequency,
  90. "priority": newWorkOrderMaster.Priority,
  91. "subscribe_unit": newWorkOrderMaster.SubscribeUnit,
  92. "category_id": newWorkOrderMaster.CategoryId,
  93. "exec_time": newWorkOrderMaster.ExecTime,
  94. "exec_persons": newWorkOrderMaster.ExecPersons,
  95. "exec_person_names": newWorkOrderMaster.ExecPersonNames,
  96. "week_month_value": newWorkOrderMaster.WeekMonthValue,
  97. "remarks": newWorkOrderMaster.Remarks,
  98. "photos": newWorkOrderMaster.Photos,
  99. }).Error; err != nil {
  100. return xerr.WithStack(err)
  101. }
  102. if err := s.WorkOrderSubUpdate(tx, newWorkOrderMaster); err != nil {
  103. return xerr.WithStack(err)
  104. }
  105. return nil
  106. }); err != nil {
  107. return xerr.WithStack(err)
  108. }
  109. }
  110. return nil
  111. }
  112. // OrderIsShow 工单的开启和关闭
  113. func (s *StoreEntry) OrderIsShow(ctx context.Context, id int64) error {
  114. workOrderMaster := &model.WorkOrderMaster{Id: id}
  115. if err := s.DB.First(workOrderMaster).Error; err != nil {
  116. if errors.Is(err, gorm.ErrRecordNotFound) {
  117. return xerr.Custom("该工单不存在")
  118. }
  119. return xerr.WithStack(err)
  120. }
  121. isShow := pasturePb.IsShow_No
  122. if workOrderMaster.IsShow == pasturePb.IsShow_No {
  123. isShow = pasturePb.IsShow_Ok
  124. }
  125. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  126. if err := tx.Model(workOrderMaster).Where("id = ?", id).Update("is_show", isShow).Error; err != nil {
  127. return xerr.WithStack(err)
  128. }
  129. workOrderMaster.IsShow = isShow
  130. if err := s.WorkOrderSubUpdate(tx, workOrderMaster); err != nil {
  131. return xerr.WithStack(err)
  132. }
  133. return nil
  134. }); err != nil {
  135. return xerr.WithStack(err)
  136. }
  137. return nil
  138. }
  139. // WorkOrderSubUpdate 子工单重新维护
  140. // 如果工单是开启状态,则重新生成子工单,如果工单是关闭状态,则取消子工单
  141. func (s *StoreEntry) WorkOrderSubUpdate(tx *gorm.DB, workOrderMaster *model.WorkOrderMaster) error {
  142. if workOrderMaster.IsShow == pasturePb.IsShow_Ok {
  143. newWorkOrderSubList := model.NewWorkOrderSub(workOrderMaster)
  144. if len(newWorkOrderSubList) <= 0 {
  145. return nil
  146. }
  147. if err := tx.Create(&newWorkOrderSubList).Error; err != nil {
  148. return xerr.WithStack(err)
  149. }
  150. } else {
  151. // 获取当天的零点时间
  152. zeroTime := util.TimeParseLocalUnix(time.Now().Format("2006-01-02"))
  153. // 先检查是否存在符合条件的记录
  154. var count int64
  155. if err := tx.Model(&model.WorkOrderSub{}).
  156. Where("work_order_master_id = ?", workOrderMaster.Id).
  157. Where("is_show = ?", pasturePb.IsShow_Ok).
  158. Where("exec_time > ?", zeroTime).
  159. Where("status = ?", pasturePb.WorkOrderStatus_Distribute).
  160. Count(&count).Error; err != nil {
  161. return xerr.WithStack(err)
  162. }
  163. if count <= 0 {
  164. return nil
  165. }
  166. if err := tx.Model(new(model.WorkOrderSub)).
  167. Where("work_order_master_id = ?", workOrderMaster.Id).
  168. Where("is_show = ?", pasturePb.IsShow_Ok).
  169. Where("exec_time > ?", zeroTime).
  170. Where("status = ?", pasturePb.WorkOrderStatus_Distribute).
  171. Update("status", pasturePb.WorkOrderStatus_Canceled).Error; err != nil {
  172. return xerr.WithStack(err)
  173. }
  174. }
  175. return nil
  176. }
  177. func (s *StoreEntry) SendAsynqWorkOrder(ctx context.Context, workOrder *model.WorkOrderMaster) {
  178. if workOrder.IsShow == pasturePb.IsShow_No {
  179. return
  180. }
  181. timeUnix, _ := util.ConvertParseLocalUnix(workOrder.ExecTime)
  182. nowTime := time.Now()
  183. // 过滤掉10秒内要执行的任务
  184. if timeUnix <= nowTime.Unix()+10 {
  185. return
  186. }
  187. // 判断是否是周任务,并且当前周不在执行周期内,则不执行任务
  188. if workOrder.WeekMonthValue != "" {
  189. execWeekMonth := strings.Split(workOrder.WeekMonthValue, ",")
  190. currentWeekMonth := ""
  191. if workOrder.Frequency == pasturePb.WorkOrderFrequency_Weekly {
  192. currentWeekMonth = fmt.Sprintf("%d", nowTime.Weekday())
  193. }
  194. if workOrder.Frequency == pasturePb.WorkOrderFrequency_Monthly {
  195. currentWeekMonth = fmt.Sprintf("%d", nowTime.Day())
  196. }
  197. var info bool
  198. for _, weekMonth := range execWeekMonth {
  199. if currentWeekMonth == weekMonth {
  200. info = true
  201. break
  202. }
  203. }
  204. // 如果有,则不执行任务
  205. if info {
  206. return
  207. }
  208. }
  209. execTime := time.Now().Unix() - timeUnix
  210. if _, err := s.AsynqClient.CtxEnqueue(
  211. ctx,
  212. model.NewTaskWorkOrderPayload(workOrder.Id, time.Duration(execTime)*time.Second),
  213. ); err != nil {
  214. zaplog.Error("PushMessage CtxEnqueue", zap.Any("Err", err))
  215. }
  216. }
  217. // UserWorkOrderList 用户工单列表
  218. func (s *StoreEntry) UserWorkOrderList(ctx context.Context, workOrderStatus pasturePb.WorkOrderStatus_Kind, pagination *pasturePb.PaginationModel) (*pasturePb.UserWorkOrderResponse, error) {
  219. userModel, err := s.GetUserModel(ctx)
  220. if err != nil {
  221. return nil, xerr.WithStack(err)
  222. }
  223. var count int64 = 0
  224. userWorkOrderList := make([]*model.WorkOrderSub, 0)
  225. pref := s.DB.Model(userWorkOrderList).
  226. Where("is_show = ?", pasturePb.IsShow_Ok)
  227. if workOrderStatus != pasturePb.WorkOrderStatus_Invalid {
  228. pref.Where("status = ?", workOrderStatus)
  229. }
  230. if err = pref.Where(
  231. s.DB.Where("exec_user_id = ?", userModel.SystemUser.Id).
  232. Or("FIND_IN_SET(?, set_user_ids) > 0", userModel.SystemUser.Id),
  233. ).
  234. Order("id desc").
  235. Count(&count).
  236. Limit(int(pagination.PageSize)).
  237. Offset(int(pagination.PageOffset)).
  238. Find(&userWorkOrderList).Error; err != nil {
  239. return nil, xerr.WithStack(err)
  240. }
  241. mMap := make(map[int64]*model.WorkOrderMaster)
  242. workOderMasterList := make([]*model.WorkOrderMaster, 0)
  243. if err = s.DB.Model(&model.WorkOrderMaster{}).Find(&workOderMasterList).Error; err != nil {
  244. return nil, xerr.WithStack(err)
  245. }
  246. for _, workOrderMaster := range workOderMasterList {
  247. mMap[workOrderMaster.Id] = workOrderMaster
  248. }
  249. priorityMap := s.WorkOrderPriorityMap()
  250. return &pasturePb.UserWorkOrderResponse{
  251. Code: http.StatusOK,
  252. Msg: "ok",
  253. Data: &pasturePb.UserWorkOrderData{
  254. List: model.WorkOrderSubSlice(userWorkOrderList).ToPB(mMap, priorityMap),
  255. Total: 0,
  256. PageSize: pagination.PageSize,
  257. Page: pagination.Page,
  258. },
  259. }, nil
  260. }