flow.go 12 KB

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