work.go 9.1 KB

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