work.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. Message: "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. currentUser, _ := s.GetCurrentSystemUser(ctx)
  64. workOrderCategoryMap := s.WorkOrderCategoryMap()
  65. systemUserList, _ := s.SystemUserList(ctx)
  66. newWorkOrderMaster := model.NewWorkOrderMaster(req, currentUser, systemUserList, workOrderCategoryMap)
  67. if req.Id <= 0 {
  68. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  69. if err := tx.Create(newWorkOrderMaster).Error; err != nil {
  70. return xerr.WithStack(err)
  71. }
  72. newWorkOrderSubList := model.NewWorkOrderSub(newWorkOrderMaster)
  73. if len(newWorkOrderSubList) > 0 {
  74. if err := tx.Create(&newWorkOrderSubList).Error; err != nil {
  75. return xerr.WithStack(err)
  76. }
  77. }
  78. return nil
  79. }); err != nil {
  80. return xerr.WithStack(err)
  81. }
  82. } else {
  83. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  84. if err := tx.Model(newWorkOrderMaster).Where("id = ?", req.Id).Updates(map[string]interface{}{
  85. "name": newWorkOrderMaster.Name,
  86. "frequency": newWorkOrderMaster.Frequency,
  87. "priority": newWorkOrderMaster.Priority,
  88. "subscribe_unit": newWorkOrderMaster.SubscribeUnit,
  89. "category_id": newWorkOrderMaster.CategoryId,
  90. "exec_time": newWorkOrderMaster.ExecTime,
  91. "exec_persons": newWorkOrderMaster.ExecPersons,
  92. "exec_person_names": newWorkOrderMaster.ExecPersonNames,
  93. "week_month_value": newWorkOrderMaster.WeekMonthValue,
  94. "remarks": newWorkOrderMaster.Remarks,
  95. "photos": newWorkOrderMaster.Photos,
  96. }).Error; err != nil {
  97. return xerr.WithStack(err)
  98. }
  99. if err := s.WorkOrderSubUpdate(tx, newWorkOrderMaster); err != nil {
  100. return xerr.WithStack(err)
  101. }
  102. return nil
  103. }); err != nil {
  104. return xerr.WithStack(err)
  105. }
  106. }
  107. return nil
  108. }
  109. // OrderIsShow 工单的开启和关闭
  110. func (s *StoreEntry) OrderIsShow(ctx context.Context, id int64) error {
  111. workOrderMaster := &model.WorkOrderMaster{Id: id}
  112. if err := s.DB.First(workOrderMaster).Error; err != nil {
  113. if errors.Is(err, gorm.ErrRecordNotFound) {
  114. return xerr.Custom("该工单不存在")
  115. }
  116. return xerr.WithStack(err)
  117. }
  118. isShow := pasturePb.IsShow_No
  119. if workOrderMaster.IsShow == pasturePb.IsShow_No {
  120. isShow = pasturePb.IsShow_Ok
  121. }
  122. if err := s.DB.Transaction(func(tx *gorm.DB) error {
  123. if err := tx.Model(workOrderMaster).Where("id = ?", id).Update("is_show", isShow).Error; err != nil {
  124. return xerr.WithStack(err)
  125. }
  126. workOrderMaster.IsShow = isShow
  127. if err := s.WorkOrderSubUpdate(tx, workOrderMaster); err != nil {
  128. return xerr.WithStack(err)
  129. }
  130. return nil
  131. }); err != nil {
  132. return xerr.WithStack(err)
  133. }
  134. return nil
  135. }
  136. // WorkOrderSubUpdate 子工单重新维护
  137. // 如果工单是开启状态,则重新生成子工单,如果工单是关闭状态,则取消子工单
  138. func (s *StoreEntry) WorkOrderSubUpdate(tx *gorm.DB, workOrderMaster *model.WorkOrderMaster) error {
  139. if workOrderMaster.IsShow == pasturePb.IsShow_Ok {
  140. newWorkOrderSubList := model.NewWorkOrderSub(workOrderMaster)
  141. if len(newWorkOrderSubList) <= 0 {
  142. return nil
  143. }
  144. if err := tx.Create(&newWorkOrderSubList).Error; err != nil {
  145. return xerr.WithStack(err)
  146. }
  147. } else {
  148. // 获取当天的零点时间
  149. zeroTime := util.TimeParseLocalUnix(time.Now().Format("2006-01-02"))
  150. // 先检查是否存在符合条件的记录
  151. var count int64
  152. if err := tx.Model(&model.WorkOrderSub{}).
  153. Where("work_order_master_id = ?", workOrderMaster.Id).
  154. Where("is_show = ?", pasturePb.IsShow_Ok).
  155. Where("exec_time > ?", zeroTime).
  156. Where("status = ?", pasturePb.WorkOrderStatus_Distribute).
  157. Count(&count).Error; err != nil {
  158. return xerr.WithStack(err)
  159. }
  160. if count <= 0 {
  161. return nil
  162. }
  163. if err := tx.Model(new(model.WorkOrderSub)).
  164. Where("work_order_master_id = ?", workOrderMaster.Id).
  165. Where("is_show = ?", pasturePb.IsShow_Ok).
  166. Where("exec_time > ?", zeroTime).
  167. Where("status = ?", pasturePb.WorkOrderStatus_Distribute).
  168. Update("status", pasturePb.WorkOrderStatus_Canceled).Error; err != nil {
  169. return xerr.WithStack(err)
  170. }
  171. }
  172. return nil
  173. }
  174. func (s *StoreEntry) SendAsynqWorkOrder(ctx context.Context, workOrder *model.WorkOrderMaster) {
  175. if workOrder.IsShow == pasturePb.IsShow_No {
  176. return
  177. }
  178. timeUnix, _ := util.ConvertParseLocalUnix(workOrder.ExecTime)
  179. nowTime := time.Now()
  180. // 过滤掉10秒内要执行的任务
  181. if timeUnix <= nowTime.Unix()+10 {
  182. return
  183. }
  184. // 判断是否是周任务,并且当前周不在执行周期内,则不执行任务
  185. if workOrder.WeekMonthValue != "" {
  186. execWeekMonth := strings.Split(workOrder.WeekMonthValue, ",")
  187. currentWeekMonth := ""
  188. if workOrder.Frequency == pasturePb.WorkOrderFrequency_Weekly {
  189. currentWeekMonth = fmt.Sprintf("%d", nowTime.Weekday())
  190. }
  191. if workOrder.Frequency == pasturePb.WorkOrderFrequency_Monthly {
  192. currentWeekMonth = fmt.Sprintf("%d", nowTime.Day())
  193. }
  194. var info bool
  195. for _, weekMonth := range execWeekMonth {
  196. if currentWeekMonth == weekMonth {
  197. info = true
  198. break
  199. }
  200. }
  201. // 如果有,则不执行任务
  202. if info {
  203. return
  204. }
  205. }
  206. execTime := time.Now().Unix() - timeUnix
  207. if _, err := s.AsynqClient.CtxEnqueue(
  208. ctx,
  209. model.NewTaskWorkOrderPayload(workOrder.Id, time.Duration(execTime)*time.Second),
  210. ); err != nil {
  211. zaplog.Error("PushMessage CtxEnqueue", zap.Any("Err", err))
  212. }
  213. }
  214. // UserWorkOrderList 用户工单列表
  215. func (s *StoreEntry) UserWorkOrderList(ctx context.Context, workOrderStatus pasturePb.WorkOrderStatus_Kind, pagination *pasturePb.PaginationModel) (*pasturePb.UserWorkOrderResponse, error) {
  216. currUser, err := s.GetCurrentSystemUser(ctx)
  217. if err != nil {
  218. return nil, xerr.WithStack(err)
  219. }
  220. var count int64 = 0
  221. userWorkOrderList := make([]*model.WorkOrderSub, 0)
  222. pref := s.DB.Model(userWorkOrderList).
  223. Where("is_show = ?", pasturePb.IsShow_Ok)
  224. if workOrderStatus != pasturePb.WorkOrderStatus_Invalid {
  225. pref.Where("status = ?", workOrderStatus)
  226. }
  227. if err := pref.Where(
  228. s.DB.Where("exec_user_id = ?", currUser.Id).
  229. Or("FIND_IN_SET(?, set_user_ids) > 0", currUser.Id),
  230. ).
  231. Order("id desc").
  232. Count(&count).
  233. Limit(int(pagination.PageSize)).
  234. Offset(int(pagination.PageOffset)).
  235. Find(&userWorkOrderList).Error; err != nil {
  236. return nil, xerr.WithStack(err)
  237. }
  238. mMap := make(map[int64]*model.WorkOrderMaster)
  239. workOderMasterList := make([]*model.WorkOrderMaster, 0)
  240. if err := s.DB.Model(&model.WorkOrderMaster{}).Find(&workOderMasterList).Error; err != nil {
  241. return nil, xerr.WithStack(err)
  242. }
  243. for _, workOrderMaster := range workOderMasterList {
  244. mMap[workOrderMaster.Id] = workOrderMaster
  245. }
  246. priorityMap := s.WorkOrderPriorityMap()
  247. return &pasturePb.UserWorkOrderResponse{
  248. Code: http.StatusOK,
  249. Message: "ok",
  250. Data: &pasturePb.UserWorkOrderData{
  251. List: model.WorkOrderSubSlice(userWorkOrderList).ToPB(mMap, priorityMap),
  252. Total: 0,
  253. PageSize: pagination.PageSize,
  254. Page: pagination.Page,
  255. },
  256. }, nil
  257. }