flow.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. package work_flow_service
  2. import (
  3. "fmt"
  4. "gfast/app/model/admin/user"
  5. flowModel "gfast/app/model/admin/wf_flow"
  6. "gfast/app/model/admin/wf_flow_process"
  7. "gfast/app/model/admin/wf_run"
  8. "gfast/app/model/admin/wf_run_process"
  9. "gfast/app/model/admin/wf_run_sign"
  10. "gfast/library/utils"
  11. "github.com/gogf/gf/container/garray"
  12. "github.com/gogf/gf/encoding/gjson"
  13. "github.com/gogf/gf/errors/gerror"
  14. "github.com/gogf/gf/frame/g"
  15. "github.com/gogf/gf/text/gstr"
  16. "github.com/gogf/gf/util/gconv"
  17. )
  18. //工作流数据
  19. type WorkFlow struct {
  20. WfModel int `json:"wf_model"` //模式
  21. SingSt int `json:"sing_st"`
  22. FlowId uint `json:"flow_id"`
  23. Status *wf_run_process.Entity `json:"status"`
  24. FlowProcess uint `json:"flow_process"`
  25. RunId uint `json:"run_id"`
  26. RunProcess uint `json:"run_process"`
  27. FlowName string `json:"flow_name"`
  28. Process *ProcessData `json:"process"`
  29. NextProcess []*ProcessData `json:"next_process"`
  30. Preprocess map[int]string `json:"preprocess"`
  31. SingUser []uint64 `json:"sing_user"`
  32. SignInfo *wf_run_sign.Entity `json:"sign_info"`
  33. BillCheck string `json:"bill_check"`
  34. BillTime string `json:"bill_time"`
  35. }
  36. var msgNoAction = "该功能仅对捐赠用户开放,捐赠199即可获得完整工作流功能及配套视频。"
  37. //获取流程信息
  38. func GetFlowInfoById(flowId int64) (entity *flowModel.Entity, err error) {
  39. return flowModel.GetByID(flowId)
  40. }
  41. //获取流程名称
  42. func GetFlowName(flowId int64) (name string, err error) {
  43. var info *flowModel.Entity
  44. info, err = GetFlowInfoById(flowId)
  45. if err != nil || info == nil {
  46. return
  47. }
  48. name = info.FlowName
  49. return
  50. }
  51. //检查流程逻辑
  52. func CheckFlow(flowId int64) error {
  53. _, processList, err := ProcessAll(flowId)
  54. if err != nil {
  55. return err
  56. }
  57. if processList == nil {
  58. return gerror.New("没有找到步骤信息!")
  59. }
  60. oneStep := 0
  61. for _, process := range processList {
  62. if process.Process.ProcessType == "is_one" {
  63. oneStep++
  64. }
  65. }
  66. if oneStep == 0 {
  67. return gerror.New("没有设置第一步骤,请修改!")
  68. }
  69. if oneStep > 1 {
  70. return gerror.New(fmt.Sprintf("有 %d 个起始步骤,请修改!", oneStep))
  71. }
  72. return nil
  73. }
  74. //获取发起流程按钮及状态
  75. func SetBtn(wfFid uint, wfType, wfTitle, wfStatusField string, status int, userId uint64, departmentId uint64) (g.MapStrAny, error) {
  76. switch status {
  77. case 0:
  78. return g.MapStrAny{
  79. "title": "发起审批",
  80. "api": "wfStart",
  81. "wf_type": wfType,
  82. "wf_status_field": wfStatusField,
  83. "wf_title": wfTitle,
  84. "wf_fid": wfFid,
  85. "type": "link",
  86. }, nil
  87. case 1:
  88. st := 0
  89. userName := ""
  90. flowInfo, processList, err := WorkFlowInfo(wfFid, wfType, userId, departmentId)
  91. if err != nil {
  92. if err.Error() == "无权限" {
  93. //获取当前步骤审批人信息
  94. userNameArr := make([]string, 0, 10)
  95. for _, process := range processList {
  96. userNameArr = append(userNameArr, process.SponsorText)
  97. }
  98. return g.MapStrAny{
  99. "title": "无审批权限(" + gstr.Join(userNameArr, ",") + ")",
  100. "type": "text",
  101. }, nil
  102. }
  103. return nil, err
  104. }
  105. if flowInfo != nil && flowInfo.NextProcess != nil {
  106. if flowInfo.Status == nil {
  107. return g.MapStrAny{
  108. "title": "提示:当前流程故障,请联系管理员重置流程!",
  109. "type": "alert",
  110. }, nil
  111. }
  112. if flowInfo.SingSt == 0 {
  113. user := garray.NewStrArrayFrom(gstr.Split(flowInfo.Status.SponsorIds, ","))
  114. userName = flowInfo.Status.SponsorText
  115. if flowInfo.Status.AutoPerson == 3 || flowInfo.Status.AutoPerson == 4 || flowInfo.Status.AutoPerson == 6 {
  116. if user.Contains(gconv.String(userId)) {
  117. st = 1
  118. }
  119. } else if flowInfo.Status.AutoPerson == 5 {
  120. if user.Contains(gconv.String(departmentId)) {
  121. st = 1
  122. }
  123. }
  124. } else {
  125. userInfo, err := user.GetUserById(gconv.Uint64(flowInfo.SignInfo.Uid))
  126. if err != nil {
  127. return nil, err
  128. }
  129. userName = userInfo.UserNickname
  130. if gconv.Uint64(flowInfo.SignInfo.Uid) == userId {
  131. st = 1
  132. }
  133. }
  134. } else {
  135. return nil, nil
  136. }
  137. if st == 1 {
  138. return g.MapStrAny{
  139. "title": "审批(" + userName + ")",
  140. "api": "wfCheck",
  141. "wf_type": wfType,
  142. "wf_status_field": wfStatusField,
  143. "wf_title": wfTitle,
  144. "wf_fid": wfFid,
  145. "type": "link",
  146. }, nil
  147. } else {
  148. return g.MapStrAny{
  149. "title": "无审批权限(" + userName + ")",
  150. "type": "text",
  151. }, nil
  152. }
  153. case 100:
  154. return g.MapStrAny{
  155. "title": "代审",
  156. "api": "wfCheck",
  157. "wf_type": wfType,
  158. "wf_status_field": wfStatusField,
  159. "wf_title": wfTitle,
  160. "wf_fid": wfFid,
  161. "type": "link",
  162. "sup": "1",
  163. }, nil
  164. }
  165. return nil, nil
  166. }
  167. //流程状态查询
  168. func WorkFlowInfo(wfFid uint, wfType string, userId uint64, departmentId uint64) (
  169. *WorkFlow, []*wf_run_process.Entity, error) {
  170. workFlow := &WorkFlow{}
  171. processList := ([]*wf_run_process.Entity)(nil)
  172. if wfFid == 0 || wfType == "" {
  173. return nil, nil, gerror.New("单据编号,单据表不可为空!")
  174. }
  175. //根据表信息,判断当前流程是否还在运行
  176. runInfo, err := wf_run.GetRunning(&wf_run.RunSearch{
  177. FromId: wfFid,
  178. FromTable: wfType,
  179. IsDel: 0,
  180. Status: 0,
  181. })
  182. if err != nil {
  183. return nil, nil, err
  184. }
  185. if runInfo != nil {
  186. info := new(wf_run_process.Entity)
  187. //获取当前运行的信息
  188. where := &wf_run_process.SearchRunProcess{
  189. RunId: runInfo.Id,
  190. RunFlow: runInfo.FlowId,
  191. RunFlowProcess: runInfo.RunFlowProcess,
  192. Status: "0",
  193. }
  194. processList, err = wf_run_process.GetProcessList(where)
  195. if err != nil {
  196. return nil, nil, err
  197. }
  198. if processList == nil || len(processList) == 0 {
  199. process, err := wf_run_process.GetProcess(where)
  200. if err != nil {
  201. return nil, nil, err
  202. }
  203. processList = append(processList, process)
  204. }
  205. //如果有两个以上的运行步骤,则认定为同步模式
  206. if len(processList) < 2 {
  207. workFlow.WfModel = 0
  208. info = processList[0]
  209. } else {
  210. workFlow.WfModel = 2 //同步模式
  211. for _, process := range processList {
  212. uIds := garray.NewStrArrayFrom(gstr.Split(process.SponsorIds, ","))
  213. if process.AutoPerson == 4 || process.AutoPerson == 3 {
  214. if uIds.Contains(gconv.String(userId)) {
  215. info = process
  216. break
  217. }
  218. } else {
  219. if uIds.Contains(gconv.String(departmentId)) {
  220. info = process
  221. break
  222. }
  223. }
  224. }
  225. if info == nil || info.Id == 0 {
  226. return nil, processList, gerror.New("无权限")
  227. }
  228. }
  229. //设置运行信息数据
  230. workFlow.SingSt = 0
  231. workFlow.FlowId = runInfo.FlowId
  232. if info == nil {
  233. info = new(wf_run_process.Entity)
  234. }
  235. workFlow.Status = info
  236. workFlow.FlowProcess = info.RunFlowProcess
  237. workFlow.RunId = runInfo.Id
  238. workFlow.RunProcess = info.Id
  239. //获取流程名称
  240. flowName, err := GetFlowName(gconv.Int64(runInfo.FlowId))
  241. if err != nil {
  242. return nil, nil, err
  243. }
  244. workFlow.FlowName = flowName
  245. //获取流程步骤信息
  246. var processData *ProcessData
  247. processData, err = GetProcessInfo(info.RunFlowProcess, runInfo.Id)
  248. if err != nil {
  249. return nil, nil, err
  250. }
  251. workFlow.Process = processData
  252. //获取下一个步骤信息
  253. var nextProcess []*ProcessData
  254. nextProcess, err = GetNexProcessInfo(wfType, wfFid, info.RunFlowProcess, runInfo.Id)
  255. if err != nil {
  256. return nil, nil, err
  257. }
  258. workFlow.NextProcess = nextProcess
  259. //获取前几个步骤信息,用于步骤回退
  260. var preProcess map[int]string
  261. preProcess, err = GetPreProcessInfo(info.Id)
  262. workFlow.Preprocess = preProcess
  263. //获取所有会签人员 todo...
  264. if runInfo.IsSing == 1 {
  265. info, err = wf_run_process.GetProcess(&wf_run_process.SearchRunProcess{
  266. RunId: runInfo.Id,
  267. RunFlow: runInfo.FlowId,
  268. RunFlowProcess: runInfo.RunFlowProcess,
  269. Status: "0",
  270. })
  271. if err != nil {
  272. return nil, nil, err
  273. }
  274. workFlow.SingSt = 1
  275. workFlow.FlowProcess = info.RunFlowProcess
  276. process, err := GetProcessInfo(info.RunFlowProcess, runInfo.Id)
  277. if err != nil {
  278. return nil, nil, err
  279. }
  280. workFlow.Status = &wf_run_process.Entity{
  281. WfMode: gconv.Int(process.WfMode),
  282. WfAction: process.WfAction,
  283. }
  284. nextProcess, err = GetNexProcessInfo(wfType, wfFid, info.RunFlowProcess, runInfo.Id)
  285. if err != nil {
  286. return nil, nil, err
  287. }
  288. workFlow.NextProcess = nextProcess
  289. workFlow.Process = process
  290. workFlow.RunProcess = info.Id
  291. workFlow.SignInfo, err = GetSignInfoById(gconv.Uint(runInfo.SingId))
  292. } else {
  293. workFlow.BillCheck = ""
  294. workFlow.BillTime = ""
  295. }
  296. } else {
  297. workFlow.BillCheck = ""
  298. workFlow.BillTime = ""
  299. }
  300. return workFlow, processList, nil
  301. }
  302. //获取对应类型的工作流
  303. func GetWorkFlowByType(wfType string) (flows []*flowModel.Entity, err error) {
  304. return flowModel.GetWorkFlowByType(wfType)
  305. }
  306. func StartWorkFlow(req *flowModel.SaveWfFlowReq) error {
  307. //判断流程是否存在--获取所选工作流信息
  308. flowInfo, err := flowModel.GetByID(req.WfId)
  309. if err != nil {
  310. return err
  311. }
  312. if flowInfo == nil {
  313. return gerror.New("未找到工作流信息")
  314. }
  315. //判断单据(业务表信息)是否存在
  316. bill, err := GetBill(req.WfFid, req.WfType)
  317. if err != nil {
  318. return err
  319. }
  320. if bill == nil {
  321. return gerror.New("单据不存在")
  322. }
  323. //根据流程获取流程第一个步骤
  324. wfProcesses, err := wf_flow_process.GetProcessesByMap(g.Map{"flow_id": req.WfId})
  325. if err != nil {
  326. return err
  327. }
  328. if wfProcesses == nil {
  329. gerror.New("没有流程信息。")
  330. }
  331. firstProcess := getFirstProcess(wfProcesses)
  332. if firstProcess == nil {
  333. return gerror.New("流程设计出错,未找到第一步流程,请联系管理员!")
  334. }
  335. tx, err := g.DB().Begin()
  336. if err != nil {
  337. g.Log().Error(err)
  338. return gerror.New("开启事务处理失败")
  339. }
  340. //保存流程数据
  341. runId, err := AddWfRun(req.WfId, firstProcess.Id, req.WfFid, req.WfType, req.WfTitle, req.WfStatusField, req.UserId, tx)
  342. if err != nil {
  343. tx.Rollback()
  344. return gerror.New("流程设计出错,未找到第一步流程,请联系管理员!")
  345. }
  346. //添加流程运行步骤
  347. err = AddWorkflowProcess(req.WfId, firstProcess, runId, req.UserId, "", tx)
  348. if err != nil {
  349. tx.Rollback()
  350. return err
  351. }
  352. //设置第一步审批人员/部门信息
  353. err = SetBusinessChecker(req.WfFid, req.WfType, runId, firstProcess, "", tx)
  354. if err != nil {
  355. tx.Rollback()
  356. return err
  357. }
  358. //添加流程日志
  359. err = AddWorkflowCache(runId, flowInfo, firstProcess, req.WfFid, tx)
  360. if err != nil {
  361. tx.Rollback()
  362. return err
  363. }
  364. //更新单据数据
  365. err = UpdateBill(req.WfFid, req.WfType, req.WfStatusField, 1, tx)
  366. if err != nil {
  367. tx.Rollback()
  368. return err
  369. }
  370. err = AddRunLog(runId, req, "Send", tx)
  371. if err != nil {
  372. tx.Rollback()
  373. return err
  374. }
  375. tx.Commit()
  376. return nil
  377. }
  378. //获取审批日志
  379. func FlowLog(logType string, wfFid uint, wfType string) ([]*RunLogInfo, error) {
  380. if logType == "logs" {
  381. infos, err := RunLog(wfFid, wfType)
  382. if err != nil {
  383. return nil, err
  384. }
  385. return infos, nil
  386. }
  387. return nil, gerror.New("参数出错!")
  388. }
  389. func WorkCheckAction(req *flowModel.CheckWfSaveReq) error {
  390. if req.Art != "" {
  391. art := gjson.New(req.Art)
  392. url := art.GetString("0.url")
  393. if url != "" {
  394. url, err := utils.GetFilesPath(url)
  395. if err != nil {
  396. return err
  397. }
  398. art.Set("0.url", url)
  399. }
  400. req.Art, _ = art.ToJsonString()
  401. }
  402. if req.SingSt == 0 {
  403. runCheck, err := RunCheck(req.RunProcess)
  404. if err != nil {
  405. return err
  406. }
  407. if runCheck == 2 {
  408. return gerror.New("该业务已办理,请勿重复提交!")
  409. }
  410. if req.SubmitToSave == "ok" {
  411. //提交处理
  412. err = DoTask(req)
  413. if err != nil {
  414. return err
  415. }
  416. } else if req.SubmitToSave == "back" {
  417. //退回处理
  418. err = DoBack(req)
  419. if err != nil {
  420. return err
  421. }
  422. } else if req.SubmitToSave == "sing" {
  423. //会签处理
  424. err = DoSing(req)
  425. if err != nil {
  426. return err
  427. }
  428. } else {
  429. return gerror.New("参数出错")
  430. }
  431. } else {
  432. err := DoSingEnt(req)
  433. if err != nil {
  434. return err
  435. }
  436. }
  437. return nil
  438. }
  439. type Running struct {
  440. *wf_run.Entity
  441. FlowName string `json:"flow_name"`
  442. User string `json:"user"`
  443. }
  444. func GetRunningFlow() ([]*Running, error) {
  445. run, err := wf_run.GetRuns("status", 0)
  446. if err != nil {
  447. return nil, err
  448. }
  449. running := make([]*Running, len(run))
  450. for k, v := range run {
  451. rn := &Running{Entity: v}
  452. flow, _ := flowModel.GetByID(gconv.Int64(v.FlowId))
  453. if flow != nil {
  454. rn.FlowName = flow.FlowName
  455. }
  456. process, err := wf_run_process.GetProcessByMap(g.Map{
  457. "run_id": v.Id,
  458. "run_flow_process": v.RunFlowProcess,
  459. })
  460. if err != nil {
  461. return nil, err
  462. }
  463. sponsorText := ""
  464. for _, s := range process {
  465. sponsorText += s.SponsorText + ","
  466. }
  467. sponsorText = gstr.TrimRightStr(sponsorText, ",")
  468. rn.User = sponsorText
  469. running[k] = rn
  470. }
  471. return running, nil
  472. }