procInstService.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package service
  2. import (
  3. "errors"
  4. "sync"
  5. "time"
  6. "github.com/jinzhu/gorm"
  7. "github.com/go-workflow/go-workflow/workflow-engine/flow"
  8. "github.com/go-workflow/go-workflow/workflow-engine/model"
  9. "github.com/mumushuiding/util"
  10. )
  11. // ProcessReceiver 接收页面传递参数
  12. type ProcessReceiver struct {
  13. UserID string `json:"userId"`
  14. ProcInstID string `json:"procInstID"`
  15. Username string `json:"username"`
  16. Company string `json:"company"`
  17. ProcName string `json:"procName"`
  18. Title string `json:"title"`
  19. Department string `json:"department"`
  20. Var *map[string]string `json:"var"`
  21. }
  22. // ProcessPageReceiver 分页参数
  23. type ProcessPageReceiver struct {
  24. util.Page
  25. // 我分管的部门
  26. Departments []string `json:"departments"`
  27. // 我所属于的用户组或者角色
  28. Groups []string `josn:"groups"`
  29. UserID string `json:"userID"`
  30. Username string `json:"username"`
  31. Company string `json:"company"`
  32. ProcName string `json:"procName"`
  33. ProcInstID string `json:"procInstID"`
  34. }
  35. var copyLock sync.Mutex
  36. // GetDefaultProcessPageReceiver GetDefaultProcessPageReceiver
  37. func GetDefaultProcessPageReceiver() *ProcessPageReceiver {
  38. var p = ProcessPageReceiver{}
  39. p.PageIndex = 1
  40. p.PageSize = 10
  41. return &p
  42. }
  43. func findAll(pr *ProcessPageReceiver) ([]*model.ProcInst, int, error) {
  44. var page = util.Page{}
  45. page.PageRequest(pr.PageIndex, pr.PageSize)
  46. return model.FindProcInsts(pr.UserID, pr.ProcName, pr.Company, pr.Groups, pr.Departments, pr.PageIndex, pr.PageSize)
  47. }
  48. // FindProcInstByID FindProcInstByID
  49. func FindProcInstByID(id int) (string, error) {
  50. data, err := model.FindProcInstByID(id)
  51. if err != nil {
  52. return "", err
  53. }
  54. return util.ToJSONStr(data)
  55. }
  56. // FindAllPageAsJSON FindAllPageAsJSON
  57. func FindAllPageAsJSON(pr *ProcessPageReceiver) (string, error) {
  58. datas, count, err := findAll(pr)
  59. if err != nil {
  60. return "", err
  61. }
  62. return util.ToPageJSON(datas, count, pr.PageIndex, pr.PageSize)
  63. }
  64. // FindMyProcInstByToken FindMyProcInstByToken
  65. // 根据token获取流程信息
  66. func FindMyProcInstByToken(token string, receiver *ProcessPageReceiver) (string, error) {
  67. // 根据 token 获取用户信息
  68. userinfo, err := GetUserinfoFromRedis(token)
  69. if err != nil {
  70. return "", err
  71. }
  72. if len(userinfo.Company) == 0 {
  73. return "", errors.New("保存在redis中的【用户信息 userinfo】字段 company 不能为空")
  74. }
  75. if len(userinfo.ID) == 0 {
  76. return "", errors.New("保存在redis中的【用户信息 userinfo】字段 ID 不能为空")
  77. }
  78. receiver.Company = userinfo.Company
  79. receiver.Departments = userinfo.Departments
  80. receiver.Groups = userinfo.Roles
  81. receiver.UserID = userinfo.ID
  82. // str, _ = util.ToJSONStr(receiver)
  83. // fmt.Printf("receiver:%s\n", str)
  84. return FindAllPageAsJSON(receiver)
  85. }
  86. // StartProcessInstanceByToken 启动流程
  87. func StartProcessInstanceByToken(token string, p *ProcessReceiver) (int, error) {
  88. // 根据 token 获取用户信息
  89. userinfo, err := GetUserinfoFromRedis(token)
  90. if err != nil {
  91. return 0, err
  92. }
  93. if len(userinfo.Company) == 0 {
  94. return 0, errors.New("保存在redis中的【用户信息 userinfo】字段 company 不能为空")
  95. }
  96. if len(userinfo.Username) == 0 {
  97. return 0, errors.New("保存在redis中的【用户信息 userinfo】字段 username 不能为空")
  98. }
  99. if len(userinfo.ID) == 0 {
  100. return 0, errors.New("保存在redis中的【用户信息 userinfo】字段 ID 不能为空")
  101. }
  102. if len(userinfo.Department) == 0 {
  103. return 0, errors.New("保存在redis中的【用户信息 userinfo】字段 department 不能为空")
  104. }
  105. p.Company = userinfo.Company
  106. p.Department = userinfo.Department
  107. p.UserID = userinfo.ID
  108. p.Username = userinfo.Username
  109. return p.StartProcessInstanceByID(p.Var)
  110. }
  111. // StartProcessInstanceByID 启动流程
  112. func (p *ProcessReceiver) StartProcessInstanceByID(variable *map[string]string) (int, error) {
  113. // times := time.Now()
  114. // runtime.GOMAXPROCS(2)
  115. // 获取流程定义
  116. node, prodefID, procdefName, err := GetResourceByNameAndCompany(p.ProcName, p.Company)
  117. if err != nil {
  118. return 0, err
  119. }
  120. // fmt.Printf("获取流程定义耗时:%v", time.Since(times))
  121. //--------以下需要添加事务-----------------
  122. step := 0 // 0 为开始节点
  123. tx := model.GetTx()
  124. // 新建流程实例
  125. var procInst = model.ProcInst{
  126. ProcDefID: prodefID,
  127. ProcDefName: procdefName,
  128. Title: p.Title,
  129. Department: p.Department,
  130. StartTime: util.FormatDate(time.Now(), util.YYYY_MM_DD_HH_MM_SS),
  131. StartUserID: p.UserID,
  132. StartUserName: p.Username,
  133. Company: p.Company,
  134. } //开启事务
  135. // times = time.Now()
  136. procInstID, err := CreateProcInstTx(&procInst, tx) // 事务
  137. // fmt.Printf("启动流程实例耗时:%v", time.Since(times))
  138. exec := &model.Execution{
  139. ProcDefID: prodefID,
  140. ProcInstID: procInstID,
  141. }
  142. task := &model.Task{
  143. NodeID: "开始",
  144. ProcInstID: procInstID,
  145. Assignee: p.UserID,
  146. IsFinished: true,
  147. ClaimTime: util.FormatDate(time.Now(), util.YYYY_MM_DD_HH_MM_SS),
  148. Step: step,
  149. MemberCount: 1,
  150. UnCompleteNum: 0,
  151. ActType: "or",
  152. AgreeNum: 1,
  153. }
  154. // 生成执行流,一串运行节点
  155. _, err = GenerateExec(exec, node, p.UserID, variable, tx) //事务
  156. if err != nil {
  157. tx.Rollback()
  158. return 0, err
  159. }
  160. // 获取执行流信息
  161. var nodeinfos []*flow.NodeInfo
  162. err = util.Str2Struct(exec.NodeInfos, &nodeinfos)
  163. if err != nil {
  164. tx.Rollback()
  165. return 0, err
  166. }
  167. // fmt.Printf("生成执行流耗时:%v", time.Since(times))
  168. // -----------------生成新任务-------------
  169. // times = time.Now()
  170. if nodeinfos[0].ActType == "and" {
  171. task.UnCompleteNum = nodeinfos[0].MemberCount
  172. task.MemberCount = nodeinfos[0].MemberCount
  173. }
  174. _, err = NewTaskTx(task, tx)
  175. if err != nil {
  176. tx.Rollback()
  177. return 0, err
  178. }
  179. // fmt.Printf("生成新任务耗时:%v", time.Since(times))
  180. //--------------------流转------------------
  181. // times = time.Now()
  182. // 流程移动到下一环节
  183. err = MoveStage(nodeinfos, p.UserID, p.Username, p.Company, "启动流程", "", task.ID, procInstID, step, true, tx)
  184. if err != nil {
  185. tx.Rollback()
  186. return 0, err
  187. }
  188. // fmt.Printf("流转到下一流程耗时:%v", time.Since(times))
  189. // fmt.Println("--------------提交事务----------")
  190. tx.Commit() //结束事务
  191. return procInstID, err
  192. }
  193. // CreateProcInstByID 新建流程实例
  194. // func CreateProcInstByID(processDefinitionID int, startUserID string) (int, error) {
  195. // var procInst = model.ProcInst{
  196. // ProcDefID: processDefinitionID,
  197. // StartTime: util.FormatDate(time.Now(), util.YYYY_MM_DD_HH_MM_SS),
  198. // StartUserID: startUserID,
  199. // }
  200. // return procInst.Save()
  201. // }
  202. // CreateProcInstTx CreateProcInstTx
  203. // 开户事务
  204. func CreateProcInstTx(procInst *model.ProcInst, tx *gorm.DB) (int, error) {
  205. return procInst.SaveTx(tx)
  206. }
  207. // SetProcInstFinish SetProcInstFinish
  208. // 设置流程结束
  209. func SetProcInstFinish(procInstID int, endTime string, tx *gorm.DB) error {
  210. var p = &model.ProcInst{}
  211. p.ID = procInstID
  212. p.EndTime = endTime
  213. p.IsFinished = true
  214. return p.UpdateTx(tx)
  215. }
  216. // StartByMyself 我发起的流程
  217. func StartByMyself(receiver *ProcessPageReceiver) (string, error) {
  218. var page = util.Page{}
  219. page.PageRequest(receiver.PageIndex, receiver.PageSize)
  220. datas, count, err := model.StartByMyself(receiver.UserID, receiver.Company, receiver.PageIndex, receiver.PageSize)
  221. if err != nil {
  222. return "", err
  223. }
  224. return util.ToPageJSON(datas, count, receiver.PageIndex, receiver.PageSize)
  225. }
  226. // FindProcNotify 查询抄送我的
  227. func FindProcNotify(receiver *ProcessPageReceiver) (string, error) {
  228. var page = util.Page{}
  229. page.PageRequest(receiver.PageIndex, receiver.PageSize)
  230. datas, count, err := model.FindProcNotify(receiver.UserID, receiver.Company, receiver.Groups, receiver.PageIndex, receiver.PageSize)
  231. if err != nil {
  232. return "", err
  233. }
  234. return util.ToPageJSON(datas, count, receiver.PageIndex, receiver.PageSize)
  235. }
  236. // UpdateProcInst UpdateProcInst
  237. // 更新流程实例
  238. func UpdateProcInst(procInst *model.ProcInst, tx *gorm.DB) error {
  239. return procInst.UpdateTx(tx)
  240. }
  241. // MoveFinishedProcInstToHistory MoveFinishedProcInstToHistory
  242. func MoveFinishedProcInstToHistory() error {
  243. // 要注意并发,可能会运行多个app实例
  244. // 加锁
  245. copyLock.Lock()
  246. defer copyLock.Unlock()
  247. // 从pro_inst表查询已经结束的流程
  248. proinsts, err := model.FindFinishedProc()
  249. if err != nil {
  250. return err
  251. }
  252. if len(proinsts) == 0 {
  253. return nil
  254. }
  255. for _, v := range proinsts {
  256. // 复制 proc_inst
  257. duration, err := util.TimeStrSub(v.EndTime, v.StartTime, util.YYYY_MM_DD_HH_MM_SS)
  258. if err != nil {
  259. return err
  260. }
  261. v.Duration = duration
  262. err = copyProcToHistory(v)
  263. if err != nil {
  264. return err
  265. }
  266. tx := model.GetTx()
  267. // 流程实例的task移至历史纪录
  268. err = copyTaskToHistoryByProInstID(v.ID, tx)
  269. if err != nil {
  270. tx.Rollback()
  271. DelProcInstHistoryByID(v.ID)
  272. return err
  273. }
  274. // execution移至历史纪录
  275. err = copyExecutionToHistoryByProcInstID(v.ID, tx)
  276. if err != nil {
  277. tx.Rollback()
  278. DelProcInstHistoryByID(v.ID)
  279. return err
  280. }
  281. // identitylink移至历史纪录
  282. err = copyIdentitylinkToHistoryByProcInstID(v.ID, tx)
  283. if err != nil {
  284. tx.Rollback()
  285. DelProcInstHistoryByID(v.ID)
  286. return err
  287. }
  288. // 删除流程实例
  289. err = DelProcInstByIDTx(v.ID, tx)
  290. if err != nil {
  291. tx.Rollback()
  292. DelProcInstHistoryByID(v.ID)
  293. return err
  294. }
  295. tx.Commit()
  296. }
  297. return nil
  298. }
  299. // DelProcInstByIDTx DelProcInstByIDTx
  300. func DelProcInstByIDTx(procInstID int, tx *gorm.DB) error {
  301. return model.DelProcInstByIDTx(procInstID, tx)
  302. }
  303. func copyIdentitylinkToHistoryByProcInstID(procInstID int, tx *gorm.DB) error {
  304. return model.CopyIdentitylinkToHistoryByProcInstID(procInstID, tx)
  305. }
  306. func copyExecutionToHistoryByProcInstID(procInstID int, tx *gorm.DB) error {
  307. return model.CopyExecutionToHistoryByProcInstIDTx(procInstID, tx)
  308. }
  309. func copyProcToHistory(procInst *model.ProcInst) error {
  310. return model.SaveProcInstHistory(procInst)
  311. }
  312. func copyTaskToHistoryByProInstID(procInstID int, tx *gorm.DB) error {
  313. return model.CopyTaskToHistoryByProInstID(procInstID, tx)
  314. }